MODSET=beta"
exit 1
endif
# ensure a clean branch
git diff -s --exit-code || (echo "local repository not clean"; exit 1)
# update files with new version
sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' versions.yaml
sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' ./cmd/builder/internal/builder/config.go
sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' ./cmd/builder/test/core.builder.yaml
sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' ./cmd/otelcorecol/builder-config.yaml
sed -i.bak 's/$(PREVIOUS_VERSION)/$(RELEASE_CANDIDATE)/g' examples/k8s/otel-config.yaml
find . -name "*.bak" -type f -delete
# commit changes before running multimod
git add .
git commit -m "prepare release $(RELEASE_CANDIDATE)"
$(MAKE) multimod-prerelease
# regenerate files
$(MAKE) -C cmd/builder config
$(MAKE) genotelcorecol
git add .
git commit -m "add multimod changes $(RELEASE_CANDIDATE)" || (echo "no multimod changes to commit")
.PHONY: clean
clean:
test -d bin && $(RM) bin/*
.PHONY: checklinks
checklinks:
command -v $(DOCKERCMD) >/dev/null 2>&1 || { echo >&2 "$(DOCKERCMD) not installed. Install before continuing"; exit 1; }
$(DOCKERCMD) run -w /home/repo --rm \
--mount 'type=bind,source='$(PWD)',target=/home/repo' \
lycheeverse/lychee \
--config .github/lychee.toml \
--root-dir /home/repo \
-v \
--no-progress './**/*.md'
# error message "failed to sync logger: sync /dev/stderr: inappropriate ioctl for device"
# is a known issue but does not affect function.
.PHONY: crosslink
crosslink:
@echo "Executing crosslink"
$(GO_TOOL) crosslink --root=$(shell pwd) --prune
FILENAME?=$(shell git branch --show-current)
.PHONY: chlog-new
chlog-new:
$(GO_TOOL) chloggen new --config $(CHLOGGEN_CONFIG) --filename $(FILENAME)
.PHONY: chlog-validate
chlog-validate:
$(GO_TOOL) chloggen validate --config $(CHLOGGEN_CONFIG)
.PHONY: chlog-preview
chlog-preview:
$(GO_TOOL) chloggen update --config $(CHLOGGEN_CONFIG) --dry
.PHONY: chlog-update
chlog-update:
$(GO_TOOL) chloggen update --config $(CHLOGGEN_CONFIG) --version $(VERSION)
.PHONY: builder-integration-test
builder-integration-test:
cd ./cmd/builder && ./test/test.sh
.PHONY: mdatagen-test
mdatagen-test:
cd cmd/mdatagen && $(GOCMD) install .
cd cmd/mdatagen && $(GOCMD) generate ./...
cd cmd/mdatagen && $(MAKE) fmt
cd cmd/mdatagen && $(GOCMD) test ./...
GITHUBGEN_ARGS ?= -skipgithub
GITHUBGEN := $(GO_TOOL) githubgen $(GITHUBGEN_ARGS)
.PHONY: generate-gh-issue-templates
generate-gh-issue-templates:
$(GITHUBGEN) issue-templates
.PHONY: generate-codeowners
generate-codeowners:
$(GITHUBGEN) --default-codeowner "open-telemetry/collector-approvers" codeowners
.PHONY: gengithub
gengithub: generate-codeowners generate-gh-issue-templates
.PHONY: gendistributions
gendistributions:
$(GITHUBGEN) distributions
.PHONY: generate-chloggen-components
generate-chloggen-components:
$(GITHUBGEN) chloggen-components
opentelemetry-collector-0.141.0/Makefile.Common 0000664 0000000 0000000 00000005062 15113313446 0021430 0 ustar 00root root 0000000 0000000 SHELL = /bin/bash
# ALL_PKGS is the list of all packages where ALL_SRC files reside.
ALL_PKGS := $(sort $(shell go list ./...))
# COVER_PKGS is the list of packages to include in the coverage
COVER_PKGS := $(shell go list ./... | tr "\n" ",")
CURR_MOD := $(shell go list -m | tr '/' '-' )
GOCMD?= go
GOOS := $(shell $(GOCMD) env GOOS)
GOARCH := $(shell $(GOCMD) env GOARCH)
GOTEST_TIMEOUT?=240s
# -race is not supported on windows arm64
GOTEST_OPT?= -timeout $(GOTEST_TIMEOUT) $(if $(and $(filter windows,$(GOOS)), $(filter arm64,$(GOARCH))),, -race)
# SRC_ROOT is the top of the source tree.
SRC_ROOT := $(shell git rev-parse --show-toplevel)
TOOLS_MOD_DIR := $(SRC_ROOT)/internal/tools
TOOLS_MOD_FILE := $(TOOLS_MOD_DIR)/go.mod
GO_TOOL := $(GOCMD) tool -modfile $(TOOLS_MOD_FILE)
CHLOGGEN_CONFIG := .chloggen/config.yaml
# no trailing slash
JUNIT_OUT_DIR ?= $(TOOLS_MOD_DIR)/testresults
.PHONY: test
test:
$(GO_TOOL) gotestsum --packages="./..." -- $(GOTEST_OPT)
.PHONY: test-with-cover
test-with-cover:
mkdir -p $(PWD)/coverage/unit
$(GO_TOOL) gotestsum \
--packages="./..." -- \
$(GOTEST_OPT) -cover -covermode=atomic -coverpkg $(COVER_PKGS) -args -test.gocoverdir="$(PWD)/coverage/unit"
.PHONY: test-with-junit
test-with-junit:
mkdir -p $(JUNIT_OUT_DIR)
$(GO_TOOL) gotestsum \
--packages="./..." --junitfile $(JUNIT_OUT_DIR)/$(CURR_MOD)-junit.xml -- \
$(GOTEST_OPT) ./...
.PHONY: benchmark
benchmark:
MEMBENCH=yes $(GO_TOOL) gotestsum \
--packages="$(ALL_PKGS)" -- \
-bench=. -run=notests ./... | tee benchmark.txt
.PHONY: fmt
fmt: common/gofmt common/goimports common/gofumpt
# `modernize' cannot be installed as a Go tool via `go get -tool'.
#
# See [1] for more details.
#
# [1]: https://github.com/golang/go/issues/73279
.PHONY: modernize
modernize:
$(GOCMD) run \
golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest \
-fix -test -v ./...
.PHONY: tidy
tidy:
rm -fr go.sum
$(GOCMD) mod tidy -compat=1.24.0
.PHONY: lint
lint:
$(GO_TOOL) golangci-lint run
.PHONY: common/gofmt
common/gofmt:
gofmt -w -s ./
.PHONY: common/goimports
common/goimports:
$(GO_TOOL) goimports -w -local go.opentelemetry.io/collector ./
.PHONY: common/gofumpt
common/gofumpt:
$(GO_TOOL) gofumpt -l -w -extra .
.PHONY: vulncheck
vulncheck:
$(GO_TOOL) govulncheck ./...
.PHONY: generate
generate:
$(GOCMD) generate ./...
.PHONY: impi
impi:
$(GO_TOOL) impi \
--local go.opentelemetry.io/collector \
--scheme stdThirdPartyLocal ./...
.PHONY: moddownload
moddownload:
$(GOCMD) mod download
timebenchmark:
go test -bench=. -benchtime=1s ./...
opentelemetry-collector-0.141.0/README.md 0000664 0000000 0000000 00000057631 15113313446 0020031 0 ustar 00root root 0000000 0000000 ---
Getting Started
•
Getting Involved
•
Getting In Touch
Vision
•
Configuration
•
Monitoring
•
Security
•
Package
---
#
OpenTelemetry Collector
The OpenTelemetry Collector offers a vendor-agnostic implementation on how to
receive, process and export telemetry data. In addition, it removes the need
to run, operate and maintain multiple agents/collectors in order to support
open-source telemetry data formats (e.g. Jaeger, Prometheus, etc.) to
multiple open-source or commercial back-ends.
Objectives:
- Usable: Reasonable default configuration, supports popular protocols, runs and collects out of the box.
- Performant: Highly stable and performant under varying loads and configurations.
- Observable: An exemplar of an observable service.
- Extensible: Customizable without touching the core code.
- Unified: Single codebase, deployable as an agent or collector with support for traces, metrics and logs.
## Community
The OpenTelemetry Collector SIG is present at the [#otel-collector](https://cloud-native.slack.com/archives/C01N6P7KR6W)
channel on the CNCF Slack and [meets once a week](https://github.com/open-telemetry/community#implementation-sigs) via
video calls. Everyone is invited to join those calls, which typically serves the following purposes:
- meet the humans behind the project
- get an opinion about specific proposals
- look for a sponsor for a proposed component after trying already via GitHub and Slack
- get attention to a specific pull-request that got stuck and is difficult to discuss asynchronously
We rotate our video calls between three time slots, in order to
allow everyone to join at least once every three meetings. The rotation order is as follows:
Tuesday:
- [17:00 PT](https://dateful.com/convert/pst-pdt-pacific-time?t=1700)
Wednesday:
- [09:00 PT](https://dateful.com/convert/pst-pdt-pacific-time?t=0900)
- [05:00 PT](https://dateful.com/convert/pst-pdt-pacific-time?t=0500)
Contributors to the project are also welcome to have ad-hoc meetings for synchronous discussions about specific points.
Post a note in #otel-collector-dev on Slack inviting others, specifying the topic to be discussed. Unless there are strong
reasons to keep the meeting private, please make it an open invitation for other contributors to join. Try also to
identify who would be the other contributors interested on that topic and in which timezones they are.
Remember that our source of truth is GitHub: every decision made via Slack or video calls has to be recorded in the
relevant GitHub issue. Ideally, the agenda items from the meeting notes would include a link to the issue or pull
request where a discussion is happening already. We acknowledge that not everyone can join Slack or the synchronous
calls and don't want them to feel excluded.
## Supported OTLP version
This code base is currently built against using OTLP protocol v1.5.0,
considered Stable. [See the OpenTelemetry Protocol Stability
definition
here.](https://github.com/open-telemetry/opentelemetry-proto?tab=readme-ov-file#stability-definition)
## Stability levels
See [Stability Levels and versioning](docs/component-stability.md) for more details.
## Compatibility
When used as a library, the OpenTelemetry Collector attempts to track the currently supported versions of Go, as [defined by the Go team](https://go.dev/doc/devel/release#policy).
Removing support for an unsupported Go version is not considered a breaking change.
Support for Go versions on the OpenTelemetry Collector is updated as follows:
1. The first release after the release of a new Go minor version `N` will add build and tests steps for the new Go minor version.
2. The first release after the release of a new Go minor version `N` will remove support for Go version `N-2`.
Official OpenTelemetry Collector distro binaries will be built with a release in the latest Go minor version series.
## Verifying the images signatures
> [!NOTE]
> To verify a signed artifact or blob, first [install Cosign](https://docs.sigstore.dev/cosign/system_config/installation/), then follow the instructions below.
We are signing the images `otel/opentelemetry-collector` and `otel/opentelemetry-collector-contrib` using [sigstore cosign](https://github.com/sigstore/cosign) tool and to verify the signatures you can run the following command:
```console
$ cosign verify \
--certificate-identity=https://github.com/open-telemetry/opentelemetry-collector-releases/.github/workflows/base-release.yaml@refs/tags/ \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
```
where:
- ``: is the release that you want to validate
- ``: is the image that you want to check
Example:
```console
$ cosign verify --certificate-identity=https://github.com/open-telemetry/opentelemetry-collector-releases/.github/workflows/base-release.yaml@refs/tags/v0.98.0 --certificate-oidc-issuer=https://token.actions.githubusercontent.com ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.98.0
Verification for ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.98.0 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
[{"critical":{"identity":{"docker-reference":"ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib"},"image":{"docker-manifest-digest":"sha256:5cea85bcbc734a3c0a641368e5a4ea9d31b472997e9f2feca57eeb4a147fcf1a"},"type":"cosign container image signature"},"optional":{"1.3.6.1.4.1.57264.1.1":"https://token.actions.githubusercontent.com","1.3.6.1.4.1.57264.1.2":"push","1.3.6.1.4.1.57264.1.3":"9e20bf5c142e53070ccb8320a20315fffb41469e","1.3.6.1.4.1.57264.1.4":"Release Contrib","1.3.6.1.4.1.57264.1.5":"open-telemetry/opentelemetry-collector-releases","1.3.6.1.4.1.57264.1.6":"refs/tags/v0.98.0","Bundle":{"SignedEntryTimestamp":"MEUCIQDdlmNeKXQrHnonwWiHLhLLwFDVDNoOBCn2sv85J9P8mgIgDQFssWJImo1hn38VlojvSCL7Qq5FMmtnGu0oLsNdOm8=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIxMzVjY2RlN2YzZTNhYjU2NmFmYzJhYWU3MDljYmJlNmFhMDZlZWMzNDA2MWNkZjMyNmRhYzM2MmY0NWM4Yjg4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUURFbDV6N0diMWRVYkM5KzR4c1VvbDhMcWZNV2hiTzhkdEpwdExyMXhUNWZnSWdTdEwwN1I0ZDA5R2x0ZkV0azJVbmlJSlJhQVdrVDJNWDVtRXJNSlplc2pRPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaG9ha05EUW5jeVowRjNTVUpCWjBsVlNETkNjRFZTYlVSU1VpOXphMWg0YVdWUFlrcFhSbmRrUjNNNGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDVFUlhoTlJGRjRUMFJOTlZkb1kwNU5hbEYzVGtSRmVFMUVVWGxQUkUwMVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZyWlRsSE1ubHNjMjkzYVZZMmRFOVZSazlRVVhNd2NXY3hTSEV5WmpsVUx6UTJZbEFLU1ZSNE0ybFRkVXBhV0hGc1dEUldWV2Q1VlZndmNVazJhblZ2WlZSVEswaG5XVUoyYjBseVNERTFUeTltZEd0VmVtRlBRMEpwZDNkbloxbHZUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZHTkRrMUNrdDFNRWhqTm5rek1rNUNTVTFFU21ReVpuWkxNMHBCZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJkWldVZEJNVlZrUlZGRlFpOTNVamhOU0hGSFpVZG9NR1JJUW5wUGFUaDJXakpzTUdGSVZtbE1iVTUyWWxNNWRtTkhWblZNV0ZKc1lrZFdkQXBhV0ZKNVpWTTVkbU5IVm5Wa1IxWnpXbGN4YkdSSVNqVk1WMDUyWWtkNGJGa3pVblpqYVRGNVdsZDRiRmxZVG14amVUaDFXakpzTUdGSVZtbE1NMlIyQ21OdGRHMWlSemt6WTNrNWFWbFlUbXhNV0Vwc1lrZFdhR015VlhWbFYwWjBZa1ZDZVZwWFducE1NMUpvV2pOTmRtUnFRWFZQVkdkMVRVUkJOVUpuYjNJS1FtZEZSVUZaVHk5TlFVVkNRa04wYjJSSVVuZGplbTkyVEROU2RtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JBcGlibEYxV1RJNWRFMUNTVWREYVhOSFFWRlJRbWMzT0hkQlVVbEZRa2hDTVdNeVozZE9aMWxMUzNkWlFrSkJSMFIyZWtGQ1FYZFJiMDlYVlhsTlIwcHRDazVYVFhoT1JFcHNUbFJOZDA1NlFtcFpNa2swVFhwSmQxbFVTWGROZWtVeFdtMWFiVmxxVVhoT1JGazFXbFJCWkVKbmIzSkNaMFZGUVZsUEwwMUJSVVVLUWtFNVUxcFhlR3haV0U1c1NVVk9kbUp1VW5saFYwbDNVRkZaUzB0M1dVSkNRVWRFZG5wQlFrSlJVWFppTTBKc1lta3hNRnBYZUd4aVYxWXdZMjVyZGdwaU0wSnNZbTVTYkdKSFZuUmFXRko1WlZNeGFtSXllSE5hVjA0d1lqTkpkR050Vm5OYVYwWjZXbGhOZDBoM1dVdExkMWxDUWtGSFJIWjZRVUpDWjFGU0NtTnRWbTFqZVRrd1dWZGtla3d6V1hkTWFtczBUR3BCZDA5M1dVdExkMWxDUWtGSFJIWjZRVUpEUVZGMFJFTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxSlIwbENaMjl5UW1kRlJVRlpUeTlOUVVWS1FraHZUUXBsUjJnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemwyWTBkV2RVeFlVbXhpUjFaMFdsaFNlV1ZUT1haalIxWjFaRWRXYzFwWE1XeGtTRW8xQ2t4WFRuWmlSM2hzV1ROU2RtTnBNWGxhVjNoc1dWaE9iR041T0hWYU1td3dZVWhXYVV3elpIWmpiWFJ0WWtjNU0yTjVPV2xaV0U1c1RGaEtiR0pIVm1nS1l6SlZkV1ZYUm5SaVJVSjVXbGRhZWt3elVtaGFNMDEyWkdwQmRVOVVaM1ZOUkVFMFFtZHZja0puUlVWQldVOHZUVUZGUzBKRGIwMUxSR3hzVFdwQ2FRcGFhbFpxVFZSUmVWcFVWWHBOUkdOM1dUSk9hVTlFVFhsTlIwVjVUVVJOZUU1WFdtMWFiVWt3VFZSUk1rOVhWWGRJVVZsTFMzZFpRa0pCUjBSMmVrRkNDa04zVVZCRVFURnVZVmhTYjJSWFNYUmhSemw2WkVkV2EwMUdTVWREYVhOSFFWRlJRbWMzT0hkQlVYZEZVa0Y0UTJGSVVqQmpTRTAyVEhrNWJtRllVbThLWkZkSmRWa3lPWFJNTWpsM1dsYzBkR1JIVm5OYVZ6RnNaRWhLTlV3eU9YZGFWelV3V2xkNGJHSlhWakJqYm10MFdUSTVjMkpIVm1wa1J6bDVURmhLYkFwaVIxWm9ZekpXZWsxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDlYVlhsTlIwcHRUbGROZUU1RVNteE9WRTEzVG5wQ2Fsa3lTVFJOZWtsM0NsbFVTWGROZWtVeFdtMWFiVmxxVVhoT1JGazFXbFJCYUVKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWsxTlJWaEtiRnB1VFhaa1IwWnVZM2s1TWsxRE5EVUtUME0wZDAxQ2EwZERhWE5IUVZGUlFtYzNPSGRCVVRoRlEzZDNTazVFUVhkTmFsVjZUbXBqTWsxRVJVZERhWE5IUVZGUlFtYzNPSGRCVWtGRlNYZDNhQXBoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NamwzV2xjMGRHUkhWbk5hVnpGc1pFaEtOVTFDWjBkRGFYTkhRVkZSUW1jM09IZEJVa1ZGQ2tObmQwbE9SR3MxVDFSbmQwMUVTWGRuV1hOSFEybHpSMEZSVVVKbk56aDNRVkpKUldaUmVEZGhTRkl3WTBoTk5reDVPVzVoV0ZKdlpGZEpkVmt5T1hRS1RESTVkMXBYTkhSa1IxWnpXbGN4YkdSSVNqVk1NamwzV2xjMU1GcFhlR3hpVjFZd1kyNXJkRmt5T1hOaVIxWnFaRWM1ZVV4WVNteGlSMVpvWXpKV2VncE1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU0wcHNZa2RXYUdNeVZYUlpNamwxWkVoS2NGbHBOVFZaVnpGelVVaEtiRnB1VFhaa1IwWnVDbU41T1RKTlF6UTFUME0wZDAxRVowZERhWE5IUVZGUlFtYzNPSGRCVWsxRlMyZDNiMDlYVlhsTlIwcHRUbGROZUU1RVNteE9WRTEzVG5wQ2Fsa3lTVFFLVFhwSmQxbFVTWGROZWtVeFdtMWFiVmxxVVhoT1JGazFXbFJCVlVKbmIzSkNaMFZGUVZsUEwwMUJSVlZDUVZsTlFraENNV015WjNka1VWbExTM2RaUWdwQ1FVZEVkbnBCUWtaUlVtNUVSMVp2WkVoU2QyTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZak5DYkdKcE1UQmFWM2hzWWxkV01HTnVhM1ppTTBKc0NtSnVVbXhpUjFaMFdsaFNlV1ZUTVdwaU1uaHpXbGRPTUdJelNYUmpiVlp6V2xkR2VscFlUWFpaVjA0d1lWYzVkV041T1hsa1Z6VjZUSHBuTWs1RVJYZ0tUbnBGTVU1cVkzWlpXRkl3V2xjeGQyUklUWFpOYWtGWFFtZHZja0puUlVWQldVOHZUVUZGVjBKQlowMUNia0l4V1cxNGNGbDZRMEpwWjFsTFMzZFpRZ3BDUVVoWFpWRkpSVUZuVWpoQ1NHOUJaVUZDTWtGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQQ2tGQlFVSnFjM1JvUlVOUlFVRkJVVVJCUldOM1VsRkpaMWg2Y2xaME0xQjRkU3ROWVZKRkswUkdORzlGUldNMGVucHphSGR1VDJ4bGMwZGlla2xwYnpNS0wxWmpRMGxSUkZNelJ6QmlNemRhYUhRNGFITjJUSEozYkc1UFFXYzJWRXh1U1ZSS09HTjNkMVEzTW5sMVRVdFlUbFJCUzBKblozRm9hMnBQVUZGUlJBcEJkMDV1UVVSQ2EwRnFRWGxFUkZSYVFqQlRPVXBGYkZsSGJuTnZWVmhLYm04MU5Fc3ZUVUZUTlN0RFFVMU9lbWRqUWpWQ2JrRk5OMWhNUjBoV01HRnhDbVpaY21weFkyOXFia3RaUTAxSFRWRnFjalpUVGt0Q2NVaEtZVGwxTDBSTlQySlpNa0pKTVV0ME4yTnhOemhFT0VOcVMzQmFVblJoYnpadFVVMUVZMk1LUms5M2VYWnhWalJPVld0dlpsRTlQUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=","integratedTime":1712809120,"logIndex":84797936,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}},"Issuer":"https://token.actions.githubusercontent.com","Subject":"https://github.com/open-telemetry/opentelemetry-collector-releases/.github/workflows/base-release.yaml@refs/tags/v0.98.0","githubWorkflowName":"Release Contrib","githubWorkflowRef":"refs/tags/v0.98.0","githubWorkflowRepository":"open-telemetry/opentelemetry-collector-releases","githubWorkflowSha":"9e20bf5c142e53070ccb8320a20315fffb41469e","githubWorkflowTrigger":"push"}},{"critical":{"identity":{"docker-reference":"ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib"},"image":{"docker-manifest-digest":"sha256:5cea85bcbc734a3c0a641368e5a4ea9d31b472997e9f2feca57eeb4a147fcf1a"},"type":"cosign container image signature"},"optional":{"1.3.6.1.4.1.57264.1.1":"https://token.actions.githubusercontent.com","1.3.6.1.4.1.57264.1.2":"push","1.3.6.1.4.1.57264.1.3":"9e20bf5c142e53070ccb8320a20315fffb41469e","1.3.6.1.4.1.57264.1.4":"Release Contrib","1.3.6.1.4.1.57264.1.5":"open-telemetry/opentelemetry-collector-releases","1.3.6.1.4.1.57264.1.6":"refs/tags/v0.98.0","Bundle":{"SignedEntryTimestamp":"MEUCIQD1ehDnPO6fzoPIpeQ3KFuYHHBiX7RcEbpo9B2r7JAlzwIgZ1bsuQz7gAXbNU1IEdsTQgfAnRk3xVXO16GnKXM2sAQ=","Payload":{"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIxMzVjY2RlN2YzZTNhYjU2NmFmYzJhYWU3MDljYmJlNmFhMDZlZWMzNDA2MWNkZjMyNmRhYzM2MmY0NWM4Yjg4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRU92QXl0aE5RVGNvNHFMdG9GZUVOV0toNCtEK2I5SUxyYWhoa09WMmVBM0FpQjNEL2FpUGd1T05zUlB5alhaWk1hdnlCam0vMkVxNFNUMkZJWHozTnpyYWc9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaHBSRU5EUW5jMlowRjNTVUpCWjBsVlZuRlRLMnd4WXpoMWVFUktOWEppZDAxMlVuaDBSR3hXVW1nMGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDVFUlhoTlJGRjRUMFJSZVZkb1kwNU5hbEYzVGtSRmVFMUVVWGxQUkZGNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVYyWlRCdGJrRkdRVzl1TVZoUGRIVlRMMXBNT0djeE5YUlJkVmxPTmtRemVUUlBWM0FLT1ZSTFMwUlVkRkJHU2xST1ZrWlJkVTlKUWs1bVJqWk1ORTlGYkd4dlZuUndaSE5uYjB0NVZGTnlPR3hTV1c1S1JIRlBRMEpwTUhkbloxbHdUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZDSzFkSENuVmtlRE5IZUcxS1RWUkpUVVJyYW13clJtdzFXRzkzZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJkWldVZEJNVlZrUlZGRlFpOTNVamhOU0hGSFpVZG9NR1JJUW5wUGFUaDJXakpzTUdGSVZtbE1iVTUyWWxNNWRtTkhWblZNV0ZKc1lrZFdkQXBhV0ZKNVpWTTVkbU5IVm5Wa1IxWnpXbGN4YkdSSVNqVk1WMDUyWWtkNGJGa3pVblpqYVRGNVdsZDRiRmxZVG14amVUaDFXakpzTUdGSVZtbE1NMlIyQ21OdGRHMWlSemt6WTNrNWFWbFlUbXhNV0Vwc1lrZFdhR015VlhWbFYwWjBZa1ZDZVZwWFducE1NMUpvV2pOTmRtUnFRWFZQVkdkMVRVUkJOVUpuYjNJS1FtZEZSVUZaVHk5TlFVVkNRa04wYjJSSVVuZGplbTkyVEROU2RtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JBcGlibEYxV1RJNWRFMUNTVWREYVhOSFFWRlJRbWMzT0hkQlVVbEZRa2hDTVdNeVozZE9aMWxMUzNkWlFrSkJSMFIyZWtGQ1FYZFJiMDlYVlhsTlIwcHRDazVYVFhoT1JFcHNUbFJOZDA1NlFtcFpNa2swVFhwSmQxbFVTWGROZWtVeFdtMWFiVmxxVVhoT1JGazFXbFJCWkVKbmIzSkNaMFZGUVZsUEwwMUJSVVVLUWtFNVUxcFhlR3haV0U1c1NVVk9kbUp1VW5saFYwbDNVRkZaUzB0M1dVSkNRVWRFZG5wQlFrSlJVWFppTTBKc1lta3hNRnBYZUd4aVYxWXdZMjVyZGdwaU0wSnNZbTVTYkdKSFZuUmFXRko1WlZNeGFtSXllSE5hVjA0d1lqTkpkR050Vm5OYVYwWjZXbGhOZDBoM1dVdExkMWxDUWtGSFJIWjZRVUpDWjFGU0NtTnRWbTFqZVRrd1dWZGtla3d6V1hkTWFtczBUR3BCZDA5M1dVdExkMWxDUWtGSFJIWjZRVUpEUVZGMFJFTjBiMlJJVW5kamVtOTJURE5TZG1FeVZuVUtURzFHYW1SSGJIWmliazExV2pKc01HRklWbWxrV0U1c1kyMU9kbUp1VW14aWJsRjFXVEk1ZEUxSlIwbENaMjl5UW1kRlJVRlpUeTlOUVVWS1FraHZUUXBsUjJnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemwyWTBkV2RVeFlVbXhpUjFaMFdsaFNlV1ZUT1haalIxWjFaRWRXYzFwWE1XeGtTRW8xQ2t4WFRuWmlSM2hzV1ROU2RtTnBNWGxhVjNoc1dWaE9iR041T0hWYU1td3dZVWhXYVV3elpIWmpiWFJ0WWtjNU0yTjVPV2xaV0U1c1RGaEtiR0pIVm1nS1l6SlZkV1ZYUm5SaVJVSjVXbGRhZWt3elVtaGFNMDEyWkdwQmRVOVVaM1ZOUkVFMFFtZHZja0puUlVWQldVOHZUVUZGUzBKRGIwMUxSR3hzVFdwQ2FRcGFhbFpxVFZSUmVWcFVWWHBOUkdOM1dUSk9hVTlFVFhsTlIwVjVUVVJOZUU1WFdtMWFiVWt3VFZSUk1rOVhWWGRJVVZsTFMzZFpRa0pCUjBSMmVrRkNDa04zVVZCRVFURnVZVmhTYjJSWFNYUmhSemw2WkVkV2EwMUdTVWREYVhOSFFWRlJRbWMzT0hkQlVYZEZVa0Y0UTJGSVVqQmpTRTAyVEhrNWJtRllVbThLWkZkSmRWa3lPWFJNTWpsM1dsYzBkR1JIVm5OYVZ6RnNaRWhLTlV3eU9YZGFWelV3V2xkNGJHSlhWakJqYm10MFdUSTVjMkpIVm1wa1J6bDVURmhLYkFwaVIxWm9ZekpXZWsxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDlYVlhsTlIwcHRUbGROZUU1RVNteE9WRTEzVG5wQ2Fsa3lTVFJOZWtsM0NsbFVTWGROZWtVeFdtMWFiVmxxVVhoT1JGazFXbFJCYUVKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWsxTlJWaEtiRnB1VFhaa1IwWnVZM2s1TWsxRE5EVUtUME0wZDAxQ2EwZERhWE5IUVZGUlFtYzNPSGRCVVRoRlEzZDNTazVFUVhkTmFsVjZUbXBqTWsxRVJVZERhWE5IUVZGUlFtYzNPSGRCVWtGRlNYZDNhQXBoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NamwzV2xjMGRHUkhWbk5hVnpGc1pFaEtOVTFDWjBkRGFYTkhRVkZSUW1jM09IZEJVa1ZGQ2tObmQwbE9SR3MxVDFSbmQwMUVTWGRuV1hOSFEybHpSMEZSVVVKbk56aDNRVkpKUldaUmVEZGhTRkl3WTBoTk5reDVPVzVoV0ZKdlpGZEpkVmt5T1hRS1RESTVkMXBYTkhSa1IxWnpXbGN4YkdSSVNqVk1NamwzV2xjMU1GcFhlR3hpVjFZd1kyNXJkRmt5T1hOaVIxWnFaRWM1ZVV4WVNteGlSMVpvWXpKV2VncE1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU0wcHNZa2RXYUdNeVZYUlpNamwxWkVoS2NGbHBOVFZaVnpGelVVaEtiRnB1VFhaa1IwWnVDbU41T1RKTlF6UTFUME0wZDAxRVowZERhWE5IUVZGUlFtYzNPSGRCVWsxRlMyZDNiMDlYVlhsTlIwcHRUbGROZUU1RVNteE9WRTEzVG5wQ2Fsa3lTVFFLVFhwSmQxbFVTWGROZWtVeFdtMWFiVmxxVVhoT1JGazFXbFJCVlVKbmIzSkNaMFZGUVZsUEwwMUJSVlZDUVZsTlFraENNV015WjNka1VWbExTM2RaUWdwQ1FVZEVkbnBCUWtaUlVtNUVSMVp2WkVoU2QyTjZiM1pNTW1Sd1pFZG9NVmxwTldwaU1qQjJZak5DYkdKcE1UQmFWM2hzWWxkV01HTnVhM1ppTTBKc0NtSnVVbXhpUjFaMFdsaFNlV1ZUTVdwaU1uaHpXbGRPTUdJelNYUmpiVlp6V2xkR2VscFlUWFpaVjA0d1lWYzVkV041T1hsa1Z6VjZUSHBuTWs1RVJYZ0tUbnBGTVU1cVkzWlpXRkl3V2xjeGQyUklUWFpOYWtGWFFtZHZja0puUlVWQldVOHZUVUZGVjBKQlowMUNia0l4V1cxNGNGbDZRMEpwZDFsTFMzZFpRZ3BDUVVoWFpWRkpSVUZuVWpsQ1NITkJaVkZDTTBGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQQ2tGQlFVSnFjM1JvUjJKSlFVRkJVVVJCUldkM1VtZEphRUZQZUZNM2RteDRjVzVGYTBKVVRtSlZVRUpsUkZSbk0waGtlRlkyY0cxWk9FdGliREV6TjNBS1lWUnViMEZwUlVFelMyMUxVbU5uYWxBeVQzSmxORVpyVm5vNU4xaENNWGRsUzBOeWFXazFTMWx2UTB0bVkxRktSREJSZDBObldVbExiMXBKZW1vd1JRcEJkMDFFWVVGQmQxcFJTWGhCUzNwcVpHMUZTV2gzV21Kb1lVSlNlalk1Y1N0MWVrNVZSMmxhYlRWVk4xcE5aWFJMUTFSM1VFTkljRkZQVldvdlVERkJDa2R0YWt3elJucFFObTVpYkRGblNYZFNUbXN6UkhkNWMwOUJUMHhoUVVoR09IaHhZV0ZzT0U5WGNGRmFhRGh4TTJVMVNVSmFXR0ZWVkhocFlWbGFTM29LUXpWS1RGVlNWbnBMTURsd04wVjBUd290TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0=","integratedTime":1712809122,"logIndex":84797940,"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"}},"Issuer":"https://token.actions.githubusercontent.com","Subject":"https://github.com/open-telemetry/opentelemetry-collector-releases/.github/workflows/base-release.yaml@refs/tags/v0.98.0","githubWorkflowName":"Release Contrib","githubWorkflowRef":"refs/tags/v0.98.0","githubWorkflowRepository":"open-telemetry/opentelemetry-collector-releases","githubWorkflowSha":"9e20bf5c142e53070ccb8320a20315fffb41469e","githubWorkflowTrigger":"push"}}]
```
> [!NOTE]
> We started signing the images with release `v0.95.0`
## Contributing
See the [Contributing Guide](CONTRIBUTING.md) for details.
Here is a list of community roles with current and previous members:
### Maintainers
- [Alex Boten](https://github.com/codeboten), Honeycomb
- [Bogdan Drutu](https://github.com/bogdandrutu), Snowflake
- [Dmitrii Anoshin](https://github.com/dmitryax), Splunk
- [Pablo Baeyens](https://github.com/mx-psi), DataDog
For more information about the maintainer role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#maintainer).
### Approvers
- [Andrew Wilkins](https://github.com/axw), Elastic
- [Antoine Toulme](https://github.com/atoulme), Splunk
- [Damien Mathieu](https://github.com/dmathieu), Elastic
- [Evan Bradley](https://github.com/evan-bradley), Dynatrace
- [Jade Guiton](https://github.com/jade-guiton-dd), Datadog
- [Joshua MacDonald](https://github.com/jmacd), Microsoft
- [Tyler Helmuth](https://github.com/TylerHelmuth), Honeycomb
- [Yang Song](https://github.com/songy23), Datadog
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
In addition to what is described at the organization-level, the SIG Collector requires all core approvers to take part in rotating
the role of the [release manager](./docs/release.md#release-manager).
### Triagers
- [Andrzej Stencel](https://github.com/andrzej-stencel), Elastic
- [Chao Weng](https://github.com/sincejune), AppDynamics
- [Vihas Makwana](https://github.com/VihasMakwana), Elastic
- Actively seeking contributors to triage issues
For more information about the triager role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).
### Emeritus Maintainers
- [Paulo Janotti](https://github.com/pjanotti)
- [Tigran Najaryan](https://github.com/tigrannajaryan)
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
### Emeritus Approvers
- [Anthony Mirabella](https://github.com/Aneurysm9)
- [Daniel Jaglowski](https://github.com/djaglowski)
- [James Bebbington](https://github.com/james-bebbington)
- [Jay Camp](https://github.com/jrcamp)
- [Juraci Paixรฃo Krรถhling](https://github.com/jpkrohling)
- [Nail Islamov](https://github.com/nilebox)
- [Owais Lone](https://github.com/owais)
- [Rahul Patel](https://github.com/rghetia)
- [Steven Karis](https://github.com/sjkaris)
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
### Emeritus Triagers
- [Alolita Sharma](https://github.com/alolita)
- [Andrew Hsu](https://github.com/andrewhsu)
- [Punya Biswal](https://github.com/punya)
- [Steve Flanders](https://github.com/flands)
For more information about the emeritus role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
### Thanks to all of our contributors!
opentelemetry-collector-0.141.0/VERSIONING.md 0000664 0000000 0000000 00000033524 15113313446 0020552 0 ustar 00root root 0000000 0000000 # Versioning and stability
The OpenTelemetry Collector SIG produces several artifacts for [a variety of audiences](CONTRIBUTING.md#target-audiences). This document describes the versioning and support policy for these artifacts. These policies are designed so that the following goal can be achieved:
**Users are provided software artifacts of value that are stable and secure.**
The policies are divided depending on the artifact's target audience. While an artifact is supported, [critical bugs](docs/release.md#bugfix-release-criteria) and security vulnerabilities MUST be addressed. The main criteria for the length of support for an artifact is how easy it is for an artifact's target audience to adapt to disruptive changes.
These policies reflect the current consensus of the OpenTelemetry Collector SIG. They are subject to change as the project evolves.
## Software artifacts for end users
Software artifacts intended for [end users](CONTRIBUTING.md#end-users) of the OpenTelemetry Collector include
- Binary distributions of the OpenTelemetry Collector.
- Go modules that expose Collector components, such as receivers, processors, connectors, extensions and exporters.
These artifacts are versioned according to the [semantic versioning v2.0.0](https://semver.org/) specification.
### General considerations
Binary distributions produced by the Collector SIG contain components and features with varying [levels of stability](README.md#stability-levels). We abide by the following principles to relate the Collector's version to the stability of its components and features:
* The Collector's core framework behavior MUST be stable in order for a Collector distribution to be v1.0.0 or higher.
* Users can easily understand when they are opting in to use a component or feature that is not stable.
* The Collector MUST be configurable so that unstable components or features can be excluded ensuring that a fully stable configuration is possible.
* The Collector's telemetry (e.g. Collector logs) MUST provide the ability to identify usage of unstable components or features.
### Long-term support after v1
The OpenTelemetry Collector SIG provides long-term support for stable binary distributions of the OpenTelemetry Collector and its components. The following policies apply to long-term support for any major version starting on v1:
* A binary distribution of the OpenTelemetry Collector MUST be supported for a minimum of **one year** after the release of the next major version of said distribution.
* Components MUST be supported for a minimum of **6 months** after the release of the next major version of said component or after the component has been marked as deprecated. If a component has been deprecated for 6 months it MAY be removed from a binary distribution of the OpenTelemetry Collector. This does not imply a major version change in the Collector distribution.
## Go modules
Go modules are intended to be used by [component developers](CONTRIBUTING.md#component-developers) and [Collector library users](CONTRIBUTING.md#collector-library-users) of the OpenTelemetry Collector
Unless otherwise specified, the following public API expectations apply to all modules in opentelemetry-collector and opentelemetry-collector-contrib.
As a general rule, stability guarantees of modules versioned as `v1` or higher are aligned with [Go 1 compatibility promise](https://go.dev/doc/go1compat).
### General Go API considerations
OpenTelemetry authors reserve the right to introduce API changes breaking compatibility between minor versions in the following scenarios:
* **Struct literals.** It may be necessary to add new fields to exported structs in the API. Code that uses unkeyed
struct literals (such as pkg.T{3, "x"}) to create values of these types would fail to compile after such a change.
However, code that uses keyed literals (pkg.T{A: 3, B: "x"}) will continue to compile. We therefore recommend
using OpenTelemetry collector structs with the keyed literals only.
* **Methods.** As with struct fields, it may be necessary to add methods to types. Under some circumstances,
such as when the type is embedded in a struct along with another type, the addition of the new method may
break the struct by creating a conflict with an existing method of the other embedded type. We cannot protect
against this rare case and do not guarantee compatibility in such scenarios.
* **Dot imports.** If a program imports a package using `import .`, additional names defined in the imported package
in future releases may conflict with other names defined in the program. We do not recommend the use of
`import .` with OpenTelemetry Collector modules.
Unless otherwise specified in the documentation, the following may change in any way between minor versions:
* **String representation**. The `String` or `Error` method of any struct is intended to be human-readable and may
change its output in any way.
* **Go version compatibility**. Removing support for an unsupported Go version is not considered a breaking change.
* **OS version compatibility**. Removing support for an unsupported OS version is not considered a breaking change. Upgrading or downgrading OS version support per the [platform support](docs/platform-support.md) document is not considered a breaking change.
* **Protocol compatibility**. Changing the default minimum version of a supported protocol (e.g. TLS) or dropping support for protocols when there are security concerns is not considered a breaking change.
* **Dependency updates**. Updating dependencies is not considered a breaking change except when their types are part of the
public API or the update may change the behavior of applications in an incompatible way.
* **Underlying type for interfaces**. If a struct exported as an interface has an experimental
method, this method may change or be removed in a minor version. The method will be published in an
optional interface under an experimental module to signal it is experimental.
### Configuration structures
Configuration structures are part of the public API and backwards
compatibility should be maintained through any changes made to configuration structures.
Unless otherwise specified in the documentation, the following may change in any way between minor versions:
* **Adding new fields to configuration structures**. Because configuration structures are typically instantiated through
unmarshalling a serialized representation of the structure, and not through structure literals, additive changes to
the set of exported fields in a configuration structure are not considered to break backward compatibility.
* **Relaxing validation rules**. An invalid configuration struct as defined by its `Validate` method return value
may become valid after a change to the validation rules.
The following are explicitly considered to be breaking changes:
* **Modifying struct tags related to serialization**. Struct tags used to configure serialization mechanisms (`yaml:`,
`mapstructure:`, etc) are part of the structure definition and must maintain compatibility to the same extent as the
structure. However, changes are allowed when tag modifications produce a
functionally-equivalent result when serializing or deserializing the structure.
For example, adding a tag to a field so it will not be emitted during serialization
if it has a default value would not alter its value if the serialized representation
were again deserialized, so such a change would be permitted.
* **Making validation rules more strict**. A valid configuration struct as defined by its `Validate` method return value
must continue to be valid after a change to the validation rules, except when the configuration struct would cause an error
on its intended usage (e.g. when calling a method or when passed to any method or function in any module under opentelemetry-collector).
### Module versioning and schema
* Versioning of this project will be idiomatic of a Go project using [Go
modules](https://golang.org/ref/mod#versions).
* [Semantic import
versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning)
will be used.
* Versions will comply with [semver 2.0](https://semver.org/spec/v2.0.0.html).
* If a module is version `v2` or higher, the major version of the module
must be included as a `/vN` at the end of the module paths used in
`go.mod` files (e.g., `module go.opentelemetry.io/collector/v2`, `require
go.opentelemetry.io/collector/v2 v2.0.1`) and in the package import path
(e.g., `import "go.opentelemetry.io/collector/v2/component"`). This includes the
paths used in `go get` commands (e.g., `go get
go.opentelemetry.io/collector/v2@v2.0.1`. Note there is both a `/v2` and a
`@v2.0.1` in that example. One way to think about it is that the module
name now includes the `/v2`, so include `/v2` whenever you are using the
module name).
* If a module is version `v0` or `v1`, do not include the major version in
either the module path or the import path.
* Semantic convention packages will contain a complete version identifier in their
import path to enable concurrent use of multiple convention versions in a single
application. This identifies the version of the specification used to generate
the package and is not related to the version of the module containing the package.
* A single module should exist, rooted at the top level of this repository,
that contains all packages provided for use outside this repository.
* Additional modules may be created in this repository to provide for
isolation of build-time tools, other commands or independent libraries. Such modules should be
versioned in sync with the `go.opentelemetry.io/collector` module.
* Experimental modules still under active development will be versioned with a major
version of `v0` to imply the stability guarantee defined by
[semver](https://semver.org/spec/v2.0.0.html#spec-item-4).
> Major version zero (0.y.z) is for initial development. Anything MAY
> change at any time. The public API SHOULD NOT be considered stable.
* Versioning of the associated [contrib
repository](https://github.com/open-telemetry/opentelemetry-collector-contrib) of
this project will be idiomatic of a Go project using [Go
modules](https://golang.org/ref/mod#versions).
* [Semantic import
versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning)
will be used.
* Versions will comply with [semver 2.0](https://semver.org/spec/v2.0.0.html).
* If a module is version `v2` or higher, the
major version of the module must be included as a `/vN` at the end of the
module paths used in `go.mod` files (e.g., `module
github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor/v2`, `require
github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor/v2 v2.0.1`) and in the
package import path (e.g., `import
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor/v2"`). This includes
the paths used in `go get` commands (e.g., `go get
github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor/v2@v2.0.1`. Note there
is both a `/v2` and a `@v2.0.1` in that example. One way to think about
it is that the module name now includes the `/v2`, so include `/v2`
whenever you are using the module name).
* If a module is version `v0` or `v1`, do not include the major version
in either the module path or the import path.
* Modules will be used to encapsulate receivers, processors, exporters,
extensions, connectors and any other independent sets of related components.
* Experimental modules still under active development will be versioned with a major
version of `v0` to imply the stability guarantee defined by
[semver](https://semver.org/spec/v2.0.0.html#spec-item-4).
> Major version zero (0.y.z) is for initial development. Anything MAY
> change at any time. The public API SHOULD NOT be considered stable.
* Experimental modules will start their versioning at `v0.0.0` and will
increment their minor version when backwards incompatible changes are
released and increment their patch version when backwards compatible
changes are released.
* Mature modules for which we guarantee a stable public API will
be versioned with a major version of `v1` or greater.
* All stable contrib modules of the same major version with this project
will use the same entire version.
* Stable modules may be released with an incremented minor or patch
version even though that module's code has not been changed. Instead
the only change that will have been included is to have updated that
modules dependency on this project's stable APIs.
* Contrib modules will be kept up to date with this project's releases.
* GitHub releases will be made for all releases.
* Go modules will be made available at Go package mirrors.
### Long-term support after v1
The OpenTelemetry Collector SIG provides long-term support for stable Go modules. Support for modules depend on the module's [target audiences](CONTRIBUTING.md#target-audiences). The following policies apply to long-term support for any major version starting on v1:
- Modules intended for **component developers** MUST be supported for a minimum of **1 year** after the release of the next major version of said module or after the module has been marked as deprecated.
- Modules intended for **Collector library users** MUST be supported for a minimum of **6 months** after the release of the next major version of said module or after the module has been marked as deprecated.
opentelemetry-collector-0.141.0/client/ 0000775 0000000 0000000 00000000000 15113313446 0020014 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/client/Makefile 0000664 0000000 0000000 00000000033 15113313446 0021450 0 ustar 00root root 0000000 0000000 include ../Makefile.Common
opentelemetry-collector-0.141.0/client/client.go 0000664 0000000 0000000 00000013434 15113313446 0021626 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package client contains generic representations of clients connecting to
// different receivers. Components, such as processors or exporters, can make
// use of this information to make decisions related to grouping of batches,
// tenancy, load balancing, tagging, among others.
//
// The structs defined here are typically used within the context that is
// propagated down the pipeline, with the values being produced by
// authenticators and/or receivers, and consumed by processors and exporters.
//
// # Producers
//
// Receivers are responsible for obtaining a client.Info from the current
// context and enhancing the client.Info with the net.Addr from the peer,
// storing a new client.Info into the context that it passes down. For HTTP
// requests, the net.Addr is typically the IP address of the client.
//
// Typically, however, receivers would delegate this processing to helpers such
// as the confighttp or configgrpc packages: both contain interceptors that will
// enhance the context with the client.Info, such that no actions are needed by
// receivers that are built using confighttp.HTTPServerSettings or
// configgrpc.GRPCServerSettings.
//
// Authenticators are responsible for obtaining a client.Info from the current
// context, enhancing the client.Info with an implementation of client.AuthData,
// and storing a new client.Info into the context that it passes down. The
// attribute names should be documented with their return types and considered
// part of the public API for the authenticator.
//
// # Consumers
//
// Provided that the pipeline does not contain processors that would discard or
// rewrite the context, such as the batch processor, processors and exporters
// have access to the client.Info via client.FromContext. Among other usages,
// this data can be used to:
//
// - annotate data points with authentication data (username, tenant, ...)
//
// - route data points based on authentication data
//
// - rate limit client calls based on IP addresses
//
// Processors and exporters relying on the existence of data from the
// client.Info, especially client.AuthData, should clearly document this as part
// of the component's README file. The expected pattern for consuming data is to
// allow users to specify the attribute name to use in the component. The
// expected data type should also be communicated to users, who should then
// compare this with the authenticators that are part of the pipeline. For
// example, assuming that the OIDC authenticator pushes a "subject" string
// attribute and that we have a hypothetical "authprinter" processor that prints
// the "username" to the console, this is how an OpenTelemetry Collector
// configuration would look like:
//
// extensions:
// oidc:
// issuer_url: http://localhost:8080/auth/realms/opentelemetry
// audience: collector
// receivers:
// otlp:
// protocols:
// grpc:
// auth:
// authenticator: oidc
// processors:
// authprinter:
// attribute: subject
// exporters:
// debug:
// service:
// extensions: [oidc]
// pipelines:
// traces:
// receivers: [otlp]
// processors: [authprinter]
// exporters: [debug]
package client // import "go.opentelemetry.io/collector/client"
import (
"context"
"iter"
"maps"
"net"
"strings"
)
type ctxKey struct{}
// Info contains data related to the clients connecting to receivers.
type Info struct {
// Addr for the client connecting to this collector. Available in a
// best-effort basis, and generally reliable for receivers making use of
// confighttp.ToServer and configgrpc.ToServerOption.
Addr net.Addr
// Auth information from the incoming request as provided by
// configauth.ServerAuthenticator implementations tied to the receiver for
// this connection.
Auth AuthData
// Metadata is the request metadata from the client connecting to this connector.
Metadata Metadata
// prevent unkeyed literal initialization
_ struct{}
}
// AuthData represents the authentication data as seen by authenticators tied to
// the receivers.
type AuthData interface {
// GetAttribute returns the value for the given attribute. Authenticator
// implementations might define different data types for different
// attributes. While "string" is used most of the time, a key named
// "membership" might return a list of strings.
GetAttribute(string) any
// GetAttributeNames returns the names of all attributes in this authentication data.
GetAttributeNames() []string
}
const MetadataHostName = "Host"
// NewContext takes an existing context and derives a new context with the
// client.Info value stored on it.
func NewContext(ctx context.Context, c Info) context.Context {
return context.WithValue(ctx, ctxKey{}, c)
}
// FromContext takes a context and returns a ClientInfo from it.
// When a ClientInfo isn't present, a new empty one is returned.
func FromContext(ctx context.Context) Info {
c, ok := ctx.Value(ctxKey{}).(Info)
if !ok {
c = Info{}
}
return c
}
// 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 {
c[strings.ToLower(k)] = v
}
return Metadata{
data: c,
}
}
// Keys returns an iterator for the metadata keys.
func (m Metadata) Keys() iter.Seq[string] {
return maps.Keys(m.data)
}
// 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
}
vals := m.data[strings.ToLower(key)]
if len(vals) == 0 {
return nil
}
ret := make([]string, len(vals))
copy(ret, vals)
return ret
}
opentelemetry-collector-0.141.0/client/client_test.go 0000664 0000000 0000000 00000004441 15113313446 0022663 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
// Package client contains generic representations of clients connecting to
// different receivers
package client
import (
"context"
"net"
"slices"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewContext(t *testing.T) {
testCases := []struct {
name string
cl Info
}{
{
name: "valid client",
cl: Info{
Addr: &net.IPAddr{
IP: net.IPv4(1, 2, 3, 4),
},
},
},
{
name: "nil client",
cl: Info{},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ctx := NewContext(context.Background(), tt.cl)
assert.Equal(t, ctx.Value(ctxKey{}), tt.cl)
})
}
}
func TestFromContext(t *testing.T) {
testCases := []struct {
name string
input context.Context
expected Info
}{
{
name: "context with client",
input: context.WithValue(context.Background(), ctxKey{}, Info{
Addr: &net.IPAddr{
IP: net.IPv4(1, 2, 3, 4),
},
}),
expected: Info{
Addr: &net.IPAddr{
IP: net.IPv4(1, 2, 3, 4),
},
},
},
{
name: "context without client",
input: context.Background(),
expected: Info{},
},
{
name: "context with something else in the key",
input: context.WithValue(context.Background(), ctxKey{}, "unexpected!"),
expected: Info{},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, FromContext(tt.input))
})
}
}
func TestMetadata(t *testing.T) {
source := map[string][]string{"test-key": {"test-val"}, "TEST-KEY-2": {"test-val"}}
md := NewMetadata(source)
assert.Equal(t, []string{"test-key", "test-key-2"}, slices.Sorted(md.Keys()))
assert.Equal(t, []string{"test-val"}, md.Get("test-key"))
assert.Equal(t, []string{"test-val"}, md.Get("test-KEY")) // case insensitive lookup
assert.Equal(t, []string{"test-val"}, md.Get("test-key-2")) // case insensitive lookup
// test if copy. In regular use, source cannot change
val := md.Get("test-key")
source["test-key"][0] = "abc"
assert.Equal(t, []string{"test-val"}, val)
assert.Empty(t, md.Get("non-existent-key"))
}
func TestUninstantiatedMetadata(t *testing.T) {
i := Info{}
assert.Empty(t, slices.Collect(i.Metadata.Keys()))
assert.Empty(t, i.Metadata.Get("test"))
}
opentelemetry-collector-0.141.0/client/doc_test.go 0000664 0000000 0000000 00000004225 15113313446 0022152 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package client_test
import (
"context"
"fmt"
"net"
"go.opentelemetry.io/collector/client"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/pdata/ptrace"
)
func Example_receiver() {
// Your receiver get a next consumer when it's constructed
next, err := consumer.NewTraces(func(_ context.Context, _ ptrace.Traces) error {
return nil
})
if err != nil {
panic(err)
}
// You'll convert the incoming data into pipeline data
td := ptrace.NewTraces()
// You probably have a context with client metadata from your listener or
// scraper
ctx := context.Background()
// Get the client from the context: if it doesn't exist, FromContext will
// create one
cl := client.FromContext(ctx)
// Extract the client information based on your original context and set it
// to Addr
//nolint:govet
cl.Addr = &net.IPAddr{
IP: net.IPv4(1, 2, 3, 4),
}
// When you are done, propagate the context down the pipeline to the next
// consumer and handle error.
if err = next.ConsumeTraces(ctx, td); err != nil {
panic(err)
}
}
func Example_processor() {
// Your processor or exporter will receive a context, from which you get the
// client information
ctx := context.Background()
cl := client.FromContext(ctx)
// And use the information from the client as you need
fmt.Println(cl.Addr)
}
func Example_authenticator() {
// Your configauth.AuthenticateFunc receives a context
ctx := context.Background()
// Get the client from the context: if it doesn't exist, FromContext will
// create one
cl := client.FromContext(ctx)
// After a successful authentication, place the data you want to propagate
// as part of an AuthData implementation of your own
cl.Auth = &exampleAuthData{
username: "jdoe",
}
// Your configauth.AuthenticateFunc should return this new context
_ = client.NewContext(ctx, cl)
}
type exampleAuthData struct {
username string
}
func (e *exampleAuthData) GetAttribute(key string) any {
if key == "username" {
return e.username
}
return nil
}
func (e *exampleAuthData) GetAttributeNames() []string {
return []string{"username"}
}
opentelemetry-collector-0.141.0/client/go.mod 0000664 0000000 0000000 00000001760 15113313446 0021126 0 ustar 00root root 0000000 0000000 module go.opentelemetry.io/collector/client
go 1.24.0
require (
github.com/stretchr/testify v1.11.1
go.opentelemetry.io/collector/consumer v1.47.0
go.opentelemetry.io/collector/pdata v1.47.0
go.uber.org/goleak v1.3.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/hashicorp/go-version v1.7.0 // 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.3-0.20250322232337-35a7c28c31ee // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/collector/featuregate v1.47.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace go.opentelemetry.io/collector/consumer => ../consumer
replace go.opentelemetry.io/collector/pdata => ../pdata
replace go.opentelemetry.io/collector/featuregate => ../featuregate
replace go.opentelemetry.io/collector/internal/testutil => ../internal/testutil
opentelemetry-collector-0.141.0/client/go.sum 0000664 0000000 0000000 00000007727 15113313446 0021164 0 ustar 00root root 0000000 0000000 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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/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/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.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.opentelemetry.io/proto/slim/otlp v1.9.0 h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE=
go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI=
go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8=
go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4=
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=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
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=
opentelemetry-collector-0.141.0/client/package_test.go 0000664 0000000 0000000 00000000307 15113313446 0022775 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package client
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/ 0000775 0000000 0000000 00000000000 15113313446 0017301 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/ 0000775 0000000 0000000 00000000000 15113313446 0020727 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/Makefile 0000664 0000000 0000000 00000001037 15113313446 0022370 0 ustar 00root root 0000000 0000000 include ../../Makefile.Common
.PHONY: ocb
ocb:
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.
#
# The default config file is checked in so that `go install` will work
# and so that non-unix builds don't need sed to be installed.
.PHONY: config
config: internal/config/default.yaml
sed '-e/replaces:/,$$d' <../otelcorecol/builder-config.yaml > internal/config/default.yaml
opentelemetry-collector-0.141.0/cmd/builder/README.md 0000664 0000000 0000000 00000025366 15113313446 0022222 0 ustar 00root root 0000000 0000000 # OpenTelemetry Collector Builder (ocb)
This program generates a custom OpenTelemetry Collector binary based on a given configuration.
## TL;DR
```console
$ go install go.opentelemetry.io/collector/cmd/builder@v0.129.0
$ cat > otelcol-builder.yaml < /tmp/otelcol.yaml < github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.128.0
```
The builder also allows setting the scheme to use as the default URI scheme via `conf_resolver.default_uri_scheme`:
```yaml
conf_resolver:
default_uri_scheme: "env"
```
This tells the builder to produce a Collector that uses the `env` scheme when expanding configuration that does not
provide a scheme, such as `${HOST}` (instead of doing `${env:HOST}`).
## Steps
The builder has 3 steps:
* Generate: generates the golang source code
* Get modules: generates the go.mod file based on the imported modules in the generated golang source code
* Compilation: builds the OpenTelemetry Collector executable
Each step can be skipped independently: `--skip-generate`, `--skip-get-modules` and `--skip-compilation`.
For instance, a code generation step could execute
```console
ocb --skip-compilation --config=config.yaml
```
then commit the code in a git repo. A CI can sync the code and execute
```console
ocb --skip-generate --skip-get-modules --config=config.yaml
```
to only execute the compilation step.
### Strict versioning checks
The builder checks the relevant `go.mod`
file for the following things after `go get`ing all components and calling
`go mod tidy`:
1. The `dist::otelcol_version` field in the build configuration must have
matching major and minor versions as the core library version calculated by
the Go toolchain, considering all components. A mismatch could happen, for
example, when the builder or one of the components depends on a newer release
of the core collector library.
2. For each component in the build configuration, the major and minor versions
included in the `gomod` module specifier must match the one calculated by
the Go toolchain, considering all components. A mismatch could
happen, for example, when the enclosing Go module uses a newer
release of the core collector library.
The `--skip-strict-versioning` flag disables these versioning checks.
This flag is available temporarily and
**will be removed in a future minor version**.
### Cgo disabled by default
By default, the OpenTelemetry Collector binary is built with `CGO_ENABLED=0` in accordance with
how the official OpenTelemetry Collector releases are built. This can be overridden by adding
the following configuration option to the `dist` section of the builder configuration file:
```yaml
dist:
cgo_enabled: true
```
opentelemetry-collector-0.141.0/cmd/builder/RELEASE.md 0000664 0000000 0000000 00000001027 15113313446 0022331 0 ustar 00root root 0000000 0000000 # Releasing the OpenTelemetry Collector Builder
This project uses [`goreleaser`](https://github.com/goreleaser/goreleaser) to manage the release of new versions.
To release a new version, simply add a tag named `vX.Y.Z`, like:
```
git tag -a v0.1.1 -m "Release v0.1.1"
git push upstream v0.1.1
```
A new GitHub workflow should be started, and at the end, a GitHub release should have been created, similar with the ["Release v0.56.0"](https://github.com/open-telemetry/opentelemetry-collector/releases/tag/cmd%2Fbuilder%2Fv0.56.0). opentelemetry-collector-0.141.0/cmd/builder/go.mod 0000664 0000000 0000000 00000002713 15113313446 0022040 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
module go.opentelemetry.io/collector/cmd/builder
go 1.24.0
require (
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/env/v2 v2.0.0
github.com/knadh/koanf/providers/file v1.2.0
github.com/knadh/koanf/providers/fs v1.0.0
github.com/knadh/koanf/v2 v2.3.0
github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
go.uber.org/goleak v1.3.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.1
golang.org/x/mod v0.30.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/knadh/koanf/maps v0.1.2 // 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.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/sys v0.36.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
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
v0.57.1 // Release failed, use v0.57.2
v0.57.0 // Release failed, use v0.57.2
)
opentelemetry-collector-0.141.0/cmd/builder/go.sum 0000664 0000000 0000000 00000012726 15113313446 0022072 0 ustar 00root root 0000000 0000000 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
github.com/knadh/koanf/parsers/yaml v1.1.0/go.mod h1:HHmcHXUrp9cOPcuC+2wrr44GTUB0EC+PyfN3HZD9tFg=
github.com/knadh/koanf/providers/env/v2 v2.0.0 h1:Ad5H3eun722u+FvchiIcEIJZsZ2M6oxCkgZfWN5B5KY=
github.com/knadh/koanf/providers/env/v2 v2.0.0/go.mod h1:1g01PE+Ve1gBfWNNw2wmULRP0tc8RJrjn5p2N/jNCIc=
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/providers/fs v1.0.0 h1:tvn4MrduLgdOSUqqEHULUuIcELXf6xDOpH8GUErpYaY=
github.com/knadh/koanf/providers/fs v1.0.0/go.mod h1:FksHET+xXFNDozvj8ZCdom54OnZ6eGKJtC5FhZJKx/8=
github.com/knadh/koanf/v2 v2.3.0 h1:Qg076dDRFHvqnKG97ZEsi9TAg2/nFTa9hCdcSa1lvlM=
github.com/knadh/koanf/v2 v2.3.0/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
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.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
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=
opentelemetry-collector-0.141.0/cmd/builder/header.txt 0000664 0000000 0000000 00000001060 15113313446 0022715 0 ustar 00root root 0000000 0000000 Copyright The OpenTelemetry Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. opentelemetry-collector-0.141.0/cmd/builder/internal/ 0000775 0000000 0000000 00000000000 15113313446 0022543 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/internal/builder/ 0000775 0000000 0000000 00000000000 15113313446 0024171 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/internal/builder/config.go 0000664 0000000 0000000 00000017713 15113313446 0025776 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package builder // import "go.opentelemetry.io/collector/cmd/builder/internal/builder"
import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"slices"
"strings"
"time"
"go.uber.org/multierr"
"go.uber.org/zap"
)
const (
defaultBetaOtelColVersion = "v0.141.0"
defaultStableOtelColVersion = "v1.47.0"
)
// errMissingGoMod indicates an empty gomod field
var errMissingGoMod = errors.New("missing gomod specification for module")
// Config holds the builder's configuration
type Config struct {
Logger *zap.Logger
OtelColVersion string `mapstructure:"-"` // only used be the go.mod template
SkipGenerate bool `mapstructure:"-"`
SkipCompilation bool `mapstructure:"-"`
SkipGetModules bool `mapstructure:"-"`
SkipStrictVersioning bool `mapstructure:"-"`
LDFlags string `mapstructure:"-"`
LDSet bool `mapstructure:"-"` // only used to override LDFlags
GCFlags string `mapstructure:"-"`
GCSet bool `mapstructure:"-"` // only used to override GCFlags
Verbose bool `mapstructure:"-"`
Distribution Distribution `mapstructure:"dist"`
Exporters []Module `mapstructure:"exporters"`
Extensions []Module `mapstructure:"extensions"`
Receivers []Module `mapstructure:"receivers"`
Processors []Module `mapstructure:"processors"`
Connectors []Module `mapstructure:"connectors"`
ConfmapProviders []Module `mapstructure:"providers"`
ConfmapConverters []Module `mapstructure:"converters"`
Replaces []string `mapstructure:"replaces"`
Excludes []string `mapstructure:"excludes"`
ConfResolver ConfResolver `mapstructure:"conf_resolver"`
downloadModules retry `mapstructure:"-"`
}
type ConfResolver struct {
// When set, will be used to set the CollectorSettings.ConfResolver.DefaultScheme value,
// which determines how the Collector interprets URIs that have no scheme, such as ${ENV}.
// See https://pkg.go.dev/go.opentelemetry.io/collector/confmap#ResolverSettings for more details.
DefaultURIScheme string `mapstructure:"default_uri_scheme"`
}
// Distribution holds the parameters for the final binary
type Distribution struct {
Module string `mapstructure:"module"`
Name string `mapstructure:"name"`
Go string `mapstructure:"go"`
Description string `mapstructure:"description"`
OutputPath string `mapstructure:"output_path"`
Version string `mapstructure:"version"`
BuildTags string `mapstructure:"build_tags"`
DebugCompilation bool `mapstructure:"debug_compilation"`
CGoEnabled bool `mapstructure:"cgo_enabled"`
}
// Module represents a receiver, exporter, processor or extension for the distribution
type Module struct {
Name string `mapstructure:"name"` // if not specified, this is package part of the go mod (last part of the path)
Import string `mapstructure:"import"` // if not specified, this is the path part of the go mods
GoMod string `mapstructure:"gomod"` // a gomod-compatible spec for the module
Path string `mapstructure:"path"` // an optional path to the local version of this module
}
type retry struct {
numRetries int
wait time.Duration
}
// NewDefaultConfig creates a new config, with default values
func NewDefaultConfig() (*Config, error) {
log, err := zap.NewDevelopment()
if err != nil {
panic(fmt.Sprintf("failed to obtain a logger instance: %v", err))
}
outputDir, err := os.MkdirTemp("", "otelcol-distribution")
if err != nil {
return nil, err
}
return &Config{
OtelColVersion: defaultBetaOtelColVersion,
Logger: log,
Distribution: Distribution{
OutputPath: outputDir,
Module: "go.opentelemetry.io/collector/cmd/builder",
},
// basic retry if error from go mod command (in case of transient network error).
// retry 3 times with 5 second spacing interval
downloadModules: retry{
numRetries: 3,
wait: 5 * time.Second,
},
ConfmapProviders: []Module{
{
GoMod: "go.opentelemetry.io/collector/confmap/provider/envprovider " + defaultStableOtelColVersion,
},
{
GoMod: "go.opentelemetry.io/collector/confmap/provider/fileprovider " + defaultStableOtelColVersion,
},
{
GoMod: "go.opentelemetry.io/collector/confmap/provider/httpprovider " + defaultStableOtelColVersion,
},
{
GoMod: "go.opentelemetry.io/collector/confmap/provider/httpsprovider " + defaultStableOtelColVersion,
},
{
GoMod: "go.opentelemetry.io/collector/confmap/provider/yamlprovider " + defaultStableOtelColVersion,
},
},
}, nil
}
// Validate checks whether the current configuration is valid
func (c *Config) Validate() error {
return multierr.Combine(
validateModules("extension", c.Extensions),
validateModules("receiver", c.Receivers),
validateModules("exporter", c.Exporters),
validateModules("processor", c.Processors),
validateModules("connector", c.Connectors),
validateModules("provider", c.ConfmapProviders),
validateModules("converter", c.ConfmapConverters),
)
}
// SetGoPath sets go path
func (c *Config) SetGoPath() error {
if !c.SkipCompilation || !c.SkipGetModules {
//nolint:gosec // #nosec G204
if _, err := exec.Command(c.Distribution.Go, "env").CombinedOutput(); err != nil {
path, err := exec.LookPath("go")
if err != nil {
return ErrGoNotFound
}
c.Distribution.Go = path
}
c.Logger.Info("Using go", zap.String("go-executable", c.Distribution.Go))
}
return nil
}
// ParseModules will parse the Modules entries and populate the missing values
func (c *Config) ParseModules() error {
var err error
usedNames := make(map[string]int)
c.Extensions, err = parseModules(c.Extensions, usedNames)
if err != nil {
return err
}
c.Receivers, err = parseModules(c.Receivers, usedNames)
if err != nil {
return err
}
c.Exporters, err = parseModules(c.Exporters, usedNames)
if err != nil {
return err
}
c.Processors, err = parseModules(c.Processors, usedNames)
if err != nil {
return err
}
c.Connectors, err = parseModules(c.Connectors, usedNames)
if err != nil {
return err
}
c.ConfmapProviders, err = parseModules(c.ConfmapProviders, usedNames)
if err != nil {
return err
}
c.ConfmapConverters, err = parseModules(c.ConfmapConverters, usedNames)
if err != nil {
return err
}
return nil
}
func (c *Config) allComponents() []Module {
return slices.Concat[[]Module](c.Exporters, c.Receivers, c.Processors, c.Extensions, c.Connectors, c.ConfmapProviders, c.ConfmapConverters)
}
func validateModules(name string, mods []Module) error {
for i, mod := range mods {
if mod.GoMod == "" {
return fmt.Errorf("%s module at index %v: %w", name, i, errMissingGoMod)
}
}
return nil
}
func parseModules(mods []Module, usedNames map[string]int) ([]Module, error) {
var parsedModules []Module
for _, mod := range mods {
if mod.Import == "" {
mod.Import = strings.Split(mod.GoMod, " ")[0]
}
if mod.Name == "" {
parts := strings.Split(mod.Import, "/")
mod.Name = parts[len(parts)-1]
}
originalModName := mod.Name
if count, exists := usedNames[mod.Name]; exists {
var newName string
for {
newName = fmt.Sprintf("%s%d", mod.Name, count+1)
if _, transformedExists := usedNames[newName]; !transformedExists {
break
}
count++
}
mod.Name = newName
usedNames[newName] = 1
}
usedNames[originalModName] = 1
// Check if path is empty, otherwise filepath.Abs replaces it with current path ".".
if mod.Path != "" {
var err error
mod.Path, err = filepath.Abs(mod.Path)
if err != nil {
return mods, fmt.Errorf("module has a relative \"path\" element, but we couldn't resolve the current working dir: %w", err)
}
// Check if the path exists
if _, err := os.Stat(mod.Path); os.IsNotExist(err) {
return mods, fmt.Errorf("filepath does not exist: %s", mod.Path)
}
}
parsedModules = append(parsedModules, mod)
}
return parsedModules, nil
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/config_test.go 0000664 0000000 0000000 00000022415 15113313446 0027030 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package builder
import (
"os"
"strings"
"testing"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"go.opentelemetry.io/collector/cmd/builder/internal/config"
)
func TestAliases(t *testing.T) {
// prepare
cfg := Config{
Extensions: []Module{
{
GoMod: "github.com/org/repo/impl v0.1.2",
},
{
GoMod: "github.com/org/repo2/impl v0.1.2",
},
{
GoMod: "github.com/org/repo3/impl v0.1.2",
},
},
Receivers: []Module{
{
GoMod: "github.com/org/repo v0.1.2",
},
{
GoMod: "github.com/org2/repo v0.1.2",
},
{
GoMod: "github.com/org/repo4/impl v0.1.2",
},
},
Exporters: []Module{
{
GoMod: "github.com/another/module v0.1.2",
},
{
GoMod: "github.com/org/repo5/impl v0.1.2",
},
},
Processors: []Module{
{
GoMod: "github.com/another/module2 v0.1.2",
},
{
GoMod: "github.com/another2/module v0.1.2",
},
},
Connectors: []Module{
{
GoMod: "github.com/another/module3 v0.1.2",
},
{
GoMod: "github.com/another2/module4 v0.1.2",
},
{
GoMod: "github.com/another3/module v0.1.2",
},
},
}
// test
err := cfg.ParseModules()
require.NoError(t, err)
// verify
assert.Equal(t, "github.com/org/repo/impl v0.1.2", cfg.Extensions[0].GoMod)
assert.Equal(t, "github.com/org/repo/impl", cfg.Extensions[0].Import)
assert.Equal(t, "impl", cfg.Extensions[0].Name)
assert.Equal(t, "github.com/org/repo2/impl v0.1.2", cfg.Extensions[1].GoMod)
assert.Equal(t, "github.com/org/repo2/impl", cfg.Extensions[1].Import)
assert.Equal(t, "impl2", cfg.Extensions[1].Name)
assert.Equal(t, "github.com/org/repo3/impl v0.1.2", cfg.Extensions[2].GoMod)
assert.Equal(t, "github.com/org/repo3/impl", cfg.Extensions[2].Import)
assert.Equal(t, "impl3", cfg.Extensions[2].Name)
assert.Equal(t, "github.com/org/repo v0.1.2", cfg.Receivers[0].GoMod)
assert.Equal(t, "github.com/org/repo", cfg.Receivers[0].Import)
assert.Equal(t, "repo", cfg.Receivers[0].Name)
assert.Equal(t, "github.com/org2/repo v0.1.2", cfg.Receivers[1].GoMod)
assert.Equal(t, "github.com/org2/repo", cfg.Receivers[1].Import)
assert.Equal(t, "repo2", cfg.Receivers[1].Name)
assert.Equal(t, "github.com/org/repo4/impl v0.1.2", cfg.Receivers[2].GoMod)
assert.Equal(t, "github.com/org/repo4/impl", cfg.Receivers[2].Import)
assert.Equal(t, "impl4", cfg.Receivers[2].Name)
assert.Equal(t, "github.com/another/module v0.1.2", cfg.Exporters[0].GoMod)
assert.Equal(t, "github.com/another/module", cfg.Exporters[0].Import)
assert.Equal(t, "module", cfg.Exporters[0].Name)
assert.Equal(t, "github.com/org/repo5/impl v0.1.2", cfg.Exporters[1].GoMod)
assert.Equal(t, "github.com/org/repo5/impl", cfg.Exporters[1].Import)
assert.Equal(t, "impl5", cfg.Exporters[1].Name)
assert.Equal(t, "github.com/another/module2 v0.1.2", cfg.Processors[0].GoMod)
assert.Equal(t, "github.com/another/module2", cfg.Processors[0].Import)
assert.Equal(t, "module2", cfg.Processors[0].Name)
assert.Equal(t, "github.com/another2/module v0.1.2", cfg.Processors[1].GoMod)
assert.Equal(t, "github.com/another2/module", cfg.Processors[1].Import)
assert.Equal(t, "module3", cfg.Processors[1].Name)
assert.Equal(t, "github.com/another/module3 v0.1.2", cfg.Connectors[0].GoMod)
assert.Equal(t, "github.com/another/module3", cfg.Connectors[0].Import)
assert.Equal(t, "module32", cfg.Connectors[0].Name)
assert.Equal(t, "github.com/another2/module4 v0.1.2", cfg.Connectors[1].GoMod)
assert.Equal(t, "github.com/another2/module4", cfg.Connectors[1].Import)
assert.Equal(t, "module4", cfg.Connectors[1].Name)
assert.Equal(t, "github.com/another3/module v0.1.2", cfg.Connectors[2].GoMod)
assert.Equal(t, "github.com/another3/module", cfg.Connectors[2].Import)
assert.Equal(t, "module5", cfg.Connectors[2].Name)
}
func TestParseModules(t *testing.T) {
// prepare
cfg := Config{
Extensions: []Module{{
GoMod: "github.com/org/repo v0.1.2",
}},
}
// test
err := cfg.ParseModules()
require.NoError(t, err)
// verify
assert.Equal(t, "github.com/org/repo v0.1.2", cfg.Extensions[0].GoMod)
assert.Equal(t, "github.com/org/repo", cfg.Extensions[0].Import)
assert.Equal(t, "repo", cfg.Extensions[0].Name)
}
func TestInvalidConverter(t *testing.T) {
// Create a Config instance with invalid Converters
config := &Config{
ConfmapConverters: []Module{
{
Path: "./invalid/module/path", // Invalid module path to trigger an error
},
},
}
// Call the method and expect an error
err := config.ParseModules()
require.Error(t, err, "expected an error when parsing invalid modules")
}
func TestRelativePath(t *testing.T) {
// prepare
cfg := Config{
Extensions: []Module{{
GoMod: "some-module",
Path: "./templates",
}},
}
// test
err := cfg.ParseModules()
require.NoError(t, err)
// verify
cwd, err := os.Getwd()
require.NoError(t, err)
assert.True(t, strings.HasPrefix(cfg.Extensions[0].Path, cwd))
}
func TestModuleFromCore(t *testing.T) {
// prepare
cfg := Config{
Extensions: []Module{ // see issue-12
{
Import: "go.opentelemetry.io/collector/receiver/otlpreceiver",
GoMod: "go.opentelemetry.io/collector v0.0.0",
},
{
Import: "go.opentelemetry.io/collector/receiver/otlpreceiver",
GoMod: "go.opentelemetry.io/collector v0.0.0",
},
},
}
// test
err := cfg.ParseModules()
require.NoError(t, err)
// verify
assert.True(t, strings.HasPrefix(cfg.Extensions[0].Name, "otlpreceiver"))
}
func TestMissingModule(t *testing.T) {
type invalidModuleTest struct {
cfg Config
err error
}
// prepare
configurations := []invalidModuleTest{
{
cfg: Config{
Logger: zap.NewNop(),
ConfmapProviders: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
{
cfg: Config{
Logger: zap.NewNop(),
Extensions: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
{
cfg: Config{
Logger: zap.NewNop(),
Receivers: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
{
cfg: Config{
Logger: zap.NewNop(),
Exporters: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
{
cfg: Config{
Logger: zap.NewNop(),
Processors: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
{
cfg: Config{
Logger: zap.NewNop(),
Connectors: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
{
cfg: Config{
Logger: zap.NewNop(),
ConfmapConverters: []Module{{
Import: "invalid",
}},
},
err: errMissingGoMod,
},
}
for _, test := range configurations {
assert.ErrorIs(t, test.cfg.Validate(), test.err)
}
}
func TestNewDefaultConfig(t *testing.T) {
cfg, err := NewDefaultConfig()
require.NoError(t, err)
require.NoError(t, cfg.ParseModules())
assert.NoError(t, cfg.Validate())
assert.NoError(t, cfg.SetGoPath())
require.NoError(t, cfg.Validate())
assert.False(t, cfg.Distribution.DebugCompilation)
assert.Empty(t, cfg.Distribution.BuildTags)
assert.False(t, cfg.LDSet)
assert.Empty(t, cfg.LDFlags)
assert.False(t, cfg.GCSet)
assert.Empty(t, cfg.GCFlags)
}
func TestNewBuiltinConfig(t *testing.T) {
k := koanf.New(".")
require.NoError(t, k.Load(config.DefaultProvider(), yaml.Parser()))
cfg := Config{Logger: zaptest.NewLogger(t)}
require.NoError(t, k.UnmarshalWithConf("", &cfg, koanf.UnmarshalConf{Tag: "mapstructure"}))
assert.NoError(t, cfg.ParseModules())
assert.NoError(t, cfg.Validate())
assert.NoError(t, cfg.SetGoPath())
// Unlike the config initialized in NewDefaultConfig(), we expect
// the builtin default to be practically useful, so there must be
// a set of modules present.
assert.NotEmpty(t, cfg.Receivers)
assert.NotEmpty(t, cfg.Exporters)
assert.NotEmpty(t, cfg.Extensions)
assert.NotEmpty(t, cfg.Processors)
}
func TestSkipGoValidation(t *testing.T) {
cfg := Config{
Distribution: Distribution{
Go: "invalid/go/binary/path",
},
SkipCompilation: true,
SkipGetModules: true,
}
assert.NoError(t, cfg.Validate())
assert.NoError(t, cfg.SetGoPath())
}
func TestSkipGoInitialization(t *testing.T) {
cfg := Config{
SkipCompilation: true,
SkipGetModules: true,
}
assert.NoError(t, cfg.Validate())
assert.NoError(t, cfg.SetGoPath())
assert.Empty(t, cfg.Distribution.Go)
}
func TestBuildTagConfig(t *testing.T) {
cfg := Config{
Distribution: Distribution{
BuildTags: "customTag",
},
SkipCompilation: true,
SkipGetModules: true,
}
require.NoError(t, cfg.Validate())
assert.Equal(t, "customTag", cfg.Distribution.BuildTags)
}
func TestDebugOptionSetConfig(t *testing.T) {
cfg := Config{
Distribution: Distribution{
DebugCompilation: true,
},
SkipCompilation: true,
SkipGetModules: true,
}
require.NoError(t, cfg.Validate())
assert.True(t, cfg.Distribution.DebugCompilation)
}
func TestAddsDefaultProviders(t *testing.T) {
cfg, err := NewDefaultConfig()
require.NoError(t, err)
require.NoError(t, cfg.ParseModules())
assert.Len(t, cfg.ConfmapProviders, 5)
}
func TestSkipsNilFieldValidation(t *testing.T) {
cfg, err := NewDefaultConfig()
require.NoError(t, err)
cfg.ConfmapProviders = nil
cfg.ConfmapConverters = nil
assert.NoError(t, cfg.Validate())
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/main.go 0000664 0000000 0000000 00000017415 15113313446 0025454 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
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"
"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")
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"
)
const otelcolPath = "go.opentelemetry.io/collector/otelcol"
func runGoCommand(cfg *Config, args ...string) ([]byte, error) {
if cfg.Verbose {
cfg.Logger.Info("Running go subcommand.", zap.Any("arguments", args))
}
//nolint:gosec // #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
cmd.Env = os.Environ()
if cfg.Distribution.CGoEnabled {
cmd.Env = append(cmd.Env, "CGO_ENABLED=1")
} else {
cmd.Env = append(cmd.Env, "CGO_ENABLED=0")
}
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
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 stdout.Bytes(), nil
}
// GenerateAndCompile will generate the source files based on the given configuration, update go mod, and will compile into a binary
func GenerateAndCompile(cfg *Config) error {
if err := Generate(cfg); err != nil {
return err
}
// run go get to update go.mod and go.sum files
if err := GetModules(cfg); err != nil {
return err
}
return Compile(cfg)
}
// Generate assembles a new distribution based on the given configuration
func Generate(cfg *Config) error {
if cfg.SkipGenerate {
cfg.Logger.Info("Skipping generating source codes.")
return nil
}
// if the file does not exist, try to create it
if _, err := os.Stat(cfg.Distribution.OutputPath); os.IsNotExist(err) {
if err = os.Mkdir(cfg.Distribution.OutputPath, 0o750); 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)
}
for _, tmpl := range []*template.Template{
mainTemplate,
mainOthersTemplate,
mainWindowsTemplate,
componentsTemplate,
goModTemplate,
} {
if err := processAndWrite(cfg, tmpl, tmpl.Name(), cfg); err != nil {
return fmt.Errorf("failed to generate source file %q: %w", tmpl.Name(), err)
}
}
cfg.Logger.Info("Sources created", zap.String("path", cfg.Distribution.OutputPath))
return nil
}
// Compile generates a binary from the sources based on the configuration
func Compile(cfg *Config) error {
if cfg.SkipCompilation {
cfg.Logger.Info("Generating source codes only, the distribution will not be compiled.")
return nil
}
cfg.Logger.Info("Compiling")
ldflags := "-s -w" // we strip the symbols by default for smaller binaries
gcflags := ""
args := []string{"build", "-trimpath", "-o", cfg.Distribution.Name}
if cfg.Distribution.DebugCompilation {
cfg.Logger.Info("Debug compilation is enabled, the debug symbols will be left on the resulting binary")
ldflags = cfg.LDFlags
gcflags = "all=-N -l"
} else {
if cfg.LDSet {
cfg.Logger.Info("Using custom ldflags", zap.String("ldflags", cfg.LDFlags))
ldflags = cfg.LDFlags
}
if cfg.GCSet {
cfg.Logger.Info("Using custom gcflags", zap.String("gcflags", cfg.GCFlags))
gcflags = cfg.GCFlags
}
}
if cfg.Distribution.CGoEnabled {
cfg.Logger.Info("Building with cgo enabled")
}
args = append(args, "-ldflags="+ldflags, "-gcflags="+gcflags)
if cfg.Distribution.BuildTags != "" {
args = append(args, "-tags", cfg.Distribution.BuildTags)
}
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)))
return nil
}
// GetModules retrieves the go modules, updating go.mod and go.sum in the process
func GetModules(cfg *Config) error {
if cfg.SkipGetModules {
cfg.Logger.Info("Generating source codes only, will not update go.mod and retrieve Go modules.")
return nil
}
if _, err := runGoCommand(cfg, "mod", "tidy", "-compat=1.24"); 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 := readGoModFile(cfg)
if err != nil {
return err
}
coreDepVersion, ok := dependencyVersions[otelcolPath]
betaVersion := semver.MajorMinor(defaultBetaOtelColVersion)
if !ok {
return fmt.Errorf("core collector %w: '%s'. %s", ErrDepNotFound, otelcolPath, skipStrictMsg)
}
if semver.MajorMinor(coreDepVersion) != betaVersion {
return fmt.Errorf(
"%w: core collector version calculated by component dependencies %q does not match configured version %q. %s",
ErrVersionMismatch, coreDepVersion, betaVersion, 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")
failReason := "unknown"
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, cfg.downloadModules.numRetries)))
time.Sleep(cfg.downloadModules.wait)
continue
}
return nil
}
return fmt.Errorf("%w: %s", errDownloadFailed, failReason)
}
func processAndWrite(cfg *Config, tmpl *template.Template, outFile string, tmplParams any) error {
out, err := os.Create(filepath.Clean(filepath.Join(cfg.Distribution.OutputPath, outFile)))
if err != nil {
return err
}
defer out.Close()
return tmpl.Execute(out, tmplParams)
}
func readGoModFile(cfg *Config) (string, map[string]string, error) {
var modPath string
stdout, err := runGoCommand(cfg, "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.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
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/main_test.go 0000664 0000000 0000000 00000033266 15113313446 0026515 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package builder
import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"golang.org/x/mod/modfile"
)
const (
goModTestFile = `// 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
)`
modulePrefix = "go.opentelemetry.io/collector"
)
var replaceModules = []string{
"",
"/component",
"/component/componentstatus",
"/component/componenttest",
"/client",
"/config/configauth",
"/config/configcompression",
"/config/configgrpc",
"/config/confighttp",
"/config/configmiddleware",
"/config/confignet",
"/config/configopaque",
"/config/configoptional",
"/config/configretry",
"/config/configtelemetry",
"/config/configtls",
"/confmap",
"/confmap/xconfmap",
"/confmap/provider/envprovider",
"/confmap/provider/fileprovider",
"/confmap/provider/httpprovider",
"/confmap/provider/httpsprovider",
"/confmap/provider/yamlprovider",
"/consumer",
"/consumer/consumererror",
"/consumer/consumererror/xconsumererror",
"/consumer/xconsumer",
"/consumer/consumertest",
"/connector",
"/connector/connectortest",
"/connector/xconnector",
"/exporter",
"/exporter/debugexporter",
"/exporter/xexporter",
"/exporter/exportertest",
"/exporter/exporterhelper",
"/exporter/exporterhelper/xexporterhelper",
"/exporter/nopexporter",
"/exporter/otlpexporter",
"/exporter/otlphttpexporter",
"/extension",
"/extension/extensionauth",
"/extension/extensionauth/extensionauthtest",
"/extension/extensioncapabilities",
"/extension/extensionmiddleware",
"/extension/extensionmiddleware/extensionmiddlewaretest",
"/extension/extensiontest",
"/extension/zpagesextension",
"/extension/xextension",
"/featuregate",
"/internal/memorylimiter",
"/internal/fanoutconsumer",
"/internal/sharedcomponent",
"/internal/telemetry",
"/internal/testutil",
"/otelcol",
"/pdata",
"/pdata/testdata",
"/pdata/pprofile",
"/pdata/xpdata",
"/pipeline",
"/pipeline/xpipeline",
"/processor",
"/processor/processortest",
"/processor/batchprocessor",
"/processor/memorylimiterprocessor",
"/processor/processorhelper",
"/processor/processorhelper/xprocessorhelper",
"/processor/xprocessor",
"/receiver",
"/receiver/nopreceiver",
"/receiver/otlpreceiver",
"/receiver/receivertest",
"/receiver/receiverhelper",
"/receiver/xreceiver",
"/service",
"/service/hostcapabilities",
"/service/telemetry/telemetrytest",
}
func newTestConfig(tb testing.TB) *Config {
cfg, err := NewDefaultConfig()
require.NoError(tb, err)
cfg.downloadModules.wait = 0
cfg.downloadModules.numRetries = 1
return cfg
}
func newInitializedConfig(t *testing.T) *Config {
cfg := newTestConfig(t)
// Validate and ParseModules will be called before the config is
// given to Generate.
assert.NoError(t, cfg.Validate())
assert.NoError(t, cfg.ParseModules())
return cfg
}
func TestGenerateDefault(t *testing.T) {
require.NoError(t, Generate(newInitializedConfig(t)))
}
func TestGenerateInvalidOutputPath(t *testing.T) {
cfg := newInitializedConfig(t)
cfg.Distribution.OutputPath = ":/invalid"
err := Generate(cfg)
require.ErrorContains(t, err, "failed to create output path")
}
func TestVersioning(t *testing.T) {
replaces := generateReplaces()
tests := []struct {
name string
cfgBuilder func() *Config
expectedErr error
}{
{
name: "defaults",
cfgBuilder: func() *Config {
cfg := newTestConfig(t)
cfg.Distribution.Go = "go"
cfg.Replaces = append(cfg.Replaces, replaces...)
return cfg
},
expectedErr: nil,
},
{
name: "only gomod file, skip generate",
cfgBuilder: func() *Config {
cfg := newTestConfig(t)
tempDir := t.TempDir()
err := makeModule(tempDir, []byte(goModTestFile))
require.NoError(t, err)
cfg.Distribution.OutputPath = tempDir
cfg.SkipGenerate = true
cfg.Distribution.Go = "go"
return cfg
},
expectedErr: ErrDepNotFound,
},
{
name: "old component version",
cfgBuilder: func() *Config {
cfg := newTestConfig(t)
cfg.Distribution.Go = "go"
cfg.Exporters = []Module{
{
GoMod: "go.opentelemetry.io/collector/exporter/otlpexporter v0.112.0",
},
}
cfg.ConfmapProviders = []Module{}
cfg.Replaces = append(cfg.Replaces, replaces...)
return cfg
},
expectedErr: nil,
},
{
name: "old component version without strict mode",
cfgBuilder: func() *Config {
cfg := newTestConfig(t)
cfg.Distribution.Go = "go"
cfg.SkipStrictVersioning = true
cfg.Exporters = []Module{
{
GoMod: "go.opentelemetry.io/collector/exporter/otlpexporter v0.112.0",
},
}
cfg.ConfmapProviders = []Module{}
cfg.Replaces = append(cfg.Replaces, replaces...)
return cfg
},
expectedErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// X25519 curves are not supported when GODEBUG=fips140=only is set, so we
// detect if it is and conditionally also add the tlsmklem=0 flag to disable
// these curves. See: https://pkg.go.dev/crypto/tls#Config.CurvePreferences
if strings.Contains(os.Getenv("GODEBUG"), "fips140=only") {
t.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tlsmlkem=0")
}
cfg := tt.cfgBuilder()
require.NoError(t, cfg.Validate())
require.NoError(t, cfg.ParseModules())
err := GenerateAndCompile(cfg)
require.ErrorIs(t, err, tt.expectedErr)
})
}
}
func TestSkipGenerate(t *testing.T) {
cfg := newInitializedConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.SkipGenerate = true
err := Generate(cfg)
require.NoError(t, err)
outputFile, err := os.Open(cfg.Distribution.OutputPath)
defer func() {
require.NoError(t, outputFile.Close())
}()
require.NoError(t, err)
_, err = outputFile.Readdirnames(1)
require.ErrorIs(t, err, io.EOF, "skip generate should leave output directory empty")
}
func TestGenerateAndCompile(t *testing.T) {
replaces := generateReplaces()
testCases := []struct {
name string
cfgBuilder func(t *testing.T) *Config
}{
{
name: "Default Configuration Compilation",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
return cfg
},
},
{
name: "LDFlags Compilation",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.LDSet = true
cfg.LDFlags = `-X "test.gitVersion=0743dc6c6411272b98494a9b32a63378e84c34da" -X "test.gitTag=local-testing" -X "test.goVersion=go version go1.20.7 darwin/amd64"`
return cfg
},
},
{
name: "GCFlags Compilation",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.GCSet = true
cfg.GCFlags = `all=-N -l`
return cfg
},
},
{
name: "Build Tags Compilation",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.Distribution.BuildTags = "customTag"
return cfg
},
},
{
name: "Debug Compilation",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.Logger = zap.NewNop()
cfg.Distribution.DebugCompilation = true
return cfg
},
},
{
name: "No providers",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.ConfmapProviders = []Module{}
return cfg
},
},
{
name: "With confmap factories",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.SkipStrictVersioning = true
return cfg
},
},
{
name: "ConfResolverDefaultURIScheme set",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.ConfResolver = ConfResolver{
DefaultURIScheme: "env",
}
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
return cfg
},
},
{
name: "CGoEnabled set to true",
cfgBuilder: func(t *testing.T) *Config {
cfg := newTestConfig(t)
cfg.Distribution.OutputPath = t.TempDir()
cfg.Replaces = append(cfg.Replaces, replaces...)
cfg.Distribution.CGoEnabled = true
return cfg
},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(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))
})
}
}
// Test that the go.mod files that other tests in this file
// may generate have all their modules covered by our
// "replace" statements created in `generateReplaces`.
//
// An incomplete set of replace statements in these tests
// may cause them to fail during the release process, when
// the local version of modules in the release branch is
// not yet available on the Go package repository.
// Unless the replace statements route all modules to the
// local copy, `go get` will try to fetch the unreleased
// version remotely and some tests will fail.
func TestReplaceStatementsAreComplete(t *testing.T) {
workspaceDir := getWorkspaceDir()
replaceMods := map[string]bool{}
for _, suffix := range replaceModules {
replaceMods[modulePrefix+suffix] = false
}
for _, mod := range replaceModules {
verifyGoMod(t, workspaceDir+mod, replaceMods)
}
var err error
dir := t.TempDir()
cfg, err := NewDefaultConfig()
require.NoError(t, err)
cfg.Distribution.Go = "go"
cfg.Distribution.OutputPath = dir
cfg.Replaces = append(cfg.Replaces, generateReplaces()...)
// Configure all components that we want to use elsewhere in these tests.
// This ensures the resulting go.mod file has maximum coverage of modules
// that exist in the Core repository.
usedNames := make(map[string]int)
cfg.Exporters, err = parseModules([]Module{
{
GoMod: "go.opentelemetry.io/collector/exporter/debugexporter v1.9999.9999",
},
{
GoMod: "go.opentelemetry.io/collector/exporter/nopexporter v1.9999.9999",
},
{
GoMod: "go.opentelemetry.io/collector/exporter/otlpexporter v1.9999.9999",
},
{
GoMod: "go.opentelemetry.io/collector/exporter/otlphttpexporter v1.9999.9999",
},
}, usedNames)
require.NoError(t, err)
cfg.Receivers, err = parseModules([]Module{
{
GoMod: "go.opentelemetry.io/collector/receiver/nopreceiver v1.9999.9999",
},
{
GoMod: "go.opentelemetry.io/collector/receiver/otlpreceiver v1.9999.9999",
},
}, usedNames)
require.NoError(t, err)
cfg.Extensions, err = parseModules([]Module{
{
GoMod: "go.opentelemetry.io/collector/extension/zpagesextension v1.9999.9999",
},
}, usedNames)
require.NoError(t, err)
cfg.Processors, err = parseModules([]Module{
{
GoMod: "go.opentelemetry.io/collector/processor/batchprocessor v1.9999.9999",
},
{
GoMod: "go.opentelemetry.io/collector/processor/memorylimiterprocessor v1.9999.9999",
},
}, usedNames)
require.NoError(t, err)
require.NoError(t, cfg.Validate())
require.NoError(t, cfg.ParseModules())
err = GenerateAndCompile(cfg)
require.NoError(t, err)
verifyGoMod(t, dir, replaceMods)
for k, v := range replaceMods {
assert.Truef(t, v, "Module not used: %s", k)
}
}
func verifyGoMod(t *testing.T, dir string, replaceMods map[string]bool) {
gomodpath := path.Join(dir, "go.mod")
//nolint:gosec // #nosec G304 We control this path and generate the file inside, so we can assume it is safe.
gomod, err := os.ReadFile(gomodpath)
require.NoError(t, err)
mod, err := modfile.Parse(gomodpath, gomod, nil)
require.NoError(t, err)
for _, req := range mod.Require {
if !strings.HasPrefix(req.Mod.Path, modulePrefix) {
continue
}
_, ok := replaceMods[req.Mod.Path]
assert.Truef(t, ok, "Module missing from replace statements list: %s", req.Mod.Path)
replaceMods[req.Mod.Path] = true
}
}
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, 0o750); 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, 0o600)
if err != nil {
return fmt.Errorf("failed to write go.mod file: %w", err)
}
return nil
}
func generateReplaces() []string {
workspaceDir := getWorkspaceDir()
modules := replaceModules
replaces := make([]string, len(modules))
for i, mod := range modules {
replaces[i] = fmt.Sprintf("%s%s => %s%s", modulePrefix, mod, workspaceDir, mod)
}
return replaces
}
func getWorkspaceDir() string {
// This 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)
return filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(thisFile)))))
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/package_test.go 0000664 0000000 0000000 00000000310 15113313446 0027144 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package builder
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates.go 0000664 0000000 0000000 00000001740 15113313446 0026520 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package builder // import "go.opentelemetry.io/collector/cmd/builder/internal/builder"
import (
_ "embed"
"text/template"
)
var (
//go:embed templates/components.go.tmpl
componentsBytes []byte
componentsTemplate = parseTemplate("components.go", componentsBytes)
//go:embed templates/main.go.tmpl
mainBytes []byte
mainTemplate = parseTemplate("main.go", mainBytes)
//go:embed templates/main_others.go.tmpl
mainOthersBytes []byte
mainOthersTemplate = parseTemplate("main_others.go", mainOthersBytes)
//go:embed templates/main_windows.go.tmpl
mainWindowsBytes []byte
mainWindowsTemplate = parseTemplate("main_windows.go", mainWindowsBytes)
//go:embed templates/go.mod.tmpl
goModBytes []byte
goModTemplate = parseTemplate("go.mod", goModBytes)
)
func parseTemplate(name string, bytes []byte) *template.Template {
return template.Must(template.New(name).Parse(string(bytes)))
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates/ 0000775 0000000 0000000 00000000000 15113313446 0026167 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates/components.go.tmpl 0000664 0000000 0000000 00000005517 15113313446 0031666 0 ustar 00root root 0000000 0000000 // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT.
package main
import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/exporter"
"go.opentelemetry.io/collector/extension"
"go.opentelemetry.io/collector/otelcol"
"go.opentelemetry.io/collector/processor"
"go.opentelemetry.io/collector/receiver"
"go.opentelemetry.io/collector/service/telemetry/otelconftelemetry"
{{- range .Connectors}}
{{.Name}} "{{.Import}}"
{{- end}}
{{- range .Exporters}}
{{.Name}} "{{.Import}}"
{{- end}}
{{- range .Extensions}}
{{.Name}} "{{.Import}}"
{{- end}}
{{- range .Processors}}
{{.Name}} "{{.Import}}"
{{- end}}
{{- range .Receivers}}
{{.Name}} "{{.Import}}"
{{- end}}
)
func components() (otelcol.Factories, error) {
var err error
factories := otelcol.Factories{
Telemetry: otelconftelemetry.NewFactory(),
}
factories.Extensions, err = otelcol.MakeFactoryMap[extension.Factory](
{{- range .Extensions}}
{{.Name}}.NewFactory(),
{{- end}}
)
if err != nil {
return otelcol.Factories{}, err
}
factories.ExtensionModules = make(map[component.Type]string, len(factories.Extensions))
{{- range .Extensions}}
factories.ExtensionModules[{{.Name}}.NewFactory().Type()] = "{{.GoMod}}"
{{- end}}
factories.Receivers, err = otelcol.MakeFactoryMap[receiver.Factory](
{{- range .Receivers}}
{{.Name}}.NewFactory(),
{{- end}}
)
if err != nil {
return otelcol.Factories{}, err
}
factories.ReceiverModules = make(map[component.Type]string, len(factories.Receivers))
{{- range .Receivers}}
factories.ReceiverModules[{{.Name}}.NewFactory().Type()] = "{{.GoMod}}"
{{- end}}
factories.Exporters, err = otelcol.MakeFactoryMap[exporter.Factory](
{{- range .Exporters}}
{{.Name}}.NewFactory(),
{{- end}}
)
if err != nil {
return otelcol.Factories{}, err
}
factories.ExporterModules = make(map[component.Type]string, len(factories.Exporters))
{{- range .Exporters}}
factories.ExporterModules[{{.Name}}.NewFactory().Type()] = "{{.GoMod}}"
{{- end}}
factories.Processors, err = otelcol.MakeFactoryMap[processor.Factory](
{{- range .Processors}}
{{.Name}}.NewFactory(),
{{- end}}
)
if err != nil {
return otelcol.Factories{}, err
}
factories.ProcessorModules = make(map[component.Type]string, len(factories.Processors))
{{- range .Processors}}
factories.ProcessorModules[{{.Name}}.NewFactory().Type()] = "{{.GoMod}}"
{{- end}}
factories.Connectors, err = otelcol.MakeFactoryMap[connector.Factory](
{{- range .Connectors}}
{{.Name}}.NewFactory(),
{{- end}}
)
if err != nil {
return otelcol.Factories{}, err
}
factories.ConnectorModules = make(map[component.Type]string, len(factories.Connectors))
{{- range .Connectors}}
factories.ConnectorModules[{{.Name}}.NewFactory().Type()] = "{{.GoMod}}"
{{- end}}
return factories, nil
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates/go.mod.tmpl 0000664 0000000 0000000 00000003007 15113313446 0030250 0 ustar 00root root 0000000 0000000 // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT.
module {{.Distribution.Module}}
go 1.24
require (
{{- range .ConfmapConverters}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
{{- range .ConfmapProviders}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
{{- range .Connectors}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
{{- range .Extensions}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
{{- range .Receivers}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
{{- range .Exporters}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
{{- range .Processors}}
{{if .GoMod}}{{.GoMod}}{{end}}
{{- end}}
go.opentelemetry.io/collector/otelcol {{.OtelColVersion}}
)
require (
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
)
{{- range .ConfmapConverters}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .ConfmapProviders}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .Connectors}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .Extensions}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .Receivers}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .Exporters}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .Processors}}
{{if ne .Path ""}}replace {{.GoMod}} => {{.Path}}{{end}}
{{- end}}
{{- range .Replaces}}
replace {{.}}
{{- end}}
{{- range .Excludes}}
exclude {{.}}
{{- end}}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates/main.go.tmpl 0000664 0000000 0000000 00000003446 15113313446 0030424 0 ustar 00root root 0000000 0000000 // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT.
// Program {{ .Distribution.Name }} is an OpenTelemetry Collector binary.
package main
import (
"log"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/confmap"
{{- range .ConfmapConverters}}
{{.Name}} "{{.Import}}"
{{- end}}
{{- range .ConfmapProviders}}
{{.Name}} "{{.Import}}"
{{- end}}
"go.opentelemetry.io/collector/otelcol"
)
func main() {
info := component.BuildInfo{
Command: "{{ .Distribution.Name }}",
Description: "{{ .Distribution.Description }}",
Version: "{{ .Distribution.Version }}",
}
set := otelcol.CollectorSettings{
BuildInfo: info,
Factories: components,
ConfigProviderSettings: otelcol.ConfigProviderSettings{
ResolverSettings: confmap.ResolverSettings{
ProviderFactories: []confmap.ProviderFactory{
{{- range .ConfmapProviders}}
{{.Name}}.NewFactory(),
{{- end}}
},
{{- if .ConfmapConverters }}
ConverterFactories: []confmap.ConverterFactory{
{{- range .ConfmapConverters}}
{{.Name}}.NewFactory(),
{{- end}}
},
{{- end }}
{{- if .ConfResolver.DefaultURIScheme }}
DefaultScheme: "{{ .ConfResolver.DefaultURIScheme }}",
{{- end }}
},
},
ProviderModules: map[string]string{
{{- range .ConfmapProviders}}
{{.Name}}.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "{{.GoMod}}",
{{- end}}
},
ConverterModules: []string{
{{- range .ConfmapConverters}}
"{{.GoMod}}",
{{- end}}
},
}
if err := run(set); err != nil {
log.Fatal(err)
}
}
func runInteractive(params otelcol.CollectorSettings) error {
cmd := otelcol.NewCommand(params)
if err := cmd.Execute(); err != nil {
log.Fatalf("collector server run finished with error: %v", err)
}
return nil
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates/main_others.go.tmpl 0000664 0000000 0000000 00000000367 15113313446 0032007 0 ustar 00root root 0000000 0000000 // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT.
//go:build !windows
package main
import "go.opentelemetry.io/collector/otelcol"
func run(params otelcol.CollectorSettings) error {
return runInteractive(params)
}
opentelemetry-collector-0.141.0/cmd/builder/internal/builder/templates/main_windows.go.tmpl 0000664 0000000 0000000 00000001545 15113313446 0032174 0 ustar 00root root 0000000 0000000 // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT.
//go:build windows
package main
import (
"errors"
"fmt"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"go.opentelemetry.io/collector/otelcol"
)
func run(params otelcol.CollectorSettings) error {
// No need to supply service name when startup is invoked through
// the Service Control Manager directly.
if err := svc.Run("", otelcol.NewSvcHandler(params)); err != nil {
if errors.Is(err, windows.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
// Per https://learn.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-startservicectrldispatchera#return-value
// this means that the process is not running as a service, so run interactively.
return runInteractive(params)
}
return fmt.Errorf("failed to start collector server: %w", err)
}
return nil
}
opentelemetry-collector-0.141.0/cmd/builder/internal/command.go 0000664 0000000 0000000 00000012705 15113313446 0024515 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/builder/internal"
import (
"fmt"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/env/v2"
"github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/v2"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"go.uber.org/multierr"
"go.uber.org/zap"
"go.opentelemetry.io/collector/cmd/builder/internal/builder"
"go.opentelemetry.io/collector/cmd/builder/internal/config"
)
const (
configFlag = "config"
skipGenerateFlag = "skip-generate"
skipCompilationFlag = "skip-compilation"
skipGetModulesFlag = "skip-get-modules"
skipStrictVersioningFlag = "skip-strict-versioning"
ldflagsFlag = "ldflags"
gcflagsFlag = "gcflags"
distributionOutputPathFlag = "output-path"
verboseFlag = "verbose"
)
// Command is the main entrypoint for this application
func Command() (*cobra.Command, error) {
cmd := &cobra.Command{
SilenceUsage: true, // Don't print usage on Run error.
SilenceErrors: true, // Don't print errors; main does it.
Use: "ocb",
Long: fmt.Sprintf("OpenTelemetry Collector Builder (%s)", version) + `
ocb generates a custom OpenTelemetry Collector binary using the
build configuration given by the "--config" argument. If no build
configuration is provided, ocb will generate a default Collector.
`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
cfg, err := initConfig(cmd.Flags())
if err != nil {
return err
}
if err = cfg.Validate(); err != nil {
return fmt.Errorf("invalid configuration: %w", err)
}
if err = cfg.SetGoPath(); err != nil {
return fmt.Errorf("go not found: %w", err)
}
if err = cfg.ParseModules(); err != nil {
return fmt.Errorf("invalid module configuration: %w", err)
}
return builder.GenerateAndCompile(cfg)
},
}
if err := initFlags(cmd.Flags()); err != nil {
return nil, err
}
// version of this binary
cmd.AddCommand(versionCommand())
return cmd, nil
}
func initFlags(flags *flag.FlagSet) error {
flags.String(configFlag, "", "build configuration file")
// the distribution parameters, which we accept as CLI flags as well
flags.Bool(skipGenerateFlag, false, "Whether builder should skip generating go code (default false)")
flags.Bool(skipCompilationFlag, false, "Whether builder should only generate go code with no compile of the collector (default false)")
flags.Bool(skipGetModulesFlag, false, "Whether builder should skip updating go.mod and retrieve Go module list (default false)")
flags.Bool(skipStrictVersioningFlag, true, "Whether builder should skip strictly checking the calculated versions following dependency resolution")
flags.Bool(verboseFlag, false, "Whether builder should print verbose output (default false)")
flags.String(ldflagsFlag, "", `ldflags to include in the "go build" command`)
flags.String(gcflagsFlag, "", `gcflags to include in the "go build" command`)
flags.String(distributionOutputPathFlag, "", "Where to write the resulting files")
return flags.MarkDeprecated(distributionOutputPathFlag, "use config distribution::output_path")
}
func initConfig(flags *flag.FlagSet) (*builder.Config, error) {
cfg, err := builder.NewDefaultConfig()
if err != nil {
return nil, err
}
cfg.Logger.Info("OpenTelemetry Collector Builder", zap.String("version", version))
var provider koanf.Provider
cfgFile, _ := flags.GetString(configFlag)
if cfgFile != "" {
cfg.Logger.Info("Using config file", zap.String("path", cfgFile))
// load the config file
provider = file.Provider(cfgFile)
} else {
cfg.Logger.Info("Using default build configuration")
// or the default if the config isn't provided
provider = config.DefaultProvider()
}
k := koanf.New(".")
if err = k.Load(provider, yaml.Parser()); err != nil {
return nil, fmt.Errorf("failed to load configuration file: %w", err)
}
// handle env variables
if err = k.Load(env.Provider(".", env.Opt{}), nil); err != nil {
return nil, fmt.Errorf("failed to load environment variables: %w", err)
}
if err = k.UnmarshalWithConf("", cfg, koanf.UnmarshalConf{Tag: "mapstructure"}); err != nil {
return nil, fmt.Errorf("failed to unmarshal configuration: %w", err)
}
if err = applyFlags(flags, cfg); err != nil {
return nil, fmt.Errorf("failed to apply flags configuration: %w", err)
}
return cfg, nil
}
func applyFlags(flags *flag.FlagSet, cfg *builder.Config) error {
var errs, err error
cfg.SkipGenerate, err = flags.GetBool(skipGenerateFlag)
errs = multierr.Append(errs, err)
cfg.SkipCompilation, err = flags.GetBool(skipCompilationFlag)
errs = multierr.Append(errs, err)
cfg.SkipGetModules, err = flags.GetBool(skipGetModulesFlag)
errs = multierr.Append(errs, err)
cfg.SkipStrictVersioning, err = flags.GetBool(skipStrictVersioningFlag)
errs = multierr.Append(errs, err)
if flags.Changed(ldflagsFlag) {
cfg.LDSet = true
cfg.LDFlags, err = flags.GetString(ldflagsFlag)
errs = multierr.Append(errs, err)
}
if flags.Changed(gcflagsFlag) {
cfg.GCSet = true
cfg.GCFlags, err = flags.GetString(gcflagsFlag)
errs = multierr.Append(errs, err)
}
cfg.Verbose, err = flags.GetBool(verboseFlag)
errs = multierr.Append(errs, err)
if flags.Changed(distributionOutputPathFlag) {
cfg.Distribution.OutputPath, err = flags.GetString(distributionOutputPathFlag)
errs = multierr.Append(errs, err)
}
return errs
}
opentelemetry-collector-0.141.0/cmd/builder/internal/command_test.go 0000664 0000000 0000000 00000006501 15113313446 0025551 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"strings"
"testing"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/cmd/builder/internal/builder"
)
func TestCommand(t *testing.T) {
tests := []struct {
name string
want *cobra.Command
wantErr bool
}{
{
name: "command created",
want: &cobra.Command{
SilenceUsage: true, // Don't print usage on Run error.
SilenceErrors: true, // Don't print errors; main does it.
Use: "ocb",
Long: "OpenTelemetry Collector Builder",
Args: cobra.NoArgs,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Command()
if !tt.wantErr {
require.NoErrorf(t, err, "Command()")
assert.Equal(t, tt.want.Aliases, got.Aliases)
assert.Equal(t, tt.want.Annotations, got.Annotations)
assert.Equal(t, tt.want.ValidArgs, got.ValidArgs)
assert.Equal(t, tt.want.ArgAliases, got.ArgAliases)
assert.Equal(t, tt.want.Use, got.Use)
assert.Equal(t, tt.want.SilenceUsage, got.SilenceUsage)
assert.Equal(t, tt.want.SilenceErrors, got.SilenceErrors)
assert.True(t, strings.HasPrefix(got.Long, tt.want.Long))
assert.Empty(t, got.Short)
assert.NotEqual(t, tt.want.HasFlags(), got.Flags().HasFlags())
} else {
require.Error(t, err)
}
})
}
}
func TestApplyFlags(t *testing.T) {
tests := []struct {
name string
flags []string
want *builder.Config
}{
{
name: "Default flag values",
want: &builder.Config{
SkipStrictVersioning: true,
},
},
{
name: "All flag values",
flags: []string{"--skip-generate=true", "--skip-compilation=true", "--skip-get-modules=true", "--skip-strict-versioning=true", "--ldflags=test", "--gcflags=test", "--verbose=true"},
want: &builder.Config{
SkipGenerate: true,
SkipCompilation: true,
SkipGetModules: true,
SkipStrictVersioning: true,
LDFlags: "test",
GCFlags: "test",
Verbose: true,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
flags := flag.NewFlagSet("version=1.0.0", 1)
require.NoError(t, initFlags(flags))
require.NoError(t, flags.Parse(tt.flags))
cfg, err := builder.NewDefaultConfig()
require.NoError(t, err)
require.NoError(t, applyFlags(flags, cfg))
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.LDFlags, cfg.LDFlags)
assert.Equal(t, tt.want.Verbose, cfg.Verbose)
})
}
}
func TestInitConfig(t *testing.T) {
tests := []struct {
name string
flags *flag.FlagSet
wantErr bool
}{
{
name: "initConfig created correctly",
flags: flag.NewFlagSet("version=1.0.0", 1),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.NoError(t, initFlags(tt.flags))
_, err := initConfig(tt.flags)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}
opentelemetry-collector-0.141.0/cmd/builder/internal/config/ 0000775 0000000 0000000 00000000000 15113313446 0024010 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/internal/config/default.go 0000664 0000000 0000000 00000001043 15113313446 0025761 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package config // import "go.opentelemetry.io/collector/cmd/builder/internal/config"
import (
"embed"
"github.com/knadh/koanf/providers/fs"
"github.com/knadh/koanf/v2"
)
//go:embed *.yaml
var configs embed.FS
// DefaultProvider returns a koanf.Provider that provides the default build
// configuration file. This is the same configuration that otelcorecol is
// built with.
func DefaultProvider() koanf.Provider {
return fs.Provider(configs, "default.yaml")
}
opentelemetry-collector-0.141.0/cmd/builder/internal/config/default.yaml 0000664 0000000 0000000 00000003505 15113313446 0026323 0 ustar 00root root 0000000 0000000 # NOTE:
# This builder configuration is NOT used to build any official binary.
# To see the builder manifests used for official binaries,
# check https://github.com/open-telemetry/opentelemetry-collector-releases
#
# For the OpenTelemetry Collector Core official distribution sources, check
# https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol
dist:
module: go.opentelemetry.io/collector/cmd/otelcorecol
name: otelcorecol
description: Local OpenTelemetry Collector binary, testing only.
version: 0.141.0-dev
receivers:
- gomod: go.opentelemetry.io/collector/receiver/nopreceiver v0.141.0
- gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.141.0
exporters:
- gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.141.0
- gomod: go.opentelemetry.io/collector/exporter/nopexporter v0.141.0
- gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.141.0
- gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.141.0
extensions:
- gomod: go.opentelemetry.io/collector/extension/memorylimiterextension v0.141.0
- gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.141.0
processors:
- gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.141.0
- gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.141.0
connectors:
- gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.141.0
providers:
- gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v1.47.0
- gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v1.47.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpprovider v1.47.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpsprovider v1.47.0
- gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.47.0
opentelemetry-collector-0.141.0/cmd/builder/internal/package_test.go 0000664 0000000 0000000 00000000311 15113313446 0025517 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/builder/internal/version.go 0000664 0000000 0000000 00000001417 15113313446 0024562 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/builder/internal"
import (
"fmt"
"runtime/debug"
"github.com/spf13/cobra"
)
var version = ""
func init() {
// the second returned value is a boolean, which is true if the binaries are built with module support.
if version != "" {
return
}
info, ok := debug.ReadBuildInfo()
if ok {
version = info.Main.Version
}
}
func versionCommand() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Version of ocb",
Long: "Prints the version of the ocb binary",
RunE: func(cmd *cobra.Command, _ []string) error {
cmd.Println(fmt.Sprintf("%s version %s", cmd.Parent().Name(), version))
return nil
},
}
}
opentelemetry-collector-0.141.0/cmd/builder/main.go 0000664 0000000 0000000 00000000436 15113313446 0022205 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package main
import (
"github.com/spf13/cobra"
"go.opentelemetry.io/collector/cmd/builder/internal"
)
func main() {
cmd, err := internal.Command()
cobra.CheckErr(err)
cobra.CheckErr(cmd.Execute())
}
opentelemetry-collector-0.141.0/cmd/builder/metadata.yaml 0000664 0000000 0000000 00000000270 15113313446 0023372 0 ustar 00root root 0000000 0000000 type: builder
github_project: open-telemetry/opentelemetry-collector
status:
disable_codecov_badge: true
class: cmd
stability:
alpha: [metrics]
codeowners:
active: []
opentelemetry-collector-0.141.0/cmd/builder/test/ 0000775 0000000 0000000 00000000000 15113313446 0021706 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/builder/test/README.md 0000664 0000000 0000000 00000000605 15113313446 0023166 0 ustar 00root root 0000000 0000000 # Testing for the OpenTelemetry Collector Builder
This is a set of end-to-end tests for the builder. As such, it includes only positive tests, based on the manifest files in this directory. Each manifest is expected to be in a working state and should yield an OpenTelemetry Collector instance that is ready within a time interval. "Ready" is defined by calling its healthcheck endpoint.
opentelemetry-collector-0.141.0/cmd/builder/test/core.builder.yaml 0000664 0000000 0000000 00000000536 15113313446 0025153 0 ustar 00root root 0000000 0000000 dist:
name: core
module: go.opentelemetry.io/collector/builder/test/core
go: ${GOBIN}
extensions:
- gomod: go.opentelemetry.io/collector/extension/zpagesextension v0.141.0
receivers:
- gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.141.0
exporters:
- gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.141.0
opentelemetry-collector-0.141.0/cmd/builder/test/core.otel.yaml 0000664 0000000 0000000 00000000367 15113313446 0024472 0 ustar 00root root 0000000 0000000 extensions:
zpages:
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
debug:
service:
extensions: [zpages]
pipelines:
traces:
receivers:
- otlp
processors: []
exporters:
- debug
opentelemetry-collector-0.141.0/cmd/builder/test/test.sh 0000775 0000000 0000000 00000007706 15113313446 0023236 0 ustar 00root root 0000000 0000000 #!/bin/bash
#
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
WORKSPACE_DIR=$( cd -- "$( dirname "$(dirname "$(dirname -- "${SCRIPT_DIR}")")" )" &> /dev/null && pwd )
export WORKSPACE_DIR
GOBIN=$(go env GOBIN)
if [[ "$GO" == "" ]]; then
GOBIN=$(which go)
fi
export GOBIN
if [[ "$GOBIN" == "" ]]; then
echo "Could not determine which Go binary to use."
exit 1
fi
echo "Using ${GOBIN} to compile the distributions."
test_build_config() {
local test="$1"
local build_config="$2"
out="${base}/${test}"
if ! mkdir -p "${out}"; then
echo "โ FAIL ${test}. Failed to create test directory for the test. Aborting tests."
exit 2
fi
echo "Starting test '${test}' at $(date)" >> "${out}/test.log"
final_build_config=$(basename "${build_config}")
go tool -modfile "${WORKSPACE_DIR}/internal/tools/go.mod" envsubst \
-o "${out}/${final_build_config}" -i <(cat "$build_config" "$replaces")
if ! go run . --config "${out}/${final_build_config}" --output-path "${out}" > "${out}/builder.log" 2>&1; then
echo "โ FAIL ${test}. Failed to compile the test ${test}. Build logs:"
cat "${out}/builder.log"
failed=true
return
fi
if [ ! -f "${out}/${test}" ]; then
echo "โ FAIL ${test}. Binary not found for ${test} at '${out}/${test}'. Build logs:"
cat "${out}/builder.log"
failed=true
return
fi
# start the distribution
if [ ! -f "./test/${test}.otel.yaml" ]; then
echo "โ FAIL ${test}. Config file for ${test} not found at './test/${test}.otel.yaml'"
failed=true
return
fi
"${out}/${test}" --config "./test/${test}.otel.yaml" > "${out}/otelcol.log" 2>&1 &
pid=$!
retries=0
while true
do
if ! kill -0 "${pid}" >/dev/null 2>&1; then
echo "โ FAIL ${test}. The OpenTelemetry Collector isn't running. Startup log:"
cat "${out}/otelcol.log"
failed=true
break
fi
# Since the content of the servicez page depend on which extensions are
# built into the collector, we depend only on the zpages extension
# being present and serving something.
if curl --fail --silent --output /dev/null http://localhost:55679/debug/servicez; then
echo "โ
PASS ${test}"
kill "${pid}"
ret=$?
if [ $ret -ne 0 ]; then
echo "Failed to stop the running instance for test ${test}. Return code: ${ret} . Skipping tests."
exit 4
fi
break
fi
echo "Server still unavailable for test '${test}'" >> "${out}/test.log"
((retries++))
if [ "$retries" -gt "$max_retries" ]; then
echo "โ FAIL ${test}. Server wasn't up after about 5s."
failed=true
kill "${pid}"
ret=$?
if [ $ret -ne 0 ]; then
echo "Failed to stop the running instance for test ${test}. Return code: ${ret} . Skipping tests."
exit 8
fi
break
fi
sleep 0.1s
done
echo "Stopping server for '${test}' (pid: ${pid})" >> "${out}/test.log"
}
# each attempt pauses for 100ms before retrying
max_retries=50
tests="core"
base=$(mktemp -d)
echo "Running the tests in ${base}"
replaces="$base/replaces"
# Get path of all core modules, in sorted order
core_mods=$(cd ../.. && find . -type f -name "go.mod" -exec dirname {} \; | sort)
echo "replaces:" >> "$replaces"
for mod_path in $core_mods; do
mod=${mod_path#"."} # remove initial dot
echo " - go.opentelemetry.io/collector$mod => \${WORKSPACE_DIR}$mod" >> "$replaces"
done
echo "Wrote replace statements to $replaces"
failed=false
for test in $tests
do
test_build_config "$test" "./test/${test}.builder.yaml"
done
if [[ "$failed" == "true" ]]; then
exit 1
fi
opentelemetry-collector-0.141.0/cmd/githubgen/ 0000775 0000000 0000000 00000000000 15113313446 0021255 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/githubgen/allowlist.txt 0000664 0000000 0000000 00000000000 15113313446 0024016 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/ 0000775 0000000 0000000 00000000000 15113313446 0021061 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/Makefile 0000664 0000000 0000000 00000000036 15113313446 0022520 0 ustar 00root root 0000000 0000000 include ../../Makefile.Common
opentelemetry-collector-0.141.0/cmd/mdatagen/README.md 0000664 0000000 0000000 00000012420 15113313446 0022337 0 ustar 00root root 0000000 0000000 # Metadata Generator
| Status | |
| ------------- |-----------|
| Stability | [alpha]: metrics |
| Issues | [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Acmd%2Fmdatagen) [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aclosed+is%3Aissue+label%3Acmd%2Fmdatagen) |
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@dmitryax](https://www.github.com/dmitryax) |
[alpha]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#alpha
Every component's documentation should include a brief description of the component and guidance on how to use it.
There is also some information about the component (or metadata) that should be included to help end-users understand the current state of the component and whether it is right for their use case.
Examples of this metadata about a component are:
* its stability level
* the distributions containing it
* the types of pipelines it supports
* metrics emitted in the case of a scraping receiver, a scraper, or a connector
The metadata generator defines a schema for specifying this information to ensure it is complete and well-formed.
The metadata generator is then able to ingest the metadata, validate it against the schema and produce documentation in a standardized format.
An example of how this generated documentation looks can be found in [documentation.md](https://github.com/open-telemetry/opentelemetry-collector/blob/main/cmd/mdatagen/internal/samplereceiver/documentation.md).
## Using the Metadata Generator
In order for a component to benefit from the metadata generator (`mdatagen`) these requirements need to be met:
1. A yaml file containing the metadata that needs to be included in the component
2. The component should declare a `go:generate mdatagen` directive which tells `mdatagen` what to generate
As an example, here is a minimal `metadata.yaml` for the [OTLP receiver](https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver):
```yaml
type: otlp
status:
class: receiver
stability:
beta: [logs]
stable: [metrics, traces]
```
Detailed information about the schema of `metadata.yaml` can be found in [metadata-schema.yaml](./metadata-schema.yaml).
The `go:generate mdatagen` directive is usually defined in a `doc.go` file in the same package as the component, for example:
```go
//go:generate mdatagen metadata.yaml
package main
```
Below are some more examples that can be used for reference:
* The ElasticSearch receiver has an extensive [metadata.yaml](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/elasticsearchreceiver/metadata.yaml)
* The host metrics receiver has internal subcomponents, each with their own `metadata.yaml` and `doc.go`. See [cpuscraper](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/hostmetricsreceiver/internal/scraper/cpuscraper) for example.
You can run `cd cmd/mdatagen && $(GOCMD) install .` to install the `mdatagen` tool in `GOBIN` and then run `mdatagen metadata.yaml` to generate documentation for a specific component or you can run `make generate` to generate documentation for all components.
### Generate multiple metadata packages
By default, `mdatagen` will generate a package called `metadata` in the `internal` directory. If you want to generate a package with a different name, you can use the `generated_package_name` configuration field to provide an alternate name.
```yaml
type: otlp
generated_package_name: customname
status:
class: receiver
stability:
beta: [logs]
stable: [metrics, traces]
```
The most common scenario for this would be making major changes to a receiver's metadata without breaking what exists. In this scenario, `mdatagen` could produce separate packages for different metadata specs in the same receiver:
```go
//go:generate mdatagen metadata.yaml
//go:generate mdatagen custom.yaml
package main
```
With two different packages generated, the behaviour for which metadata is used can be easily controlled via featuregate or a similar mechanism.
## Contributing to the Metadata Generator
The code for generating the documentation can be found in [loader.go](./internal/loader.go) and the templates for rendering the documentation can be found in [templates](./internal/templates).
When making updates to the metadata generator or introducing support for new functionality:
1. Ensure the [metadata-schema.yaml](./metadata-schema.yaml) and [metadata.yaml](./metadata.yaml) files reflect the changes.
2. Run `make mdatagen-test`.
3. Make sure all tests are passing including [generated tests](./internal/samplereceiver/internal/metadata/generated_metrics_test.go).
4. Run `make generate`.
opentelemetry-collector-0.141.0/cmd/mdatagen/generated_package_test.go 0000664 0000000 0000000 00000000243 15113313446 0026057 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package main
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/go.mod 0000664 0000000 0000000 00000021204 15113313446 0022166 0 ustar 00root root 0000000 0000000 module go.opentelemetry.io/collector/cmd/mdatagen
go 1.24.0
require (
github.com/google/go-cmp v0.7.0
github.com/spf13/cobra v1.10.1
github.com/stretchr/testify v1.11.1
go.opentelemetry.io/collector/component v1.47.0
go.opentelemetry.io/collector/component/componenttest v0.141.0
go.opentelemetry.io/collector/confmap v1.47.0
go.opentelemetry.io/collector/confmap/provider/fileprovider v1.47.0
go.opentelemetry.io/collector/connector v0.141.0
go.opentelemetry.io/collector/connector/connectortest v0.141.0
go.opentelemetry.io/collector/consumer v1.47.0
go.opentelemetry.io/collector/consumer/consumertest v0.141.0
go.opentelemetry.io/collector/filter v0.141.0
go.opentelemetry.io/collector/pdata v1.47.0
go.opentelemetry.io/collector/pdata/xpdata v0.141.0
go.opentelemetry.io/collector/pipeline v1.47.0
go.opentelemetry.io/collector/processor v1.47.0
go.opentelemetry.io/collector/processor/processortest v0.141.0
go.opentelemetry.io/collector/receiver v1.47.0
go.opentelemetry.io/collector/receiver/receivertest v0.141.0
go.opentelemetry.io/collector/scraper v0.141.0
go.opentelemetry.io/collector/scraper/scrapertest v0.141.0
go.opentelemetry.io/collector/service/hostcapabilities v0.141.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/metric v1.38.0
go.opentelemetry.io/otel/sdk/metric v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
go.uber.org/goleak v1.3.0
go.uber.org/zap v1.27.1
golang.org/x/text v0.31.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/go-version v1.7.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.2 // indirect
github.com/knadh/koanf/providers/confmap v1.0.0 // indirect
github.com/knadh/koanf/v2 v2.3.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.9 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/collector/component/componentstatus v0.141.0 // indirect
go.opentelemetry.io/collector/connector/xconnector v0.141.0 // indirect
go.opentelemetry.io/collector/consumer/consumererror v0.141.0 // indirect
go.opentelemetry.io/collector/consumer/xconsumer v0.141.0 // indirect
go.opentelemetry.io/collector/featuregate v1.47.0 // indirect
go.opentelemetry.io/collector/internal/fanoutconsumer v0.141.0 // indirect
go.opentelemetry.io/collector/pdata/pprofile v0.141.0 // indirect
go.opentelemetry.io/collector/pdata/testdata v0.141.0 // indirect
go.opentelemetry.io/collector/pipeline/xpipeline v0.141.0 // indirect
go.opentelemetry.io/collector/processor/xprocessor v0.141.0 // indirect
go.opentelemetry.io/collector/receiver/xreceiver v0.141.0 // indirect
go.opentelemetry.io/collector/service v0.141.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/sys v0.38.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/grpc v1.77.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
)
replace go.opentelemetry.io/collector/component => ../../component
replace go.opentelemetry.io/collector/component/componenttest => ../../component/componenttest
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/consumer => ../../consumer
replace go.opentelemetry.io/collector/receiver/receivertest => ../../receiver/receivertest
retract (
v0.76.2
v0.76.1
v0.65.0
)
replace go.opentelemetry.io/collector/pdata/pprofile => ../../pdata/pprofile
replace go.opentelemetry.io/collector/consumer/xconsumer => ../../consumer/xconsumer
replace go.opentelemetry.io/collector/consumer/consumertest => ../../consumer/consumertest
replace go.opentelemetry.io/collector/receiver/xreceiver => ../../receiver/xreceiver
replace go.opentelemetry.io/collector/pipeline => ../../pipeline
replace go.opentelemetry.io/collector/processor/xprocessor => ../../processor/xprocessor
replace go.opentelemetry.io/collector/processor/processortest => ../../processor/processortest
replace go.opentelemetry.io/collector/component/componentstatus => ../../component/componentstatus
replace go.opentelemetry.io/collector/processor => ../../processor
replace go.opentelemetry.io/collector/consumer/consumererror => ../../consumer/consumererror
replace go.opentelemetry.io/collector/scraper => ../../scraper
replace go.opentelemetry.io/collector/scraper/scrapertest => ../../scraper/scrapertest
replace go.opentelemetry.io/collector/featuregate => ../../featuregate
replace go.opentelemetry.io/collector/connector => ../../connector
replace go.opentelemetry.io/collector/connector/connectortest => ../../connector/connectortest
replace go.opentelemetry.io/collector/pipeline/xpipeline => ../../pipeline/xpipeline
replace go.opentelemetry.io/collector/internal/fanoutconsumer => ../../internal/fanoutconsumer
replace go.opentelemetry.io/collector/connector/xconnector => ../../connector/xconnector
replace go.opentelemetry.io/collector/internal/telemetry => ../../internal/telemetry
replace go.opentelemetry.io/collector/extension/extensiontest => ../../extension/extensiontest
replace go.opentelemetry.io/collector/exporter => ../../exporter
replace go.opentelemetry.io/collector/confmap/xconfmap => ../../confmap/xconfmap
replace go.opentelemetry.io/collector/extension/extensionmiddleware => ../../extension/extensionmiddleware
replace go.opentelemetry.io/collector/config/configmiddleware => ../../config/configmiddleware
replace go.opentelemetry.io/collector/exporter/exportertest => ../../exporter/exportertest
replace go.opentelemetry.io/collector/client => ../../client
replace go.opentelemetry.io/collector/extension => ../../extension
replace go.opentelemetry.io/collector/config/configauth => ../../config/configauth
replace go.opentelemetry.io/collector/otelcol => ../../otelcol
replace go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest => ../../extension/extensionmiddleware/extensionmiddlewaretest
replace go.opentelemetry.io/collector/extension/xextension => ../../extension/xextension
replace go.opentelemetry.io/collector/extension/zpagesextension => ../../extension/zpagesextension
replace go.opentelemetry.io/collector/config/configretry => ../../config/configretry
replace go.opentelemetry.io/collector/config/configoptional => ../../config/configoptional
replace go.opentelemetry.io/collector/config/configopaque => ../../config/configopaque
replace go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest => ../../extension/extensionauth/extensionauthtest
replace go.opentelemetry.io/collector/service => ../../service
replace go.opentelemetry.io/collector/extension/extensionauth => ../../extension/extensionauth
replace go.opentelemetry.io/collector/service/hostcapabilities => ../../service/hostcapabilities
replace go.opentelemetry.io/collector/config/configtls => ../../config/configtls
replace go.opentelemetry.io/collector/config/configcompression => ../../config/configcompression
replace go.opentelemetry.io/collector/exporter/xexporter => ../../exporter/xexporter
replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry
replace go.opentelemetry.io/collector/config/confighttp => ../../config/confighttp
replace go.opentelemetry.io/collector/extension/extensioncapabilities => ../../extension/extensioncapabilities
replace go.opentelemetry.io/collector/pdata/xpdata => ../../pdata/xpdata
replace go.opentelemetry.io/collector/exporter/exporterhelper => ../../exporter/exporterhelper
replace go.opentelemetry.io/collector/service/telemetry/telemetrytest => ../../service/telemetry/telemetrytest
replace go.opentelemetry.io/collector/internal/testutil => ../../internal/testutil
opentelemetry-collector-0.141.0/cmd/mdatagen/go.sum 0000664 0000000 0000000 00000021773 15113313446 0022226 0 ustar 00root root 0000000 0000000 github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
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.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/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.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
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/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/providers/confmap v1.0.0 h1:mHKLJTE7iXEys6deO5p6olAiZdG5zwp8Aebir+/EaRE=
github.com/knadh/koanf/providers/confmap v1.0.0/go.mod h1:txHYHiI2hAtF0/0sCmcuol4IDcuQbKTybiB1nOcUo1A=
github.com/knadh/koanf/v2 v2.3.0 h1:Qg076dDRFHvqnKG97ZEsi9TAg2/nFTa9hCdcSa1lvlM=
github.com/knadh/koanf/v2 v2.3.0/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
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/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
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.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.opentelemetry.io/proto/slim/otlp v1.9.0 h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE=
go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI=
go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8=
go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4=
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.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
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=
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/ 0000775 0000000 0000000 00000000000 15113313446 0022675 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/command.go 0000664 0000000 0000000 00000036420 15113313446 0024647 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"bytes"
"errors"
"fmt"
"go/format"
"io/fs"
"os"
"path/filepath"
"regexp"
"runtime/debug"
"slices"
"sort"
"strings"
"text/template"
"github.com/spf13/cobra"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"gopkg.in/yaml.v3"
)
const (
statusStart = ""
statusEnd = ""
)
var nonComponents = []string{
"cmd",
"converter",
"pkg",
"provider",
}
func getVersion() (string, error) {
// the second returned value is a boolean, which is true if the binaries are built with module support.
info, ok := debug.ReadBuildInfo()
if !ok {
return "", errors.New("could not read build info")
}
return info.Main.Version, nil
}
// NewCommand constructs a new cobra.Command using the given Settings.
// Any URIs specified in CollectorSettings.ConfigProviderSettings.ResolverSettings.URIs
// are considered defaults and will be overwritten by config flags passed as
// command-line arguments to the executable.
// At least one Provider must be set.
func NewCommand() (*cobra.Command, error) {
ver, err := getVersion()
if err != nil {
return nil, err
}
rootCmd := &cobra.Command{
Use: "mdatagen",
Version: ver,
SilenceUsage: true,
RunE: func(_ *cobra.Command, args []string) error {
return run(args[0])
},
}
return rootCmd, nil
}
func run(ymlPath string) error {
if ymlPath == "" {
return errors.New("argument must be metadata.yaml file")
}
ymlPath, err := filepath.Abs(ymlPath)
if err != nil {
return fmt.Errorf("failed to get absolute path for %v: %w", ymlPath, err)
}
ymlDir := filepath.Dir(ymlPath)
packageName := filepath.Base(ymlDir)
raw, readErr := os.ReadFile(ymlPath) //nolint:gosec // G304: abs path is cleaned/validated above; safe to read
if readErr != nil {
return fmt.Errorf("failed reading %v: %w", ymlPath, readErr)
}
if err = validateYAMLKeyOrder(raw); err != nil {
return fmt.Errorf("metadata.yaml ordering check failed: %w", err)
}
md, err := LoadMetadata(ymlPath)
if err != nil {
return fmt.Errorf("failed loading %v: %w", ymlPath, err)
}
tmplDir := "templates"
codeDir := filepath.Join(ymlDir, "internal", md.GeneratedPackageName)
toGenerate := map[string]string{}
if md.Status != nil {
if !slices.Contains(nonComponents, md.Status.Class) {
toGenerate[filepath.Join(tmplDir, "status.go.tmpl")] = filepath.Join(codeDir, "generated_status.go")
err = generateFile(filepath.Join(tmplDir, "component_test.go.tmpl"),
filepath.Join(ymlDir, "generated_component_test.go"), md, packageName)
if err != nil {
return err
}
} else {
if _, err = os.Stat(filepath.Join(codeDir, "generated_status.go")); err == nil {
err = os.Remove(filepath.Join(codeDir, "generated_status.go"))
if err != nil {
return err
}
}
if _, err = os.Stat(filepath.Join(ymlDir, "generated_component_test.go")); err == nil {
err = os.Remove(filepath.Join(ymlDir, "generated_component_test.go"))
if err != nil {
return err
}
}
}
err = generateFile(filepath.Join(tmplDir, "package_test.go.tmpl"),
filepath.Join(ymlDir, "generated_package_test.go"), md, packageName)
if err != nil {
return err
}
if _, err = os.Stat(filepath.Join(ymlDir, "README.md")); err == nil {
err = inlineReplace(
filepath.Join(tmplDir, "readme.md.tmpl"),
filepath.Join(ymlDir, "README.md"),
md, statusStart, statusEnd, md.GeneratedPackageName)
if err != nil {
return err
}
}
}
if len(md.Telemetry.Metrics) != 0 { // if there are telemetry metrics, generate telemetry specific files
testDir := filepath.Join(ymlDir, "internal", md.GeneratedPackageName+"test")
if err = os.MkdirAll(testDir, 0o700); err != nil {
return fmt.Errorf("unable to create output test directory %q: %w", codeDir, err)
}
toGenerate[filepath.Join(tmplDir, "telemetry.go.tmpl")] = filepath.Join(codeDir, "generated_telemetry.go")
toGenerate[filepath.Join(tmplDir, "telemetry_test.go.tmpl")] = filepath.Join(codeDir, "generated_telemetry_test.go")
toGenerate[filepath.Join(tmplDir, "telemetrytest.go.tmpl")] = filepath.Join(testDir, "generated_telemetrytest.go")
toGenerate[filepath.Join(tmplDir, "telemetrytest_test.go.tmpl")] = filepath.Join(testDir, "generated_telemetrytest_test.go")
} else {
if _, err = os.Stat(filepath.Join(ymlDir, "generated_telemetry.go")); err == nil {
err = os.Remove(filepath.Join(ymlDir, "generated_telemetry.go"))
if err != nil {
return err
}
}
if _, err = os.Stat(filepath.Join(ymlDir, "generated_telemetry_test.go")); err == nil {
err = os.Remove(filepath.Join(ymlDir, "generated_telemetry_test.go"))
if err != nil {
return err
}
}
if _, err = os.Stat(filepath.Join(ymlDir, "generated_telemetrytest.go")); err == nil {
err = os.Remove(filepath.Join(ymlDir, "generated_telemetrytest.go"))
if err != nil {
return err
}
}
if _, err = os.Stat(filepath.Join(ymlDir, "generated_telemetrytest_test.go")); err == nil {
err = os.Remove(filepath.Join(ymlDir, "generated_telemetrytest_test.go"))
if err != nil {
return err
}
}
}
if len(md.Metrics) != 0 || len(md.Telemetry.Metrics) != 0 || len(md.ResourceAttributes) != 0 || len(md.Events) != 0 { // if there's metrics or internal metrics or events, generate documentation for them
toGenerate[filepath.Join(tmplDir, "documentation.md.tmpl")] = filepath.Join(ymlDir, "documentation.md")
}
if len(md.Metrics) > 0 || len(md.Events) > 0 || len(md.ResourceAttributes) > 0 {
testdataDir := filepath.Join(codeDir, "testdata")
if err = os.MkdirAll(filepath.Join(codeDir, "testdata"), 0o700); err != nil {
return fmt.Errorf("unable to create output directory %q: %w", testdataDir, err)
}
toGenerate[filepath.Join(tmplDir, "testdata", "config.yaml.tmpl")] = filepath.Join(testdataDir, "config.yaml")
toGenerate[filepath.Join(tmplDir, "config.go.tmpl")] = filepath.Join(codeDir, "generated_config.go")
toGenerate[filepath.Join(tmplDir, "config_test.go.tmpl")] = filepath.Join(codeDir, "generated_config_test.go")
}
if len(md.ResourceAttributes) > 0 { // only generate resource files if resource attributes are configured
toGenerate[filepath.Join(tmplDir, "resource.go.tmpl")] = filepath.Join(codeDir, "generated_resource.go")
toGenerate[filepath.Join(tmplDir, "resource_test.go.tmpl")] = filepath.Join(codeDir, "generated_resource_test.go")
}
if len(md.Metrics) > 0 { // only generate metrics if metrics are present
toGenerate[filepath.Join(tmplDir, "metrics.go.tmpl")] = filepath.Join(codeDir, "generated_metrics.go")
toGenerate[filepath.Join(tmplDir, "metrics_test.go.tmpl")] = filepath.Join(codeDir, "generated_metrics_test.go")
}
if md.supportsSignal("logs") &&
(md.Status.Class == "receiver" || md.Status.Class == "scraper") {
toGenerate[filepath.Join(tmplDir, "logs.go.tmpl")] = filepath.Join(codeDir, "generated_logs.go")
toGenerate[filepath.Join(tmplDir, "logs_test.go.tmpl")] = filepath.Join(codeDir, "generated_logs_test.go")
}
// If at least one file to generate, will need the codeDir
if len(toGenerate) > 0 {
if err = os.MkdirAll(codeDir, 0o700); err != nil {
return fmt.Errorf("unable to create output directory %q: %w", codeDir, err)
}
}
for tmpl, dst := range toGenerate {
if err := generateFile(tmpl, dst, md, md.GeneratedPackageName); err != nil {
return err
}
}
return nil
}
func templatize(tmplFile string, md Metadata) *template.Template {
return template.Must(
template.
New(filepath.Base(tmplFile)).
Option("missingkey=error").
Funcs(map[string]any{
"publicVar": func(s string) (string, error) {
return FormatIdentifier(s, true)
},
"attributeInfo": func(an AttributeName) Attribute {
return md.Attributes[an]
},
"getEventConditionalAttributes": func(attrs map[AttributeName]Attribute) []AttributeName {
seen := make(map[AttributeName]bool)
used := make([]AttributeName, 0)
for _, event := range md.Events {
for _, attribute := range event.Attributes {
v, exists := attrs[attribute]
if exists && v.IsConditional() && !seen[attribute] {
used = append(used, attribute)
seen[attribute] = true
}
}
}
sort.Slice(used, func(i, j int) bool { return string(used[i]) < string(used[j]) })
return used
},
"getMetricConditionalAttributes": func(attrs map[AttributeName]Attribute) []AttributeName {
seen := make(map[AttributeName]bool)
used := make([]AttributeName, 0)
for _, event := range md.Metrics {
for _, attribute := range event.Attributes {
v, exists := attrs[attribute]
if exists && v.IsConditional() && !seen[attribute] {
used = append(used, attribute)
seen[attribute] = true
}
}
}
sort.Slice(used, func(i, j int) bool { return string(used[i]) < string(used[j]) })
return used
},
"metricInfo": func(mn MetricName) Metric {
return md.Metrics[mn]
},
"eventInfo": func(en EventName) Event {
return md.Events[en]
},
"telemetryInfo": func(mn MetricName) Metric {
return md.Telemetry.Metrics[mn]
},
"parseImportsRequired": func(metrics map[MetricName]Metric) bool {
for _, m := range metrics {
if m.Data().HasMetricInputType() {
return true
}
}
return false
},
"stringsJoin": strings.Join,
"stringsSplit": strings.Split,
"userLinks": func(elems []string) []string {
result := make([]string, len(elems))
for i, elem := range elems {
if elem == "open-telemetry/collector-approvers" {
result[i] = "[@open-telemetry/collector-approvers](https://github.com/orgs/open-telemetry/teams/collector-approvers)"
} else {
result[i] = fmt.Sprintf("[@%s](https://www.github.com/%s)", elem, elem)
}
}
return result
},
"casesTitle": cases.Title(language.English).String,
"toLowerCase": strings.ToLower,
"toCamelCase": func(s string) string {
caser := cases.Title(language.English).String
parts := strings.Split(s, "_")
var result strings.Builder
for _, part := range parts {
fmt.Fprintf(&result, "%s", caser(part))
}
return result.String()
},
"inc": func(i int) int { return i + 1 },
"distroURL": distroURL,
"isExporter": func() bool {
return md.Status.Class == "exporter"
},
"isProcessor": func() bool {
return md.Status.Class == "processor"
},
"isReceiver": func() bool {
return md.Status.Class == "receiver"
},
"isExtension": func() bool {
return md.Status.Class == "extension"
},
"isConnector": func() bool {
return md.Status.Class == "connector"
},
"isScraper": func() bool {
return md.Status.Class == "scraper"
},
"isCommand": func() bool {
return md.Status.Class == "cmd"
},
"supportsLogs": func() bool { return md.supportsSignal("logs") },
"supportsMetrics": func() bool { return md.supportsSignal("metrics") },
"supportsTraces": func() bool { return md.supportsSignal("traces") },
"supportsLogsToLogs": func() bool { return md.supportsSignal("logs_to_logs") },
"supportsLogsToMetrics": func() bool { return md.supportsSignal("logs_to_metrics") },
"supportsLogsToTraces": func() bool { return md.supportsSignal("logs_to_traces") },
"supportsMetricsToLogs": func() bool { return md.supportsSignal("metrics_to_logs") },
"supportsMetricsToMetrics": func() bool { return md.supportsSignal("metrics_to_metrics") },
"supportsMetricsToTraces": func() bool { return md.supportsSignal("metrics_to_traces") },
"supportsTracesToLogs": func() bool { return md.supportsSignal("traces_to_logs") },
"supportsTracesToMetrics": func() bool { return md.supportsSignal("traces_to_metrics") },
"supportsTracesToTraces": func() bool { return md.supportsSignal("traces_to_traces") },
"expectConsumerError": func() bool {
return md.Tests.ExpectConsumerError
},
// ParseFS delegates the parsing of the files to `Glob`
// which uses the `\` as a special character.
// Meaning on windows based machines, the `\` needs to be replaced
// with a `/` for it to find the file.
}).ParseFS(TemplateFS, "templates/helper.tmpl", strings.ReplaceAll(tmplFile, "\\", "/")))
}
func executeTemplate(tmplFile string, md Metadata, goPackage string) ([]byte, error) {
tmpl := templatize(tmplFile, md)
buf := bytes.Buffer{}
if err := tmpl.Execute(&buf, TemplateContext{Metadata: md, Package: goPackage}); err != nil {
return []byte{}, fmt.Errorf("failed executing template: %w", err)
}
return buf.Bytes(), nil
}
func inlineReplace(tmplFile, outputFile string, md Metadata, start, end, goPackage string) error {
var readmeContents []byte
var err error
if readmeContents, err = os.ReadFile(outputFile); err != nil { //nolint:gosec
return err
}
re := regexp.MustCompile(fmt.Sprintf("%s[\\s\\S]*%s", start, end))
if !re.Match(readmeContents) {
return nil
}
if md.GithubProject == "" {
md.GithubProject = "open-telemetry/opentelemetry-collector-contrib"
}
buf, err := executeTemplate(tmplFile, md, goPackage)
if err != nil {
return err
}
s := re.ReplaceAllString(string(readmeContents), string(buf))
if err := os.WriteFile(outputFile, []byte(s), 0o600); err != nil {
return fmt.Errorf("failed writing %q: %w", outputFile, err)
}
return nil
}
func generateFile(tmplFile, outputFile string, md Metadata, goPackage string) error {
if err := os.Remove(outputFile); err != nil && !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("unable to remove generated file %q: %w", outputFile, err)
}
result, err := executeTemplate(tmplFile, md, goPackage)
if err != nil {
return err
}
var formatErr error
if strings.HasSuffix(outputFile, ".go") {
if formatted, err := format.Source(result); err == nil {
result = formatted
} else {
formatErr = fmt.Errorf("failed formatting %s:%w", outputFile, err)
}
}
if err := os.WriteFile(outputFile, result, 0o600); err != nil {
return fmt.Errorf("failed writing %q: %w", outputFile, err)
}
return formatErr
}
func validateMappingKeysSorted(root *yaml.Node, path ...string) error {
// unwrap doc
n := root
if n.Kind == yaml.DocumentNode && len(n.Content) > 0 {
n = n.Content[0]
}
// follow path
for _, seg := range path {
if n.Kind != yaml.MappingNode {
return nil
}
var next *yaml.Node
for i := 0; i < len(n.Content); i += 2 {
if n.Content[i].Value == seg {
next = n.Content[i+1]
break
}
}
if next == nil {
return nil
}
n = next
}
if n.Kind != yaml.MappingNode {
return nil
}
// collect keys
keys := make([]string, 0, len(n.Content)/2)
for i := 0; i < len(n.Content); i += 2 {
keys = append(keys, n.Content[i].Value)
}
if !slices.IsSorted(keys) {
return fmt.Errorf("%v keys are not sorted: %v", path, keys)
}
return nil
}
// ValidateYAMLKeyOrder checks the sections we care about.
func validateYAMLKeyOrder(raw []byte) error {
var doc yaml.Node
if err := yaml.Unmarshal(raw, &doc); err != nil {
return err
}
for _, p := range [][]string{
{"resource_attributes"},
{"entities"},
{"attributes"},
{"metrics"},
{"events"},
{"telemetry", "metrics"},
} {
if err := validateMappingKeysSorted(&doc, p...); err != nil {
return err
}
}
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/command_test.go 0000664 0000000 0000000 00000057060 15113313446 0025711 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"os"
"path/filepath"
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component"
)
func TestNewCommand(t *testing.T) {
cmd, err := NewCommand()
require.NoError(t, err)
assert.NotNil(t, cmd)
assert.IsType(t, &cobra.Command{}, cmd)
assert.Equal(t, "mdatagen", cmd.Use)
assert.True(t, cmd.SilenceUsage)
}
func TestRunContents(t *testing.T) {
tests := []struct {
yml string
wantMetricsGenerated bool
// TODO: we should add one more flag for logs builder
wantEventsGenerated bool
wantMetricsContext bool
wantLogsGenerated bool
wantConfigGenerated bool
wantTelemetryGenerated bool
wantResourceAttributesGenerated bool
wantReadmeGenerated bool
wantStatusGenerated bool
wantComponentTestGenerated bool
wantGoleakIgnore bool
wantGoleakSkip bool
wantGoleakSetup bool
wantGoleakTeardown bool
wantErr bool
wantOrderErr bool
wantAttributes []string
}{
{
yml: "invalid.yaml",
wantErr: true,
},
{
yml: "unsorted_rattr.yaml",
wantOrderErr: true,
},
{
yml: "basic_connector.yaml",
wantErr: false,
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "basic_receiver.yaml",
wantErr: false,
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
wantLogsGenerated: true,
},
{
yml: "basic_pkg.yaml",
wantErr: false,
wantStatusGenerated: false,
wantReadmeGenerated: true,
},
{
yml: "metrics_and_type.yaml",
wantMetricsGenerated: true,
wantConfigGenerated: true,
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "resource_attributes_only.yaml",
wantConfigGenerated: true,
wantStatusGenerated: true,
wantResourceAttributesGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
wantLogsGenerated: true,
},
{
yml: "status_only.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_tests_receiver.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
wantLogsGenerated: true,
},
{
yml: "with_tests_exporter.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_tests_processor.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_tests_extension.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_tests_connector.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_goleak_ignores.yaml",
wantStatusGenerated: true,
wantGoleakIgnore: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_goleak_skip.yaml",
wantStatusGenerated: true,
wantGoleakSkip: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_goleak_setup.yaml",
wantStatusGenerated: true,
wantGoleakSetup: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_goleak_teardown.yaml",
wantStatusGenerated: true,
wantGoleakTeardown: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "with_telemetry.yaml",
wantStatusGenerated: true,
wantTelemetryGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
wantAttributes: []string{"name"},
wantLogsGenerated: true,
},
{
yml: "invalid_telemetry_missing_value_type_for_histogram.yaml",
wantErr: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "async_metric.yaml",
wantMetricsGenerated: true,
wantConfigGenerated: true,
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "custom_generated_package_name.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
wantLogsGenerated: true,
},
{
yml: "with_conditional_attribute.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantMetricsGenerated: true,
wantLogsGenerated: true,
wantConfigGenerated: true,
wantComponentTestGenerated: true,
},
{
yml: "events/basic_event.yaml",
wantStatusGenerated: true,
wantReadmeGenerated: true,
wantComponentTestGenerated: true,
wantConfigGenerated: true,
wantEventsGenerated: true,
wantLogsGenerated: true,
},
}
for _, tt := range tests {
t.Run(tt.yml, func(t *testing.T) {
tmpdir := filepath.Join(t.TempDir(), "shortname")
err := os.MkdirAll(tmpdir, 0o750)
require.NoError(t, err)
ymlContent, err := os.ReadFile(filepath.Join("testdata", tt.yml))
require.NoError(t, err)
metadataFile := filepath.Join(tmpdir, "metadata.yaml")
require.NoError(t, os.WriteFile(metadataFile, ymlContent, 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, "empty.go"), []byte("package shortname"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module shortname"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, "README.md"), []byte(`
foo
`), 0o600))
md, err := LoadMetadata(metadataFile)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
generatedPackageDir := filepath.Join("internal", md.GeneratedPackageName)
require.NoError(t, os.MkdirAll(filepath.Join(tmpdir, generatedPackageDir), 0o700))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, generatedPackageDir, "generated_status.go"), []byte("status"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, generatedPackageDir, "generated_telemetry_test.go"), []byte("test"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tmpdir, generatedPackageDir, "generated_component_test.go"), []byte("test"), 0o600))
err = run(metadataFile)
if tt.wantOrderErr {
require.Error(t, err)
require.Contains(t, err.Error(), "metadata.yaml ordering check failed")
return
}
require.NoError(t, err)
var contents []byte
if tt.wantMetricsGenerated {
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_metrics.go"))
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_metrics_test.go"))
require.FileExists(t, filepath.Join(tmpdir, "documentation.md"))
if len(tt.wantAttributes) > 0 {
contents, err = os.ReadFile(filepath.Join(tmpdir, "documentation.md")) //nolint:gosec
require.NoError(t, err)
for _, attr := range tt.wantAttributes {
require.Contains(t, string(contents), attr)
}
}
contents, err = os.ReadFile(filepath.Join(tmpdir, generatedPackageDir, "generated_metrics.go")) //nolint:gosec
require.NoError(t, err)
if tt.wantMetricsContext {
require.Contains(t, string(contents), "\"context\"")
} else {
require.NotContains(t, string(contents), "\"context\"")
}
} else {
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_metrics.go"))
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_metrics_test.go"))
}
if tt.wantLogsGenerated {
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_logs.go"))
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_logs_test.go"))
} else {
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_logs.go"))
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_logs_test.go"))
}
if tt.wantConfigGenerated {
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_config.go"))
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_config_test.go"))
} else {
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_config.go"))
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_config_test.go"))
}
if tt.wantTelemetryGenerated {
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_telemetry.go"))
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_telemetry_test.go"))
require.FileExists(t, filepath.Join(tmpdir, "documentation.md"))
contents, err = os.ReadFile(filepath.Join(tmpdir, generatedPackageDir, "generated_telemetry.go")) //nolint:gosec
require.NoError(t, err)
if tt.wantMetricsContext {
require.Contains(t, string(contents), "\"context\"")
} else {
require.NotContains(t, string(contents), "\"context\"")
}
} else {
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_telemetry.go"))
}
if !tt.wantMetricsGenerated && !tt.wantTelemetryGenerated && !tt.wantResourceAttributesGenerated && !tt.wantEventsGenerated {
require.NoFileExists(t, filepath.Join(tmpdir, "documentation.md"))
}
if tt.wantStatusGenerated {
require.FileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_status.go"))
} else {
require.NoFileExists(t, filepath.Join(tmpdir, generatedPackageDir, "generated_status.go"))
}
contents, err = os.ReadFile(filepath.Join(tmpdir, "README.md")) //nolint:gosec
require.NoError(t, err)
if tt.wantReadmeGenerated {
require.NotContains(t, string(contents), "foo")
} else {
require.Contains(t, string(contents), "foo")
}
if tt.wantComponentTestGenerated {
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)
} else {
require.NoFileExists(t, filepath.Join(tmpdir, "generated_component_test.go"))
}
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.NotContains(t, string(contents), "teardownFunc")
}
})
}
}
func TestRun(t *testing.T) {
type args struct {
ymlPath string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "no argument",
args: args{""},
wantErr: true,
},
{
name: "no such file",
args: args{"/no/such/file"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := run(tt.args.ymlPath)
if !tt.wantErr {
require.NoError(t, err, "run()")
} else {
require.Error(t, err)
}
})
}
}
func TestInlineReplace(t *testing.T) {
tests := []struct {
name string
markdown string
outputFile string
componentClass string
warnings []string
stability map[component.StabilityLevel][]string
deprecation map[string]DeprecationInfo
distros []string
codeowners *Codeowners
githubProject string
}{
{
name: "readme with empty status",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status.md",
componentClass: "receiver",
distros: []string{"contrib"},
githubProject: "open-telemetry/opentelemetry-collector",
},
{
name: "readme with status for extension",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status_extension.md",
componentClass: "extension",
distros: []string{"contrib"},
},
{
name: "readme with status for converter",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status_converter.md",
componentClass: "converter",
distros: []string{"contrib"},
},
{
name: "readme with status for provider",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status_provider.md",
componentClass: "provider",
distros: []string{"contrib"},
},
{
name: "readme with status with codeowners and seeking new",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status_codeowners_and_seeking_new.md",
componentClass: "receiver",
distros: []string{"contrib"},
codeowners: &Codeowners{
Active: []string{"foo"},
SeekingNew: true,
},
},
{
name: "readme with status with codeowners and emeritus",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status_codeowners_and_emeritus.md",
componentClass: "receiver",
distros: []string{"contrib"},
codeowners: &Codeowners{
Active: []string{"foo"},
Emeritus: []string{"bar"},
},
},
{
name: "readme with status with codeowners",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_status_codeowners.md",
componentClass: "receiver",
distros: []string{"contrib"},
codeowners: &Codeowners{
Active: []string{"open-telemetry/collector-approvers"},
},
},
{
name: "readme with status table",
markdown: `# Some component
| Status | |
| ------------------------ |-----------|
Some info about a component
`,
outputFile: "readme_with_status.md",
componentClass: "receiver",
distros: []string{"contrib"},
githubProject: "open-telemetry/opentelemetry-collector",
},
{
name: "readme with no status",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_without_status.md",
distros: []string{"contrib"},
},
{
name: "component with warnings",
markdown: `# Some component
Some info about a component
### warnings
Some warning there.
`,
outputFile: "readme_with_warnings.md",
warnings: []string{"warning1"},
distros: []string{"contrib"},
},
{
name: "readme with multiple signals",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_multiple_signals.md",
stability: map[component.StabilityLevel][]string{
component.StabilityLevelBeta: {"metrics"},
component.StabilityLevelAlpha: {"logs"},
},
distros: []string{"contrib"},
},
{
name: "readme with multiple signals and deprecation",
markdown: `# Some component
Some info about a component
`,
outputFile: "readme_with_multiple_signals_and_deprecation.md",
stability: map[component.StabilityLevel][]string{
component.StabilityLevelBeta: {"metrics"},
component.StabilityLevelAlpha: {"logs"},
component.StabilityLevelDeprecated: {"traces"},
},
deprecation: DeprecationMap{
"traces": DeprecationInfo{
Date: "2025-02-05",
Migration: "no migration needed",
},
},
distros: []string{"contrib"},
},
{
name: "readme with cmd class",
markdown: `# Some component
Some info about a component
`,
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[component.StabilityLevel][]string{component.StabilityLevelBeta: {"metrics"}}
if len(tt.stability) > 0 {
stability = tt.stability
}
md := Metadata{
GithubProject: tt.githubProject,
Type: "foo",
ShortFolderName: "foo",
Status: &Status{
DisableCodeCov: true,
Stability: stability,
Distributions: tt.distros,
Class: tt.componentClass,
Warnings: tt.warnings,
Codeowners: tt.codeowners,
Deprecation: tt.deprecation,
},
}
tmpdir := t.TempDir()
readmeFile := filepath.Join(tmpdir, "README.md")
require.NoError(t, os.WriteFile(readmeFile, []byte(tt.markdown), 0o600))
err := inlineReplace("templates/readme.md.tmpl", readmeFile, md, statusStart, statusEnd, "metadata")
require.NoError(t, err)
require.FileExists(t, filepath.Join(tmpdir, "README.md"))
got, err := os.ReadFile(filepath.Join(tmpdir, "README.md")) //nolint:gosec
require.NoError(t, err)
got = bytes.ReplaceAll(got, []byte("\r\n"), []byte("\n"))
expected, err := os.ReadFile(filepath.Join("testdata", tt.outputFile))
require.NoError(t, err)
expected = bytes.ReplaceAll(expected, []byte("\r\n"), []byte("\n"))
fmt.Println(string(got))
fmt.Println(string(expected))
require.Equal(t, string(expected), string(got))
})
}
}
func TestGenerateStatusMetadata(t *testing.T) {
tests := []struct {
name string
output string
md Metadata
expected string
}{
{
name: "foo component with beta status",
md: Metadata{
Type: "foo",
Status: &Status{
Stability: map[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"
)
var (
Type = component.MustNewType("foo")
ScopeName = ""
)
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")
ScopeName = ""
)
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/otel/metric"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/collector/component"
)
func Meter(settings component.TelemetrySettings) metric.Meter {
return settings.MeterProvider.Meter("")
}
func Tracer(settings component.TelemetrySettings) trace.Tracer {
return settings.TracerProvider.Tracer("")
}
`,
},
{
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/otel/metric"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/collector/component"
)
func Meter(settings component.TelemetrySettings) metric.Meter {
return settings.MeterProvider.Meter("")
}
func Tracer(settings component.TelemetrySettings) trace.Tracer {
return settings.TracerProvider.Tracer("")
}
`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tmpdir := t.TempDir()
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_telemetry.go")) //nolint:gosec
require.NoError(t, err)
require.Equal(t, tt.expected, string(actual))
})
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/embedded_templates.go 0000664 0000000 0000000 00000000640 15113313446 0027033 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import "embed"
// TemplateFS ensures that the files needed
// to generate metadata as an embedded filesystem since
// `go get` doesn't require these files to be downloaded.
//
//go:embed templates/*.tmpl templates/testdata/*.tmpl
var TemplateFS embed.FS
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/embedded_templates_test.go 0000664 0000000 0000000 00000003414 15113313446 0030074 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"io/fs"
"path"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEnsureTemplatesLoaded(t *testing.T) {
t.Parallel()
const (
rootDir = "templates"
)
var (
templateFiles = map[string]struct{}{
path.Join(rootDir, "component_test.go.tmpl"): {},
path.Join(rootDir, "documentation.md.tmpl"): {},
path.Join(rootDir, "metrics.go.tmpl"): {},
path.Join(rootDir, "metrics_test.go.tmpl"): {},
path.Join(rootDir, "logs.go.tmpl"): {},
path.Join(rootDir, "logs_test.go.tmpl"): {},
path.Join(rootDir, "resource.go.tmpl"): {},
path.Join(rootDir, "resource_test.go.tmpl"): {},
path.Join(rootDir, "config.go.tmpl"): {},
path.Join(rootDir, "config_test.go.tmpl"): {},
path.Join(rootDir, "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"): {},
path.Join(rootDir, "telemetrytest.go.tmpl"): {},
path.Join(rootDir, "telemetrytest_test.go.tmpl"): {},
path.Join(rootDir, "helper.tmpl"): {},
}
count = 0
)
require.NoError(t, fs.WalkDir(TemplateFS, ".", func(path string, d fs.DirEntry, _ error) error {
if d != nil && d.IsDir() {
return nil
}
count++
assert.Contains(t, templateFiles, path)
return nil
}))
assert.Equal(t, len(templateFiles), count, "Must match the expected number of calls")
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/event.go 0000664 0000000 0000000 00000001517 15113313446 0024351 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"errors"
"go.opentelemetry.io/collector/confmap"
)
type (
EventName string
)
func (ln EventName) Render() (string, error) {
return FormatIdentifier(string(ln), true)
}
func (ln EventName) RenderUnexported() (string, error) {
return FormatIdentifier(string(ln), false)
}
type Event struct {
Signal `mapstructure:",squash"`
}
func (l *Event) validate() error {
var errs error
if l.Description == "" {
errs = errors.Join(errs, errors.New(`missing event description`))
}
return errs
}
func (l *Event) Unmarshal(parser *confmap.Conf) error {
if !parser.IsSet("enabled") {
return errors.New("missing required field: `enabled`")
}
return parser.Unmarshal(l)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/event_test.go 0000664 0000000 0000000 00000001547 15113313446 0025413 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEventNameRender(t *testing.T) {
for _, tt := range []struct {
name EventName
success bool
expectedExported string
expectedUnExported string
}{
{"", false, "", ""},
{"otel.val", true, "OtelVal", "otelVal"},
{"otel_val_2", true, "OtelVal2", "otelVal2"},
} {
exported, err := tt.name.Render()
if tt.success {
require.NoError(t, err)
assert.Equal(t, tt.expectedExported, exported)
} else {
require.Error(t, err)
}
unexported, err := tt.name.RenderUnexported()
if tt.success {
require.NoError(t, err)
assert.Equal(t, tt.expectedUnExported, unexported)
} else {
require.Error(t, err)
}
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/lint.go 0000664 0000000 0000000 00000003072 15113313446 0024174 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"errors"
"strings"
"unicode"
"go.opentelemetry.io/collector/cmd/mdatagen/third_party/golint"
)
// FormatIdentifier variable in a go-safe way
func FormatIdentifier(s string, exported bool) (string, error) {
if s == "" {
return "", errors.New("string cannot be empty")
}
// Convert various characters to . for strings.Title to operate on.
replace := strings.NewReplacer("_", ".", "-", ".", "<", ".", ">", ".", "/", ".", ":", ".")
str := replace.Replace(s)
str = strings.Title(str) //nolint:staticcheck // SA1019
str = strings.ReplaceAll(str, ".", "")
var word string
var output string
// Fixup acronyms to make lint happy.
for idx, r := range str {
if idx == 0 {
if exported {
r = unicode.ToUpper(r)
} else {
r = unicode.ToLower(r)
}
}
if unicode.IsUpper(r) || unicode.IsNumber(r) {
// If the current word is an acronym and it's either exported or it's not the
// beginning of an unexported variable then upper case it.
if golint.Acronyms[strings.ToUpper(word)] && (exported || output != "") {
output += strings.ToUpper(word)
word = string(r)
} else {
output += word
word = string(r)
}
} else {
word += string(r)
}
}
if golint.Acronyms[strings.ToUpper(word)] && output != "" {
output += strings.ToUpper(word)
} else {
output += word
}
// Remove white spaces
output = strings.Join(strings.Fields(output), "")
return output, nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/lint_test.go 0000664 0000000 0000000 00000002342 15113313446 0025232 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestFormatIdentifier(t *testing.T) {
tests := []struct {
input string
want string
exported bool
wantErr string
}{
// Unexported.
{input: "max.cpu", want: "maxCPU"},
{input: "max.foo", want: "maxFoo"},
{input: "cpu.utilization", want: "cpuUtilization"},
{input: "cpu", want: "cpu"},
{input: "max.ip.addr", want: "maxIPAddr"},
{input: "some_metric", want: "someMetric"},
{input: "some-metric", want: "someMetric"},
{input: "Upper.Case", want: "upperCase"},
{input: "max.ip6", want: "maxIP6"},
{input: "max.ip6.idle", want: "maxIP6Idle"},
{input: "node_netstat_IpExt_OutOctets", want: "nodeNetstatIPExtOutOctets"},
// Exported.
{input: "cpu.state", want: "CPUState", exported: true},
// Errors
{input: "", want: "", wantErr: "string cannot be empty"},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
got, err := FormatIdentifier(tt.input, tt.exported)
if tt.wantErr != "" {
require.EqualError(t, err, tt.wantErr)
} else {
require.NoError(t, err)
require.Equal(t, tt.want, got)
}
})
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/loader.go 0000664 0000000 0000000 00000004734 15113313446 0024502 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"context"
"errors"
"fmt"
"os/exec"
"path/filepath"
"strings"
"go.opentelemetry.io/collector/confmap/confmaptest"
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
)
func setAttributeDefaultFields(attrs map[AttributeName]Attribute) {
for k, v := range attrs {
v.FullName = k
if v.RequirementLevel == "" {
v.RequirementLevel = AttributeRequirementLevelRecommended
}
attrs[k] = v
}
}
type TemplateContext struct {
Metadata
// Package name for generated code.
Package string
}
func LoadMetadata(filePath string) (Metadata, error) {
cp, err := fileprovider.NewFactory().Create(confmaptest.NewNopProviderSettings()).Retrieve(context.Background(), "file:"+filePath, nil)
if err != nil {
return Metadata{}, err
}
conf, err := cp.AsConf()
if err != nil {
return Metadata{}, err
}
md := Metadata{ShortFolderName: shortFolderName(filePath), Tests: Tests{Host: "newMdatagenNopHost()"}}
err = conf.Unmarshal(&md)
if err != nil {
return md, err
}
packageName, err := packageName(filepath.Dir(filePath))
if err != nil {
return md, fmt.Errorf("unable to determine package name: %w", err)
}
md.PackageName = packageName
if md.ScopeName == "" {
md.ScopeName = packageName
}
if md.GeneratedPackageName == "" {
md.GeneratedPackageName = "metadata"
}
if err := md.Validate(); err != nil {
return md, err
}
setAttributeDefaultFields(md.Attributes)
setAttributeDefaultFields(md.ResourceAttributes)
return md, nil
}
var componentTypes = []string{
"connector",
"exporter",
"extension",
"processor",
"scraper",
"receiver",
}
func shortFolderName(filePath string) string {
parentFolder := filepath.Base(filepath.Dir(filePath))
for _, cType := range componentTypes {
if before, ok := strings.CutSuffix(parentFolder, cType); ok {
return before
}
}
return parentFolder
}
func packageName(filePath string) (string, error) {
cmd := exec.Command("go", "list", "-f", "{{.ImportPath}}")
cmd.Dir = filePath
output, err := cmd.Output()
if err != nil {
var ee *exec.ExitError
if errors.As(err, &ee) {
return "", fmt.Errorf("unable to determine package name: %v failed: (stderr) %v", cmd.Args, string(ee.Stderr))
}
return "", fmt.Errorf("unable to determine package name: %v failed: %v %w", cmd.Args, string(output), err)
}
return strings.TrimSpace(string(output)), nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/loader_test.go 0000664 0000000 0000000 00000053401 15113313446 0025534 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)
func boolPtr(b bool) *bool {
return &b
}
func TestTwoPackagesInDirectory(t *testing.T) {
contents, err := os.ReadFile("testdata/twopackages.yaml")
require.NoError(t, err)
tempDir := t.TempDir()
metadataPath := filepath.Join(tempDir, "metadata.yaml")
// we create a trivial module and packages to avoid having invalid go checked into our test directory.
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module twopackages"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "package1.go"), []byte("package package1"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "package2.go"), []byte("package package2"), 0o600))
require.NoError(t, os.WriteFile(metadataPath, contents, 0o600))
_, err = LoadMetadata(metadataPath)
require.Error(t, err)
require.ErrorContains(t, err, "unable to determine package name: [go list -f {{.ImportPath}}] failed: (stderr) found packages package1 (package1.go) and package2 (package2.go)")
}
func TestLoadMetadata(t *testing.T) {
tests := []struct {
name string
want Metadata
wantErr string
}{
{
name: "samplereceiver/metadata.yaml",
want: Metadata{
GithubProject: "open-telemetry/opentelemetry-collector",
GeneratedPackageName: "metadata",
Type: "sample",
SemConvVersion: "1.37.0",
PackageName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver",
Status: &Status{
DisableCodeCov: true,
Class: "receiver",
Stability: map[component.StabilityLevel][]string{
component.StabilityLevelDevelopment: {"logs"},
component.StabilityLevelBeta: {"traces"},
component.StabilityLevelStable: {"metrics"},
component.StabilityLevelDeprecated: {"profiles"},
},
Distributions: []string{},
Deprecation: DeprecationMap{
"profiles": DeprecationInfo{
Date: "2025-02-05",
Migration: "no migration needed",
},
},
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": {
Description: "Resource attribute with any string value.",
EnabledPtr: boolPtr(true),
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "string.resource.attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"string.enum.resource.attr": {
Description: "Resource attribute with a known set of string values.",
EnabledPtr: boolPtr(true),
Enum: []string{"one", "two"},
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "string.enum.resource.attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"optional.resource.attr": {
Description: "Explicitly disabled ResourceAttribute.",
EnabledPtr: boolPtr(false),
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "optional.resource.attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"slice.resource.attr": {
Description: "Resource attribute with a slice value.",
EnabledPtr: boolPtr(true),
Type: ValueType{
ValueType: pcommon.ValueTypeSlice,
},
FullName: "slice.resource.attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"map.resource.attr": {
Description: "Resource attribute with a map value.",
EnabledPtr: boolPtr(true),
Type: ValueType{
ValueType: pcommon.ValueTypeMap,
},
FullName: "map.resource.attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"string.resource.attr_disable_warning": {
Description: "Resource attribute with any string value.",
Warnings: Warnings{
IfEnabledNotSet: "This resource_attribute will be disabled by default soon.",
},
EnabledPtr: boolPtr(true),
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "string.resource.attr_disable_warning",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"string.resource.attr_remove_warning": {
Description: "Resource attribute with any string value.",
Warnings: Warnings{
IfConfigured: "This resource_attribute is deprecated and will be removed soon.",
},
EnabledPtr: boolPtr(false),
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "string.resource.attr_remove_warning",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"string.resource.attr_to_be_removed": {
Description: "Resource attribute with any string value.",
Warnings: Warnings{
IfEnabled: "This resource_attribute is deprecated and will be removed soon.",
},
EnabledPtr: boolPtr(true),
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "string.resource.attr_to_be_removed",
RequirementLevel: AttributeRequirementLevelRecommended,
},
},
Attributes: map[AttributeName]Attribute{
"enum_attr": {
Description: "Attribute with a known set of string values.",
NameOverride: "",
Enum: []string{"red", "green", "blue"},
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "enum_attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"string_attr": {
Description: "Attribute with any string value.",
NameOverride: "",
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "string_attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"overridden_int_attr": {
Description: "Integer attribute with overridden name.",
NameOverride: "state",
Type: ValueType{
ValueType: pcommon.ValueTypeInt,
},
FullName: "overridden_int_attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"boolean_attr": {
Description: "Attribute with a boolean value.",
Type: ValueType{
ValueType: pcommon.ValueTypeBool,
},
FullName: "boolean_attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"boolean_attr2": {
Description: "Another attribute with a boolean value.",
Type: ValueType{
ValueType: pcommon.ValueTypeBool,
},
FullName: "boolean_attr2",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"slice_attr": {
Description: "Attribute with a slice value.",
Type: ValueType{
ValueType: pcommon.ValueTypeSlice,
},
FullName: "slice_attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"map_attr": {
Description: "Attribute with a map value.",
Type: ValueType{
ValueType: pcommon.ValueTypeMap,
},
FullName: "map_attr",
RequirementLevel: AttributeRequirementLevelRecommended,
},
"conditional_int_attr": {
Description: "A conditional attribute with an integer value",
Type: ValueType{
ValueType: pcommon.ValueTypeInt,
},
FullName: "conditional_int_attr",
RequirementLevel: AttributeRequirementLevelConditionallyRequired,
},
"conditional_string_attr": {
Description: "A conditional attribute with any string value",
Type: ValueType{
ValueType: pcommon.ValueTypeStr,
},
FullName: "conditional_string_attr",
RequirementLevel: AttributeRequirementLevelConditionallyRequired,
},
"opt_in_bool_attr": {
Description: "An opt-in attribute with a boolean value",
Type: ValueType{
ValueType: pcommon.ValueTypeBool,
},
FullName: "opt_in_bool_attr",
RequirementLevel: AttributeRequirementLevelOptIn,
},
},
Metrics: map[MetricName]Metric{
"default.metric": {
Signal: Signal{
Enabled: true,
Description: "Monotonic cumulative sum int metric enabled by default.",
ExtendedDocumentation: "The metric will be become optional soon.",
Stability: Stability{Level: component.StabilityLevelDevelopment},
Warnings: Warnings{
IfEnabledNotSet: "This metric will be disabled by default soon.",
},
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr", "conditional_int_attr", "conditional_string_attr", "opt_in_bool_attr"},
},
Unit: strPtr("s"),
Sum: &Sum{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt},
AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityCumulative},
Mono: Mono{Monotonic: true},
},
},
"system.cpu.time": {
Signal: Signal{
Enabled: true,
Stability: Stability{Level: component.StabilityLevelBeta},
SemanticConvention: &SemanticConvention{SemanticConventionRef: "https://github.com/open-telemetry/semantic-conventions/blob/v1.37.0/docs/system/system-metrics.md#metric-systemcputime"},
Description: "Monotonic cumulative sum int metric enabled by default.",
ExtendedDocumentation: "The metric will be become optional soon.",
},
Unit: strPtr("s"),
Sum: &Sum{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt},
AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityCumulative},
Mono: Mono{Monotonic: true},
},
},
"optional.metric": {
Signal: Signal{
Enabled: false,
Description: "[DEPRECATED] Gauge double metric disabled by default.",
Stability: Stability{Level: component.StabilityLevelDeprecated},
Warnings: Warnings{
IfConfigured: "This metric is deprecated and will be removed soon.",
},
Attributes: []AttributeName{"string_attr", "boolean_attr", "boolean_attr2", "conditional_string_attr"},
},
Unit: strPtr("1"),
Gauge: &Gauge{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble},
},
},
"optional.metric.empty_unit": {
Signal: Signal{
Enabled: false,
Description: "[DEPRECATED] Gauge double metric disabled by default.",
Stability: Stability{Level: component.StabilityLevelDeprecated},
Warnings: Warnings{
IfConfigured: "This metric is deprecated and will be removed soon.",
},
Attributes: []AttributeName{"string_attr", "boolean_attr"},
},
Unit: strPtr(""),
Gauge: &Gauge{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble},
},
},
"default.metric.to_be_removed": {
Signal: Signal{
Enabled: true,
Description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.",
ExtendedDocumentation: "The metric will be removed soon.",
Stability: Stability{Level: component.StabilityLevelDeprecated},
Warnings: Warnings{
IfEnabled: "This metric is deprecated and will be removed soon.",
},
},
Unit: strPtr("s"),
Sum: &Sum{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble},
AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityDelta},
Mono: Mono{Monotonic: false},
},
},
"metric.input_type": {
Signal: Signal{
Enabled: true,
Description: "Monotonic cumulative sum int metric with string input_type enabled by default.",
Stability: Stability{Level: component.StabilityLevelDevelopment},
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr"},
},
Unit: strPtr("s"),
Sum: &Sum{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt},
MetricInputType: MetricInputType{InputType: "string"},
AggregationTemporality: AggregationTemporality{Aggregation: pmetric.AggregationTemporalityCumulative},
Mono: Mono{Monotonic: true},
},
},
},
Events: map[EventName]Event{
"default.event": {
Signal: Signal{
Enabled: true,
Description: "Example event enabled by default.",
Warnings: Warnings{
IfEnabledNotSet: "This event will be disabled by default soon.",
},
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr", "conditional_int_attr", "conditional_string_attr", "opt_in_bool_attr"},
},
},
"default.event.to_be_renamed": {
Signal: Signal{
Enabled: false,
Description: "[DEPRECATED] Example event disabled by default.",
ExtendedDocumentation: "The event will be renamed soon.",
Warnings: Warnings{
IfConfigured: "This event is deprecated and will be renamed soon.",
},
Attributes: []AttributeName{"string_attr", "boolean_attr", "boolean_attr2", "conditional_string_attr"},
},
},
"default.event.to_be_removed": {
Signal: Signal{
Enabled: true,
Description: "[DEPRECATED] Example to-be-removed event enabled by default.",
ExtendedDocumentation: "The event will be removed soon.",
Warnings: Warnings{
IfEnabled: "This event is deprecated and will be removed soon.",
},
Attributes: []AttributeName{"string_attr", "overridden_int_attr", "enum_attr", "slice_attr", "map_attr"},
},
},
},
Telemetry: Telemetry{
Metrics: map[MetricName]Metric{
"batch_size_trigger_send": {
Signal: Signal{
Enabled: true,
Stability: Stability{Level: component.StabilityLevelDeprecated, From: "v0.110.0"},
Description: "Number of times the batch was sent due to a size trigger",
},
Unit: strPtr("{times}"),
Sum: &Sum{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt},
Mono: Mono{Monotonic: true},
},
},
"request_duration": {
Signal: Signal{
Enabled: true,
Stability: Stability{Level: component.StabilityLevelAlpha},
Description: "Duration of request",
},
Unit: strPtr("s"),
Histogram: &Histogram{
MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble},
Boundaries: []float64{1, 10, 100},
},
},
"process_runtime_total_alloc_bytes": {
Signal: Signal{
Enabled: true,
Stability: Stability{Level: component.StabilityLevelStable},
Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')",
},
Unit: strPtr("By"),
Sum: &Sum{
Mono: Mono{true},
MetricValueType: MetricValueType{
ValueType: pmetric.NumberDataPointValueTypeInt,
},
Async: true,
},
},
"queue_length": {
Signal: Signal{
Enabled: true,
Stability: Stability{Level: component.StabilityLevelAlpha},
Description: "This metric is optional and therefore not initialized in NewTelemetryBuilder.",
ExtendedDocumentation: "For example this metric only exists if feature A is enabled.",
},
Unit: strPtr("{items}"),
Optional: true,
Gauge: &Gauge{
MetricValueType: MetricValueType{
ValueType: pmetric.NumberDataPointValueTypeInt,
},
Async: true,
},
},
"queue_capacity": {
Signal: Signal{
Enabled: true,
Description: "Queue capacity - sync gauge example.",
Stability: Stability{Level: component.StabilityLevelDevelopment},
},
Unit: strPtr("{items}"),
Gauge: &Gauge{
MetricValueType: MetricValueType{
ValueType: pmetric.NumberDataPointValueTypeInt,
},
},
},
},
},
ScopeName: "go.opentelemetry.io/collector/internal/receiver/samplereceiver",
ShortFolderName: "sample",
Tests: Tests{Host: "newMdatagenNopHost()"},
},
},
{
name: "testdata/parent.yaml",
want: Metadata{
Type: "subcomponent",
Parent: "parentComponent",
GeneratedPackageName: "metadata",
ScopeName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/testdata",
PackageName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/testdata",
ShortFolderName: "testdata",
Tests: Tests{Host: "newMdatagenNopHost()"},
},
},
{
name: "testdata/generated_package_name.yaml",
want: Metadata{
Type: "custom",
GeneratedPackageName: "customname",
ScopeName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/testdata",
PackageName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/testdata",
ShortFolderName: "testdata",
Tests: Tests{Host: "newMdatagenNopHost()"},
Status: &Status{
Class: "receiver",
Stability: map[component.StabilityLevel][]string{
component.StabilityLevelDevelopment: {"logs"},
component.StabilityLevelBeta: {"traces"},
component.StabilityLevelStable: {"metrics"},
},
},
},
},
{
name: "testdata/empty_test_config.yaml",
want: Metadata{
Type: "test",
GeneratedPackageName: "metadata",
ScopeName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/testdata",
PackageName: "go.opentelemetry.io/collector/cmd/mdatagen/internal/testdata",
ShortFolderName: "testdata",
Tests: Tests{Host: "newMdatagenNopHost()"},
Status: &Status{
Class: "receiver",
Stability: map[component.StabilityLevel][]string{
component.StabilityLevelBeta: {"logs"},
},
},
},
},
{
name: "testdata/invalid_type_rattr.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'resource_attributes[string.resource.attr].type' invalid type: \"invalidtype\"",
},
{
name: "testdata/no_enabled.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'metrics[system.cpu.time]' missing required field: `enabled`",
},
{
name: "testdata/events/no_enabled.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'events[system.event]' missing required field: `enabled`",
},
{
name: "testdata/no_value_type.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'metrics[system.cpu.time]' decoding failed due to the following error(s):\n\n" +
"'sum' missing required field: `value_type`",
},
{
name: "testdata/unknown_value_type.yaml",
wantErr: "decoding failed due to the following error(s):\n\n'metrics[system.cpu.time]' decoding failed due to the following error(s):\n\n'sum' decoding failed due to the following error(s):\n\n'value_type' invalid value_type: \"unknown\"",
},
{
name: "testdata/invalid_aggregation.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'metrics[default.metric]' decoding failed due to the following error(s):\n\n'sum' decoding failed due to the following error(s):\n\n'aggregation_temporality' invalid aggregation: \"invalidaggregation\"",
},
{
name: "testdata/invalid_type_attr.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'attributes[used_attr].type' invalid type: \"invalidtype\"",
},
{
name: "testdata/invalid_metric_stability.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'metrics[default.metric]' decoding failed due to the following error(s):\n\n'stability' decoding failed due to the following error(s):\n\n'level' unsupported stability level: \"development42\"",
},
{
name: "testdata/invalid_metric_semconvref.yaml",
want: Metadata{},
wantErr: "metric \"default.metric\": invalid semantic-conventions URL: want https://github.com/open-telemetry/semantic-conventions/blob/v1.37.2/*#metric-defaultmetric, got \"https://github.com/open-telemetry/semantic-conventions/blob/v1.38.0/docs/system/system-metrics.md#metric-systemcputime\"",
},
{
name: "testdata/no_metric_stability.yaml",
want: Metadata{},
wantErr: "decoding failed due to the following error(s):\n\n'metrics[default.metric]' decoding failed due to the following error(s):\n\n'stability' missing required field: `stability.level`",
},
{
name: "testdata/~~this file doesn't exist~~.yaml",
wantErr: "unable to read the file file:testdata/~~this file doesn't exist~~.yaml",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := LoadMetadata(tt.name)
if tt.wantErr != "" {
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
} else {
require.NoError(t, err)
require.Equal(t, tt.want, got)
}
})
}
}
func strPtr(s string) *string {
return &s
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/metadata.go 0000664 0000000 0000000 00000042630 15113313446 0025011 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"errors"
"fmt"
"regexp"
"slices"
"strconv"
"strings"
"go.opentelemetry.io/collector/filter"
"go.opentelemetry.io/collector/pdata/pcommon"
)
type Metadata struct {
// Type of the component.
Type string `mapstructure:"type"`
// Type of the parent component (applicable to subcomponents).
Parent string `mapstructure:"parent"`
// Status information for the component.
Status *Status `mapstructure:"status"`
// The name of the package that will be generated.
GeneratedPackageName string `mapstructure:"generated_package_name"`
// Telemetry information for the component.
Telemetry Telemetry `mapstructure:"telemetry"`
// SemConvVersion is a version number of OpenTelemetry semantic conventions applied to the scraped metrics.
SemConvVersion string `mapstructure:"sem_conv_version"`
// ResourceAttributes that can be emitted by the component.
ResourceAttributes map[AttributeName]Attribute `mapstructure:"resource_attributes"`
// Entities organizes resource attributes into logical entities.
Entities []Entity `mapstructure:"entities"`
// Attributes emitted by one or more metrics.
Attributes map[AttributeName]Attribute `mapstructure:"attributes"`
// Metrics that can be emitted by the component.
Metrics map[MetricName]Metric `mapstructure:"metrics"`
// Events that can be emitted by the component.
Events map[EventName]Event `mapstructure:"events"`
// GithubProject is the project where the component README lives in the format of org/repo, defaults to open-telemetry/opentelemetry-collector-contrib
GithubProject string `mapstructure:"github_project"`
// ScopeName of the metrics emitted by the component.
ScopeName string `mapstructure:"scope_name"`
// ShortFolderName is the shortened folder name of the component, removing class if present
ShortFolderName string `mapstructure:"-"`
// Tests is the set of tests generated with the component
Tests Tests `mapstructure:"tests"`
// PackageName is the name of the package where the component is defined.
PackageName string `mapstructure:"package_name"`
}
func (md Metadata) GetCodeCovComponentID() string {
if md.Status.CodeCovComponentID != "" {
return md.Status.CodeCovComponentID
}
return strings.ReplaceAll(md.Status.Class+"_"+md.Type, "/", "_")
}
func (md Metadata) HasEntities() bool {
return len(md.Entities) > 0
}
func (md *Metadata) Validate() error {
var errs error
if err := md.validateType(); err != nil {
errs = errors.Join(errs, err)
}
if md.Parent != "" {
if md.Status != nil {
// status is not required for subcomponents.
errs = errors.Join(errs, errors.New("status must be empty for subcomponents"))
}
} else {
errs = errors.Join(errs, md.Status.Validate())
}
if err := md.validateResourceAttributes(); err != nil {
errs = errors.Join(errs, err)
}
if err := md.validateEntities(); err != nil {
errs = errors.Join(errs, err)
}
if err := md.validateMetricsAndEvents(); err != nil {
errs = errors.Join(errs, err)
}
return errs
}
// typeRegexp is used to validate the type of a component.
// A type must start with an ASCII alphabetic character and
// can only contain ASCII alphanumeric characters and '_'.
// 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_]{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)
}
return nil
}
func (md *Metadata) validateResourceAttributes() error {
var errs error
for name, attr := range md.ResourceAttributes {
if attr.Description == "" {
errs = errors.Join(errs, fmt.Errorf("empty description for resource attribute: %v", name))
}
empty := ValueType{ValueType: pcommon.ValueTypeEmpty}
if attr.Type == empty {
errs = errors.Join(errs, fmt.Errorf("empty type for resource attribute: %v", name))
}
if attr.EnabledPtr == nil {
errs = errors.Join(errs, fmt.Errorf("enabled field is required for resource attribute: %v", name))
}
}
return errs
}
func (md *Metadata) validateEntities() error {
var errs error
usedAttrs := make(map[AttributeName]string)
seenTypes := make(map[string]bool)
for _, entity := range md.Entities {
if entity.Type == "" {
errs = errors.Join(errs, errors.New("entity type cannot be empty"))
continue
}
if seenTypes[entity.Type] {
errs = errors.Join(errs, fmt.Errorf(`duplicate entity type: %v`, entity.Type))
}
seenTypes[entity.Type] = true
if entity.Brief == "" {
errs = errors.Join(errs, fmt.Errorf(`entity "%v": brief is required`, entity.Type))
}
if len(entity.Identity) == 0 {
errs = errors.Join(errs, fmt.Errorf(`entity "%v": identity is required`, entity.Type))
}
for _, ref := range entity.Identity {
if _, ok := md.ResourceAttributes[ref.Ref]; !ok {
errs = errors.Join(errs, fmt.Errorf(`entity "%v": identity refers to undefined resource attribute: %v`, entity.Type, ref.Ref))
}
if otherEntity, used := usedAttrs[ref.Ref]; used {
errs = errors.Join(errs, fmt.Errorf(`entity "%v": attribute %v is already used by entity "%v"`, entity.Type, ref.Ref, otherEntity))
} else {
usedAttrs[ref.Ref] = entity.Type
}
}
for _, ref := range entity.Description {
if _, ok := md.ResourceAttributes[ref.Ref]; !ok {
errs = errors.Join(errs, fmt.Errorf(`entity "%v": description refers to undefined resource attribute: %v`, entity.Type, ref.Ref))
}
if otherEntity, used := usedAttrs[ref.Ref]; used {
errs = errors.Join(errs, fmt.Errorf(`entity "%v": attribute %v is already used by entity "%v"`, entity.Type, ref.Ref, otherEntity))
} else {
usedAttrs[ref.Ref] = entity.Type
}
}
}
return errs
}
func (md *Metadata) validateMetricsAndEvents() error {
var errs error
usedAttrs := map[AttributeName]bool{}
errs = errors.Join(errs,
validateMetrics(md.Metrics, md.Attributes, usedAttrs, md.SemConvVersion),
validateMetrics(md.Telemetry.Metrics, md.Attributes, usedAttrs, md.SemConvVersion),
validateEvents(md.Events, md.Attributes, usedAttrs),
md.validateAttributes(usedAttrs))
return errs
}
func (md *Metadata) validateAttributes(usedAttrs map[AttributeName]bool) error {
var errs error
unusedAttrs := make([]AttributeName, 0, len(md.Attributes))
for attrName, attr := range md.Attributes {
if attr.Description == "" {
errs = errors.Join(errs, fmt.Errorf(`missing attribute description for: %v`, attrName))
}
empty := ValueType{ValueType: pcommon.ValueTypeEmpty}
if attr.Type == empty {
errs = errors.Join(errs, fmt.Errorf("empty type for attribute: %v", attrName))
}
if attr.EnabledPtr != nil {
errs = errors.Join(errs, fmt.Errorf("enabled field is not allowed for regular attribute: %v", attrName))
}
if !usedAttrs[attrName] {
unusedAttrs = append(unusedAttrs, attrName)
}
}
if len(unusedAttrs) > 0 {
errs = errors.Join(errs, fmt.Errorf("unused attributes: %v", unusedAttrs))
}
return errs
}
func (md *Metadata) supportsSignal(signal string) bool {
if md.Status == nil {
return false
}
for _, signals := range md.Status.Stability {
if slices.Contains(signals, signal) {
return true
}
}
return false
}
func validateMetrics(metrics map[MetricName]Metric, attributes map[AttributeName]Attribute, usedAttrs map[AttributeName]bool, semConvVersion string) error {
var errs error
for mn, m := range metrics {
if err := m.validate(mn, semConvVersion); err != nil {
errs = errors.Join(errs, fmt.Errorf(`metric "%v": %w`, mn, err))
continue
}
unknownAttrs := make([]AttributeName, 0, len(m.Attributes))
for _, attr := range m.Attributes {
if _, ok := attributes[attr]; ok {
usedAttrs[attr] = true
} else {
unknownAttrs = append(unknownAttrs, attr)
}
}
if len(unknownAttrs) > 0 {
errs = errors.Join(errs, fmt.Errorf(`metric "%v" refers to undefined attributes: %v`, mn, unknownAttrs))
}
}
return errs
}
func validateEvents(events map[EventName]Event, attributes map[AttributeName]Attribute, usedAttrs map[AttributeName]bool) error {
var errs error
for en, e := range events {
if err := e.validate(); err != nil {
errs = errors.Join(errs, fmt.Errorf(`event "%v": %w`, en, err))
continue
}
unknownAttrs := make([]AttributeName, 0, len(e.Attributes))
for _, attr := range e.Attributes {
if _, ok := attributes[attr]; ok {
usedAttrs[attr] = true
} else {
unknownAttrs = append(unknownAttrs, attr)
}
}
if len(unknownAttrs) > 0 {
errs = errors.Join(errs, fmt.Errorf(`event "%v" refers to undefined attributes: %v`, en, unknownAttrs))
}
}
return errs
}
type AttributeName string
// AttributeRequirementLevel defines the requirement level of an attribute.
type AttributeRequirementLevel string
const (
// AttributeRequirementLevelRequired means the attribute is always included and cannot be excluded.
AttributeRequirementLevelRequired AttributeRequirementLevel = "required"
// AttributeRequirementLevelConditionallyRequired means the attribute is included by default when certain conditions are met.
AttributeRequirementLevelConditionallyRequired AttributeRequirementLevel = "conditionally_required"
// AttributeRequirementLevelRecommended means the attribute is included by default but can be disabled via configuration.
AttributeRequirementLevelRecommended AttributeRequirementLevel = "recommended"
// AttributeRequirementLevelOptIn means the attribute is not included unless explicitly enabled in user config.
AttributeRequirementLevelOptIn AttributeRequirementLevel = "opt_in"
)
// String returns capitalized display name of the requirement level for documentation.
func (rl AttributeRequirementLevel) String() string {
switch rl {
case AttributeRequirementLevelRequired:
return "Required"
case AttributeRequirementLevelConditionallyRequired:
return "Conditionally Required"
case AttributeRequirementLevelRecommended:
return "Recommended"
case AttributeRequirementLevelOptIn:
return "Opt-In"
}
return ""
}
func (mn AttributeName) Render() (string, error) {
return FormatIdentifier(string(mn), true)
}
func (mn AttributeName) RenderUnexported() (string, error) {
return FormatIdentifier(string(mn), false)
}
// ValueType defines an attribute value type.
type ValueType struct {
// ValueType is type of the attribute value.
ValueType pcommon.ValueType
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (mvt *ValueType) UnmarshalText(text []byte) error {
switch vtStr := string(text); vtStr {
case "string":
mvt.ValueType = pcommon.ValueTypeStr
case "int":
mvt.ValueType = pcommon.ValueTypeInt
case "double":
mvt.ValueType = pcommon.ValueTypeDouble
case "bool":
mvt.ValueType = pcommon.ValueTypeBool
case "bytes":
mvt.ValueType = pcommon.ValueTypeBytes
case "slice":
mvt.ValueType = pcommon.ValueTypeSlice
case "map":
mvt.ValueType = pcommon.ValueTypeMap
default:
return fmt.Errorf("invalid type: %q", vtStr)
}
return nil
}
// String returns capitalized name of the ValueType.
func (mvt ValueType) String() string {
return strings.Title(strings.ToLower(mvt.ValueType.String())) //nolint:staticcheck // SA1019
}
// Primitive returns name of primitive type for the ValueType.
func (mvt ValueType) Primitive() string {
switch mvt.ValueType {
case pcommon.ValueTypeStr:
return "string"
case pcommon.ValueTypeInt:
return "int64"
case pcommon.ValueTypeDouble:
return "float64"
case pcommon.ValueTypeBool:
return "bool"
case pcommon.ValueTypeBytes:
return "[]byte"
case pcommon.ValueTypeSlice:
return "[]any"
case pcommon.ValueTypeMap:
return "map[string]any"
case pcommon.ValueTypeEmpty:
return ""
default:
return ""
}
}
type SemanticConvention struct {
SemanticConventionRef string `mapstructure:"ref"`
}
type Warnings struct {
// A warning that will be displayed if the field is enabled in user config.
IfEnabled string `mapstructure:"if_enabled"`
// A warning that will be displayed if `enabled` field is not set explicitly in user config.
IfEnabledNotSet string `mapstructure:"if_enabled_not_set"`
// A warning that will be displayed if the field is configured by user in any way.
IfConfigured string `mapstructure:"if_configured"`
}
type Attribute struct {
// Description describes the purpose of the attribute.
Description string `mapstructure:"description"`
// NameOverride can be used to override the attribute name.
NameOverride string `mapstructure:"name_override"`
// EnabledPtr defines whether the attribute is enabled by default.
EnabledPtr *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.
Type ValueType `mapstructure:"type"`
// FullName is the attribute name populated from the map key.
FullName AttributeName `mapstructure:"-"`
// Warnings that will be shown to user under specified conditions.
Warnings Warnings `mapstructure:"warnings"`
// RequirementLevel defines the requirement level of the attribute.
RequirementLevel AttributeRequirementLevel `mapstructure:"requirement_level"`
}
// IsConditional returns true if the attribute is conditionally required.
func (a Attribute) IsConditional() bool {
return a.RequirementLevel == AttributeRequirementLevelConditionallyRequired
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (rl *AttributeRequirementLevel) UnmarshalText(text []byte) error {
switch string(text) {
case "required":
*rl = AttributeRequirementLevelRequired
case "conditionally_required":
*rl = AttributeRequirementLevelConditionallyRequired
case "recommended":
*rl = AttributeRequirementLevelRecommended
case "opt_in":
*rl = AttributeRequirementLevelOptIn
case "":
*rl = AttributeRequirementLevelRecommended
default:
return fmt.Errorf("invalid requirement_level %q", string(text))
}
return nil
}
// Enabled returns the boolean value of EnabledPtr.
// This method is needed to differentiate between different types of attributes:
// - Resource attributes: EnabledPtr is always set (non-nil) due to validation
// - Regular attributes: EnabledPtr is always nil due to validation
// Panics if EnabledPtr is nil, indicating incorrect template usage.
func (a Attribute) Enabled() bool {
if a.EnabledPtr == nil {
panic("Enabled() must not be called on regular attributes, only on resource attributes")
}
return *a.EnabledPtr
}
// Name returns actual name of the attribute that is set on the metric after applying NameOverride.
func (a Attribute) Name() AttributeName {
if a.NameOverride != "" {
return AttributeName(a.NameOverride)
}
return a.FullName
}
func (a Attribute) TestValue() string {
if a.Enum != nil {
return fmt.Sprintf(`%q`, a.Enum[0])
}
switch a.Type.ValueType {
case pcommon.ValueTypeEmpty:
return ""
case pcommon.ValueTypeStr:
return fmt.Sprintf(`"%s-val"`, a.FullName)
case pcommon.ValueTypeInt:
return strconv.Itoa(len(a.FullName))
case pcommon.ValueTypeDouble:
return fmt.Sprintf("%f", 0.1+float64(len(a.FullName)))
case pcommon.ValueTypeBool:
return strconv.FormatBool(len(a.FullName)%2 == 0)
case pcommon.ValueTypeMap:
return fmt.Sprintf(`map[string]any{"key1": "%s-val1", "key2": "%s-val2"}`, a.FullName, a.FullName)
case pcommon.ValueTypeSlice:
return fmt.Sprintf(`[]any{"%s-item1", "%s-item2"}`, a.FullName, a.FullName)
case pcommon.ValueTypeBytes:
return fmt.Sprintf(`[]byte("%s-val")`, a.FullName)
}
return ""
}
type Signal struct {
// Enabled defines whether the signal is enabled by default.
Enabled bool `mapstructure:"enabled"`
// Warnings that will be shown to user under specified conditions.
Warnings Warnings `mapstructure:"warnings"`
// Description of the signal.
Description string `mapstructure:"description"`
// The semantic convention reference of the signal.
SemanticConvention *SemanticConvention `mapstructure:"semantic_convention"`
// The stability level of the signal.
Stability Stability `mapstructure:"stability"`
// Extended documentation of the signal. If specified, this will be appended to the description used in generated documentation.
ExtendedDocumentation string `mapstructure:"extended_documentation"`
// Attributes is the list of attributes that the signal emits.
Attributes []AttributeName `mapstructure:"attributes"`
}
func (s Signal) HasConditionalAttributes(attrs map[AttributeName]Attribute) bool {
for _, attr := range s.Attributes {
if v, exists := attrs[attr]; exists && v.IsConditional() {
return true
}
}
return false
}
type Entity struct {
// Type is the type of the entity.
Type string `mapstructure:"type"`
// Brief is a brief description of the entity.
Brief string `mapstructure:"brief"`
// Stability is the stability level of the entity.
Stability string `mapstructure:"stability"`
// Identity contains references to resource attributes that uniquely identify the entity.
Identity []EntityAttributeRef `mapstructure:"identity"`
// Description contains references to resource attributes that describe the entity.
Description []EntityAttributeRef `mapstructure:"description"`
}
type EntityAttributeRef struct {
// Ref is the reference to a resource attribute.
Ref AttributeName `mapstructure:"ref"`
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/metadata_test.go 0000664 0000000 0000000 00000020465 15113313446 0026052 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"io/fs"
"path/filepath"
"slices"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestValidate(t *testing.T) {
tests := []struct {
name string
wantErr string
}{
{
name: "testdata/no_type.yaml",
wantErr: "missing type",
},
{
name: "testdata/no_status.yaml",
wantErr: "missing status",
},
{
name: "testdata/no_class.yaml",
wantErr: "missing class",
},
{
name: "testdata/invalid_class.yaml",
wantErr: "invalid class: incorrectclass",
},
{
name: "testdata/no_stability.yaml",
wantErr: "missing stability",
},
{
name: "testdata/no_deprecation_info.yaml",
wantErr: "deprecated component missing deprecation date and migration guide for traces",
},
{
name: "testdata/no_deprecation_date_info.yaml",
wantErr: "deprecated component missing date in YYYY-MM-DD format: traces",
},
{
name: "testdata/no_deprecation_migration_info.yaml",
wantErr: "deprecated component missing migration guide: traces",
},
{
name: "testdata/deprecation_info_invalid_date.yaml",
wantErr: "deprecated component missing valid date in YYYY-MM-DD format: traces",
},
{
name: "testdata/invalid_stability.yaml",
wantErr: "decoding failed due to the following error(s):\n\n'status.stability' unsupported stability level: \"incorrectstability\"",
},
{
name: "testdata/no_stability_component.yaml",
wantErr: "missing component for stability: Beta",
},
{
name: "testdata/invalid_stability_component.yaml",
wantErr: "invalid component: incorrectcomponent",
},
{
name: "testdata/no_description_rattr.yaml",
wantErr: "empty description for resource attribute: string.resource.attr",
},
{
name: "testdata/no_type_rattr.yaml",
wantErr: "empty type for resource attribute: string.resource.attr",
},
{
name: "testdata/no_metric_description.yaml",
wantErr: "metric \"default.metric\": missing metric description",
},
{
name: "testdata/events/no_description.yaml",
wantErr: "event \"default.event\": missing event description",
},
{
name: "testdata/no_metric_unit.yaml",
wantErr: "metric \"default.metric\": missing metric unit",
},
{
name: "testdata/no_metric_type.yaml",
wantErr: "metric \"system.cpu.time\": missing metric type key, " +
"one of the following has to be specified: sum, gauge, histogram",
},
{
name: "testdata/two_metric_types.yaml",
wantErr: "metric \"system.cpu.time\": more than one metric type keys, " +
"only one of the following has to be specified: sum, gauge, histogram",
},
{
name: "testdata/invalid_input_type.yaml",
wantErr: "metric \"system.cpu.time\": invalid `input_type` value \"double\", must be \"\" or \"string\"",
},
{
name: "testdata/unknown_metric_attribute.yaml",
wantErr: "metric \"system.cpu.time\" refers to undefined attributes: [missing]",
},
{
name: "testdata/events/unknown_attribute.yaml",
wantErr: "event \"system.event\" refers to undefined attributes: [missing]",
},
{
name: "testdata/unused_attribute.yaml",
wantErr: "unused attributes: [unused_attr]",
},
{
name: "testdata/no_description_attr.yaml",
wantErr: "missing attribute description for: string_attr",
},
{
name: "testdata/no_type_attr.yaml",
wantErr: "empty type for attribute: used_attr",
},
{
name: "testdata/entity_undefined_id_attribute.yaml",
wantErr: `entity "host": identity refers to undefined resource attribute: host.missing`,
},
{
name: "testdata/entity_undefined_description_attribute.yaml",
wantErr: `entity "host": description refers to undefined resource attribute: host.missing`,
},
{
name: "testdata/entity_empty_id_attributes.yaml",
wantErr: `entity "host": identity is required`,
},
{
name: "testdata/entity_duplicate_attributes.yaml",
wantErr: `attribute host.name is already used by entity`,
},
{
name: "testdata/entity_duplicate_types.yaml",
wantErr: `duplicate entity type: host`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := LoadMetadata(tt.name)
require.Error(t, err)
require.ErrorContains(t, err, tt.wantErr)
})
}
}
func TestValidateMetricDuplicates(t *testing.T) {
allowedMetrics := map[string][]string{
"container.cpu.utilization": {"docker_stats", "kubeletstats"},
"container.memory.rss": {"docker_stats", "kubeletstats"},
"container.uptime": {"docker_stats", "kubeletstats"},
}
allMetrics := map[string][]string{}
err := filepath.Walk("../../../receiver", func(path string, info fs.FileInfo, _ error) error {
if info.Name() == "metadata.yaml" {
md, err := LoadMetadata(path)
require.NoError(t, err)
if len(md.Metrics) > 0 {
for metricName := range md.Metrics {
allMetrics[md.Type] = append(allMetrics[md.Type], string(metricName))
}
}
}
return nil
})
require.NoError(t, err)
seen := make(map[string]string)
for receiver, metrics := range allMetrics {
for _, metricName := range metrics {
if val, exists := seen[metricName]; exists {
receivers, allowed := allowedMetrics[metricName]
assert.Truef(
t,
allowed && slices.Contains(receivers, receiver) && slices.Contains(receivers, val),
"Duplicate metric %v in receivers %v and %v. Please validate that this is intentional by adding the metric name and receiver types in the allowedMetrics map in this test\n", metricName, receiver, val,
)
}
seen[metricName] = receiver
}
}
}
func TestSupportsSignal(t *testing.T) {
md := Metadata{}
assert.False(t, md.supportsSignal("logs"))
}
func TestCodeCovID(t *testing.T) {
tests := []struct {
md Metadata
want string
}{
{
md: Metadata{
Type: "aes",
Status: &Status{
Class: "provider",
CodeCovComponentID: "my_custom_id",
},
},
want: "my_custom_id",
},
{
md: Metadata{
Type: "count",
Status: &Status{
Class: "connector",
},
},
want: "connector_count",
},
{
md: Metadata{
Type: "file",
Status: &Status{
Class: "exporter",
},
},
want: "exporter_file",
},
}
for _, tt := range tests {
t.Run(tt.md.Type, func(t *testing.T) {
got := tt.md.GetCodeCovComponentID()
assert.Equal(t, tt.want, got)
})
}
}
func TestAttributeRequirementLevel(t *testing.T) {
tests := []struct {
name string
requirementLevel AttributeRequirementLevel
wantConditional bool
}{
{
name: "required",
requirementLevel: AttributeRequirementLevelRequired,
wantConditional: false,
},
{
name: "conditionally_required",
requirementLevel: AttributeRequirementLevelConditionallyRequired,
wantConditional: true,
},
{
name: "recommended",
requirementLevel: AttributeRequirementLevelRecommended,
wantConditional: false,
},
{
name: "opt_in",
requirementLevel: AttributeRequirementLevelOptIn,
wantConditional: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
attr := Attribute{RequirementLevel: tt.requirementLevel}
assert.Equal(t, tt.wantConditional, attr.IsConditional())
})
}
}
func TestAttributeRequirementLevelUnmarshalText(t *testing.T) {
tests := []struct {
name string
input string
want AttributeRequirementLevel
wantErr bool
}{
{
name: "required",
input: "required",
want: AttributeRequirementLevelRequired,
},
{
name: "conditionally_required",
input: "conditionally_required",
want: AttributeRequirementLevelConditionallyRequired,
},
{
name: "recommended",
input: "recommended",
want: AttributeRequirementLevelRecommended,
},
{
name: "opt_in",
input: "opt_in",
want: AttributeRequirementLevelOptIn,
},
{
name: "empty defaults to recommended",
input: "",
want: AttributeRequirementLevelRecommended,
},
{
name: "invalid value",
input: "invalid",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var rl AttributeRequirementLevel
err := rl.UnmarshalText([]byte(tt.input))
if tt.wantErr {
assert.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, rl)
})
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/metric.go 0000664 0000000 0000000 00000026365 15113313446 0024523 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"errors"
"fmt"
"regexp"
"strings"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/pdata/pmetric"
)
var reNonAlnum = regexp.MustCompile(`[^a-z0-9]+`)
type MetricName string
func (mn MetricName) Render() (string, error) {
return FormatIdentifier(string(mn), true)
}
func (mn MetricName) RenderUnexported() (string, error) {
return FormatIdentifier(string(mn), false)
}
type Metric struct {
Signal `mapstructure:",squash"`
// Optional can be used to specify metrics that may
// or may not be present in all cases, depending on configuration.
Optional bool `mapstructure:"optional"`
// Unit of the metric.
Unit *string `mapstructure:"unit"`
// Sum stores metadata for sum metric type
Sum *Sum `mapstructure:"sum,omitempty"`
// Gauge stores metadata for gauge metric type
Gauge *Gauge `mapstructure:"gauge,omitempty"`
// Histogram stores metadata for histogram metric type
Histogram *Histogram `mapstructure:"histogram,omitempty"`
// Override the default prefix for the metric name.
Prefix string `mapstructure:"prefix"`
}
type Stability struct {
Level component.StabilityLevel `mapstructure:"level"`
From string `mapstructure:"from"`
}
func (s Stability) String() string {
if s.Level == component.StabilityLevelUndefined ||
s.Level == component.StabilityLevelStable {
return ""
}
if s.From != "" {
return fmt.Sprintf(" [%s since %s]", s.Level.String(), s.From)
}
return fmt.Sprintf(" [%s]", s.Level.String())
}
func (s *Stability) Unmarshal(parser *confmap.Conf) error {
if !parser.IsSet("level") {
return errors.New("missing required field: `stability.level`")
}
return parser.Unmarshal(s)
}
func (m *Metric) validate(metricName MetricName, semConvVersion string) error {
var errs error
if m.Sum == nil && m.Gauge == nil && m.Histogram == nil {
errs = errors.Join(errs, errors.New("missing metric type key, "+
"one of the following has to be specified: sum, gauge, histogram"))
}
if (m.Sum != nil && m.Gauge != nil) || (m.Sum != nil && m.Histogram != nil) || (m.Gauge != nil && m.Histogram != nil) {
errs = errors.Join(errs, errors.New("more than one metric type keys, "+
"only one of the following has to be specified: sum, gauge, histogram"))
}
if m.Description == "" {
errs = errors.Join(errs, errors.New(`missing metric description`))
}
if m.Unit == nil {
errs = errors.Join(errs, errors.New(`missing metric unit`))
}
if m.Sum != nil {
errs = errors.Join(errs, m.Sum.Validate())
}
if m.Gauge != nil {
errs = errors.Join(errs, m.Gauge.Validate())
}
if m.SemanticConvention != nil {
if err := validateSemConvMetricURL(m.SemanticConvention.SemanticConventionRef, semConvVersion, string(metricName)); err != nil {
errs = errors.Join(errs, err)
}
}
return errs
}
func metricAnchor(metricName string) string {
m := strings.ToLower(strings.TrimSpace(metricName))
m = reNonAlnum.ReplaceAllString(m, "")
return "metric-" + m
}
// validateSemConvMetricURL verifies the URL matches exactly:
// https://github.com/open-telemetry/semantic-conventions/blob//*#metric-
func validateSemConvMetricURL(rawURL, semConvVersion, metricName string) error {
if strings.TrimSpace(rawURL) == "" {
return errors.New("url is empty")
}
if strings.TrimSpace(semConvVersion) == "" {
return errors.New("semConvVersion is empty")
}
if strings.TrimSpace(metricName) == "" {
return errors.New("metricName is empty")
}
semConvVersion = "v" + semConvVersion
anchor := metricAnchor(metricName)
// Build a strict regex that enforces https, repo, blob, given version, any doc path, and exact anchor.
pattern := fmt.Sprintf(`^https://github\.com/open-telemetry/semantic-conventions/blob/%s/[^#\s]+#%s$`,
semConvVersion,
anchor,
)
re := regexp.MustCompile(pattern)
if !re.MatchString(rawURL) {
return fmt.Errorf(
"invalid semantic-conventions URL: want https://github.com/open-telemetry/semantic-conventions/blob/%s/*#%s, got %q",
semConvVersion, anchor, rawURL)
}
return nil
}
func (m *Metric) Unmarshal(parser *confmap.Conf) error {
if !parser.IsSet("enabled") {
return errors.New("missing required field: `enabled`")
}
if !parser.IsSet("stability") {
return errors.New("missing required field: `stability`")
}
return parser.Unmarshal(m)
}
func (m Metric) Data() MetricData {
if m.Sum != nil {
return m.Sum
}
if m.Gauge != nil {
return m.Gauge
}
if m.Histogram != nil {
return m.Histogram
}
return nil
}
// MetricData is generic interface for all metric datatypes.
type MetricData interface {
Type() string
HasMonotonic() bool
HasAggregated() bool
HasMetricInputType() bool
Instrument() string
IsAsync() bool
}
// AggregationTemporality defines a metric aggregation type.
type AggregationTemporality struct {
// Aggregation describes if the aggregator reports delta changes
// since last report time, or cumulative changes since a fixed start time.
Aggregation pmetric.AggregationTemporality
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (agg *AggregationTemporality) UnmarshalText(text []byte) error {
switch vtStr := string(text); vtStr {
case "cumulative":
agg.Aggregation = pmetric.AggregationTemporalityCumulative
case "delta":
agg.Aggregation = pmetric.AggregationTemporalityDelta
default:
return fmt.Errorf("invalid aggregation: %q", vtStr)
}
return nil
}
// String returns string representation of the aggregation temporality.
func (agg *AggregationTemporality) String() string {
return agg.Aggregation.String()
}
// Mono defines the metric monotonicity.
type Mono struct {
// Monotonic is true if the sum is monotonic.
Monotonic bool `mapstructure:"monotonic"`
}
// MetricInputType defines the metric input value type
type MetricInputType struct {
// InputType is the type the metric needs to be parsed from, options are "string"
InputType string `mapstructure:"input_type"`
}
func (mit MetricInputType) HasMetricInputType() bool {
return mit.InputType != ""
}
// String returns name of the datapoint type.
func (mit MetricInputType) String() string {
return mit.InputType
}
func (mit MetricInputType) Validate() error {
if mit.InputType != "" && mit.InputType != "string" {
return fmt.Errorf("invalid `input_type` value \"%v\", must be \"\" or \"string\"", mit.InputType)
}
return nil
}
// MetricValueType defines the metric number type.
type MetricValueType struct {
// ValueType is type of the metric number, options are "double", "int".
ValueType pmetric.NumberDataPointValueType
}
func (mvt *MetricValueType) Unmarshal(parser *confmap.Conf) error {
if !parser.IsSet("value_type") {
return errors.New("missing required field: `value_type`")
}
return nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (mvt *MetricValueType) UnmarshalText(text []byte) error {
switch vtStr := string(text); vtStr {
case "int":
mvt.ValueType = pmetric.NumberDataPointValueTypeInt
case "double":
mvt.ValueType = pmetric.NumberDataPointValueTypeDouble
default:
return fmt.Errorf("invalid value_type: %q", vtStr)
}
return nil
}
// String returns name of the datapoint type.
func (mvt MetricValueType) String() string {
return mvt.ValueType.String()
}
// BasicType returns name of a golang basic type for the datapoint type.
func (mvt MetricValueType) BasicType() string {
switch mvt.ValueType {
case pmetric.NumberDataPointValueTypeInt:
return "int64"
case pmetric.NumberDataPointValueTypeDouble:
return "float64"
case pmetric.NumberDataPointValueTypeEmpty:
return ""
default:
return ""
}
}
var _ MetricData = (*Gauge)(nil)
type Gauge struct {
MetricValueType `mapstructure:"value_type"`
MetricInputType `mapstructure:",squash"`
Async bool `mapstructure:"async,omitempty"`
}
// Unmarshal is a custom unmarshaler for gauge. Needed mostly to avoid MetricValueType.Unmarshal inheritance.
func (d *Gauge) Unmarshal(parser *confmap.Conf) error {
if err := d.MetricValueType.Unmarshal(parser); err != nil {
return err
}
return parser.Unmarshal(d, confmap.WithIgnoreUnused())
}
func (d *Gauge) Type() string {
return "Gauge"
}
func (d *Gauge) HasMonotonic() bool {
return false
}
func (d *Gauge) HasAggregated() bool {
return false
}
func (d *Gauge) Instrument() string {
instrumentName := cases.Title(language.English).String(d.BasicType())
if d.Async {
instrumentName += "Observable"
}
instrumentName += "Gauge"
return instrumentName
}
func (d *Gauge) IsAsync() bool {
return d.Async
}
var _ MetricData = (*Sum)(nil)
type Sum struct {
AggregationTemporality `mapstructure:"aggregation_temporality"`
Mono `mapstructure:",squash"`
MetricValueType `mapstructure:"value_type"`
MetricInputType `mapstructure:",squash"`
Async bool `mapstructure:"async,omitempty"`
}
// Unmarshal is a custom unmarshaler for sum. Needed mostly to avoid MetricValueType.Unmarshal inheritance.
func (d *Sum) Unmarshal(parser *confmap.Conf) error {
if err := d.MetricValueType.Unmarshal(parser); err != nil {
return err
}
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
// add a test case to Test_LoadMetadata for file no_monotonic.yaml once the issue is solved.
//
// Unmarshal is a custom unmarshaler for Mono.
// func (m *Mono) Unmarshal(parser *confmap.Conf) error {
// if !parser.IsSet("monotonic") {
// return errors.New("missing required field: `monotonic`")
// }
// return parser.Unmarshal(m)
// }
func (d *Sum) Type() string {
return "Sum"
}
func (d *Sum) HasMonotonic() bool {
return true
}
func (d *Sum) HasAggregated() bool {
return true
}
func (d *Sum) Instrument() string {
instrumentName := cases.Title(language.English).String(d.BasicType())
if d.Async {
instrumentName += "Observable"
}
if !d.Monotonic {
instrumentName += "UpDown"
}
instrumentName += "Counter"
return instrumentName
}
func (d *Sum) IsAsync() bool {
return d.Async
}
var _ MetricData = (*Histogram)(nil)
type Histogram struct {
AggregationTemporality `mapstructure:"aggregation_temporality"`
Mono `mapstructure:",squash"`
MetricValueType `mapstructure:"value_type"`
MetricInputType `mapstructure:",squash"`
Async bool `mapstructure:"async,omitempty"`
Boundaries []float64 `mapstructure:"bucket_boundaries"`
}
func (d *Histogram) Type() string {
return "Histogram"
}
func (d *Histogram) HasMonotonic() bool {
return false
}
func (d *Histogram) HasAggregated() bool {
return true
}
func (d *Histogram) Instrument() string {
instrumentName := cases.Title(language.English).String(d.BasicType())
return instrumentName + d.Type()
}
// Unmarshal is a custom unmarshaler for histogram. Needed mostly to avoid MetricValueType.Unmarshal inheritance.
func (d *Histogram) Unmarshal(parser *confmap.Conf) error {
if err := d.MetricValueType.Unmarshal(parser); err != nil {
return err
}
return parser.Unmarshal(d, confmap.WithIgnoreUnused())
}
func (d *Histogram) IsAsync() bool {
return d.Async
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/metric_test.go 0000664 0000000 0000000 00000003351 15113313446 0025550 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/pmetric"
)
func TestMetricData(t *testing.T) {
for _, arg := range []struct {
metricData MetricData
wantType string
wantHasAggregated bool
wantHasMonotonic bool
wantInstrument string
wantAsync bool
}{
{&Gauge{}, "Gauge", false, false, "Gauge", false},
{&Gauge{Async: true}, "Gauge", false, false, "ObservableGauge", true},
{&Gauge{MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt}, Async: true}, "Gauge", false, false, "Int64ObservableGauge", true},
{&Gauge{MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble}, Async: true}, "Gauge", false, false, "Float64ObservableGauge", true},
{&Sum{}, "Sum", true, true, "UpDownCounter", false},
{&Sum{Mono: Mono{true}}, "Sum", true, true, "Counter", false},
{&Sum{Async: true}, "Sum", true, true, "ObservableUpDownCounter", true},
{&Sum{MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeInt}, Async: true}, "Sum", true, true, "Int64ObservableUpDownCounter", true},
{&Sum{MetricValueType: MetricValueType{pmetric.NumberDataPointValueTypeDouble}, Async: true}, "Sum", true, true, "Float64ObservableUpDownCounter", true},
{&Histogram{}, "Histogram", true, false, "Histogram", false},
} {
assert.Equal(t, arg.wantType, arg.metricData.Type())
assert.Equal(t, arg.wantHasAggregated, arg.metricData.HasAggregated())
assert.Equal(t, arg.wantHasMonotonic, arg.metricData.HasMonotonic())
assert.Equal(t, arg.wantInstrument, arg.metricData.Instrument())
assert.Equal(t, arg.wantAsync, arg.metricData.IsAsync())
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/ 0000775 0000000 0000000 00000000000 15113313446 0026071 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/doc.go 0000664 0000000 0000000 00000000476 15113313446 0027174 0 ustar 00root root 0000000 0000000 // 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
package sampleconnector // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleconnector"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/documentation.md 0000664 0000000 0000000 00000011061 15113313446 0031263 0 ustar 00root root 0000000 0000000 [comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
# sample
## Default Metrics
The following metrics are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
metrics:
:
enabled: false
```
### default.metric
Monotonic cumulative sum int metric enabled by default.
The metric will be become optional soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Int | Cumulative | true | Development |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| state | Integer attribute with overridden name. | Any Int | Recommended |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | Recommended |
| slice_attr | Attribute with a slice value. | Any Slice | Recommended |
| map_attr | Attribute with a map value. | Any Map | Recommended |
### default.metric.to_be_removed
[DEPRECATED] Non-monotonic delta sum double metric enabled by default.
The metric will be removed soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Double | Delta | false | Deprecated |
### metric.input_type
Monotonic cumulative sum int metric with string input_type enabled by default.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Int | Cumulative | true | Development |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| state | Integer attribute with overridden name. | Any Int | Recommended |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | Recommended |
| slice_attr | Attribute with a slice value. | Any Slice | Recommended |
| map_attr | Attribute with a map value. | Any Map | Recommended |
## Optional Metrics
The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
metrics:
:
enabled: true
```
### optional.metric
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| 1 | Gauge | Double | Deprecated |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| boolean_attr | Attribute with a boolean value. | Any Bool | Recommended |
| boolean_attr2 | Another attribute with a boolean value. | Any Bool | Recommended |
### optional.metric.empty_unit
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| | Gauge | Double | Deprecated |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| boolean_attr | Attribute with a boolean value. | Any Bool | Recommended |
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| map.resource.attr | Resource attribute with a map value. | Any Map | true |
| optional.resource.attr | Explicitly disabled ResourceAttribute. | Any Str | false |
| slice.resource.attr | Resource attribute with a slice value. | Any Slice | true |
| string.enum.resource.attr | Resource attribute with a known set of string values. | Str: ``one``, ``two`` | true |
| string.resource.attr | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_disable_warning | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_remove_warning | Resource attribute with any string value. | Any Str | false |
| string.resource.attr_to_be_removed | Resource attribute with any string value. | Any Str | true |
## Entities
The following entities are defined for this component:
### test.entity
A test entity.
**Stability:** stable
**Identity Attributes:**
- `string.resource.attr`
**Description Attributes:**
- `map.resource.attr`
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/factory.go 0000664 0000000 0000000 00000002355 15113313446 0030074 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package sampleconnector // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleconnector"
import (
"context"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleconnector/internal/metadata"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/pdata/pmetric"
)
// NewFactory returns a connector.Factory for sample connector.
func NewFactory() connector.Factory {
return connector.NewFactory(
metadata.Type,
func() component.Config { return &struct{}{} },
connector.WithMetricsToMetrics(createMetricsToMetricsConnector, metadata.MetricsToMetricsStability))
}
func createMetricsToMetricsConnector(context.Context, connector.Settings, component.Config, consumer.Metrics) (connector.Metrics, error) {
return nopInstance, nil
}
var nopInstance = &nopConnector{}
type nopConnector struct {
component.StartFunc
component.ShutdownFunc
}
func (n nopConnector) Capabilities() consumer.Capabilities {
return consumer.Capabilities{MutatesData: false}
}
func (n nopConnector) ConsumeMetrics(context.Context, pmetric.Metrics) error {
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/generated_component_test.go 0000664 0000000 0000000 00000005575 15113313446 0033513 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
//go:build !freebsd && !illumos
package sampleconnector
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"
"go.opentelemetry.io/collector/pipeline"
)
var typ = component.MustNewType("sample")
func TestComponentFactoryType(t *testing.T) {
require.Equal(t, typ, NewFactory().Type())
}
func TestComponentConfigStruct(t *testing.T) {
require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()))
}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct {
createFn func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error)
name string
}{
{
name: "metrics_to_metrics",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewMetricsRouter(map[pipeline.ID]consumer.Metrics{pipeline.NewID(pipeline.SignalMetrics): consumertest.NewNop()})
return factory.CreateMetricsToMetrics(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, sub.Unmarshal(&cfg))
for _, tt := range tests {
t.Run(tt.name+"-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), connectortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
t.Run(tt.name+"-lifecycle", func(t *testing.T) {
firstConnector, err := tt.createFn(context.Background(), connectortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := newMdatagenNopHost()
require.NoError(t, err)
require.NoError(t, firstConnector.Start(context.Background(), host))
require.NoError(t, firstConnector.Shutdown(context.Background()))
secondConnector, err := tt.createFn(context.Background(), connectortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondConnector.Start(context.Background(), host))
require.NoError(t, secondConnector.Shutdown(context.Background()))
})
}
}
var _ component.Host = (*mdatagenNopHost)(nil)
type mdatagenNopHost struct{}
func newMdatagenNopHost() component.Host {
return &mdatagenNopHost{}
}
func (mnh *mdatagenNopHost) GetExtensions() map[component.ID]component.Component {
return nil
}
func (mnh *mdatagenNopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory {
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/generated_package_test.go 0000664 0000000 0000000 00000000256 15113313446 0033073 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package sampleconnector
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/ 0000775 0000000 0000000 00000000000 15113313446 0027705 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata/ 0000775 0000000 0000000 00000000000 15113313446 0031465 5 ustar 00root root 0000000 0000000 generated_config.go 0000664 0000000 0000000 00000010546 15113313446 0035226 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/filter"
)
// MetricConfig provides common config for a particular metric.
type MetricConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ms)
if err != nil {
return err
}
ms.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// MetricsConfig provides config for 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"`
}
func DefaultMetricsConfig() MetricsConfig {
return MetricsConfig{
DefaultMetric: MetricConfig{
Enabled: true,
},
DefaultMetricToBeRemoved: MetricConfig{
Enabled: true,
},
MetricInputType: MetricConfig{
Enabled: true,
},
OptionalMetric: MetricConfig{
Enabled: false,
},
OptionalMetricEmptyUnit: MetricConfig{
Enabled: false,
},
}
}
// ResourceAttributeConfig provides common config for a particular resource attribute.
type ResourceAttributeConfig struct {
Enabled bool `mapstructure:"enabled"`
// 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
}
func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(rac)
if err != nil {
return err
}
rac.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// ResourceAttributesConfig provides config for sample resource attributes.
type ResourceAttributesConfig struct {
MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"`
OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"`
SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"`
StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"`
StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"`
StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"`
StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"`
StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"`
}
func DefaultResourceAttributesConfig() ResourceAttributesConfig {
return ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
OptionalResourceAttr: ResourceAttributeConfig{
Enabled: false,
},
SliceResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringEnumResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrDisableWarning: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{
Enabled: false,
},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{
Enabled: true,
},
}
}
// MetricsBuilderConfig is a configuration for sample metrics builder.
type MetricsBuilderConfig struct {
Metrics MetricsConfig `mapstructure:"metrics"`
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
}
func DefaultMetricsBuilderConfig() MetricsBuilderConfig {
return MetricsBuilderConfig{
Metrics: DefaultMetricsConfig(),
ResourceAttributes: DefaultResourceAttributesConfig(),
}
}
generated_config_test.go 0000664 0000000 0000000 00000013004 15113313446 0036255 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
)
func TestMetricsBuilderConfig(t *testing.T) {
tests := []struct {
name string
want MetricsBuilderConfig
}{
{
name: "default",
want: DefaultMetricsBuilderConfig(),
},
{
name: "all_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: true},
DefaultMetricToBeRemoved: MetricConfig{Enabled: true},
MetricInputType: MetricConfig{Enabled: true},
OptionalMetric: MetricConfig{Enabled: true},
OptionalMetricEmptyUnit: MetricConfig{Enabled: true},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
},
{
name: "none_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: false},
DefaultMetricToBeRemoved: MetricConfig{Enabled: false},
MetricInputType: MetricConfig{Enabled: false},
OptionalMetric: MetricConfig{Enabled: false},
OptionalMetricEmptyUnit: MetricConfig{Enabled: false},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadMetricsBuilderConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultMetricsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
func TestResourceAttributesConfig(t *testing.T) {
tests := []struct {
name string
want ResourceAttributesConfig
}{
{
name: "default",
want: DefaultResourceAttributesConfig(),
},
{
name: "all_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
{
name: "none_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
sub, err = sub.Sub("resource_attributes")
require.NoError(t, err)
cfg := DefaultResourceAttributesConfig()
require.NoError(t, sub.Unmarshal(&cfg))
return cfg
}
generated_metrics.go 0000664 0000000 0000000 00000063623 15113313446 0035433 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"fmt"
"strconv"
"time"
conventions "go.opentelemetry.io/otel/semconv/v1.9.0"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/filter"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)
// AttributeEnumAttr specifies the value enum_attr attribute.
type AttributeEnumAttr int
const (
_ AttributeEnumAttr = iota
AttributeEnumAttrRed
AttributeEnumAttrGreen
AttributeEnumAttrBlue
)
// String returns the string representation of the AttributeEnumAttr.
func (av AttributeEnumAttr) String() string {
switch av {
case AttributeEnumAttrRed:
return "red"
case AttributeEnumAttrGreen:
return "green"
case AttributeEnumAttrBlue:
return "blue"
}
return ""
}
// MapAttributeEnumAttr is a helper map of string to AttributeEnumAttr attribute value.
var MapAttributeEnumAttr = map[string]AttributeEnumAttr{
"red": AttributeEnumAttrRed,
"green": AttributeEnumAttrGreen,
"blue": AttributeEnumAttrBlue,
}
var MetricsInfo = metricsInfo{
DefaultMetric: metricInfo{
Name: "default.metric",
},
DefaultMetricToBeRemoved: metricInfo{
Name: "default.metric.to_be_removed",
},
MetricInputType: metricInfo{
Name: "metric.input_type",
},
OptionalMetric: metricInfo{
Name: "optional.metric",
},
OptionalMetricEmptyUnit: metricInfo{
Name: "optional.metric.empty_unit",
},
}
type metricsInfo struct {
DefaultMetric metricInfo
DefaultMetricToBeRemoved metricInfo
MetricInputType metricInfo
OptionalMetric metricInfo
OptionalMetricEmptyUnit metricInfo
}
type metricInfo struct {
Name string
}
type metricDefaultMetric struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric metric with initial data.
func (m *metricDefaultMetric) init() {
m.data.SetName("default.metric")
m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(true)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
m.data.Sum().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricDefaultMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetIntValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutInt("state", overriddenIntAttrAttributeValue)
dp.Attributes().PutStr("enum_attr", enumAttrAttributeValue)
dp.Attributes().PutEmptySlice("slice_attr").FromRaw(sliceAttrAttributeValue)
dp.Attributes().PutEmptyMap("map_attr").FromRaw(mapAttrAttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetric) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetric(cfg MetricConfig) metricDefaultMetric {
m := metricDefaultMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricDefaultMetricToBeRemoved struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric.to_be_removed metric with initial data.
func (m *metricDefaultMetricToBeRemoved) init() {
m.data.SetName("default.metric.to_be_removed")
m.data.SetDescription("[DEPRECATED] Non-monotonic delta sum double metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(false)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
}
func (m *metricDefaultMetricToBeRemoved) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetricToBeRemoved) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetricToBeRemoved) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBeRemoved {
m := metricDefaultMetricToBeRemoved{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type 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.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric metric with initial data.
func (m *metricOptionalMetric) init() {
m.data.SetName("optional.metric")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("1")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr2", booleanAttr2AttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetric) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetric(cfg MetricConfig) metricOptionalMetric {
m := metricOptionalMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricOptionalMetricEmptyUnit struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric.empty_unit metric with initial data.
func (m *metricOptionalMetricEmptyUnit) init() {
m.data.SetName("optional.metric.empty_unit")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetricEmptyUnit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetricEmptyUnit) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetricEmptyUnit) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetricEmptyUnit(cfg MetricConfig) metricOptionalMetricEmptyUnit {
m := metricOptionalMetricEmptyUnit{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations
// required to produce metric representation defined in metadata and user config.
type MetricsBuilder struct {
config MetricsBuilderConfig // config of the metrics builder.
startTime pcommon.Timestamp // start time that will be applied to all recorded data points.
metricsCapacity int // maximum observed number of metrics per resource.
metricsBuffer pmetric.Metrics // accumulates metrics data before emitting.
buildInfo component.BuildInfo // contains version information.
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
metricDefaultMetric metricDefaultMetric
metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved
metricMetricInputType metricMetricInputType
metricOptionalMetric metricOptionalMetric
metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit
}
// MetricBuilderOption applies changes to default metrics builder.
type MetricBuilderOption interface {
apply(*MetricsBuilder)
}
type metricBuilderOptionFunc func(mb *MetricsBuilder)
func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) {
mbof(mb)
}
// WithStartTime sets startTime on the metrics builder.
func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption {
return metricBuilderOptionFunc(func(mb *MetricsBuilder) {
mb.startTime = startTime
})
}
func NewMetricsBuilder(mbc MetricsBuilderConfig, settings connector.Settings, options ...MetricBuilderOption) *MetricsBuilder {
if !mbc.Metrics.DefaultMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.")
}
if mbc.Metrics.DefaultMetricToBeRemoved.Enabled {
settings.Logger.Warn("[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetricEmptyUnit.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.")
}
if !mbc.ResourceAttributes.StringResourceAttrDisableWarning.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.")
}
if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || 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 {
settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.")
}
mb := &MetricsBuilder{
config: mbc,
startTime: pcommon.NewTimestampFromTime(time.Now()),
metricsBuffer: pmetric.NewMetrics(),
buildInfo: settings.BuildInfo,
metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric),
metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved),
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.apply(mb)
}
return mb
}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics.
func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(mb.config.ResourceAttributes)
}
// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity.
func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) {
if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() {
mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len()
}
}
// ResourceMetricsOption applies changes to provided resource metrics.
type ResourceMetricsOption interface {
apply(pmetric.ResourceMetrics)
}
type resourceMetricsOptionFunc func(pmetric.ResourceMetrics)
func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) {
rmof(rm)
}
// WithResource sets the provided resource on the emitted ResourceMetrics.
// It's recommended to use ResourceBuilder to create the resource.
func WithResource(res pcommon.Resource) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
res.CopyTo(rm.Resource())
})
}
// WithStartTimeOverride overrides start time for all the resource metrics data points.
// This option should be only used if different start time has to be set on metrics coming from different resources.
func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
var dps pmetric.NumberDataPointSlice
metrics := rm.ScopeMetrics().At(0).Metrics()
for i := 0; i < metrics.Len(); i++ {
switch metrics.At(i).Type() {
case pmetric.MetricTypeGauge:
dps = metrics.At(i).Gauge().DataPoints()
case pmetric.MetricTypeSum:
dps = metrics.At(i).Sum().DataPoints()
}
for j := 0; j < dps.Len(); j++ {
dps.At(j).SetStartTimestamp(start)
}
}
})
}
// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for
// recording another set of data points as part of another resource. This function can be helpful when one scraper
// needs to emit metrics from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceMetricsOption arguments.
func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) {
rm := pmetric.NewResourceMetrics()
rm.SetSchemaUrl(conventions.SchemaURL)
ils := rm.ScopeMetrics().AppendEmpty()
ils.Scope().SetName(ScopeName)
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 options {
op.apply(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())
}
}
// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for
// recording another set of metrics. This function will be responsible for applying all the transformations required to
// produce metric representation defined in metadata and user config, e.g. delta or cumulative.
func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics {
mb.EmitForResource(options...)
metrics := mb.metricsBuffer
mb.metricsBuffer = pmetric.NewMetrics()
return metrics
}
// RecordDefaultMetricDataPoint adds a data point to default.metric metric.
func (mb *MetricsBuilder) RecordDefaultMetricDataPoint(ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) {
mb.metricDefaultMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue)
}
// RecordDefaultMetricToBeRemovedDataPoint adds a data point to default.metric.to_be_removed metric.
func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Timestamp, val float64) {
mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val)
}
// 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, booleanAttr2AttributeValue bool) {
mb.metricOptionalMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue, booleanAttr2AttributeValue)
}
// RecordOptionalMetricEmptyUnitDataPoint adds a data point to optional.metric.empty_unit metric.
func (mb *MetricsBuilder) RecordOptionalMetricEmptyUnitDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
mb.metricOptionalMetricEmptyUnit.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue)
}
// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted,
// and metrics builder should update its startTime and reset it's internal state accordingly.
func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) {
mb.startTime = pcommon.NewTimestampFromTime(time.Now())
for _, op := range options {
op.apply(mb)
}
}
generated_metrics_test.go 0000664 0000000 0000000 00000027431 15113313446 0036467 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/connector/connectortest"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)
type testDataSet int
const (
testDataSetDefault testDataSet = iota
testDataSetAll
testDataSetNone
)
func TestMetricsBuilder(t *testing.T) {
tests := []struct {
name string
metricsSet testDataSet
resAttrsSet testDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
metricsSet: testDataSetAll,
resAttrsSet: testDataSetAll,
},
{
name: "none_set",
metricsSet: testDataSetNone,
resAttrsSet: testDataSetNone,
expectEmpty: true,
},
{
name: "filter_set_include",
resAttrsSet: testDataSetAll,
},
{
name: "filter_set_exclude",
resAttrsSet: testDataSetAll,
expectEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
start := pcommon.Timestamp(1_000_000_000)
ts := pcommon.Timestamp(1_000_001_000)
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
settings := connectortest.NewNopSettings(connectortest.NopType)
settings.Logger = zap.New(observedZapCore)
mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start))
expectedWarnings := 0
if tt.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 tt.metricsSet == testDataSetDefault || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.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 tt.resAttrsSet == testDataSetAll || tt.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 tt.resAttrsSet == testDataSetDefault || tt.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++
}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultMetricsCount := 0
allMetricsCount := 0
defaultMetricsCount++
allMetricsCount++
mb.RecordDefaultMetricDataPoint(ts, 1, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"})
defaultMetricsCount++
allMetricsCount++
mb.RecordDefaultMetricToBeRemovedDataPoint(ts, 1)
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, false)
allMetricsCount++
mb.RecordOptionalMetricEmptyUnitDataPoint(ts, 1, "string_attr-val", true)
rb := mb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
metrics := mb.Emit(WithResource(res))
if tt.expectEmpty {
assert.Equal(t, 0, metrics.ResourceMetrics().Len())
return
}
assert.Equal(t, 1, metrics.ResourceMetrics().Len())
rm := metrics.ResourceMetrics().At(0)
assert.Equal(t, res, rm.Resource())
assert.Equal(t, 1, rm.ScopeMetrics().Len())
ms := rm.ScopeMetrics().At(0).Metrics()
if tt.metricsSet == testDataSetDefault {
assert.Equal(t, defaultMetricsCount, ms.Len())
}
if tt.metricsSet == testDataSetAll {
assert.Equal(t, allMetricsCount, ms.Len())
}
validatedMetrics := make(map[string]bool)
for i := 0; i < ms.Len(); i++ {
switch ms.At(i).Name() {
case "default.metric":
assert.False(t, validatedMetrics["default.metric"], "Found a duplicate in the metrics slice: default.metric")
validatedMetrics["default.metric"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw())
case "default.metric.to_be_removed":
assert.False(t, validatedMetrics["default.metric.to_be_removed"], "Found a duplicate in the metrics slice: default.metric.to_be_removed")
validatedMetrics["default.metric.to_be_removed"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.False(t, ms.At(i).Sum().IsMonotonic())
assert.Equal(t, pmetric.AggregationTemporalityDelta, ms.At(i).Sum().AggregationTemporality())
dp := ms.At(i).Sum().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
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.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(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
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Equal(t, "1", ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
attrVal, ok = dp.Attributes().Get("boolean_attr2")
assert.True(t, ok)
assert.False(t, attrVal.Bool())
case "optional.metric.empty_unit":
assert.False(t, validatedMetrics["optional.metric.empty_unit"], "Found a duplicate in the metrics slice: optional.metric.empty_unit")
validatedMetrics["optional.metric.empty_unit"] = true
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Empty(t, ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
}
}
})
}
}
generated_resource.go 0000664 0000000 0000000 00000007632 15113313446 0035612 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/xpdata/entity"
)
// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml.
// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines.
type ResourceBuilder struct {
config ResourceAttributesConfig
res pcommon.Resource
}
// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application.
func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder {
return &ResourceBuilder{
config: rac,
res: pcommon.NewResource(),
}
}
// SetMapResourceAttr sets provided value as "map.resource.attr" attribute.
func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) {
if rb.config.MapResourceAttr.Enabled {
rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val)
}
}
// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute.
func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) {
if rb.config.OptionalResourceAttr.Enabled {
rb.res.Attributes().PutStr("optional.resource.attr", val)
}
}
// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute.
func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) {
if rb.config.SliceResourceAttr.Enabled {
rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val)
}
}
// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "one")
}
}
// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "two")
}
}
// SetStringResourceAttr sets provided value as "string.resource.attr" attribute.
func (rb *ResourceBuilder) SetStringResourceAttr(val string) {
if rb.config.StringResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.resource.attr", val)
}
}
// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) {
if rb.config.StringResourceAttrDisableWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val)
}
}
// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) {
if rb.config.StringResourceAttrRemoveWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val)
}
}
// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) {
if rb.config.StringResourceAttrToBeRemoved.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val)
}
}
// AssociateWithTestEntity associates the resource with entity type "test.entity".
// This method is experimental and will be replaced with an entity builder pattern in the future.
// However, for now, it allows associating resources with entities and producing correct entity references.
func (rb *ResourceBuilder) AssociateWithTestEntity() {
entityRef := entity.ResourceEntityRefs(rb.res).AppendEmpty()
entityRef.SetType("test.entity")
idKeys := entityRef.IdKeys()
idKeys.Append("string.resource.attr")
descKeys := entityRef.DescriptionKeys()
descKeys.Append("map.resource.attr")
}
// Emit returns the built resource and resets the internal builder state.
func (rb *ResourceBuilder) Emit() pcommon.Resource {
r := rb.res
rb.res = pcommon.NewResource()
return r
}
generated_resource_test.go 0000664 0000000 0000000 00000005421 15113313446 0036643 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestResourceBuilder(t *testing.T) {
for _, tt := range []string{"default", "all_set", "none_set"} {
t.Run(tt, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt)
rb := NewResourceBuilder(cfg)
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource
switch tt {
case "default":
assert.Equal(t, 6, res.Attributes().Len())
case "all_set":
assert.Equal(t, 8, res.Attributes().Len())
case "none_set":
assert.Equal(t, 0, res.Attributes().Len())
return
default:
assert.Failf(t, "unexpected test case: %s", tt)
}
val, ok := res.Attributes().Get("map.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw())
}
val, ok = res.Attributes().Get("optional.resource.attr")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "optional.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("slice.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw())
}
val, ok = res.Attributes().Get("string.enum.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "one", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_disable_warning")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_disable_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_remove_warning")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "string.resource.attr_remove_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_to_be_removed")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_to_be_removed-val", val.Str())
}
})
}
}
generated_status.go 0000664 0000000 0000000 00000000512 15113313446 0035274 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/component"
)
var (
Type = component.MustNewType("sample")
ScopeName = "go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleconnector"
)
const (
MetricsToMetricsStability = component.StabilityLevelDevelopment
)
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata/testdata/ 0000775 0000000 0000000 00000000000 15113313446 0033276 5 ustar 00root root 0000000 0000000 config.yaml 0000664 0000000 0000000 00000006215 15113313446 0035354 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/internal/metadata/testdata 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"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/metadata.yaml 0000664 0000000 0000000 00000011326 15113313446 0030540 0 ustar 00root root 0000000 0000000 # Sample metadata file with all available configurations for a connector.
type: sample
github_project: open-telemetry/opentelemetry-collector
sem_conv_version: 1.9.0
status:
disable_codecov_badge: true
class: connector
stability:
development: [metrics_to_metrics]
distributions: []
unsupported_platforms: [freebsd, illumos]
codeowners:
active: []
warnings:
- Any additional information that should be brought to the consumer's attention
resource_attributes:
map.resource.attr:
description: Resource attribute with a map value.
type: map
enabled: true
optional.resource.attr:
description: Explicitly disabled ResourceAttribute.
type: string
enabled: false
slice.resource.attr:
description: Resource attribute with a slice value.
type: slice
enabled: true
string.enum.resource.attr:
description: Resource attribute with a known set of string values.
type: string
enum: [one, two]
enabled: true
string.resource.attr:
description: Resource attribute with any string value.
type: string
enabled: true
string.resource.attr_disable_warning:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled_not_set: This resource_attribute will be disabled by default soon.
string.resource.attr_remove_warning:
description: Resource attribute with any string value.
type: string
enabled: false
warnings:
if_configured: This resource_attribute is deprecated and will be removed soon.
string.resource.attr_to_be_removed:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled: This resource_attribute is deprecated and will be removed soon.
entities:
- type: test.entity
brief: A test entity.
stability: stable
identity:
- ref: string.resource.attr
description:
- ref: map.resource.attr
attributes:
boolean_attr:
description: Attribute with a boolean value.
type: bool
# This 2nd boolean attribute allows us to test both values for boolean attributes,
# as test values are based on the parity of the attribute name length.
boolean_attr2:
description: Another attribute with a boolean value.
type: bool
enum_attr:
description: Attribute with a known set of string values.
type: string
enum: [red, green, blue]
map_attr:
description: Attribute with a map value.
type: map
overridden_int_attr:
name_override: state
description: Integer attribute with overridden name.
type: int
slice_attr:
description: Attribute with a slice value.
type: slice
string_attr:
description: Attribute with any string value.
type: string
metrics:
default.metric:
enabled: true
description: Monotonic cumulative sum int metric enabled by default.
extended_documentation: The metric will be become optional soon.
stability:
level: development
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
attributes:
[string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr]
warnings:
if_enabled_not_set: This metric will be disabled by default soon.
default.metric.to_be_removed:
enabled: true
description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default."
extended_documentation: The metric will be removed soon.
stability:
level: deprecated
unit: s
sum:
value_type: double
monotonic: false
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.
stability:
level: development
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]
optional.metric:
enabled: false
description: "[DEPRECATED] Gauge double metric disabled by default."
stability:
level: deprecated
unit: "1"
gauge:
value_type: double
attributes: [string_attr, boolean_attr, boolean_attr2]
warnings:
if_configured: This metric is deprecated and will be removed soon.
optional.metric.empty_unit:
enabled: false
description: "[DEPRECATED] Gauge double metric disabled by default."
stability:
level: deprecated
unit: ""
gauge:
value_type: double
attributes: [string_attr, boolean_attr]
warnings:
if_configured: This metric is deprecated and will be removed soon.
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleconnector/metrics_test.go 0000664 0000000 0000000 00000002145 15113313446 0031127 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package sampleconnector
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleconnector/internal/metadata"
"go.opentelemetry.io/collector/connector/connectortest"
"go.opentelemetry.io/collector/consumer/consumertest"
"go.opentelemetry.io/collector/pdata/pmetric"
)
// TestGeneratedMetrics verifies that the internal/metadata API is generated correctly.
func TestGeneratedMetrics(t *testing.T) {
mb := metadata.NewMetricsBuilder(metadata.DefaultMetricsBuilderConfig(), connectortest.NewNopSettings(metadata.Type))
m := mb.Emit()
require.Equal(t, 0, m.ResourceMetrics().Len())
}
func TestNopConnector(t *testing.T) {
connector, err := createMetricsToMetricsConnector(context.Background(), connectortest.NewNopSettings(metadata.Type), newMdatagenNopHost(), new(consumertest.MetricsSink))
require.NoError(t, err)
require.False(t, connector.Capabilities().MutatesData)
require.NoError(t, connector.ConsumeMetrics(context.Background(), pmetric.NewMetrics()))
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/ 0000775 0000000 0000000 00000000000 15113313446 0027273 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/README.md 0000664 0000000 0000000 00000004454 15113313446 0030561 0 ustar 00root root 0000000 0000000 # Sample Receiver
This receiver is used for testing purposes to check the output of mdatagen.
| Status | |
| ------------- |-----------|
| Stability | [deprecated]: profiles |
| | [development]: logs |
| | [beta]: traces |
| | [stable]: metrics |
| Deprecation of profiles | [Date]: 2025-02-05 |
| | [Migration Note]: no migration needed |
| Unsupported Platforms | freebsd, illumos |
| Distributions | [] |
| Warnings | [Any additional information that should be brought to the consumer's attention](#warnings) |
| Issues | [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fsamplefactory) [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fsamplefactory) |
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@dmitryax](https://www.github.com/dmitryax) |
[deprecated]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecated
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
[beta]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#beta
[stable]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stable
[Date]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecation-information
[Migration Note]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecation-information
## Warnings
This is where warnings are described.
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/doc.go 0000664 0000000 0000000 00000000512 15113313446 0030365 0 ustar 00root root 0000000 0000000 // 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
package samplefactoryreceiver // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplefactoryreceiver"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/documentation.md 0000664 0000000 0000000 00000016645 15113313446 0032502 0 ustar 00root root 0000000 0000000 [comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
# sample
## Default Metrics
The following metrics are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
metrics:
:
enabled: false
```
### default.metric
Monotonic cumulative sum int metric enabled by default.
The metric will be become optional soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic |
| ---- | ----------- | ---------- | ----------------------- | --------- |
| s | Sum | Int | Cumulative | true |
#### Attributes
| Name | Description | Values | Optional |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | false |
| state | Integer attribute with overridden name. | Any Int | false |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | false |
| slice_attr | Attribute with a slice value. | Any Slice | false |
| map_attr | Attribute with a map value. | Any Map | false |
| optional_int_attr | An optional attribute with an integer value | Any Int | true |
| optional_string_attr | An optional attribute with any string value | Any Str | true |
### default.metric.to_be_removed
[DEPRECATED] Non-monotonic delta sum double metric enabled by default.
The metric will be removed soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic |
| ---- | ----------- | ---------- | ----------------------- | --------- |
| 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 | Optional |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | false |
| state | Integer attribute with overridden name. | Any Int | false |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | false |
| slice_attr | Attribute with a slice value. | Any Slice | false |
| map_attr | Attribute with a map value. | Any Map | false |
## Optional Metrics
The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
metrics:
:
enabled: true
```
### optional.metric
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Double |
#### Attributes
| Name | Description | Values | Optional |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | false |
| boolean_attr | Attribute with a boolean value. | Any Bool | false |
| boolean_attr2 | Another attribute with a boolean value. | Any Bool | false |
| optional_string_attr | An optional attribute with any string value | Any Str | true |
### optional.metric.empty_unit
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| | Gauge | Double |
#### Attributes
| Name | Description | Values | Optional |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | false |
| boolean_attr | Attribute with a boolean value. | Any Bool | false |
## Default Events
The following events are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
events:
:
enabled: false
```
### default.event
Example event enabled by default.
#### 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_int_attr | An optional attribute with an integer value | Any Int |
| optional_string_attr | An optional attribute with any string value | Any Str |
### default.event.to_be_removed
[DEPRECATED] Example to-be-removed event enabled by default.
The event will be removed soon.
#### 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 Events
The following events are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
events:
:
enabled: true
```
### default.event.to_be_renamed
[DEPRECATED] Example event disabled by default.
The event will be renamed soon.
#### Attributes
| Name | Description | Values |
| ---- | ----------- | ------ |
| string_attr | Attribute with any string value. | Any Str |
| boolean_attr | Attribute with a boolean value. | Any Bool |
| boolean_attr2 | Another attribute with a boolean value. | Any Bool |
| optional_string_attr | An optional attribute with any string value | Any Str |
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| map.resource.attr | Resource attribute with a map value. | Any Map | true |
| optional.resource.attr | Explicitly disabled ResourceAttribute. | Any Str | false |
| slice.resource.attr | Resource attribute with a slice value. | Any Slice | true |
| string.enum.resource.attr | Resource attribute with a known set of string values. | Str: ``one``, ``two`` | true |
| string.resource.attr | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_disable_warning | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_remove_warning | Resource attribute with any string value. | Any Str | false |
| string.resource.attr_to_be_removed | Resource attribute with any string value. | Any Str | true |
## Internal Telemetry
The following telemetry is emitted by this component.
### otelcol_batch_size_trigger_send
Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]
| Unit | Metric Type | Value Type | Monotonic |
| ---- | ----------- | ---------- | --------- |
| {times} | Sum | Int | true |
### otelcol_process_runtime_total_alloc_bytes
Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')
| Unit | Metric Type | Value Type | Monotonic |
| ---- | ----------- | ---------- | --------- |
| By | Sum | Int | true |
### otelcol_queue_capacity
Queue capacity - sync gauge example.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| {items} | Gauge | Int |
### otelcol_queue_length
This metric is optional and therefore not initialized in NewTelemetryBuilder. [alpha]
For example this metric only exists if feature A is enabled.
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| {items} | Gauge | Int |
### otelcol_request_duration
Duration of request [alpha]
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| s | Histogram | Double |
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/factory.go 0000664 0000000 0000000 00000004424 15113313446 0031275 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package samplefactoryreceiver // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplefactoryreceiver"
import (
"context"
"errors"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/receiver"
"go.opentelemetry.io/collector/service/hostcapabilities"
)
// 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.Settings, component.Config, consumer.Traces) (receiver.Traces, error) {
return nopInstance, nil
}
func createMetrics(ctx context.Context, set receiver.Settings, _ component.Config, _ consumer.Metrics) (receiver.Metrics, error) {
telemetryBuilder, err := metadata.NewTelemetryBuilder(set.TelemetrySettings)
if err != nil {
return nil, err
}
err = telemetryBuilder.RegisterProcessRuntimeTotalAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error {
observer.Observe(2)
return nil
})
if err != nil {
return nil, err
}
telemetryBuilder.BatchSizeTriggerSend.Add(ctx, 1)
return nopReceiver{telemetryBuilder: telemetryBuilder}, nil
}
func createLogs(context.Context, receiver.Settings, component.Config, consumer.Logs) (receiver.Logs, error) {
return nopInstance, nil
}
var nopInstance = &nopReceiver{}
type nopReceiver struct {
component.StartFunc
telemetryBuilder *metadata.TelemetryBuilder
}
func (r nopReceiver) Start(_ context.Context, host component.Host) error {
if _, ok := host.(hostcapabilities.ComponentFactory); !ok {
return errors.New("host does not implement hostcapabilities.ComponentFactory")
}
return nil
}
// Shutdown shuts down the component.
func (r nopReceiver) Shutdown(context.Context) error {
if r.telemetryBuilder != nil {
r.telemetryBuilder.Shutdown()
}
return nil
}
generated_component_test.go 0000664 0000000 0000000 00000006056 15113313446 0034631 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver // Code generated by mdatagen. DO NOT EDIT.
//go:build !freebsd && !illumos
package samplefactoryreceiver
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"
)
var typ = component.MustNewType("sample")
func TestComponentFactoryType(t *testing.T) {
require.Equal(t, typ, NewFactory().Type())
}
func TestComponentConfigStruct(t *testing.T) {
require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()))
}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct {
createFn func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error)
name string
}{
{
name: "logs",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg, consumertest.NewNop())
},
},
{
name: "metrics",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg, consumertest.NewNop())
},
},
{
name: "traces",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(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, sub.Unmarshal(&cfg))
for _, tt := range tests {
t.Run(tt.name+"-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
t.Run(tt.name+"-lifecycle", func(t *testing.T) {
firstRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := newMdatagenNopHost()
require.NoError(t, err)
require.NoError(t, firstRcvr.Start(context.Background(), host))
require.NoError(t, firstRcvr.Shutdown(context.Background()))
secondRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondRcvr.Start(context.Background(), host))
require.NoError(t, secondRcvr.Shutdown(context.Background()))
})
}
}
var _ component.Host = (*mdatagenNopHost)(nil)
type mdatagenNopHost struct{}
func newMdatagenNopHost() component.Host {
return &mdatagenNopHost{}
}
func (mnh *mdatagenNopHost) GetExtensions() map[component.ID]component.Component {
return nil
}
func (mnh *mdatagenNopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory {
return nil
}
generated_package_test.go 0000664 0000000 0000000 00000000264 15113313446 0034215 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver // Code generated by mdatagen. DO NOT EDIT.
package samplefactoryreceiver
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/ 0000775 0000000 0000000 00000000000 15113313446 0031107 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata/ 0000775 0000000 0000000 00000000000 15113313446 0032667 5 ustar 00root root 0000000 0000000 generated_config.go 0000664 0000000 0000000 00000014344 15113313446 0036430 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/filter"
)
// MetricConfig provides common config for a particular metric.
type MetricConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ms)
if err != nil {
return err
}
ms.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// MetricsConfig provides config for 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"`
}
func DefaultMetricsConfig() MetricsConfig {
return MetricsConfig{
DefaultMetric: MetricConfig{
Enabled: true,
},
DefaultMetricToBeRemoved: MetricConfig{
Enabled: true,
},
MetricInputType: MetricConfig{
Enabled: true,
},
OptionalMetric: MetricConfig{
Enabled: false,
},
OptionalMetricEmptyUnit: MetricConfig{
Enabled: false,
},
}
}
// EventConfig provides common config for a particular event.
type EventConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ec *EventConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ec)
if err != nil {
return err
}
ec.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// EventsConfig provides config for sample events.
type EventsConfig struct {
DefaultEvent EventConfig `mapstructure:"default.event"`
DefaultEventToBeRemoved EventConfig `mapstructure:"default.event.to_be_removed"`
DefaultEventToBeRenamed EventConfig `mapstructure:"default.event.to_be_renamed"`
}
func DefaultEventsConfig() EventsConfig {
return EventsConfig{
DefaultEvent: EventConfig{
Enabled: true,
},
DefaultEventToBeRemoved: EventConfig{
Enabled: true,
},
DefaultEventToBeRenamed: EventConfig{
Enabled: false,
},
}
}
// 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"`
// Experimental: EventsInclude defines a list of filters for attribute values.
// If the list is not empty, only events with matching resource attribute values will be emitted.
EventsInclude []filter.Config `mapstructure:"events_include"`
// Experimental: EventsExclude defines a list of filters for attribute values.
// If the list is not empty, events with matching resource attribute values will not be emitted.
// EventsInclude has higher priority than EventsExclude.
EventsExclude []filter.Config `mapstructure:"events_exclude"`
enabledSetByUser bool
}
func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(rac)
if err != nil {
return err
}
rac.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// ResourceAttributesConfig provides config for sample resource attributes.
type ResourceAttributesConfig struct {
MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"`
OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"`
SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"`
StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"`
StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"`
StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"`
StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"`
StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"`
}
func DefaultResourceAttributesConfig() ResourceAttributesConfig {
return ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
OptionalResourceAttr: ResourceAttributeConfig{
Enabled: false,
},
SliceResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringEnumResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrDisableWarning: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{
Enabled: false,
},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{
Enabled: true,
},
}
}
// MetricsBuilderConfig is a configuration for sample metrics builder.
type MetricsBuilderConfig struct {
Metrics MetricsConfig `mapstructure:"metrics"`
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
}
func DefaultMetricsBuilderConfig() MetricsBuilderConfig {
return MetricsBuilderConfig{
Metrics: DefaultMetricsConfig(),
ResourceAttributes: DefaultResourceAttributesConfig(),
}
}
// LogsBuilderConfig is a configuration for sample logs builder.
type LogsBuilderConfig struct {
Events EventsConfig `mapstructure:"events"`
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
}
func DefaultLogsBuilderConfig() LogsBuilderConfig {
return LogsBuilderConfig{
Events: DefaultEventsConfig(),
ResourceAttributes: DefaultResourceAttributesConfig(),
}
}
generated_config_test.go 0000664 0000000 0000000 00000013534 15113313446 0037467 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
)
func TestMetricsBuilderConfig(t *testing.T) {
tests := []struct {
name string
want MetricsBuilderConfig
}{
{
name: "default",
want: DefaultMetricsBuilderConfig(),
},
{
name: "all_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: true},
DefaultMetricToBeRemoved: MetricConfig{Enabled: true},
MetricInputType: MetricConfig{Enabled: true},
OptionalMetric: MetricConfig{Enabled: true},
OptionalMetricEmptyUnit: MetricConfig{Enabled: true},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
},
{
name: "none_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: false},
DefaultMetricToBeRemoved: MetricConfig{Enabled: false},
MetricInputType: MetricConfig{Enabled: false},
OptionalMetric: MetricConfig{Enabled: false},
OptionalMetricEmptyUnit: MetricConfig{Enabled: false},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadMetricsBuilderConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultMetricsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
func loadLogsBuilderConfig(t *testing.T, name string) LogsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultLogsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
func TestResourceAttributesConfig(t *testing.T) {
tests := []struct {
name string
want ResourceAttributesConfig
}{
{
name: "default",
want: DefaultResourceAttributesConfig(),
},
{
name: "all_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
{
name: "none_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
sub, err = sub.Sub("resource_attributes")
require.NoError(t, err)
cfg := DefaultResourceAttributesConfig()
require.NoError(t, sub.Unmarshal(&cfg))
return cfg
}
generated_logs.go 0000664 0000000 0000000 00000006175 15113313446 0036132 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
conventions "go.opentelemetry.io/otel/semconv/v1.9.0"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/receiver"
)
// LogsBuilder provides an interface for scrapers to report logs while taking care of all the transformations
// required to produce log representation defined in metadata and user config.
type LogsBuilder struct {
logsBuffer plog.Logs
logRecordsBuffer plog.LogRecordSlice
buildInfo component.BuildInfo // contains version information.
}
// LogBuilderOption applies changes to default logs builder.
type LogBuilderOption interface {
apply(*LogsBuilder)
}
func NewLogsBuilder(settings receiver.Settings) *LogsBuilder {
lb := &LogsBuilder{
logsBuffer: plog.NewLogs(),
logRecordsBuffer: plog.NewLogRecordSlice(),
buildInfo: settings.BuildInfo,
}
return lb
}
// ResourceLogsOption applies changes to provided resource logs.
type ResourceLogsOption interface {
apply(plog.ResourceLogs)
}
type resourceLogsOptionFunc func(plog.ResourceLogs)
func (rlof resourceLogsOptionFunc) apply(rl plog.ResourceLogs) {
rlof(rl)
}
// WithLogsResource sets the provided resource on the emitted ResourceLogs.
// It's recommended to use ResourceBuilder to create the resource.
func WithLogsResource(res pcommon.Resource) ResourceLogsOption {
return resourceLogsOptionFunc(func(rl plog.ResourceLogs) {
res.CopyTo(rl.Resource())
})
}
// AppendLogRecord adds a log record to the logs builder.
func (lb *LogsBuilder) AppendLogRecord(lr plog.LogRecord) {
lr.MoveTo(lb.logRecordsBuffer.AppendEmpty())
}
// EmitForResource saves all the generated logs under a new resource and updates the internal state to be ready for
// recording another set of log records as part of another resource. This function can be helpful when one scraper
// needs to emit logs from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceLogsOption arguments.
func (lb *LogsBuilder) EmitForResource(options ...ResourceLogsOption) {
rl := plog.NewResourceLogs()
rl.SetSchemaUrl(conventions.SchemaURL)
ils := rl.ScopeLogs().AppendEmpty()
ils.Scope().SetName(ScopeName)
ils.Scope().SetVersion(lb.buildInfo.Version)
for _, op := range options {
op.apply(rl)
}
if lb.logRecordsBuffer.Len() > 0 {
lb.logRecordsBuffer.MoveAndAppendTo(ils.LogRecords())
lb.logRecordsBuffer = plog.NewLogRecordSlice()
}
if ils.LogRecords().Len() > 0 {
rl.MoveTo(lb.logsBuffer.ResourceLogs().AppendEmpty())
}
}
// Emit returns all the logs accumulated by the logs builder and updates the internal state to be ready for
// recording another set of logs. This function will be responsible for applying all the transformations required to
// produce logs representation defined in metadata and user config.
func (lb *LogsBuilder) Emit(options ...ResourceLogsOption) plog.Logs {
lb.EmitForResource(options...)
logs := lb.logsBuffer
lb.logsBuffer = plog.NewLogs()
return logs
}
generated_logs_test.go 0000664 0000000 0000000 00000003661 15113313446 0037166 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/receiver/receivertest"
)
func TestLogsBuilderAppendLogRecord(t *testing.T) {
observedZapCore, _ := observer.New(zap.WarnLevel)
settings := receivertest.NewNopSettings(receivertest.NopType)
settings.Logger = zap.New(observedZapCore)
lb := NewLogsBuilder(settings)
res := pcommon.NewResource()
// append the first log record
lr := plog.NewLogRecord()
lr.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr.Attributes().PutStr("type", "log")
lr.Body().SetStr("the first log record")
// append the second log record
lr2 := plog.NewLogRecord()
lr2.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr2.Attributes().PutStr("type", "event")
lr2.Body().SetStr("the second log record")
lb.AppendLogRecord(lr)
lb.AppendLogRecord(lr2)
logs := lb.Emit(WithLogsResource(res))
assert.Equal(t, 1, logs.ResourceLogs().Len())
rl := logs.ResourceLogs().At(0)
assert.Equal(t, 1, rl.ScopeLogs().Len())
sl := rl.ScopeLogs().At(0)
assert.Equal(t, ScopeName, sl.Scope().Name())
assert.Equal(t, lb.buildInfo.Version, sl.Scope().Version())
assert.Equal(t, 2, sl.LogRecords().Len())
attrVal, ok := sl.LogRecords().At(0).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "log", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(0).Body().Type())
assert.Equal(t, "the first log record", sl.LogRecords().At(0).Body().Str())
attrVal, ok = sl.LogRecords().At(1).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "event", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(1).Body().Type())
assert.Equal(t, "the second log record", sl.LogRecords().At(1).Body().Str())
}
generated_metrics.go 0000664 0000000 0000000 00000065571 15113313446 0036641 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"fmt"
"strconv"
"time"
conventions "go.opentelemetry.io/otel/semconv/v1.9.0"
"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"
)
// AttributeEnumAttr specifies the value enum_attr attribute.
type AttributeEnumAttr int
const (
_ AttributeEnumAttr = iota
AttributeEnumAttrRed
AttributeEnumAttrGreen
AttributeEnumAttrBlue
)
// String returns the string representation of the AttributeEnumAttr.
func (av AttributeEnumAttr) String() string {
switch av {
case AttributeEnumAttrRed:
return "red"
case AttributeEnumAttrGreen:
return "green"
case AttributeEnumAttrBlue:
return "blue"
}
return ""
}
// MapAttributeEnumAttr is a helper map of string to AttributeEnumAttr attribute value.
var MapAttributeEnumAttr = map[string]AttributeEnumAttr{
"red": AttributeEnumAttrRed,
"green": AttributeEnumAttrGreen,
"blue": AttributeEnumAttrBlue,
}
var MetricsInfo = metricsInfo{
DefaultMetric: metricInfo{
Name: "default.metric",
},
DefaultMetricToBeRemoved: metricInfo{
Name: "default.metric.to_be_removed",
},
MetricInputType: metricInfo{
Name: "metric.input_type",
},
OptionalMetric: metricInfo{
Name: "optional.metric",
},
OptionalMetricEmptyUnit: metricInfo{
Name: "optional.metric.empty_unit",
},
}
type metricsInfo struct {
DefaultMetric metricInfo
DefaultMetricToBeRemoved metricInfo
MetricInputType metricInfo
OptionalMetric metricInfo
OptionalMetricEmptyUnit metricInfo
}
type metricInfo struct {
Name string
}
type MetricAttributeOption interface {
apply(pmetric.NumberDataPoint)
}
type metricAttributeOptionFunc func(pmetric.NumberDataPoint)
func (maof metricAttributeOptionFunc) apply(dp pmetric.NumberDataPoint) {
maof(dp)
}
func WithOptionalIntAttrMetricAttribute(optionalIntAttrAttributeValue int64) MetricAttributeOption {
return metricAttributeOptionFunc(func(dp pmetric.NumberDataPoint) {
dp.Attributes().PutInt("optional_int_attr", optionalIntAttrAttributeValue)
})
}
func WithOptionalStringAttrMetricAttribute(optionalStringAttrAttributeValue string) MetricAttributeOption {
return metricAttributeOptionFunc(func(dp pmetric.NumberDataPoint) {
dp.Attributes().PutStr("optional_string_attr", optionalStringAttrAttributeValue)
})
}
type metricDefaultMetric struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric metric with initial data.
func (m *metricDefaultMetric) init() {
m.data.SetName("default.metric")
m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(true)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
m.data.Sum().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricDefaultMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any, options ...MetricAttributeOption) {
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)
for _, op := range options {
op.apply(dp)
}
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetric) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetric(cfg MetricConfig) metricDefaultMetric {
m := metricDefaultMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricDefaultMetricToBeRemoved struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric.to_be_removed metric with initial data.
func (m *metricDefaultMetricToBeRemoved) init() {
m.data.SetName("default.metric.to_be_removed")
m.data.SetDescription("[DEPRECATED] Non-monotonic delta sum double metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(false)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
}
func (m *metricDefaultMetricToBeRemoved) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetricToBeRemoved) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetricToBeRemoved) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBeRemoved {
m := metricDefaultMetricToBeRemoved{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type 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.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric metric with initial data.
func (m *metricOptionalMetric) init() {
m.data.SetName("optional.metric")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("1")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool, options ...MetricAttributeOption) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr2", booleanAttr2AttributeValue)
for _, op := range options {
op.apply(dp)
}
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetric) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetric(cfg MetricConfig) metricOptionalMetric {
m := metricOptionalMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricOptionalMetricEmptyUnit struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric.empty_unit metric with initial data.
func (m *metricOptionalMetricEmptyUnit) init() {
m.data.SetName("optional.metric.empty_unit")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetricEmptyUnit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetricEmptyUnit) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetricEmptyUnit) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetricEmptyUnit(cfg MetricConfig) metricOptionalMetricEmptyUnit {
m := metricOptionalMetricEmptyUnit{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations
// required to produce metric representation defined in metadata and user config.
type MetricsBuilder struct {
config MetricsBuilderConfig // config of the metrics builder.
startTime pcommon.Timestamp // start time that will be applied to all recorded data points.
metricsCapacity int // maximum observed number of metrics per resource.
metricsBuffer pmetric.Metrics // accumulates metrics data before emitting.
buildInfo component.BuildInfo // contains version information.
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
metricDefaultMetric metricDefaultMetric
metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved
metricMetricInputType metricMetricInputType
metricOptionalMetric metricOptionalMetric
metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit
}
// MetricBuilderOption applies changes to default metrics builder.
type MetricBuilderOption interface {
apply(*MetricsBuilder)
}
type metricBuilderOptionFunc func(mb *MetricsBuilder)
func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) {
mbof(mb)
}
// WithStartTime sets startTime on the metrics builder.
func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption {
return metricBuilderOptionFunc(func(mb *MetricsBuilder) {
mb.startTime = startTime
})
}
func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.Settings, options ...MetricBuilderOption) *MetricsBuilder {
if !mbc.Metrics.DefaultMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.")
}
if mbc.Metrics.DefaultMetricToBeRemoved.Enabled {
settings.Logger.Warn("[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetricEmptyUnit.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.")
}
if !mbc.ResourceAttributes.StringResourceAttrDisableWarning.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.")
}
if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || 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 {
settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.")
}
mb := &MetricsBuilder{
config: mbc,
startTime: pcommon.NewTimestampFromTime(time.Now()),
metricsBuffer: pmetric.NewMetrics(),
buildInfo: settings.BuildInfo,
metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric),
metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved),
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.apply(mb)
}
return mb
}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics.
func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(mb.config.ResourceAttributes)
}
// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity.
func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) {
if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() {
mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len()
}
}
// ResourceMetricsOption applies changes to provided resource metrics.
type ResourceMetricsOption interface {
apply(pmetric.ResourceMetrics)
}
type resourceMetricsOptionFunc func(pmetric.ResourceMetrics)
func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) {
rmof(rm)
}
// WithResource sets the provided resource on the emitted ResourceMetrics.
// It's recommended to use ResourceBuilder to create the resource.
func WithResource(res pcommon.Resource) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
res.CopyTo(rm.Resource())
})
}
// WithStartTimeOverride overrides start time for all the resource metrics data points.
// This option should be only used if different start time has to be set on metrics coming from different resources.
func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
var dps pmetric.NumberDataPointSlice
metrics := rm.ScopeMetrics().At(0).Metrics()
for i := 0; i < metrics.Len(); i++ {
switch metrics.At(i).Type() {
case pmetric.MetricTypeGauge:
dps = metrics.At(i).Gauge().DataPoints()
case pmetric.MetricTypeSum:
dps = metrics.At(i).Sum().DataPoints()
}
for j := 0; j < dps.Len(); j++ {
dps.At(j).SetStartTimestamp(start)
}
}
})
}
// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for
// recording another set of data points as part of another resource. This function can be helpful when one scraper
// needs to emit metrics from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceMetricsOption arguments.
func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) {
rm := pmetric.NewResourceMetrics()
rm.SetSchemaUrl(conventions.SchemaURL)
ils := rm.ScopeMetrics().AppendEmpty()
ils.Scope().SetName(ScopeName)
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 options {
op.apply(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())
}
}
// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for
// recording another set of metrics. This function will be responsible for applying all the transformations required to
// produce metric representation defined in metadata and user config, e.g. delta or cumulative.
func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics {
mb.EmitForResource(options...)
metrics := mb.metricsBuffer
mb.metricsBuffer = pmetric.NewMetrics()
return metrics
}
// RecordDefaultMetricDataPoint adds a data point to default.metric metric.
func (mb *MetricsBuilder) RecordDefaultMetricDataPoint(ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any, options ...MetricAttributeOption) {
mb.metricDefaultMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue, options...)
}
// RecordDefaultMetricToBeRemovedDataPoint adds a data point to default.metric.to_be_removed metric.
func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Timestamp, val float64) {
mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val)
}
// 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, booleanAttr2AttributeValue bool, options ...MetricAttributeOption) {
mb.metricOptionalMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue, booleanAttr2AttributeValue, options...)
}
// RecordOptionalMetricEmptyUnitDataPoint adds a data point to optional.metric.empty_unit metric.
func (mb *MetricsBuilder) RecordOptionalMetricEmptyUnitDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
mb.metricOptionalMetricEmptyUnit.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue)
}
// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted,
// and metrics builder should update its startTime and reset it's internal state accordingly.
func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) {
mb.startTime = pcommon.NewTimestampFromTime(time.Now())
for _, op := range options {
op.apply(mb)
}
}
generated_metrics_test.go 0000664 0000000 0000000 00000030563 15113313446 0037671 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver/receivertest"
)
type testDataSet int
const (
testDataSetDefault testDataSet = iota
testDataSetAll
testDataSetNone
)
func TestMetricsBuilder(t *testing.T) {
tests := []struct {
name string
metricsSet testDataSet
resAttrsSet testDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
metricsSet: testDataSetAll,
resAttrsSet: testDataSetAll,
},
{
name: "none_set",
metricsSet: testDataSetNone,
resAttrsSet: testDataSetNone,
expectEmpty: true,
},
{
name: "filter_set_include",
resAttrsSet: testDataSetAll,
},
{
name: "filter_set_exclude",
resAttrsSet: testDataSetAll,
expectEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
start := pcommon.Timestamp(1_000_000_000)
ts := pcommon.Timestamp(1_000_001_000)
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
settings := receivertest.NewNopSettings(receivertest.NopType)
settings.Logger = zap.New(observedZapCore)
mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start))
expectedWarnings := 0
if tt.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 tt.metricsSet == testDataSetDefault || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.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 tt.resAttrsSet == testDataSetAll || tt.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 tt.resAttrsSet == testDataSetDefault || tt.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++
}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultMetricsCount := 0
allMetricsCount := 0
defaultMetricsCount++
allMetricsCount++
mb.RecordDefaultMetricDataPoint(ts, 1, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, WithOptionalIntAttrMetricAttribute(17), WithOptionalStringAttrMetricAttribute("optional_string_attr-val"))
defaultMetricsCount++
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, false, WithOptionalStringAttrMetricAttribute("optional_string_attr-val"))
allMetricsCount++
mb.RecordOptionalMetricEmptyUnitDataPoint(ts, 1, "string_attr-val", true)
rb := mb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
metrics := mb.Emit(WithResource(res))
if tt.expectEmpty {
assert.Equal(t, 0, metrics.ResourceMetrics().Len())
return
}
assert.Equal(t, 1, metrics.ResourceMetrics().Len())
rm := metrics.ResourceMetrics().At(0)
assert.Equal(t, res, rm.Resource())
assert.Equal(t, 1, rm.ScopeMetrics().Len())
ms := rm.ScopeMetrics().At(0).Metrics()
if tt.metricsSet == testDataSetDefault {
assert.Equal(t, defaultMetricsCount, ms.Len())
}
if tt.metricsSet == testDataSetAll {
assert.Equal(t, allMetricsCount, ms.Len())
}
validatedMetrics := make(map[string]bool)
for i := 0; i < ms.Len(); i++ {
switch ms.At(i).Name() {
case "default.metric":
assert.False(t, validatedMetrics["default.metric"], "Found a duplicate in the metrics slice: default.metric")
validatedMetrics["default.metric"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw())
attrVal, ok = dp.Attributes().Get("optional_int_attr")
assert.True(t, ok)
assert.EqualValues(t, 17, attrVal.Int())
attrVal, ok = dp.Attributes().Get("optional_string_attr")
assert.True(t, ok)
assert.Equal(t, "optional_string_attr-val", attrVal.Str())
case "default.metric.to_be_removed":
assert.False(t, validatedMetrics["default.metric.to_be_removed"], "Found a duplicate in the metrics slice: default.metric.to_be_removed")
validatedMetrics["default.metric.to_be_removed"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.False(t, ms.At(i).Sum().IsMonotonic())
assert.Equal(t, pmetric.AggregationTemporalityDelta, ms.At(i).Sum().AggregationTemporality())
dp := ms.At(i).Sum().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
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.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(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
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Equal(t, "1", ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
attrVal, ok = dp.Attributes().Get("boolean_attr2")
assert.True(t, ok)
assert.False(t, attrVal.Bool())
attrVal, ok = dp.Attributes().Get("optional_string_attr")
assert.True(t, ok)
assert.Equal(t, "optional_string_attr-val", attrVal.Str())
case "optional.metric.empty_unit":
assert.False(t, validatedMetrics["optional.metric.empty_unit"], "Found a duplicate in the metrics slice: optional.metric.empty_unit")
validatedMetrics["optional.metric.empty_unit"] = true
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Empty(t, ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
}
}
})
}
}
generated_resource.go 0000664 0000000 0000000 00000006426 15113313446 0037014 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/pdata/pcommon"
)
// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml.
// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines.
type ResourceBuilder struct {
config ResourceAttributesConfig
res pcommon.Resource
}
// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application.
func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder {
return &ResourceBuilder{
config: rac,
res: pcommon.NewResource(),
}
}
// SetMapResourceAttr sets provided value as "map.resource.attr" attribute.
func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) {
if rb.config.MapResourceAttr.Enabled {
rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val)
}
}
// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute.
func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) {
if rb.config.OptionalResourceAttr.Enabled {
rb.res.Attributes().PutStr("optional.resource.attr", val)
}
}
// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute.
func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) {
if rb.config.SliceResourceAttr.Enabled {
rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val)
}
}
// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "one")
}
}
// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "two")
}
}
// SetStringResourceAttr sets provided value as "string.resource.attr" attribute.
func (rb *ResourceBuilder) SetStringResourceAttr(val string) {
if rb.config.StringResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.resource.attr", val)
}
}
// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) {
if rb.config.StringResourceAttrDisableWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val)
}
}
// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) {
if rb.config.StringResourceAttrRemoveWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val)
}
}
// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) {
if rb.config.StringResourceAttrToBeRemoved.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val)
}
}
// Emit returns the built resource and resets the internal builder state.
func (rb *ResourceBuilder) Emit() pcommon.Resource {
r := rb.res
rb.res = pcommon.NewResource()
return r
}
generated_resource_test.go 0000664 0000000 0000000 00000005421 15113313446 0040045 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestResourceBuilder(t *testing.T) {
for _, tt := range []string{"default", "all_set", "none_set"} {
t.Run(tt, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt)
rb := NewResourceBuilder(cfg)
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource
switch tt {
case "default":
assert.Equal(t, 6, res.Attributes().Len())
case "all_set":
assert.Equal(t, 8, res.Attributes().Len())
case "none_set":
assert.Equal(t, 0, res.Attributes().Len())
return
default:
assert.Failf(t, "unexpected test case: %s", tt)
}
val, ok := res.Attributes().Get("map.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw())
}
val, ok = res.Attributes().Get("optional.resource.attr")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "optional.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("slice.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw())
}
val, ok = res.Attributes().Get("string.enum.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "one", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_disable_warning")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_disable_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_remove_warning")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "string.resource.attr_remove_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_to_be_removed")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_to_be_removed-val", val.Str())
}
})
}
}
generated_status.go 0000664 0000000 0000000 00000000742 15113313446 0036503 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/component"
)
var (
Type = component.MustNewType("sample")
ScopeName = "go.opentelemetry.io/collector/internal/receiver/samplefactoryreceiver"
)
const (
ProfilesStability = component.StabilityLevelDeprecated
LogsStability = component.StabilityLevelDevelopment
TracesStability = component.StabilityLevelBeta
MetricsStability = component.StabilityLevelStable
)
generated_telemetry.go 0000664 0000000 0000000 00000011304 15113313446 0037166 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"context"
"errors"
"sync"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/collector/component"
)
func Meter(settings component.TelemetrySettings) metric.Meter {
return settings.MeterProvider.Meter("go.opentelemetry.io/collector/internal/receiver/samplefactoryreceiver")
}
func Tracer(settings component.TelemetrySettings) trace.Tracer {
return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/internal/receiver/samplefactoryreceiver")
}
// TelemetryBuilder provides an interface for components to report telemetry
// as defined in metadata and user config.
type TelemetryBuilder struct {
meter metric.Meter
mu sync.Mutex
registrations []metric.Registration
BatchSizeTriggerSend metric.Int64Counter
ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter
QueueCapacity metric.Int64Gauge
QueueLength metric.Int64ObservableGauge
RequestDuration metric.Float64Histogram
}
// TelemetryBuilderOption applies changes to default builder.
type TelemetryBuilderOption interface {
apply(*TelemetryBuilder)
}
type telemetryBuilderOptionFunc func(mb *TelemetryBuilder)
func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) {
tbof(mb)
}
// RegisterProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric.
func (builder *TelemetryBuilder) RegisterProcessRuntimeTotalAllocBytesCallback(cb metric.Int64Callback) error {
reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error {
cb(ctx, &observerInt64{inst: builder.ProcessRuntimeTotalAllocBytes, obs: o})
return nil
}, builder.ProcessRuntimeTotalAllocBytes)
if err != nil {
return err
}
builder.mu.Lock()
defer builder.mu.Unlock()
builder.registrations = append(builder.registrations, reg)
return nil
}
// RegisterQueueLengthCallback sets callback for observable QueueLength metric.
func (builder *TelemetryBuilder) RegisterQueueLengthCallback(cb metric.Int64Callback) error {
reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error {
cb(ctx, &observerInt64{inst: builder.QueueLength, obs: o})
return nil
}, builder.QueueLength)
if err != nil {
return err
}
builder.mu.Lock()
defer builder.mu.Unlock()
builder.registrations = append(builder.registrations, reg)
return nil
}
type observerInt64 struct {
embedded.Int64Observer
inst metric.Int64Observable
obs metric.Observer
}
func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) {
oi.obs.ObserveInt64(oi.inst, value, opts...)
}
// Shutdown unregister all registered callbacks for async instruments.
func (builder *TelemetryBuilder) Shutdown() {
builder.mu.Lock()
defer builder.mu.Unlock()
for _, reg := range builder.registrations {
reg.Unregister()
}
}
// NewTelemetryBuilder provides a struct with methods to update all internal telemetry
// for a component
func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) {
builder := TelemetryBuilder{}
for _, op := range options {
op.apply(&builder)
}
builder.meter = Meter(settings)
var err, errs error
builder.BatchSizeTriggerSend, err = builder.meter.Int64Counter(
"otelcol_batch_size_trigger_send",
metric.WithDescription("Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]"),
metric.WithUnit("{times}"),
)
errs = errors.Join(errs, err)
builder.ProcessRuntimeTotalAllocBytes, err = builder.meter.Int64ObservableCounter(
"otelcol_process_runtime_total_alloc_bytes",
metric.WithDescription("Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')"),
metric.WithUnit("By"),
)
errs = errors.Join(errs, err)
builder.QueueCapacity, err = builder.meter.Int64Gauge(
"otelcol_queue_capacity",
metric.WithDescription("Queue capacity - sync gauge example."),
metric.WithUnit("{items}"),
)
errs = errors.Join(errs, err)
builder.QueueLength, err = builder.meter.Int64ObservableGauge(
"otelcol_queue_length",
metric.WithDescription("This metric is optional and therefore not initialized in NewTelemetryBuilder. [Alpha]"),
metric.WithUnit("{items}"),
)
errs = errors.Join(errs, err)
builder.RequestDuration, err = builder.meter.Float64Histogram(
"otelcol_request_duration",
metric.WithDescription("Duration of request [Alpha]"),
metric.WithUnit("s"),
metric.WithExplicitBucketBoundaries([]float64{1, 10, 100}...),
)
errs = errors.Join(errs, err)
return &builder, errs
}
generated_telemetry_test.go 0000664 0000000 0000000 00000003541 15113313446 0040231 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata // 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"
"go.opentelemetry.io/collector/component/componenttest"
)
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/samplefactoryreceiver", 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/samplefactoryreceiver", m.name)
} else {
require.Fail(t, "returned Meter not mockTracer")
}
}
func TestNewTelemetryBuilder(t *testing.T) {
set := componenttest.NewNopTelemetrySettings()
applied := false
_, err := NewTelemetryBuilder(set, telemetryBuilderOptionFunc(func(b *TelemetryBuilder) {
applied = true
}))
require.NoError(t, err)
require.True(t, applied)
}
testdata/ 0000775 0000000 0000000 00000000000 15113313446 0034421 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata config.yaml 0000664 0000000 0000000 00000010464 15113313446 0036557 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/internal/metadata/testdata 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
events:
default.event:
enabled: true
default.event.to_be_removed:
enabled: true
default.event.to_be_renamed:
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
events:
default.event:
enabled: false
default.event.to_be_removed:
enabled: false
default.event.to_be_renamed:
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: ".*"
events_include:
- regexp: ".*"
optional.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
slice.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.enum.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr_disable_warning:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr_remove_warning:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr_to_be_removed:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
filter_set_exclude:
resource_attributes:
map.resource.attr:
enabled: true
metrics_exclude:
- regexp: ".*"
events_exclude:
- regexp: ".*"
optional.resource.attr:
enabled: true
metrics_exclude:
- strict: "optional.resource.attr-val"
events_exclude:
- strict: "optional.resource.attr-val"
slice.resource.attr:
enabled: true
metrics_exclude:
- regexp: ".*"
events_exclude:
- regexp: ".*"
string.enum.resource.attr:
enabled: true
metrics_exclude:
- strict: "one"
events_exclude:
- strict: "one"
string.resource.attr:
enabled: true
metrics_exclude:
- strict: "string.resource.attr-val"
events_exclude:
- strict: "string.resource.attr-val"
string.resource.attr_disable_warning:
enabled: true
metrics_exclude:
- strict: "string.resource.attr_disable_warning-val"
events_exclude:
- strict: "string.resource.attr_disable_warning-val"
string.resource.attr_remove_warning:
enabled: true
metrics_exclude:
- strict: "string.resource.attr_remove_warning-val"
events_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"
events_exclude:
- strict: "string.resource.attr_to_be_removed-val"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplefactoryreceiver/metadata.yaml 0000664 0000000 0000000 00000001276 15113313446 0031745 0 ustar 00root root 0000000 0000000 # Sample metadata file with all available configurations for a receiver.
type: sample
scope_name: go.opentelemetry.io/collector/internal/receiver/samplefactoryreceiver
github_project: open-telemetry/opentelemetry-collector
sem_conv_version: 1.9.0
status:
disable_codecov_badge: true
class: receiver
stability:
development: [logs]
beta: [traces]
stable: [metrics]
deprecated: [profiles]
deprecation:
profiles:
migration: "no migration needed"
date: "2025-02-05"
distributions: []
unsupported_platforms: [freebsd, illumos]
codeowners:
active: [dmitryax]
warnings:
- Any additional information that should be brought to the consumer's attention
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/ 0000775 0000000 0000000 00000000000 15113313446 0026116 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/README.md 0000664 0000000 0000000 00000003304 15113313446 0027375 0 ustar 00root root 0000000 0000000 # Sample Processor
This processor 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 | [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Aprocessor%2Fsample) [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aclosed+is%3Aissue+label%3Aprocessor%2Fsample) |
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | |
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
[beta]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#beta
[stable]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stable
## Warnings
This is where warnings are described.
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/doc.go 0000664 0000000 0000000 00000000476 15113313446 0027221 0 ustar 00root root 0000000 0000000 // 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
package sampleprocessor // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleprocessor"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/documentation.md 0000664 0000000 0000000 00000001643 15113313446 0031315 0 ustar 00root root 0000000 0000000 [comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
# sample
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| map.resource.attr | Resource attribute with a map value. | Any Map | true |
| optional.resource.attr | Explicitly disabled ResourceAttribute. | Any Str | false |
| slice.resource.attr | Resource attribute with a slice value. | Any Slice | true |
| string.enum.resource.attr | Resource attribute with a known set of string values. | Str: ``one``, ``two`` | true |
| string.resource.attr | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_disable_warning | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_remove_warning | Resource attribute with any string value. | Any Str | false |
| string.resource.attr_to_be_removed | Resource attribute with any string value. | Any Str | true |
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/factory.go 0000664 0000000 0000000 00000003614 15113313446 0030120 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package sampleprocessor // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleprocessor"
import (
"context"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/sampleprocessor/internal/metadata"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/pdata/ptrace"
"go.opentelemetry.io/collector/processor"
)
// NewFactory returns a receiver.Factory for sample receiver.
func NewFactory() processor.Factory {
return processor.NewFactory(
metadata.Type,
func() component.Config { return &struct{}{} },
processor.WithTraces(createTracesProcessor, metadata.TracesStability),
processor.WithMetrics(createMetricsProcessor, metadata.MetricsStability),
processor.WithLogs(createLogsProcessor, metadata.LogsStability))
}
func createTracesProcessor(context.Context, processor.Settings, component.Config, consumer.Traces) (processor.Traces, error) {
return nopInstance, nil
}
func createMetricsProcessor(context.Context, processor.Settings, component.Config, consumer.Metrics) (processor.Metrics, error) {
return nopInstance, nil
}
func createLogsProcessor(context.Context, processor.Settings, component.Config, consumer.Logs) (processor.Logs, error) {
return nopInstance, nil
}
var nopInstance = &nopProcessor{}
type nopProcessor struct {
component.StartFunc
component.ShutdownFunc
}
func (n nopProcessor) ConsumeTraces(context.Context, ptrace.Traces) error {
return nil
}
func (n nopProcessor) ConsumeLogs(context.Context, plog.Logs) error {
return nil
}
func (n nopProcessor) Capabilities() consumer.Capabilities {
return consumer.Capabilities{MutatesData: true}
}
func (n nopProcessor) ConsumeMetrics(context.Context, pmetric.Metrics) error {
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/generated_component_test.go 0000664 0000000 0000000 00000012077 15113313446 0033533 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
//go:build !freebsd && !illumos
package sampleprocessor
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"
)
var typ = component.MustNewType("sample")
func TestComponentFactoryType(t *testing.T) {
require.Equal(t, typ, NewFactory().Type())
}
func TestComponentConfigStruct(t *testing.T) {
require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()))
}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct {
createFn func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error)
name string
}{
{
name: "logs",
createFn: func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg, consumertest.NewNop())
},
},
{
name: "metrics",
createFn: func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg, consumertest.NewNop())
},
},
{
name: "traces",
createFn: func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(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, sub.Unmarshal(&cfg))
for _, tt := range tests {
t.Run(tt.name+"-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), processortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
t.Run(tt.name+"-lifecycle", func(t *testing.T) {
c, err := tt.createFn(context.Background(), processortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := newMdatagenNopHost()
err = c.Start(context.Background(), host)
require.NoError(t, err)
require.NotPanics(t, func() {
switch tt.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
}
var _ component.Host = (*mdatagenNopHost)(nil)
type mdatagenNopHost struct{}
func newMdatagenNopHost() component.Host {
return &mdatagenNopHost{}
}
func (mnh *mdatagenNopHost) GetExtensions() map[component.ID]component.Component {
return nil
}
func (mnh *mdatagenNopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory {
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/generated_package_test.go 0000664 0000000 0000000 00000000256 15113313446 0033120 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package sampleprocessor
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/ 0000775 0000000 0000000 00000000000 15113313446 0027732 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata/ 0000775 0000000 0000000 00000000000 15113313446 0031512 5 ustar 00root root 0000000 0000000 generated_config.go 0000664 0000000 0000000 00000004212 15113313446 0035244 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/confmap"
)
// ResourceAttributeConfig provides common config for a particular resource attribute.
type ResourceAttributeConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(rac)
if err != nil {
return err
}
rac.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// ResourceAttributesConfig provides config for sample resource attributes.
type ResourceAttributesConfig struct {
MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"`
OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"`
SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"`
StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"`
StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"`
StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"`
StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"`
StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"`
}
func DefaultResourceAttributesConfig() ResourceAttributesConfig {
return ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
OptionalResourceAttr: ResourceAttributeConfig{
Enabled: false,
},
SliceResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringEnumResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrDisableWarning: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{
Enabled: false,
},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{
Enabled: true,
},
}
}
generated_config_test.go 0000664 0000000 0000000 00000004777 15113313446 0036323 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap/confmaptest"
)
func TestResourceAttributesConfig(t *testing.T) {
tests := []struct {
name string
want ResourceAttributesConfig
}{
{
name: "default",
want: DefaultResourceAttributesConfig(),
},
{
name: "all_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
{
name: "none_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
sub, err = sub.Sub("resource_attributes")
require.NoError(t, err)
cfg := DefaultResourceAttributesConfig()
require.NoError(t, sub.Unmarshal(&cfg))
return cfg
}
generated_resource.go 0000664 0000000 0000000 00000006426 15113313446 0035637 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/pdata/pcommon"
)
// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml.
// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines.
type ResourceBuilder struct {
config ResourceAttributesConfig
res pcommon.Resource
}
// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application.
func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder {
return &ResourceBuilder{
config: rac,
res: pcommon.NewResource(),
}
}
// SetMapResourceAttr sets provided value as "map.resource.attr" attribute.
func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) {
if rb.config.MapResourceAttr.Enabled {
rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val)
}
}
// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute.
func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) {
if rb.config.OptionalResourceAttr.Enabled {
rb.res.Attributes().PutStr("optional.resource.attr", val)
}
}
// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute.
func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) {
if rb.config.SliceResourceAttr.Enabled {
rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val)
}
}
// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "one")
}
}
// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "two")
}
}
// SetStringResourceAttr sets provided value as "string.resource.attr" attribute.
func (rb *ResourceBuilder) SetStringResourceAttr(val string) {
if rb.config.StringResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.resource.attr", val)
}
}
// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) {
if rb.config.StringResourceAttrDisableWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val)
}
}
// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) {
if rb.config.StringResourceAttrRemoveWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val)
}
}
// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) {
if rb.config.StringResourceAttrToBeRemoved.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val)
}
}
// Emit returns the built resource and resets the internal builder state.
func (rb *ResourceBuilder) Emit() pcommon.Resource {
r := rb.res
rb.res = pcommon.NewResource()
return r
}
generated_resource_test.go 0000664 0000000 0000000 00000005421 15113313446 0036670 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestResourceBuilder(t *testing.T) {
for _, tt := range []string{"default", "all_set", "none_set"} {
t.Run(tt, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt)
rb := NewResourceBuilder(cfg)
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource
switch tt {
case "default":
assert.Equal(t, 6, res.Attributes().Len())
case "all_set":
assert.Equal(t, 8, res.Attributes().Len())
case "none_set":
assert.Equal(t, 0, res.Attributes().Len())
return
default:
assert.Failf(t, "unexpected test case: %s", tt)
}
val, ok := res.Attributes().Get("map.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw())
}
val, ok = res.Attributes().Get("optional.resource.attr")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "optional.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("slice.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw())
}
val, ok = res.Attributes().Get("string.enum.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "one", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_disable_warning")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_disable_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_remove_warning")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "string.resource.attr_remove_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_to_be_removed")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_to_be_removed-val", val.Str())
}
})
}
}
generated_status.go 0000664 0000000 0000000 00000000640 15113313446 0035323 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/component"
)
var (
Type = component.MustNewType("sample")
ScopeName = "go.opentelemetry.io/collector/internal/receiver/samplereceiver"
)
const (
LogsStability = component.StabilityLevelDevelopment
TracesStability = component.StabilityLevelBeta
MetricsStability = component.StabilityLevelStable
)
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata/testdata/ 0000775 0000000 0000000 00000000000 15113313446 0033323 5 ustar 00root root 0000000 0000000 config.yaml 0000664 0000000 0000000 00000001622 15113313446 0035376 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/internal/metadata/testdata default:
all_set:
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:
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
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/sampleprocessor/metadata.yaml 0000664 0000000 0000000 00000003555 15113313446 0030572 0 ustar 00root root 0000000 0000000 # Sample metadata file with all available configurations for a receiver.
type: sample
scope_name: go.opentelemetry.io/collector/internal/receiver/samplereceiver
github_project: open-telemetry/opentelemetry-collector
sem_conv_version: 1.9.0
status:
disable_codecov_badge: true
class: processor
stability:
development: [logs]
beta: [traces]
stable: [metrics]
distributions: []
unsupported_platforms: [freebsd, illumos]
codeowners:
active: []
warnings:
- Any additional information that should be brought to the consumer's attention
resource_attributes:
map.resource.attr:
description: Resource attribute with a map value.
type: map
enabled: true
optional.resource.attr:
description: Explicitly disabled ResourceAttribute.
type: string
enabled: false
slice.resource.attr:
description: Resource attribute with a slice value.
type: slice
enabled: true
string.enum.resource.attr:
description: Resource attribute with a known set of string values.
type: string
enum: [one, two]
enabled: true
string.resource.attr:
description: Resource attribute with any string value.
type: string
enabled: true
string.resource.attr_disable_warning:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled_not_set: This resource_attribute will be disabled by default soon.
string.resource.attr_remove_warning:
description: Resource attribute with any string value.
type: string
enabled: false
warnings:
if_configured: This resource_attribute is deprecated and will be removed soon.
string.resource.attr_to_be_removed:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled: This resource_attribute is deprecated and will be removed soon.
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/ 0000775 0000000 0000000 00000000000 15113313446 0025703 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/README.md 0000664 0000000 0000000 00000004420 15113313446 0027162 0 ustar 00root root 0000000 0000000 # Sample Receiver
This receiver is used for testing purposes to check the output of mdatagen.
| Status | |
| ------------- |-----------|
| Stability | [deprecated]: profiles |
| | [development]: logs |
| | [beta]: traces |
| | [stable]: metrics |
| Deprecation of profiles | [Date]: 2025-02-05 |
| | [Migration Note]: no migration needed |
| Unsupported Platforms | freebsd, illumos |
| Distributions | [] |
| Warnings | [Any additional information that should be brought to the consumer's attention](#warnings) |
| Issues | [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fsample) [](https://github.com/open-telemetry/opentelemetry-collector/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) |
[deprecated]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecated
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
[beta]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#beta
[stable]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stable
[Date]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecation-information
[Migration Note]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecation-information
## Warnings
This is where warnings are described.
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/doc.go 0000664 0000000 0000000 00000000474 15113313446 0027004 0 ustar 00root root 0000000 0000000 // 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
package samplereceiver // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/documentation.md 0000664 0000000 0000000 00000021225 15113313446 0031100 0 ustar 00root root 0000000 0000000 [comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
# sample
## Default Metrics
The following metrics are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
metrics:
:
enabled: false
```
### default.metric
Monotonic cumulative sum int metric enabled by default.
The metric will be become optional soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Int | Cumulative | true | Development |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| state | Integer attribute with overridden name. | Any Int | Recommended |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | Recommended |
| slice_attr | Attribute with a slice value. | Any Slice | Recommended |
| map_attr | Attribute with a map value. | Any Map | Recommended |
| conditional_int_attr | A conditional attribute with an integer value | Any Int | Conditionally Required |
| conditional_string_attr | A conditional attribute with any string value | Any Str | Conditionally Required |
| opt_in_bool_attr | An opt-in attribute with a boolean value | Any Bool | Opt-In |
### default.metric.to_be_removed
[DEPRECATED] Non-monotonic delta sum double metric enabled by default.
The metric will be removed soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Double | Delta | false | Deprecated |
### metric.input_type
Monotonic cumulative sum int metric with string input_type enabled by default.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Int | Cumulative | true | Development |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| state | Integer attribute with overridden name. | Any Int | Recommended |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | Recommended |
| slice_attr | Attribute with a slice value. | Any Slice | Recommended |
| map_attr | Attribute with a map value. | Any Map | Recommended |
### system.cpu.time
Monotonic cumulative sum int metric enabled by default.
The metric will be become optional soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability | Semantic Convention |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- | ------------------- |
| s | Sum | Int | Cumulative | true | Beta | [system.cpu.time](https://github.com/open-telemetry/semantic-conventions/blob/v1.37.0/docs/system/system-metrics.md#metric-systemcputime) |
## Optional Metrics
The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
metrics:
:
enabled: true
```
### optional.metric
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| 1 | Gauge | Double | Deprecated |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| boolean_attr | Attribute with a boolean value. | Any Bool | Recommended |
| boolean_attr2 | Another attribute with a boolean value. | Any Bool | Recommended |
| conditional_string_attr | A conditional attribute with any string value | Any Str | Conditionally Required |
### optional.metric.empty_unit
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| | Gauge | Double | Deprecated |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| boolean_attr | Attribute with a boolean value. | Any Bool | Recommended |
## Default Events
The following events are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
events:
:
enabled: false
```
### default.event
Example event enabled by default.
#### 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 |
| conditional_int_attr | A conditional attribute with an integer value | Any Int |
| conditional_string_attr | A conditional attribute with any string value | Any Str |
| opt_in_bool_attr | An opt-in attribute with a boolean value | Any Bool |
### default.event.to_be_removed
[DEPRECATED] Example to-be-removed event enabled by default.
The event will be removed soon.
#### 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 Events
The following events are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
events:
:
enabled: true
```
### default.event.to_be_renamed
[DEPRECATED] Example event disabled by default.
The event will be renamed soon.
#### Attributes
| Name | Description | Values |
| ---- | ----------- | ------ |
| string_attr | Attribute with any string value. | Any Str |
| boolean_attr | Attribute with a boolean value. | Any Bool |
| boolean_attr2 | Another attribute with a boolean value. | Any Bool |
| conditional_string_attr | A conditional attribute with any string value | Any Str |
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| map.resource.attr | Resource attribute with a map value. | Any Map | true |
| optional.resource.attr | Explicitly disabled ResourceAttribute. | Any Str | false |
| slice.resource.attr | Resource attribute with a slice value. | Any Slice | true |
| string.enum.resource.attr | Resource attribute with a known set of string values. | Str: ``one``, ``two`` | true |
| string.resource.attr | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_disable_warning | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_remove_warning | Resource attribute with any string value. | Any Str | false |
| string.resource.attr_to_be_removed | Resource attribute with any string value. | Any Str | true |
## Internal Telemetry
The following telemetry is emitted by this component.
### otelcol_batch_size_trigger_send
Number of times the batch was sent due to a size trigger [Deprecated since v0.110.0]
| Unit | Metric Type | Value Type | Monotonic | Stability |
| ---- | ----------- | ---------- | --------- | --------- |
| {times} | Sum | Int | true | Deprecated |
### otelcol_process_runtime_total_alloc_bytes
Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')
| Unit | Metric Type | Value Type | Monotonic | Stability |
| ---- | ----------- | ---------- | --------- | --------- |
| By | Sum | Int | true | Stable |
### otelcol_queue_capacity
Queue capacity - sync gauge example. [Development]
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| {items} | Gauge | Int | Development |
### otelcol_queue_length
This metric is optional and therefore not initialized in NewTelemetryBuilder. [Alpha]
For example this metric only exists if feature A is enabled.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| {items} | Gauge | Int | Alpha |
### otelcol_request_duration
Duration of request [Alpha]
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| s | Histogram | Double | Alpha |
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/factory.go 0000664 0000000 0000000 00000004230 15113313446 0027700 0 ustar 00root root 0000000 0000000 // 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/otel/metric"
"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.Settings, component.Config, consumer.Traces) (receiver.Traces, error) {
return nopInstance, nil
}
func createMetrics(ctx context.Context, set receiver.Settings, _ component.Config, _ consumer.Metrics) (receiver.Metrics, error) {
telemetryBuilder, err := metadata.NewTelemetryBuilder(set.TelemetrySettings)
if err != nil {
return nil, err
}
err = telemetryBuilder.RegisterProcessRuntimeTotalAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error {
observer.Observe(2)
return nil
})
if err != nil {
return nil, err
}
telemetryBuilder.BatchSizeTriggerSend.Add(ctx, 1)
return nopReceiver{telemetryBuilder: telemetryBuilder}, nil
}
func createLogs(context.Context, receiver.Settings, component.Config, consumer.Logs) (receiver.Logs, error) {
return nopInstance, nil
}
var nopInstance = &nopReceiver{}
type nopReceiver struct {
component.StartFunc
telemetryBuilder *metadata.TelemetryBuilder
}
func (r nopReceiver) initOptionalMetric() {
_ = r.telemetryBuilder.RegisterQueueLengthCallback(func(_ context.Context, observer metric.Int64Observer) error {
observer.Observe(3)
return nil
})
}
// Shutdown shuts down the component.
func (r nopReceiver) Shutdown(context.Context) error {
if r.telemetryBuilder != nil {
r.telemetryBuilder.Shutdown()
}
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/generated_component_test.go 0000664 0000000 0000000 00000006047 15113313446 0033320 0 ustar 00root root 0000000 0000000 // 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"
)
var typ = component.MustNewType("sample")
func TestComponentFactoryType(t *testing.T) {
require.Equal(t, typ, NewFactory().Type())
}
func TestComponentConfigStruct(t *testing.T) {
require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()))
}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct {
createFn func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error)
name string
}{
{
name: "logs",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg, consumertest.NewNop())
},
},
{
name: "metrics",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg, consumertest.NewNop())
},
},
{
name: "traces",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(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, sub.Unmarshal(&cfg))
for _, tt := range tests {
t.Run(tt.name+"-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
t.Run(tt.name+"-lifecycle", func(t *testing.T) {
firstRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := newMdatagenNopHost()
require.NoError(t, err)
require.NoError(t, firstRcvr.Start(context.Background(), host))
require.NoError(t, firstRcvr.Shutdown(context.Background()))
secondRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondRcvr.Start(context.Background(), host))
require.NoError(t, secondRcvr.Shutdown(context.Background()))
})
}
}
var _ component.Host = (*mdatagenNopHost)(nil)
type mdatagenNopHost struct{}
func newMdatagenNopHost() component.Host {
return &mdatagenNopHost{}
}
func (mnh *mdatagenNopHost) GetExtensions() map[component.ID]component.Component {
return nil
}
func (mnh *mdatagenNopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory {
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/generated_package_test.go 0000664 0000000 0000000 00000000255 15113313446 0032704 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package samplereceiver
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/ 0000775 0000000 0000000 00000000000 15113313446 0027517 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata/ 0000775 0000000 0000000 00000000000 15113313446 0031277 5 ustar 00root root 0000000 0000000 generated_config.go 0000664 0000000 0000000 00000014542 15113313446 0035040 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/filter"
)
// MetricConfig provides common config for a particular metric.
type MetricConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ms)
if err != nil {
return err
}
ms.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// MetricsConfig provides config for 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"`
SystemCPUTime MetricConfig `mapstructure:"system.cpu.time"`
}
func DefaultMetricsConfig() MetricsConfig {
return MetricsConfig{
DefaultMetric: MetricConfig{
Enabled: true,
},
DefaultMetricToBeRemoved: MetricConfig{
Enabled: true,
},
MetricInputType: MetricConfig{
Enabled: true,
},
OptionalMetric: MetricConfig{
Enabled: false,
},
OptionalMetricEmptyUnit: MetricConfig{
Enabled: false,
},
SystemCPUTime: MetricConfig{
Enabled: true,
},
}
}
// EventConfig provides common config for a particular event.
type EventConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ec *EventConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ec)
if err != nil {
return err
}
ec.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// EventsConfig provides config for sample events.
type EventsConfig struct {
DefaultEvent EventConfig `mapstructure:"default.event"`
DefaultEventToBeRemoved EventConfig `mapstructure:"default.event.to_be_removed"`
DefaultEventToBeRenamed EventConfig `mapstructure:"default.event.to_be_renamed"`
}
func DefaultEventsConfig() EventsConfig {
return EventsConfig{
DefaultEvent: EventConfig{
Enabled: true,
},
DefaultEventToBeRemoved: EventConfig{
Enabled: true,
},
DefaultEventToBeRenamed: EventConfig{
Enabled: false,
},
}
}
// 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"`
// Experimental: EventsInclude defines a list of filters for attribute values.
// If the list is not empty, only events with matching resource attribute values will be emitted.
EventsInclude []filter.Config `mapstructure:"events_include"`
// Experimental: EventsExclude defines a list of filters for attribute values.
// If the list is not empty, events with matching resource attribute values will not be emitted.
// EventsInclude has higher priority than EventsExclude.
EventsExclude []filter.Config `mapstructure:"events_exclude"`
enabledSetByUser bool
}
func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(rac)
if err != nil {
return err
}
rac.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// ResourceAttributesConfig provides config for sample resource attributes.
type ResourceAttributesConfig struct {
MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"`
OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"`
SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"`
StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"`
StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"`
StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"`
StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"`
StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"`
}
func DefaultResourceAttributesConfig() ResourceAttributesConfig {
return ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
OptionalResourceAttr: ResourceAttributeConfig{
Enabled: false,
},
SliceResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringEnumResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrDisableWarning: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{
Enabled: false,
},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{
Enabled: true,
},
}
}
// MetricsBuilderConfig is a configuration for sample metrics builder.
type MetricsBuilderConfig struct {
Metrics MetricsConfig `mapstructure:"metrics"`
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
}
func DefaultMetricsBuilderConfig() MetricsBuilderConfig {
return MetricsBuilderConfig{
Metrics: DefaultMetricsConfig(),
ResourceAttributes: DefaultResourceAttributesConfig(),
}
}
// LogsBuilderConfig is a configuration for sample logs builder.
type LogsBuilderConfig struct {
Events EventsConfig `mapstructure:"events"`
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
}
func DefaultLogsBuilderConfig() LogsBuilderConfig {
return LogsBuilderConfig{
Events: DefaultEventsConfig(),
ResourceAttributes: DefaultResourceAttributesConfig(),
}
}
generated_config_test.go 0000664 0000000 0000000 00000013725 15113313446 0036101 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
)
func TestMetricsBuilderConfig(t *testing.T) {
tests := []struct {
name string
want MetricsBuilderConfig
}{
{
name: "default",
want: DefaultMetricsBuilderConfig(),
},
{
name: "all_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: true},
DefaultMetricToBeRemoved: MetricConfig{Enabled: true},
MetricInputType: MetricConfig{Enabled: true},
OptionalMetric: MetricConfig{Enabled: true},
OptionalMetricEmptyUnit: MetricConfig{Enabled: true},
SystemCPUTime: MetricConfig{Enabled: true},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
},
{
name: "none_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: false},
DefaultMetricToBeRemoved: MetricConfig{Enabled: false},
MetricInputType: MetricConfig{Enabled: false},
OptionalMetric: MetricConfig{Enabled: false},
OptionalMetricEmptyUnit: MetricConfig{Enabled: false},
SystemCPUTime: MetricConfig{Enabled: false},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadMetricsBuilderConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultMetricsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
func loadLogsBuilderConfig(t *testing.T, name string) LogsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultLogsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
func TestResourceAttributesConfig(t *testing.T) {
tests := []struct {
name string
want ResourceAttributesConfig
}{
{
name: "default",
want: DefaultResourceAttributesConfig(),
},
{
name: "all_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
{
name: "none_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
sub, err = sub.Sub("resource_attributes")
require.NoError(t, err)
cfg := DefaultResourceAttributesConfig()
require.NoError(t, sub.Unmarshal(&cfg))
return cfg
}
generated_logs.go 0000664 0000000 0000000 00000041475 15113313446 0034544 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"context"
conventions "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/filter"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/receiver"
)
type EventAttributeOption interface {
apply(plog.LogRecord)
}
type eventAttributeOptionFunc func(plog.LogRecord)
func (eaof eventAttributeOptionFunc) apply(lr plog.LogRecord) {
eaof(lr)
}
func WithConditionalIntAttrEventAttribute(conditionalIntAttrAttributeValue int64) EventAttributeOption {
return eventAttributeOptionFunc(func(dp plog.LogRecord) {
dp.Attributes().PutInt("conditional_int_attr", conditionalIntAttrAttributeValue)
})
}
func WithConditionalStringAttrEventAttribute(conditionalStringAttrAttributeValue string) EventAttributeOption {
return eventAttributeOptionFunc(func(dp plog.LogRecord) {
dp.Attributes().PutStr("conditional_string_attr", conditionalStringAttrAttributeValue)
})
}
type eventDefaultEvent struct {
data plog.LogRecordSlice // data buffer for generated log records.
config EventConfig // event config provided by user.
}
func (e *eventDefaultEvent) recordEvent(ctx context.Context, timestamp pcommon.Timestamp, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any, optInBoolAttrAttributeValue bool, options ...EventAttributeOption) {
if !e.config.Enabled {
return
}
dp := e.data.AppendEmpty()
dp.SetEventName("default.event")
dp.SetTimestamp(timestamp)
if span := trace.SpanContextFromContext(ctx); span.IsValid() {
dp.SetTraceID(pcommon.TraceID(span.TraceID()))
dp.SetSpanID(pcommon.SpanID(span.SpanID()))
}
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)
dp.Attributes().PutBool("opt_in_bool_attr", optInBoolAttrAttributeValue)
for _, op := range options {
op.apply(dp)
}
}
// emit appends recorded event data to a events slice and prepares it for recording another set of log records.
func (e *eventDefaultEvent) emit(lrs plog.LogRecordSlice) {
if e.config.Enabled && e.data.Len() > 0 {
e.data.MoveAndAppendTo(lrs)
}
}
func newEventDefaultEvent(cfg EventConfig) eventDefaultEvent {
e := eventDefaultEvent{config: cfg}
if cfg.Enabled {
e.data = plog.NewLogRecordSlice()
}
return e
}
type eventDefaultEventToBeRemoved struct {
data plog.LogRecordSlice // data buffer for generated log records.
config EventConfig // event config provided by user.
}
func (e *eventDefaultEventToBeRemoved) recordEvent(ctx context.Context, timestamp pcommon.Timestamp, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) {
if !e.config.Enabled {
return
}
dp := e.data.AppendEmpty()
dp.SetEventName("default.event.to_be_removed")
dp.SetTimestamp(timestamp)
if span := trace.SpanContextFromContext(ctx); span.IsValid() {
dp.SetTraceID(pcommon.TraceID(span.TraceID()))
dp.SetSpanID(pcommon.SpanID(span.SpanID()))
}
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)
}
// emit appends recorded event data to a events slice and prepares it for recording another set of log records.
func (e *eventDefaultEventToBeRemoved) emit(lrs plog.LogRecordSlice) {
if e.config.Enabled && e.data.Len() > 0 {
e.data.MoveAndAppendTo(lrs)
}
}
func newEventDefaultEventToBeRemoved(cfg EventConfig) eventDefaultEventToBeRemoved {
e := eventDefaultEventToBeRemoved{config: cfg}
if cfg.Enabled {
e.data = plog.NewLogRecordSlice()
}
return e
}
type eventDefaultEventToBeRenamed struct {
data plog.LogRecordSlice // data buffer for generated log records.
config EventConfig // event config provided by user.
}
func (e *eventDefaultEventToBeRenamed) recordEvent(ctx context.Context, timestamp pcommon.Timestamp, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool, options ...EventAttributeOption) {
if !e.config.Enabled {
return
}
dp := e.data.AppendEmpty()
dp.SetEventName("default.event.to_be_renamed")
dp.SetTimestamp(timestamp)
if span := trace.SpanContextFromContext(ctx); span.IsValid() {
dp.SetTraceID(pcommon.TraceID(span.TraceID()))
dp.SetSpanID(pcommon.SpanID(span.SpanID()))
}
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr2", booleanAttr2AttributeValue)
for _, op := range options {
op.apply(dp)
}
}
// emit appends recorded event data to a events slice and prepares it for recording another set of log records.
func (e *eventDefaultEventToBeRenamed) emit(lrs plog.LogRecordSlice) {
if e.config.Enabled && e.data.Len() > 0 {
e.data.MoveAndAppendTo(lrs)
}
}
func newEventDefaultEventToBeRenamed(cfg EventConfig) eventDefaultEventToBeRenamed {
e := eventDefaultEventToBeRenamed{config: cfg}
if cfg.Enabled {
e.data = plog.NewLogRecordSlice()
}
return e
}
// LogsBuilder provides an interface for scrapers to report logs while taking care of all the transformations
// required to produce log representation defined in metadata and user config.
type LogsBuilder struct {
config LogsBuilderConfig // config of the logs builder.
logsBuffer plog.Logs
logRecordsBuffer plog.LogRecordSlice
buildInfo component.BuildInfo // contains version information.
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
eventDefaultEvent eventDefaultEvent
eventDefaultEventToBeRemoved eventDefaultEventToBeRemoved
eventDefaultEventToBeRenamed eventDefaultEventToBeRenamed
}
// LogBuilderOption applies changes to default logs builder.
type LogBuilderOption interface {
apply(*LogsBuilder)
}
func NewLogsBuilder(lbc LogsBuilderConfig, settings receiver.Settings) *LogsBuilder {
if !lbc.Events.DefaultEvent.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.event`: This event will be disabled by default soon.")
}
if lbc.Events.DefaultEventToBeRemoved.Enabled {
settings.Logger.Warn("[WARNING] `default.event.to_be_removed` should not be enabled: This event is deprecated and will be removed soon.")
}
if lbc.Events.DefaultEventToBeRenamed.enabledSetByUser {
settings.Logger.Warn("[WARNING] `default.event.to_be_renamed` should not be configured: This event is deprecated and will be renamed soon.")
}
if !lbc.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 lbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || lbc.ResourceAttributes.StringResourceAttrRemoveWarning.EventsInclude != nil || lbc.ResourceAttributes.StringResourceAttrRemoveWarning.EventsExclude != 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 lbc.ResourceAttributes.StringResourceAttrToBeRemoved.Enabled {
settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.")
}
lb := &LogsBuilder{
config: lbc,
logsBuffer: plog.NewLogs(),
logRecordsBuffer: plog.NewLogRecordSlice(),
buildInfo: settings.BuildInfo,
eventDefaultEvent: newEventDefaultEvent(lbc.Events.DefaultEvent),
eventDefaultEventToBeRemoved: newEventDefaultEventToBeRemoved(lbc.Events.DefaultEventToBeRemoved),
eventDefaultEventToBeRenamed: newEventDefaultEventToBeRenamed(lbc.Events.DefaultEventToBeRenamed),
resourceAttributeIncludeFilter: make(map[string]filter.Filter),
resourceAttributeExcludeFilter: make(map[string]filter.Filter),
}
if lbc.ResourceAttributes.MapResourceAttr.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["map.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.MapResourceAttr.EventsInclude)
}
if lbc.ResourceAttributes.MapResourceAttr.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["map.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.MapResourceAttr.EventsExclude)
}
if lbc.ResourceAttributes.OptionalResourceAttr.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["optional.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.OptionalResourceAttr.EventsInclude)
}
if lbc.ResourceAttributes.OptionalResourceAttr.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["optional.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.OptionalResourceAttr.EventsExclude)
}
if lbc.ResourceAttributes.SliceResourceAttr.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["slice.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.SliceResourceAttr.EventsInclude)
}
if lbc.ResourceAttributes.SliceResourceAttr.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["slice.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.SliceResourceAttr.EventsExclude)
}
if lbc.ResourceAttributes.StringEnumResourceAttr.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["string.enum.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.StringEnumResourceAttr.EventsInclude)
}
if lbc.ResourceAttributes.StringEnumResourceAttr.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["string.enum.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.StringEnumResourceAttr.EventsExclude)
}
if lbc.ResourceAttributes.StringResourceAttr.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["string.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttr.EventsInclude)
}
if lbc.ResourceAttributes.StringResourceAttr.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["string.resource.attr"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttr.EventsExclude)
}
if lbc.ResourceAttributes.StringResourceAttrDisableWarning.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["string.resource.attr_disable_warning"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttrDisableWarning.EventsInclude)
}
if lbc.ResourceAttributes.StringResourceAttrDisableWarning.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["string.resource.attr_disable_warning"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttrDisableWarning.EventsExclude)
}
if lbc.ResourceAttributes.StringResourceAttrRemoveWarning.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["string.resource.attr_remove_warning"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttrRemoveWarning.EventsInclude)
}
if lbc.ResourceAttributes.StringResourceAttrRemoveWarning.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["string.resource.attr_remove_warning"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttrRemoveWarning.EventsExclude)
}
if lbc.ResourceAttributes.StringResourceAttrToBeRemoved.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["string.resource.attr_to_be_removed"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttrToBeRemoved.EventsInclude)
}
if lbc.ResourceAttributes.StringResourceAttrToBeRemoved.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["string.resource.attr_to_be_removed"] = filter.CreateFilter(lbc.ResourceAttributes.StringResourceAttrToBeRemoved.EventsExclude)
}
return lb
}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted logs.
func (lb *LogsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(lb.config.ResourceAttributes)
}
// ResourceLogsOption applies changes to provided resource logs.
type ResourceLogsOption interface {
apply(plog.ResourceLogs)
}
type resourceLogsOptionFunc func(plog.ResourceLogs)
func (rlof resourceLogsOptionFunc) apply(rl plog.ResourceLogs) {
rlof(rl)
}
// WithLogsResource sets the provided resource on the emitted ResourceLogs.
// It's recommended to use ResourceBuilder to create the resource.
func WithLogsResource(res pcommon.Resource) ResourceLogsOption {
return resourceLogsOptionFunc(func(rl plog.ResourceLogs) {
res.CopyTo(rl.Resource())
})
}
// AppendLogRecord adds a log record to the logs builder.
func (lb *LogsBuilder) AppendLogRecord(lr plog.LogRecord) {
lr.MoveTo(lb.logRecordsBuffer.AppendEmpty())
}
// EmitForResource saves all the generated logs under a new resource and updates the internal state to be ready for
// recording another set of log records as part of another resource. This function can be helpful when one scraper
// needs to emit logs from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceLogsOption arguments.
func (lb *LogsBuilder) EmitForResource(options ...ResourceLogsOption) {
rl := plog.NewResourceLogs()
rl.SetSchemaUrl(conventions.SchemaURL)
ils := rl.ScopeLogs().AppendEmpty()
ils.Scope().SetName(ScopeName)
ils.Scope().SetVersion(lb.buildInfo.Version)
lb.eventDefaultEvent.emit(ils.LogRecords())
lb.eventDefaultEventToBeRemoved.emit(ils.LogRecords())
lb.eventDefaultEventToBeRenamed.emit(ils.LogRecords())
for _, op := range options {
op.apply(rl)
}
if lb.logRecordsBuffer.Len() > 0 {
lb.logRecordsBuffer.MoveAndAppendTo(ils.LogRecords())
lb.logRecordsBuffer = plog.NewLogRecordSlice()
}
for attr, filter := range lb.resourceAttributeIncludeFilter {
if val, ok := rl.Resource().Attributes().Get(attr); ok && !filter.Matches(val.AsString()) {
return
}
}
for attr, filter := range lb.resourceAttributeExcludeFilter {
if val, ok := rl.Resource().Attributes().Get(attr); ok && filter.Matches(val.AsString()) {
return
}
}
if ils.LogRecords().Len() > 0 {
rl.MoveTo(lb.logsBuffer.ResourceLogs().AppendEmpty())
}
}
// Emit returns all the logs accumulated by the logs builder and updates the internal state to be ready for
// recording another set of logs. This function will be responsible for applying all the transformations required to
// produce logs representation defined in metadata and user config.
func (lb *LogsBuilder) Emit(options ...ResourceLogsOption) plog.Logs {
lb.EmitForResource(options...)
logs := lb.logsBuffer
lb.logsBuffer = plog.NewLogs()
return logs
}
// RecordDefaultEventEvent adds a log record of default.event event.
func (lb *LogsBuilder) RecordDefaultEventEvent(ctx context.Context, timestamp pcommon.Timestamp, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any, optInBoolAttrAttributeValue bool, options ...EventAttributeOption) {
lb.eventDefaultEvent.recordEvent(ctx, timestamp, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue, optInBoolAttrAttributeValue, options...)
}
// RecordDefaultEventToBeRemovedEvent adds a log record of default.event.to_be_removed event.
func (lb *LogsBuilder) RecordDefaultEventToBeRemovedEvent(ctx context.Context, timestamp pcommon.Timestamp, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) {
lb.eventDefaultEventToBeRemoved.recordEvent(ctx, timestamp, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue)
}
// RecordDefaultEventToBeRenamedEvent adds a log record of default.event.to_be_renamed event.
func (lb *LogsBuilder) RecordDefaultEventToBeRenamedEvent(ctx context.Context, timestamp pcommon.Timestamp, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool, options ...EventAttributeOption) {
lb.eventDefaultEventToBeRenamed.recordEvent(ctx, timestamp, stringAttrAttributeValue, booleanAttrAttributeValue, booleanAttr2AttributeValue, options...)
}
generated_logs_test.go 0000664 0000000 0000000 00000027205 15113313446 0035576 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/receiver/receivertest"
)
type eventsTestDataSet int
const (
eventTestDataSetDefault eventsTestDataSet = iota
eventTestDataSetAll
eventTestDataSetNone
)
func TestLogsBuilderAppendLogRecord(t *testing.T) {
observedZapCore, _ := observer.New(zap.WarnLevel)
settings := receivertest.NewNopSettings(receivertest.NopType)
settings.Logger = zap.New(observedZapCore)
lb := NewLogsBuilder(loadLogsBuilderConfig(t, "all_set"), settings)
rb := lb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
// append the first log record
lr := plog.NewLogRecord()
lr.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr.Attributes().PutStr("type", "log")
lr.Body().SetStr("the first log record")
// append the second log record
lr2 := plog.NewLogRecord()
lr2.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr2.Attributes().PutStr("type", "event")
lr2.Body().SetStr("the second log record")
lb.AppendLogRecord(lr)
lb.AppendLogRecord(lr2)
logs := lb.Emit(WithLogsResource(res))
assert.Equal(t, 1, logs.ResourceLogs().Len())
rl := logs.ResourceLogs().At(0)
assert.Equal(t, 1, rl.ScopeLogs().Len())
sl := rl.ScopeLogs().At(0)
assert.Equal(t, ScopeName, sl.Scope().Name())
assert.Equal(t, lb.buildInfo.Version, sl.Scope().Version())
assert.Equal(t, 2, sl.LogRecords().Len())
attrVal, ok := sl.LogRecords().At(0).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "log", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(0).Body().Type())
assert.Equal(t, "the first log record", sl.LogRecords().At(0).Body().Str())
attrVal, ok = sl.LogRecords().At(1).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "event", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(1).Body().Type())
assert.Equal(t, "the second log record", sl.LogRecords().At(1).Body().Str())
}
func TestLogsBuilder(t *testing.T) {
tests := []struct {
name string
eventsSet eventsTestDataSet
resAttrsSet eventsTestDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
eventsSet: eventTestDataSetAll,
resAttrsSet: eventTestDataSetAll,
},
{
name: "none_set",
eventsSet: eventTestDataSetNone,
resAttrsSet: eventTestDataSetNone,
expectEmpty: true,
},
{
name: "filter_set_include",
resAttrsSet: eventTestDataSetAll,
},
{
name: "filter_set_exclude",
resAttrsSet: eventTestDataSetAll,
expectEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
timestamp := pcommon.Timestamp(1_000_001_000)
traceID := [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
spanID := [8]byte{0, 1, 2, 3, 4, 5, 6, 7}
ctx := trace.ContextWithSpanContext(context.Background(), trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID(traceID),
SpanID: trace.SpanID(spanID),
TraceFlags: trace.FlagsSampled,
}))
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
settings := receivertest.NewNopSettings(receivertest.NopType)
settings.Logger = zap.New(observedZapCore)
lb := NewLogsBuilder(loadLogsBuilderConfig(t, tt.name), settings)
expectedWarnings := 0
if tt.eventsSet == eventTestDataSetDefault {
assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `default.event`: This event will be disabled by default soon.", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
if tt.eventsSet == eventTestDataSetDefault || tt.eventsSet == eventTestDataSetAll {
assert.Equal(t, "[WARNING] `default.event.to_be_removed` should not be enabled: This event is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
if tt.eventsSet == eventTestDataSetAll || tt.eventsSet == eventTestDataSetNone {
assert.Equal(t, "[WARNING] `default.event.to_be_renamed` should not be configured: This event is deprecated and will be renamed soon.", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
if tt.resAttrsSet == eventTestDataSetDefault {
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 tt.resAttrsSet == eventTestDataSetAll || tt.resAttrsSet == eventTestDataSetNone {
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 tt.resAttrsSet == eventTestDataSetDefault || tt.resAttrsSet == eventTestDataSetAll {
assert.Equal(t, "[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultEventsCount := 0
allEventsCount := 0
defaultEventsCount++
allEventsCount++
lb.RecordDefaultEventEvent(ctx, timestamp, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, true, WithConditionalIntAttrEventAttribute(20), WithConditionalStringAttrEventAttribute("conditional_string_attr-val"))
defaultEventsCount++
allEventsCount++
lb.RecordDefaultEventToBeRemovedEvent(ctx, timestamp, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"})
allEventsCount++
lb.RecordDefaultEventToBeRenamedEvent(ctx, timestamp, "string_attr-val", true, false, WithConditionalStringAttrEventAttribute("conditional_string_attr-val"))
rb := lb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
logs := lb.Emit(WithLogsResource(res))
if tt.expectEmpty || ((tt.name == "default" || tt.name == "filter_set_include") && defaultEventsCount == 0) {
assert.Equal(t, 0, logs.ResourceLogs().Len())
return
}
assert.Equal(t, 1, logs.ResourceLogs().Len())
rl := logs.ResourceLogs().At(0)
assert.Equal(t, res, rl.Resource())
assert.Equal(t, 1, rl.ScopeLogs().Len())
lrs := rl.ScopeLogs().At(0).LogRecords()
if tt.eventsSet == eventTestDataSetDefault {
assert.Equal(t, defaultEventsCount, lrs.Len())
}
if tt.eventsSet == eventTestDataSetAll {
assert.Equal(t, allEventsCount, lrs.Len())
}
validatedEvents := make(map[string]bool)
for i := 0; i < lrs.Len(); i++ {
switch lrs.At(i).EventName() {
case "default.event":
assert.False(t, validatedEvents["default.event"], "Found a duplicate in the events slice: default.event")
validatedEvents["default.event"] = true
lr := lrs.At(i)
assert.Equal(t, timestamp, lr.Timestamp())
assert.Equal(t, pcommon.TraceID(traceID), lr.TraceID())
assert.Equal(t, pcommon.SpanID(spanID), lr.SpanID())
attrVal, ok := lr.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = lr.Attributes().Get("state")
assert.True(t, ok)
assert.EqualValues(t, 19, attrVal.Int())
attrVal, ok = lr.Attributes().Get("enum_attr")
assert.True(t, ok)
assert.Equal(t, "red", attrVal.Str())
attrVal, ok = lr.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = lr.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw())
attrVal, ok = lr.Attributes().Get("conditional_int_attr")
assert.True(t, ok)
assert.EqualValues(t, 20, attrVal.Int())
attrVal, ok = lr.Attributes().Get("conditional_string_attr")
assert.True(t, ok)
assert.Equal(t, "conditional_string_attr-val", attrVal.Str())
attrVal, ok = lr.Attributes().Get("opt_in_bool_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
case "default.event.to_be_removed":
assert.False(t, validatedEvents["default.event.to_be_removed"], "Found a duplicate in the events slice: default.event.to_be_removed")
validatedEvents["default.event.to_be_removed"] = true
lr := lrs.At(i)
assert.Equal(t, timestamp, lr.Timestamp())
assert.Equal(t, pcommon.TraceID(traceID), lr.TraceID())
assert.Equal(t, pcommon.SpanID(spanID), lr.SpanID())
attrVal, ok := lr.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = lr.Attributes().Get("state")
assert.True(t, ok)
assert.EqualValues(t, 19, attrVal.Int())
attrVal, ok = lr.Attributes().Get("enum_attr")
assert.True(t, ok)
assert.Equal(t, "red", attrVal.Str())
attrVal, ok = lr.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = lr.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw())
case "default.event.to_be_renamed":
assert.False(t, validatedEvents["default.event.to_be_renamed"], "Found a duplicate in the events slice: default.event.to_be_renamed")
validatedEvents["default.event.to_be_renamed"] = true
lr := lrs.At(i)
assert.Equal(t, timestamp, lr.Timestamp())
assert.Equal(t, pcommon.TraceID(traceID), lr.TraceID())
assert.Equal(t, pcommon.SpanID(spanID), lr.SpanID())
attrVal, ok := lr.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = lr.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
attrVal, ok = lr.Attributes().Get("boolean_attr2")
assert.True(t, ok)
assert.False(t, attrVal.Bool())
attrVal, ok = lr.Attributes().Get("conditional_string_attr")
assert.True(t, ok)
assert.Equal(t, "conditional_string_attr-val", attrVal.Str())
}
}
})
}
}
generated_metrics.go 0000664 0000000 0000000 00000072235 15113313446 0035244 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"fmt"
"strconv"
"time"
conventions "go.opentelemetry.io/otel/semconv/v1.37.0"
"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"
)
// AttributeEnumAttr specifies the value enum_attr attribute.
type AttributeEnumAttr int
const (
_ AttributeEnumAttr = iota
AttributeEnumAttrRed
AttributeEnumAttrGreen
AttributeEnumAttrBlue
)
// String returns the string representation of the AttributeEnumAttr.
func (av AttributeEnumAttr) String() string {
switch av {
case AttributeEnumAttrRed:
return "red"
case AttributeEnumAttrGreen:
return "green"
case AttributeEnumAttrBlue:
return "blue"
}
return ""
}
// MapAttributeEnumAttr is a helper map of string to AttributeEnumAttr attribute value.
var MapAttributeEnumAttr = map[string]AttributeEnumAttr{
"red": AttributeEnumAttrRed,
"green": AttributeEnumAttrGreen,
"blue": AttributeEnumAttrBlue,
}
var MetricsInfo = metricsInfo{
DefaultMetric: metricInfo{
Name: "default.metric",
},
DefaultMetricToBeRemoved: metricInfo{
Name: "default.metric.to_be_removed",
},
MetricInputType: metricInfo{
Name: "metric.input_type",
},
OptionalMetric: metricInfo{
Name: "optional.metric",
},
OptionalMetricEmptyUnit: metricInfo{
Name: "optional.metric.empty_unit",
},
SystemCPUTime: metricInfo{
Name: "system.cpu.time",
},
}
type metricsInfo struct {
DefaultMetric metricInfo
DefaultMetricToBeRemoved metricInfo
MetricInputType metricInfo
OptionalMetric metricInfo
OptionalMetricEmptyUnit metricInfo
SystemCPUTime metricInfo
}
type metricInfo struct {
Name string
}
type MetricAttributeOption interface {
apply(pmetric.NumberDataPoint)
}
type metricAttributeOptionFunc func(pmetric.NumberDataPoint)
func (maof metricAttributeOptionFunc) apply(dp pmetric.NumberDataPoint) {
maof(dp)
}
func WithConditionalIntAttrMetricAttribute(conditionalIntAttrAttributeValue int64) MetricAttributeOption {
return metricAttributeOptionFunc(func(dp pmetric.NumberDataPoint) {
dp.Attributes().PutInt("conditional_int_attr", conditionalIntAttrAttributeValue)
})
}
func WithConditionalStringAttrMetricAttribute(conditionalStringAttrAttributeValue string) MetricAttributeOption {
return metricAttributeOptionFunc(func(dp pmetric.NumberDataPoint) {
dp.Attributes().PutStr("conditional_string_attr", conditionalStringAttrAttributeValue)
})
}
type metricDefaultMetric struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric metric with initial data.
func (m *metricDefaultMetric) init() {
m.data.SetName("default.metric")
m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(true)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
m.data.Sum().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricDefaultMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any, optInBoolAttrAttributeValue bool, options ...MetricAttributeOption) {
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)
dp.Attributes().PutBool("opt_in_bool_attr", optInBoolAttrAttributeValue)
for _, op := range options {
op.apply(dp)
}
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetric) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetric(cfg MetricConfig) metricDefaultMetric {
m := metricDefaultMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricDefaultMetricToBeRemoved struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric.to_be_removed metric with initial data.
func (m *metricDefaultMetricToBeRemoved) init() {
m.data.SetName("default.metric.to_be_removed")
m.data.SetDescription("[DEPRECATED] Non-monotonic delta sum double metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(false)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
}
func (m *metricDefaultMetricToBeRemoved) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetricToBeRemoved) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetricToBeRemoved) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBeRemoved {
m := metricDefaultMetricToBeRemoved{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type 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.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric metric with initial data.
func (m *metricOptionalMetric) init() {
m.data.SetName("optional.metric")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("1")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool, options ...MetricAttributeOption) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr2", booleanAttr2AttributeValue)
for _, op := range options {
op.apply(dp)
}
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetric) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetric(cfg MetricConfig) metricOptionalMetric {
m := metricOptionalMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricOptionalMetricEmptyUnit struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric.empty_unit metric with initial data.
func (m *metricOptionalMetricEmptyUnit) init() {
m.data.SetName("optional.metric.empty_unit")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetricEmptyUnit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetricEmptyUnit) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetricEmptyUnit) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetricEmptyUnit(cfg MetricConfig) metricOptionalMetricEmptyUnit {
m := metricOptionalMetricEmptyUnit{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricSystemCPUTime 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 system.cpu.time metric with initial data.
func (m *metricSystemCPUTime) init() {
m.data.SetName("system.cpu.time")
m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(true)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
}
func (m *metricSystemCPUTime) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetIntValue(val)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricSystemCPUTime) 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 *metricSystemCPUTime) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricSystemCPUTime(cfg MetricConfig) metricSystemCPUTime {
m := metricSystemCPUTime{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations
// required to produce metric representation defined in metadata and user config.
type MetricsBuilder struct {
config MetricsBuilderConfig // config of the metrics builder.
startTime pcommon.Timestamp // start time that will be applied to all recorded data points.
metricsCapacity int // maximum observed number of metrics per resource.
metricsBuffer pmetric.Metrics // accumulates metrics data before emitting.
buildInfo component.BuildInfo // contains version information.
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
metricDefaultMetric metricDefaultMetric
metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved
metricMetricInputType metricMetricInputType
metricOptionalMetric metricOptionalMetric
metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit
metricSystemCPUTime metricSystemCPUTime
}
// MetricBuilderOption applies changes to default metrics builder.
type MetricBuilderOption interface {
apply(*MetricsBuilder)
}
type metricBuilderOptionFunc func(mb *MetricsBuilder)
func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) {
mbof(mb)
}
// WithStartTime sets startTime on the metrics builder.
func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption {
return metricBuilderOptionFunc(func(mb *MetricsBuilder) {
mb.startTime = startTime
})
}
func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.Settings, options ...MetricBuilderOption) *MetricsBuilder {
if !mbc.Metrics.DefaultMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.")
}
if mbc.Metrics.DefaultMetricToBeRemoved.Enabled {
settings.Logger.Warn("[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetricEmptyUnit.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.")
}
if !mbc.ResourceAttributes.StringResourceAttrDisableWarning.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.")
}
if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || 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 {
settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.")
}
mb := &MetricsBuilder{
config: mbc,
startTime: pcommon.NewTimestampFromTime(time.Now()),
metricsBuffer: pmetric.NewMetrics(),
buildInfo: settings.BuildInfo,
metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric),
metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved),
metricMetricInputType: newMetricMetricInputType(mbc.Metrics.MetricInputType),
metricOptionalMetric: newMetricOptionalMetric(mbc.Metrics.OptionalMetric),
metricOptionalMetricEmptyUnit: newMetricOptionalMetricEmptyUnit(mbc.Metrics.OptionalMetricEmptyUnit),
metricSystemCPUTime: newMetricSystemCPUTime(mbc.Metrics.SystemCPUTime),
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.apply(mb)
}
return mb
}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics.
func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(mb.config.ResourceAttributes)
}
// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity.
func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) {
if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() {
mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len()
}
}
// ResourceMetricsOption applies changes to provided resource metrics.
type ResourceMetricsOption interface {
apply(pmetric.ResourceMetrics)
}
type resourceMetricsOptionFunc func(pmetric.ResourceMetrics)
func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) {
rmof(rm)
}
// WithResource sets the provided resource on the emitted ResourceMetrics.
// It's recommended to use ResourceBuilder to create the resource.
func WithResource(res pcommon.Resource) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
res.CopyTo(rm.Resource())
})
}
// WithStartTimeOverride overrides start time for all the resource metrics data points.
// This option should be only used if different start time has to be set on metrics coming from different resources.
func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
var dps pmetric.NumberDataPointSlice
metrics := rm.ScopeMetrics().At(0).Metrics()
for i := 0; i < metrics.Len(); i++ {
switch metrics.At(i).Type() {
case pmetric.MetricTypeGauge:
dps = metrics.At(i).Gauge().DataPoints()
case pmetric.MetricTypeSum:
dps = metrics.At(i).Sum().DataPoints()
}
for j := 0; j < dps.Len(); j++ {
dps.At(j).SetStartTimestamp(start)
}
}
})
}
// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for
// recording another set of data points as part of another resource. This function can be helpful when one scraper
// needs to emit metrics from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceMetricsOption arguments.
func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) {
rm := pmetric.NewResourceMetrics()
rm.SetSchemaUrl(conventions.SchemaURL)
ils := rm.ScopeMetrics().AppendEmpty()
ils.Scope().SetName(ScopeName)
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())
mb.metricSystemCPUTime.emit(ils.Metrics())
for _, op := range options {
op.apply(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())
}
}
// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for
// recording another set of metrics. This function will be responsible for applying all the transformations required to
// produce metric representation defined in metadata and user config, e.g. delta or cumulative.
func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics {
mb.EmitForResource(options...)
metrics := mb.metricsBuffer
mb.metricsBuffer = pmetric.NewMetrics()
return metrics
}
// RecordDefaultMetricDataPoint adds a data point to default.metric metric.
func (mb *MetricsBuilder) RecordDefaultMetricDataPoint(ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any, optInBoolAttrAttributeValue bool, options ...MetricAttributeOption) {
mb.metricDefaultMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue, optInBoolAttrAttributeValue, options...)
}
// RecordDefaultMetricToBeRemovedDataPoint adds a data point to default.metric.to_be_removed metric.
func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Timestamp, val float64) {
mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val)
}
// 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, booleanAttr2AttributeValue bool, options ...MetricAttributeOption) {
mb.metricOptionalMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue, booleanAttr2AttributeValue, options...)
}
// RecordOptionalMetricEmptyUnitDataPoint adds a data point to optional.metric.empty_unit metric.
func (mb *MetricsBuilder) RecordOptionalMetricEmptyUnitDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
mb.metricOptionalMetricEmptyUnit.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue)
}
// RecordSystemCPUTimeDataPoint adds a data point to system.cpu.time metric.
func (mb *MetricsBuilder) RecordSystemCPUTimeDataPoint(ts pcommon.Timestamp, val int64) {
mb.metricSystemCPUTime.recordDataPoint(mb.startTime, ts, val)
}
// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted,
// and metrics builder should update its startTime and reset it's internal state accordingly.
func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) {
mb.startTime = pcommon.NewTimestampFromTime(time.Now())
for _, op := range options {
op.apply(mb)
}
}
generated_metrics_test.go 0000664 0000000 0000000 00000032714 15113313446 0036301 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver/receivertest"
)
type testDataSet int
const (
testDataSetDefault testDataSet = iota
testDataSetAll
testDataSetNone
)
func TestMetricsBuilder(t *testing.T) {
tests := []struct {
name string
metricsSet testDataSet
resAttrsSet testDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
metricsSet: testDataSetAll,
resAttrsSet: testDataSetAll,
},
{
name: "none_set",
metricsSet: testDataSetNone,
resAttrsSet: testDataSetNone,
expectEmpty: true,
},
{
name: "filter_set_include",
resAttrsSet: testDataSetAll,
},
{
name: "filter_set_exclude",
resAttrsSet: testDataSetAll,
expectEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
start := pcommon.Timestamp(1_000_000_000)
ts := pcommon.Timestamp(1_000_001_000)
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
settings := receivertest.NewNopSettings(receivertest.NopType)
settings.Logger = zap.New(observedZapCore)
mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start))
expectedWarnings := 0
if tt.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 tt.metricsSet == testDataSetDefault || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.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 tt.resAttrsSet == testDataSetAll || tt.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 tt.resAttrsSet == testDataSetDefault || tt.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++
}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultMetricsCount := 0
allMetricsCount := 0
defaultMetricsCount++
allMetricsCount++
mb.RecordDefaultMetricDataPoint(ts, 1, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, true, WithConditionalIntAttrMetricAttribute(20), WithConditionalStringAttrMetricAttribute("conditional_string_attr-val"))
defaultMetricsCount++
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, false, WithConditionalStringAttrMetricAttribute("conditional_string_attr-val"))
allMetricsCount++
mb.RecordOptionalMetricEmptyUnitDataPoint(ts, 1, "string_attr-val", true)
defaultMetricsCount++
allMetricsCount++
mb.RecordSystemCPUTimeDataPoint(ts, 1)
rb := mb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
metrics := mb.Emit(WithResource(res))
if tt.expectEmpty {
assert.Equal(t, 0, metrics.ResourceMetrics().Len())
return
}
assert.Equal(t, 1, metrics.ResourceMetrics().Len())
rm := metrics.ResourceMetrics().At(0)
assert.Equal(t, res, rm.Resource())
assert.Equal(t, 1, rm.ScopeMetrics().Len())
ms := rm.ScopeMetrics().At(0).Metrics()
if tt.metricsSet == testDataSetDefault {
assert.Equal(t, defaultMetricsCount, ms.Len())
}
if tt.metricsSet == testDataSetAll {
assert.Equal(t, allMetricsCount, ms.Len())
}
validatedMetrics := make(map[string]bool)
for i := 0; i < ms.Len(); i++ {
switch ms.At(i).Name() {
case "default.metric":
assert.False(t, validatedMetrics["default.metric"], "Found a duplicate in the metrics slice: default.metric")
validatedMetrics["default.metric"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw())
attrVal, ok = dp.Attributes().Get("conditional_int_attr")
assert.True(t, ok)
assert.EqualValues(t, 20, attrVal.Int())
attrVal, ok = dp.Attributes().Get("conditional_string_attr")
assert.True(t, ok)
assert.Equal(t, "conditional_string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("opt_in_bool_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
case "default.metric.to_be_removed":
assert.False(t, validatedMetrics["default.metric.to_be_removed"], "Found a duplicate in the metrics slice: default.metric.to_be_removed")
validatedMetrics["default.metric.to_be_removed"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.False(t, ms.At(i).Sum().IsMonotonic())
assert.Equal(t, pmetric.AggregationTemporalityDelta, ms.At(i).Sum().AggregationTemporality())
dp := ms.At(i).Sum().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
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.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(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
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Equal(t, "1", ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
attrVal, ok = dp.Attributes().Get("boolean_attr2")
assert.True(t, ok)
assert.False(t, attrVal.Bool())
attrVal, ok = dp.Attributes().Get("conditional_string_attr")
assert.True(t, ok)
assert.Equal(t, "conditional_string_attr-val", attrVal.Str())
case "optional.metric.empty_unit":
assert.False(t, validatedMetrics["optional.metric.empty_unit"], "Found a duplicate in the metrics slice: optional.metric.empty_unit")
validatedMetrics["optional.metric.empty_unit"] = true
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Empty(t, ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
case "system.cpu.time":
assert.False(t, validatedMetrics["system.cpu.time"], "Found a duplicate in the metrics slice: system.cpu.time")
validatedMetrics["system.cpu.time"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.True(t, 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())
}
}
})
}
}
generated_resource.go 0000664 0000000 0000000 00000006426 15113313446 0035424 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/pdata/pcommon"
)
// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml.
// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines.
type ResourceBuilder struct {
config ResourceAttributesConfig
res pcommon.Resource
}
// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application.
func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder {
return &ResourceBuilder{
config: rac,
res: pcommon.NewResource(),
}
}
// SetMapResourceAttr sets provided value as "map.resource.attr" attribute.
func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) {
if rb.config.MapResourceAttr.Enabled {
rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val)
}
}
// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute.
func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) {
if rb.config.OptionalResourceAttr.Enabled {
rb.res.Attributes().PutStr("optional.resource.attr", val)
}
}
// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute.
func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) {
if rb.config.SliceResourceAttr.Enabled {
rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val)
}
}
// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "one")
}
}
// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "two")
}
}
// SetStringResourceAttr sets provided value as "string.resource.attr" attribute.
func (rb *ResourceBuilder) SetStringResourceAttr(val string) {
if rb.config.StringResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.resource.attr", val)
}
}
// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) {
if rb.config.StringResourceAttrDisableWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val)
}
}
// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) {
if rb.config.StringResourceAttrRemoveWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val)
}
}
// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) {
if rb.config.StringResourceAttrToBeRemoved.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val)
}
}
// Emit returns the built resource and resets the internal builder state.
func (rb *ResourceBuilder) Emit() pcommon.Resource {
r := rb.res
rb.res = pcommon.NewResource()
return r
}
generated_resource_test.go 0000664 0000000 0000000 00000005421 15113313446 0036455 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestResourceBuilder(t *testing.T) {
for _, tt := range []string{"default", "all_set", "none_set"} {
t.Run(tt, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt)
rb := NewResourceBuilder(cfg)
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource
switch tt {
case "default":
assert.Equal(t, 6, res.Attributes().Len())
case "all_set":
assert.Equal(t, 8, res.Attributes().Len())
case "none_set":
assert.Equal(t, 0, res.Attributes().Len())
return
default:
assert.Failf(t, "unexpected test case: %s", tt)
}
val, ok := res.Attributes().Get("map.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw())
}
val, ok = res.Attributes().Get("optional.resource.attr")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "optional.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("slice.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw())
}
val, ok = res.Attributes().Get("string.enum.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "one", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_disable_warning")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_disable_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_remove_warning")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "string.resource.attr_remove_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_to_be_removed")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_to_be_removed-val", val.Str())
}
})
}
}
generated_status.go 0000664 0000000 0000000 00000000733 15113313446 0035113 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/component"
)
var (
Type = component.MustNewType("sample")
ScopeName = "go.opentelemetry.io/collector/internal/receiver/samplereceiver"
)
const (
ProfilesStability = component.StabilityLevelDeprecated
LogsStability = component.StabilityLevelDevelopment
TracesStability = component.StabilityLevelBeta
MetricsStability = component.StabilityLevelStable
)
generated_telemetry.go 0000664 0000000 0000000 00000011304 15113313446 0035576 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"context"
"errors"
"sync"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/collector/component"
)
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")
}
// TelemetryBuilder provides an interface for components to report telemetry
// as defined in metadata and user config.
type TelemetryBuilder struct {
meter metric.Meter
mu sync.Mutex
registrations []metric.Registration
BatchSizeTriggerSend metric.Int64Counter
ProcessRuntimeTotalAllocBytes metric.Int64ObservableCounter
QueueCapacity metric.Int64Gauge
QueueLength metric.Int64ObservableGauge
RequestDuration metric.Float64Histogram
}
// TelemetryBuilderOption applies changes to default builder.
type TelemetryBuilderOption interface {
apply(*TelemetryBuilder)
}
type telemetryBuilderOptionFunc func(mb *TelemetryBuilder)
func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) {
tbof(mb)
}
// RegisterProcessRuntimeTotalAllocBytesCallback sets callback for observable ProcessRuntimeTotalAllocBytes metric.
func (builder *TelemetryBuilder) RegisterProcessRuntimeTotalAllocBytesCallback(cb metric.Int64Callback) error {
reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error {
cb(ctx, &observerInt64{inst: builder.ProcessRuntimeTotalAllocBytes, obs: o})
return nil
}, builder.ProcessRuntimeTotalAllocBytes)
if err != nil {
return err
}
builder.mu.Lock()
defer builder.mu.Unlock()
builder.registrations = append(builder.registrations, reg)
return nil
}
// RegisterQueueLengthCallback sets callback for observable QueueLength metric.
func (builder *TelemetryBuilder) RegisterQueueLengthCallback(cb metric.Int64Callback) error {
reg, err := builder.meter.RegisterCallback(func(ctx context.Context, o metric.Observer) error {
cb(ctx, &observerInt64{inst: builder.QueueLength, obs: o})
return nil
}, builder.QueueLength)
if err != nil {
return err
}
builder.mu.Lock()
defer builder.mu.Unlock()
builder.registrations = append(builder.registrations, reg)
return nil
}
type observerInt64 struct {
embedded.Int64Observer
inst metric.Int64Observable
obs metric.Observer
}
func (oi *observerInt64) Observe(value int64, opts ...metric.ObserveOption) {
oi.obs.ObserveInt64(oi.inst, value, opts...)
}
// Shutdown unregister all registered callbacks for async instruments.
func (builder *TelemetryBuilder) Shutdown() {
builder.mu.Lock()
defer builder.mu.Unlock()
for _, reg := range builder.registrations {
reg.Unregister()
}
}
// NewTelemetryBuilder provides a struct with methods to update all internal telemetry
// for a component
func NewTelemetryBuilder(settings component.TelemetrySettings, options ...TelemetryBuilderOption) (*TelemetryBuilder, error) {
builder := TelemetryBuilder{}
for _, op := range options {
op.apply(&builder)
}
builder.meter = Meter(settings)
var err, errs error
builder.BatchSizeTriggerSend, err = builder.meter.Int64Counter(
"otelcol_batch_size_trigger_send",
metric.WithDescription("Number of times the batch was sent due to a size trigger [Deprecated since v0.110.0]"),
metric.WithUnit("{times}"),
)
errs = errors.Join(errs, err)
builder.ProcessRuntimeTotalAllocBytes, err = builder.meter.Int64ObservableCounter(
"otelcol_process_runtime_total_alloc_bytes",
metric.WithDescription("Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')"),
metric.WithUnit("By"),
)
errs = errors.Join(errs, err)
builder.QueueCapacity, err = builder.meter.Int64Gauge(
"otelcol_queue_capacity",
metric.WithDescription("Queue capacity - sync gauge example. [Development]"),
metric.WithUnit("{items}"),
)
errs = errors.Join(errs, err)
builder.QueueLength, err = builder.meter.Int64ObservableGauge(
"otelcol_queue_length",
metric.WithDescription("This metric is optional and therefore not initialized in NewTelemetryBuilder. [Alpha]"),
metric.WithUnit("{items}"),
)
errs = errors.Join(errs, err)
builder.RequestDuration, err = builder.meter.Float64Histogram(
"otelcol_request_duration",
metric.WithDescription("Duration of request [Alpha]"),
metric.WithUnit("s"),
metric.WithExplicitBucketBoundaries([]float64{1, 10, 100}...),
)
errs = errors.Join(errs, err)
return &builder, errs
}
generated_telemetry_test.go 0000664 0000000 0000000 00000003523 15113313446 0036641 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata // 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"
"go.opentelemetry.io/collector/component/componenttest"
)
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")
}
}
func TestNewTelemetryBuilder(t *testing.T) {
set := componenttest.NewNopTelemetrySettings()
applied := false
_, err := NewTelemetryBuilder(set, telemetryBuilderOptionFunc(func(b *TelemetryBuilder) {
applied = true
}))
require.NoError(t, err)
require.True(t, applied)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata/testdata/ 0000775 0000000 0000000 00000000000 15113313446 0033110 5 ustar 00root root 0000000 0000000 config.yaml 0000664 0000000 0000000 00000010607 15113313446 0035166 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadata/testdata 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
system.cpu.time:
enabled: true
events:
default.event:
enabled: true
default.event.to_be_removed:
enabled: true
default.event.to_be_renamed:
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
system.cpu.time:
enabled: false
events:
default.event:
enabled: false
default.event.to_be_removed:
enabled: false
default.event.to_be_renamed:
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: ".*"
events_include:
- regexp: ".*"
optional.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
slice.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.enum.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr_disable_warning:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr_remove_warning:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
string.resource.attr_to_be_removed:
enabled: true
metrics_include:
- regexp: ".*"
events_include:
- regexp: ".*"
filter_set_exclude:
resource_attributes:
map.resource.attr:
enabled: true
metrics_exclude:
- regexp: ".*"
events_exclude:
- regexp: ".*"
optional.resource.attr:
enabled: true
metrics_exclude:
- strict: "optional.resource.attr-val"
events_exclude:
- strict: "optional.resource.attr-val"
slice.resource.attr:
enabled: true
metrics_exclude:
- regexp: ".*"
events_exclude:
- regexp: ".*"
string.enum.resource.attr:
enabled: true
metrics_exclude:
- strict: "one"
events_exclude:
- strict: "one"
string.resource.attr:
enabled: true
metrics_exclude:
- strict: "string.resource.attr-val"
events_exclude:
- strict: "string.resource.attr-val"
string.resource.attr_disable_warning:
enabled: true
metrics_exclude:
- strict: "string.resource.attr_disable_warning-val"
events_exclude:
- strict: "string.resource.attr_disable_warning-val"
string.resource.attr_remove_warning:
enabled: true
metrics_exclude:
- strict: "string.resource.attr_remove_warning-val"
events_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"
events_exclude:
- strict: "string.resource.attr_to_be_removed-val"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/ 0000775 0000000 0000000 00000000000 15113313446 0032177 5 ustar 00root root 0000000 0000000 generated_telemetrytest.go 0000664 0000000 0000000 00000006725 15113313446 0037411 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadatatest // Code generated by mdatagen. DO NOT EDIT.
package metadatatest
import (
"testing"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/receiver"
"go.opentelemetry.io/collector/receiver/receivertest"
)
func NewSettings(tt *componenttest.Telemetry) receiver.Settings {
set := receivertest.NewNopSettings(receivertest.NopType)
set.ID = component.NewID(component.MustNewType("sample"))
set.TelemetrySettings = tt.NewTelemetrySettings()
return set
}
func AssertEqualBatchSizeTriggerSend(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) {
want := metricdata.Metrics{
Name: "otelcol_batch_size_trigger_send",
Description: "Number of times the batch was sent due to a size trigger [Deprecated since v0.110.0]",
Unit: "{times}",
Data: metricdata.Sum[int64]{
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
DataPoints: dps,
},
}
got, err := tt.GetMetric("otelcol_batch_size_trigger_send")
require.NoError(t, err)
metricdatatest.AssertEqual(t, want, got, opts...)
}
func AssertEqualProcessRuntimeTotalAllocBytes(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) {
want := metricdata.Metrics{
Name: "otelcol_process_runtime_total_alloc_bytes",
Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')",
Unit: "By",
Data: metricdata.Sum[int64]{
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
DataPoints: dps,
},
}
got, err := tt.GetMetric("otelcol_process_runtime_total_alloc_bytes")
require.NoError(t, err)
metricdatatest.AssertEqual(t, want, got, opts...)
}
func AssertEqualQueueCapacity(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) {
want := metricdata.Metrics{
Name: "otelcol_queue_capacity",
Description: "Queue capacity - sync gauge example. [Development]",
Unit: "{items}",
Data: metricdata.Gauge[int64]{
DataPoints: dps,
},
}
got, err := tt.GetMetric("otelcol_queue_capacity")
require.NoError(t, err)
metricdatatest.AssertEqual(t, want, got, opts...)
}
func AssertEqualQueueLength(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) {
want := metricdata.Metrics{
Name: "otelcol_queue_length",
Description: "This metric is optional and therefore not initialized in NewTelemetryBuilder. [Alpha]",
Unit: "{items}",
Data: metricdata.Gauge[int64]{
DataPoints: dps,
},
}
got, err := tt.GetMetric("otelcol_queue_length")
require.NoError(t, err)
metricdatatest.AssertEqual(t, want, got, opts...)
}
func AssertEqualRequestDuration(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.HistogramDataPoint[float64], opts ...metricdatatest.Option) {
want := metricdata.Metrics{
Name: "otelcol_request_duration",
Description: "Duration of request [Alpha]",
Unit: "s",
Data: metricdata.Histogram[float64]{
Temporality: metricdata.CumulativeTemporality,
DataPoints: dps,
},
}
got, err := tt.GetMetric("otelcol_request_duration")
require.NoError(t, err)
metricdatatest.AssertEqual(t, want, got, opts...)
}
generated_telemetrytest_test.go 0000664 0000000 0000000 00000003451 15113313446 0040441 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/internal/metadatatest // Code generated by mdatagen. DO NOT EDIT.
package metadatatest
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata"
"go.opentelemetry.io/collector/component/componenttest"
)
func TestSetupTelemetry(t *testing.T) {
testTel := componenttest.NewTelemetry()
tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings())
require.NoError(t, err)
defer tb.Shutdown()
require.NoError(t, tb.RegisterProcessRuntimeTotalAllocBytesCallback(func(_ context.Context, observer metric.Int64Observer) error {
observer.Observe(1)
return nil
}))
require.NoError(t, tb.RegisterQueueLengthCallback(func(_ context.Context, observer metric.Int64Observer) error {
observer.Observe(1)
return nil
}))
tb.BatchSizeTriggerSend.Add(context.Background(), 1)
tb.QueueCapacity.Record(context.Background(), 1)
tb.RequestDuration.Record(context.Background(), 1)
AssertEqualBatchSizeTriggerSend(t, testTel,
[]metricdata.DataPoint[int64]{{Value: 1}},
metricdatatest.IgnoreTimestamp())
AssertEqualProcessRuntimeTotalAllocBytes(t, testTel,
[]metricdata.DataPoint[int64]{{Value: 1}},
metricdatatest.IgnoreTimestamp())
AssertEqualQueueCapacity(t, testTel,
[]metricdata.DataPoint[int64]{{Value: 1}},
metricdatatest.IgnoreTimestamp())
AssertEqualQueueLength(t, testTel,
[]metricdata.DataPoint[int64]{{Value: 1}},
metricdatatest.IgnoreTimestamp())
AssertEqualRequestDuration(t, testTel,
[]metricdata.HistogramDataPoint[float64]{{}}, metricdatatest.IgnoreValue(),
metricdatatest.IgnoreTimestamp())
require.NoError(t, testTel.Shutdown(context.Background()))
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/metadata.yaml 0000664 0000000 0000000 00000020356 15113313446 0030355 0 ustar 00root root 0000000 0000000 # Sample metadata file with all available configurations for a receiver.
type: sample
scope_name: go.opentelemetry.io/collector/internal/receiver/samplereceiver
github_project: open-telemetry/opentelemetry-collector
sem_conv_version: 1.37.0
status:
disable_codecov_badge: true
class: receiver
stability:
development: [logs]
beta: [traces]
stable: [metrics]
deprecated: [profiles]
deprecation:
profiles:
migration: "no migration needed"
date: "2025-02-05"
distributions: []
unsupported_platforms: [freebsd, illumos]
codeowners:
active: [dmitryax]
warnings:
- Any additional information that should be brought to the consumer's attention
resource_attributes:
map.resource.attr:
description: Resource attribute with a map value.
type: map
enabled: true
optional.resource.attr:
description: Explicitly disabled ResourceAttribute.
type: string
enabled: false
slice.resource.attr:
description: Resource attribute with a slice value.
type: slice
enabled: true
string.enum.resource.attr:
description: Resource attribute with a known set of string values.
type: string
enum: [one, two]
enabled: true
string.resource.attr:
description: Resource attribute with any string value.
type: string
enabled: true
string.resource.attr_disable_warning:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled_not_set: This resource_attribute will be disabled by default soon.
string.resource.attr_remove_warning:
description: Resource attribute with any string value.
type: string
enabled: false
warnings:
if_configured: This resource_attribute is deprecated and will be removed soon.
string.resource.attr_to_be_removed:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled: This resource_attribute is deprecated and will be removed soon.
attributes:
boolean_attr:
description: Attribute with a boolean value.
type: bool
# This 2nd boolean attribute allows us to test both values for boolean attributes,
# as test values are based on the parity of the attribute name length.
boolean_attr2:
description: Another attribute with a boolean value.
type: bool
conditional_int_attr:
description: A conditional attribute with an integer value
type: int
requirement_level: conditionally_required
conditional_string_attr:
description: A conditional attribute with any string value
type: string
requirement_level: conditionally_required
enum_attr:
description: Attribute with a known set of string values.
type: string
enum: [red, green, blue]
map_attr:
description: Attribute with a map value.
type: map
opt_in_bool_attr:
description: An opt-in attribute with a boolean value
type: bool
requirement_level: opt_in
overridden_int_attr:
name_override: state
description: Integer attribute with overridden name.
type: int
slice_attr:
description: Attribute with a slice value.
type: slice
string_attr:
description: Attribute with any string value.
type: string
events:
default.event:
enabled: true
description: Example event enabled by default.
attributes:
[
string_attr,
overridden_int_attr,
enum_attr,
slice_attr,
map_attr,
conditional_int_attr,
conditional_string_attr,
opt_in_bool_attr,
]
warnings:
if_enabled_not_set: This event will be disabled by default soon.
default.event.to_be_removed:
enabled: true
description: "[DEPRECATED] Example to-be-removed event enabled by default."
extended_documentation: The event will be removed soon.
warnings:
if_enabled: This event is deprecated and will be removed soon.
attributes:
[string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr]
default.event.to_be_renamed:
enabled: false
description: "[DEPRECATED] Example event disabled by default."
extended_documentation: The event will be renamed soon.
attributes: [string_attr, boolean_attr, boolean_attr2, conditional_string_attr]
warnings:
if_configured: This event is deprecated and will be renamed soon.
metrics:
default.metric:
enabled: true
description: Monotonic cumulative sum int metric enabled by default.
extended_documentation: The metric will be become optional soon.
stability:
level: development
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
attributes:
[
string_attr,
overridden_int_attr,
enum_attr,
slice_attr,
map_attr,
conditional_int_attr,
conditional_string_attr,
opt_in_bool_attr,
]
warnings:
if_enabled_not_set: This metric will be disabled by default soon.
default.metric.to_be_removed:
enabled: true
description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default."
extended_documentation: The metric will be removed soon.
stability:
level: deprecated
unit: s
sum:
value_type: double
monotonic: false
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.
stability:
level: development
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]
optional.metric:
enabled: false
description: "[DEPRECATED] Gauge double metric disabled by default."
stability:
level: deprecated
unit: "1"
gauge:
value_type: double
attributes: [string_attr, boolean_attr, boolean_attr2, conditional_string_attr]
warnings:
if_configured: This metric is deprecated and will be removed soon.
optional.metric.empty_unit:
enabled: false
description: "[DEPRECATED] Gauge double metric disabled by default."
stability:
level: deprecated
unit: ""
gauge:
value_type: double
attributes: [string_attr, boolean_attr]
warnings:
if_configured: This metric is deprecated and will be removed soon.
system.cpu.time:
enabled: true
stability:
level: beta
description: Monotonic cumulative sum int metric enabled by default.
extended_documentation: The metric will be become optional soon.
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
semantic_convention:
ref: https://github.com/open-telemetry/semantic-conventions/blob/v1.37.0/docs/system/system-metrics.md#metric-systemcputime
telemetry:
metrics:
batch_size_trigger_send:
enabled: true
stability:
level: deprecated
from: v0.110.0
description: Number of times the batch was sent due to a size trigger
unit: "{times}"
sum:
value_type: int
monotonic: true
process_runtime_total_alloc_bytes:
enabled: true
stability:
level: stable
description: Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')
unit: By
sum:
async: true
value_type: int
monotonic: true
queue_capacity:
enabled: true
description: Queue capacity - sync gauge example.
stability:
level: development
unit: "{items}"
gauge:
value_type: int
queue_length:
enabled: true
stability:
level: alpha
description: This metric is optional and therefore not initialized in NewTelemetryBuilder.
extended_documentation: For example this metric only exists if feature A is enabled.
unit: "{items}"
optional: true
gauge:
async: true
value_type: int
request_duration:
enabled: true
stability:
level: alpha
description: Duration of request
unit: s
histogram:
value_type: double
bucket_boundaries: [1, 10, 100]
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplereceiver/metrics_test.go 0000664 0000000 0000000 00000003433 15113313446 0030742 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package samplereceiver
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadatatest"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/consumer/consumertest"
"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.NewNopSettings(metadata.Type))
m := mb.Emit()
require.Equal(t, 0, m.ResourceMetrics().Len())
}
func TestComponentTelemetry(t *testing.T) {
tt := componenttest.NewTelemetry()
factory := NewFactory()
receiver, err := factory.CreateMetrics(context.Background(), metadatatest.NewSettings(tt), newMdatagenNopHost(), new(consumertest.MetricsSink))
require.NoError(t, err)
metadatatest.AssertEqualBatchSizeTriggerSend(t, tt,
[]metricdata.DataPoint[int64]{
{
Value: 1,
},
}, metricdatatest.IgnoreTimestamp())
metadatatest.AssertEqualProcessRuntimeTotalAllocBytes(t, tt,
[]metricdata.DataPoint[int64]{
{
Value: 2,
},
}, metricdatatest.IgnoreTimestamp())
rcv, ok := receiver.(nopReceiver)
require.True(t, ok)
rcv.initOptionalMetric()
metadatatest.AssertEqualQueueLength(t, tt,
[]metricdata.DataPoint[int64]{
{
Value: 3,
},
}, metricdatatest.IgnoreTimestamp())
require.NoError(t, tt.Shutdown(context.Background()))
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/ 0000775 0000000 0000000 00000000000 15113313446 0025536 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/README.md 0000664 0000000 0000000 00000003122 15113313446 0027013 0 ustar 00root root 0000000 0000000 # Sample Scraper
This scraper is used for testing purposes to check the output of mdatagen.
| Status | |
| ------------- |-----------|
| Stability | [development]: logs |
| | [stable]: metrics |
| Unsupported Platforms | freebsd, illumos |
| Distributions | [] |
| Warnings | [Any additional information that should be brought to the consumer's attention](#warnings) |
| Issues | [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aopen+is%3Aissue+label%3Ascraper%2Fsample) [](https://github.com/open-telemetry/opentelemetry-collector/issues?q=is%3Aclosed+is%3Aissue+label%3Ascraper%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/blob/main/docs/component-stability.md#development
[stable]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stable
## Warnings
This is where warnings are described.
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/doc.go 0000664 0000000 0000000 00000000472 15113313446 0026635 0 ustar 00root root 0000000 0000000 // 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
package samplescraper // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplescraper"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/documentation.md 0000664 0000000 0000000 00000011530 15113313446 0030731 0 ustar 00root root 0000000 0000000 [comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
# sample
## Default Metrics
The following metrics are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
metrics:
:
enabled: false
```
### default.metric
Monotonic cumulative sum int metric enabled by default.
The metric will be become optional soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Int | Cumulative | true | Development |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| state | Integer attribute with overridden name. | Any Int | Recommended |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | Recommended |
| slice_attr | Attribute with a slice value. | Any Slice | Recommended |
| map_attr | Attribute with a map value. | Any Map | Recommended |
### default.metric.to_be_removed
[DEPRECATED] Non-monotonic delta sum double metric enabled by default.
The metric will be removed soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Double | Delta | false | Deprecated |
### metric.input_type
Monotonic cumulative sum int metric with string input_type enabled by default.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- |
| s | Sum | Int | Cumulative | true | Development |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| state | Integer attribute with overridden name. | Any Int | Recommended |
| enum_attr | Attribute with a known set of string values. | Str: ``red``, ``green``, ``blue`` | Recommended |
| slice_attr | Attribute with a slice value. | Any Slice | Recommended |
| map_attr | Attribute with a map value. | Any Map | Recommended |
### system.cpu.time
Monotonic cumulative sum int metric enabled by default.
The metric will be become optional soon.
| Unit | Metric Type | Value Type | Aggregation Temporality | Monotonic | Stability | Semantic Convention |
| ---- | ----------- | ---------- | ----------------------- | --------- | --------- | ------------------- |
| s | Sum | Int | Cumulative | true | Beta | [system.cpu.time](https://github.com/open-telemetry/semantic-conventions/blob/v1.37.0/docs/system/system-metrics.md#metric-systemcputime) |
## Optional Metrics
The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
metrics:
:
enabled: true
```
### optional.metric
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| 1 | Gauge | Double | Deprecated |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| boolean_attr | Attribute with a boolean value. | Any Bool | Recommended |
| boolean_attr2 | Another attribute with a boolean value. | Any Bool | Recommended |
### optional.metric.empty_unit
[DEPRECATED] Gauge double metric disabled by default.
| Unit | Metric Type | Value Type | Stability |
| ---- | ----------- | ---------- | --------- |
| | Gauge | Double | Deprecated |
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
| string_attr | Attribute with any string value. | Any Str | Recommended |
| boolean_attr | Attribute with a boolean value. | Any Bool | Recommended |
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| map.resource.attr | Resource attribute with a map value. | Any Map | true |
| optional.resource.attr | Explicitly disabled ResourceAttribute. | Any Str | false |
| slice.resource.attr | Resource attribute with a slice value. | Any Slice | true |
| string.enum.resource.attr | Resource attribute with a known set of string values. | Str: ``one``, ``two`` | true |
| string.resource.attr | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_disable_warning | Resource attribute with any string value. | Any Str | true |
| string.resource.attr_remove_warning | Resource attribute with any string value. | Any Str | false |
| string.resource.attr_to_be_removed | Resource attribute with any string value. | Any Str | true |
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/factory.go 0000664 0000000 0000000 00000002245 15113313446 0027537 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package samplescraper // import "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplescraper"
import (
"context"
"go.opentelemetry.io/collector/cmd/mdatagen/internal/samplescraper/internal/metadata"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/scraper"
)
// NewFactory returns a receiver.Factory for sample receiver.
func NewFactory() scraper.Factory {
return scraper.NewFactory(
metadata.Type,
func() component.Config { return &struct{}{} },
scraper.WithMetrics(createMetrics, metadata.MetricsStability),
scraper.WithLogs(createLogs, metadata.LogsStability))
}
func createMetrics(context.Context, scraper.Settings, component.Config) (scraper.Metrics, error) {
return scraper.NewMetrics(func(context.Context) (pmetric.Metrics, error) {
return pmetric.NewMetrics(), nil
})
}
func createLogs(context.Context, scraper.Settings, component.Config) (scraper.Logs, error) {
return scraper.NewLogs(func(context.Context) (plog.Logs, error) { return plog.Logs{}, nil })
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/generated_component_test.go 0000664 0000000 0000000 00000005334 15113313446 0033151 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
//go:build !freebsd && !illumos
package samplescraper
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/scraper"
"go.opentelemetry.io/collector/scraper/scrapertest"
)
var typ = component.MustNewType("sample")
func TestComponentFactoryType(t *testing.T) {
require.Equal(t, typ, NewFactory().Type())
}
func TestComponentConfigStruct(t *testing.T) {
require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()))
}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct {
createFn func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error)
name string
}{
{
name: "logs",
createFn: func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg)
},
},
{
name: "metrics",
createFn: func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(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, sub.Unmarshal(&cfg))
for _, tt := range tests {
t.Run(tt.name+"-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), scrapertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
t.Run(tt.name+"-lifecycle", func(t *testing.T) {
firstRcvr, err := tt.createFn(context.Background(), scrapertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := newMdatagenNopHost()
require.NoError(t, err)
require.NoError(t, firstRcvr.Start(context.Background(), host))
require.NoError(t, firstRcvr.Shutdown(context.Background()))
secondRcvr, err := tt.createFn(context.Background(), scrapertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondRcvr.Start(context.Background(), host))
require.NoError(t, secondRcvr.Shutdown(context.Background()))
})
}
}
var _ component.Host = (*mdatagenNopHost)(nil)
type mdatagenNopHost struct{}
func newMdatagenNopHost() component.Host {
return &mdatagenNopHost{}
}
func (mnh *mdatagenNopHost) GetExtensions() map[component.ID]component.Component {
return nil
}
func (mnh *mdatagenNopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory {
return nil
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/generated_package_test.go 0000664 0000000 0000000 00000000254 15113313446 0032536 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package samplescraper
import (
"testing"
"go.uber.org/goleak"
)
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/ 0000775 0000000 0000000 00000000000 15113313446 0027352 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata/ 0000775 0000000 0000000 00000000000 15113313446 0031132 5 ustar 00root root 0000000 0000000 generated_config.go 0000664 0000000 0000000 00000010744 15113313446 0034673 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/filter"
)
// MetricConfig provides common config for a particular metric.
type MetricConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ms)
if err != nil {
return err
}
ms.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// MetricsConfig provides config for 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"`
SystemCPUTime MetricConfig `mapstructure:"system.cpu.time"`
}
func DefaultMetricsConfig() MetricsConfig {
return MetricsConfig{
DefaultMetric: MetricConfig{
Enabled: true,
},
DefaultMetricToBeRemoved: MetricConfig{
Enabled: true,
},
MetricInputType: MetricConfig{
Enabled: true,
},
OptionalMetric: MetricConfig{
Enabled: false,
},
OptionalMetricEmptyUnit: MetricConfig{
Enabled: false,
},
SystemCPUTime: MetricConfig{
Enabled: true,
},
}
}
// 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
}
func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(rac)
if err != nil {
return err
}
rac.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// ResourceAttributesConfig provides config for sample resource attributes.
type ResourceAttributesConfig struct {
MapResourceAttr ResourceAttributeConfig `mapstructure:"map.resource.attr"`
OptionalResourceAttr ResourceAttributeConfig `mapstructure:"optional.resource.attr"`
SliceResourceAttr ResourceAttributeConfig `mapstructure:"slice.resource.attr"`
StringEnumResourceAttr ResourceAttributeConfig `mapstructure:"string.enum.resource.attr"`
StringResourceAttr ResourceAttributeConfig `mapstructure:"string.resource.attr"`
StringResourceAttrDisableWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_disable_warning"`
StringResourceAttrRemoveWarning ResourceAttributeConfig `mapstructure:"string.resource.attr_remove_warning"`
StringResourceAttrToBeRemoved ResourceAttributeConfig `mapstructure:"string.resource.attr_to_be_removed"`
}
func DefaultResourceAttributesConfig() ResourceAttributesConfig {
return ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
OptionalResourceAttr: ResourceAttributeConfig{
Enabled: false,
},
SliceResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringEnumResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttr: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrDisableWarning: ResourceAttributeConfig{
Enabled: true,
},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{
Enabled: false,
},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{
Enabled: true,
},
}
}
// MetricsBuilderConfig is a configuration for sample metrics builder.
type MetricsBuilderConfig struct {
Metrics MetricsConfig `mapstructure:"metrics"`
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
}
func DefaultMetricsBuilderConfig() MetricsBuilderConfig {
return MetricsBuilderConfig{
Metrics: DefaultMetricsConfig(),
ResourceAttributes: DefaultResourceAttributesConfig(),
}
}
generated_config_test.go 0000664 0000000 0000000 00000013175 15113313446 0035733 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
)
func TestMetricsBuilderConfig(t *testing.T) {
tests := []struct {
name string
want MetricsBuilderConfig
}{
{
name: "default",
want: DefaultMetricsBuilderConfig(),
},
{
name: "all_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: true},
DefaultMetricToBeRemoved: MetricConfig{Enabled: true},
MetricInputType: MetricConfig{Enabled: true},
OptionalMetric: MetricConfig{Enabled: true},
OptionalMetricEmptyUnit: MetricConfig{Enabled: true},
SystemCPUTime: MetricConfig{Enabled: true},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
},
{
name: "none_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
DefaultMetric: MetricConfig{Enabled: false},
DefaultMetricToBeRemoved: MetricConfig{Enabled: false},
MetricInputType: MetricConfig{Enabled: false},
OptionalMetric: MetricConfig{Enabled: false},
OptionalMetricEmptyUnit: MetricConfig{Enabled: false},
SystemCPUTime: MetricConfig{Enabled: false},
},
ResourceAttributes: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadMetricsBuilderConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}, ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultMetricsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
func TestResourceAttributesConfig(t *testing.T) {
tests := []struct {
name string
want ResourceAttributesConfig
}{
{
name: "default",
want: DefaultResourceAttributesConfig(),
},
{
name: "all_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: true},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: true},
SliceResourceAttr: ResourceAttributeConfig{Enabled: true},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttr: ResourceAttributeConfig{Enabled: true},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: true},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: true},
},
},
{
name: "none_set",
want: ResourceAttributesConfig{
MapResourceAttr: ResourceAttributeConfig{Enabled: false},
OptionalResourceAttr: ResourceAttributeConfig{Enabled: false},
SliceResourceAttr: ResourceAttributeConfig{Enabled: false},
StringEnumResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttr: ResourceAttributeConfig{Enabled: false},
StringResourceAttrDisableWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrRemoveWarning: ResourceAttributeConfig{Enabled: false},
StringResourceAttrToBeRemoved: ResourceAttributeConfig{Enabled: false},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
sub, err = sub.Sub("resource_attributes")
require.NoError(t, err)
cfg := DefaultResourceAttributesConfig()
require.NoError(t, sub.Unmarshal(&cfg))
return cfg
}
generated_logs.go 0000664 0000000 0000000 00000006570 15113313446 0034374 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
conventions "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/scraper"
)
// LogsBuilder provides an interface for scrapers to report logs while taking care of all the transformations
// required to produce log representation defined in metadata and user config.
type LogsBuilder struct {
logsBuffer plog.Logs
logRecordsBuffer plog.LogRecordSlice
buildInfo component.BuildInfo // contains version information.
}
// LogBuilderOption applies changes to default logs builder.
type LogBuilderOption interface {
apply(*LogsBuilder)
}
func NewLogsBuilder(settings scraper.Settings) *LogsBuilder {
lb := &LogsBuilder{
logsBuffer: plog.NewLogs(),
logRecordsBuffer: plog.NewLogRecordSlice(),
buildInfo: settings.BuildInfo,
}
return lb
}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted logs.
func (lb *LogsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(ResourceAttributesConfig{})
}
// ResourceLogsOption applies changes to provided resource logs.
type ResourceLogsOption interface {
apply(plog.ResourceLogs)
}
type resourceLogsOptionFunc func(plog.ResourceLogs)
func (rlof resourceLogsOptionFunc) apply(rl plog.ResourceLogs) {
rlof(rl)
}
// WithLogsResource sets the provided resource on the emitted ResourceLogs.
// It's recommended to use ResourceBuilder to create the resource.
func WithLogsResource(res pcommon.Resource) ResourceLogsOption {
return resourceLogsOptionFunc(func(rl plog.ResourceLogs) {
res.CopyTo(rl.Resource())
})
}
// AppendLogRecord adds a log record to the logs builder.
func (lb *LogsBuilder) AppendLogRecord(lr plog.LogRecord) {
lr.MoveTo(lb.logRecordsBuffer.AppendEmpty())
}
// EmitForResource saves all the generated logs under a new resource and updates the internal state to be ready for
// recording another set of log records as part of another resource. This function can be helpful when one scraper
// needs to emit logs from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceLogsOption arguments.
func (lb *LogsBuilder) EmitForResource(options ...ResourceLogsOption) {
rl := plog.NewResourceLogs()
rl.SetSchemaUrl(conventions.SchemaURL)
ils := rl.ScopeLogs().AppendEmpty()
ils.Scope().SetName(ScopeName)
ils.Scope().SetVersion(lb.buildInfo.Version)
for _, op := range options {
op.apply(rl)
}
if lb.logRecordsBuffer.Len() > 0 {
lb.logRecordsBuffer.MoveAndAppendTo(ils.LogRecords())
lb.logRecordsBuffer = plog.NewLogRecordSlice()
}
if ils.LogRecords().Len() > 0 {
rl.MoveTo(lb.logsBuffer.ResourceLogs().AppendEmpty())
}
}
// Emit returns all the logs accumulated by the logs builder and updates the internal state to be ready for
// recording another set of logs. This function will be responsible for applying all the transformations required to
// produce logs representation defined in metadata and user config.
func (lb *LogsBuilder) Emit(options ...ResourceLogsOption) plog.Logs {
lb.EmitForResource(options...)
logs := lb.logsBuffer
lb.logsBuffer = plog.NewLogs()
return logs
}
generated_logs_test.go 0000664 0000000 0000000 00000005015 15113313446 0035424 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
"go.opentelemetry.io/collector/scraper/scrapertest"
)
func TestLogsBuilderAppendLogRecord(t *testing.T) {
observedZapCore, _ := observer.New(zap.WarnLevel)
settings := scrapertest.NewNopSettings(scrapertest.NopType)
settings.Logger = zap.New(observedZapCore)
lb := NewLogsBuilder(settings)
rb := lb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
// append the first log record
lr := plog.NewLogRecord()
lr.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr.Attributes().PutStr("type", "log")
lr.Body().SetStr("the first log record")
// append the second log record
lr2 := plog.NewLogRecord()
lr2.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr2.Attributes().PutStr("type", "event")
lr2.Body().SetStr("the second log record")
lb.AppendLogRecord(lr)
lb.AppendLogRecord(lr2)
logs := lb.Emit(WithLogsResource(res))
assert.Equal(t, 1, logs.ResourceLogs().Len())
rl := logs.ResourceLogs().At(0)
assert.Equal(t, 1, rl.ScopeLogs().Len())
sl := rl.ScopeLogs().At(0)
assert.Equal(t, ScopeName, sl.Scope().Name())
assert.Equal(t, lb.buildInfo.Version, sl.Scope().Version())
assert.Equal(t, 2, sl.LogRecords().Len())
attrVal, ok := sl.LogRecords().At(0).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "log", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(0).Body().Type())
assert.Equal(t, "the first log record", sl.LogRecords().At(0).Body().Str())
attrVal, ok = sl.LogRecords().At(1).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "event", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(1).Body().Type())
assert.Equal(t, "the second log record", sl.LogRecords().At(1).Body().Str())
}
generated_metrics.go 0000664 0000000 0000000 00000067760 15113313446 0035106 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"fmt"
"strconv"
"time"
conventions "go.opentelemetry.io/otel/semconv/v1.37.0"
"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/scraper"
)
// AttributeEnumAttr specifies the value enum_attr attribute.
type AttributeEnumAttr int
const (
_ AttributeEnumAttr = iota
AttributeEnumAttrRed
AttributeEnumAttrGreen
AttributeEnumAttrBlue
)
// String returns the string representation of the AttributeEnumAttr.
func (av AttributeEnumAttr) String() string {
switch av {
case AttributeEnumAttrRed:
return "red"
case AttributeEnumAttrGreen:
return "green"
case AttributeEnumAttrBlue:
return "blue"
}
return ""
}
// MapAttributeEnumAttr is a helper map of string to AttributeEnumAttr attribute value.
var MapAttributeEnumAttr = map[string]AttributeEnumAttr{
"red": AttributeEnumAttrRed,
"green": AttributeEnumAttrGreen,
"blue": AttributeEnumAttrBlue,
}
var MetricsInfo = metricsInfo{
DefaultMetric: metricInfo{
Name: "default.metric",
},
DefaultMetricToBeRemoved: metricInfo{
Name: "default.metric.to_be_removed",
},
MetricInputType: metricInfo{
Name: "metric.input_type",
},
OptionalMetric: metricInfo{
Name: "optional.metric",
},
OptionalMetricEmptyUnit: metricInfo{
Name: "optional.metric.empty_unit",
},
SystemCPUTime: metricInfo{
Name: "system.cpu.time",
},
}
type metricsInfo struct {
DefaultMetric metricInfo
DefaultMetricToBeRemoved metricInfo
MetricInputType metricInfo
OptionalMetric metricInfo
OptionalMetricEmptyUnit metricInfo
SystemCPUTime metricInfo
}
type metricInfo struct {
Name string
}
type metricDefaultMetric struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric metric with initial data.
func (m *metricDefaultMetric) init() {
m.data.SetName("default.metric")
m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(true)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
m.data.Sum().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricDefaultMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue string, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetIntValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutInt("state", overriddenIntAttrAttributeValue)
dp.Attributes().PutStr("enum_attr", enumAttrAttributeValue)
dp.Attributes().PutEmptySlice("slice_attr").FromRaw(sliceAttrAttributeValue)
dp.Attributes().PutEmptyMap("map_attr").FromRaw(mapAttrAttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetric) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetric(cfg MetricConfig) metricDefaultMetric {
m := metricDefaultMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricDefaultMetricToBeRemoved struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills default.metric.to_be_removed metric with initial data.
func (m *metricDefaultMetricToBeRemoved) init() {
m.data.SetName("default.metric.to_be_removed")
m.data.SetDescription("[DEPRECATED] Non-monotonic delta sum double metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(false)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityDelta)
}
func (m *metricDefaultMetricToBeRemoved) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricDefaultMetricToBeRemoved) updateCapacity() {
if m.data.Sum().DataPoints().Len() > m.capacity {
m.capacity = m.data.Sum().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricDefaultMetricToBeRemoved) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricDefaultMetricToBeRemoved(cfg MetricConfig) metricDefaultMetricToBeRemoved {
m := metricDefaultMetricToBeRemoved{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type 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.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric metric with initial data.
func (m *metricOptionalMetric) init() {
m.data.SetName("optional.metric")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("1")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetric) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool, booleanAttr2AttributeValue bool) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr2", booleanAttr2AttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetric) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetric) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetric(cfg MetricConfig) metricOptionalMetric {
m := metricOptionalMetric{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricOptionalMetricEmptyUnit struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills optional.metric.empty_unit metric with initial data.
func (m *metricOptionalMetricEmptyUnit) init() {
m.data.SetName("optional.metric.empty_unit")
m.data.SetDescription("[DEPRECATED] Gauge double metric disabled by default.")
m.data.SetUnit("")
m.data.SetEmptyGauge()
m.data.Gauge().DataPoints().EnsureCapacity(m.capacity)
}
func (m *metricOptionalMetricEmptyUnit) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
if !m.config.Enabled {
return
}
dp := m.data.Gauge().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetDoubleValue(val)
dp.Attributes().PutStr("string_attr", stringAttrAttributeValue)
dp.Attributes().PutBool("boolean_attr", booleanAttrAttributeValue)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricOptionalMetricEmptyUnit) updateCapacity() {
if m.data.Gauge().DataPoints().Len() > m.capacity {
m.capacity = m.data.Gauge().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metricOptionalMetricEmptyUnit) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Gauge().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricOptionalMetricEmptyUnit(cfg MetricConfig) metricOptionalMetricEmptyUnit {
m := metricOptionalMetricEmptyUnit{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
type metricSystemCPUTime 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 system.cpu.time metric with initial data.
func (m *metricSystemCPUTime) init() {
m.data.SetName("system.cpu.time")
m.data.SetDescription("Monotonic cumulative sum int metric enabled by default.")
m.data.SetUnit("s")
m.data.SetEmptySum()
m.data.Sum().SetIsMonotonic(true)
m.data.Sum().SetAggregationTemporality(pmetric.AggregationTemporalityCumulative)
}
func (m *metricSystemCPUTime) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val int64) {
if !m.config.Enabled {
return
}
dp := m.data.Sum().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.SetIntValue(val)
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metricSystemCPUTime) 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 *metricSystemCPUTime) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.Sum().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetricSystemCPUTime(cfg MetricConfig) metricSystemCPUTime {
m := metricSystemCPUTime{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations
// required to produce metric representation defined in metadata and user config.
type MetricsBuilder struct {
config MetricsBuilderConfig // config of the metrics builder.
startTime pcommon.Timestamp // start time that will be applied to all recorded data points.
metricsCapacity int // maximum observed number of metrics per resource.
metricsBuffer pmetric.Metrics // accumulates metrics data before emitting.
buildInfo component.BuildInfo // contains version information.
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
metricDefaultMetric metricDefaultMetric
metricDefaultMetricToBeRemoved metricDefaultMetricToBeRemoved
metricMetricInputType metricMetricInputType
metricOptionalMetric metricOptionalMetric
metricOptionalMetricEmptyUnit metricOptionalMetricEmptyUnit
metricSystemCPUTime metricSystemCPUTime
}
// MetricBuilderOption applies changes to default metrics builder.
type MetricBuilderOption interface {
apply(*MetricsBuilder)
}
type metricBuilderOptionFunc func(mb *MetricsBuilder)
func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) {
mbof(mb)
}
// WithStartTime sets startTime on the metrics builder.
func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption {
return metricBuilderOptionFunc(func(mb *MetricsBuilder) {
mb.startTime = startTime
})
}
func NewMetricsBuilder(mbc MetricsBuilderConfig, settings scraper.Settings, options ...MetricBuilderOption) *MetricsBuilder {
if !mbc.Metrics.DefaultMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `default.metric`: This metric will be disabled by default soon.")
}
if mbc.Metrics.DefaultMetricToBeRemoved.Enabled {
settings.Logger.Warn("[WARNING] `default.metric.to_be_removed` should not be enabled: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetric.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric` should not be configured: This metric is deprecated and will be removed soon.")
}
if mbc.Metrics.OptionalMetricEmptyUnit.enabledSetByUser {
settings.Logger.Warn("[WARNING] `optional.metric.empty_unit` should not be configured: This metric is deprecated and will be removed soon.")
}
if !mbc.ResourceAttributes.StringResourceAttrDisableWarning.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `string.resource.attr_disable_warning`: This resource_attribute will be disabled by default soon.")
}
if mbc.ResourceAttributes.StringResourceAttrRemoveWarning.enabledSetByUser || 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 {
settings.Logger.Warn("[WARNING] `string.resource.attr_to_be_removed` should not be enabled: This resource_attribute is deprecated and will be removed soon.")
}
mb := &MetricsBuilder{
config: mbc,
startTime: pcommon.NewTimestampFromTime(time.Now()),
metricsBuffer: pmetric.NewMetrics(),
buildInfo: settings.BuildInfo,
metricDefaultMetric: newMetricDefaultMetric(mbc.Metrics.DefaultMetric),
metricDefaultMetricToBeRemoved: newMetricDefaultMetricToBeRemoved(mbc.Metrics.DefaultMetricToBeRemoved),
metricMetricInputType: newMetricMetricInputType(mbc.Metrics.MetricInputType),
metricOptionalMetric: newMetricOptionalMetric(mbc.Metrics.OptionalMetric),
metricOptionalMetricEmptyUnit: newMetricOptionalMetricEmptyUnit(mbc.Metrics.OptionalMetricEmptyUnit),
metricSystemCPUTime: newMetricSystemCPUTime(mbc.Metrics.SystemCPUTime),
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.apply(mb)
}
return mb
}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics.
func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(mb.config.ResourceAttributes)
}
// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity.
func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) {
if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() {
mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len()
}
}
// ResourceMetricsOption applies changes to provided resource metrics.
type ResourceMetricsOption interface {
apply(pmetric.ResourceMetrics)
}
type resourceMetricsOptionFunc func(pmetric.ResourceMetrics)
func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) {
rmof(rm)
}
// WithResource sets the provided resource on the emitted ResourceMetrics.
// It's recommended to use ResourceBuilder to create the resource.
func WithResource(res pcommon.Resource) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
res.CopyTo(rm.Resource())
})
}
// WithStartTimeOverride overrides start time for all the resource metrics data points.
// This option should be only used if different start time has to be set on metrics coming from different resources.
func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
var dps pmetric.NumberDataPointSlice
metrics := rm.ScopeMetrics().At(0).Metrics()
for i := 0; i < metrics.Len(); i++ {
switch metrics.At(i).Type() {
case pmetric.MetricTypeGauge:
dps = metrics.At(i).Gauge().DataPoints()
case pmetric.MetricTypeSum:
dps = metrics.At(i).Sum().DataPoints()
}
for j := 0; j < dps.Len(); j++ {
dps.At(j).SetStartTimestamp(start)
}
}
})
}
// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for
// recording another set of data points as part of another resource. This function can be helpful when one scraper
// needs to emit metrics from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceMetricsOption arguments.
func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) {
rm := pmetric.NewResourceMetrics()
rm.SetSchemaUrl(conventions.SchemaURL)
ils := rm.ScopeMetrics().AppendEmpty()
ils.Scope().SetName(ScopeName)
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())
mb.metricSystemCPUTime.emit(ils.Metrics())
for _, op := range options {
op.apply(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())
}
}
// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for
// recording another set of metrics. This function will be responsible for applying all the transformations required to
// produce metric representation defined in metadata and user config, e.g. delta or cumulative.
func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics {
mb.EmitForResource(options...)
metrics := mb.metricsBuffer
mb.metricsBuffer = pmetric.NewMetrics()
return metrics
}
// RecordDefaultMetricDataPoint adds a data point to default.metric metric.
func (mb *MetricsBuilder) RecordDefaultMetricDataPoint(ts pcommon.Timestamp, val int64, stringAttrAttributeValue string, overriddenIntAttrAttributeValue int64, enumAttrAttributeValue AttributeEnumAttr, sliceAttrAttributeValue []any, mapAttrAttributeValue map[string]any) {
mb.metricDefaultMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, overriddenIntAttrAttributeValue, enumAttrAttributeValue.String(), sliceAttrAttributeValue, mapAttrAttributeValue)
}
// RecordDefaultMetricToBeRemovedDataPoint adds a data point to default.metric.to_be_removed metric.
func (mb *MetricsBuilder) RecordDefaultMetricToBeRemovedDataPoint(ts pcommon.Timestamp, val float64) {
mb.metricDefaultMetricToBeRemoved.recordDataPoint(mb.startTime, ts, val)
}
// 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, booleanAttr2AttributeValue bool) {
mb.metricOptionalMetric.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue, booleanAttr2AttributeValue)
}
// RecordOptionalMetricEmptyUnitDataPoint adds a data point to optional.metric.empty_unit metric.
func (mb *MetricsBuilder) RecordOptionalMetricEmptyUnitDataPoint(ts pcommon.Timestamp, val float64, stringAttrAttributeValue string, booleanAttrAttributeValue bool) {
mb.metricOptionalMetricEmptyUnit.recordDataPoint(mb.startTime, ts, val, stringAttrAttributeValue, booleanAttrAttributeValue)
}
// RecordSystemCPUTimeDataPoint adds a data point to system.cpu.time metric.
func (mb *MetricsBuilder) RecordSystemCPUTimeDataPoint(ts pcommon.Timestamp, val int64) {
mb.metricSystemCPUTime.recordDataPoint(mb.startTime, ts, val)
}
// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted,
// and metrics builder should update its startTime and reset it's internal state accordingly.
func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) {
mb.startTime = pcommon.NewTimestampFromTime(time.Now())
for _, op := range options {
op.apply(mb)
}
}
generated_metrics_test.go 0000664 0000000 0000000 00000031317 15113313446 0036132 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/scraper/scrapertest"
)
type testDataSet int
const (
testDataSetDefault testDataSet = iota
testDataSetAll
testDataSetNone
)
func TestMetricsBuilder(t *testing.T) {
tests := []struct {
name string
metricsSet testDataSet
resAttrsSet testDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
metricsSet: testDataSetAll,
resAttrsSet: testDataSetAll,
},
{
name: "none_set",
metricsSet: testDataSetNone,
resAttrsSet: testDataSetNone,
expectEmpty: true,
},
{
name: "filter_set_include",
resAttrsSet: testDataSetAll,
},
{
name: "filter_set_exclude",
resAttrsSet: testDataSetAll,
expectEmpty: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
start := pcommon.Timestamp(1_000_000_000)
ts := pcommon.Timestamp(1_000_001_000)
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
settings := scrapertest.NewNopSettings(scrapertest.NopType)
settings.Logger = zap.New(observedZapCore)
mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start))
expectedWarnings := 0
if tt.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 tt.metricsSet == testDataSetDefault || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.metricsSet == testDataSetAll || tt.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 tt.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 tt.resAttrsSet == testDataSetAll || tt.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 tt.resAttrsSet == testDataSetDefault || tt.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++
}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultMetricsCount := 0
allMetricsCount := 0
defaultMetricsCount++
allMetricsCount++
mb.RecordDefaultMetricDataPoint(ts, 1, "string_attr-val", 19, AttributeEnumAttrRed, []any{"slice_attr-item1", "slice_attr-item2"}, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"})
defaultMetricsCount++
allMetricsCount++
mb.RecordDefaultMetricToBeRemovedDataPoint(ts, 1)
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, false)
allMetricsCount++
mb.RecordOptionalMetricEmptyUnitDataPoint(ts, 1, "string_attr-val", true)
defaultMetricsCount++
allMetricsCount++
mb.RecordSystemCPUTimeDataPoint(ts, 1)
rb := mb.NewResourceBuilder()
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
metrics := mb.Emit(WithResource(res))
if tt.expectEmpty {
assert.Equal(t, 0, metrics.ResourceMetrics().Len())
return
}
assert.Equal(t, 1, metrics.ResourceMetrics().Len())
rm := metrics.ResourceMetrics().At(0)
assert.Equal(t, res, rm.Resource())
assert.Equal(t, 1, rm.ScopeMetrics().Len())
ms := rm.ScopeMetrics().At(0).Metrics()
if tt.metricsSet == testDataSetDefault {
assert.Equal(t, defaultMetricsCount, ms.Len())
}
if tt.metricsSet == testDataSetAll {
assert.Equal(t, allMetricsCount, ms.Len())
}
validatedMetrics := make(map[string]bool)
for i := 0; i < ms.Len(); i++ {
switch ms.At(i).Name() {
case "default.metric":
assert.False(t, validatedMetrics["default.metric"], "Found a duplicate in the metrics slice: default.metric")
validatedMetrics["default.metric"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(t, map[string]any{"key1": "map_attr-val1", "key2": "map_attr-val2"}, attrVal.Map().AsRaw())
case "default.metric.to_be_removed":
assert.False(t, validatedMetrics["default.metric.to_be_removed"], "Found a duplicate in the metrics slice: default.metric.to_be_removed")
validatedMetrics["default.metric.to_be_removed"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Non-monotonic delta sum double metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.False(t, ms.At(i).Sum().IsMonotonic())
assert.Equal(t, pmetric.AggregationTemporalityDelta, ms.At(i).Sum().AggregationTemporality())
dp := ms.At(i).Sum().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
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.True(t, 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.Equal(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.Equal(t, "red", attrVal.Str())
attrVal, ok = dp.Attributes().Get("slice_attr")
assert.True(t, ok)
assert.Equal(t, []any{"slice_attr-item1", "slice_attr-item2"}, attrVal.Slice().AsRaw())
attrVal, ok = dp.Attributes().Get("map_attr")
assert.True(t, ok)
assert.Equal(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
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Equal(t, "1", ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
attrVal, ok = dp.Attributes().Get("boolean_attr2")
assert.True(t, ok)
assert.False(t, attrVal.Bool())
case "optional.metric.empty_unit":
assert.False(t, validatedMetrics["optional.metric.empty_unit"], "Found a duplicate in the metrics slice: optional.metric.empty_unit")
validatedMetrics["optional.metric.empty_unit"] = true
assert.Equal(t, pmetric.MetricTypeGauge, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Gauge().DataPoints().Len())
assert.Equal(t, "[DEPRECATED] Gauge double metric disabled by default.", ms.At(i).Description())
assert.Empty(t, ms.At(i).Unit())
dp := ms.At(i).Gauge().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueTypeDouble, dp.ValueType())
assert.InDelta(t, float64(1), dp.DoubleValue(), 0.01)
attrVal, ok := dp.Attributes().Get("string_attr")
assert.True(t, ok)
assert.Equal(t, "string_attr-val", attrVal.Str())
attrVal, ok = dp.Attributes().Get("boolean_attr")
assert.True(t, ok)
assert.True(t, attrVal.Bool())
case "system.cpu.time":
assert.False(t, validatedMetrics["system.cpu.time"], "Found a duplicate in the metrics slice: system.cpu.time")
validatedMetrics["system.cpu.time"] = true
assert.Equal(t, pmetric.MetricTypeSum, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).Sum().DataPoints().Len())
assert.Equal(t, "Monotonic cumulative sum int metric enabled by default.", ms.At(i).Description())
assert.Equal(t, "s", ms.At(i).Unit())
assert.True(t, 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())
}
}
})
}
}
generated_resource.go 0000664 0000000 0000000 00000006426 15113313446 0035257 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/pdata/pcommon"
)
// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml.
// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines.
type ResourceBuilder struct {
config ResourceAttributesConfig
res pcommon.Resource
}
// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application.
func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder {
return &ResourceBuilder{
config: rac,
res: pcommon.NewResource(),
}
}
// SetMapResourceAttr sets provided value as "map.resource.attr" attribute.
func (rb *ResourceBuilder) SetMapResourceAttr(val map[string]any) {
if rb.config.MapResourceAttr.Enabled {
rb.res.Attributes().PutEmptyMap("map.resource.attr").FromRaw(val)
}
}
// SetOptionalResourceAttr sets provided value as "optional.resource.attr" attribute.
func (rb *ResourceBuilder) SetOptionalResourceAttr(val string) {
if rb.config.OptionalResourceAttr.Enabled {
rb.res.Attributes().PutStr("optional.resource.attr", val)
}
}
// SetSliceResourceAttr sets provided value as "slice.resource.attr" attribute.
func (rb *ResourceBuilder) SetSliceResourceAttr(val []any) {
if rb.config.SliceResourceAttr.Enabled {
rb.res.Attributes().PutEmptySlice("slice.resource.attr").FromRaw(val)
}
}
// SetStringEnumResourceAttrOne sets "string.enum.resource.attr=one" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrOne() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "one")
}
}
// SetStringEnumResourceAttrTwo sets "string.enum.resource.attr=two" attribute.
func (rb *ResourceBuilder) SetStringEnumResourceAttrTwo() {
if rb.config.StringEnumResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.enum.resource.attr", "two")
}
}
// SetStringResourceAttr sets provided value as "string.resource.attr" attribute.
func (rb *ResourceBuilder) SetStringResourceAttr(val string) {
if rb.config.StringResourceAttr.Enabled {
rb.res.Attributes().PutStr("string.resource.attr", val)
}
}
// SetStringResourceAttrDisableWarning sets provided value as "string.resource.attr_disable_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrDisableWarning(val string) {
if rb.config.StringResourceAttrDisableWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_disable_warning", val)
}
}
// SetStringResourceAttrRemoveWarning sets provided value as "string.resource.attr_remove_warning" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrRemoveWarning(val string) {
if rb.config.StringResourceAttrRemoveWarning.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_remove_warning", val)
}
}
// SetStringResourceAttrToBeRemoved sets provided value as "string.resource.attr_to_be_removed" attribute.
func (rb *ResourceBuilder) SetStringResourceAttrToBeRemoved(val string) {
if rb.config.StringResourceAttrToBeRemoved.Enabled {
rb.res.Attributes().PutStr("string.resource.attr_to_be_removed", val)
}
}
// Emit returns the built resource and resets the internal builder state.
func (rb *ResourceBuilder) Emit() pcommon.Resource {
r := rb.res
rb.res = pcommon.NewResource()
return r
}
generated_resource_test.go 0000664 0000000 0000000 00000005421 15113313446 0036310 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestResourceBuilder(t *testing.T) {
for _, tt := range []string{"default", "all_set", "none_set"} {
t.Run(tt, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt)
rb := NewResourceBuilder(cfg)
rb.SetMapResourceAttr(map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"})
rb.SetOptionalResourceAttr("optional.resource.attr-val")
rb.SetSliceResourceAttr([]any{"slice.resource.attr-item1", "slice.resource.attr-item2"})
rb.SetStringEnumResourceAttrOne()
rb.SetStringResourceAttr("string.resource.attr-val")
rb.SetStringResourceAttrDisableWarning("string.resource.attr_disable_warning-val")
rb.SetStringResourceAttrRemoveWarning("string.resource.attr_remove_warning-val")
rb.SetStringResourceAttrToBeRemoved("string.resource.attr_to_be_removed-val")
res := rb.Emit()
assert.Equal(t, 0, rb.Emit().Attributes().Len()) // Second call should return empty Resource
switch tt {
case "default":
assert.Equal(t, 6, res.Attributes().Len())
case "all_set":
assert.Equal(t, 8, res.Attributes().Len())
case "none_set":
assert.Equal(t, 0, res.Attributes().Len())
return
default:
assert.Failf(t, "unexpected test case: %s", tt)
}
val, ok := res.Attributes().Get("map.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, map[string]any{"key1": "map.resource.attr-val1", "key2": "map.resource.attr-val2"}, val.Map().AsRaw())
}
val, ok = res.Attributes().Get("optional.resource.attr")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "optional.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("slice.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, []any{"slice.resource.attr-item1", "slice.resource.attr-item2"}, val.Slice().AsRaw())
}
val, ok = res.Attributes().Get("string.enum.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "one", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_disable_warning")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_disable_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_remove_warning")
assert.Equal(t, tt == "all_set", ok)
if ok {
assert.Equal(t, "string.resource.attr_remove_warning-val", val.Str())
}
val, ok = res.Attributes().Get("string.resource.attr_to_be_removed")
assert.True(t, ok)
if ok {
assert.Equal(t, "string.resource.attr_to_be_removed-val", val.Str())
}
})
}
}
generated_status.go 0000664 0000000 0000000 00000000562 15113313446 0034746 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata // Code generated by mdatagen. DO NOT EDIT.
package metadata
import (
"go.opentelemetry.io/collector/component"
)
var (
Type = component.MustNewType("sample")
ScopeName = "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplescraper"
)
const (
LogsStability = component.StabilityLevelDevelopment
MetricsStability = component.StabilityLevelStable
)
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata/testdata/ 0000775 0000000 0000000 00000000000 15113313446 0032743 5 ustar 00root root 0000000 0000000 config.yaml 0000664 0000000 0000000 00000006340 15113313446 0035020 0 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/internal/metadata/testdata 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
system.cpu.time:
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
system.cpu.time:
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"
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/samplescraper/metadata.yaml 0000664 0000000 0000000 00000012015 15113313446 0030201 0 ustar 00root root 0000000 0000000 # Sample metadata file with all available configurations for a scraper.
type: sample
github_project: open-telemetry/opentelemetry-collector
sem_conv_version: 1.37.0
status:
disable_codecov_badge: true
class: scraper
stability:
stable: [metrics]
development: [logs]
distributions: []
unsupported_platforms: [freebsd, illumos]
codeowners:
active: [dmitryax]
warnings:
- Any additional information that should be brought to the consumer's attention
resource_attributes:
map.resource.attr:
description: Resource attribute with a map value.
type: map
enabled: true
optional.resource.attr:
description: Explicitly disabled ResourceAttribute.
type: string
enabled: false
slice.resource.attr:
description: Resource attribute with a slice value.
type: slice
enabled: true
string.enum.resource.attr:
description: Resource attribute with a known set of string values.
type: string
enum: [one, two]
enabled: true
string.resource.attr:
description: Resource attribute with any string value.
type: string
enabled: true
string.resource.attr_disable_warning:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled_not_set: This resource_attribute will be disabled by default soon.
string.resource.attr_remove_warning:
description: Resource attribute with any string value.
type: string
enabled: false
warnings:
if_configured: This resource_attribute is deprecated and will be removed soon.
string.resource.attr_to_be_removed:
description: Resource attribute with any string value.
type: string
enabled: true
warnings:
if_enabled: This resource_attribute is deprecated and will be removed soon.
attributes:
boolean_attr:
description: Attribute with a boolean value.
type: bool
# This 2nd boolean attribute allows us to test both values for boolean attributes,
# as test values are based on the parity of the attribute name length.
boolean_attr2:
description: Another attribute with a boolean value.
type: bool
enum_attr:
description: Attribute with a known set of string values.
type: string
enum: [red, green, blue]
map_attr:
description: Attribute with a map value.
type: map
overridden_int_attr:
name_override: state
description: Integer attribute with overridden name.
type: int
slice_attr:
description: Attribute with a slice value.
type: slice
string_attr:
description: Attribute with any string value.
type: string
metrics:
default.metric:
enabled: true
description: Monotonic cumulative sum int metric enabled by default.
extended_documentation: The metric will be become optional soon.
stability:
level: development
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
attributes:
[string_attr, overridden_int_attr, enum_attr, slice_attr, map_attr]
warnings:
if_enabled_not_set: This metric will be disabled by default soon.
default.metric.to_be_removed:
enabled: true
description: "[DEPRECATED] Non-monotonic delta sum double metric enabled by default."
extended_documentation: The metric will be removed soon.
stability:
level: deprecated
unit: s
sum:
value_type: double
monotonic: false
aggregation_temporality: delta
warnings:
if_enabled: This metric is deprecated and will be removed soon.
metric.input_type:
enabled: true
stability:
level: development
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]
optional.metric:
enabled: false
description: "[DEPRECATED] Gauge double metric disabled by default."
stability:
level: deprecated
unit: "1"
gauge:
value_type: double
attributes: [string_attr, boolean_attr, boolean_attr2]
warnings:
if_configured: This metric is deprecated and will be removed soon.
optional.metric.empty_unit:
enabled: false
description: "[DEPRECATED] Gauge double metric disabled by default."
stability:
level: deprecated
unit: ""
gauge:
value_type: double
attributes: [string_attr, boolean_attr]
warnings:
if_configured: This metric is deprecated and will be removed soon.
system.cpu.time:
enabled: true
stability:
level: beta
description: Monotonic cumulative sum int metric enabled by default.
extended_documentation: The metric will be become optional soon.
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
semantic_convention:
ref: https://github.com/open-telemetry/semantic-conventions/blob/v1.37.0/docs/system/system-metrics.md#metric-systemcputime
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/status.go 0000664 0000000 0000000 00000012256 15113313446 0024555 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
import (
"errors"
"fmt"
"slices"
"sort"
"time"
"go.opentelemetry.io/collector/component"
)
// distroURL returns the 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 is open source and maintained by the OpenTelemetry project.
// - The link must point to a publicly accessible repository.
func distroURL(name string) string {
switch name {
case "core":
return "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol"
case "contrib":
return "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib"
case "k8s":
return "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-k8s"
case "otlp":
return "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-otlp"
default:
return ""
}
}
type Codeowners struct {
// Active codeowners
Active []string `mapstructure:"active"`
// Emeritus codeowners
Emeritus []string `mapstructure:"emeritus"`
// Whether new codeowners are being sought
SeekingNew bool `mapstructure:"seeking_new"`
}
type Status struct {
Stability StabilityMap `mapstructure:"stability"`
Distributions []string `mapstructure:"distributions"`
Class string `mapstructure:"class"`
Warnings []string `mapstructure:"warnings"`
Codeowners *Codeowners `mapstructure:"codeowners"`
UnsupportedPlatforms []string `mapstructure:"unsupported_platforms"`
Deprecation DeprecationMap `mapstructure:"deprecation"`
CodeCovComponentID string `mapstructure:"codecov_component_id"`
DisableCodeCov bool `mapstructure:"disable_codecov_badge"`
}
type DeprecationMap map[string]DeprecationInfo
type DeprecationInfo struct {
Date string `mapstructure:"date"`
Migration string `mapstructure:"migration"`
}
var validClasses = []string{
"cmd",
"connector",
"converter",
"exporter",
"extension",
"pkg",
"processor",
"provider",
"receiver",
"scraper",
}
var validStabilityKeys = []string{
"converter",
"extension",
"logs",
"logs_to_traces",
"logs_to_metrics",
"logs_to_logs",
"logs_to_profiles",
"metrics",
"metrics_to_traces",
"metrics_to_metrics",
"metrics_to_logs",
"metrics_to_profiles",
"profiles",
"profiles_to_profiles",
"profiles_to_traces",
"profiles_to_metrics",
"profiles_to_logs",
"provider",
"traces_to_traces",
"traces_to_metrics",
"traces_to_logs",
"traces_to_profiles",
"traces",
}
func (s *Status) SortedDistributions() []string {
sorted := s.Distributions
sort.Slice(sorted, func(i, j int) bool {
if s.Distributions[i] == "core" {
return true
}
if s.Distributions[i] == "contrib" {
return s.Distributions[j] != "core"
}
if s.Distributions[j] == "core" {
return false
}
if s.Distributions[j] == "contrib" {
return s.Distributions[i] == "core"
}
return s.Distributions[i] < s.Distributions[j]
})
return sorted
}
func (s *Status) Validate() error {
var errs error
if s == nil {
return errors.New("missing status")
}
if err := s.validateClass(); err != nil {
errs = errors.Join(errs, err)
}
if err := s.Stability.Validate(); err != nil {
errs = errors.Join(errs, err)
}
if err := s.Deprecation.Validate(s.Stability); err != nil {
errs = errors.Join(errs, err)
}
return errs
}
func (s *Status) validateClass() error {
if s.Class == "" {
return errors.New("missing class")
}
if !slices.Contains(validClasses, s.Class) {
return fmt.Errorf("invalid class: %v", s.Class)
}
return nil
}
type StabilityMap map[component.StabilityLevel][]string
func (ms StabilityMap) Validate() error {
var errs error
if len(ms) == 0 {
return errors.New("missing stability")
}
for stability, cmps := range ms {
if len(cmps) == 0 {
errs = errors.Join(errs, fmt.Errorf("missing component for stability: %v", stability))
}
for _, c := range cmps {
if !slices.Contains(validStabilityKeys, c) {
errs = errors.Join(errs, fmt.Errorf("invalid component: %v", c))
}
}
}
return errs
}
func (dm DeprecationMap) Validate(ms StabilityMap) error {
var errs error
for stability, cmps := range ms {
if stability != component.StabilityLevelDeprecated {
continue
}
for _, c := range cmps {
depInfo, found := dm[c]
if !found {
errs = errors.Join(errs, fmt.Errorf("deprecated component missing deprecation date and migration guide for %v", c))
continue
}
if depInfo.Migration == "" {
errs = errors.Join(errs, fmt.Errorf("deprecated component missing migration guide: %v", c))
}
if depInfo.Date == "" {
errs = errors.Join(errs, fmt.Errorf("deprecated component missing date in YYYY-MM-DD format: %v", c))
} else {
_, err := time.Parse("2006-01-02", depInfo.Date)
if err != nil {
errs = errors.Join(errs, fmt.Errorf("deprecated component missing valid date in YYYY-MM-DD format: %v", c))
}
}
}
}
return errs
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/status_test.go 0000664 0000000 0000000 00000004217 15113313446 0025612 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestDistroURL(t *testing.T) {
tests := []struct {
input string
output string
}{
{
input: "core",
output: "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol",
},
{
input: "contrib",
output: "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib",
},
{
input: "k8s",
output: "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-k8s",
},
{
input: "otlp",
output: "https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-otlp",
},
{
input: "not_found",
output: "",
},
}
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
assert.Equal(t, test.output, distroURL(test.input))
})
}
}
func TestSortedDistributions(t *testing.T) {
tests := []struct {
name string
s Status
result []string
}{
{
"all combined",
Status{Distributions: []string{"arm", "contrib", "core", "foo", "bar"}},
[]string{"core", "contrib", "arm", "bar", "foo"},
},
{
"core only",
Status{Distributions: []string{"core"}},
[]string{"core"},
},
{
"core and contrib only",
Status{Distributions: []string{"core", "contrib"}},
[]string{"core", "contrib"},
},
{
"core and contrib reversed",
Status{Distributions: []string{"contrib", "core"}},
[]string{"core", "contrib"},
},
{
"neither core nor contrib",
Status{Distributions: []string{"foo", "bar"}},
[]string{"bar", "foo"},
},
{
"no core, contrib, something else",
Status{Distributions: []string{"foo", "contrib", "bar"}},
[]string{"contrib", "bar", "foo"},
},
{
"core, no contrib, something else",
Status{Distributions: []string{"foo", "core", "bar"}},
[]string{"core", "bar", "foo"},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
assert.Equal(t, test.result, test.s.SortedDistributions())
})
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/telemetry.go 0000664 0000000 0000000 00000000363 15113313446 0025240 0 ustar 00root root 0000000 0000000 // Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/cmd/mdatagen/internal"
type Telemetry struct {
Metrics map[MetricName]Metric `mapstructure:"metrics"`
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/ 0000775 0000000 0000000 00000000000 15113313446 0024673 5 ustar 00root root 0000000 0000000 opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/component_test.go.tmpl 0000664 0000000 0000000 00000047463 15113313446 0031254 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
{{- if len .Status.UnsupportedPlatforms }}
//go:build {{ range $i, $v := .Status.UnsupportedPlatforms }}{{ if $i }} && {{ end }}!{{ . }}{{ end }}
{{- end }}
package {{ .Package }}
import (
{{- 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"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
{{- if not (and .Tests.SkipLifecycle .Tests.SkipShutdown) }}
"go.opentelemetry.io/collector/confmap/confmaptest"
{{- if isExporter }}
"go.opentelemetry.io/collector/exporter"
"go.opentelemetry.io/collector/exporter/exportertest"
{{- end }}
{{- if isProcessor }}
"go.opentelemetry.io/collector/consumer/consumertest"
"go.opentelemetry.io/collector/processor"
"go.opentelemetry.io/collector/processor/processortest"
{{- end }}
{{- if isReceiver }}
"go.opentelemetry.io/collector/consumer/consumertest"
"go.opentelemetry.io/collector/receiver"
"go.opentelemetry.io/collector/receiver/receivertest"
{{- end }}
{{- if isScraper }}
"go.opentelemetry.io/collector/scraper"
"go.opentelemetry.io/collector/scraper/scrapertest"
{{- end }}
{{- if isExtension }}
"go.opentelemetry.io/collector/extension/extensiontest"
{{- end }}
{{- if isConnector }}
"go.opentelemetry.io/collector/connector"
"go.opentelemetry.io/collector/connector/connectortest"
"go.opentelemetry.io/collector/consumer"
"go.opentelemetry.io/collector/consumer/consumertest"
"go.opentelemetry.io/collector/pipeline"
{{- 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 }}
)
var typ = component.MustNewType("{{ .Type }}")
func TestComponentFactoryType(t *testing.T) {
require.Equal(t, typ, NewFactory().Type())
}
func TestComponentConfigStruct(t *testing.T) {
require.NoError(t, componenttest.CheckConfigStruct(NewFactory().CreateDefaultConfig()))
}
{{ if not (and .Tests.SkipLifecycle .Tests.SkipShutdown) -}}
{{ if isExporter -}}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct{
createFn func(ctx context.Context, set exporter.Settings, cfg component.Config) (component.Component, error)
name string
}{
{{ if supportsLogs }}
{
name: "logs",
createFn: func(ctx context.Context, set exporter.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg)
},
},
{{ end }}
{{ if supportsMetrics }}
{
name: "metrics",
createFn: func(ctx context.Context, set exporter.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg)
},
},
{{ end }}
{{ if supportsTraces }}
{
name: "traces",
createFn: func(ctx context.Context, set exporter.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(ctx, set, cfg)
},
},
{{ end }}
}
cm, err := confmaptest.LoadConf("metadata.yaml")
require.NoError(t, err)
cfg := factory.CreateDefaultConfig()
sub, err := cm.Sub("tests::config")
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(&cfg))
for _, tt := range tests {
{{- if not .Tests.SkipShutdown }}
t.Run(tt.name + "-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), exportertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
{{- end }}
{{- if not .Tests.SkipLifecycle }}
t.Run(tt.name + "-lifecycle", func(t *testing.T) {
c, err := tt.createFn(context.Background(), exportertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := {{ .Tests.Host }}
err = c.Start(context.Background(), host)
require.NoError(t, err)
require.NotPanics(t, func() {
switch tt.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)
}
})
{{ if not expectConsumerError }}
require.NoError(t, err)
{{ end }}
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
{{- end }}
}
}
{{ end }}
{{ if isProcessor }}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct{
createFn func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error)
name string
}{
{{ if supportsLogs }}
{
name: "logs",
createFn: func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg, consumertest.NewNop())
},
},
{{ end }}
{{ if supportsMetrics }}
{
name: "metrics",
createFn: func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg, consumertest.NewNop())
},
},
{{ end }}
{{ if supportsTraces }}
{
name: "traces",
createFn: func(ctx context.Context, set processor.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(ctx, set, cfg, consumertest.NewNop())
},
},
{{ end }}
}
cm, err := confmaptest.LoadConf("metadata.yaml")
require.NoError(t, err)
cfg := factory.CreateDefaultConfig()
sub, err := cm.Sub("tests::config")
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(&cfg))
for _, tt := range tests {
{{- if not .Tests.SkipShutdown }}
t.Run(tt.name + "-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), processortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
{{- end }}
{{- if not .Tests.SkipLifecycle }}
t.Run(tt.name + "-lifecycle", func(t *testing.T) {
c, err := tt.createFn(context.Background(), processortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := {{ .Tests.Host }}
err = c.Start(context.Background(), host)
require.NoError(t, err)
require.NotPanics(t, func() {
switch tt.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)
})
{{- end }}
}
}
{{ end }}
{{ if isReceiver }}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct{
createFn func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error)
name string
}{
{{ if supportsLogs }}
{
name: "logs",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg, consumertest.NewNop())
},
},
{{ end }}
{{ if supportsMetrics }}
{
name: "metrics",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg, consumertest.NewNop())
},
},
{{ end }}
{{ if supportsTraces }}
{
name: "traces",
createFn: func(ctx context.Context, set receiver.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(ctx, set, cfg, consumertest.NewNop())
},
},
{{ end }}
}
cm, err := confmaptest.LoadConf("metadata.yaml")
require.NoError(t, err)
cfg := factory.CreateDefaultConfig()
sub, err := cm.Sub("tests::config")
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(&cfg))
for _, tt := range tests {
{{- if not .Tests.SkipShutdown }}
t.Run(tt.name + "-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
{{- end }}
{{- if not .Tests.SkipLifecycle }}
t.Run(tt.name + "-lifecycle", func(t *testing.T) {
firstRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := {{ .Tests.Host }}
require.NoError(t, err)
require.NoError(t, firstRcvr.Start(context.Background(), host))
require.NoError(t, firstRcvr.Shutdown(context.Background()))
secondRcvr, err := tt.createFn(context.Background(), receivertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondRcvr.Start(context.Background(), host))
require.NoError(t, secondRcvr.Shutdown(context.Background()))
})
{{- end }}
}
}
{{ end }}
{{ if isScraper }}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct{
createFn func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error)
name string
}{
{{ if supportsLogs }}
{
name: "logs",
createFn: func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateLogs(ctx, set, cfg)
},
},
{{ end }}
{{ if supportsMetrics }}
{
name: "metrics",
createFn: func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateMetrics(ctx, set, cfg)
},
},
{{ end }}
{{ if supportsTraces }}
{
name: "traces",
createFn: func(ctx context.Context, set scraper.Settings, cfg component.Config) (component.Component, error) {
return factory.CreateTraces(ctx, set, cfg)
},
},
{{ end }}
}
cm, err := confmaptest.LoadConf("metadata.yaml")
require.NoError(t, err)
cfg := factory.CreateDefaultConfig()
sub, err := cm.Sub("tests::config")
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(&cfg))
for _, tt := range tests {
{{- if not .Tests.SkipShutdown }}
t.Run(tt.name + "-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), scrapertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
{{- end }}
{{- if not .Tests.SkipLifecycle }}
t.Run(tt.name + "-lifecycle", func(t *testing.T) {
firstRcvr, err := tt.createFn(context.Background(), scrapertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := {{ .Tests.Host }}
require.NoError(t, err)
require.NoError(t, firstRcvr.Start(context.Background(), host))
require.NoError(t, firstRcvr.Shutdown(context.Background()))
secondRcvr, err := tt.createFn(context.Background(), scrapertest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondRcvr.Start(context.Background(), host))
require.NoError(t, secondRcvr.Shutdown(context.Background()))
})
{{- end }}
}
}
{{ end }}
{{ if isExtension }}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
cm, err := confmaptest.LoadConf("metadata.yaml")
require.NoError(t, err)
cfg := factory.CreateDefaultConfig()
sub, err := cm.Sub("tests::config")
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(&cfg))
{{- if not .Tests.SkipShutdown }}
t.Run("shutdown", func(t *testing.T) {
e, err := factory.Create(context.Background(), extensiontest.NewNopSettings(typ), 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) {
firstExt, err := factory.Create(context.Background(), extensiontest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, firstExt.Start(context.Background(), {{ .Tests.Host }}))
require.NoError(t, firstExt.Shutdown(context.Background()))
secondExt, err := factory.Create(context.Background(), extensiontest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondExt.Start(context.Background(), {{ .Tests.Host }}))
require.NoError(t, secondExt.Shutdown(context.Background()))
})
{{- end }}
}
{{ end }}
{{ if isConnector }}
func TestComponentLifecycle(t *testing.T) {
factory := NewFactory()
tests := []struct{
createFn func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error)
name string
}{
{{ if supportsLogsToLogs }}
{
name: "logs_to_logs",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewLogsRouter(map[pipeline.ID]consumer.Logs{pipeline.NewID(pipeline.SignalLogs): consumertest.NewNop()})
return factory.CreateLogsToLogs(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsLogsToMetrics }}
{
name: "logs_to_metrics",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewMetricsRouter(map[pipeline.ID]consumer.Metrics{pipeline.NewID(pipeline.SignalMetrics): consumertest.NewNop()})
return factory.CreateLogsToMetrics(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsLogsToTraces }}
{
name: "logs_to_traces",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewTracesRouter(map[pipeline.ID]consumer.Traces{pipeline.NewID(pipeline.SignalTraces): consumertest.NewNop()})
return factory.CreateLogsToTraces(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsMetricsToLogs }}
{
name: "metrics_to_logs",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewLogsRouter(map[pipeline.ID]consumer.Logs{pipeline.NewID(pipeline.SignalLogs): consumertest.NewNop()})
return factory.CreateMetricsToLogs(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsMetricsToMetrics }}
{
name: "metrics_to_metrics",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewMetricsRouter(map[pipeline.ID]consumer.Metrics{pipeline.NewID(pipeline.SignalMetrics): consumertest.NewNop()})
return factory.CreateMetricsToMetrics(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsMetricsToTraces }}
{
name: "metrics_to_traces",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewTracesRouter(map[pipeline.ID]consumer.Traces{pipeline.NewID(pipeline.SignalTraces): consumertest.NewNop()})
return factory.CreateMetricsToTraces(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsTracesToLogs }}
{
name: "traces_to_logs",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewLogsRouter(map[pipeline.ID]consumer.Logs{pipeline.NewID(pipeline.SignalLogs): consumertest.NewNop()})
return factory.CreateTracesToLogs(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsTracesToMetrics }}
{
name: "traces_to_metrics",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewMetricsRouter(map[pipeline.ID]consumer.Metrics{pipeline.NewID(pipeline.SignalMetrics): consumertest.NewNop()})
return factory.CreateTracesToMetrics(ctx, set, cfg, router)
},
},
{{ end }}
{{ if supportsTracesToTraces }}
{
name: "traces_to_traces",
createFn: func(ctx context.Context, set connector.Settings, cfg component.Config) (component.Component, error) {
router := connector.NewTracesRouter(map[pipeline.ID]consumer.Traces{pipeline.NewID(pipeline.SignalTraces): consumertest.NewNop()})
return factory.CreateTracesToTraces(ctx, set, cfg, router)
},
},
{{ end }}
}
cm, err := confmaptest.LoadConf("metadata.yaml")
require.NoError(t, err)
cfg := factory.CreateDefaultConfig()
sub, err := cm.Sub("tests::config")
require.NoError(t, err)
require.NoError(t, sub.Unmarshal(&cfg))
for _, tt := range tests {
{{- if not .Tests.SkipShutdown }}
t.Run(tt.name + "-shutdown", func(t *testing.T) {
c, err := tt.createFn(context.Background(), connectortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
err = c.Shutdown(context.Background())
require.NoError(t, err)
})
{{- end }}
{{- if not .Tests.SkipLifecycle }}
t.Run(tt.name + "-lifecycle", func(t *testing.T) {
firstConnector, err := tt.createFn(context.Background(), connectortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
host := {{ .Tests.Host }}
require.NoError(t, err)
require.NoError(t, firstConnector.Start(context.Background(), host))
require.NoError(t, firstConnector.Shutdown(context.Background()))
secondConnector, err := tt.createFn(context.Background(), connectortest.NewNopSettings(typ), cfg)
require.NoError(t, err)
require.NoError(t, secondConnector.Start(context.Background(), host))
require.NoError(t, secondConnector.Shutdown(context.Background()))
})
{{- end }}
}
}
{{ 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 }}
{{- if not .Tests.SkipLifecycle }}
var _ component.Host = (*mdatagenNopHost)(nil)
type mdatagenNopHost struct{}
func newMdatagenNopHost() component.Host {
return &mdatagenNopHost{}
}
func (mnh *mdatagenNopHost) GetExtensions() map[component.ID]component.Component {
return nil
}
func (mnh *mdatagenNopHost) GetFactory(_ component.Kind, _ component.Type) component.Factory {
return nil
}
{{- end }}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/config.go.tmpl 0000664 0000000 0000000 00000011705 15113313446 0027446 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ .Package }}
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.
type MetricConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ms *MetricConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ms)
if err != nil {
return err
}
ms.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// MetricsConfig provides config for {{ .Type }} metrics.
type MetricsConfig struct {
{{- range $name, $metric := .Metrics }}
{{ $name.Render }} MetricConfig `mapstructure:"{{ $name }}"`
{{- end }}
}
func DefaultMetricsConfig() MetricsConfig {
return MetricsConfig{
{{- range $name, $metric := .Metrics }}
{{ $name.Render }}: MetricConfig{
Enabled: {{ $metric.Enabled }},
},
{{- end }}
}
}
{{- end }}
{{ if .Events }}
// EventConfig provides common config for a particular event.
type EventConfig struct {
Enabled bool `mapstructure:"enabled"`
enabledSetByUser bool
}
func (ec *EventConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(ec)
if err != nil {
return err
}
ec.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// EventsConfig provides config for {{ .Type }} events.
type EventsConfig struct {
{{- range $name, $event := .Events }}
{{ $name.Render }} EventConfig `mapstructure:"{{ $name }}"`
{{- end }}
}
func DefaultEventsConfig() EventsConfig {
return EventsConfig{
{{- range $name, $event := .Events }}
{{ $name.Render }}: EventConfig{
Enabled: {{ $event.Enabled }},
},
{{- end }}
}
}
{{- end }}
{{ if .ResourceAttributes -}}
// 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 }}
{{- if .Events }}
// Experimental: EventsInclude defines a list of filters for attribute values.
// If the list is not empty, only events with matching resource attribute values will be emitted.
EventsInclude []filter.Config `mapstructure:"events_include"`
// Experimental: EventsExclude defines a list of filters for attribute values.
// If the list is not empty, events with matching resource attribute values will not be emitted.
// EventsInclude has higher priority than EventsExclude.
EventsExclude []filter.Config `mapstructure:"events_exclude"`
{{- end }}
enabledSetByUser bool
}
func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error {
if parser == nil {
return nil
}
err := parser.Unmarshal(rac)
if err != nil {
return err
}
rac.enabledSetByUser = parser.IsSet("enabled")
return nil
}
// ResourceAttributesConfig provides config for {{ .Type }} resource attributes.
type ResourceAttributesConfig struct {
{{- range $name, $attr := .ResourceAttributes }}
{{ $name.Render }} ResourceAttributeConfig `mapstructure:"{{ $name }}"`
{{- end }}
}
func DefaultResourceAttributesConfig() ResourceAttributesConfig {
return ResourceAttributesConfig{
{{- range $name, $attr := .ResourceAttributes }}
{{ $name.Render }}: ResourceAttributeConfig {
Enabled: {{ $attr.Enabled }},
},
{{- end }}
}
}
{{- end }}
{{ if .Metrics -}}
// MetricsBuilderConfig is a configuration for {{ .Type }} metrics builder.
type MetricsBuilderConfig struct {
Metrics MetricsConfig `mapstructure:"metrics"`
{{- if .ResourceAttributes }}
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
{{- end }}
}
func DefaultMetricsBuilderConfig() MetricsBuilderConfig {
return MetricsBuilderConfig {
Metrics: DefaultMetricsConfig(),
{{- if .ResourceAttributes }}
ResourceAttributes: DefaultResourceAttributesConfig(),
{{- end }}
}
}
{{- end }}
{{ if .Events -}}
// LogsBuilderConfig is a configuration for {{ .Type }} logs builder.
type LogsBuilderConfig struct {
Events EventsConfig `mapstructure:"events"`
{{- if .ResourceAttributes }}
ResourceAttributes ResourceAttributesConfig `mapstructure:"resource_attributes"`
{{- end }}
}
func DefaultLogsBuilderConfig() LogsBuilderConfig {
return LogsBuilderConfig {
Events: DefaultEventsConfig(),
{{- if .ResourceAttributes }}
ResourceAttributes: DefaultResourceAttributesConfig(),
{{- end }}
}
}
{{- end }}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/config_test.go.tmpl 0000664 0000000 0000000 00000007374 15113313446 0030514 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ .Package }}
import (
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
)
{{ if .Metrics }}
func TestMetricsBuilderConfig(t *testing.T) {
tests := []struct {
name string
want MetricsBuilderConfig
}{
{
name: "default",
want: DefaultMetricsBuilderConfig(),
},
{
name: "all_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
{{- range $name, $_ := .Metrics }}
{{ $name.Render }}: MetricConfig{Enabled: true},
{{- end }}
},
{{- if .ResourceAttributes }}
ResourceAttributes: ResourceAttributesConfig{
{{- range $name, $_ := .ResourceAttributes }}
{{ $name.Render }}: ResourceAttributeConfig{Enabled: true},
{{- end }}
},
{{- end }}
},
},
{
name: "none_set",
want: MetricsBuilderConfig{
Metrics: MetricsConfig{
{{- range $name, $_ := .Metrics }}
{{ $name.Render }}: MetricConfig{Enabled: false},
{{- end }}
},
{{- if .ResourceAttributes }}
ResourceAttributes: ResourceAttributesConfig{
{{- range $name, $_ := .ResourceAttributes }}
{{ $name.Render }}: ResourceAttributeConfig{Enabled: false},
{{- end }}
},
{{- end }}
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadMetricsBuilderConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(MetricConfig{}
{{- if .ResourceAttributes }}, ResourceAttributeConfig{}{{ end }}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadMetricsBuilderConfig(t *testing.T, name string) MetricsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultMetricsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
{{- end }}
{{ if .Events }}
func loadLogsBuilderConfig(t *testing.T, name string) LogsBuilderConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
cfg := DefaultLogsBuilderConfig()
require.NoError(t, sub.Unmarshal(&cfg, confmap.WithIgnoreUnused()))
return cfg
}
{{- end }}
{{ if .ResourceAttributes -}}
func TestResourceAttributesConfig(t *testing.T) {
tests := []struct {
name string
want ResourceAttributesConfig
}{
{
name: "default",
want: DefaultResourceAttributesConfig(),
},
{
name: "all_set",
want: ResourceAttributesConfig{
{{- range $name, $_ := .ResourceAttributes }}
{{ $name.Render }}: ResourceAttributeConfig{Enabled: true},
{{- end }}
},
},
{
name: "none_set",
want: ResourceAttributesConfig{
{{- range $name, $_ := .ResourceAttributes }}
{{ $name.Render }}: ResourceAttributeConfig{Enabled: false},
{{- end }}
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := loadResourceAttributesConfig(t, tt.name)
diff := cmp.Diff(tt.want, cfg, cmpopts.IgnoreUnexported(ResourceAttributeConfig{}))
require.Emptyf(t, diff, "Config mismatch (-expected +actual):\n%s", diff)
})
}
}
func loadResourceAttributesConfig(t *testing.T, name string) ResourceAttributesConfig {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
sub, err := cm.Sub(name)
require.NoError(t, err)
sub, err = sub.Sub("resource_attributes")
require.NoError(t, err)
cfg := DefaultResourceAttributesConfig()
require.NoError(t, sub.Unmarshal(&cfg))
return cfg
}
{{- end }}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/documentation.md.tmpl 0000664 0000000 0000000 00000015531 15113313446 0031046 0 ustar 00root root 0000000 0000000 {{- define "metric-documentation" -}}
{{- $metricName := . }}
{{- $metric := $metricName | metricInfo -}}
### {{ $metricName }}
{{ $metric.Description }}
{{- if $metric.ExtendedDocumentation }}
{{ $metric.ExtendedDocumentation }}
{{- end }}
| Unit | Metric Type | Value Type |{{ if $metric.Data.HasAggregated }} Aggregation Temporality |{{ end }}{{ if $metric.Data.HasMonotonic }} Monotonic |{{ end }}{{ if $metric.Stability.Level }} Stability |{{ end }}{{ if $metric.SemanticConvention }} Semantic Convention |{{ end }}
| ---- | ----------- | ---------- |{{ if $metric.Data.HasAggregated }} ----------------------- |{{ end }}{{ if $metric.Data.HasMonotonic }} --------- |{{ end }}{{ if $metric.Stability.Level }} --------- |{{ end }}{{ if $metric.SemanticConvention }} ------------------- |{{ end }}
| {{ $metric.Unit }} | {{ $metric.Data.Type }} | {{ $metric.Data.MetricValueType }} |
{{- if $metric.Data.HasAggregated }} {{ $metric.Data.AggregationTemporality }} |{{ end }}
{{- if $metric.Data.HasMonotonic }} {{ $metric.Data.Monotonic }} |{{ end }}
{{- if $metric.Stability.Level }} {{ $metric.Stability.Level }} |{{ end }}
{{- if $metric.SemanticConvention }} [{{ $metricName }}]({{ $metric.SemanticConvention.SemanticConventionRef }}) |{{ end }}
{{- if $metric.Attributes }}
#### Attributes
| Name | Description | Values | Requirement Level |
| ---- | ----------- | ------ | -------- |
{{- range $metric.Attributes }}
{{- $attribute := . | attributeInfo }}
| {{ $attribute.Name }} | {{ $attribute.Description }} |
{{- if $attribute.Enum }} {{ $attribute.Type }}: ``{{ stringsJoin $attribute.Enum "``, ``" }}``{{ else }} Any {{ $attribute.Type }}{{ end }} | {{ $attribute.RequirementLevel }} |
{{- end }}
{{- end }}
{{- end -}}
{{- define "event-documentation" -}}
{{- $eventName := . }}
{{- $event := $eventName | eventInfo -}}
### {{ $eventName }}
{{ $event.Description }}
{{- if $event.ExtendedDocumentation }}
{{ $event.ExtendedDocumentation }}
{{- end }}
{{- if $event.Attributes }}
#### Attributes
| Name | Description | Values |
| ---- | ----------- | ------ |
{{- range $event.Attributes }}
{{- $attribute := . | attributeInfo }}
| {{ $attribute.Name }} | {{ $attribute.Description }} |
{{- if $attribute.Enum }} {{ $attribute.Type }}: ``{{ stringsJoin $attribute.Enum "``, ``" }}``{{ else }} Any {{ $attribute.Type }}{{ end }} |
{{- end }}
{{- end }}
{{- end -}}
{{- define "telemetry-documentation" -}}
{{- $metricName := . }}
{{- $metric := $metricName | telemetryInfo -}}
### {{ if $metric.Prefix -}}{{ $metric.Prefix }}{{- else -}}otelcol_{{- end -}}{{ $metricName }}
{{ $metric.Description }}{{ $metric.Stability }}
{{- if $metric.ExtendedDocumentation }}
{{ $metric.ExtendedDocumentation }}
{{- end }}
| Unit | Metric Type | Value Type |{{ if $metric.Data.HasMonotonic }} Monotonic |{{ end }}{{ if $metric.Stability.Level }} Stability |{{ end }}{{ if $metric.SemanticConvention }} Semantic Convention |{{ end }}
| ---- | ----------- | ---------- |{{ if $metric.Data.HasMonotonic }} --------- |{{ end }}{{ if $metric.Stability.Level }} --------- |{{ end }}{{ if $metric.SemanticConvention }} ------------------- |{{ end }}
| {{ $metric.Unit }} | {{ $metric.Data.Type }} | {{ $metric.Data.MetricValueType }} |
{{- if $metric.Data.HasMonotonic }} {{ $metric.Data.Monotonic }} |{{ end }}
{{- if $metric.Stability.Level }} {{ $metric.Stability.Level }} |{{ end }}
{{- if $metric.SemanticConvention }} [{{ $metricName }}]({{ $metric.SemanticConvention.SemanticConventionRef }}) |{{ end }}
{{- if $metric.Attributes }}
#### Attributes
| Name | Description | Values |
| ---- | ----------- | ------ |
{{- range $metric.Attributes }}
{{- $attribute := . | attributeInfo }}
| {{ $attribute.Name }} | {{ $attribute.Description }} |
{{- if $attribute.Enum }} {{ $attribute.Type }}: ``{{ stringsJoin $attribute.Enum "``, ``" }}``{{ else }} Any {{ $attribute.Type }}{{ end }} |
{{- end }}
{{- end }}
{{- end -}}
[comment]: <> (Code generated by mdatagen. DO NOT EDIT.)
# {{ .Type }}
{{- if .Parent }}
**Parent Component:** {{ .Parent }}
{{- end }}
{{- if .Metrics }}
## Default Metrics
The following metrics are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
metrics:
:
enabled: false
```
{{- end }}
{{- range $metricName, $metric := .Metrics }}
{{- if $metric.Enabled }}
{{ template "metric-documentation" $metricName }}
{{- end }}
{{- end }}
{{- $optionalMetricSeen := false }}
{{- range $metricName, $metric := .Metrics }}
{{- if not $metric.Enabled }}
{{- if not $optionalMetricSeen }}
## Optional Metrics
The following metrics are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
metrics:
:
enabled: true
```
{{- end }}
{{- $optionalMetricSeen = true }}
{{ template "metric-documentation" $metricName }}
{{- end }}
{{- end }}
{{- if .Events }}
## Default Events
The following events are emitted by default. Each of them can be disabled by applying the following configuration:
```yaml
events:
:
enabled: false
```
{{- range $eventName, $event := .Events }}
{{- if $event.Enabled }}
{{ template "event-documentation" $eventName }}
{{- end }}
{{- end }}
{{- end }}
{{- $optionalEventSeen := false }}
{{- range $eventName, $event := .Events }}
{{- if not $event.Enabled }}
{{- if not $optionalEventSeen }}
## Optional Events
The following events are not emitted by default. Each of them can be enabled by applying the following configuration:
```yaml
events:
:
enabled: true
```
{{- end }}
{{- $optionalEventSeen = true }}
{{ template "event-documentation" $eventName }}
{{- end }}
{{- end }}
{{- if .ResourceAttributes }}
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
{{- range $attributeName, $attribute := .ResourceAttributes }}
| {{ $attributeName }} | {{ $attribute.Description }} |
{{- if $attribute.Enum }} {{ $attribute.Type }}: ``{{ stringsJoin $attribute.Enum "``, ``" }}``{{ else }} Any {{ $attribute.Type }}{{ end }} | {{ $attribute.Enabled }} |
{{- end }}
{{- end }}
{{- if .Entities }}
## Entities
The following entities are defined for this component:
{{- range $entity := .Entities }}
### {{ $entity.Type }}
{{ $entity.Brief }}
{{- if $entity.Stability }}
**Stability:** {{ $entity.Stability }}
{{- end }}
{{- if $entity.Identity }}
**Identity Attributes:**
{{- range $entity.Identity }}
- `{{ .Ref }}`
{{- end }}
{{- end }}
{{- if $entity.Description }}
**Description Attributes:**
{{- range $entity.Description }}
- `{{ .Ref }}`
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Telemetry.Metrics }}
## Internal Telemetry
The following telemetry is emitted by this component.
{{- range $metricName, $metric := .Telemetry.Metrics }}
{{- if $metric.Enabled }}
{{ template "telemetry-documentation" $metricName }}
{{- end }}
{{- end }}
{{- end }}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/helper.tmpl 0000664 0000000 0000000 00000001610 15113313446 0027046 0 ustar 00root root 0000000 0000000 {{- define "putAttribute" -}}
{{- if eq (attributeInfo .).Type.Primitive "[]byte" }}
dp.Attributes().PutEmptyBytes("{{ (attributeInfo .).Name }}").FromRaw({{ .RenderUnexported }}AttributeValue)
{{- else if eq (attributeInfo .).Type.Primitive "[]any" }}
dp.Attributes().PutEmptySlice("{{ (attributeInfo .).Name }}").FromRaw({{ .RenderUnexported }}AttributeValue)
{{- else if eq (attributeInfo .).Type.Primitive "map[string]any" }}
dp.Attributes().PutEmptyMap("{{ (attributeInfo .).Name }}").FromRaw({{ .RenderUnexported }}AttributeValue)
{{- else }}
dp.Attributes().Put{{ (attributeInfo .).Type }}("{{ (attributeInfo .).Name }}", {{ .RenderUnexported }}AttributeValue)
{{- end }}
{{- end -}}
{{- define "getAttributeValue" -}}
{{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ (index (attributeInfo .).Enum 0) | publicVar }}{{ else }}{{ (attributeInfo .).TestValue }}{{ end }}
{{- end -}}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/logs.go.tmpl 0000664 0000000 0000000 00000024332 15113313446 0027145 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ .Package }}
import (
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
{{- if or isReceiver isScraper }}
"go.opentelemetry.io/collector/{{ .Status.Class }}"
{{- end }}
{{- if .SemConvVersion }}
conventions "go.opentelemetry.io/otel/semconv/v{{ .SemConvVersion }}"
{{- end }}
{{- if .Events }}
"context"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/collector/filter"
{{- end }}
)
{{ if getEventConditionalAttributes .Attributes }}
type EventAttributeOption interface {
apply(plog.LogRecord)
}
type eventAttributeOptionFunc func(plog.LogRecord)
func (eaof eventAttributeOptionFunc) apply(lr plog.LogRecord) {
eaof(lr)
}
{{ range getEventConditionalAttributes .Attributes }}
func With{{ .Render }}EventAttribute({{ .RenderUnexported }}AttributeValue {{ (attributeInfo .).Type.Primitive }}) EventAttributeOption {
return eventAttributeOptionFunc(func(dp plog.LogRecord) {
{{- template "putAttribute" . }}
})
}
{{ end }}
{{ end }}
{{ range $name, $event := .Events -}}
type event{{ $name.Render }} struct {
data plog.LogRecordSlice // data buffer for generated log records.
config EventConfig // event config provided by user.
}
func (e *event{{ $name.Render }}) recordEvent(ctx context.Context, timestamp pcommon.Timestamp
{{- range $event.Attributes -}}{{- if not (attributeInfo .).IsConditional -}}, {{ .RenderUnexported }}AttributeValue {{ (attributeInfo .).Type.Primitive }}{{ end }}{{end}}{{- if $event.HasConditionalAttributes $.Attributes -}}, options ...EventAttributeOption{{- end -}}) {
if !e.config.Enabled {
return
}
dp := e.data.AppendEmpty()
dp.SetEventName("{{ $name }}")
dp.SetTimestamp(timestamp)
if span := trace.SpanContextFromContext(ctx); span.IsValid() {
dp.SetTraceID(pcommon.TraceID(span.TraceID()))
dp.SetSpanID(pcommon.SpanID(span.SpanID()))
}
{{- range $event.Attributes }}
{{- if not (attributeInfo .).IsConditional -}}
{{- template "putAttribute" . }}
{{- end }}
{{- end }}
{{ if $event.HasConditionalAttributes $.Attributes }}
for _, op := range options {
op.apply(dp)
}
{{- end }}
}
// emit appends recorded event data to a events slice and prepares it for recording another set of log records.
func (e *event{{ $name.Render }}) emit(lrs plog.LogRecordSlice) {
if e.config.Enabled && e.data.Len() > 0 {
e.data.MoveAndAppendTo(lrs)
}
}
func newEvent{{ $name.Render }}(cfg EventConfig) event{{ $name.Render }} {
e := event{{ $name.Render }}{config: cfg}
if cfg.Enabled {
e.data = plog.NewLogRecordSlice()
}
return e
}
{{ end -}}
// LogsBuilder provides an interface for scrapers to report logs while taking care of all the transformations
// required to produce log representation defined in metadata and user config.
type LogsBuilder struct {
{{- if .Events }}
config LogsBuilderConfig // config of the logs builder.
{{- end }}
logsBuffer plog.Logs
logRecordsBuffer plog.LogRecordSlice
buildInfo component.BuildInfo // contains version information.
{{- if and .Events .ResourceAttributes }}
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
{{- end }}
{{- range $name, $event := .Events }}
event{{ $name.Render }} event{{ $name.Render }}
{{- end }}
}
// LogBuilderOption applies changes to default logs builder.
type LogBuilderOption interface {
apply(*LogsBuilder)
}
{{- if or isReceiver isScraper }}
func NewLogsBuilder({{ if .Events }}lbc LogsBuilderConfig, {{ end }}settings {{ .Status.Class }}.Settings) *LogsBuilder {
{{- range $name, $event := .Events }}
{{- if $event.Warnings.IfEnabled }}
if lbc.Events.{{ $name.Render }}.Enabled {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be enabled: {{ $event.Warnings.IfEnabled }}")
}
{{- end }}
{{- if $event.Warnings.IfEnabledNotSet }}
if !lbc.Events.{{ $name.Render }}.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $event.Warnings.IfEnabledNotSet }}")
}
{{- end }}
{{- if $event.Warnings.IfConfigured }}
if lbc.Events.{{ $name.Render }}.enabledSetByUser {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be configured: {{ $event.Warnings.IfConfigured }}")
}
{{- end }}
{{- end }}
{{- if .Events }}
{{- range $name, $attr := .ResourceAttributes }}
{{- if $attr.Warnings.IfEnabled }}
if lbc.ResourceAttributes.{{ $name.Render }}.Enabled {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be enabled: {{ $attr.Warnings.IfEnabled }}")
}
{{- end }}
{{- if $attr.Warnings.IfEnabledNotSet }}
if !lbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $attr.Warnings.IfEnabledNotSet }}")
}
{{- end }}
{{- if $attr.Warnings.IfConfigured }}
if lbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser || lbc.ResourceAttributes.{{ $name.Render }}.EventsInclude != nil || lbc.ResourceAttributes.{{ $name.Render }}.EventsExclude != nil {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}")
}
{{- end }}
{{- end }}
{{- end }}
lb := &LogsBuilder{
{{- if .Events }}
config: lbc,
{{- end }}
logsBuffer: plog.NewLogs(),
logRecordsBuffer: plog.NewLogRecordSlice(),
buildInfo: settings.BuildInfo,
{{- range $name, $event := .Events }}
event{{ $name.Render }}: newEvent{{ $name.Render }}(lbc.Events.{{ $name.Render }}),
{{- end }}
{{ if and .Events .ResourceAttributes -}}
resourceAttributeIncludeFilter: make(map[string]filter.Filter),
resourceAttributeExcludeFilter: make(map[string]filter.Filter),
{{- end }}
}
{{- if .Events }}
{{- range $name, $attr := .ResourceAttributes }}
if lbc.ResourceAttributes.{{ $name.Render }}.EventsInclude != nil {
lb.resourceAttributeIncludeFilter["{{ $name }}"] = filter.CreateFilter(lbc.ResourceAttributes.{{ $name.Render }}.EventsInclude)
}
if lbc.ResourceAttributes.{{ $name.Render }}.EventsExclude != nil {
lb.resourceAttributeExcludeFilter["{{ $name }}"] = filter.CreateFilter(lbc.ResourceAttributes.{{ $name.Render }}.EventsExclude)
}
{{- end }}
{{- end }}
return lb
}
{{- end }}
{{- if .ResourceAttributes }}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted logs.
func (lb *LogsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder({{ if .Events }}lb.config.ResourceAttributes{{ else }}ResourceAttributesConfig{}{{ end }})
}
{{- end }}
// ResourceLogsOption applies changes to provided resource logs.
type ResourceLogsOption interface {
apply(plog.ResourceLogs)
}
type resourceLogsOptionFunc func(plog.ResourceLogs)
func (rlof resourceLogsOptionFunc) apply(rl plog.ResourceLogs) {
rlof(rl)
}
// WithLogsResource sets the provided resource on the emitted ResourceLogs.
// It's recommended to use ResourceBuilder to create the resource.
func WithLogsResource(res pcommon.Resource) ResourceLogsOption {
return resourceLogsOptionFunc(func(rl plog.ResourceLogs) {
res.CopyTo(rl.Resource())
})
}
// AppendLogRecord adds a log record to the logs builder.
func (lb *LogsBuilder) AppendLogRecord(lr plog.LogRecord) {
lr.MoveTo(lb.logRecordsBuffer.AppendEmpty())
}
// EmitForResource saves all the generated logs under a new resource and updates the internal state to be ready for
// recording another set of log records as part of another resource. This function can be helpful when one scraper
// needs to emit logs from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceLogsOption arguments.
func (lb *LogsBuilder) EmitForResource(options ...ResourceLogsOption) {
rl := plog.NewResourceLogs()
{{- if .SemConvVersion }}
rl.SetSchemaUrl(conventions.SchemaURL)
{{- end }}
ils := rl.ScopeLogs().AppendEmpty()
ils.Scope().SetName(ScopeName)
ils.Scope().SetVersion(lb.buildInfo.Version)
{{- range $name, $event := .Events }}
lb.event{{- $name.Render }}.emit(ils.LogRecords())
{{- end }}
for _, op := range options {
op.apply(rl)
}
if lb.logRecordsBuffer.Len() > 0 {
lb.logRecordsBuffer.MoveAndAppendTo(ils.LogRecords())
lb.logRecordsBuffer = plog.NewLogRecordSlice()
}
{{ if and .Events .ResourceAttributes -}}
for attr, filter := range lb.resourceAttributeIncludeFilter {
if val, ok := rl.Resource().Attributes().Get(attr); ok && !filter.Matches(val.AsString()) {
return
}
}
for attr, filter := range lb.resourceAttributeExcludeFilter {
if val, ok := rl.Resource().Attributes().Get(attr); ok && filter.Matches(val.AsString()) {
return
}
}
{{- end }}
if ils.LogRecords().Len() > 0 {
rl.MoveTo(lb.logsBuffer.ResourceLogs().AppendEmpty())
}
}
// Emit returns all the logs accumulated by the logs builder and updates the internal state to be ready for
// recording another set of logs. This function will be responsible for applying all the transformations required to
// produce logs representation defined in metadata and user config.
func (lb *LogsBuilder) Emit(options ...ResourceLogsOption) plog.Logs {
lb.EmitForResource(options...)
logs := lb.logsBuffer
lb.logsBuffer = plog.NewLogs()
return logs
}
{{ range $name, $event := .Events -}}
// Record{{ $name.Render }}Event adds a log record of {{ $name }} event.
func (lb *LogsBuilder) Record{{ $name.Render }}Event(ctx context.Context, timestamp pcommon.Timestamp
{{- range $event.Attributes -}}
{{- if not (attributeInfo .).IsConditional -}}
, {{ .RenderUnexported }}AttributeValue {{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ else }}{{ (attributeInfo .).Type.Primitive }}{{ end }}
{{- end -}}
{{- end -}}
{{- if $event.HasConditionalAttributes $.Attributes -}}
, options... EventAttributeOption
{{- end -}}) {
lb.event{{ $name.Render }}.recordEvent(ctx, timestamp
{{- range $event.Attributes -}}
{{- if not (attributeInfo .).IsConditional -}}
, {{ .RenderUnexported }}AttributeValue{{ if (attributeInfo .).Enum }}.String(){{ end }}
{{- end -}}
{{- end -}}
{{- if $event.HasConditionalAttributes $.Attributes -}}
, options...
{{- end -}})
}
{{ end }}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/logs_test.go.tmpl 0000664 0000000 0000000 00000022540 15113313446 0030203 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ .Package }}
import (
"time"
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/plog"
{{- if or isReceiver isScraper }}
"go.opentelemetry.io/collector/{{ .Status.Class }}/{{ .Status.Class }}test"
{{- end }}
{{- if .Events }}
"context"
"go.opentelemetry.io/otel/trace"
{{- end }}
)
{{- if .Events }}
type eventsTestDataSet int
const (
eventTestDataSetDefault eventsTestDataSet = iota
eventTestDataSetAll
eventTestDataSetNone
)
{{- end }}
func TestLogsBuilderAppendLogRecord(t *testing.T) {
observedZapCore, _ := observer.New(zap.WarnLevel)
{{- if or isReceiver isScraper }}
settings := {{ .Status.Class }}test.NewNopSettings({{ .Status.Class }}test.NopType)
{{- end }}
settings.Logger = zap.New(observedZapCore)
lb := NewLogsBuilder({{ if .Events }}loadLogsBuilderConfig(t, "all_set"), {{ end }}settings)
{{ if .ResourceAttributes }}
rb := lb.NewResourceBuilder()
{{- range $name, $attr := .ResourceAttributes }}
{{- if $attr.Enum }}
rb.Set{{ $attr.Name.Render }}{{ index $attr.Enum 0 | publicVar }}()
{{- else }}
rb.Set{{ $attr.Name.Render }}({{ $attr.TestValue }})
{{- end }}
{{- end }}
res := rb.Emit()
{{- else }}
res := pcommon.NewResource()
{{- end }}
// append the first log record
lr := plog.NewLogRecord()
lr.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr.Attributes().PutStr("type", "log")
lr.Body().SetStr("the first log record")
// append the second log record
lr2 := plog.NewLogRecord()
lr2.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
lr2.Attributes().PutStr("type", "event")
lr2.Body().SetStr("the second log record")
lb.AppendLogRecord(lr)
lb.AppendLogRecord(lr2)
logs := lb.Emit(WithLogsResource(res))
assert.Equal(t, 1, logs.ResourceLogs().Len())
rl := logs.ResourceLogs().At(0)
assert.Equal(t, 1, rl.ScopeLogs().Len())
sl := rl.ScopeLogs().At(0)
assert.Equal(t, ScopeName,sl.Scope().Name())
assert.Equal(t, lb.buildInfo.Version, sl.Scope().Version())
assert.Equal(t, 2, sl.LogRecords().Len())
attrVal, ok := sl.LogRecords().At(0).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "log", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(0).Body().Type())
assert.Equal(t, "the first log record", sl.LogRecords().At(0).Body().Str())
attrVal, ok = sl.LogRecords().At(1).Attributes().Get("type")
assert.True(t, ok)
assert.Equal(t, "event", attrVal.Str())
assert.Equal(t, pcommon.ValueTypeStr, sl.LogRecords().At(1).Body().Type())
assert.Equal(t, "the second log record", sl.LogRecords().At(1).Body().Str())
}
{{- if .Events }}
func TestLogsBuilder(t *testing.T) {
tests := []struct {
name string
eventsSet eventsTestDataSet
resAttrsSet eventsTestDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
eventsSet: eventTestDataSetAll,
resAttrsSet: eventTestDataSetAll,
},
{
name: "none_set",
eventsSet: eventTestDataSetNone,
resAttrsSet: eventTestDataSetNone,
expectEmpty: true,
},
{{- if .ResourceAttributes }}
{
name: "filter_set_include",
resAttrsSet: eventTestDataSetAll,
},
{
name: "filter_set_exclude",
resAttrsSet: eventTestDataSetAll,
expectEmpty: true,
},
{{- end }}
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
timestamp := pcommon.Timestamp(1_000_001_000)
traceID := [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
spanID := [8]byte{0, 1, 2, 3, 4, 5, 6, 7}
ctx := trace.ContextWithSpanContext(context.Background(), trace.NewSpanContext(trace.SpanContextConfig{
TraceID: trace.TraceID(traceID),
SpanID: trace.SpanID(spanID),
TraceFlags: trace.FlagsSampled,
}))
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
{{- if or isReceiver isScraper }}
settings := {{ .Status.Class }}test.NewNopSettings({{ .Status.Class }}test.NopType)
{{- end }}
settings.Logger = zap.New(observedZapCore)
lb := NewLogsBuilder(loadLogsBuilderConfig(t, tt.name), settings)
expectedWarnings := 0
{{- range $name, $event := .Events }}
{{- if and $event.Enabled $event.Warnings.IfEnabled }}
if tt.eventsSet == eventTestDataSetDefault || tt.eventsSet == eventTestDataSetAll {
assert.Equal(t, "[WARNING] `{{ $name }}` should not be enabled: {{ $event.Warnings.IfEnabled }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- if $event.Warnings.IfEnabledNotSet }}
if tt.eventsSet == eventTestDataSetDefault {
assert.Equal(t, "[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $event.Warnings.IfEnabledNotSet }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- if $event.Warnings.IfConfigured }}
if tt.eventsSet == eventTestDataSetAll || tt.eventsSet == eventTestDataSetNone {
assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $event.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- end }}
{{- range $name, $attr := .ResourceAttributes }}
{{- if and $attr.Enabled $attr.Warnings.IfEnabled }}
if tt.resAttrsSet == eventTestDataSetDefault || tt.resAttrsSet == eventTestDataSetAll {
assert.Equal(t, "[WARNING] `{{ $name }}` should not be enabled: {{ $attr.Warnings.IfEnabled }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- if $attr.Warnings.IfEnabledNotSet }}
if tt.resAttrsSet == eventTestDataSetDefault {
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 tt.resAttrsSet == eventTestDataSetAll || tt.resAttrsSet == eventTestDataSetNone {
assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- end }}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultEventsCount := 0
allEventsCount := 0
{{- range $name, $event := .Events }}
{{ if $event.Enabled }}defaultEventsCount++{{ end }}
allEventsCount++
lb.Record{{ $name.Render }}Event(ctx, timestamp
{{- range $event.Attributes -}}
{{- if not (attributeInfo .).IsConditional -}}
, {{- template "getAttributeValue" . -}}
{{- end -}}
{{- end -}}
{{- range $event.Attributes -}}
{{- if (attributeInfo .).IsConditional -}}
, With{{ .Render }}EventAttribute({{- template "getAttributeValue" . -}})
{{- end -}}
{{- end -}}
)
{{- end }}
{{ if .ResourceAttributes }}
rb := lb.NewResourceBuilder()
{{- range $name, $attr := .ResourceAttributes }}
{{- if $attr.Enum }}
rb.Set{{ $attr.Name.Render }}{{ index $attr.Enum 0 | publicVar }}()
{{- else }}
rb.Set{{ $attr.Name.Render }}({{ $attr.TestValue }})
{{- end }}
{{- end }}
res := rb.Emit()
{{- else }}
res := pcommon.NewResource()
{{- end }}
logs := lb.Emit(WithLogsResource(res))
if tt.expectEmpty || ((tt.name == "default" || tt.name == "filter_set_include") && defaultEventsCount == 0) {
assert.Equal(t, 0, logs.ResourceLogs().Len())
return
}
assert.Equal(t, 1, logs.ResourceLogs().Len())
rl := logs.ResourceLogs().At(0)
assert.Equal(t, res, rl.Resource())
assert.Equal(t, 1, rl.ScopeLogs().Len())
lrs := rl.ScopeLogs().At(0).LogRecords()
if tt.eventsSet == eventTestDataSetDefault {
assert.Equal(t, defaultEventsCount, lrs.Len())
}
if tt.eventsSet == eventTestDataSetAll {
assert.Equal(t, allEventsCount, lrs.Len())
}
validatedEvents := make(map[string]bool)
for i := 0; i < lrs.Len(); i++ {
switch lrs.At(i).EventName() {
{{- range $name, $event := .Events }}
case "{{ $name }}":
assert.False(t, validatedEvents["{{ $name }}"], "Found a duplicate in the events slice: {{ $name }}")
validatedEvents["{{ $name }}"] = true
lr := lrs.At(i)
assert.Equal(t, timestamp, lr.Timestamp())
assert.Equal(t, pcommon.TraceID(traceID), lr.TraceID())
assert.Equal(t, pcommon.SpanID(spanID), lr.SpanID())
{{- range $i, $attr := $event.Attributes }}
attrVal, ok {{ if eq $i 0 }}:{{ end }}= lr.Attributes().Get("{{ (attributeInfo $attr).Name }}")
assert.True(t, ok)
{{- if eq (attributeInfo $attr).Type.String "Bool"}}
assert.{{- if eq (attributeInfo $attr).TestValue "true" }}True{{ else }}False{{- end }}(t, attrVal.{{ (attributeInfo $attr).Type }}()
{{- else if eq (attributeInfo $attr).Type.String "Int"}}
assert.EqualValues(t, {{ (attributeInfo $attr).TestValue }}, attrVal.{{ (attributeInfo $attr).Type }}()
{{- else }}
assert.Equal(t, {{ (attributeInfo $attr).TestValue }}, attrVal.{{ (attributeInfo $attr).Type }}()
{{- end }}
{{- if or (eq (attributeInfo $attr).Type.String "Slice") (eq (attributeInfo $attr).Type.String "Map")}}.AsRaw(){{ end }})
{{- end }}
{{- end }}
}
}
})
}
}
{{- end }}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/metrics.go.tmpl 0000664 0000000 0000000 00000036206 15113313446 0027652 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ .Package }}
import (
{{- if .Metrics | parseImportsRequired }}
"strconv"
"fmt"
{{- end }}
"time"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
{{- if or isReceiver isScraper isConnector }}
"go.opentelemetry.io/collector/{{ .Status.Class }}"
{{- end }}
{{- if .SemConvVersion }}
conventions "go.opentelemetry.io/otel/semconv/v{{ .SemConvVersion }}"
{{- end }}
{{ if .ResourceAttributes -}}
"go.opentelemetry.io/collector/filter"
{{- end }}
)
{{ range $name, $info := .Attributes }}
{{- if $info.Enum -}}
// Attribute{{ $name.Render }} specifies the value {{ $name }} attribute.
type Attribute{{ $name.Render }} int
const (
_ Attribute{{ $name.Render }} = iota
{{- range $info.Enum }}
Attribute{{ $name.Render }}{{ . | publicVar }}
{{- end }}
)
// String returns the string representation of the Attribute{{ $name.Render }}.
func (av Attribute{{ $name.Render }}) String() string {
switch av {
{{- range $info.Enum }}
case Attribute{{ $name.Render }}{{ . | publicVar }}:
return "{{ . }}"
{{- end }}
}
return ""
}
// MapAttribute{{ $name.Render }} is a helper map of string to Attribute{{ $name.Render }} attribute value.
var MapAttribute{{ $name.Render }} = map[string]Attribute{{ $name.Render }}{
{{- range $info.Enum }}
"{{ . }}": Attribute{{ $name.Render }}{{ . | publicVar }},
{{- end }}
}
{{ end }}
{{- end }}
var MetricsInfo = metricsInfo{
{{- range $name, $metric := .Metrics }}
{{ $name.Render }}: metricInfo{
Name: "{{ $name }}",
},
{{- end }}
}
type metricsInfo struct {
{{- range $name, $metric := .Metrics }}
{{ $name.Render }} metricInfo
{{- end }}
}
type metricInfo struct {
Name string
}
{{ if getMetricConditionalAttributes .Attributes }}
type MetricAttributeOption interface {
apply(pmetric.NumberDataPoint)
}
type metricAttributeOptionFunc func(pmetric.NumberDataPoint)
func (maof metricAttributeOptionFunc) apply(dp pmetric.NumberDataPoint) {
maof(dp)
}
{{ range getMetricConditionalAttributes .Attributes }}
func With{{ .Render }}MetricAttribute({{ .RenderUnexported }}AttributeValue {{ (attributeInfo .).Type.Primitive }}) MetricAttributeOption {
return metricAttributeOptionFunc(func(dp pmetric.NumberDataPoint) {
{{- template "putAttribute" . }}
})
}
{{ end }}
{{ end }}
{{ range $name, $metric := .Metrics -}}
type metric{{ $name.Render }} struct {
data pmetric.Metric // data buffer for generated metric.
config MetricConfig // metric config provided by user.
capacity int // max observed number of data points added to the metric.
}
// init fills {{ $name }} metric with initial data.
func (m *metric{{ $name.Render }}) init() {
m.data.SetName("{{ $name }}")
m.data.SetDescription("{{ $metric.Description }}")
m.data.SetUnit("{{ $metric.Unit }}")
m.data.SetEmpty{{ $metric.Data.Type }}()
{{- if $metric.Data.HasMonotonic }}
m.data.{{ $metric.Data.Type }}().SetIsMonotonic({{ $metric.Data.Monotonic }})
{{- end }}
{{- if $metric.Data.HasAggregated }}
m.data.{{ $metric.Data.Type }}().SetAggregationTemporality(pmetric.AggregationTemporality{{ $metric.Data.AggregationTemporality }})
{{- end }}
{{- if $metric.Attributes }}
m.data.{{ $metric.Data.Type }}().DataPoints().EnsureCapacity(m.capacity)
{{- end }}
}
func (m *metric{{ $name.Render }}) recordDataPoint(start pcommon.Timestamp, ts pcommon.Timestamp, val {{ $metric.Data.MetricValueType.BasicType }}
{{- range $metric.Attributes -}}{{- if not (attributeInfo .).IsConditional -}}, {{ .RenderUnexported }}AttributeValue {{ (attributeInfo .).Type.Primitive }}{{ end }}{{ end }}{{- if $metric.HasConditionalAttributes $.Attributes -}}, options ...MetricAttributeOption{{- end -}}) {
if !m.config.Enabled {
return
}
dp := m.data.{{ $metric.Data.Type }}().DataPoints().AppendEmpty()
dp.SetStartTimestamp(start)
dp.SetTimestamp(ts)
dp.Set{{ $metric.Data.MetricValueType }}Value(val)
{{- range $metric.Attributes }}
{{- if not (attributeInfo .).IsConditional -}}
{{- template "putAttribute" . -}}
{{- end }}
{{- end }}
{{- if $metric.HasConditionalAttributes $.Attributes }}
for _, op := range options {
op.apply(dp)
}
{{- end }}
}
// updateCapacity saves max length of data point slices that will be used for the slice capacity.
func (m *metric{{ $name.Render }}) updateCapacity() {
if m.data.{{ $metric.Data.Type }}().DataPoints().Len() > m.capacity {
m.capacity = m.data.{{ $metric.Data.Type }}().DataPoints().Len()
}
}
// emit appends recorded metric data to a metrics slice and prepares it for recording another set of data points.
func (m *metric{{ $name.Render }}) emit(metrics pmetric.MetricSlice) {
if m.config.Enabled && m.data.{{ $metric.Data.Type }}().DataPoints().Len() > 0 {
m.updateCapacity()
m.data.MoveTo(metrics.AppendEmpty())
m.init()
}
}
func newMetric{{ $name.Render }}(cfg MetricConfig) metric{{ $name.Render }} {
m := metric{{ $name.Render }}{config: cfg}
if cfg.Enabled {
m.data = pmetric.NewMetric()
m.init()
}
return m
}
{{ end -}}
// MetricsBuilder provides an interface for scrapers to report metrics while taking care of all the transformations
// required to produce metric representation defined in metadata and user config.
type MetricsBuilder struct {
config MetricsBuilderConfig // config of the metrics builder.
startTime pcommon.Timestamp // start time that will be applied to all recorded data points.
metricsCapacity int // maximum observed number of metrics per resource.
metricsBuffer pmetric.Metrics // accumulates metrics data before emitting.
buildInfo component.BuildInfo // contains version information.
{{- if .ResourceAttributes }}
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
{{- end }}
{{- range $name, $metric := .Metrics }}
metric{{ $name.Render }} metric{{ $name.Render }}
{{- end }}
}
// MetricBuilderOption applies changes to default metrics builder.
type MetricBuilderOption interface {
apply(*MetricsBuilder)
}
type metricBuilderOptionFunc func(mb *MetricsBuilder)
func (mbof metricBuilderOptionFunc) apply(mb *MetricsBuilder) {
mbof(mb)
}
// WithStartTime sets startTime on the metrics builder.
func WithStartTime(startTime pcommon.Timestamp) MetricBuilderOption {
return metricBuilderOptionFunc(func(mb *MetricsBuilder) {
mb.startTime = startTime
})
}
{{- if or isReceiver isScraper isConnector }}
func NewMetricsBuilder(mbc MetricsBuilderConfig, settings {{ .Status.Class }}.Settings, options ...MetricBuilderOption) *MetricsBuilder {
{{- range $name, $metric := .Metrics }}
{{- if $metric.Warnings.IfEnabled }}
if mbc.Metrics.{{ $name.Render }}.Enabled {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be enabled: {{ $metric.Warnings.IfEnabled }}")
}
{{- end }}
{{- if $metric.Warnings.IfEnabledNotSet }}
if !mbc.Metrics.{{ $name.Render }}.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $metric.Warnings.IfEnabledNotSet }}")
}
{{- end }}
{{- if $metric.Warnings.IfConfigured }}
if mbc.Metrics.{{ $name.Render }}.enabledSetByUser {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be configured: {{ $metric.Warnings.IfConfigured }}")
}
{{- end }}
{{- end }}
{{- range $name, $attr := .ResourceAttributes }}
{{- if $attr.Warnings.IfEnabled }}
if mbc.ResourceAttributes.{{ $name.Render }}.Enabled {
settings.Logger.Warn("[WARNING] `{{ $name }}` should not be enabled: {{ $attr.Warnings.IfEnabled }}")
}
{{- end }}
{{- if $attr.Warnings.IfEnabledNotSet }}
if !mbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser {
settings.Logger.Warn("[WARNING] Please set `enabled` field explicitly for `{{ $name }}`: {{ $attr.Warnings.IfEnabledNotSet }}")
}
{{- end }}
{{- if $attr.Warnings.IfConfigured }}
if mbc.ResourceAttributes.{{ $name.Render }}.enabledSetByUser || 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 }}
{{- end }}
mb := &MetricsBuilder{
config: mbc,
startTime: pcommon.NewTimestampFromTime(time.Now()),
metricsBuffer: pmetric.NewMetrics(),
buildInfo: settings.BuildInfo,
{{- range $name, $metric := .Metrics }}
metric{{ $name.Render }}: newMetric{{ $name.Render }}(mbc.Metrics.{{ $name.Render }}),
{{- end }}
{{ 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.apply(mb)
}
return mb
}
{{- end }}
{{- if .ResourceAttributes }}
// NewResourceBuilder returns a new resource builder that should be used to build a resource associated with for the emitted metrics.
func (mb *MetricsBuilder) NewResourceBuilder() *ResourceBuilder {
return NewResourceBuilder(mb.config.ResourceAttributes)
}
{{- end }}
// updateCapacity updates max length of metrics and resource attributes that will be used for the slice capacity.
func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) {
if mb.metricsCapacity < rm.ScopeMetrics().At(0).Metrics().Len() {
mb.metricsCapacity = rm.ScopeMetrics().At(0).Metrics().Len()
}
}
// ResourceMetricsOption applies changes to provided resource metrics.
type ResourceMetricsOption interface {
apply(pmetric.ResourceMetrics)
}
type resourceMetricsOptionFunc func(pmetric.ResourceMetrics)
func (rmof resourceMetricsOptionFunc) apply(rm pmetric.ResourceMetrics) {
rmof(rm)
}
// WithResource sets the provided resource on the emitted ResourceMetrics.
// It's recommended to use ResourceBuilder to create the resource.
func WithResource(res pcommon.Resource) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
res.CopyTo(rm.Resource())
})
}
// WithStartTimeOverride overrides start time for all the resource metrics data points.
// This option should be only used if different start time has to be set on metrics coming from different resources.
func WithStartTimeOverride(start pcommon.Timestamp) ResourceMetricsOption {
return resourceMetricsOptionFunc(func(rm pmetric.ResourceMetrics) {
var dps pmetric.NumberDataPointSlice
metrics := rm.ScopeMetrics().At(0).Metrics()
for i := 0; i < metrics.Len(); i++ {
switch metrics.At(i).Type() {
case pmetric.MetricTypeGauge:
dps = metrics.At(i).Gauge().DataPoints()
case pmetric.MetricTypeSum:
dps = metrics.At(i).Sum().DataPoints()
}
for j := 0; j < dps.Len(); j++ {
dps.At(j).SetStartTimestamp(start)
}
}
})
}
// EmitForResource saves all the generated metrics under a new resource and updates the internal state to be ready for
// recording another set of data points as part of another resource. This function can be helpful when one scraper
// needs to emit metrics from several resources. Otherwise calling this function is not required,
// just `Emit` function can be called instead.
// Resource attributes should be provided as ResourceMetricsOption arguments.
func (mb *MetricsBuilder) EmitForResource(options ...ResourceMetricsOption) {
rm := pmetric.NewResourceMetrics()
{{- if .SemConvVersion }}
rm.SetSchemaUrl(conventions.SchemaURL)
{{- end }}
ils := rm.ScopeMetrics().AppendEmpty()
ils.Scope().SetName(ScopeName)
ils.Scope().SetVersion(mb.buildInfo.Version)
ils.Metrics().EnsureCapacity(mb.metricsCapacity)
{{- range $name, $metric := .Metrics }}
mb.metric{{- $name.Render }}.emit(ils.Metrics())
{{- end }}
for _, op := range options {
op.apply(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())
}
}
// Emit returns all the metrics accumulated by the metrics builder and updates the internal state to be ready for
// recording another set of metrics. This function will be responsible for applying all the transformations required to
// produce metric representation defined in metadata and user config, e.g. delta or cumulative.
func (mb *MetricsBuilder) Emit(options ...ResourceMetricsOption) pmetric.Metrics {
mb.EmitForResource(options...)
metrics := mb.metricsBuffer
mb.metricsBuffer = pmetric.NewMetrics()
return metrics
}
{{ range $name, $metric := .Metrics -}}
// Record{{ $name.Render }}DataPoint adds a data point to {{ $name }} metric.
func (mb *MetricsBuilder) Record{{ $name.Render }}DataPoint(ts pcommon.Timestamp
{{- if $metric.Data.HasMetricInputType }}, inputVal {{ $metric.Data.MetricInputType.String }}
{{- else }}, val {{ $metric.Data.MetricValueType.BasicType }}
{{- end }}
{{- range $metric.Attributes -}}
{{- if not (attributeInfo .).IsConditional -}}
, {{ .RenderUnexported }}AttributeValue {{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ else }}{{ (attributeInfo .).Type.Primitive }}{{ end }}
{{- end -}}
{{- end -}}
{{- if $metric.HasConditionalAttributes $.Attributes -}}
, options... MetricAttributeOption
{{- end -}}
)
{{- if $metric.Data.HasMetricInputType }} error{{ end }} {
{{- if $metric.Data.HasMetricInputType }}
{{- if eq $metric.Data.MetricValueType.BasicType "float64" }}
val, err := strconv.ParseFloat(inputVal, 64)
{{- else if eq $metric.Data.MetricValueType.BasicType "int64" }}
val, err := strconv.ParseInt(inputVal, 10, 64)
{{- end }}
if err != nil {
return fmt.Errorf("failed to parse {{ $metric.Data.MetricValueType.BasicType }} for {{ $name.Render }}, value was %s: %w", inputVal, err)
}
{{- end }}
mb.metric{{ $name.Render }}.recordDataPoint(mb.startTime, ts, val
{{- range $metric.Attributes -}}
{{- if not (attributeInfo .).IsConditional -}}
, {{ .RenderUnexported }}AttributeValue{{ if (attributeInfo .).Enum }}.String(){{ end }}
{{- end -}}
{{- end -}}
{{- if $metric.HasConditionalAttributes $.Attributes -}}
, options...
{{- end -}}
)
{{- if $metric.Data.HasMetricInputType }}
return nil
{{- end }}
}
{{ end }}
// Reset resets metrics builder to its initial state. It should be used when external metrics source is restarted,
// and metrics builder should update its startTime and reset it's internal state accordingly.
func (mb *MetricsBuilder) Reset(options ...MetricBuilderOption) {
mb.startTime = pcommon.NewTimestampFromTime(time.Now())
for _, op := range options {
op.apply(mb)
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/metrics_test.go.tmpl 0000664 0000000 0000000 00000017626 15113313446 0030716 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ .Package }}
import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
{{- if or isReceiver isScraper isConnector }}
"go.opentelemetry.io/collector/{{ .Status.Class }}/{{ .Status.Class }}test"
{{- end }}
"go.uber.org/zap"
"go.uber.org/zap/zaptest/observer"
)
type testDataSet int
const (
testDataSetDefault testDataSet = iota
testDataSetAll
testDataSetNone
)
func TestMetricsBuilder(t *testing.T) {
tests := []struct {
name string
metricsSet testDataSet
resAttrsSet testDataSet
expectEmpty bool
}{
{
name: "default",
},
{
name: "all_set",
metricsSet: testDataSetAll,
resAttrsSet: testDataSetAll,
},
{
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 _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
start := pcommon.Timestamp(1_000_000_000)
ts := pcommon.Timestamp(1_000_001_000)
observedZapCore, observedLogs := observer.New(zap.WarnLevel)
{{- if or isReceiver isScraper isConnector }}
settings := {{ .Status.Class }}test.NewNopSettings({{ .Status.Class }}test.NopType)
{{- end }}
settings.Logger = zap.New(observedZapCore)
mb := NewMetricsBuilder(loadMetricsBuilderConfig(t, tt.name), settings, WithStartTime(start))
expectedWarnings := 0
{{- range $name, $metric := .Metrics }}
{{- if and $metric.Enabled $metric.Warnings.IfEnabled }}
if tt.metricsSet == testDataSetDefault || tt.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 tt.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 tt.metricsSet == testDataSetAll || tt.metricsSet == testDataSetNone {
assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $metric.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- end }}
{{- range $name, $attr := .ResourceAttributes }}
{{- if and $attr.Enabled $attr.Warnings.IfEnabled }}
if tt.resAttrsSet == testDataSetDefault || tt.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 tt.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 tt.resAttrsSet == testDataSetAll || tt.resAttrsSet == testDataSetNone {
assert.Equal(t, "[WARNING] `{{ $name }}` should not be configured: {{ $attr.Warnings.IfConfigured }}", observedLogs.All()[expectedWarnings].Message)
expectedWarnings++
}
{{- end }}
{{- end }}
assert.Equal(t, expectedWarnings, observedLogs.Len())
defaultMetricsCount := 0
allMetricsCount := 0
{{- range $name, $metric := .Metrics }}
{{ if $metric.Enabled }}defaultMetricsCount++{{ end }}
allMetricsCount++
mb.Record{{ $name.Render }}DataPoint(ts, {{ if $metric.Data.HasMetricInputType }}"1"{{ else }}1{{ end }}
{{- range $metric.Attributes -}}
{{- if not (attributeInfo .).IsConditional -}}
, {{- template "getAttributeValue" . -}}
{{- end -}}
{{- end -}}
{{- range $metric.Attributes -}}
{{- if (attributeInfo .).IsConditional -}}
, With{{ .Render }}MetricAttribute({{- template "getAttributeValue" . -}})
{{- end -}}
{{- end -}}
)
{{- end }}
{{ if .ResourceAttributes }}
rb := mb.NewResourceBuilder()
{{- range $name, $attr := .ResourceAttributes }}
{{- if $attr.Enum }}
rb.Set{{ $attr.Name.Render }}{{ index $attr.Enum 0 | publicVar }}()
{{- else }}
rb.Set{{ $attr.Name.Render }}({{ $attr.TestValue }})
{{- end }}
{{- end }}
res := rb.Emit()
{{- else }}
res := pcommon.NewResource()
{{- end }}
metrics := mb.Emit(WithResource(res))
if tt.expectEmpty {
assert.Equal(t, 0, metrics.ResourceMetrics().Len())
return
}
assert.Equal(t, 1, metrics.ResourceMetrics().Len())
rm := metrics.ResourceMetrics().At(0)
assert.Equal(t, res, rm.Resource())
assert.Equal(t, 1, rm.ScopeMetrics().Len())
ms := rm.ScopeMetrics().At(0).Metrics()
if tt.metricsSet == testDataSetDefault {
assert.Equal(t, defaultMetricsCount, ms.Len())
}
if tt.metricsSet == testDataSetAll {
assert.Equal(t, allMetricsCount, ms.Len())
}
validatedMetrics := make(map[string]bool)
for i := 0; i < ms.Len(); i++ {
switch ms.At(i).Name() {
{{- range $name, $metric := .Metrics }}
case "{{ $name }}":
assert.False(t, validatedMetrics["{{ $name }}"], "Found a duplicate in the metrics slice: {{ $name }}")
validatedMetrics["{{ $name }}"] = true
assert.Equal(t, pmetric.MetricType{{ $metric.Data.Type }}, ms.At(i).Type())
assert.Equal(t, 1, ms.At(i).{{ $metric.Data.Type }}().DataPoints().Len())
assert.Equal(t, "{{ $metric.Description }}", ms.At(i).Description())
{{- if len $metric.Unit}}
assert.Equal(t, "{{ $metric.Unit }}", ms.At(i).Unit())
{{- else }}
assert.Empty(t, ms.At(i).Unit())
{{- end }}
{{- if $metric.Data.HasMonotonic }}
assert.{{- if $metric.Data.Monotonic }}True{{ else }}False{{ end }}(t, ms.At(i).{{ $metric.Data.Type }}().IsMonotonic())
{{- end }}
{{- if $metric.Data.HasAggregated }}
assert.Equal(t, pmetric.AggregationTemporality{{ $metric.Data.AggregationTemporality }}, ms.At(i).{{ $metric.Data.Type }}().AggregationTemporality())
{{- end }}
dp := ms.At(i).{{ $metric.Data.Type }}().DataPoints().At(0)
assert.Equal(t, start, dp.StartTimestamp())
assert.Equal(t, ts, dp.Timestamp())
assert.Equal(t, pmetric.NumberDataPointValueType{{ $metric.Data.MetricValueType }}, dp.ValueType())
{{- if eq $metric.Data.MetricValueType.BasicType "float64" }}
assert.InDelta(t, {{ $metric.Data.MetricValueType.BasicType }}(1), dp.{{ $metric.Data.MetricValueType }}Value(), 0.01)
{{- else }}
assert.Equal(t, {{ $metric.Data.MetricValueType.BasicType }}(1), dp.{{ $metric.Data.MetricValueType }}Value())
{{- end }}
{{- range $i, $attr := $metric.Attributes }}
attrVal, ok {{ if eq $i 0 }}:{{ end }}= dp.Attributes().Get("{{ (attributeInfo $attr).Name }}")
assert.True(t, ok)
{{- if eq (attributeInfo $attr).Type.String "Bool"}}
assert.{{- if eq (attributeInfo $attr).TestValue "true" }}True{{ else }}False{{- end }}(t, attrVal.{{ (attributeInfo $attr).Type }}()
{{- else if eq (attributeInfo $attr).Type.String "Int"}}
assert.EqualValues(t, {{ (attributeInfo $attr).TestValue }}, attrVal.{{ (attributeInfo $attr).Type }}()
{{- else }}
assert.Equal(t, {{ (attributeInfo $attr).TestValue }}, attrVal.{{ (attributeInfo $attr).Type }}()
{{- end }}
{{- if or (eq (attributeInfo $attr).Type.String "Slice") (eq (attributeInfo $attr).Type.String "Map")}}.AsRaw(){{ end }})
{{- end }}
{{- end }}
}
}
})
}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/package_test.go.tmpl 0000664 0000000 0000000 00000001457 15113313446 0030636 0 ustar 00root root 0000000 0000000 // Code generated by mdatagen. DO NOT EDIT.
package {{ if isCommand -}}main{{ else }}{{ .Package }}{{- end }}
import (
{{- if .Tests.GoLeak.Skip }}
"os"
{{- end }}
"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
os.Exit(m.Run())
{{- 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 }}
}
opentelemetry-collector-0.141.0/cmd/mdatagen/internal/templates/readme.md.tmpl 0000664 0000000 0000000 00000010413 15113313446 0027424 0 ustar 00root root 0000000 0000000
{{- if len .Status.Stability }}
| Status | |
| ------------- |-----------|
{{- $class := .Status.Class }}
{{- $shortName := .ShortFolderName }}
{{- if ne $class "connector" }}
{{- $idx := 0 }}
{{- range $stability, $value := .Status.Stability }}
| {{ if not $idx }}Stability{{ else }} {{ end }} | [{{ toLowerCase $stability.String }}]{{ if and (ne $class "extension") (ne $class "converter") (ne $class "provider") }}: {{ stringsJoin $value ", " }} {{ end }} |
{{- $idx = inc $idx }}
{{- end }}
{{- if .Status.Deprecation }}
{{- range $deprecation, $value := .Status.Deprecation }}
| Deprecation of {{ toLowerCase $deprecation }} | [Date]: {{ $value.Date }}{{ if and (ne $class "extension") (ne $class "converter") (ne $class "provider") }} {{ end }} |
| | [Migration Note]: {{ $value.Migration }}{{ if ne $class "extension" }} {{ end }} |
{{- end }}
{{- end }}
{{- end}}
{{- if .Status.UnsupportedPlatforms }}
| Unsupported Platforms | {{ stringsJoin .Status.UnsupportedPlatforms ", " }} |
{{- end }}
{{- if and (ne $class "cmd") (ne $class "pkg") }}
| Distributions | [{{ stringsJoin .Status.SortedDistributions "], [" }}] |
{{- end }}
{{- if .Status.Warnings }}
| Warnings | [{{ stringsJoin .Status.Warnings ", " }}](#warnings) |
{{- end }}
{{- if ne $class "" }}
| Issues | [](https://github.com/{{ .GithubProject }}/issues?q=is%3Aopen+is%3Aissue+label%3A{{ $class }}%2F{{ $shortName }}) [](https://github.com/{{ .GithubProject }}/issues?q=is%3Aclosed+is%3Aissue+label%3A{{ $class }}%2F{{ $shortName }}) |
{{- if not .Status.DisableCodeCov }}
| Code coverage | [](https://app.codecov.io/gh/{{ .GithubProject}}/tree/main/?components%5B0%5D={{ .GetCodeCovComponentID }}&displayType=list) |
{{- end }}
{{- end }}
{{- if .Status.Codeowners }}
{{- $codeowners := userLinks .Status.Codeowners.Active }}
{{- $emeritus := userLinks .Status.Codeowners.Emeritus }}
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | {{ stringsJoin $codeowners ", " }} {{ if .Status.Codeowners.SeekingNew }}\| Seeking more code owners! {{ end }}|
{{- if $emeritus }}
| Emeritus | {{ stringsJoin $emeritus ", " }} |
{{- end }}
{{- end }}
{{range $stability, $val := .Status.Stability}}
[{{ toLowerCase $stability.String }}]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#{{ toLowerCase $stability.String }}
{{- end }}
{{- if .Status.Deprecation }}
[Date]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecation-information
[Migration Note]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#deprecation-information
{{- end }}
{{- range .Status.SortedDistributions }}
[{{.}}]: {{ distroURL . }}
{{- end }}
{{- if eq $class "connector"}}
## Supported Pipeline Types
| [Exporter Pipeline Type] | [Receiver Pipeline Type] | [Stability Level] |
| ------------------------ | ------------------------ | ----------------- |
{{- range $stability, $pipelines := .Status.Stability }}
{{- range $pipeline := $pipelines }}
{{- $parts := stringsSplit $pipeline "_to_" }}
| {{index $parts 0}} | {{index $parts 1}} | [{{ toLowerCase $stability.String }}] |
{{- end }}
{{- end }}
[Exporter Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#exporter-pipeline-type
[Receiver Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#receiver-pipeline-type
[Stability Level]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stability-levels
{{- end }}
{{- end }}