Technical Documentation: open-telemetry/opentelemetry-collector-contrib
βΉοΈ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference
Overview (`README.md`)
OpenTelemetry Collector Contrib
This is a repository for OpenTelemetry Collector components that are not suitable for the core repository of the collector.
The official distributions, core and contrib, are available as part of the opentelemetry-collector-releases repository. Some of the components in this repository are part of the "core" distribution, such as the Jaeger and Prometheus components, but most of the components here are only available as part of the "contrib" distribution. Users of the OpenTelemetry Collector are also encouraged to build their own custom distributions with the OpenTelemetry Collector Builder, using the components they need from the core repository, the contrib repository, and possibly third-party or internal repositories.
Each component has its own support levels, as defined in the following sections. For each signal that a component supports, there's a stability level, setting the right expectations. It is possible then that a component will be Stable for traces but Alpha for metrics and Development for logs.
Stability levels
Stability level for components in this repository follow the definitions from the OpenTelemetry Collector repository.
Gated features
Some features are hidden behind feature gates before they are part of the main code path for the component. Note that the feature gates themselves might be at different lifecycle stages.
Support
Each component is supported either by the community of OpenTelemetry Collector Contrib maintainers, as defined by the GitHub group @open-telemetry/collector-contrib-maintainers, or by specific vendors. See the individual README files for information about the specific components.
The OpenTelemetry Collector Contrib maintainers may at any time downgrade specific components if they are deemed unmaintained or if they pose a risk to the repository and/or binary distribution.
Even though the OpenTelemetry Collector Contrib maintainers are ultimately responsible for the components hosted here, actual support will likely be provided by individual contributors, typically a code owner for the specific component.
Contributing
See CONTRIBUTING.md.
Maintainers
- Alex Boten, Grafana Labs
- Andrzej Stencel, Elastic
- Antoine Toulme, Splunk
- Bogdan Drutu, Snowflake
- Braydon Kains, Google
- Christos Markou, Elastic
- Dmitrii Anoshin, Splunk
- Edmo Vamerlatti Costa, Elastic
- Evan Bradley, Dynatrace
- Pablo Baeyens, DataDog
- Sean Marciniak, Splunk
- Tyler Helmuth, Grafana Labs
- Yang Song, DataDog
For more information about the maintainer role, see the community repository.
Approvers
- Arthur Silva Sens, Grafana Labs
- ConstanΓ§a Manteigas, Elastic
- Curtis Robert, Splunk
- David Ashpole, Google
- Israel Blancas, Coralogix
- Joshua MacDonald, Microsoft
- Matt Wear, Dash0
- Mike Goldsmith, Honeycomb
- Paulo Dias, Five9
- Paulo Janotti, Splunk
- Sam DeHaan, Grafana Labs
- Vihas Makwana, Elastic
For more information about the approver role, see the community repository.
Triagers
- Benedikt Bongartz, Red Hat
- Bogdan Stancu, Adobe
- DΓ³nal O'Sullivan, Elastic
- Douglas Camata, Coralogix
- Dylan Strohschein, Dynatrace
- George Krajcsovits, Grafana Labs
- James Moessis, Optiver
- Jared Tan, DaoCloud
- Khushi Jain, Elastic
- Murphy Chen, DaoCloud
- Ondrej Dubaj, Dynatrace
- Roger Coll, Elastic
- Vibhanshu Singh
- Actively seeking contributors to triage issues
For more information about the triager role, see the community repository.
Emeritus
- Alolita Sharma, Triager
- Andrew Wilkins, Approver
- Anthony Mirabella, Approver
- Bryan Aguilar, Approver
- Daniel Jaglowski, Maintainer
- Florian Bacher, Triager
- Gabriel Aszalos, Triager
- Goutham Veeramachaneni, Triager
- Juraci PaixΓ£o KrΓΆhling, Maintainer
- Przemek Maciolek, Approver
- Punya Biswal, Triager
- Ruslan Kovalov, Approver
- Steve Flanders, Triager
- Tigran Najaryan, Maintainer
- Ziqi Zhao, Approver
For more information about the emeritus role, see the community repository.
No Over-Representation
A community member cannot be promoted to be a Collector contrib maintainer if, after their promotion, the resulting maintainers group has more than one-fourth (25%) of the members affiliated with the same employer. Job changes and similar events might result in over-representation, and no new maintainers from the same company can be promoted until representation is balanced again. In the event of confusion or concern, the OpenTelemetry Collector SIG will defer to the CNCF definition of "same employer".
PRs and Reviews
When creating a PR please follow the process described
here.
New PRs will be automatically associated with the reviewers based on
CODEOWNERS. PRs will be also automatically assigned to one of the
maintainers or approvers for facilitation.
The facilitator is responsible for helping the PR author and reviewers to make progress
or if progress cannot be made for closing the PR.
If the reviewers do not have approval rights the facilitator is also responsible
for the official approval that is required for the PR to be merged and if the facilitator
is a maintainer they are responsible for merging the PR as well.
The facilitator is not required to perform a thorough review, but they are encouraged to
enforce Collector best practices and consistency across the codebase and component
behavior. The facilitators will typically rely on codeowner's detailed review of the code
when making the final approval decision.
Marking the PR with the ready to merge label should only happen (by triagers/approvers/maintainers)
once there is at least one approval from an approver, as per the description above.
Marking the PR with the waiting-for-approvers label can be done (by triagers/code owners/approvers/maintainers)
once the PR has been reviewed and approved by code owners, all review comments are addressed, CI is green,
and it is only waiting on a review from an approver or maintainer. Use this label instead of pinging@open-telemetry/collector-contrib-approvers. Once an approver approves the PR, replace it with the ready to merge label.
Overview (`.chloggen/README.md`)
Changelog folder
This repo uses chloggen to manage its changelog files. You can find the source code for the tool here.
Here is a quick explanation of the config.yaml file for chloggen:
# The directory that stores individual changelog entries.
# Each entry is stored in a dedicated yaml file.
# - 'chloggen new' will copy the 'template_yaml' to this directory as a new entry file.
# - 'chloggen validate' will validate that all entry files are valid.
# - 'chloggen update' will read and delete all entry files in this directory, and update 'changelog_md'.
# Specify as relative path from root of repo.
# (Optional) Default: .chloggen
entries_dir: .chloggen
# This file is used as the input for individual changelog entries.
# Specify as relative path from root of repo.
# (Optional) Default: .chloggen/TEMPLATE.yaml
template_yaml: .chloggen/TEMPLATE.yaml
summary_template: .chloggen/summary.tmpl
# The CHANGELOG file or files to which 'chloggen update' will write new entries
# (Optional) Default filename: CHANGELOG.md
change_logs:
user: CHANGELOG.md
api: CHANGELOG-API.md
# The default change_log or change_logs to which an entry should be added.
# If 'change_logs' is specified in this file, and no value is specified for 'default_change_logs',
# then 'change_logs' MUST be specified in every entry file.
default_change_logs: [user]Overview (`pkg/README.md`)
`pkg` folder
The Go modules in this folder can help in building new components (receivers, processors, exporters, extensions...) and are meant for external consumption.
Carefully review the public API to ensure that we only expose what is deemed necessary, so that we can easily change the code without affecting external users.
Breaking changes can happen on any module on this folder under the opentelemetry-collector contribution guidelines.
If you are introducing a new module that will only be used by components in the opentelemetry-collector-contrib repository, consider placing it on the internal folder instead.
This will reduce our public API footprint and maintenance burden.
Overview (`testbed/README.md`)
OpenTelemetry Collector Testbed
Testbed is a controlled environment and tools for conducting end-to-end tests for the Otel Collector,
including reproducible short-term benchmarks, correctness tests, long-running stability tests and
maximum load stress tests.
Usage
For each type of tests that should have a summary report create a new directory and then a test suite function which utilizes *testing.M. This function should delegate all functionality to testbed.DoTestMain supplying a global instance of testbed.TestResultsSummary to it.
Each test case within the suite should create a testbed.TestCase and supply implementations of each of the various interfaces the NewTestCase function takes as parameters.
DataFlow
testbed.TestCase uses LoadGenerator and MockBackend to further encapsulate pluggable components. LoadGenerator's reference implementation ProviderSender, created via testbed.NewLoadGenerator() further encapsulates DataProvider and DataSender in order to generate and send data. Any type satisfying the LoadGenerator interface can be used with testbed.NewLoadGeneratorTestCase() to exercise functionality beyond the single component limitation of ProviderSender. MockBackend further encapsulates DataReceiver and provides consume functionality.
For instance, if using the existing end-to-end test, the general dataflow can be (Note that MockBackend does not really have a consumer instance, only to make it intuitive, this diagram draws it a separate module):
Pluggable Test Components
DataProvider- Generates test data to send to receiver under test.PerfTestDataProvider- Implementation of theDataProviderfor use in performance tests. Tracing IDs are based on the incremented batch and data items counters.GoldenDataProvider- Implementation ofDataProviderfor use in correctness tests. Provides data from the "Golden" dataset generated using pairwise combinatorial testing techniques.
DataSender- Sends data to the collector instance under test.OTLPTraceDataSender,OTLPMetricsDataSender,OTLPLogsDataSender- OTLP/gRPC and OTLP/HTTP variants live in thetestbed/testbedpackage.- All other senders live in their own sub-package under
testbed/datasenders/<component>datasender, e.g.jaegerdatasender.NewJaegerGRPCDataSender(jaegerreceiver) orzipkindatasender.NewZipkinDataSender(zipkinreceiver). Seetestbed/datasenders/for the full set.
DataReceiver- Receives data from the collector instance under test and stores it for use in test assertions.OTLPDataReceiver,OTLPHTTPDataReceiver- live in thetestbed/testbedpackage.- All other receivers live in their own sub-package under
testbed/datareceivers/<component>datareceiver, e.g.jaegerdatareceiver.NewJaegerDataReceiverorzipkindatareceiver.NewZipkinDataReceiver. Seetestbed/datareceivers/for the full set.
OtelcolRunner- Configures, starts and stops one or more instances of otelcol which will be the subject of testing being executed.ChildProcess- Implementation ofOtelcolRunnerruns a single otelcol as a child process on the same machine as the test executor.InProcessCollector- Implementation ofOtelcolRunnerruns a single otelcol as a go routine within the same process as the test executor.
TestCaseValidator- Validates and reports on test results.PerfTestValidator- Implementation ofTestCaseValidatorfor test suites usingPerformanceResultsfor summarizing results.CorrectnessTestValidator- Implementation ofTestCaseValidatorfor test suites usingCorrectnessResultsfor summarizing results.
TestResultsSummary- Records itemized test case results plus a summary of one category of testing.PerformanceResults- Implementation ofTestResultsSummarywith fields suitable for reporting performance test results.CorrectnessResults- Implementation ofTestResultsSummarywith fields suitable for reporting data translation correctness test results.
Adding New Receiver and/or Exporters to the testbed
New DataSender and DataReceiver implementations live in their own sub-package
under testbed/datasenders/<component>datasender andtestbed/datareceivers/<component>datareceiver. Connector helpers follow the
same pattern under testbed/dataconnectors/<component>dataconnector. Keeping
one component per package means each test binary only compiles the senders,
receivers, and connectors it actually exercises.
Generally, when designing a test for new exporter and receiver components, developers should mainly focus on designing and implementing the components with yellow background in the diagram above as the other components are implemented by the testbed framework:
DataSender- This part should provide below interfaces for testing purpose:Start()- Start sender and connect to the configured endpoint. Must be called before sending data.Flush()- Send any accumulated data.GetCollectorPort()- Return the port to which this sender will send data.GenConfigYAMLStr()- Generate a config string to place in receiver part of collector config so that it can receive data from this sender.ProtocolName()- Return protocol name to use in collector config pipeline.
DataReceiver- This part should provide below interfaces for testing purpose:Start()- Start receiver.Stop()- Stop receiver.GenConfigYAMLStr()- Generate a config string to place in exporter part of collector config so that it can send data to this receiver.ProtocolName()- Return protocol name to use in collector config pipeline.
Testing- This part may vary from what kind of testing developers would like to do. In existing implementation, we can refer to End-to-End testing, Metrics testing, Traces testing, Correctness Traces testing, and Correctness Metrics testing. For instance, if developers would like to design a trace test for a new exporter and receiver:- go
func TestTrace10kSPS(t *testing.T) { tests := []struct { name string sender testbed.DataSender receiver testbed.DataReceiver resourceSpec testbed.ResourceSpec }{ { "NewExporterOrReceiver", xxxdatasender.NewXXXDataSender(testbed.DefaultHost, testutil.GetAvailablePort(t)), xxxdatareceiver.NewXXXDataReceiver(testutil.GetAvailablePort(t)), testbed.ResourceSpec{ ExpectedMaxCPU: XX, ExpectedMaxRAM: XX, }, }, ... } processors := []ProcessorNameAndConfigBody{ { Name: "batch", Body: ` batch: `, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { Scenario10kItemsPerSecond( t, test.sender, test.receiver, test.resourceSpec, performanceResultsSummary, processors, ) }) } }
Running the tests
To run the tests, use the e2e-test Makefile target, which will compile the Collector and run the end-to-end test suites against it.
Run all tests
Run the following at the root of the repo:
make e2e-testRun a particular test suite
Run the following at the root of the repo:
TESTS_DIR=correctnesstests/metrics make e2e-testAdvanced usage
A Makefile is also located at testbed/Makefile that offers targets to directly run certain test suites. Note that these targets will not compile the Collector before running.
Overview (`cmd/codecovgen/README.md`)
codecovgen
This tool generates the component list in the .codecov.yml file.
Each Go module gets its own component, which allows to have code coverage results on a per-component basis.
Overview (`cmd/githubgen/README.md`)
β οΈ This executable has moved to opentelemetry-go-build-tools.
See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/37294.
Overview (`cmd/golden/README.md`)
Golden tester
| Status | |
|---|---|
| Stability | alpha: metrics |
| Issues | |
| Code coverage | |
| Code Owners | @atoulme |
Overview (`cmd/opampsupervisor/README.md`)
OpAMP Supervisor for the OpenTelemetry Collector
| Status | |
|---|---|
| Stability | alpha: metrics |
| Issues | |
| Code Owners | @evan-bradley, @atoulme, @tigrannajaryan, @douglascamata, @dpaasman00 |
This is an implementation of an OpAMP Supervisor that runs a Collector instance using configuration provided from an OpAMP server. This implementation
is following a design specified here.
The design is still undergoing changes, and as such this implementation may change as well.
Binary and container images for the Supervisor are available under tags starting with cmd/opampsupervisor here.
More information
If you'd like to learn more about OpAMP, see the
OpAMP specification.
For production-ready client and server implementations in Go, see the
OpAMP Go repository.
If you have questions or would like to participate, we'd love to hear from you.
There is a regular SIG meeting, see the
meeting notes
for more information. You can also get in touch with us in the
#otel-opamp channel on
the CNCF Slack workspace.
Installing the Supervisor
Binary
Binaries are available as downloadable assets from OpenTelemetry Collector releases with tags using the prefix cmd/opampsupervisor. You can download the file containing the binary for your OS and architecture, and install it on your machine manually.
Linux/macOS
Replace <VERSION> with your desired Supervisor version, and <OS> and <ARCH> with your platform-specific information:
curl --proto '=https' --tlsv1.2 -fL -o opampsupervisor \
"https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/cmd%2Fopampsupervisor%2Fv<VERSION>/opampsupervisor_<VERSION>_<OS>_<ARCH>"
chmod +x opampsupervisorWindows
Replace <VERSION> with your desired Supervisor version:
Invoke-WebRequest -Uri "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/cmd%2Fopampsupervisor%2Fv<VERSION>/opampsupervisor_<VERSION>_windows_amd64.exe" -OutFile "opampsupervisor.exe"
Unblock-File -Path "opampsupervisor.exe"Container image
Container images are available for download from GitHub Container registry:
docker pull ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-opampsupervisorUsing the Supervisor
To use the Supervisor, you will need four things:
- A Supervisor binary, which can be obtained through the installation step above.
- A Collector binary that you would like to control through the Supervisor.
- A Supervisor config file. See examples here.
- A running OpAMP server.
To test the Supervisor with an example server, download the
opamp-go repository, and run the
OpAMP example server in the internal/examples/server directory.
git clone [email protected]:open-telemetry/opamp-go.git
cd opamp-go/internal/examples/server
go run .Visit localhost:4321 to verify that the server is running.
In a separate directory, create a Supervisor configuration file named supervisor.yaml. Copy one of the existing examples or create a new configuration. The agent::executable should be set to the path of your Collector binary:
agent:
executable: <COLLECTOR_BINARY>Start the Supervisor:
./opampsupervisor --config=supervisor.yamlThe supervisor's own log encoding is configured under telemetry.logs.encoding.
Use console for plain-text logs with ISO8601 timestamps. Leave the field
unset (or set it to json) to keep the default JSON output.
telemetry:
logs:
encoding: consoleThe supervisor can also configure resource detection for its own telemetry
using the experimental telemetry.resource.detection/development field.
telemetry:
resource:
detection/development:
detectors:
- host: {}
- process: {}Supported detector entries are container, host, process, and service.
Do not set the OTEL_EXPERIMENTAL_CONFIG_FILE environment variable for the
Supervisor process. xotelconf.NewSDK uses that file to configure the SDK and
it supersedes the configuration passed by the Supervisor. If the variable is
set (for example to control the Collector's resource config), it can also
override the Supervisor's own resource detection and telemetry resource
settings. The Supervisor logs a warning at startup when the variable is set
while telemetry.resource.detection/development is configured.
Visit localhost:4321 again to verify that your Collector appears in the Agents list.
Collector crash log snippets
The Supervisor can include the tail of the Collector's logs in health and remote config failure messages when the Collector process exits unexpectedly. This is disabled by default because Collector logs may contain sensitive data. To enable it, set agent::collector_crash_log_snippet_kib to the maximum number of log KiB to include. A value of 0 disables the feature. 4 is a reasonable starting point. The maximum value is 1024 (1 MiB).
agent:
collector_crash_log_snippet_kib: 4Persistent data storage
The supervisor persists some data to disk in order to mantain state between restarts. The directory where this data is stored may be specified via the supervisor configuration:
storage:
directory: "/path/to/storage/dir"By default, the supervisor will use /var/lib/otelcol/supervisor on posix systems, and %ProgramData%/Otelcol/Supervisor on Windows.
This directory will be created on supervisor startup if it does not exist.
Healthcheck
The Supervisor can be configured to expose a healthcheck endpoint that can be used to determine whether the Supervisor is running and healthy. This can be configured in the Supervisor configuration file:
healthcheck:
endpoint: localhost:13133At the moment this healtcheck checks that the following conditions are met:
- The Supervisor is able to persist state to disk.
- The Supervisor is able to generate the agent's configuration.
For more details on the healthcheck configuration, see the see the full list of ServerConfig options.
Note that the healthceck endpoint is not enabled by default. To enable it, you must explicitly set at least the endpoint field in the configuration.
Startup Fallback Configuration
The Supervisor supports a startup fallback configuration mechanism that provides resilience when the OpAMP server is unreachable at startup and there's no previous configuration state persisted in disk. This is useful for ensuring the Collector can start with a known-good configuration during network outages or server maintenance. When the Supervisor successfully connects to the OpAMP server, the regular configuration (indicated by agent::config_files) is restored and any potential remote configuration received from the OpAMP server is applied.
If, when the Supervisor starts, there's previous configuration state persisted in disk, the Supervisor will use it to start the Collector.
Configuration Options
The following options can be configured under the agent section:
agent:
startup_fallback_configs:
- /path/to/fallback_config.yaml| Option | Description |
|---|---|
startup_fallback_configs |
List of paths to startup fallback configuration files to use. If more than one path is specified, they are merged in order. Together, these must form a complete, standalone Collector configuration. |
Important Notes
The startup fallback configuration is a set of standalone configuration files. It is intentionally not merged with the
agent::config_filessetting. This ensures predictable behavior without dependencies on other configuration files.The OpAMP extension and "own telemetry" configuration are automatically added to the fallback configuration. This maintains the Collector's own telemetry flowing and the communication between Supervisor and Collector.
The Supervisor will continue attempting to reconnect to the OpAMP server even while using the fallback configuration.
Example
See examples/supervisor_fallback.yaml for a complete example configuration with fallback enabled.
Automatic Remote Configuration Rollback
The Supervisor supports automatic rollback when a remote configuration received from
the OpAMP backend causes the Collector to fail to start correctly. This feature is
disabled by default and can be enabled in the Supervisor configuration file:
agent:
automatic_config_rollback: trueWhen enabled, the Supervisor will watch the health of the Collector after applying remote
configurations received from the OpAMP backend and it will cache the last working one in
disk, besides the last received. If a remote configurations causes the Collector
to fail to start correctly, the Supervisor will automatically swap to the last working one
and restart the Collector. During this process, a new "APPLIED" status will be reported for
the last working configuration.
Status
The OpenTelemetry OpAMP Supervisor is intended to be the reference
implementation of an OpAMP Supervisor, and as such will support all OpAMP
capabilities. Additionally, it follows a design document for the features it
intends to support.
For a list of open issues related to the Supervisor, see these issues.
Key:
β : Fully implemented
β οΈ: Implemented with caveats
OpAMP capabilities
| OpAMP capability | Status |
|---|---|
| AcceptsRemoteConfig | β |
| ReportsEffectiveConfig | β |
| AcceptsPackages | https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/47272 |
| ReportsPackageStatuses | https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/47272 |
| ReportsOwnTraces | β |
| ReportsOwnMetrics | β |
| ReportsOwnLogs | β |
| AcceptsOpAMPConnectionSettings | β |
| AcceptsOtherConnectionSettings | β |
| AcceptsRestartCommand | β |
| ReportsHealth | β οΈ |
| ReportsStatus | https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/38729 |
| ReportsRemoteConfig | β |
| ReportsAvailableComponents | β |
Supervisor specification features
| Feature | Status |
|---|---|
| Offers Supervisor configuration including configuring capabilities | β |
| Starts and stops a Collector using remote configuration | β |
| Communicates with OpAMP extension running in the Collector | β |
| Updates the Collector binary | https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/33947 |
| Configures the Collector to report it's own metrics over OTLP | β |
| Configures the Collector to report it's own logs over OTLP | β |
| Sanitization or restriction of Collector config | https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/24310 |
Overview (`cmd/telemetrygen/README.md`)
Telemetry generator for OpenTelemetry
| Status | |
|---|---|
| Stability | alpha: metrics, traces, logs |
| Issues | |
| Code Owners | @mx-psi, @codeboten, @Erog38, @bogdan-st |
This utility simulates a client generating traces, metrics, and logs. It is useful for testing and demonstration purposes.
Installing
To install the latest version run the following command:
go install github.com/open-telemetry/opentelemetry-collector-contrib/cmd/telemetrygen@latestCheck the go install reference to install specific versions.
Docker build
You can build locally the Docker image with:
make docker-telemetrygenUsing github actions, we also push a docker image on commit to main or on release to this Github docker registry.
Running
First, you'll need an OpenTelemetry Collector to receive the telemetry data. Follow the project's instructions for a detailed setting up guide. The following configuration file should be sufficient:
config.yaml:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
debug:
verbosity: detailed
service:
pipelines:
logs:
receivers: [otlp]
exporters: [debug]
metrics:
receivers: [otlp]
exporters: [debug]
traces:
receivers: [otlp]
exporters: [debug]Starting OpenTelemetry collector via docker:
docker run -p 4317:4317 -v $(pwd)/config.yaml:/etc/otelcol-contrib/config.yaml ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.149.0Other options for running the collector are documented here https://opentelemetry.io/docs/collector/getting-started/
Export timeout
The maximum time to wait for signals to reach the destination can be configured with the following flag:
--timeout=10s #Defaults to 10sBatching signals
All telemetry signals have batching capability configurable with the following flags:
--batch=false #Defaults to true, no flag needed for batching--batch-size=1000 #Defaults to 100Once the OpenTelemetry Collector instance is up and running, run telemetrygen for your desired telemetry:
Traces
telemetrygen traces --otlp-insecure --duration 5sOr, to generate a specific number of traces:
telemetrygen traces --otlp-insecure --traces 1Or, to generate traces continuously (use --duration inf with --rate for throttling):
telemetrygen traces --otlp-insecure --duration inf --rate 0.1To send traces in secure connection, see examples/secure-tracing
Check telemetrygen traces --help for all the options.
Logs
telemetrygen logs --otlp-insecure --duration 5sOr, to generate a specific number of logs:
telemetrygen logs --otlp-insecure --logs 1Or, to generate logs continuously:
telemetrygen logs --otlp-insecure --duration inf --rate 0.1To send logs in secure connection, see examples/secure-tracing
Check telemetrygen logs --help for all the options.
Metrics
telemetrygen metrics --otlp-insecure --duration 5sOr, to generate a specific number of metrics:
telemetrygen metrics --otlp-insecure --metrics 1Or, to generate metrics continuously:
telemetrygen metrics --otlp-insecure --duration inf --rate 0.1To send metrics in secure connection, see examples/secure-tracing
Check telemetrygen metrics --help for all the options.
Attributes
Custom attributes can be added at two different levels, using two different flags:
| Flag | Sets | Applied to |
|---|---|---|
--otlp-attributes |
Resource attributes | The OTLP resource, once per run. They describe the entity producing the telemetry and are shared by every span, metric data point and log record. |
--telemetry-attributes |
Span, metric data point and log record attributes | Each generated telemetry item individually. |
Because service.name is a resource attribute, --otlp-attributes service.name="my-service" overrides the --service flag.
Both flags accept the same value formats: key="value", key=true, key=false, key=, and key=["value1", "value2", ...] for slices. All items of a slice must have the same type. Both flags may be repeated to set multiple attributes.
String values must keep their double quotes when they reach telemetrygen, so escape them (or wrap the whole argument in single quotes) to prevent the shell from removing them:
telemetrygen traces --otlp-insecure --traces 1 \
--otlp-attributes service.name=\"my-service\" \
--otlp-attributes host.name=\"host-1\" \
--telemetry-attributes http.request.method=\"GET\" \
--telemetry-attributes http.response.status_code=200This generates a resource carrying service.name and host.name, and spans that each carry http.request.method and http.response.status_code.
Overview (`config/configdbauth/README.md`)
Database Authentication Configuration
This package provides the configuration for wiring a connection-oriented
component to a dbauth provider that supplies a credential at the moment the
component opens a connection β for example, a database receiver that needs a
username and password (or a short-lived token) to dial its database.
It is the configuration half of the db_auth framework. The provider
interface it resolves (Provider, Credential, Request) lives in a
separate, dependency-light module,extension/dbauth, so a provider extension can
implement the interface without taking on this package's confmap dependency
How a provider is declared and selected
A credential provider is a Collector extension that also implementsdbauth.Provider. It is declared once (and listed in service.extensions) with
its provider-wide configuration, then each component references it by component
ID inside its db_auth block β the value of the block is the provider's
component ID:
extensions:
aws_iam: # declared once, with provider-wide config
region: us-east-2
aws_iam/west: # a second instance for a different region
region: us-west-2
receivers:
postgresql/this:
endpoint: this-db:5432
username: monitor
db_auth: aws_iam # reference the extension by ID
postgresql/another:
endpoint: another-db:5432
username: reader
db_auth: aws_iam/west # reference a differently-configured instance
service:
extensions: [aws_iam, aws_iam/west]The extension holds all provider-wide configuration (here, the AWS region). To
vary that configuration across components, declare multiple extension instances
(aws_iam, aws_iam/west) and point each component at the one it needs. There
is no inline override in the db_auth block β the value is only a reference.
The per-connection inputs a provider needs β the endpoint to connect to, the
database user β are not configured on the extension or repeated in thedb_auth block. The consuming component already knows them (its ownendpoint and username) and passes them to the provider with eachGetCredential call as a dbauth.Request. So one declared extension serves many
components that differ only by endpoint/user, with no per-database extension
instance and nothing repeated.
This means:
- A provider is declared once per configuration (one extension instance in
the collector build); any receiver can reference it by ID, with no per-receiver
provider list to maintain, and new providers require no receiver code changes. - Databases that share provider config reference one instance; a database that
needs a different provider-wide value references a separate declared instance. - Resolution mirrors
config/configauth: the component finds the provider inhost.GetExtensions()atStart(), not via aninit()registry.
The credential and the request
The provider interface, Credential, and Request are defined inextension/dbauth:
type Provider interface {
GetCredential(ctx context.Context, req Request) (*Credential, error)
}
type Request struct {
Endpoint string // host:port the credential is for
Username string // the consumer's configured username
}
type Credential struct {
Username *string // nil: use the consumer's configured username
Secret string // opaque: a password or a minted token
NotAfter *time.Time // nil: no expiry applies; advisory only
}Request carries the per-connection inputs the consumer supplies on every call;
a provider uses the fields it needs (AWS IAM mints a token scoped to Endpoint
for Username) and ignores the rest. Provider-wide configuration (such as the
AWS region) lives on the extension's own config, not in the request.
The Credential carries credential material and nothing about how to apply
it β the consuming component decides where the secret goes (for a SQL driver,
usually the password slot of a connection string). The pointer fields are
load-bearing:
Username == nilmeans the provider supplies no username and the consumer
should fall back to its own configured username. A non-nil pointer (including a
pointer to the empty string) means the provider generated the username and the
consumer must use it. Dynamic providers such as Vault mint both a username and a
secret per lease, which is why this is a pointer rather than a plain string.NotAfter == nilmeans no expiry applies (a static password). When set, it is
an advisory hint for observability β the provider owns refresh-before-expiry, so
consumers need not act on it.
Genericity
The same Credential and the same Provider interface cover every connection
credential shape without an interface change. How each maps onto the struct:
| Provider | Username |
Secret |
NotAfter |
|---|---|---|---|
| Static (inline / file) | from config/file | the password | nil |
| AWS IAM (RDS/Aurora) | nil |
minted RDS auth token | now + ~15m |
| Azure Managed Identity | nil |
minted access token | token expiry |
| GCP Cloud SQL IAM | nil |
minted access token | token expiry |
| Vault dynamic creds | minted (non-nil) | minted password | lease expiry |
Overview (`connector/countconnector/README.md`)
Count Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @akats7 | Seeking more code owners! |
| Emeritus | @djaglowski, @jpkrohling |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
| metrics | metrics | alpha |
| logs | metrics | alpha |
| profiles | metrics | alpha |
The count connector can be used to count spans, span events, metrics, data points, and log records.
Configuration
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
Default Configuration
The count connector may be used without any configuration settings. The following table describes the
default behavior of the connector.
| Exporter Pipeline Type | Description | Default Metric Names |
|---|---|---|
| traces | Counts all spans and span events. | trace.span.count, trace.span.event.count |
| metrics | Counts all metrics and data points. | metric.count, metric.datapoint.count |
| logs | Counts all log records. | log.record.count |
For example, in the following configuration the connector will count spans and span events from the traces/in
pipeline and emit metrics called trace.span.count and trace.span.event.count onto the metrics/out pipeline.
receivers:
foo:
exporters:
bar:
connectors:
count:
service:
pipelines:
traces/in:
receivers: [foo]
exporters: [count]
metrics/out:
receivers: [count]
exporters: [bar]Custom Counts
Optionally, emit custom counts by defining metrics under one or more of the following sections:
spansspaneventsmetricsdatapointslogs
Optionally, specify a description for the metric.
Note: If any custom metrics are defined for a data type, the default metric will not be emitted.
Conditions
Conditions may be specified for custom metrics. If specified, data that matches any one
of the conditions will be counted. i.e. Conditions are ORed together.
receivers:
foo:
exporters:
bar:
connectors:
count:
spanevents:
my.prod.event.count:
description: The number of span events from my prod environment.
conditions:
- 'spanevent.attributes["env"] == "prod"'
- 'spanevent.name == "prodevent"'Attributes
spans, spanevents, datapoints, and logs may be counted according to attributes. In such cases, attribute precedence follows this order:
span(logRecord, DataPoint, profile) attributes > scope attributes > resource attributes.
If attributes are specified for custom metrics, a separate count will be generated for each unique
set of attribute values. Each count will be emitted as a data point on the same metric.
Optionally, include a default_value for an attribute, to count data that does not contain the attribute. The default_value value can be of type string, integer, or float.
receivers:
foo:
exporters:
bar:
connectors:
count:
logs:
my.log.count:
description: The number of logs from each environment.
attributes:
- key: env
default_value: unspecified_environmentExample Usage
Count spans and span events, only exporting the count metrics.
receivers:
foo:
exporters:
bar:
connectors:
count:
service:
pipelines:
traces:
receivers: [foo]
exporters: [count]
metrics:
receivers: [count]
exporters: [bar]Count spans and span events, exporting both the original traces and the count metrics.
receivers:
foo:
exporters:
bar/traces_backend:
bar/metrics_backend:
connectors:
count:
service:
pipelines:
traces:
receivers: [foo]
exporters: [bar/traces_backend, count]
metrics:
receivers: [count]
exporters: [bar/metrics_backend]Count spans, span events, metrics, data points, and log records, exporting count metrics to a separate backend.
receivers:
foo/traces:
foo/metrics:
foo/logs:
exporters:
bar/all_types:
bar/counts_only:
connectors:
count:
service:
pipelines:
traces:
receivers: [foo/traces]
exporters: [bar/all_types, count]
metrics:
receivers: [foo/metrics]
exporters: [bar/all_types, count]
logs:
receivers: [foo/logs]
exporters: [bar/all_types, count]
metrics/counts:
receivers: [count]
exporters: [bar/counts_only]Count logs with a severity of ERROR or higher.
receivers:
foo:
exporters:
bar:
connectors:
count:
logs:
my.error.log.count:
description: Error+ logs.
conditions:
- `severity_number >= SEVERITY_NUMBER_ERROR`
service:
pipelines:
logs:
receivers: [foo]
exporters: [count]
metrics:
receivers: [count]
exporters: [bar]Count logs with a severity of ERROR or higher. Maintain a separate count for each environment.
receivers:
foo:
exporters:
bar:
connectors:
count:
logs:
my.error.log.count:
description: Error+ logs.
conditions:
- `severity_number >= SEVERITY_NUMBER_ERROR`
attributes:
- key: env
service:
pipelines:
logs:
receivers: [foo]
exporters: [count]
metrics:
receivers: [count]
exporters: [bar]Count all spans and span events (default behavior). Count metrics and data points based on the env attribute.
receivers:
foo/traces:
foo/metrics:
foo/logs:
exporters:
bar/all_types:
bar/counts_only:
connectors:
count:
metrics:
my.prod.metric.count:
conditions:
- `attributes["env"] == "prod"
my.test.metric.count:
conditions:
- `attributes["env"] == "test"
datapoints:
my.prod.datapoint.count:
conditions:
- `attributes["env"] == "prod"
my.test.datapoint.count:
conditions:
- `attributes["env"] == "test"
service:
pipelines:
traces:
receivers: [foo/traces]
exporters: [bar/all_types, count]
metrics:
receivers: [foo/metrics]
exporters: [bar/all_types, count]
metrics/counts:
receivers: [count]
exporters: [bar/counts_only]Overview (`connector/datadogconnector/README.md`)
Datadog Connector
| Status | |
|---|---|
| Unsupported Platforms | aix, solaris |
| Distributions | contrib |
| Warnings | Statefulness |
| Issues | |
| Code coverage | |
| Code Owners | @mx-psi, @dineshg13, @jade-guiton-dd, @IbraheemA |
| Emeritus | @gbbr, @ankitpatel96 |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | beta |
| traces | traces | beta |
Description
The Datadog Connector is a connector component that derives APM statistics, in the form of metrics, from service traces, for display in the Datadog APMβ―product. This component is required for trace-emitting services and their statistics to appear in Datadog APM.
The Datadog connector can also forward the traces passed into it into another trace pipeline. Notably, if you plan to sample your traces with the tailsamplingprocessor or the probabilisticsamplerprocessor, you should place the Datadog connector upstream to ensure that the metrics are computed before sampling, ensuring their accuracy. An example is given below.
Usage
# ...
processors:
# ...
probabilistic_sampler:
sampling_percentage: 20
connectors:
# add the "datadog" connector definition and further configurations
datadog/connector:
exporters:
datadog:
api:
key: ${env:DD_API_KEY}
sending_queue:
batch:
service:
pipelines:
traces:
receivers: [otlp]
exporters: [datadog/connector]
traces/2: # this pipeline uses sampling
receivers: [datadog/connector]
processors: [probabilistic_sampler]
exporters: [datadog]
metrics:
receivers: [datadog/connector]
exporters: [datadog]In this example configuration, incoming traces are received through OTLP, and processed by the Datadog connector in the traces pipeline. The traces are then forwarded to the traces/2 pipeline, where a sample of them is exported to Datadog. In parallel, the APM stats computed from the full stream of traces are sent to the metrics pipeline, where they are exported to Datadog as well.
Configurations
/* Detailed source-code truncated for AI context efficiency. */Warnings
- Statefulness: The
datadogconnector aggregates trace metrics into buckets defined bybucket_intervalbefore flushing them, keeping this aggregation state in memory on a single collector instance. All spans that should be aggregated together must be routed to the same collector instance, or the resulting trace metrics will be incomplete or inconsistent.
Overview (`connector/exceptionsconnector/README.md`)
Exceptions Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @marctc |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
| traces | logs | alpha |
| logs | logs | alpha |
| logs | metrics | alpha |
Overview
Generate metrics and logs from recorded application exceptions associated with spans.
Each metric and log will have at least the following dimensions:
- Service name
- Span name
- Span kind
- Status code
With the provided default config, each metric and log will also have the following dimensions:
- Exception message
- Exception type
Each log will additionally have the following attributes:
- Exception stacktrace
- Span attributes. If you want to filter out some attributes (like only copying HTTP attributes starting with
http.) use the transform processor.
Configurations
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
The following settings can be optionally configured:
dimensions: the list of dimensions to add together with the default dimensions defined above.Each additional dimension is defined with a
namewhich is looked up in the span's collection of attributes or resource attributes.The provided default config includes
exception.typeandexception.messageas additional dimensions.exemplars: Use to configure how to attach exemplars to metrics.enabled(default:false): enabling will add spans as Exemplars.
Examples
The following is a simple example usage of the exceptions connector.
receivers:
nop:
exporters:
nop:
connectors:
exceptions:
service:
pipelines:
traces:
receivers: [nop]
exporters: [exceptions]
metrics:
receivers: [exceptions]
exporters: [nop]
logs:
receivers: [exceptions]
exporters: [nop]The following is a more complex example usage of the exceptions connector using Prometheus and Loki as exporters.
receivers:
otlp:
protocols:
grpc:
http:
exporters:
prometheus_remote_write:
endpoint: http://prometheus:9090/api/v1/write
loki:
endpoint: http://loki:3100/loki/api/v1/push
connectors:
exceptions:
service:
pipelines:
traces:
receivers: [otlp]
exporters: [exceptions]
metrics:
receivers: [exceptions]
exporters: [prometheus_remote_write]
logs:
receivers: [exceptions]
exporters: [loki]The full list of settings exposed for this connector are documented in exceptionsconnector/config.go.
More Examples
For more example configuration covering various other use cases, please visit the testdata directory.
Overview (`connector/failoverconnector/README.md`)
Failover Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @akats7, @khushijain21 |
| Emeritus | @fatsheep9146 |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | traces | alpha |
| metrics | metrics | alpha |
| logs | logs | alpha |
Allows for health based routing between trace, metric, and log pipelines depending on the health of target downstream exporters.
Configuration
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
The following settings are available:
priority_levels (required): list of pipeline level priorities in a 1 - n configuration, multiple pipelines can sit at a single priority level.retry_interval (optional): the frequency at which the pipeline levels will attempt to reestablish connection with all higher priority levels. Default value is 10 minutes. (See Example below for further explanation)sending_queue (optional): queues and batches data in the connector before it is routed to a priority level. Supports the commonsending_queuesettings and is enabled by default.
We recommend configuring the queue here instead of on the exporters in the priority pipelines, and disablingsending_queueon those exporters.
Moving the queue to the connector avoids data being stuck in the queue of an unhealthy exporter, where it cannot be failed over to another priority level.condition: Conditional statements that decide when the connector should failover. Currently supports below typeserror:contains: ["network failure", "connection refused"] (required list of non-empty, case-insensitive substrings)
Only errors whose message contains any configured string trigger failover. Non-matching errors are returned
to the upstream caller without failing over, and they do not mark the pipeline level unhealthy during
retry sampling either. Whenconditionis omitted, all errors trigger failover.
The connector intakes a list of priority_levels each of which can contain multiple pipelines.
If any pipeline at a stable level fails, the level is considered unhealthy and the connector will move down one priority level and route all data to the new level (assuming it is stable).
The connector will periodically try to reestablish a stable connection with the higher priority levels. retry_interval will be the frequency at which the connector will try to iterate through all unhealthy higher priority levels.
Configuration Example:
connectors:
failover:
priority_levels:
- [traces/first, traces/also_first]
- [traces/second]
- [traces/third]
retry_interval: 10s
service:
pipelines:
traces:
receivers: [otlp]
exporters: [failover]
traces/first:
receivers: [failover]
exporters: [otlp_grpc/first]
traces/second:
receivers: [failover]
exporters: [otlp_grpc/second]
traces/third:
receivers: [failover]
exporters: [otlp_grpc/third]
traces/also_first:
receivers: [failover]
exporters: [otlp_grpc/fourth]Overview (`connector/grafanacloudconnector/README.md`)
Grafana Cloud Connector
| Status | |
|---|---|
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @rlankfo, @jcreixell |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
Deprecation Notice: The component type has been renamed from
grafanacloudtografana_cloud
to follow the OpenTelemetry snake_case naming convention.
The old namegrafanacloudstill works but is deprecated and will be removed in a future release.
Please update your configuration to usegrafana_cloud.
Overview
The Grafana Cloud Connector (grafanacloudconnector) is a connector component that can analyze telemetry in pipelines to generate usage metrics for the following Grafana Cloud products:
- Application Observability
Usage
connectors:
grafana_cloud/connector:
extensions:
basicauth/grafana_cloud:
client_auth:
username: "${env:GRAFANA_CLOUD_INSTANCE_ID}"
password: "${env:GRAFANA_CLOUD_API_KEY}"
exporters:
otlphttp/grafana_cloud:
endpoint: "${env:GRAFANA_CLOUD_OTLP_ENDPOINT}"
auth:
authenticator: basicauth/grafana_cloud
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlphttp/grafana_cloud, grafana_cloud/connector]
metrics:
receivers: [otlp, grafana_cloud/connector]
exporters: [otlphttp/grafana_cloud]In this example configuration, usage metrics for Grafana Cloud Application Observability are derived from incoming spans.
Configuration
connectors:
grafanacloud/connector:
## @param host_identifiers List of span attributes used to identify the host running the workloads.
## The first matching attribute is used.
# host_identifiers: ["k8s.node.name", "host.id", "k8s.node.uid"]
## @param metrics_flush_interval Interval at which host metrics are flushed.
## Valid values are between 15s and 5m.
# metrics_flush_interval: 60sExample configuration for the component
connectors:
grafana_cloud:
host_identifiers: ["mycompany.myHostAttribute", "k8s.node.name", "host.id", "k8s.node.uid"]
metrics_flush_interval: 60sThis connector will generate a host info metric based on the first host_identifiers resource attribute found on spans. The rest are skipped. Valid flush intervals are between 15s and 5m.
Overview (`connector/metricsaslogsconnector/README.md`)
Metrics as Logs Connector
| Status | |
|---|---|
| Distributions | [] |
| Issues | |
| Code coverage | |
| Code Owners | @atoulme |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| metrics | logs | development |
Deprecation Notice: The component type has been renamed from
metricsaslogstometrics_as_logs
to follow the OpenTelemetry snake_case naming convention.
The old namemetricsaslogsstill works but is deprecated and will be removed in a future release.
Please update your configuration to usemetrics_as_logs.
This connector converts OpenTelemetry metrics into logs, creating one log entry per metric data point. Each metric data point is transformed into a structured log record with configurable JSON body format.
Current Limitations
β οΈ Current implementation discards the following metric features:
- Metric exemplars
- Advanced metadata
These features may be added in future iterations.
Configuration
The following settings can be optionally configured:
include_resource_attributes(default =true): Whether to include resource attributes in the generated logsinclude_scope_info(default =true): Whether to include instrumentation scope information in the generated logs
Log Body Format
The connector always generates log bodies in the following JSON format:
{"metric_name": "$NAME", "value": "$VALUE"}Where:
$NAMEis the actual metric name$VALUEis the metric value (simple values for gauge/sum, complex JSON for histogram/summary)
Example Usage
Basic Configuration
connectors:
metrics_as_logs:
service:
pipelines:
logs:
receivers: [metrics_as_logs]
processors: []
exporters: [debug]
metrics:
receivers: [otlp]
processors: []
exporters: [metrics_as_logs]Advanced Configuration
connectors:
metrics_as_logs:
include_resource_attributes: false
include_scope_info: falseExample Metric Conversions
For a gauge metric cpu_usage with value 85.2:
{
"body": {"metric_name": "cpu_usage", "value": "85.2"},
"attributes": {
"metric.name": "cpu_usage",
"metric.type": "Gauge",
"metric.description": "CPU usage percentage",
"metric.unit": "%"
}
}For a histogram metric request_duration:
{
"body": {
"metric_name": "request_duration",
"value": "{\"count\":100,\"sum\":1.5,\"bucket_counts\":[10,50,40],\"explicit_bounds\":[0.1,0.5,1.0]}"
},
"attributes": {
"metric.name": "request_duration",
"metric.type": "Histogram",
"metric.description": "Request duration in seconds",
"metric.unit": "s",
"metric.aggregation_temporality": "Delta"
}
}Output Structure
Each metric data point is converted to a log record with:
- Body: Fixed JSON format:
{"metric_name": "$NAME", "value": "$VALUE"} - Timestamp: Metric data point timestamp
- Observed Timestamp: Metric data point start timestamp (if available)
- Attributes:
- Original metric data point attributes (labels)
metric.name: The metric namemetric.type: The metric type (Gauge, Sum, Histogram, etc.)metric.description: Metric description (if available)metric.unit: Metric unit (if available)- Additional type-specific attributes:
- For Sum metrics:
metric.is_monotonic,metric.aggregation_temporality - For Histogram/ExponentialHistogram:
metric.aggregation_temporality
- For Sum metrics:
- Resource attributes (if
include_resource_attributesis true) - Instrumentation scope information (if
include_scope_infois true)
Supported Metric Types
All OpenTelemetry metric types are supported:
- Gauge: Point-in-time measurements
- Sum: Cumulative or delta measurements
- Histogram: Distribution of measurements with buckets
- Exponential Histogram: Distribution with exponentially sized buckets
- Summary: Distribution with quantile values
Value Encoding
The value field in the JSON body contains:
- For simple metrics (Gauge, Sum): numeric value as string
- For complex metrics (Histogram, etc.): JSON-encoded object as string
All JSON special characters in metric names and values are properly escaped.
Overview (`connector/otlpjsonconnector/README.md`)
OTLP JSON Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @ChrsMark |
| Emeritus | @djaglowski |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| logs | metrics | alpha |
| logs | traces | alpha |
| logs | logs | alpha |
Deprecation Notice: The component type has been renamed from
otlpjsontootlp_json
to follow the OpenTelemetry snake_case naming convention.
The old nameotlpjsonstill works but is deprecated and will be removed in a future release.
Please update your configuration to useotlp_json.
Allows to extract otlpjson data from incoming Logs and specifically the Body field.
The data is written in
Protobuf JSON
encoding
using OpenTelemetry
protocol.
Configuration
Configuration Example:
receivers:
file_log:
include:
- /var/log/foo.log
exporters:
debug:
connectors:
# Deprecated (still works):
# otlpjson:
# New name:
otlp_json:
service:
pipelines:
logs/raw:
receivers: [file_log]
exporters: [otlpjson]
metrics/otlp:
receivers: [otlpjson]
exporters: [debug]
logs/otlp:
receivers: [otlpjson]
exporters: [debug]
traces/otlp:
receivers: [otlpjson]
exporters: [debug]Overview (`connector/roundrobinconnector/README.md`)
Round-Robin Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @bogdandrutu |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | traces | beta |
| metrics | metrics | beta |
| logs | logs | beta |
Deprecation Notice: The component type has been renamed from
roundrobintoround_robin
to follow the OpenTelemetry snake_case naming convention.
The old nameroundrobinstill works but is deprecated and will be removed in a future release.
Please update your configuration to useround_robin.
The round_robin connector can fork pipelines of the same type and equally split the load between them.
Configuration
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
The roundrobin connector does not have any configuration settings.
receivers:
otlp:
exporters:
prometheus_remote_write/1:
prometheus_remote_write/2:
connectors:
round_robin:Preprocess data, then export using multiple exporter instances to scale the throughput if the exporter
does not support scale well (e.g. prometheus_remote_write).
receivers:
otlp:
processors:
resource_detection:
exporters:
prometheus_remote_write/1:
prometheus_remote_write/2:
connectors:
round_robin:
service:
pipelines:
metrics:
receivers: [otlp]
processors: [resource_detection]
exporters: [round_robin]
metrics/1:
receivers: [round_robin]
exporters: [prometheus_remote_write/1]
metrics/2:
receivers: [round_robin]
exporters: [prometheus_remote_write/2]Overview (`connector/routingconnector/README.md`)
Routing Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @TylerHelmuth, @evan-bradley, @edmocosta, @bogdandrutu, @mwear | Seeking more code owners! |
| Emeritus | @jpkrohling |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | traces | alpha |
| metrics | metrics | alpha |
| logs | logs | alpha |
Routes logs, metrics or traces based on resource attributes to specific pipelines using OpenTelemetry Transformation Language (OTTL) statements as routing conditions.
Configuration
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
The following settings are available:
table (required): the routing table for this connector.table.condition: the routing condition provided as the OTTL condition. Required iftable.statementis not provided. Use context-qualified paths (e.g.,resource.attributes["key"],span.attributes["key"]) to automatically infer the context (see Context Inference).table.statement: the routing condition provided as the OTTL statement. Required iftable.conditionis not provided. Generallyconditionis preferred since it is more terse. May not be used with the deprecatedrequestcontext.table.context (optional): the OTTL Context in which the condition/statement will be evaluated. Deprecated:requestβ useotelcol.client.metadataorotelcol.grpc.metadatapaths instead (see Limitations). In most cases this field should be omitted; the context is inferred automatically from context-qualified paths. If specified, it takes precedence over inference.table.action (optional, default: move): determines what happens to the data when the routing condition is met. Valid values aremoveandcopy.move: Matched data is moved to the target pipeline(s) and removed from subsequent route evaluation. This is the default behavior.copy: Matched data is copied to the target pipeline(s) but remains available for evaluation by subsequent routes. This allows the same data to be routed to multiple pipelines.
table.pipelines (required): the list of pipelines to use when the routing condition is met.default_pipelines (optional): contains the list of pipelines to use when a record does not meet any of specified conditions.error_mode (optional): determines how errors returned from OTTL statements are handled. Valid values arepropagate,ignoreandsilent. Ifignoreorsilentis used and a statement's condition has an error then the payload will be routed to the default pipelines. Whensilentis used the error is not logged. If not supplied,ignoreis used.
Context Inference
The routing connector supports OTTL context inference, allowing you to write clearer and more maintainable routing conditions using context-qualified paths. This is the recommended approach for specifying routing conditions.
- condition: resource.attributes["env"] == "prod"
pipelines: [logs/prod]
- condition: span.attributes["http.method"] == "GET"
pipelines: [traces/http]
- condition: log.severity_text == "ERROR"
pipelines: [logs/errors]This approach makes it immediately clear which attributes you're accessing without needing a separate context field.
Supported contexts
| Context | Path prefix | Example |
|---|---|---|
| Resource | resource. |
resource.attributes["service.name"] |
| Span | span. |
span.attributes["http.method"] |
| Log | log. |
log.body, log.attributes["level"] |
| Metric | metric. |
metric.name |
| Datapoint | datapoint. |
datapoint.attributes["host"] |
| OtelCol | otelcol. |
otelcol.client.metadata["X-Tenant"][0], otelcol.grpc.metadata["x-tenant"][0] |
The otelcol.client.metadata and otelcol.grpc.metadata paths provide access to incoming HTTP and gRPC request metadata respectively, and are valid in all signal contexts.
Limitations
- Deprecated: The
requestcontext is deprecated. Useotelcol.client.metadata["key"](HTTP/client metadata) orotelcol.grpc.metadata["key"](gRPC metadata) paths instead. These are supported in all signal contexts. A warning is logged when therequestcontext is used. Therequestcontext only supports theconditionfield with a very limited grammar:request["key"] == "value"orrequest["key"] != "value". - When using context inference without an explicit
contextfield, the inferred context must be compatible with the pipeline signal type (e.g.,spancontext can only be used in traces pipelines).
Supported [OTTL] functions
Additional Settings
The full list of settings exposed for this connector are documented in config.go with detailed sample configuration files:
Examples
[!NOTE]
The examples below use context-qualified paths, which is the recommended configuration style. The explicitcontextfield is still supported for backward compatibility but is no longer the primary documentation style. See Context Inference for details.
Route logs based on tenant
receivers:
otlp:
exporters:
file/other:
path: ./other.log
file/acme:
path: ./acme.log
file/ecorp:
path: ./ecorp.log
connectors:
routing:
default_pipelines: [logs/other]
table:
- context: resource
condition: otelcol.client.metadata["X-Tenant"][0] == "acme"
pipelines: [logs/acme]
- context: resource
condition: otelcol.client.metadata["X-Tenant"][0] == "ecorp"
pipelines: [logs/ecorp]
service:
pipelines:
logs/in:
receivers: [otlp]
exporters: [routing]
logs/acme:
receivers: [routing]
exporters: [file/acme]
logs/ecorp:
receivers: [routing]
exporters: [file/ecorp]
logs/other:
receivers: [routing]
exporters: [file/other]Route logs based on region
receivers:
otlp:
exporters:
file/other:
path: ./other.log
file/east:
path: ./east.log
file/west:
path: ./west.log
connectors:
routing:
default_pipelines: [logs/other]
table:
- condition: log.attributes["region"] == "east"
pipelines: [logs/east]
- condition: log.attributes["region"] == "west"
pipelines: [logs/west]
service:
pipelines:
logs/in:
receivers: [otlp]
exporters: [routing]
logs/east:
receivers: [routing]
exporters: [file/east]
logs/west:
receivers: [routing]
exporters: [file/west]
logs/other:
receivers: [routing]
exporters: [file/other]Route low-severity logs to cheap storage, remainder by service name
receivers:
otlp:
exporters:
file/cheap:
path: ./cheap.log
file/service1:
path: ./service1-important.log
file/service2:
path: ./service2-important.log
connectors:
routing:
table:
- condition: log.severity_number < SEVERITY_NUMBER_ERROR
pipelines: [logs/cheap]
- condition: resource.attributes["service.name"] == "service1"
pipelines: [logs/service1]
- condition: resource.attributes["service.name"] == "service2"
pipelines: [logs/service2]
service:
pipelines:
logs/in:
receivers: [otlp]
exporters: [routing]
logs/cheap:
receivers: [routing]
exporters: [file/cheap]
logs/service1:
receivers: [routing]
exporters: [file/service1]
logs/service2:
receivers: [routing]
exporters: [file/service2]Route low-severity logs to cheap storage, remainder by tenant
receivers:
otlp:
exporters:
file/cheap:
path: ./cheap.log
file/acme:
path: ./acme.log
file/ecorp:
path: ./ecorp.log
connectors:
routing:
table:
- condition: log.severity_number < SEVERITY_NUMBER_ERROR
pipelines: [logs/cheap]
- context: resource
condition: otelcol.client.metadata["X-Tenant"][0] == "acme"
pipelines: [logs/acme]
- context: resource
condition: otelcol.client.metadata["X-Tenant"][0] == "ecorp"
pipelines: [logs/ecorp]
service:
pipelines:
logs/in:
receivers: [otlp]
exporters: [routing]
logs/cheap:
receivers: [routing]
exporters: [file/cheap]
logs/acme:
receivers: [routing]
exporters: [file/acme]
logs/ecorp:
receivers: [routing]
exporters: [file/ecorp]Route all logs to an archive, while also routing errors using `action: copy`
Conditions with no OTTL paths (such as the literal "true") cannot be inferred, so an explicit context field is required.
receivers:
otlp:
exporters:
file/archive:
path: ./archive.log
file/errors:
path: ./errors.log
file/other:
path: ./other.log
connectors:
routing:
default_pipelines: [logs/other]
table:
- context: resource
condition: "true"
action: copy
pipelines: [logs/archive]
- condition: log.severity_number >= SEVERITY_NUMBER_ERROR
pipelines: [logs/errors]
service:
pipelines:
logs/in:
receivers: [otlp]
exporters: [routing]
logs/archive:
receivers: [routing]
exporters: [file/archive]
logs/errors:
receivers: [routing]
exporters: [file/errors]
logs/other:
receivers: [routing]
exporters: [file/other]In this example:
- All logs are first copied to the archive pipeline (using
action: copy), which means the original data remains available for subsequent route evaluation. - Error logs are then moved to the errors pipeline (using the default
action: move). - Any remaining logs (non-errors) go to the default pipeline.
Route traces to multiple pipelines using `action: copy`
receivers:
otlp:
exporters:
file/prod:
path: ./prod.json
file/high-latency:
path: ./high-latency.json
file/other:
path: ./other.json
connectors:
routing:
default_pipelines: [traces/other]
table:
- condition: resource.attributes["env"] == "prod"
action: copy
pipelines: [traces/prod]
- condition: span.attributes["http.duration_ms"] > 1000
pipelines: [traces/high-latency]
service:
pipelines:
traces/in:
receivers: [otlp]
exporters: [routing]
traces/prod:
receivers: [routing]
exporters: [file/prod]
traces/high-latency:
receivers: [routing]
exporters: [file/high-latency]
traces/other:
receivers: [routing]
exporters: [file/other]In this example:
- Production traces are copied to the prod pipeline. Since
action: copyis used, the traces remain available for subsequent evaluation. - High-latency spans (>1000ms) are then moved to the high-latency pipeline. A production trace with high latency will appear in both the prod and high-latency pipelines.
- Remaining traces go to the default pipeline.
`match_once`
The match_once field was deprecated as of v0.116.0 and removed in v0.120.0.
The following examples demonstrate some strategies for migrating a configuration from match_once.
Example without `default_pipelines`
If not using default_pipelines, you may be able to split the router into multiple parallel routers.
In the following example, the "env" and "region" are not directly related.
routing:
match_once: false
table:
- condition: attributes["env"] == "prod"
pipelines: [ logs/prod ]
- condition: attributes["env"] == "dev"
pipelines: [ logs/dev ]
- condition: attributes["region"] == "east"
pipelines: [ logs/east ]
- condition: attributes["region"] == "west"
pipelines: [ logs/west ]
service:
pipelines:
logs/in::exporters: [routing]
logs/prod::receivers: [routing]
logs/dev::receivers: [routing]
logs/east::receivers: [routing]
logs/west::receivers: [routing]Therefore, the same behavior can be achieved using separate routers. Listing both routers in the pipeline configuration will
result in each receiving an independent handle to the data. The same data can then match routes in both routers.
routing/env:
table:
- condition: resource.attributes["env"] == "prod"
pipelines: [ logs/prod ]
- condition: resource.attributes["env"] == "dev"
pipelines: [ logs/dev ]
routing/region:
table:
- condition: resource.attributes["region"] == "east"
pipelines: [ logs/east ]
- condition: resource.attributes["region"] == "west"
pipelines: [ logs/west ]
service:
pipelines:
logs/in::exporters: [routing/env, routing/region]
logs/prod::receivers: [routing/env]
logs/dev::receivers: [routing/env]
logs/east::receivers: [routing/region]
logs/west::receivers: [routing/region]Example with `default_pipelines`
The following example demonstrates strategies for migrating from match_once: true while using default_pipelines.
routing:
match_once: true
default_pipelines: [ logs/default ]
table:
- condition: resource.attributes["env"] == "prod"
pipelines: [ logs/prod ]
- condition: resource.attributes["env"] == "dev"
pipelines: [ logs/dev ]
- condition: resource.attributes["region"] == "east"
pipelines: [ logs/east ]
- condition: resource.attributes["region"] == "west"
pipelines: [ logs/west ]
service:
pipelines:
logs/in::exporters: [routing]
logs/default::receivers: [routing]
logs/prod::receivers: [routing]
logs/dev::receivers: [routing]
logs/east::receivers: [routing]
logs/west::receivers: [routing]If the number of routes are limited, you may be able to articulate a route for each combination of conditions. This avoids the need to change any pipelines.
routing:
default_pipelines: [ logs/default ]
table:
- condition: resource.attributes["env"] == "prod" and resource.attributes["region"] == "east"
pipelines: [ logs/prod, logs/east ]
- condition: resource.attributes["env"] == "prod" and resource.attributes["region"] == "west"
pipelines: [ logs/prod, logs/west ]
- condition: resource.attributes["env"] == "dev" and resource.attributes["region"] == "east"
pipelines: [ logs/dev, logs/east ]
- condition: resource.attributes["env"] == "dev" and resource.attributes["region"] == "west"
pipelines: [ logs/dev, logs/west ]
service:
pipelines:
logs/in::exporters: [routing]
logs/default::receivers: [routing]
logs/prod::receivers: [routing]
logs/dev::receivers: [routing]
logs/east::receivers: [routing]
logs/west::receivers: [routing]A more general solution is to use a layered approach. In this design, the first layer is a single router that sorts data according to whether it matches
any route or no route. This allows the second layer to work without default_pipelines. The downside to this approach is that the set of conditions
in the first and second layers must be kept in sync.
# First layer separates logs that match no routes
routing:
default_pipelines: [ logs/default ]
table: # all routes forward to second layer
- condition: resource.attributes["env"] == "prod"
pipelines: [ logs/env, logs/region ]
- condition: resource.attributes["env"] == "dev"
pipelines: [ logs/env, logs/region ]
- condition: resource.attributes["region"] == "east"
pipelines: [ logs/env, logs/region ]
- condition: resource.attributes["region"] == "west"
pipelines: [ logs/env, logs/region ]
# Second layer routes logs based on environment and region
routing/env:
table:
- condition: resource.attributes["env"] == "prod"
pipelines: [ logs/prod ]
- condition: resource.attributes["env"] == "dev"
pipelines: [ logs/dev ]
routing/region:
table:
- condition: resource.attributes["region"] == "east"
pipelines: [ logs/east ]
- condition: resource.attributes["region"] == "west"
pipelines: [ logs/west ]
service:
pipelines:
logs/in::exporters: [routing]
logs/prod::receivers: [routing/env]
logs/dev::receivers: [routing/env]
logs/east::receivers: [routing/region]
logs/west::receivers: [routing/region]Overview (`connector/servicegraphconnector/README.md`)
Service Graph Connector
| Status | |
|---|---|
| Distributions | contrib, k8s |
| Warnings | Statefulness |
| Issues | |
| Code coverage | |
| Code Owners | @mapno, @JaredTan95 |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
Note: The component type has been renamed from
servicegraphtoservice_graph.
The old name still works but is deprecated and will be removed in a future release.
Please update your configuration to useservice_graph.
Overview
The service graphs connector builds a map representing the interrelationships between various services in a system.
The connector will analyse trace data and generate metrics describing the relationship between the services.
These metrics can be used by data visualization apps (e.g. Grafana) to draw a service graph.
Service graphs are useful for a number of use-cases:
- Infer the topology of a distributed system. As distributed systems grow, they become more complex. Service graphs can help you understand the structure of the system.
- Provide a high level overview of the health of your system.
Service graphs show error rates, latencies, among other relevant data. - Provide an historic view of a systemβs topology.
Distributed systems change very frequently,
and service graphs offer a way of seeing how these systems have evolved over time.
This component is based on Grafana Tempo's service graph processor.
How it works
Service graphs work by inspecting traces and looking for spans with parent-children relationship that represent a request.
The connector uses the OpenTelemetry semantic conventions to detect a myriad of requests.
It currently supports the following requests:
- A direct request between two services where the outgoing and the incoming span must have
span.kindclient and server respectively. - A request across a messaging system where the outgoing and the incoming span must have
span.kindproducer and consumer respectively. - A database request; in this case the connector looks for spans containing attributes
span.kind=client as well as db.name.
Every span that can be paired up to form a request is kept in an in-memory store,
until its corresponding pair span is received or the maximum waiting time has passed.
When either of these conditions are reached, the request is recorded and removed from the local store.
Each emitted metrics series have the client and server label corresponding with the service doing the request and the service receiving the request.
traces_service_graph_request_total{client="app", server="db", connection_type="database"} 20TLDR: The connector will try to find spans belonging to requests as seen from the client and the server and will create a metric representing an edge in the graph.
Metrics
The following metrics are emitted by the connector:
| Metric | Type | Labels | Description |
|---|---|---|---|
| traces_service_graph_request_total | Counter | client, server, connection_type | Total count of requests between two nodes |
| traces_service_graph_request_failed_total | Counter | client, server, connection_type | Total count of failed requests between two nodes |
| traces_service_graph_request_server | Histogram | client, server, connection_type | Number of seconds for a request between two nodes as seen from the server |
| traces_service_graph_request_client | Histogram | client, server, connection_type | Number of seconds for a request between two nodes as seen from the client |
| traces_service_graph_unpaired_spans_total | Counter | client, server, connection_type | Total count of unpaired spans |
| traces_service_graph_dropped_spans_total | Counter | client, server, connection_type | Total count of dropped spans |
Duration is measured both from the client and the server sides.
Possible values for connection_type: unset, messaging_system, or database.
Additional labels can be included using the dimensions configuration option. Those labels will have a prefix to mark where they originate (client or server span kinds).
The client_ prefix relates to the dimensions coming from spans with SPAN_KIND_CLIENT, and the server_ prefix relates to the
dimensions coming from spans with SPAN_KIND_SERVER.
Since the service graph connector has to process both sides of an edge,
it needs to process all spans of a trace to function properly.
If spans of a trace are spread out over multiple instances, spans are not paired up reliably.
A possible solution to this problem is using the load balancing exporter
in a layer on front of collector instances running this connector.
Visualization
Service graph metrics are natively supported by Grafana since v9.0.4.
To run it, configure a Tempo data source's 'Service Graphs' by linking to the Prometheus backend where metrics are being sent:
apiVersion: 1
datasources:
# Prometheus backend where metrics are sent
- name: Prometheus
type: prometheus
uid: prometheus
url: <prometheus-url>
jsonData:
httpMethod: GET
version: 1
- name: Tempo
type: tempo
uid: tempo
url: <tempo-url>
jsonData:
httpMethod: GET
serviceMap:
datasourceUid: 'prometheus'
version: 1Configuration
The following settings are required:
latency_histogram_buckets: the list of durations defining the latency histogram buckets. Make sure use eitherlatency_histogram_bucketsorexponential_histogram_max_size.- Default:
[2ms, 4ms, 6ms, 8ms, 10ms, 50ms, 100ms, 200ms, 400ms, 800ms, 1s, 1400ms, 2s, 5s, 10s, 15s]
- Default:
exponential_histogram_max_size: (no default) the maximum number of buckets per positive or negative number range.dimensions: the list of dimensions to add together with the default dimensions defined above.
The following settings can be optionally configured:
store: defines the config for the in-memory store used to find requests between services by pairing spans.ttl: TTL is the time to live for items in the store.- Default:
2s
- Default:
max_items: MaxItems is the maximum number of items to keep in the store.- Default:
1000
- Default:
cache_loop: the interval at which to clean the cache.- Default:
1m
- Default:
store_expiration_loop: the time to expire old entries from the store periodically.- Default:
2s
- Default:
virtual_node_peer_attributes: the list of attributes, ordered by priority, whose presence in a client span will result in the creation of a virtual server node. An empty list disables virtual node creation.- Default:
[peer.service.name, peer.service, db.name, db.namespace, db.system, db.system.name]
- Default:
virtual_node_extra_label: adds an extra labelvirtual_nodewith an optional value ofclientorserver, indicating which node is the uninstrumented one.- Default:
false
- Default:
metrics_flush_interval: the interval at which metrics are flushed to the exporter.- Default:
60s
- Default:
metrics_timestamp_offset: the offset to subtract from metric timestamps. If set to a positive duration, metric timestamps will be set to (current time - offset), effectively shifting metrics to appear as if they were generated in the past.- Default:
0
- Default:
database_name_attributes: the list of attribute names used to identify the database name from span attributes. The attributes are tried in order, selecting the first match.- Default:
[db.name, db.namespace]
- Default:
Example configurations
Sample with custom buckets and dimensions
receivers:
otlp:
protocols:
grpc:
connectors:
service_graph:
latency_histogram_buckets: [100ms, 250ms, 1s, 5s, 10s]
dimensions:
- dimension-1
- dimension-2
store:
ttl: 1s
max_items: 10
exporters:
prometheus/servicegraph:
endpoint: localhost:9090
namespace: servicegraph
service:
pipelines:
traces:
receivers: [otlp]
exporters: [service_graph]
metrics/servicegraph:
receivers: [service_graph]
exporters: [prometheus/servicegraph]Sample with options for uninstrumented services identification
receivers:
otlp:
protocols:
grpc:
connectors:
service_graph:
dimensions:
- db.system
- messaging.system
virtual_node_peer_attributes:
- db.name
- db.system
- messaging.system
- peer.service.name
virtual_node_extra_label: true
exporters:
prometheus/servicegraph:
endpoint: localhost:9090
namespace: servicegraph
service:
pipelines:
traces:
receivers: [otlp]
exporters: [service_graph]
metrics/servicegraph:
receivers: [service_graph]
exporters: [prometheus/servicegraph]Warnings
- Statefulness: The
service_graphconnector keeps every span that can be paired up to form a request in an in-memory store, periodically cleaned bycache_loop. All spans for a given request must be sent to the same collector instance, or the connector will be unable to pair them and the resulting service graph metrics will be incomplete.
Overview (`connector/signaltometricsconnector/README.md`)
Signal to Metrics Connector
Signal to metrics connector produces metrics from all signal types (traces, logs, or metrics).
| Status | |
|---|---|
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @ChrsMark, @lahsivjar |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
| logs | metrics | alpha |
| metrics | metrics | alpha |
| profiles | metrics | alpha |
Configuration
The component can produce metrics from spans, datapoints (for metrics), and logs.
At least one of the metrics for one signal type MUST be specified correctly for
the component to work.
All signal types can be configured to produce metrics with the same configuration
structure. For example, the below configuration will produce delta temporality counters
for counting number of events for each of the configured signals:
signal_to_metrics:
spans:
- name: span.count
description: Count of spans
sum:
value: Int(AdjustedCount()) # Count of total spans represented by each span
monotonic: true
datapoints:
- name: datapoint.count
description: Count of datapoints
sum:
value: "1" # increment by 1 for each datapoint
monotonic: true
logs:
- name: logrecord.count
description: Count of log records
sum:
value: "1" # increment by 1 for each log record
monotonic: true
profiles:
- name: profile.count
description: Count of profiles
sum:
value: "1" # increment by 1 for each profile
monotonic: truePath context prefixes in OTTL expressions
OTTL strings in conditions, value, count, and keys_expression may use
context path prefixes to disambiguate the target of a path.
Unprefixed paths continue to work. It is recommended to use the new syntax to avoid
future breaking changes.
Example (recommended):
signal_to_metrics:
spans:
- name: http.trace.span.duration
attributes:
- key: http.response.status_code
conditions:
- resource.attributes["service.name"] != nil
sum:
value: Int(Seconds(span.end_time - span.start_time))
monotonic: trueError Handling
The error_mode configuration option determines how the connector handles errors that occur while processing OTTL expressions:
error_mode(optional): Determines how errors returned from OTTL expressions are handled. Valid values arepropagate,ignore, andsilent.ignore(default): Errors are logged and the specific record that caused the error is skipped, but processing continues for the rest of the batch.propagate: Errors cause the entire batch to fail and be returned up the pipeline. This will result in the payload being dropped from the collector.silent: Errors are not logged and the specific record that caused the error is skipped, but processing continues for the rest of the batch.
Example with error handling:
signaltometrics:
error_mode: ignore # Log errors but continue processing other records
spans:
- name: span.count
description: Count of spans
sum:
value: Int(AdjustedCount())Metrics types
signal_to_metrics produces a variety of metric types by utilizing OTTL
to extract the relevant data for a metric type from the incoming data. The
component can produce the following metric types for each signal type:
The component does NOT perform any stateful or time based aggregations. The metric
types are aggregated for the payload sent in each Consume* call. The final metric
is then sent forward in the pipeline.
Sum
Sum metrics have the following configurations:
sum:
value: <ottl_value_expression>
monotonic: <bool>- [Required]
valuerepresents an OTTL expression to extract a value from the
incoming data. Only OTTL expressions that return a value are accepted. The
returned value determines the value type of thesummetric (intordouble).
OTTL converters
can be used to transform the data. - [Optional]
monotonicwhether the generated metric is monotonic. It defaults tofalse.
Gauge
Gauge metrics aggregate the last value of a signal and have the following configuration:
gauge:
value: <ottl_value_expression>- [Required]
valuerepresents an OTTL expression to extract a numeric value from
the signal. Only OTTL expressions that return a value are accepted. The returned
value determines the value type of thegaugemetric (intordouble).- For logs: Use e.g.
ExtractGrokPatternswith a single key selector (see below). - For other signals: Use a field such as
value_int,value_double, or a valid OTTL expression.
- For logs: Use e.g.
Examples:
Logs (with Grok pattern):
signal_to_metrics:
logs:
- name: logs.memory_mb
description: Extract memory_mb from log records
gauge:
value: ExtractGrokPatterns(body, "Memory usage %{NUMBER:memory_mb:int}MB")["memory_mb"]Traces:
signal_to_metrics:
spans:
- name: span.duration.gauge
description: Span duration as gauge
gauge:
value: Int(Seconds(end_time - start_time))Histogram
Histogram metrics have the following configurations:
histogram:
buckets: []float64
count: <ottl_value_expression>
value: <ottl_value_expression>[Optional]
bucketsrepresents the buckets to be used for the histogram.
If no buckets are configured then it defaults to:go[]float64{2, 4, 6, 8, 10, 50, 100, 200, 400, 800, 1000, 1400, 2000, 5000, 10_000, 15_000}[Optional]
countrepresents an OTTL expression to extract the count to be
recorded in the histogram from the incoming data. If no expression is provided
then it defaults to the count of the signal. OTTL converters
can be used to transform the data. For spans, a special converter adjusted count,
is provided to help calculate the span's adjusted count.[Required]
valuerepresents an OTTL expression to extract the value to be
recorded in the histogram from the incoming data. OTTL converters
can be used to transform the data.
Exponential Histogram
Exponential histogram metrics have the following configurations:
exponential_histogram:
max_size: <int64>
count: <ottl_value_expression>
value: <ottl_value_expression>- [Optional]
max_sizerepresents the maximum number of buckets per positive
or negative number range. Defaults to160. - [Optional]
countrepresents an OTTL expression to extract the count to be
recorded in the exponential histogram from the incoming data. If no expression
is provided then it defaults to the count of the signal. OTTL converters
can be used to transform the data. For spans, a special converter adjusted count,
is provided to help calculate the span's adjusted count. - [Required]
valuerepresents an OTTL expression to extract the value to be
recorded in the exponential histogram from the incoming data. OTTL converters
can be used to transform the data.
Attributes
The component can produce metrics categorized by the attributes (span attributes
for traces, datapoint attributes for datapoints, or log record attributes for logs)
from the incoming data by configuring attributes for the configured metrics.
If no attributes are configured then the metrics are produced without any attributes.
attributes:
- key: datapoint.foo
- key: datapoint.bar
default_value: bar
- key: datapoint.baz
optional: true
- keys_expression: otelcol.client.metadata["x-dynamic-attributes"]Each attribute entry must have exactly one of key or keys_expression set.
If attributes are specified then a separate metric will be generated for each unique
set of attribute values. There are four behaviors that can be configured for an
attribute:
- Without any extra parameters:
datapoint.fooin the above yaml is an example
of such configuration. In this configuration, only the signals which have the said
attribute are processed with the attribute's value as one of the attributes for
the output metric. If the attribute is missing then the signal is not processed. - With
default_value:datapoint.barin the above yaml is an example of such
configuration. In this configuration all the signals are processed irrespective
of the attribute being present or not in the input signal. The output metric
is categorized as per the incoming value of the attribute and an extra bucket
exists with the attribute set to the configured default value for all the signals
that were missing the configured attribute. - With
optionalset totrue:datapoint.bazin the above yaml is an example
of such configuration. If the attribute is configured withoptionaland present
in the incoming signal then it will be added directly to the output metric. If
it is absent then a new metric with missing attributes will be created. In addition,
theoptionalattribute will not impact the decision i.e. even if theoptional
attributes are not present in the incoming signal, the signal will be processed
and will produce a metric given all other non-optional attributes are present
or have a default value defined. - With
keys_expression: The OTTL value expression is evaluated at runtime and
must return a list of attribute keys (pcommon.Sliceor[]string). Each resolved
key is looked up in the signal's attributes and included in the output metric.
If the expression returnsnil(e.g. missing client metadata), it is treated as
an empty list. Expression evaluation errors are governed by theerror_mode
configuration. Theoptionalanddefault_valueoptions can be combined withkeys_expressionand apply to each resolved key.
Note that resource attributes are handled differently, check the resource attributes
section for more details on this. Think of attributes as conditional filters for
choosing which attributes should be included in the output metric whereasinclude_resource_attributes is an include list for customizing resource attributes
of the output metric.
Conditions
Conditions are an optional list of OTTL conditions that are evaluated on the incoming
data and are ORed together. For example:
signal_to_metrics:
datapoints:
- name: datapoint.bar.sum
description: Count total number of datapoints as per datapoint.bar attribute
conditions:
- resource.attributes["foo"] != nil
- resource.attributes["bar"] != nil
sum:
value: "1"The above configuration will produce sum metrics from datapoints with either foo
OR bar resource attribute defined.
Conditions can also be ANDed together, for example:
signal_to_metrics:
datapoints:
- name: gauge.to.exphistogram
conditions:
- metric.type == 1 AND resource.attributes["resource.foo"] != nil
exponential_histogram:
count: "1" # 1 count for each datapoint
value: Double(value_int) + value_double # handle both int and doubleThe above configuration produces exponential histogram from gauge metrics with resource
attributes resource.foo set.
Customizing resource attributes
The component allows customizing the resource attributes for the produced metrics
by specifying a list of attributes that should be included in the final metrics.
If no attributes are specified for include_resource_attributes then no filtering
is performed i.e. all resource attributes of the incoming data is considered.
include_resource_attributes:
- key: resource.foo # Include resource.foo attribute if present
- key: resource.bar # Always include resource.bar attribute, default to bar
default_value: bar
- key: resource.baz # Optional resource.baz attribute is added if present
optional: true
- keys_expression: otelcol.client.metadata["x-dynamic-resource-attributes"]Each entry must have exactly one of key or keys_expression set.
With the above configuration the produced metrics would have the following
resource attributes:
resource.foowill be present for the produced metrics if the incoming data also
has the attribute defined. If the attribute is missing in the incoming data the
output metric will be produced without the said attribute.resource.barwill always be present because of thedefault_value. If the incoming
data does not have a resource attribute with nameresource.barthen the configureddefault_valueofbarwill be used.resource.bazwill behave exactly same asresource.foo. Since resource attributes
are basically an include list, theoptionaloption is a no-op i.e. the resource
attributes withoptionalset totruebehaves identical to an attribute configured
withoutdefault_valueoroptional.- The
keys_expressionentry evaluates the OTTL value expression at runtime to
resolve a list of attribute keys. The expression must return a list of strings
(pcommon.Sliceor[]string). Each resolved key is looked up in the resource
attributes and included in the output metric. If the expression returnsnil
(e.g. missing client metadata), it is treated as an empty list. Expression
evaluation errors are governed by theerror_modeconfiguration. Theoptional
anddefault_valueoptions can be combined withkeys_expressionand apply to
each resolved key. OTTL expressions forinclude_resource_attributesshould
only reference resource-level paths (e.g.resource.attributes) or context-level
paths (e.g.otelcol.client.metadata), not signal-specific paths (e.g.attributes,span.*,log.*).
Single writer
Metrics data streams MUST obey single-writer
principle. However, since signal_to_metrics component produces metrics from all signal
types and also allows customizing the resource attributes, there is a possibility
of violating the single-writer principle. To keep the single-writer principle intact,
the component adds collector instance information as resource attributes. The following
resource attribute is added to each produced metric:
signal_to_metrics.service.instance.id: <service_instance_id_of_the_otel_collector>Custom OTTL functions
The component implements the following custom OTTL functions:
AdjustedCount: a converter capable of calculating adjusted count for a span.
Overview (`connector/slowsqlconnector/README.md`)
Slow SQL Connector
| Status | |
|---|---|
| Distributions | [] |
| Issues | |
| Code coverage | |
| Code Owners | @JaredTan95, @Frapschen |
| Emeritus | @atoulme |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | logs | development |
Deprecation Notice: The component type has been renamed from
slowsqltoslow_sql
to follow the OpenTelemetry snake_case naming convention.
The old nameslowsqlstill works but is deprecated and will be removed in a future release.
Please update your configuration to useslow_sql.
Overview
Generate logs from recorded slow database statement associated with spans.
Each log will have at least the following dimensions:
- Service name
- Span kind
- Span name
- Status code
- Trace ID
- Span ID
- Database System
- Database Statement
- Database Statement Duration
Each log will additionally have the following attributes:
- Span attributes. If you want to filter out some attributes (like only copying HTTP attributes starting with
http.) use the transform processor.
Configurations
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
The following settings can be optionally configured:
dimensions: the list of dimensions to add to logs with the default dimensions defined above.
Each additional dimension is defined with anamewhich is looked up in the span's collection of attributes or
resource attributes (AKA process tags) such asip,host.nameorregion.db_system:the list value of span attributedb.system, Filter specific db systems, define those database's statements need to be collected. ref: https://opentelemetry.io/docs/specs/semconv/attributes-registry/db/- Default:
[h2, mongodb, mssql, mysql, oracle, postgresql, mariadb]
- Default:
threshold: define a threshold and collect when thedb.statement, namely span duration, larger than this value.- Default:
500ms
- Default:
Examples
The following is a simple example usage of the slow sql connector.
receivers:
nop:
exporters:
nop:
connectors:
slow_sql:
threshold: 600ms
dimensions:
- name: k8s.namespace.name
- name: k8s.pod.name
service:
pipelines:
traces:
receivers: [nop]
exporters: [slow_sql]
logs:
receivers: [slow_sql]
exporters: [nop]The following is a more complex example usage of the slow_sql connector using Elasticsearch as exporters.
receivers:
otlp:
protocols:
grpc:
http:
exporters:
elasticsearch/slow_sql:
tls:
insecure: true
mapping:
mode: raw
endpoints:
- http://localhost:9200
user: elastic
password: elastic
connectors:
slow_sql:
threshold: 600ms
dimensions:
- name: k8s.namespace.name
- name: k8s.pod.name
service:
pipelines:
traces:
receivers: [otlp]
exporters: [slow_sql]
logs:
receivers: [slow_sql]
exporters: [elasticsearch/slow_sql]The full list of settings exposed for this connector is documented in slowsqlconnector/config.go.
More Examples
For more example configuration covering various other use cases, please visit the testdata directory.
Overview (`connector/spanmetricsconnector/README.md`)
Span Metrics Connector
| Status | |
|---|---|
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @portertech, @Frapschen, @iblancasa | Seeking more code owners! |
| Emeritus | @albertteoh |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
Deprecation Notice: The component type has been renamed from
spanmetricstospan_metrics
to follow the OpenTelemetry snake_case naming convention.
The old namespanmetricsstill works but is deprecated and will be removed in a future release.
Please update your configuration to usespan_metrics.
β οΈ Breaking Change Warning:
The default duration metrics unit will change from ms to s to adhere to the OpenTelemetry semantic conventions and a feature gate connector.spanmetrics.useSecondAsDefaultMetricsUnit is also added.
Currently, the feature gate is disabled by default, so the unit will remain ms. After one release cycle, the unit will switch to s and the feature gate will also be enabled by default.
Overview
Aggregates Request, Error and Duration (R.E.D) OpenTelemetry metrics from span data.
Request counts are computed as the number of spans seen per unique set of
dimensions, including Errors. Multiple metrics can be aggregated if, for instance,
a user wishes to view call counts just on service.name and span.name.
traces.span.metrics.calls{service.name="shipping",span.name="get_shipping/{shippingId}",span.kind="SERVER",status.code="Ok"}Error counts are computed from the Request counts which have an Error Status Code metric dimension.
traces.span.metrics.calls{service.name="shipping",span.name="get_shipping/{shippingId},span.kind="SERVER",status.code="Error"}Duration is computed from the difference between the span start and end times and inserted into the
relevant duration histogram time bucket for each unique set dimensions.
traces.span.metrics.duration{service.name="shipping",span.name="get_shipping/{shippingId}",span.kind="SERVER",status.code="Ok"}Each metric will have at least the following dimensions because they are common
across all spans:
service.namespan.namespan.kindstatus.code(orotel.status_codewhen thespanmetrics.statusCodeConvention.useOtelPrefixfeature gate is enabled)collector.instance.id
The collector.instance.id dimension is intended to add a unique UUID to all metrics, ensuring that the spanmetrics connector
does not violate the Single Writer Principle when spanmetrics is used in a multi-deployment model.
To disable, use exclude_dimensions setting:
connectors:
spanmetrics:
exclude_dimensions: ['collector.instance.id']Or, disable via the feature gate: --feature-gates=-connector.spanmetrics.includeCollectorInstanceID.
More detail, please see Known Limitation: the Single Writer Principle
Span to Metrics processor to Span to metrics connector
The spanmetrics connector replaces spanmetrics processor with multiple improvements
and breaking changes. It was done to bring the spanmetrics connector closer to the OpenTelemetry
specification and make the component agnostic to exporters logic. The spanmetrics processor
essentially was mixing the OTel with Prometheus conventions by using the OTel data model and
the Prometheus metric and attributes naming convention.
The following changes were done to the connector component.
Breaking changes:
- The
operationmetric attribute was renamed tospan.name. - The
latencyhistogram metric name was changed toduration. - The
_totalmetric prefix was dropped from generated metrics names. - The Prometheus-specific metrics labels sanitization was dropped.
Improvements:
- Added support for OTel exponential histograms for recording span duration measurements.
- Added support for the milliseconds and seconds histogram units.
- Added support for generating metrics resource scope attributes. The
spanmetricsconnector will
generate the number of metrics resource scopes that corresponds to the number of the spans resource
scopes meaning that more metrics are generated now. Previously,spanmetricsgenerated a single
metrics resource scope.
Configurations
If you are not already familiar with connectors, you may find it helpful to first
visit the Connectors README.
The following settings can be optionally configured:
histogram(default:explicit): Use to configure the type of histogram to record
calculated from spans duration measurements. Must be eitherexplicitorexponential.disable(default:false): Disable all histogram metrics.unit(default:ms): The time unit for recording duration measurements.
calculated from spans duration measurements. One of either:msors.dimensions: additional attributes to add as dimensions to thetraces.span.metrics.durationmetric,
which will be included on top of the common and configureddimensionsfor span attributes and resource attributes.explicit:buckets: the list of durations defining the duration histogram time buckets. Default
buckets:[2ms, 4ms, 6ms, 8ms, 10ms, 50ms, 100ms, 200ms, 400ms, 800ms, 1s, 1400ms, 2s, 5s, 10s, 15s]
exponential:max_size(default:160) the maximum number of buckets per positive or negative number range.
dimensions: the list of dimensions to add totraces.span.metrics.calls,traces.span.metrics.durationandtraces.span.metrics.eventmetrics with the default dimensions defined above.
Each list entry must set exactly one of:namewhich is looked up in the span's collection of attributes or resource attributes (AKA process tags) such asip,host.nameorregion.If the
named attribute is missing in the span, the optional provideddefaultis used.If no
defaultis provided, this dimension will be omitted from the metric.glob: a glob pattern with '.' treated as a separator. Every span or resource attribute whose key matches the pattern is emitted as its own dimension.
calls_dimensions: additional attributes to add as dimensions to thetraces.span.metrics.callsmetric,
which will be included on top of the common and configureddimensionsfor span attributes and resource attributes.exclude_dimensions: the list of dimensions to be excluded from the default set of dimensions. Use to exclude unneeded data from metrics.dimensions_cache_size: this setting is deprecated, please use aggregation_cardinality_limit instead.include_instrumentation_scope: a list of instrumentation scope names to include from the traces.resource_metrics_cache_size(default:1000): the size of the cache holding metrics for a service. This is mostly relevant for
cumulative temporality to avoid memory leaks and correct metric timestamp resets.aggregation_temporality(default:AGGREGATION_TEMPORALITY_CUMULATIVE): Defines the aggregation temporality of the generated metrics.
One of eitherAGGREGATION_TEMPORALITY_CUMULATIVEorAGGREGATION_TEMPORALITY_DELTA.namespace(default:traces.span.metrics): Defines the namespace of the generated metrics. Ifnamespaceprovided, generated metric name will be addednamespace.prefix.metrics_flush_interval(default:60s): Defines the flush interval of the generated metrics.metrics_expiration(default:0): Defines the expiration time astime.Duration, after which, if no new spans are received, metrics will no longer be exported. Setting to0means the metrics will never expire.series_expiration(default:0): Defines the expiration time astime.Durationfor individual metric series. When set, stale dimension combinations are removed on a later flush even if the parent metric and resource continue receiving other spans. Setting to0disables per-series expiration.metric_timestamp_cache_size(default1000): Only relevant for delta temporality span metrics. Controls the size of the cache used to keep track of a metric's TimestampUnixNano the last time it was flushed. When a metric is evicted from the cache, its next data point will indicate a "reset" in the series. Downstream components converting from delta to cumulative, likeprometheusexporter, may handle these resets by setting cumulative counters back to 0.exemplars: Use to configure how to attach exemplars to metrics.enabled(default:false): enabling will add spans as Exemplars to all metrics. Exemplars are only kept for one flush interval.rom the cache, its next data point will indicate a "reset" in the series. Downstream components converting from delta to cumulative, likeprometheusexporter, may handle these resets by setting cumulative counters back to 0.max_per_data_point(default:5): The maximum number of exemplars to attach to a single metric data point.
events: Use to configure the events metric.enabled: (default:false): enabling will add the events metric.dimensions: (mandatory ifenabled) the list of the span's event attributes to add as dimensions to thetraces.span.metrics.eventsmetric, which will be included on top of the common and configureddimensionsfor span attributes and resource attributes.
resource_metrics_key_attributes: Filter the resource attributes used to produce the resource metrics key map hash(It's only used to build the hash key, not copy the attributes to metrics resource attributes).
Use this in case changing resource attributes (e.g. process id) are breaking counter metrics.aggregation_cardinality_limit(default:0): Defines the maximum number of unique combinations of dimensions that will be tracked for metrics aggregation. When the limit is reached, additional unique combinations will be dropped but registered under a new entry withotel.metric.overflow="true". A value of0means no limit is applied.add_resource_attributes(default:false): Add the resource attributes to the resulting metrics. This option enables the old behavior before theconnector.spanmetrics.excludeResourceMetricsfeature gate was introduced. When set totrue, resource attributes will be included in the metrics even if the feature gate is enabled. See GitHub issue #42103 for more context.enable_metrics_sampling_method(default:false): When enabled, adds thesampling.methodattribute to metrics with value"extrapolated"(when the span has a valid tracestate sampling threshold) or"counted"(otherwise).
The feature gate connector.spanmetrics.legacyMetricNames (disabled by default) controls the connector to use legacy metric names.
Examples
The following is a simple example usage of the spanmetrics connector.
For configuration examples on other use cases, please refer to More Examples.
The full list of settings exposed for this connector are documented in spanmetricsconnector/config.go.
receivers:
nop:
exporters:
nop:
connectors:
span_metrics:
histogram:
dimensions:
- name: url.scheme
default: https
explicit:
buckets: [100us, 1ms, 2ms, 6ms, 10ms, 100ms, 250ms]
dimensions:
- name: http.method
default: GET
- name: http.status_code
- glob: "k8s.*.name" # match single namespace between 'k8s' and 'name' ('k8s.cluster.name', not 'k8s.cluster.label.name')
- glob: "db.**.name" # match any number of namespaces between 'db' and 'name'
calls_dimensions:
- name: http.url
default: /ping
exemplars:
enabled: true
exclude_dimensions: ['status.code']
aggregation_temporality: "AGGREGATION_TEMPORALITY_CUMULATIVE"
metrics_flush_interval: 15s
metrics_expiration: 5m
series_expiration: 5m
events:
enabled: true
dimensions:
- name: exception.type
- name: exception.message
resource_metrics_key_attributes:
- service.name
- telemetry.sdk.language
- telemetry.sdk.name
include_instrumentation_scope:
- express
service:
pipelines:
traces:
receivers: [nop]
exporters: [span_metrics]
metrics:
receivers: [span_metrics]
exporters: [nop]Using `spanmetrics` with Prometheus components
The spanmetrics connector can be used with Prometheus exporter components.
For some functionality of the exporters, e.g. like generation of the target_info metric the
incoming spans resource scope attributes must contain service.name and service.instance.id
attributes.
Let's look at the example of using the spanmetrics connector with the prometheus_remote_write exporter:
receivers:
otlp:
protocols:
http:
grpc:
exporters:
prometheus_remote_write:
endpoint: http://localhost:9090/api/v1/write
target_info:
enabled: true
connectors:
span_metrics:
namespace: span.metrics
service:
pipelines:
traces:
receivers: [otlp]
exporters: [span_metrics]
metrics:
receivers: [span_metrics]
exporters: [prometheus_remote_write]This configures the spanmetrics connector to generate metrics from received spans and export the
metrics to the Prometheus Remote Write exporter. The target_info metric will be generated for each
resource scope, while OpenTelemetry metric names and attributes will be normalized
to be compliant with Prometheus naming rules. For example, the generated calls OTel sum metric can
result in multiple Prometheus calls_total (counter type) time series and the target_info time series.
For example:
target_info{job="shippingservice", instance="...", ...} 1
calls_total{span_name="/Address", service_name="shippingservice", span_kind="SPAN_KIND_SERVER", status_code="STATUS_CODE_UNSET", ...} 142More Examples
For more example configuration covering various other use cases, please visit the testdata directory.
Known Limitation: the Single Writer Principle
Proper configuration of the spanmetricsconnector ensures compliance with the Single Writer Principle,
which is a core requirement in the OpenTelemetry metrics data model. Misconfiguration, however,
may allow multiple components to write to the same metric stream, resulting in data inconsistency,
metric conflicts, or the dropping of time series by metric backends.
Why this happens
This issue typically arises when:
- Multiple pipelines use the same instance of the
spanmetricsconnector - The connector is instantiated more than once without ensuring the resulting metric streams are distinct
- The
resource_metrics_key_attributesfield is not configured correctly or includes common/shared attributes across all instances
Recommendations
To reduce the risk of conflicting writes:
- Add
resource_metrics_key_attributesto your configuration.
connectors:
span_metrics:
resource_metrics_key_attributes:
- service.name
- telemetry.sdk.language
- telemetry.sdk.name- The feature gate
connector.spanmetrics.includeCollectorInstanceIDis enabled by default to produce uniquely identified metrics. - For exporters like Prometheus, which rely on the single writer assumption, use a dedicated pipeline with a single
spanmetricsconnectorinstance
More context is available in GitHub issue #21101.
About `resource_metrics_key_attributes`
The resource_metrics_key_attributes setting are used to build the key map that determines how metrics are grouped.
If this field is left empty, the connector will use all available attributes to compute the resource metric hash.
To avoid problems, be cautious when choosing which attributes to include.
Avoid attributes that:
- Change frequently β such as
request_id,timestamp, ortrace_id. These increase cardinality and create excessive metric streams. - Are shared across all sources β values like
true,default, orteam:backendoffer no uniqueness and can lead to multiple writers sharing the same stream. - Are optional or inconsistently applied β if an attribute is only present in some spans, this can fragment metric streams (e.g., one stream with the attribute and one without).
Instead, use attributes that are stable, present in all spans, and meaningfully distinguish each stream. Good examples include cluster_id, region, or deployment_environment.
Troubleshooting span metrics high cardinality
High cardinality issues in span metrics commonly manifest in APM dashboards as an excessive number of service operations with non-unique names. Examples include URIs with unique identifiers (e.g., GET /product/1YMWWN1N4O) or HTTP parameters with random values (e.g., GET /?_ga=GA1.2.569539246.1760114706). These patterns render operation lists difficult to interpret and ineffective for monitoring purposes.
This issue stems from violations of OpenTelemetry semantic conventions, which require span names to have low cardinality (e.g. HTTP span name specs).
Beyond degrading APM interfaces with numerous non-meaningful operation names, this problem leads to metric time series explosion, resulting in significant performance degradation and increased costs.
The span metrics connector provides an optional circuit breaker through the aggregation_cardinality_limit attribute (disabled by default) to mitigate cardinality explosion. While this feature addresses performance and cost concerns, it does not resolve the underlying issue of semantically meaningless operation names.
Fixing high cardinality span name issues
The ideal long-term solution is to modify the OpenTelemetry instrumentation code to comply with semantic conventions, preventing the generation of non-compliant high cardinality span names.
However, deploying updated instrumentation libraries can be time-consuming, often requiring an immediate interim solution to restore observability backend functionality.
Addressing high cardinality span names in the ingestion pipeline
An effective short-term solution is to implement a span sanitization layer within the observability ingestion pipeline. This can be achieved by using the OpenTelemetry Collector Transform Processor's set_semconv_span_name() function immediately before the Span Metrics Connector to enforce semantic conventions on span names.
Simple example OpenTelemetry Collector configuration to prevent span metrics cardinality explosion:
receivers:
otlp:
...
processors:
transform/sanitize_spans:
error_mode: ignore
trace_statements:
# Sanitize all span names to prevent span metrics cardinality explosion
# caused by non-compliant high cardinality span names
- set_semconv_span_name("1.37.0")
...
connectors:
span_metrics:
exporters:
otlp_http/observability-backend:
...
service:
pipelines:
traces:
receivers: [otlp]
processors: [transform/sanitize_spans, ...]
exporters: [otlp_http/observability-backend, span_metrics]
metrics:
receivers: [otlp, span_metrics]
processors: [...]
exporters: [otlp_http/observability-backend]
# ...Aggressive span name sanitization may be overly restrictive for instrumentations with incomplete resource attributes. For instance, HTTP service operations may be reduced to generic names like GET and POST when HTTP spans lack the http.route attribute. This information loss can impact the monitoring of critical business operations.
To preserve operation granularity, you can manually set the http.route attribute when detailed operation names are required. The missing http.route value can typically be derived through pattern matching on other span attributes such as http.target or url.full.
Example OpenTelemetry Collector configuration that prevents cardinality explosion
while preserving meaningful operation names on a service webshop/frontend:
/* Detailed source-code truncated for AI context efficiency. */Addressing high cardinality span names in the instrumentation code
The preferred long-term solution is to ensure span names and attributes comply with OpenTelemetry Semantic Conventions directly in the instrumentation code.
Custom web frameworks are a common source of high cardinality span names. While default OpenTelemetry instrumentation (e.g., Java Servlet) may assign generic span names like GET /my-web-fwk/*, your framework has access to more specific routing information. By overwriting span attributes in your framework code, you can create compliant, low-cardinality span names that preserve operational granularity.
Example: Custom Web Framework in Java
Consider a custom web framework that intercepts the generic route /my-web-fwk/* and dispatches requests like /my-web-fwk/product/123456ABCD or /my-web-fwk/user/john.doe.
The default Java Servlet instrumentation produces vague span names (GET /my-web-fwk/*), while directly using request URIs creates high cardinality (GET /my-web-fwk/product/123456ABCD).
The solution is to override span attributes with templated route patterns like /my-web-fwk/product/{productId} or /my-web-fwk/user/{userId}:
@WebServlet(urlPatterns = "/my-web-fwk/*")
public class MyWebFrameworkServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Default Servlet instrumentation sets vague span names: `GET /my-web-fwk/*` (and `http.route=/my-web-fwk/*`)
// Using the request URI directly would cause high cardinality and violate semantic conventions
// Instead, use the framework's low-cardinality routing information below
// Example routing logic
String uri = request.getRequestURI();
MyWebOperation myWebOperation = getWebOperation(uri);
// Fix span details to add details while complying with semantic conventions and maintaining low cardinality
String httpRoute = "/my-web-fwk/" + myWebOperation.getSubHttpRoute();
Span.current().setAttribute(HttpAttributes.HTTP_ROUTE, httpRoute);
Span.current().updateName(request.getMethod() + " " + httpRoute);
// execute the web operation
myWebOperation.execute(request, response);
}
...
}Overview (`connector/sumconnector/README.md`)
Sum Connector
| Status | |
|---|---|
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @greatestusername, @shalper2, @crobert-1 |
Supported Pipeline Types
| Exporter Pipeline Type | Receiver Pipeline Type | Stability Level |
|---|---|---|
| traces | metrics | alpha |
| metrics | metrics | alpha |
| logs | metrics | alpha |
The sum connector can be used to sum attribute values from spans, span events, metrics, data points, and log records.
Configuration
If you are not already familiar with connectors, you may find it helpful to first visit the Connectors README.
Basic configuration
This example configuration will sum numerical values found within the attribute attribute.with.numerical.value of any span telemetry routed to the connector. It will then output a metric time series with the name my.example.metric.name with those summed values.
Note: Values found within an attribute will be converted into a float regardless of their original type before being summed and output as a metric value. Non-convertible strings will be dropped and not included.
receivers:
foo:
connectors:
sum:
spans:
my.example.metric.name:
source_attribute: attribute.with.numerical.value
exporters:
bar:
service:
pipelines:
metrics/sum:
receivers: [sum]
exporters: [bar]
traces:
receivers: [foo]
exporters: [sum]Required Settings
The sum connector has three required configuration settings and numerous optional settings
- Telemetry type: Nested below the
sum:connector declaration. Declared asspans:in the Basic Example.- Can be any of
spans,spanevents,datapoints, orlogs. - For metrics use
datapoints - For traces use
spansorspanevents
- Can be any of
- Metric name: Nested below the telemetry type; this is the metric name the sum connector will output summed values to. Declared as
my.example.metric.namein the Basic Example source_attribute: A specific attribute to search for within the source telemetry being fed to the connector. This attribute is where the connector will look for numerical values to sum into the output metric value. Declared asattribute.with.numerical.valuein the Basic Example
Optional Settings
conditions: OTTL syntax can be used to provide conditions for processing incoming telemetry. Conditions are ORed together, so if any condition is met the attribute's value will be included in the resulting sum. Conditions support OTTL path context names (e.g.span.attributes["x"],resource.attributes["x"],log.attributes["x"],metric.name). Paths without an explicit context are interpreted in the context of the enclosing block. It is recommended to switch to the new syntax to avoid breaking changes in the future.attributes: Declaration of attributes to include. Any of these attributes found will generate a separate sum for each set of unique combination of attribute values and output as its own datapoint in the metric time series.key: (required forattributes) the attribute name to match againstdefault_value: (optional forattributes) a default value for the attribute when no matches are found. Thedefault_valuevalue can be of type string, integer, or float.
Detailed Example Configuration
This example declares that the sum connector is going to be ingesting logs and creating an output metric named checkout.total with numerical values found in the source_attribute total.payment.
It provides a condition to check that the attribute total.payment is not NULL. It also checks any incoming log telemetry for values present in the attribute payment.processor and creates a datapoint within the metric time series for each unique value. Any logs without values in payment.processor will be included in a datapoint with the default_value of unspecified_processor.
receivers:
foo:
connectors:
sum:
logs:
checkout.total:
source_attribute: total.payment
conditions:
- attributes["total.payment"] != "NULL"
attributes:
- key: payment.processor
default_value: unspecified_processor
exporters:
bar:
service:
pipelines:
metrics/sum:
receivers: [sum]
exporters: [bar]
logs:
receivers: [foo]
exporters: [sum]Note for Log to Metrics: If your logs contain all values in their body rather than in attributes (E.G. JSON payload) use a transform processor in your pipeline to upsert parsed key/value pairs (in this case from JSON) into attributes attached to the log.
processors:
transform/logs:
log_statements:
- context: log
statements:
- merge_maps(attributes, ParseJSON(body), "upsert")Overview (`examples/couchbase/README.md`)
Couchbase Example
This example shows how you can configure the collector to scrape a Couchbase server using its built-in Prometheus metrics exporter.
This example config retrieves a subset of metrics important for monitoring a Couchbase server, transforms them to follow OpenTelemetry conventions, then exports again to prometheus so that they may be easily viewed.
Running
First build the collector docker image by running the following command in the root of this repository:
make docker-otelcontribcolThen, start Couchbase, the collector, and a Prometheus server by running the following command in this directory:
docker-compose up -d --remove-orphans --build --force-recreateAfter Couchbase is running, you'll need to initialize Couchbase and create some buckets:
./scripts/setup.shYou should now be able to view metrics being scraped from the Couchbase instance every 5 seconds in Prometheus at http://localhost:9090 (all metrics are prefixed with couchbase_)
Once you are done with the example, you may shut it down:
docker-compose downOverview (`examples/fault-tolerant-logs-collection/README.md`)
Fault tolerant log collection example
File Log receiver's persistence can be covered by the usage of the following extensions:
- filestorage extension,
to ensure that Collector's restarts do not affect the log collection and offset tracking. - exporterhelper persistent-queue,
to ensure that Collector's restarts do not affect the delivery of the already collected logs.
A full configuration example is provided in example config
Overview (`examples/kubernetes/README.md`)
OpenTelemetry Collector Demo
This demo is a sample app to build the collector and exercise its kubernetes logs scraping functionality.
Build and Run
Kubernetes
Switch to this directory and run following command: kubectl apply -n <namespace> -f otel-collector.yaml
Include/Exclude Specific Logs
Kubernetes logs are being stored in /var/log/pods.
Path to container logs is constructed using following pattern:
/var/log/pods/<namespace>__/<container>/<restart_count>.log
You can use it to manage from which containers do you want to include and exclude logs.
For example, to include all logs from default namespace, you can use following configuration:
include:
- /var/log/pods/default_*/*/*.log
exclude: []Docker Compose
Two steps are required to build and run the demo:
- Build latest docker image in main repository directory
make docker-otelcontribcol - Switch to this directory and run
docker-compose up
Description
varlogpods contains example log files placed in kubernetes-like directory structure.
Each of the directory has different formatted logs in one of three formats (either CRI-O, CRI-Containerd or Docker).
This directory is mounted to standard location (/var/log/pods).
otel-collector-config is a configuration to autodetect and parse logs for all of three mentioned formats
Performance Tests
There are multiple tests for various configurations in testbed.
Following table shows result of example run:
| Test | Result | Duration | CPU Avg% | CPU Max% | RAM Avg MiB | RAM Max MiB | Sent Items | Received Items |
|---|---|---|---|---|---|---|---|---|
| Log10kDPS/OTLP | PASS | 15s | 10.4 | 11.0 | 68 | 94 | 150100 | 150100 |
| Log10kDPS/filelog | PASS | 15s | 7.8 | 8.7 | 65 | 93 | 150100 | 150100 |
| Log10kDPS/kubernetes_containers | PASS | 15s | 18.3 | 19.7 | 67 | 96 | 150100 | 150100 |
| Log10kDPS/kubernetes_containers_parser | PASS | 15s | 18.2 | 19.0 | 66 | 95 | 150100 | 150100 |
| Log10kDPS/k8s_CRI-Containerd | PASS | 15s | 15.4 | 16.3 | 66 | 95 | 150100 | 150100 |
| Log10kDPS/k8s_CRI-Containerd_no_attr_ops | PASS | 15s | 15.1 | 16.3 | 66 | 95 | 150100 | 150100 |
| Log10kDPS/CRI-Containerd | PASS | 15s | 11.1 | 13.0 | 65 | 93 | 150100 | 150100 |
ToDo
To cover kubernetes system logs, logs from journald should be supported as well.
Overview (`examples/logline-filtering/README.md`)
Filtering log messages based on content
File Log receiver provides support for filtering logs based on their content. This can be achieved by using
the filter operator,
configured with matching regular expressions.
With this happening at the collection point, a lot of resources at the destination backend
can be saved since no additional processing would need to take place.
A full configuration example on how to filter out logs that start with the INFO: pattern is
provided in the example config.
A full configuration example on how to only collect logs that start with the WARN: pattern is provided in
the example config
Overview (`examples/nomad/README.md`)
OpenTelemetry Collector Demo
This demo provides you with all you need to run the OpenTelemetry Collector on a local installation of HashiCorp Nomad using Traefik as your load balancer. It configures both both HTTP and gRPC endpoints on Traefik.
For a detailed, step-by-step tutorial on how to run the files included in this directory, check out Just-in-Time Nomad: Running the OpenTelemetry Collector on HashiCorp Nomad with HashiQube.
The tutorial includes instructions on how to set up a local Nomad environment using HashiQube (a fork of servian/hashiqube). It spins up a Vagrant VM running Nomad, Consul, Vault and Traefik. Detailed instructions can be found in the project readme.
Additional Resources
Check out the OpenTelemetry Collector Nomad Pack in the Nomad Pack Community Registry.
Overview (`examples/secure-tracing/README.md`)
Build A Secure Trace Collection Pipeline
Implementing robust security measures is essential for any tracing ingestion service and infrastructure. This is an illustrative example of a secure setup encompassing the following features for trace ingestion:
- Data Encryption with OTLP receiver supporting TLS. Transport Layer Security (TLS) is employed to encrypt traces in transit between the application and the OpenTelemetry (OTLP) endpoint, fortifying data security.
- Client Authentication via Envoy, a high-performance proxy.
Even though we can configure OTLP receiver with mTLS for client authentication, authorization is not supported by OpenTelemetry Collector. This is one of the reasons that we use Envoy for client authentication. It allows us to easily add authorization, ensuring that only authorized clients can submit traces to the ingestion service.
In this example, we also include a test via telementrygen: a tool provided from this repository for generating synthetic telemetry data, which helps verify the security features and overall functionality of the set up.
Data Encryption via TLS
The OpenTelemetry Collector has detailed documentation on how to configure TLS. In this example, we enable TLS for receivers which leverages server configuration.
Example
receivers:
otlp:
protocols:
grpc:
endpoint: mysite.local:55690
tls:
cert_file: server.crt
key_file: server.keyClient Authentication
Envoy sandbox for TLS is a good source for reference. A few elements in following configuration are good to call out,
require_client_certificateis set true- The
matcherundervalidation_contextexpects a client certificate withgroup-idas well astenat-idwhich provides more granular control.
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: true
common_tls_context:
# h2 If the listener is going to support both HTTP/2 and HTTP/1.1.
alpn_protocols: "h2"
tls_certificates:
- certificate_chain:
filename: "/etc/envoy.crt"
private_key:
filename: "/etc/envoy.key"
validation_context:
match_typed_subject_alt_names:
- san_type: URI
matcher:
Match tenant by two level info: group id and tenant-id.
exact: "aprn:trace-client:certmgr:::group-x:/ig/5003178/uv/tenant-a"
trusted_ca:
filename: "/etc/ca.crt"Setup Environment
Generate Certificates
To generate various self-signed certificates, including those for Envoy and the OpenTelemetry Collector receiver, as well as tracing client certificate, we utilize the widely renowned open-source tool OpenSSL, OpenSSL 3.1.0 14 was tested.
In the certs folder, you can find a set of .ext files which define the properties for a certificate. A MakeFile is provided to facilate the process.
$ cd certs
$ make clean && make allBring up services
We use docker compose to bring up Envoy and OpenTelemetry Collection Pipeline. Make sure the current folder is secure-tracing,
$ docker compose upFrom the console window, verify that Envoy and Collector are up and running. If you see error similar to following,
secure-tracing-otel-collector-1 | Error: cannot start pipelines: failed to load TLS config: failed to load TLS cert and key: read /etc/otel-collector.crt: is a directoryIt's most likely due to missing certificates. Follow the steps from section above to generate certificates.
Run test
Compile telemetrygen
From the root of this repository,
$ cd cmd/telemetrygen
$ go build .
$ cp telemetrygen ../../examples/secure-tracingSend a trace
From the root of this repository,
$ cd examples/secure-tracing
$ chmod +x telemetrygen
$ ./telemetrygen traces --traces 1 --otlp-endpoint 127.0.0.1:10000 --ca-cert 'certs/ca.crt' --mtls --client-cert 'certs/tracing-client.crt' --client-key 'certs/tracing-client.key'Verify traces are captured and sent to console running docker compose up, similar to following ...
secure-tracing-otel-collector-1 | -> service.name: Str(telemetrygen)
secure-tracing-otel-collector-1 | ScopeSpans #0
secure-tracing-otel-collector-1 | ScopeSpans SchemaURL:
secure-tracing-otel-collector-1 | InstrumentationScope telemetrygen
secure-tracing-otel-collector-1 | Span #0
secure-tracing-otel-collector-1 | Trace ID : 0fe7ca900fda938ce918f8b2d82d6ae9
secure-tracing-otel-collector-1 | Parent ID : 1011b3f973049923
secure-tracing-otel-collector-1 | ID : 65f3cfe524375dd4
secure-tracing-otel-collector-1 | Name : okey-dokey
secure-tracing-otel-collector-1 | Kind : Server
...
secure-tracing-otel-collector-1 | Attributes:
secure-tracing-otel-collector-1 | -> net.sock.peer.addr: Str(1.2.3.4)
secure-tracing-otel-collector-1 | -> peer.service: Str(telemetrygen-client)
...Shutdown Services
$ docker compose downOverview (`exporter/alertmanagerexporter/README.md`)
Alertmanager Exporter
| Status | |
|---|---|
| Stability | development: traces, logs |
| Distributions | [] |
| Issues | |
| Code coverage | |
| Code Owners | @sokoide, @mcube8 |
Exports OTEL Events (SpanEvent in Tracing added by AddEvent API and Log Records) as Alerts to Alertmanager back-end to notify Errors or Change events.
Supported pipeline types: traces, logs
Getting Started
The following settings are required:
endpoint: Alertmanager endpoint to send eventsseverity: Default severity for Alerts
The following settings are optional:
timeoutsending_queueandretry_on_failuresettings as provided by Exporter Helper.- HTTP settings
- TLS and mTLS settings
generator_urlis the source of the alerts to be used in Alertmanager's payload. The default value is "opentelemetry-collector", and can be set to the URL of the opentelemetry collector.severity_attributeis the SpanEvent or LogRecord Attribute name which can be used instead of default severity string in Alert payload.
e.g.: Ifseverity_attributeis set to "foo" and the SpanEvent or LogRecord has an attribute called foo, foo's attribute value will be used as the severity value for that particular Alert generated from the SpanEvent or LogRecord.api_versionis the API version of Alertmanager. By default the value is set to "v2" and can be overridden to "v1" if using an older version of Alertmanager.event_labelsis the list of Event or LogRecord Attributes that will be captured as Labels in the Alert payload if value exists.
Example config:
exporters:
alertmanager:
alertmanager/2:
endpoint: "https://a.new.alertmanager.target:9093"
severity: "debug"
severity_attribute: "foo"
api_version: "v2"
event_labels: ["foo", "bar"]
tls:
cert_file: /var/lib/mycert.pem
key_file: /var/lib/key.pem
timeout: 10s
sending_queue:
enabled: true
num_consumers: 2
queue_size: 10
retry_on_failure:
enabled: true
initial_interval: 10s
max_interval: 60s
max_elapsed_time: 10m
generator_url: "opentelemetry-collector"Overview (`exporter/alibabacloudlogserviceexporter/README.md`)
AlibabaCloud LogService Exporter
| Status | |
|---|---|
| Stability | beta: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @vyagh |
| Emeritus | @shabicheng, @kongluoxing, @qiansheng91 |
This exporter supports sending OpenTelemetry data to LogService.
Configuration options:
endpoint(required): LogService's Endpoint.project(required): LogService's Project Name.logstore(required): LogService's store Name. For metrics data, you should use metric store.access_key_id(optional): AlibabaCloud access key id.access_key_secret(optional): AlibabaCloud access key secret.security_token(optional): AlibabaCloud security token for STS credentials.ecs_ram_role(optional): set AlibabaCLoud ECS ram role if you are using ACK.token_file_path(optional): Set token file path if you are using ACK.
Example:
Simple Trace Data
receivers:
examplereceiver:
exporters:
alibabacloud_logservice:
endpoint: "cn-hangzhou.log.aliyuncs.com"
project: "demo-project"
logstore: "traces-store"
access_key_id: "access-key-id"
access_key_secret: "access-key-secret"
service:
pipelines:
traces:
receivers: [examplereceiver]
exporters: [alibabacloud_logservice]All Telemetry Data
If you are using OpenTelemetry Collector to collect different types of telemetry data, you should send to different LogService's store.
receivers:
examplereceiver:
exporters:
alibabacloud_logservice/logs:
endpoint: "cn-hangzhou.log.aliyuncs.com"
project: "demo-project"
logstore: "logs-store"
access_key_id: "access-key-id"
access_key_secret: "access-key-secret"
alibabacloud_logservice/metrics:
endpoint: "cn-hangzhou.log.aliyuncs.com"
project: "demo-project"
logstore: "metrics-store"
access_key_id: "access-key-id"
access_key_secret: "access-key-secret"
alibabacloud_logservice/traces:
endpoint: "cn-hangzhou.log.aliyuncs.com"
project: "demo-project"
logstore: "traces-store"
access_key_id: "access-key-id"
access_key_secret: "access-key-secret"
service:
pipelines:
traces:
receivers: [examplereceiver]
exporters: [alibabacloud_logservice/traces]
logs:
receivers: [examplereceiver]
exporters: [alibabacloud_logservice/logs]
metrics:
receivers: [examplereceiver]
exporters: [alibabacloud_logservice/metrics]Overview (`exporter/awscloudwatchlogsexporter/README.md`)
AWS CloudWatch Logs Exporter
| Status | |
|---|---|
| Stability | alpha: logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @yaten2302 | Seeking more code owners! |
| Emeritus | @bryan-aguilar, @boostchicken, @rapphil |
AWS CloudWatch Logs Exporter sends logs data to AWS CloudWatch Logs.
AWS credentials are retrieved from the default credential chain.
NOTE: OpenTelemetry Logging support is experimental, hence this exporter is subject to change.
Configuration
The following settings are required:
log_group_name: The group name of the CloudWatch Logs. If it does not exist it will be created automatically. It supports several placeholder names. One valid example is/aws/metrics/{ClusterName}. It will search for ClusterName (or aws.ecs.cluster.name) resource attribute in the metrics data and replace with the actual cluster name. If none of them are found in the resource attribute map, {ClusterName} will be replaced by undefined. Similar way, for the {TaskId}, it searches for TaskId (or aws.ecs.task.id) key in the resource attribute map. For {NodeName}, it searches for NodeName (or k8s.node.name)- List of valid placeholders:
{ClusterName}:aws.ecs.cluster.name{TaskId}:aws.ecs.task.id{NodeName}:k8s.node.name{PodName}:podork8s.pod.name{ServiceName}:service.name{ContainerInstanceId}:aws.ecs.container.instance.id{TaskDefinitionFamily}:aws.ecs.task.family{InstanceId}:service.instance.id{FaasName}:faas.name{FaasVersion}:faas.version
- List of valid placeholders:
log_stream_name: The stream name of the CloudWatch Logs. If it does not exist it will be created automatically. It supports the same placeholders aslog_group_name
The following settings can be optionally configured:
region: The AWS region where the log stream is in. Region must be specified if it is not already set in the default credential chain.endpoint: The CloudWatch Logs service endpoint which the requests are forwarded to. See the CloudWatch Logs endpoints for a list.log_retention: LogRetention is the option to set the log retention policy for only newly created CloudWatch Log Groups. Defaults to Never Expire if not specified or set to 0. Possible values for retention in days are 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653.tags: Tags is the option to set tags for the CloudWatch Log Group. If specified, please add at most 50 tags. Input is a string to string map like so: { 'key': 'value' }. Keys must be between 1-128 characters and follow the regex pattern:^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$(alphanumerics, whitespace, and _.:/=+-!). Values must be between 1-256 characters and follow the regex pattern:^([\p{L}\p{Z}\p{N}_.:/=+\-@]\*)$(alphanumerics, whitespace, and _.:/=+-!). Link to tagging restrictionsraw_log: Boolean default false. If set to true, only the log message will be exported to CloudWatch Logs. This needs to be set to true for EMF logs.max_event_payload_bytes: Per-event payload cap, in bytes, used to truncate oversized log events before they are sent to CloudWatch Logs. As of 2025-04-02 the CloudWatch Logs PutLogEvents API accepts events up to 1 MiB (1048576 bytes); the previous limit was 256 KiB. To preserve backwards compatibility this exporter still defaults to 256 KiB. Set this field to1048576(or any value up to that ceiling) to take advantage of the larger service limit. Allowed range: 41 to 1048576. A value of 0 (or omitted) means "use the package default (256 KiB)".role_arn: IAM role to upload logs to a different account.external_id: Shared identitier used when assuming an IAM role in an external AWS account. See AWS IAM Guidesending_queue: Parameters for the sending queue, where you can control parallelism and the size of the sending buffer. Obs.: this component will always have a sending queue enabled.num_consumers: Number of consumers that will consume from the sending queue. This parameter controls how many consumers will consume from the sending queue in parallel.queue_size: Maximum number of batches kept in memory before dropping; ignored if enabled is false
Examples
Simplest configuration:
exporters:
awscloudwatchlogs:
log_group_name: "testing-logs"
log_stream_name: "testing-integrations-stream"Example configuration for EMF logs:
exporters:
awscloudwatchlogs:
log_group_name: "testing-logs-emf"
log_stream_name: "testing-integrations-stream-emf"
raw_log: true
region: "us-east-1"
endpoint: "logs.us-east-1.amazonaws.com"
log_retention: 365
tags: { "sampleKey": "sampleValue" }Additional Notes
- If the log group and/or log stream are specified in an EMF log, that EMF log will be exported to that log group and/or log stream (i.e. ignores the log group and log stream defined in the configuration)
- The log group and log stream will also be created automatically if they do not already exist.
- Example of an EMF log with log group and log stream:
{
"_aws": {
"Timestamp": 1574109732004,
"LogGroupName": "Foo",
"LogStreamName": "Bar",
"CloudWatchMetrics": [
{
"Namespace": "MyApp",
"Dimensions": [["Operation"]],
"Metrics": [
{
"Name": "ProcessingLatency",
"Unit": "Milliseconds",
"StorageResolution": 60
}
]
}
]
},
"Operation": "Aggregator",
"ProcessingLatency": 100
}- Resource ARNs (Amazon Resource Name (ARN) of the AWS resource running the collector) are currently not supported with the CloudWatch Logs Exporter.
Overview (`exporter/awsemfexporter/README.md`)
AWS CloudWatch EMF Exporter
| Status | |
|---|---|
| Stability | beta: metrics |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @Aneurysm9, @mxiamxia |
| Emeritus | @shaochengwang, @bryan-aguilar |
This exporter converts OpenTelemetry metrics to
AWS CloudWatch Embedded Metric Format(EMF)
and then sends them directly to CloudWatch Logs using the
PutLogEvents API.
Data Conversion
Convert OpenTelemetry Int64DataPoints, DoubleDataPoints, SummaryDataPoints metrics datapoints into
CloudWatch EMF structured log formats and send it to CloudWatch. Logs and Metrics will be displayed in
CloudWatch console. NaN, Inf values are not supported by CloudWatch EMF and will be dropped by the exporter.
Exporter Configuration
The following exporter configuration parameters are supported.
| Name | Description | Default |
|---|---|---|
log_group_name |
Customized log group name which supports {ClusterName} and {TaskId} placeholders. One valid example is /aws/metrics/{ClusterName}. It will search for ClusterName (or aws.ecs.cluster.name) resource attribute in the metrics data and replace with the actual cluster name. If none of them are found in the resource attribute map, {ClusterName} will be replaced by undefined. Similar way, for the {TaskId}, it searches for TaskId (or aws.ecs.task.id) key in the resource attribute map. For {NodeName}, it searches for NodeName (or k8s.node.name) |
"/metrics/default" |
log_stream_name |
Customized log stream name which supports {TaskId}, {ClusterName}, {NodeName}, {ContainerInstanceId}, and {TaskDefinitionFamily} placeholders. One valid example is {TaskId}. It will search for TaskId (or aws.ecs.task.id) resource attribute in the metrics data and replace with the actual task id. If none of them are found in the resource attribute map, {TaskId} will be replaced by undefined. Similarly, for the {TaskDefinitionFamily}, it searches for TaskDefinitionFamily (or aws.ecs.task.family). For the {ClusterName}, it searches for ClusterName (or aws.ecs.cluster.name). For {NodeName}, it searches for NodeName (or k8s.node.name). For {ContainerInstanceId}, it searches for ContainerInstanceId (or aws.ecs.container.instance.id). (Note: ContainerInstanceId (or aws.ecs.container.instance.id) only works for AWS ECS EC2 launch type. |
"otel-stream" |
log_retention |
LogRetention is the option to set the log retention policy for only newly created CloudWatch Log Groups. Defaults to Never Expire if not specified or set to 0. Possible values for retention in days are 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 2192, 2557, 2922, 3288, or 3653. | "Never Expire" |
tags |
Tags is the option to set tags for the CloudWatch Log Group. If specified, please add at most 50 tags. Input is a string to string map like so: { 'key': 'value' }. Keys must be between 1-128 characters and follow the regex pattern: ^([\p{L}\p{Z}\p{N}_.:/=+\-@]+)$(alphanumerics, whitespace, and _.:/=+-!). Values must be between 1-256 characters and follow the regex pattern: ^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$(alphanumerics, whitespace, and _.:/=+-!). Link to tagging restrictions |
No tags set |
namespace |
Customized CloudWatch metrics namespace | "default" |
endpoint |
Optionally override the default CloudWatch service endpoint. | |
no_verify_ssl |
Enable or disable TLS certificate verification. | false |
proxy_address |
Upload Structured Logs to AWS CloudWatch through a proxy. | |
region |
Send Structured Logs to AWS CloudWatch in a specific region. If this field is not present in config, environment variable "AWS_REGION" can then be used to set region. | determined by metadata |
role_arn |
IAM role to upload segments to a different account. | |
external_id |
Shared identitier used when assuming an IAM role in an external AWS account. | |
max_retries |
Maximum number of retries before abandoning an attempt to post data. | 1 |
dimension_rollup_option |
DimensionRollupOption is the option for metrics dimension rollup. Three options are available: NoDimensionRollup, SingleDimensionRollupOnly and ZeroAndSingleDimensionRollup. The default value is ZeroAndSingleDimensionRollup. Enabling feature gate awsemf.nodimrollupdefault will set default to NoDimensionRollup. |
"ZeroAndSingleDimensionRollup" (Enable both zero dimension rollup and single dimension rollup) |
resource_to_telemetry_conversion |
"resource_to_telemetry_conversion" is the option for converting resource attributes to telemetry attributes. It has only one config option- enabled. For metrics, if enabled=true, all the resource attributes will be converted to metric labels by default. See Resource Attributes to Metric Labels section below for examples. |
enabled=false |
output_destination |
"output_destination" is an option to specify the EMFExporter output. Currently, two options are available. "cloudwatch" or "stdout" | cloudwatch |
detailed_metrics |
Retain detailed datapoint values in exported metrics (e.g instead of exporting a quantile as a statistical value, preserve the quantile's population) | false |
parse_json_encoded_attr_values |
List of attribute keys whose corresponding values are JSON-encoded strings and will be converted to JSON structures in emf logs. For example, the attribute string value "{\"x\":5,\"y\":6}" will be converted to a json object: {"x": 5, "y": 6} |
[ ] |
metric_declarations |
List of rules for filtering exported metrics and their dimensions. | [ ] |
metric_descriptors |
List of rules for inserting or updating metric descriptors. | [ ] |
retain_initial_value_of_delta_metric |
This option specifies how the first value of a metric is handled. AWS EMF expects metric values to only contain deltas to the previous value. In the default case the first received value is therefor not sent to AWS but only used as a baseline for follow up changes to this metric. This is fine for high throughput metrics with stable labels (e.g. requests{code=200}). In this case it does not matter if the first value of this metric is discarded. However when your metric describes infrequent events or events with high label cardinality, then the exporter in default configuration would still drop the first occurrence of this metric. With this configuration value set to true the first value of all metrics will instead be send to AWS. |
false |
metric_declaration
A metric_declaration section characterizes a rule to be used to set dimensions for exported metrics, filtered by the incoming metrics' labels and metric names.
| Name | Description | Default |
|---|---|---|
dimensions |
List of dimension sets to be exported. Dimension sets that include dimensions that are not labels are ignored. Use empty dimension set [] for metrics without labels. |
[[ ]] |
metric_name_selectors |
List of regex strings to filter metric names by. | |
label_matchers |
(Optional) list of label matching rules to filter metrics by their labels. This rule is applied to any metric that matches any of the label matchers. | [ ] |
label_matcher
A label_matcher section defines a matching rule against the labels of the incoming metric. Only metrics that match the rules will be used by the surrounding metric_declaration.
| Name | Description | Default |
|---|---|---|
label_names |
List of label names to filter by. Their corresponding values are concatenated using the separator and matched against the configured regular expression. | |
separator |
(Optional) separator placed between concatenated label values. | ";" |
regex |
Regex string to be matched against concatenated label values. |
metric_descriptor
A metric descriptor section allows the schema of a metric to be overwritten before sending out to the CloudWatch backend service. Currently, we only support unit override.
| Name | Description | Default |
|---|---|---|
metric_name |
The name of the metric to be overwritten. | |
unit |
The overwritten value of unit. The MetricDatum contains a full list of supported unit values. | |
overwrite |
true if the schema should be overwritten with the given specification, otherwise it will only be configured if empty. |
false |
AWS Credential Configuration
This exporter follows default credential resolution for the
aws-sdk-go.
Follow the guidelines for the
credential configuration.
Metric Attributes
By setting attributes on your metrics you can change how individual metrics are sent to CloudWatch. Attributes can be set in code or using components like the Attribute Processor.
The AWS EMF Exporter will interpret the following metric attributes to change how it publishes metrics to CloudWatch:
| Attribute Name | Description | Default |
|---|---|---|
aws.emf.storage_resolution |
This attribute should be set to an integer value of 1 or 60. When sending the metric value to CloudWatch use the specified storage resolution value. CloudWatch currently supports a storage resolution of 1 or 60 to indicate 1 second or 60 second resolution. |
aws.emf.storage_resolution = 60 |
Configuration Examples
Resource Attributes to Metric Labels
The resource_to_telemetry_conversion option can be used to convert resource attributes to metric labels. By default, this option is disabled.
You can specify included and excluded wildcard pattern lists to match attribute keys.
Legacy options enabled and exclude_service_attributes are deprecated (and can be disabled via the exporter.awsemf.DisableLegacyResourceToTelemetryConversion feature gate). When migrating from enabled: true, the equivalent configuration is setting included: ["*"]. See the config example below:
exporters:
awsemf:
region: 'us-west-2'
resource_to_telemetry_conversion:
included:
- "*"Metric Declaration
The following is an example of how to use metric_declaration to select what metrics should be exported.
exporters:
awsemf:
region: 'us-west-2'
output_destination: stdout
dimension_rollup_option: "NoDimensionRollup"
metric_declarations:
- dimensions: [[]]
metric_name_selectors:
# Metric without label
- "^node_load15$"
- dimensions: [[device, fstype], []]
metric_name_selectors:
- "^node_filesystem_readonly$"Overview (`exporter/awskinesisexporter/README.md`)
AWS Kinesis Exporter
| Status | |
|---|---|
| Stability | beta: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @Aneurysm9, @MovieStoreGuy |
The kinesis exporter currently exports dynamic encodings to the configured kinesis stream.
The exporter relies heavily on the kinesis.PutRecords api to reduce network I/O and reduces records into smallest atomic representation
to avoid hitting the hard limits placed on Records (No greater than 1Mb).
This producer will block until the operation is done to allow for retryable and queued data to help during high loads.
The following settings are required:
awsstream_name(no default): The name of the Kinesis stream to export to.
The following settings can be optionally configured:
awskinesis_endpoint(no default)region(default = us-west-2): the region that the kinesis stream is deployed inrole(no default): The role to be used in order to send data to the kinesis stream
encodingname(default = otlp): defines the export type to be used to send to kinesis (available isotlp_proto,otlp_json,zipkin_proto,zipkin_json,jaeger_proto)- Note :
otlp_jsonis considered experimental and should not be used for production environments.
- Note :
compression(default = none): allows to set the compression type (defaults BestSpeed for all) before forwarding to kinesis (available isflate,gzip,zlibornone)
max_records_per_batch(default = 500, PutRecords limit): The number of records that can be batched together then sent to kinesis.max_record_size(default = 1Mb, PutRecord(s) limit on record size): The max allowed size that can be exported to kinesistimeout(default = 5s): Is the timeout for every attempt to send data to the backend.retry_on_failureenabled(default = true)initial_interval(default = 5s): Time to wait after the first failure before retrying; ignored ifenabledisfalsemax_interval(default = 30s): Is the upper bound on backoff; ignored ifenabledisfalsemax_elapsed_time(default = 120s): Is the maximum amount of time spent trying to send a batch; ignored ifenabledisfalse
sending_queueenabled(default = true)num_consumers(default = 10): Number of consumers that dequeue batches; ignored ifenabledisfalsequeue_size(default = 1000): Maximum number of batches kept in memory before dropping data; ignored ifenabledisfalse;
User should calculate this asnum_seconds * requests_per_secondwhere:num_secondsis the number of seconds to buffer in case of a backend outagerequests_per_secondis the average number of requests per seconds.
Example Configuration:
exporters:
awskinesis:
aws:
stream_name: raw-trace-stream
region: us-east-1
role: arn:test-roleOverview (`exporter/awss3exporter/README.md`)
AWS S3 Exporter
| Status | |
|---|---|
| Stability | alpha: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @atoulme, @pdelewski, @Erog38 |
Schema supported
This exporter targets to support proto/json format.
Exporter Configuration
The following exporter configuration parameters are supported.
| Name | Description | Default |
|---|---|---|
region |
AWS region. | "us-east-1" |
s3_bucket |
S3 bucket | |
s3_base_prefix |
root prefix for the S3 key applied to all files. | |
s3_prefix |
prefix for the S3 key that can be overridden dynamically by resource_attrs_to_s3 parameter. |
|
s3_partition_format |
filepath formatting for the partition; See strftime for format specification. | "year=%Y/month=%m/day=%d/hour=%H/minute=%M" |
s3_partition_timezone |
timezone used to format partition | Local |
role_arn |
the Role ARN to be assumed | |
file_prefix |
file prefix defined by user | |
marshaler |
marshaler used to produce output data | otlp_json |
encoding |
Encoding extension to use to marshal data. Overrides the marshaler configuration option if set. |
|
encoding_file_extension |
file format extension suffix when using the encoding configuration option. May be left empty for no suffix to be appended. |
|
endpoint |
(REST API endpoint) overrides the endpoint used by the exporter instead of constructing it from region and s3_bucket |
|
storage_class |
S3 storageclass | STANDARD |
acl |
S3 Object Canned ACL | none (does not set by default) |
s3_force_path_style |
set this to true to force the request to use path-style addressing |
false |
disable_ssl |
set this to true to disable SSL when sending requests |
false |
compression |
should the file be compressed | none |
sending_queue |
exporters common queuing | disabled |
timeout |
exporters common timeout | 5s |
resource_attrs_to_s3 |
determines the mapping of S3 configuration values to resource attribute values for uploading operations. | |
retry_mode |
The retryer implementation, the supported values are "standard", "adaptive" and "nop". "nop" will set the retryer as aws.NopRetryer, which effectively disable the retry. |
standard |
retry_max_attempts |
The max number of attempts for retrying a request if the retry_mode is set. Setting max attempts to 0 will allow the SDK to retry all retryable errors until the request succeeds, or a non-retryable error is returned. |
3 |
retry_max_backoff |
the max backoff delay that can occur before retrying a request if retry_mode is set |
20s |
unique_key_func_name |
Name of the function to use for generating a unique portion of the key name, defaults to a random integer. Only supported value is uuidv7. |
|
retry_on_failure |
see Retry on Failure for the full set of available options. |
Marshaler
Marshaler determines the format of data sent to AWS S3. Currently, the following marshalers are implemented:
otlp_json(default): the OpenTelemetry Protocol format, represented as json.otlp_proto: the OpenTelemetry Protocol format, represented as Protocol Buffers. A single protobuf message is written into each object.sumo_ic: the Sumo Logic Installed Collector Archive format._sourceCategory, _sourceHost, and _sourceName is needed
yamlresource/add_source_category: attributes: - action: insert key: _sourceCategory value: "value" - action: insert key: _sourceHost value: "value" - action: insert key: _sourceName value: "value"
This format is supported only for logs.
body: export the log body as string.
This format is supported only for logs.
Encoding
Encoding overrides marshaler if present and sets to use an encoding extension defined in the collector configuration.
See https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/encoding.
Compression
none(default): No compression will be appliedgzip: Files will be compressed with gzip.zstd: Files will be compressed with zstd.
resource_attrs_to_s3
s3_bucket: Defines which resource attribute's value should be used as the S3 bucket.
When this option is set, it dynamically overridess3uploader/s3_bucket.
If the specified resource attribute exists in the data,
its value will be used as the bucket; otherwise,s3uploader/s3_bucketwill serve as the fallback.s3_prefix: Defines which resource attribute's value should be used as the S3 prefix.
When this option is set, it dynamically overridess3uploader/s3_prefix.
If the specified resource attribute exists in the data,
its value will be used as the prefix; otherwise,s3uploader/s3_prefixwill serve as the fallback.
Example Configurations
Following example configuration defines to store output in 'eu-central' region and bucket named 'databucket'.
exporters:
awss3:
s3uploader:
region: 'eu-central-1'
s3_bucket: 'databucket'
s3_prefix: 'metric'
# Optional (disabled by default)
sending_queue:
enabled: true
num_consumers: 10
queue_size: 100
# Optional (5s by default)
timeout: 20sLogs and traces will be stored inside 'databucket' in the following path format.
metric/year=YYYY/month=MM/day=DD/hour=HH/minute=mmPartition Formatting
By setting the s3_partition_format option, users can specify the file path for their logs.
See the strftime reference for more formatting options.
exporters:
awss3:
s3uploader:
region: 'eu-central-1'
s3_bucket: 'databucket'
s3_prefix: 'metric'
s3_partition_format: '%Y/%m/%d/%H/%M'In this case, logs and traces would be stored in the following path format.
metric/YYYY/MM/DD/HH/mmOptionally along with s3_partition_format you can provide s3_partition_timezone as name from IANA Time Zone
database to change default local timezone to custom, for example UTC or Europe/London.
Base Path Configuration
The s3_base_prefix option allows you to specify a root path inside the bucket that is not overridden by resource_attrs_to_s3. If provided, s3_prefix will be appended to this base path.
exporters:
awss3:
s3uploader:
region: 'eu-central-1'
s3_bucket: 'databucket'
s3_base_prefix: 'environment/prod'
s3_prefix: 'metric'
s3_partition_format: '%Y/%m/%d/%H/%M'In this case, logs and traces would be stored in the following path format.
environment/prod/metric/YYYY/MM/DD/HH/mmData routing based on resource attributes
When resource_attrs_to_s3/s3_bucket or resource_attrs_to_s3/s3_prefix is configured, the S3 bucket and/or prefix are dynamically derived from specified resource attributes in your data.
If the attribute values are unavailable, the bucket and prefix will fall back to the values defined in s3uploader/s3_bucket and s3uploader/s3_prefix respectively.
exporters:
awss3:
s3uploader:
region: 'eu-central-1'
s3_bucket: 'databucket'
s3_prefix: 'metric'
s3_partition_format: '%Y/%m/%d/%H/%M'
resource_attrs_to_s3:
s3_bucket: "com.awss3.bucket"
s3_prefix: "com.awss3.prefix"In this case, metrics, logs and traces would be stored in the following path format examples:
bucket1/prefix1/YYYY/MM/DD/HH/mm
bucket2/foo-prefix/YYYY/MM/DD/HH/mm
bucket3/prefix-bar/YYYY/MM/DD/HH/mm
databucket/metric/YYYY/MM/DD/HH/mm
...Base Path with Resource Attributes
When using both s3_base_prefix and resource_attrs_to_s3/s3_prefix, the s3_base_prefix is always used while s3_prefix can be dynamically overridden by resource attributes.
exporters:
awss3:
s3uploader:
region: 'eu-central-1'
s3_bucket: 'databucket'
s3_base_prefix: 'environment/prod'
s3_prefix: 'default-metric'
s3_partition_format: '%Y/%m/%d/%H/%M'
resource_attrs_to_s3:
s3_prefix: "com.awss3.prefix"In this configuration:
- Base Prefix:
environment/prod(always included) - Prefix: Dynamically set from resource attribute
com.awss3.prefixif available, otherwise falls back todefault-metric
Path format examples:
# When resource attribute com.awss3.prefix = "service-a/metrics"
environment/prod/service-a/metrics/YYYY/MM/DD/HH/mm
# When resource attribute com.awss3.prefix = "service-b/logs"
environment/prod/service-b/logs/YYYY/MM/DD/HH/mm
# When resource attribute is unavailable (fallback)
environment/prod/default-metric/YYYY/MM/DD/HH/mmThis allows you to maintain consistent organizational structure (via base path) while dynamically routing different data types or services to specific subdirectories.
Retry
Standard is the default retryer implementation used by service clients. See the retry package documentation for details on what errors are considered as retryable by the standard retryer implementation.
See also the aws-sdk-go reference for more information.
exporters:
awss3:
s3uploader:
region: 'eu-central-1'
s3_bucket: 'databucket'
s3_prefix: 'metric'
retry_mode: "standard"
retry_max_attempts: 5
retry_max_backoff: "30s"AWS Credential Configuration
This exporter follows default credential resolution for the
aws-sdk-go.
Follow the guidelines for the
credential configuration.
OpenTelemetry Collector Helm Chart for Kubernetes
For example, when using OpenTelemetry Collector Helm Chart you could use extraEnvs in the values.yaml.
extraEnvs:
- name: AWS_ACCESS_KEY_ID
value: "< YOUR AWS ACCESS KEY >"
- name: AWS_SECRET_ACCESS_KEY
value: "< YOUR AWS SECRET ACCESS KEY >"Overview (`exporter/awsxrayexporter/README.md`)
AWS X-Ray Tracing Exporter
| Status | |
|---|---|
| Stability | beta: traces |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @wangzlei, @srprash |
This exporter converts OpenTelemetry spans to
AWS X-Ray Segment Documents
and then sends them directly to X-Ray using the
PutTraceSegments API.
Data Conversion
Trace IDs and Span IDs are expected to be originally generated by either AWS API Gateway or AWS ALB and
propagated by them using the X-Amzn-Trace-Id HTTP header. However, other generation sources are
supported by replacing fully-random Trace IDs with X-Ray formatted Trace IDs where necessary:
AWS X-Ray IDs in binary are 128 bits, the same size as W3C Trace Context IDs but the string is formatted to
β1-{8 digit hex}-{24 digit hex}β. For example, The W3C format trace ID β4bf92f3577b34da6a3ce929d0e0e4736β is
converted to the X-Ray format trace ID β1-4bf92f35-77b34da6a3ce929d0e0e4736".
The http object is populated when the component attribute value is grpc as well as http. Other
synchronous call types should also result in the http object being populated.
AWS Specific Attributes
The following AWS-specific Span attributes are supported in addition to the standard names and values
defined in the OpenTelemetry Semantic Conventions.
| Attribute name | Notes and examples | Required? |
|---|---|---|
aws.operation |
The name of the API action invoked against an AWS service or resource. | No |
aws.account_id |
The AWS account number if accessing resource in different account. | No |
aws.region |
The AWS region if accessing resource in different region from app. | No |
aws.request_id |
AWS-generated unique identifier for the request. | No |
aws.queue_url |
For operations on an Amazon SQS queue, the queue's URL. | No |
aws.table_name |
For operations on a DynamoDB table, the name of the table. | No |
aws.xray.annotations |
The attribute is a slice(list) attribute that contains each of the string keys. If found on the span, the awsxrayexporter will use them in addition to the indexed_attributes configuration field when categorizing which attributes to index. This can be configured with "aws.xray.annotations"=["key1", "key2"] (Java example: span.setAttribute(stringArrayKey("aws.xray.annotations"), List.of("key1", "key2"))) |
No |
Any of these values supplied are used to populate the aws object in addition to any relevant data supplied
by the Span Resource object. X-Ray uses this data to generate inferred segments for the remote APIs.
Exporter Configuration
The following exporter configuration parameters are supported. They mirror and have the same effect as the
comparable AWS X-Ray Daemon configuration values.
| Name | Description | Default |
|---|---|---|
num_workers |
Maximum number of concurrent calls to AWS X-Ray to upload documents. | 8 |
endpoint |
Optionally override the default X-Ray service endpoint. | |
request_timeout_seconds |
Number of seconds before timing out a request. | 30 |
max_retries |
Maximun number of attempts to post a batch before failing. | 2 |
no_verify_ssl |
Enable or disable TLS certificate verification. | false |
proxy_address |
Upload segments to AWS X-Ray through a proxy. | |
region |
Send segments to AWS X-Ray service in a specific region. | |
local_mode |
Local mode to skip EC2 instance metadata check. | false |
resource_arn |
Amazon Resource Name (ARN) of the AWS resource running the collector. | |
role_arn |
IAM role to upload segments to a different account. | |
external_id |
Shared identitier used when assuming an IAM role in an external AWS account. | |
indexed_attributes |
List of attribute names to be converted to X-Ray annotations. | |
index_all_attributes |
Enable or disable conversion of all OpenTelemetry attributes to X-Ray annotations. | false |
aws_log_groups |
List of log group names for CloudWatch. | [] |
telemetry.enabled |
Whether telemetry collection is enabled at all. | false |
telemetry.include_metadata |
Whether to include metadata in the telemetry (InstanceID, Hostname, ResourceARN) | false |
telemetry.contributors |
List of X-Ray component IDs contributing to the telemetry (ex. for multiple X-Ray receivers: awsxray/1, awsxray/2) | |
telemetry.hostname |
Sets the Hostname included in the telemetry. | |
telemetry.instance_id |
Sets the InstanceID included in the telemetry. | |
telemetry.resource_arn |
Sets the Amazon Resource Name (ARN) included in the telemetry. |
Traces and logs correlation
AWS X-Ray can be integrated with CloudWatch Logs to correlate traces with logs. For this integration to work, the X-Ray
segments must have the AWS Property cloudwatch_logs set. This property is set using the AWS X-Ray exporter with the
following values that are evaluated in this order:
aws.log.group.arnsresource attribute.aws.log.group.namesresource attribute.aws_log_groupsconfiguration property.
In the case of multiple values are defined, the value with higher precedence will be used to set the cloudwatch_logs AWS Property.
aws.log.group.arns and aws.log.group.names are slice resource attributes that can be set programmatically.
Alternatively those resource attributes can be set using the OTEL_RESOURCE_ATTRIBUTES environment variable. To set multiple log group names /log group arns, you can use &
to separate them. For example, 3 log groups log-group1, log-group2, and log-group3 are set in the following command:
export OTEL_RESOURCE_ATTRIBUTES="aws.log.group.names=log-group1&log-group2&log-group3"AWS Credential Configuration
This exporter follows default credential resolution for the
aws-sdk-go.
Follow the guidelines for the
credential configuration.
Overview (`exporter/azureblobexporter/README.md`)
Azure Blob Storage Exporter
| Status | |
|---|---|
| Stability | alpha: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @hgaol, @MovieStoreGuy |
Configuration
The following settings are required:
- url: Must be specified if auth type is not connection_string. If auth type is connection_string, it's optional or will be override by the auth.connection_string. Azure storage account endpoint. This setting might be replaced with
endpointfor future. e.g. https://.blob.core.windows.net/ - auth (no default): Authentication method for exporter to ingest data.
- type (no default): Authentication type for exporter. supported values are: connection_string, service_principal, system_managed_identity, user_managed_identity and workload_identity.
- tenand_id: Tenand Id for the client, only needed when type is service_principal and workload_identity.
- client_id: Client Id for the auth, only needed when type is service_principal, user_managed_identity and workload_identity.
- client_secret: Secret for the client, only needed when type is service_principal.
- connection_string: Connection string to the endpoint. Only needed for connection_string auth type. Once provided, it'll override the
urlparameter to the storage account. - federated_token_file: The path of the projected service account token file, only needed when type is workload_identity.
The following settings can be optionally configured and have default values:
- container: container for metrics, logs and traces. A container organizes a set of blobs, similar to a directory in a file system. More details can refer this.
- metrics (default
metrics): container to store metrics. default value ismetrics. - logs (default
logs): container to store logs. default value islogs. - traces (default
traces): container to store traces. default value istraces.
- metrics (default
- blob_name_format: the final blob name will be blob_name
- template_enabled (default
false): enables Go template parsing for blob name formats. If parsing fails, it will not throw an error but will log a warning and continue formatting the blob name using other rules. - metrics_format (default
2006/01/02/metrics_15_04_05.json): blob name format. The date format follows constants in Golang, refer here. - logs_format (default
2006/01/02/logs_15_04_05.json): blob name format. - traces_format (default
2006/01/02/traces_15_04_05.json): blob name format. - timezone (default
""): Timezone for blob name formatting. Local time is used if empty. Must be a valid IANA timezone identifier accepted by Golang'stime.LoadLocation, such asUTCorAmerica/New_York. - serial_num_enabled (default
true): toggles whether a random serial number is appended to the blob name. - serial_num_range (default
10000): a range of random number to be appended after blob_name. e.g.blob_name_{serial_num}. the number will be in[0, serial_num_range). - serial_num_before_extension (default
false): places the serial number before the file extension if there is one. e.gblob_name_{serial_num}.jsoninstead ofblob_name.json_{serial_num} - time_parser_enabled (default
true): controls whether the exporter interprets the format string as a Go time layout. Whenfalse, values such as2006or15_04_05are treated as literal text. - time_parser_ranges (default
nil): limits time formatting to specific parts of the blob name. When not set (nil), the entire blob name is time-formatted iftime_parser_enabledistrue. Provide a list of character ranges like["0-10", "15-25"]to only apply time formatting within those positions. For example, if your blob name isprefix/2006/01/02/file.jsonand you settime_parser_ranges: ["7-17"], only the2006/01/02portion will be replaced with actual date values, whileprefix/and/file.jsonremain unchanged. This is helpful when your blob name contains patterns like2006that you want to keep as literal text.
- template_enabled (default
- compression (default
""): sets the algorithm used to process the payload before uploading to Azure Blob Storage. Valid values aregzip,zstd, or no value set (uncompressed). The appropriate extension (.gzor.zst) is automatically appended to the blob name. - format (default
json):jsonorproto. which present otel json or otel protobuf format, the file extension will bejsonorpb. - encodings (default using encoding specified in
format, which isjson): if specified, uses the encoding extension to encode telemetry data. Overrides format.- logs (default
nil): encoding component id. - metrics (default
nil): encoding component id. - traces (default
nil): encoding component id.
- logs (default
- append_blob: configures append blob behavior. When enabled, telemetry data is appended to a single blob instead of creating new blobs. This can be useful for aggregating data or reducing the number of blobs created.
- enabled (default
false): determines whether to use append blob mode. - separator (default
\n): string to insert between appended data blocks.
- enabled (default
retry_on_failureenabled(default = true)initial_interval(default = 5s): Time to wait after the first failure before retrying; ignored ifenabledisfalsemax_interval(default = 30s): Is the upper bound on backoff; ignored ifenabledisfalsemax_elapsed_time(default = 120s): Is the maximum amount of time spent trying to send a batch; ignored ifenabledisfalse
Blob Name Templates
When template_enabled is true, you can use Go templates in metrics_format, logs_format, and traces_format to create dynamic blob names based on telemetry data. The root object for the template is the telemetry data itself (pmetric.Metrics, plog.Logs, or ptrace.Traces).
The following template functions are available:
| Function | Description | Example |
|---|---|---|
getResourceMetricAttr |
Gets a resource attribute from metrics data. | {{ getResourceMetricAttr . 0 "service.name" }} |
getResourceLogAttr |
Gets a resource attribute from logs data. | {{ getResourceLogAttr . 0 "service.name" }} |
getResourceSpanAttr |
Gets a resource attribute from traces data. | {{ getResourceSpanAttr . 0 "service.name" }} |
getScopeMetricAttr |
Gets a scope attribute from metrics data. | {{ getScopeMetricAttr . 0 0 "scope.name" }} |
getScopeLogAttr |
Gets a scope attribute from logs data. | {{ getScopeLogAttr . 0 0 "scope.name" }} |
getScopeSpanAttr |
Gets a scope attribute from traces data. | {{ getScopeSpanAttr . 0 0 "scope.name" }} |
getMetric |
Gets a metric object. You can chain to access its fields. | {{ (getMetric . 0 0 0).Name }} |
getLogRecord |
Gets a log record object. You can chain to access its fields. | {{ (getLogRecord . 0 0 0).TraceID }} |
getSpan |
Gets a span object. You can chain to access its fields. | {{ (getSpan . 0 0 0).Name }} |
An example configuration is provided as follows:
extensions:
zpages:
endpoint: localhost:55679
text_encoding:
encoding: utf8
marshaling_separator: "\n"
unmarshaling_separator: "\r?\n"
exporter:
azure_blob/1:
url: "https://<your-account>.blob.core.windows.net/"
container:
logs: "logs"
metrics: "metrics"
traces: "traces"
blob_name_format:
template_enabled: true
metrics_format: `{{ getResourceMetricAttr . 0 "service.name" }}/2006/01/02/metrics.json`
logs_format: `{{ getScopeLogAttr . 0 0 "scope.name" }}/2006/01/02/logs.json`
traces_format: `{{ (getSpan . 0 0 0).Name }}/2006/01/02/traces.json`
serial_num_enabled: true
time_parser_enabled: true
auth:
type: "connection_string"
connection_string: "DefaultEndpointsProtocol=https;AccountName=<your-acount>;AccountKey=<account-key>;EndpointSuffix=core.windows.net"
encodings:
logs: text_encoding
append_blob:
enabled: true
separator: "\n"
compression: gzip # or "zstd" or leave unset for no compressionAppend Blob
When append_blob is enabled:
- The exporter will create append blobs instead of block blobs
- New data will be appended to existing blobs rather than creating new ones
- The configured separator will be inserted between data blocks
- If the blob doesn't exist, it will be created automatically
Overview (`exporter/azuredataexplorerexporter/README.md`)
Azure Data Explorer Exporter
| Status | |
|---|---|
| Stability | beta: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @ag-ramachandran |
| Emeritus | @asaharn |
This exporter sends metrics, logs and trace data to
Azure Data Explorer,
Azure Synapse Data Explorer and
Real time analytics in Fabric
Configuration
The following settings are required:
cluster_uri(no default): The cluster name of the provisioned ADX cluster to ingest the data.
One authentication method is required:
- Service principal:
application_id(no default): The client id to connect to the cluster and ingest data.application_key(no default): The cluster secret corresponding to the client id.tenant_id(no default): The tenant id where the application_id is referenced from.
- Managed identity:
managed_identity_id(no default): The managed identity id to authenticate with. Set to "system" for system-assigned managed identity. Set the MI client ID (GUID) for user-assigned managed identity.
- Default authentication:
use_azure_auth(default: false): Set to true to use the Azure default authentication.
The following settings can be optionally configured and have default values:
Note that the database tables are expected to be created upfront before the exporter is in operation , the definition of these are in the section Database and Table definition scripts
db_name(default = "oteldb"): The ADX database where the tables are present to ingest the data.metrics_table_name(default = OTELMetrics): The target table in the databasedb_namethat stores exported metric data.logs_table_name(default = OTELLogs): The target table in the databasedb_namethat stores exported logs data.traces_table_name(default = OTELTraces): The target table in the databasedb_namethat stores exported traces data.Optionally the following table mappings can be specified if the data needs to be mapped to a different table on ADX. This uses json table mapping that can be used to map attributes to target tables
metrics_table_json_mapping(optional, no default): The table mapping name to be used for the tabledb_name.metrics_table_namelogs_table_json_mapping(optional, no default): The table mapping name to be used for the tabledb_name.logs_table_nametraces_table_json_mapping(optional, no default): The table mapping name to be used for the tabledb_name.traces_table_nameingestion_type(possible values=queued/managed, default = queued): ADX ingest can happen in managed streaming or queued modes.
Note: Streaming ingestion has to be enabled on ADX [configure the ADX cluster] in case of
streamingoption. Refer the query below to check if streaming is enabled
.show database <DB-Name> policy streamingingestionAn example configuration is provided as follows:
/* Detailed source-code truncated for AI context efficiency. */Attribute mapping
This exporter maps OpenTelemetry trace, metric and log attributes to specific structures in the ADX tables. These can then be extended by usage of update policies in ADX if needed
Traces
| ADX Table column | Description / OpenTelemetry attribute |
|---|---|
| TraceId | A valid trace identifier is a 16-byte array with at least one non-zero byte. |
| SpanId | A valid span identifier is an 8-byte array with at least one non-zero byte. |
| ParentId | A parent spanId, for the current span |
| SpanName | The span name |
| SpanStatus | Status Code of the Span. |
| SpanStatusMessage | Status Message of the Span |
| SpanKind | SpanKind describes the relationship between the Span, its parents, and its children in a Trace |
| StartTime | A start timestamp |
| EndTime | An end timestamp |
| TraceAttributes | Custom metric attributes set from the application. Also contains the instrumentation scope name and version |
| ResourceAttributes | The resource attributes JSON map as specified in open telemetry resource semantics |
| Events | A list of timestamped Events |
| Links | A list of Links to other Spans |
Metrics
| ADX Table column | Description / OpenTelemetry attribute |
|---|---|
| Timestamp | The timestamp of the datapoint |
| MetricName | The name of the datapoint |
| MetricType | The type / datapoint type of the metric (e.g. Sum, Histogram, Gauge etc.) |
| MetricUnit | Unit of measure of the metric |
| MetricDescription | Description about the metric |
| MetricValue | The metric value measured for the datapoint |
| MetricAttributes | Custom metric attributes set from the application. Also contains the instrumentation scope name and version |
| Host | The host.name extracted from Host resource semantics. If empty , the hostname of the exporter is used |
| ResourceAttributes | The resource attributes JSON map as specified in open telemetry resource semantics |
Logs
| ADX Table column | Description / OpenTelemetry attribute |
|---|---|
| Timestamp | The timestamp of the datapoint |
| ObservedTimestamp | Time when the event was observed. |
| TraceId | Request trace id. |
| SpanId | Request span id. |
| SeverityText | The severity text (also known as log level) |
| SeverityNumber | Numerical value of the severity. |
| Body | The body of the log record. |
| LogsAttributes | Custom metric attributes set from the application. Also contains the instrumentation scope name and version |
| ResourceAttributes | The resource attributes JSON map as specified in open telemetry resource semantics |
Database and Table definition scripts
The following tables need to be created in the database specified in the configuration.
.create-merge table <Logs-Table-Name> (Timestamp:datetime, ObservedTimestamp:datetime, TraceID:string, SpanID:string, SeverityText:string, SeverityNumber:int, Body:string, ResourceAttributes:dynamic, LogsAttributes:dynamic)
.create-merge table <Metrics-Table-Name> (Timestamp:datetime, MetricName:string, MetricType:string, MetricUnit:string, MetricDescription:string, MetricValue:real, Host:string, ResourceAttributes:dynamic,MetricAttributes:dynamic)
.create-merge table <Traces-Table-Name> (TraceID:string, SpanID:string, ParentID:string, SpanName:string, SpanStatus:string, SpanKind:string, StartTime:datetime, EndTime:datetime, ResourceAttributes:dynamic, TraceAttributes:dynamic, Events:dynamic, Links:dynamic)
// This is an optional column to store the status code and message as a dynamic field. This augments the status field with Status code and status message
.alter-merge table <Traces-Table-Name> (SpanStatusMessage:string)
//Enable streaming ingestion( for managed streaming) for the created tables using
.alter table <Table-Name> policy streamingingestion enableOptional configurations/Enhancements suggestions
- Using update policies , the collected data can further be processed as per application need. The following is an example where histogram metrics are exported to a histo specific table (buckets and aggregates)
/* Detailed source-code truncated for AI context efficiency. */OpenTelemetry Exporter Helper Configurations
The ADX exporter now includes support for OpenTelemetry exporter helper configurations. This feature allows you to leverage the exporter helper capabilities(retries, timeout etc.) provided natively by Otel. Read more about the exporterhelper.
Please note that this configuration is not enabled by default. To utilize the OpenTelemetry exporter helper, you will need to add it manually to the configuration.
Example Configuration
# Example OpenTelemetry Exporter Configuration
timeout: 10s
sending_queue:
enabled: true
num_consumers: 2
queue_size: 10
retry_on_failure:
enabled: true
initial_interval: 10s
max_interval: 60s
max_elapsed_time: 10m
---
### Overview (`exporter/azuremonitorexporter/README.md`)
# Azure Monitor Exporter
| Status | |
| ------------- |-----------|
| Stability | [beta]: traces, metrics, logs |
| Distributions | [contrib] |
| Issues | [](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aexporter%2Fazuremonitor) [](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aexporter%2Fazuremonitor) |
| Code coverage | [](https://app.codecov.io/gh/open-telemetry/opentelemetry-collector-contrib/tree/main/?components%5B0%5D=exporter_azuremonitor&displayType=list) |
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@hgaol](https://www.github.com/hgaol) |
| Emeritus | [@pcwiese](https://www.github.com/pcwiese) |
[beta]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#beta
[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
This exporter sends logs, traces and metrics to [Azure Monitor](https://docs.microsoft.com/azure/azure-monitor/).
## Configuration
To configure the Azure Monitor Exporter, you must specify one of the following settings:
- `connection_string` (recommended): The Azure Application Insights Connection String is required to send telemetry data to the monitoring service. It is the recommended method for configuring the exporter, aligning with Azure Monitor's best practices. If you need guidance on creating Azure resources, please refer to the step-by-step guides to [Create an Application Insights resource](https://docs.microsoft.com/azure/azure-monitor/app/create-new-resource) and [find your connection string](https://docs.microsoft.com/azure/azure-monitor/app/sdk-connection-string?tabs=net#find-your-connection-string).
- `instrumentation_key`: Application Insights instrumentation key, which can be found in the Application Insights resource in the Azure Portal. While it is currently supported, its use is discouraged and it is slated for deprecation. It is highly encouraged to use the `connection_string` setting for new configurations and migrate existing configurations to use the `connection_string` as soon as possible.
### Environment Variable Support
In addition to the above configuration options, the Azure Monitor Exporter now supports setting the connection string via the `APPLICATIONINSIGHTS_CONNECTION_STRING` environment variable. This method is particularly useful for cloud or containerized environments where managing configuration through environment variables is standard practice.
**Note:** If both the environment variable and the `connection_string` configuration option are provided, the environment variable takes precedence.
### Configuration Options
**Important**: Only one of `connection_string` or `instrumentation_key` should be specified in your configuration. If both are provided, `connection_string` will be used as the priority setting.
The following settings can be optionally configured:
- `endpoint` (default = `https://dc.services.visualstudio.com/v2/track`): The endpoint URL where data will be submitted. While this option remains available, it is important to note that the use of the `connection_string` is recommended, as it encompasses the endpoint information. The direct configuration of the `endpoint` is considered to be on a deprecation path.
- `maxbatchsize` (default = 1024): The maximum number of telemetry items that can be submitted in each request. If this many items are buffered, the buffer will be flushed before `maxbatchinterval` expires.
- `maxbatchinterval` (default = 10s): The maximum time to wait before sending a batch of telemetry.
- `spaneventsenabled` (default = false): Enables export of span events.
- `sending_queue`
- `enabled` (default = false)
- `num_consumers` (default = 10): Number of consumers that dequeue batches; ignored if `enabled` is `false`
- `queue_size` (default = 1000): Maximum number of batches kept in memory before data; ignored if `enabled` is `false`
- `storage` (default = `none`): When set, enables persistence and uses the component specified as a storage extension for the persistent queue
- `shutdown_timeout` (default = 1s): Timeout to wait for graceful shutdown. Once exceeded, the component will shut down forcibly, dropping any element in queue.
- `custom_events_enabled` (default = `false`): Enables export log record to custom events when there's attribute `microsoft.custom_event.name` or `APPLICATION_INSIGHTS_EVENT_MARKER_ATTRIBUTE`.
- `telemetry_mappings.traces.http.success.server_policy` (default = unset): Set to `otel` to export HTTP server spans with 4xx response codes with Application Insights request `Success=true`, matching OpenTelemetry HTTP semantic conventions. HTTP client dependencies are unaffected.
- `telemetry_mappings.traces.http.success.additional_success_status_codes` (default = `[]`): Additional HTTP status codes to export with Application Insights `Success=true` for both HTTP server requests and HTTP client dependencies.
### Tag mappings (alpha)
The optional `tag_mappings:` block overrides how selected Application Insights envelope tags are populated from OpenTelemetry resource attributes. Each field takes an ordered list of sources; the first one that resolves to a non-empty string wins.
A source entry is interpreted as:
- a **resource attribute key** when it contains a `.` (e.g. `service.instance.id`, `host.name`)
- a **string literal terminal default** when it does not contain a `.` (e.g. `unknown-instance`)
Defaults preserve the historical hardcoded behavior β when a field is unset, zero-config users see no change.
| Mapping key | Application Insights tag | Default |
| --------------------- | ----------------------------- | ------------------------ |
| `cloud_role_instance` | `ai.cloud.roleInstance` | `[service.instance.id]` |
| `application_version` | `ai.application.ver` | `[service.version]` |
> The `cloud_role_name` tag (`ai.cloud.role`) is not yet configurable; its hardcoded `service.namespace`/`service.name` concatenation continues to apply.
Example β Azure Container Apps, where `service.instance.id` is set to a random uuid and operators want the revision/replica hostname instead:
```yaml
exporters:
azure_monitor:
connection_string: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/"
tag_mappings:
cloud_role_instance: [host.name, service.instance.id, unknown-instance]Validation rejects an explicitly empty array (cloud_role_instance: []) at startup. The feature is alpha and the schema may evolve.
Example:
# Recommended Configuration:
# It is highly recommended to use the connection string which includes the InstrumentationKey and IngestionEndpoint
# This is the preferred method over using 'instrumentation_key' alone.
exporters:
azure_monitor:
connection_string: "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://ingestion.azuremonitor.com/"(or)
# Legacy Configuration:
# The use of 'instrumentation_key' alone is not recommended and will be deprecated in the future. It is advised to use the connection_string instead.
# This example is provided primarily for existing configurations that have not yet transitioned to the connection string.
exporters:
azure_monitor:
instrumentation_key: b1cd0778-85fc-4677-a3fa-79d3c23e0efdExample using environment variable:
Ensure APPLICATIONINSIGHTS_CONNECTION_STRING is set in your environment, then configure the exporter without specifying a connection string or instrumentation key:
exporters:
azure_monitor:Attribute mapping
Traces
This exporter maps OpenTelemetry trace data to Application Insights data model using the following schema.
The OpenTelemetry SpanKind determines the Application Insights telemetry type.
| OpenTelemetry SpanKind | Application Insights telemetry type |
|---|---|
CLIENT, PRODUCER, INTERNAL |
Dependency |
SERVER, CONSUMER |
Request |
The exporter follows the semantic conventions to fill the Application Insights specific telemetry properties. The following table shows a basic mapping.
| Application Insights property | OpenTelemetry attribute | Default |
|---|---|---|
| Request.Name | http.method, http.route or rpc.system |
span name |
| Request.Url | http.scheme, http.host, http.target |
|
| Request.Source | http.client_ip or net.peer.name |
|
| Request.ResponseCode | http.status_code or status_code |
"0" |
| Request.Success | http.status_code or status_code |
true |
| Dependency.Name | http.method, http.route |
span name |
| Dependency.Data | http.url or span name or db.statement |
|
| Dependency.Type | "HTTP" or rpc.system or db.system or "InProc" |
|
| Dependency.Target | host of http.url or net.peer.name |
|
| Dependency.ResultCode | http.status_code or status_code |
"0" |
| Dependency.Success | http.status_code or status_code |
true |
The exact mapping can be found in trace_to_envelope.go.
All attributes are also mapped to custom properties if they are booleans or strings and to custom measurements if they are ints or doubles.
All links are mapped to property _MS.links with JSON array string.
Span Events
Span events are optionally saved to the Application Insights traces table.
Exception events are saved to the Application Insights exception table.
Logs
This exporter saves log records to Application Insights traces table.
TraceId is mapped to operation_id column and SpanId is mapped to operation_parentId column.
Custom Events
When custom_events_enabled = true, azure monitor exporter will export log record to custom events when there's attribute microsoft.custom_event.name or APPLICATION_INSIGHTS_EVENT_MARKER_ATTRIBUTE.
Exceptions
This exporter saves exception records to Application Insights exceptions table when log records indicate an exception specification.
When exception_events_enabled = true, azure monitor exporter will export log records to exceptions when either one of exception.message or exception.type attributes are set.
Metrics
This exporter saves metrics to Application Insights customMetrics table.
AAD/Entra Authentication
Details of how to use the Azure Monitor Exporter with AAD/Entra based identities can be found in the Authentication page.
Overview (`exporter/bmchelixexporter/README.md`)
BMC Helix Exporter
| Status | |
|---|---|
| Stability | alpha: metrics |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @bertysentry, @NassimBtk, @MovieStoreGuy |
Note: The exporter type has been renamed from
bmchelixtobmc_helixto follow the
snake_case naming convention. The old namebmchelixis preserved as a deprecated alias and
will continue to work, but a deprecation warning will be logged at startup. Please update your
configuration to usebmc_helix:.
This exporter supports sending metrics to BMC Helix Operations Management through its metric ingestion REST API.
Getting Started
The following settings are required:
endpoint: is the BMC Helix Portal URL of your environment, at onbmc.com for a BMC Helix SaaS tenant (e.g.,https://company.onbmc.com), or your own Helix Portal URL for an on-prem instance.api_key: API key to authenticate the exporter. Connect to BMC Helix Operations Management, go to the Administration > Repository page, and click on the Copy API Key button to get your API Key. Alternatively, it is recommended to create and use a dedicated authentication key for external integration.
Example:
exporters:
bmc_helix/helix1:
endpoint: https://company.onbmc.com
api_key: <api-key>
sending_queue:
batch:Optional Settings
The following settings can be optionally configured:
timeout: (default =10s) Timeout for requests made to the BMC Helix.enrich_metric_with_attributes: (default =true) When enabled, creates enriched metrics by appending datapoint attribute values to the metric name. This provides more detailed identification in BMC Helix Operations Management but increases metric cardinality. Set tofalseto reduce the number of unique metric series.retry_on_failuredetails hereenabled(default = true)initial_interval(default = 5s) Time to wait after the first failure before retrying; ignored ifenabledis false.max_interval(default = 30s) The upper bound on backoff; ignored ifenabledis false.max_elapsed_time(default = 300s) The maximum amount of time spent trying to send a batch; ignored ifenabledis false. If set to 0, the retries are never stopped.
Example:
exporters:
bmc_helix/helix2:
endpoint: https://company.onbmc.com
api_key: <api-key>
timeout: 20s
enrich_metric_with_attributes: false
sending_queue:
batch:
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 1m
max_elapsed_time: 8mSetting Required Attributes for Metrics
To ensure metrics are correctly populated in BMC Helix, the following attributes must be set either at the Resource level, or at the Metric level:
entityName: Unique identifier for the entity. Used as display name ifinstanceNameis missing.entityTypeId: Type identifier for the entity.instanceName: Display name of the entity.
Note: If
entityNameorentityTypeIdis missing, the metric will not be exported.
To ensure the necessary attributes are present, it is recommended to leverage the transform processor with OTTL, and include it in the configuration of the telemetry pipeline.
The minimal pipeline most often looks like: OTEL metrics --> (memory limit) --> transform processor --> bmc_helix exporter.
Transformer Example for Hardware Metrics
You can use the following OpenTelemetry Transformation Language (OTTL) configuration to map these attributes dynamically:
/* Detailed source-code truncated for AI context efficiency. */This transformer dynamically sets the attributes required for BMC Helix based on metric names and resource attributes.
Overview (`exporter/cassandraexporter/README.md`)
Cassandra Exporter
| Status | |
|---|---|
| Stability | alpha: traces, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @atoulme, @emreyalvac |
Configuration options
The following settings can be optionally configured:
dsnThe Cassandra server DSN (Data Source Name), for example127.0.0.1.
reference: github.com/apache/cassandra-gocql-driver/v2port(default = 9042): The Cassandra server porttimeout(default = 10s): The Cassandra server connection timeoutkeyspace(default = otel): The keyspace name.trace_table(default = otel_spans): The table name for traces.replication(default = class: SimpleStrategy, replication_factor: 1): The strategy of
replication. https://cassandra.apache.org/doc/4.1/cassandra/architecture/dynamo.html#replication-strategycompression(default = LZ4Compressor): https://cassandra.apache.org/doc/4.0/cassandra/operating/compression.htmlauth(default = username: "", password: "") Authorization for the Cassandra.
Example
exporters:
cassandra:
dsn: 127.0.0.1
port: 9042
timeout: 10s
keyspace: "otel"
trace_table: "otel_spans"
replication:
class: "SimpleStrategy"
replication_factor: 1
compression:
algorithm: "ZstdCompressor"
auth:
username: "your-username"
password: "your-password"Overview (`exporter/clickhouseexporter/README.md`)
ClickHouse Exporter
| Status | |
|---|---|
| Stability | development: profiles |
| alpha: metrics | |
| beta: traces, logs | |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @Frapschen, @SpencerTorres |
| Emeritus | @dmitryax, @hanjm |
This exporter supports sending OpenTelemetry data to ClickHouse.
ClickHouse is an open-source, high performance columnar OLAP database management system for real-time analytics using
SQL.
Throughput can be measured in rows per second or megabytes per second.
If the data is placed in the page cache, a query that is not too complex is processed on modern hardware at a speed of
approximately 2-10 GB/s of uncompressed data on a single server.
If 10 bytes of columns are extracted, the speed is expected to be around 100-200 million rows per second.
Note:
Batching Recommendation
For optimal performance, ClickHouse recommends inserting data in large batches:
We recommend inserting data in packets of at least 5000 rows, or no more than a single request per second. When inserting to a MergeTree table from a tab-separated dump, the insertion speed can be from 50 to 200 MB/s.
To achieve this natively, enable batching within the exporter's sending_queue configuration. You do not need to add the external batch processor to your collector pipeline. Relying on the exporter's internal batching is the recommended approach to avoid data-loss issues associated with the external processor.
Enable it by adding a batch block inside sending_queue:
exporters:
clickhouse:
endpoint: tcp://127.0.0.1:9000
sending_queue:
# num_consumers controls how many batches are inserted into ClickHouse
# concurrently.
num_consumers: 10
batch:
min_size: 5000 # rows per INSERT (items sizer); tune to your workload
flush_timeout: 5s # flush a partial batch after this delayIf you are migrating from a pipeline that uses the standalone batch processor, remove batch from the pipeline's processors list and configure sending_queue.batch instead. For durability across restarts, also set sending_queue.storage to a storage extension so queued batches survive a crash (at-least-once delivery).
Visualization Tools
Official ClickHouse Plugin for Grafana
The official ClickHouse Datasource for Grafana contains features that integrate directly with this exporter.
You can view associated logs and traces, as well as visualize other queries such as tables and time series graphs. Learn how to configure the OpenTelemetry integration.
Altinity's ClickHouse Plugin for Grafana
If the official plugin doesn't meet your needs, you can try the Altinity plugin for ClickHouse, which also supports a wide range of features.
Logs
- Get log severity count time series.
SELECT toDateTime(toStartOfInterval(Timestamp, INTERVAL 60 second)) as time, SeverityText, count() as count
FROM otel_logs
WHERE toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
GROUP BY SeverityText, time
ORDER BY time;The default logs table is ordered by (toStartOfFiveMinutes(Timestamp), ServiceName, Timestamp).
For time range queries, filter on both toStartOfFiveMinutes(Timestamp) and Timestamp, and order by the tuple (toStartOfFiveMinutes(Timestamp), Timestamp) to use the primary key's read-in-order optimization.
Apply toStartOfFiveMinutes to the range bound as well (e.g. toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)) so the time bucket bounds are not truncated off the scan.
- Find any log.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;- Find log with specific service.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE ServiceName = 'clickhouse-exporter'
AND toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;- Find log with specific attribute.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE LogAttributes['container_name'] = '/example_flog_1'
AND toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;- Find log with body contain string token.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE hasToken(Body, 'http')
AND toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;- Find log with body contain string.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE Body like '%http%'
AND toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;- Find log with body regexp match string.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE match(Body, 'http')
AND toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;- Find log with body json extract.
SELECT Timestamp as log_time, Body
FROM otel_logs
WHERE JSONExtractFloat(Body, 'bytes') > 1000
AND toStartOfFiveMinutes(Timestamp) >= toStartOfFiveMinutes(NOW() - INTERVAL 1 HOUR)
AND Timestamp >= NOW() - INTERVAL 1 HOUR
ORDER BY (toStartOfFiveMinutes(Timestamp), Timestamp) DESC
LIMIT 100;Traces
- Find spans with specific attribute.
SELECT Timestamp,
TraceId,
SpanId,
ParentSpanId,
SpanName,
SpanKind,
ServiceName,
Duration,
StatusCode,
StatusMessage,
toString(SpanAttributes),
toString(ResourceAttributes),
toString(Events.Name),
toString(Links.TraceId)
FROM otel_traces
WHERE ServiceName = 'clickhouse-exporter'
AND SpanAttributes['peer.service'] = 'telemetrygen-server'
AND Timestamp >= NOW() - INTERVAL 1 HOUR
Limit 100;- Find traces with traceID (using time primary index and TraceID skip index).
WITH
'391dae938234560b16bb63f51501cb6f' as trace_id,
(SELECT min(Start) FROM otel_traces_trace_id_ts WHERE TraceId = trace_id) as start,
(SELECT max(End) + 1 FROM otel_traces_trace_id_ts WHERE TraceId = trace_id) as end
SELECT Timestamp,
TraceId,
SpanId,
ParentSpanId,
SpanName,
SpanKind,
ServiceName,
Duration,
StatusCode,
StatusMessage,
toString(SpanAttributes),
toString(ResourceAttributes),
toString(Events.Name),
toString(Links.TraceId)
FROM otel_traces
WHERE TraceId = trace_id
AND Timestamp >= start
AND Timestamp <= end
Limit 100;- Find spans is error.
SELECT Timestamp,
TraceId,
SpanId,
ParentSpanId,
SpanName,
SpanKind,
ServiceName,
Duration,
StatusCode,
StatusMessage,
toString(SpanAttributes),
toString(ResourceAttributes),
toString(Events.Name),
toString(Links.TraceId)
FROM otel_traces
WHERE ServiceName = 'clickhouse-exporter'
AND StatusCode = 'Error'
AND Timestamp >= NOW() - INTERVAL 1 HOUR
Limit 100;- Find slow spans.
SELECT Timestamp,
TraceId,
SpanId,
ParentSpanId,
SpanName,
SpanKind,
ServiceName,
Duration,
StatusCode,
StatusMessage,
toString(SpanAttributes),
toString(ResourceAttributes),
toString(Events.Name),
toString(Links.TraceId)
FROM otel_traces
WHERE ServiceName = 'clickhouse-exporter'
AND Duration > 1 * 1e9
AND Timestamp >= NOW() - INTERVAL 1 HOUR
Limit 100;Metrics
Metrics data is stored in different clickhouse tables depending on their types. The tables will have a suffix to
distinguish which type of metrics data is stored.
| Metrics Type | Metrics Table |
|---|---|
| sum | _sum |
| gauge | _gauge |
| histogram | _histogram |
| exponential histogram | _exponential_histogram |
| summary | _summary |
Before you make a metrics query, you need to know the type of metric you wish to use. If your metrics come from
Prometheus(or someone else uses OpenMetrics protocol), you also need to know the
compatibility
between Prometheus(OpenMetrics) and OTLP Metrics.
- Find a sum metrics with name
select TimeUnix,MetricName,Attributes,Value from otel_metrics_sum
where MetricName='calls' limit 100- Find a sum metrics with name, attribute.
select TimeUnix,MetricName,Attributes,Value from otel_metrics_sum
where MetricName='calls' and Attributes['service_name']='featureflagservice'
limit 100The OTLP Metrics define two type value for one datapoint,
clickhouse only use one value of float64 to store them.
Profiles
[!IMPORTANT]
Profiles support is atdevelopmentstability. The OpenTelemetry profiling signal itself is
pre-GA (the OTLP profiles protocol is inv1development), so the schema and behavior may change
in a backwards-incompatible way. To send profiles through a collector pipeline you must enable theservice.profilesSupportfeature gate (--feature-gates=+service.profilesSupport).The profiles table requires ClickHouse 26.2 or newer. It always uses
text(full-text-search)
indexes and does not fall back tobloom_filteron older server versions. If you manage the schema
yourself (create_schema: false), you can adapt the DDL for an older version.
Profiles are stored as one denormalized row per OTLP Sample. The interned ProfilesDictionary
(strings, functions, locations, mappings, links, attributes) is resolved at write time so each row
is self-contained and can be queried without joins.
Performance Guide
A single ClickHouse instance with 32 CPU cores and 128 GB RAM can handle around 20 TB (20 Billion) logs per day,
the data compression ratio is 7 ~ 11, the compressed data store in disk is 1.8 TB ~ 2.85 TB,
add more clickhouse node to cluster can increase linearly.
The otel-collector with otlp receiver/clickhouse tcp exporter (with sending_queue batching enabled) can process
around 40k/s logs entry per CPU cores, add more collector node can increase linearly.
Reading a shared table by a resource attribute
The default schemas order primarily by time and ServiceName, and store resource-level
labels (for example a tenant or namespace attribute) in the ResourceAttributes map
rather than in the sort key. A skip index on the map values lets a query that filters on a
single attribute value prune granules, but because every value shares the same
time-partitioned parts, a wide time-range read filtered to one value still scans granules
that also contain other values' rows β the filter is applied after the granule is read.
For a low-cardinality attribute this is negligible. If you query a shared table by a
high-cardinality attribute (for example one tenant out of hundreds or thousands, each
reading concurrently), that shared-parts scan can become the read bottleneck. In that case,
set create_schema: false and manage the DDL yourself so the
attribute participates in the primary key β for example by adding it early in ORDER BY or
via a projection β accepting that this diverges from the default schema.
Configuration options
The following settings are required:
endpoint(no default): The ClickHouse server address, support multi host with port, for example:- tcp protocol
tcp://addr1:port,tcp://addr2:portor TLStcp://addr1:port,addr2:port?secure=true - http protocol
http://addr1:port,addr2:portor httpshttps://addr1:port,addr2:port - clickhouse protocol
clickhouse://addr1:port,addr2:portor TLSclickhouse://addr1:port,addr2:port?secure=true
When multiple endpoints are provided, the driver handles load balancing and automatic failover. By default, it uses
in_orderstrategy (tries endpoints in the order specified). Alternatively, useconnection_open_strategy=round_robin(distributes connections evenly) orconnection_open_strategy=random(randomly selects endpoints) inconnection_params. See connection_open_strategy documentation.- tcp protocol
Many other ClickHouse specific options can be configured through query parameters e.g. addr?dial_timeout=5s&compress=lz4. For a full list of options see the ClickHouse driver documentation
Connection options:
username(default = ): The authentication username.password(default = ): The authentication password.ttl(default = 0): The data time-to-live example 30m, 48h. Also, 0 means no ttl.database(default = default): The database name. Overrides the database defined inendpointwhen this setting is not equal todefault.connection_params(default = {}). Extra connection parameters with map format. Query parameters provided inendpointwill be individually overwritten if present in this map. Parameters can be either driver parameters (e.g.,connection_open_strategy,max_open_conns) that control client-side behavior, or ClickHouse session settings (e.g.,max_execution_time) that are passed to the server. See the driver parameters list for recognized driver options; all others are treated as session settings.create_schema(default = true): When set to true, will run DDL to create the database and tables. (See schema management)compress(default = lz4): Controls the compression algorithm. Valid options:none(disabled),zstd,lz4(default),gzip,deflate,br,true(lz4). Ignored ifcompressis set in theendpointorconnection_params.async_insert(default = true): Enables async inserts. Ignored if async inserts are configured in theendpointorconnection_params. Async inserts may still be overridden server-side.tlsAdvanced TLS configuration (See TLS).
Additional DSN features:
The underlying clickhouse-go module offers additional configuration. These can be set in the exporter's endpoint or connection_params config values.
client_info_productMust be inproductName/versionformat with comma separated entries. By default the exporter will append its binary build information. You can use this information to track the origin ofINSERTstatements in thesystem.query_logtable.
ClickHouse tables:
logs_table_name(default = otel_logs): The table name for logs.traces_table_name(default = otel_traces): The table name for traces.profiles_table_name(default = otel_profiles): The table name for profiles.metrics_tablesgaugename(default = "otel_metrics_gauge")
sumname(default = "otel_metrics_sum")
summaryname(default = "otel_metrics_summary")
histogramname(default = "otel_metrics_histogram")
exponential_histogramname(default = "otel_metrics_exp_histogram")
Cluster definition:
cluster_name(default = ): Optional. If present, will includeON CLUSTER cluster_namewhen creating the database and tables.
Table engine:
table_enginename(default = MergeTree)params(default = )
Modifies ENGINE definition when table is created. If not set then ENGINE defaults to MergeTree().
Can be combined with cluster_name to enable replication for fault tolerance.
Database engine:
database_enginename(default = )params(default = )
Modifies ENGINE definition when the database is created. If not set then the server default is used. Not used for the default database.
With Replicated, ON CLUSTER is only used for the database since a Replicated database replicates table DDL itself.
Processing:
timeout(default = 5s): The timeout for every attempt to send data to the backend.sending_queueenabled(default = true)num_consumers(default = 10): Number of concurrent consumers that dequeue and insert data into ClickHouse. Enablingbatchdoes not reduce this parallelism, only the (cheap) queue reader becomes single-threaded, while inserts still run on up tonum_consumersworkers. Ignored ifenabledisfalse.queue_size(default = 1000): Maximum size of the queue, measured insizerunits. Data is dropped when the queue is full unlessblock_on_overflowis enabled.sizer(default =requests): Howqueue_sizeis measured. One ofrequests,items, orbytes.block_on_overflow(default = false): Iftrue, waits for space when the queue is full instead of dropping data (applies backpressure to the pipeline).storage(default = none): Name of a storage extension for a persistent, crash-safe queue. When unset, the queue is in-memory and is lost on restart.batch(disabled by default): Batches data inside the sending queue. Add an emptybatch: {}to enable it with the defaults below. This replaces the standalonebatchprocessor; see the batching recommendation near the top of this document.flush_timeout(default = 200ms): Time after which a batch is sent regardless of size.min_size(default = 8192): Minimum batch size before it is sent, inbatch.sizerunits.max_size(default = 0): Maximum batch size;0means no limit. When set, larger batches are split, and it must be>= min_size.sizer(default =items): How batch size is measured. One ofitemsorbytes(notrequests). If unset, inheritssending_queue.sizer.
retry_on_failureenabled(default = true)initial_interval(default = 5s): The Time to wait after the first failure before retrying; ignored ifenabled
isfalsemax_interval(default = 30s): The upper bound on backoff; ignored ifenabledisfalsemax_elapsed_time(default = 300s): The maximum amount of time spent trying to send a batch; ignored ifenabled
isfalse
TLS
The exporter supports TLS. To enable TLS, you must specify the secure=true query parameter in the endpoint URL or use the https scheme.
You may also use certificate authentication with the tls setting:
exporters:
clickhouse:
endpoint: . . .
tls:
insecure: false
insecure_skip_verify: false
ca_file: CAroot.crt
cert_file: client.crt
key_file: client.keyThe available tls options are inherited from OpenTelemetry's TLS config structure, more options are available than shown in this example.
Schema management
By default, the exporter will create the database and tables under the names defined in the config. This is fine for simple deployments, but for production workloads, it is recommended that you manage your own schema by setting create_schema to false in the config.
This prevents each exporter process from racing to create the database and tables, and makes it easier to upgrade the exporter in the future.
In this mode, the only SQL sent to your server will be for INSERT statements.
The default DDL used by the exporter can be found in internal/sqltemplates.
Be sure to customize the indexes, TTL, and partitioning to fit your deployment.
Column names and types must be the same to preserve compatibility with the exporter's INSERT statements.
As long as the column names/types match the INSERT statement, you can create whatever kind of table you want.
See ClickHouse's LogHouse as an example of this flexibility.
Upgrading existing tables
Sometimes new columns are added to the exporter in a backwards compatible way.
The exporter runs a DESC TABLE command on startup to determine which of these new columns are available on the table schema.
If you already have tables created by a previous version of the exporter, you will need to add these new columns manually.
Here is an example of a command you can use to update your existing table (adjust database and table names as needed):
ALTER TABLE otel.otel_logs ADD COLUMN IF NOT EXISTS EventName String CODEC(ZSTD(1));To find the newest columns available check the internal/sqltemplates folder.
The CREATE TABLE statements will always have the latest columns.
In some cases the table changes will not be backwards compatible. Be sure to check the changelog for breaking changes before upgrading your collector.
Optional table upgrades
As mentioned in the previous section, the exporter is able to detect which columns are present on the schema for backwards compatibility.
Here are some columns you can add to your table to update the schema:
-- EventName
ALTER TABLE otel.otel_logs ADD COLUMN IF NOT EXISTS EventName String CODEC(ZSTD(1));
-- JSON tables only. These 3 columns are part of one feature, you must add all 3 at once.
ALTER TABLE otel.otel_logs
ADD COLUMN IF NOT EXISTS ResourceAttributesKeys Array(LowCardinality(String)) CODEC(ZSTD(1)),
ADD COLUMN IF NOT EXISTS ScopeAttributesKeys Array(LowCardinality(String)) CODEC(ZSTD(1)),
ADD COLUMN IF NOT EXISTS LogAttributesKeys Array(LowCardinality(String)) CODEC(ZSTD(1)),
-- Optional indices
ADD INDEX IF NOT EXISTS idx_res_attr_keys ResourceAttributesKeys TYPE bloom_filter(0.01) GRANULARITY 1,
ADD INDEX IF NOT EXISTS idx_scope_attr_keys ScopeAttributesKeys TYPE bloom_filter(0.01) GRANULARITY 1,
ADD INDEX IF NOT EXISTS idx_log_attr_keys LogAttributesKeys TYPE bloom_filter(0.01) GRANULARITY 1;
-- JSON tables only. These 2 columns are part of one feature, you must add all 2 at once.
ALTER TABLE otel.otel_traces
ADD COLUMN IF NOT EXISTS ResourceAttributesKeys Array(LowCardinality(String)) CODEC(ZSTD(1)),
ADD COLUMN IF NOT EXISTS SpanAttributesKeys Array(LowCardinality(String)) CODEC(ZSTD(1)),
-- Optional indices
ADD INDEX IF NOT EXISTS idx_res_attr_keys ResourceAttributesKeys TYPE bloom_filter(0.01) GRANULARITY 1,
ADD INDEX IF NOT EXISTS idx_span_attr_keys SpanAttributesKeys TYPE bloom_filter(0.01) GRANULARITY 1;Example Config
This example shows how to configure the exporter to send data to a ClickHouse server.
It uses the native protocol without TLS. The exporter will create the database and tables if they don't exist.
The data is stored for 72 hours (3 days).
receivers:
examplereceiver:
exporters:
clickhouse:
endpoint: tcp://127.0.0.1:9000?dial_timeout=10s
database: otel
async_insert: true
ttl: 72h
compress: lz4
create_schema: true
logs_table_name: otel_logs
traces_table_name: otel_traces
timeout: 5s
metrics_tables:
gauge:
name: "otel_metrics_gauge"
sum:
name: "otel_metrics_sum"
summary:
name: "otel_metrics_summary"
histogram:
name: "otel_metrics_histogram"
exponential_histogram:
name: "otel_metrics_exp_histogram"
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
# cluster_name: my_cluster
# database_engine:
# name: Replicated
# params: "'/clickhouse/databases/otel'"
# table_engine:
# name: ReplicatedMergeTree
# params:
service:
pipelines:
logs:
receivers: [ examplereceiver ]
exporters: [ clickhouse ]Experimental JSON support
JSON column types can be enabled per-exporter using the json config option:
exporters:
clickhouse:
endpoint: clickhouse://localhost:9000?enable_json_type=1
json: truePreviously, the clickhouse.json feature gate was used to enable JSON for all
ClickHouse exporter instances. This feature gate is now deprecated. Use the json
config option instead, which allows per-pipeline control.
You may also need to add enable_json_type=1 to your endpoint or connection_params.
DDL has been updated, but feel free to tune the schema as needed.
DDL can be found in the internal/sqltemplates package.
All Map columns have been replaced with JSON.
ClickHouse v25+ is recommended for reliable JSON support.
Contributing
Before contributing, review the contribution guidelines in CONTRIBUTING.md.
Integration tests
Integration tests can be run with the following command (includes unit tests):
go test -tags integrationNote: Make sure integration tests pass after making changes to SQL.
Overview (`exporter/coralogixexporter/README.md`)
Coralogix Exporter
| Status | |
|---|---|
| Stability | alpha: profiles |
| beta: traces, metrics, logs | |
| Distributions | contrib |
| Warnings | Authentication issues in v0.127.0 |
| Issues | |
| Code coverage | |
| Code Owners | @povilasv, @iblancasa, @douglascamata |
The Coralogix exporter sends traces, metrics and logs to Coralogix.
Please review the Collector's security
documentation,
which contains recommendations on securing sensitive information such as the
API key required by this exporter.
Configuration
Example configuration:
exporters:
coralogix:
# The Coralogix domain
domain: "coralogix.com"
# Your Coralogix private key is sensitive
private_key: "xxx"
# (Optional) Protocol to use for communication: "grpc" (default) or "http"
protocol: "grpc"
# (Optional) Ordered list of Resource attributes that are used for Coralogix
# AppName and SubSystem values. The first non-empty Resource attribute is used.
# Example: application_name_attributes: ["k8s.namespace.name", "service.namespace"]
# Example: subsystem_name_attributes: ["k8s.deployment.name", "k8s.daemonset.name", "service.name"]
application_name_attributes:
- "service.namespace"
subsystem_name_attributes:
- "service.name"
# Traces, Metrics and Logs emitted by this OpenTelemetry exporter
# are tagged in Coralogix with the default application and subsystem constants.
application_name: "MyBusinessEnvironment"
subsystem_name: "MyBusinessSystem"
# (Optional) Configure the sending queue for batching capabilities
sending_queue:
sizer: bytes
batch:
min_size: 4194304
max_size: 8388608
# (Optional) Timeout is the timeout for every attempt to send data to the backend.
timeout: 30s
# (Optional) Use AWS PrivateLink for private connectivity. When true, data is sent to
# ingress.private.<domain>. See "Coralogix's Domain" section below for details.
# private_link: trueTransport Protocol
The Coralogix exporter supports two transport protocols:
- gRPC (default): Uses gRPC for efficient binary communication
- HTTP: Uses HTTP with protobuf encoding, useful for proxy support or environments where gRPC is restricted
To use HTTP protocol:
exporters:
coralogix:
protocol: "http"
domain: "coralogix.com"Using HTTP Protocol with Proxy
When using HTTP protocol, you can configure proxy settings:
exporters:
coralogix:
protocol: "http"
domain: "coralogix.com"
private_key: "xxx"
application_name: "MyApp"
subsystem_name: "MySubsystem"
domain_settings:
proxy_url: "http://proxy.example.com:8080"
timeout: 30sNotes:
- Proxy support (
proxy_url) is only available when using the HTTP protocol. gRPC protocol does not support this setting. - Signal-specific settings (logs, traces, metrics) take precedence over
domain_settings. - The profiles signal is not supported when using HTTP protocol. Use gRPC protocol (default) if you need to send profiles data.
### Compression
By default, the Coralogix exporter uses gzip compression. Alternatively, you can use zstd compression, for example:
```yaml
exporters:
coralogix:
domain_settings:
compression: "zstd"v0.76.0 Coralogix Domain
Since v0.76.0 you can specify Coralogix domain in the configuration file instead of specifying different endpoints for traces, metrics and logs. For example, the configuration below, can be replaced with domain field:
Old configuration:
exporters:
coralogix:
traces:
endpoint: "ingress.coralogix.com:443"
metrics:
endpoint: "ingress.coralogix.com:443"
logs:
endpoint: "ingress.coralogix.com:443"New configuration with domain field:
exporters:
coralogix:
domain: "coralogix.com"Coralogix's Domain
Depending on your region and, you might need to use a different domain. For an up-to-date list of domains, please refer to the official Coralogix's Domain documentation.
Additionally, Coralogix supports AWS PrivateLink, which provides private connectivity between virtual private clouds (VPCs), supported AWS services, and your on-premises networks without exposing your traffic to the public internet. For an up-to-date list of AWS PrivateLink domains, please refer to Coralogix's official AWS PrivateLink documentation.
To automatically use the PrivateLink endpoint that corresponds to the configured domain, you can set the private_link configuration field to true. For example:
exporters:
coralogix:
domain: "eu2.coralogix.com"
private_link: trueApplication and SubSystem attributes
v0.62.0 release of OpenTelemetry Collector allows you to map Application name and Subsystem name to Resource attributes.
You need to set application_name_attributes and subsystem_name_attributes fields with a list of potential Resource attributes for the AppName and Subsystem values. The first not-empty Resource attribute is going to be used. If multiple resource attributes are available, the order of the attributes in the list determines their priority.
Kubernetes attributes
When using OpenTelemetry Collector with k8sattribute processor, you can use attributes coming from Kubernetes, such as k8s.namespace.name or k8s.deployment.name. The following example shows recommended list of attributes:
exporters:
coralogix:
domain: "coralogix.com"
application_name_attributes:
- "k8s.namespace.name"
- "service.namespace"
subsystem_name_attributes:
- "k8s.deployment.name"
- "k8s.statefulset.name"
- "k8s.daemonset.name"
- "k8s.cronjob.name"
- "service.name"Host Attributes
OpenTelemetry Collector Resource Detection processor can discover Host Resource attributes, such as host.name and provide Resource attributes using environment variables, which can be used for setting AppName and SubSystem fields in Coralogix.
Example:
processors:
resource_detection/system:
detectors: ["system", "env"]
system:
hostname_sources: ["os"]And setting environment variable such as:
OTEL_RESOURCE_ATTRIBUTES="env=production"You can configure Coralogix Exporter:
exporters:
coralogix:
domain: "coralogix.com"
application_name_attributes:
- "env"
subsystem_name_attributes:
- "host.name"EC2 Attributes
OpenTelemetry Collector Resource Detection processor can discover EC2 Resource attributes, such as EC2 tags as resource attributes.
Example:
processors:
resource_detection/ec2:
detectors: ["ec2"]
ec2:
# A list of regex's to match tag keys to add as resource attributes can be specified
tags:
- ^ec2.tag.name$
- ^ec2.tag.subsystem$NOTE: In order to fetch EC2 tags, the IAM role assigned to the EC2 instance must have a policy that includes the ec2:DescribeTags permission.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:DescribeTags",
"Resource": "*"
}
]
}You can configure Coralogix Exporter:
exporters:
coralogix:
domain: "coralogix.com"
application_name_attributes:
- "ec2.tag.name"
subsystem_name_attributes:
- "ec2.tag.subsystem"Custom Attributes
You can combine and create custom Resource attributes using transform processor. For example:
processors:
transform:
error_mode: ignore
log_statements:
- context: resource
statements:
- set(attributes["applicationName"], Concat(["development-environment", attributes["k8s.namespace.name"]], "-"))Then you can use the custom Resource attribute in Coralogix exporter:
exporters:
coralogix:
domain: "coralogix.com"
application_name_attributes:
- "applicationName"
subsystem_name_attributes:
- "host.name"Exporting to multiple teams based on attributes
You can export the signals based on your business logic (attributes) to different Coralogix teams. To achieve this, you'll need to use the filter processor and setup one pipeline per team. You can setup your filter processors as following (example with metrics):
processors:
filter/teamA:
metrics:
datapoint:
- 'attributes["your_label"] != "teamA"'
filter/teamB:
metrics:
datapoint:
- 'attributes["your_label"] != "teamB"'This configuration ensures separate processor per each team. Any data points without an attribute for a particular team will be dropped from exporting.
Secondly, set up an individual exporter per each team:
exporters:
coralogix/teamA:
metrics:
endpoint: "otel-metrics.coralogix.com:443"
private_key: <private_key_for_teamA>
application_name: "MyBusinessEnvironment"
subsystem_name: "MyBusinessSystem"
coralogix/teamB:
metrics:
endpoint: "otel-metrics.coralogix.com:443"
private_key: <private_key_for_teamB>
application_name: "MyBusinessEnvironment"
subsystem_name: "MyBusinessSystem"Finally, join each processor and exporter (and any other components you wish) in the pipelines. Here is an example with a Prometheus receiver:
service:
pipelines:
metrics/1:
receivers: [prometheus]
processors: [filter/teamA]
exporters: [coralogix/teamA]
metrics/2:
receivers: [prometheus]
processors: [filter/teamB]
exporters: [coralogix/teamB]Custom application and subsystem name
You can pass custom application and subsystem name via the following resource attributes:
cx.subsystem.namecx.application.name
For example:
receivers:
file_log/nginx:
include:
- '/tmp/tmp.log'
include_file_path: true
include_file_name: false
start_at: end
resource:
cx.subsystem.name: nginx
file_log/access-log:
include:
- '/tmp/access.log'
include_file_path: true
include_file_name: false
resource:
cx.subsystem.name: access-log
exporters:
coralogix:
domain: 'coralogix.com'
private_key: "XXX"
application_name: 'app_name'
timeout: 30s
service:
pipelines:
logs:
receivers: [file_log/nginx, file_log/access-log]
exporters: [coralogix]Warnings
Authentication issues in v0.127.0
Version 0.127.0 introduced a regression in the Coralogix exporter. As a consequence, it requires an updated authentication configuration to ensure proper telemetry data transmission to Coralogix. If you're using this version, please modify your configuration to include the authentication headers as shown below:
coralogix:
traces:
headers:
"Authorization": "Bearer ${env:CORALOGIX_PRIVATE_KEY}"
metrics:
headers:
"Authorization": "Bearer ${env:CORALOGIX_PRIVATE_KEY}"
logs:
headers:
"Authorization": "Bearer ${env:CORALOGIX_PRIVATE_KEY}"This configuration ensures proper authentication with the Coralogix backend.
Prior versions (v0.126.0 and earlier) and subsequent versions (v0.128.0 and later) are not affected by this authentication issue.
Need help?
Our world-class customer success team is available 24/7 to walk you through the setup for this exporter and answer any questions that may come up.
Feel free to reach out to us via our in-app chat or by sending us an email to [email protected].
Overview (`exporter/datadogexporter/README.md`)
Datadog Exporter
| Status | |
|---|---|
| Stability | beta: traces, metrics, logs |
| Unsupported Platforms | aix, freebsd, solaris |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @mx-psi, @dineshg13, @liustanley, @songy23, @mackjmr, @jade-guiton-dd, @IbraheemA |
| Emeritus | @gbbr, @jackgopack4, @ankitpatel96 |
Please review the Collector's security documentation, which contains recommendations on securing sensitive information such as the API key required by this exporter.
The Datadog Exporter now skips APM stats computation by default. It is recommended to only use the Datadog Connector in order to compute APM stats.
To temporarily revert to the previous behavior, disable theexporter.datadogexporter.DisableAPMStatsfeature gate. Example:otelcol --config=config.yaml --feature-gates=-exporter.datadogexporter.DisableAPMStats
Find the full configs of Datadog exporter and their usage in collector.yaml. More example configs can be found in the official documentation.
FAQs
Why am I getting errors 413 - Request Entity Too Large, how do I fix it?
This error indicates the payload size sent by the Datadog exporter exceeds the size limit (see previous examples https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/16834, https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/17566).
This is usually caused by the pipeline batching too many telemetry data before sending to the Datadog API intake. To fix that, prefer using the Datadog exporter sending_queue::batch section instead of the batch processor:
exporters:
datadog:
api:
key: ${env:DD_API_KEY}
sending_queue:
batch:
min_size: 10
max_size: 100
flush_timeout: 10sIf you are using the batch processor instead, try lowering send_batch_size and send_batch_max_size in your config. You might want to have a separate batch processor dedicated for datadog exporter if other exporters expect a larger batch size, e.g.
processors:
batch: # To be used by other exporters
timeout: 1s
# Default value for send_batch_size is 8192
batch/datadog:
send_batch_max_size: 100
send_batch_size: 10
timeout: 10s
...
service:
pipelines:
metrics:
receivers: ...
processors: [batch/datadog]
exporters: [datadog]The exact values for send_batch_size and send_batch_max_size depends on your specific workload. Also note that, Datadog intake has different payload size limits for the 3 signal types:
- Trace intake: 3.2MB
- Log intake: https://docs.datadoghq.com/api/latest/logs/
- Metrics V2 intake: https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
Fall back to the Zorkian metric client with feature gate
Support for Zorkian is now deprecated, please use the metrics export serializer. See https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/tag/v0.122.0 and #37930 for more info about Metrics Export Serializer.
Remap OTelβs service.name attribute to service for logs
NOTE this workaround is only needed when feature gate exporter.datadogexporter.UseLogsAgentExporter is disabled. This feature gate is enabled by default starting v0.108.0.
For Datadog Exporter versions 0.83.0 - v0.107.0, the service field of OTel logs is populated as OTel semantic convention service.name. However, service.name is not one of the default service attributes in Datadogβs log preprocessing.
To get the service field correctly populated in your logs, you can specify service.name to be the source of a logβs service by setting a log service remapper processor.
How to add custom log source
In order to add a custom source to your OTLP logs, set resource attribute datadog.log.source. This feature requires exporter.datadogexporter.UseLogsAgentExporter feature flag to be enabled (now enabled by default).
Example:
processors:
transform/logs:
log_statements:
- context: resource
statements:
- set(attributes["datadog.log.source"], "otel")My Collector K8s pod is getting rebooted on startup when I don't manually set a hostname under `exporters::datadog::hostname`
This is due to a bug with underlying hostname detection blocking the health_check extension from responding to liveness/readiness probes on startup. To fix, either set hostname_detection_timeout to be less than the pod/daemonset livenessProbe: failureThreshold * periodSeconds so that the timeout for hostname detection on startup takes less time than the control plane waits before restarting the pod, or leave hostname_detection_timeout at the default 25s value and double-check the livenessProbe and readinessProbe settings and ensure that the control plane will in fact wait long enough for startup to complete before restarting the pod.
Hostname detection is currently required to initialize the Datadog Exporter, unless a hostname is specified manually under hostname.
Overview (`exporter/datasetexporter/README.md`)
DataSet Exporter
| Status | |
|---|---|
| Stability | alpha: logs, traces |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @atoulme, @martin-majlis-s1 |
| Emeritus | @zdaratom-s1, @tomaz-s1 |
This exporter sends logs to DataSet.
See the Getting Started guide.
Configuration
Required Settings
dataset_url(no default): The URL of the DataSet API that ingests the data. Most likely https://app.scalyr.com.api_key(no default): The "Log Write" API Key required to use API. Instructions how to get API key.
If you do not want to specify api_key in the file, you can use the builtin functionality and use api_key: ${env:DATASET_API_KEY}.
Server Host Settings
Specifying the server host is crucial for ensuring the correct functionality of DataSet.
DataSet expects the server host value to be provided in the serverHost attribute.
If the server host value is stored in a different attribute, you can use the resourceprocessor or attributesprocessor to copy it into the serverHost attribute.
You can also utilize the server_host settings (described below) to populate the serverHost attribute with different values.
The process of populating the serverHost attribute works as follows:
- If the
serverHostattribute is specified and not empty in the log or trace, then it is used. - If the
serverHostattribute is specified and not empty in the resource, then it is used. - If the
host.nameattribute is specified and not empty in the resource, then it is used. - If the
server_host.server_hostsetting is specified and not empty, then it is used. - If
server_host.use_host_namesetting is set totrue, thehostnameof the node is used.
Make sure to provide the appropriate server host value in the serverHost attribute to ensure the proper functionality of DataSet and accurate handling of events.
Optional Settings
debug(default = false): Addssession_keyto the server fields. It's useful for debugging throughput issues.buffer:max_lifetime(default = 5s): The maximum delay between sending batches from the same session.purge_older_than(default = 30s): The maximum delay between receiving data for the same session after which resources associated with it are purged.group_by(default = []): The list of attributes based on which events should be grouped. They are moved from the event attributes to the session info and shown as server fields in the UI.retry_initial_interval(default = 5s): Time to wait after the first failure before retrying.retry_max_interval(default = 30s): Is the upper bound on backoff.retry_max_elapsed_time(default = 300s): Is the maximum amount of time spent trying to send a buffer.retry_shutdown_timeout(default = 30s): The maximum time for which it will try to send data to the DataSet during shutdown. This value should be shorter than container's grace period.max_parallel_outgoing(default = 100): The maximum number of parallel outgoing requests.
logs:export_resource_info_on_event(default = false): Include LogRecord resource information (if available) on the DataSet event.export_resource_prefix(default = 'resource.attributes.'): A prefix string for the resource, ifexport_resource_info_on_eventis enabled.export_scope_info_on_event(default = true): Include LogRecord scope information (if available) on the DataSet event.export_scope_prefix(default = 'scope.attributes.'): A prefix string for the scope, ifexport_scope_info_on_eventis enabled.export_separator(default = '.'): The separator to add between keys when flattening nested structures (maps, arrays).export_distinguishing_suffix(default = '_'): A suffix string to resolve naming collisions when flattening.decompose_complex_message_field(default = false): Decompose complex body / message field types (e.g. a maps, arrays) into separate fields.decomposed_complex_message_prefix(default = 'body.map.'): A prefix string to use when a complex message is decomposed.
traces:export_separator(default = '.'): The separator to add between keys when flattening nested structures (maps, arrays).export_distinguishing_suffix(default = '_'): A suffix string to resolve naming collisions when flattening.
server_host:server_host(default = ''): Specifies the server host to be used for the events.use_hostname(default = true): Determines whether thehostnameof the node should be used as the server host for the events. When set totrue, the node'shostnameis automatically used.
retry_on_failure: See retry_on_failuresending_queue: See sending_queuetimeout: See timeout
Attributes
Enabled attributes are exported in the order:
- Log properties
- Body
- Resource attributes
- Scope attributes
- Log attributes
If there is a name conflict, the export_distinguishing_suffix value is appended to the later attribute's name. If the export_distinguishing_suffix value is an empty string, then the value from the last attribute is used.
Example
Example LogRecord:
Log
- body:
- b: 1
- x: "b"
- resource:
- r: 2
- x: "r"
- scope:
- s: 3
- x: "s"
- attribute:
- a: 4
- x: "a"
- map:
- m1: 5
- m2: 6Then the event will look like:
- Default settings for
logs:- Event:text
- message: "{\"b\": 1, \"x\": \"b\"}" - scope.attributes.s: 3 - scope.attributes.x: "s" - a: 4 - x: "a" - map.m1: 5 - map.m2: 6
- Event:
- Everything enabled:
- Configuration:text
logs: export_resource_info_on_event: true export_resource_prefix: "r." export_scope_info_on_event: true export_scope_prefix: "s." decompose_complex_message_field: true decomposed_complex_message_prefix: "m." export_separator: "-" export_distinguishing_suffix: "_" - Event:text
- message: "{\"b\": 1, \"x\": \"b\"}" - m.b: 1 - m.x: "b" - r.r: 2 - r.x: "r" - s.s: 3 - s.x: "s" - a: 4 - x: "a" - map-m1: 5 - map-m2: 6
- Configuration:
- Everything enabled, prefixes are empty strings:
- Configuration:text
logs: export_resource_info_on_event: true export_resource_prefix: "" export_scope_info_on_event: true export_scope_prefix: "" decompose_complex_message_field: true decomposed_complex_message_prefix: "" export_separator: "-" export_distinguishing_suffix: "_" - Event:text
- message: "{\"b\": 1, \"x\": \"b\"}" - b: 1 - x: "b" - r: 2 - x_: "r" - s: 3 - x__: "s" - a: 4 - x___: "a" - map-m1: 5 - map-m2: 6
- Configuration:
- Everything enabled, prefixes are empty strings, suffix is empty string:
- Configuration:text
logs: export_resource_info_on_event: true export_resource_prefix: "" export_scope_info_on_event: true export_scope_prefix: "" decompose_complex_message_field: true decomposed_complex_message_prefix: "" export_separator: "-" export_distinguishing_suffix: "" - Event:text
- message: "{\"b\": 1, \"x\": \"b\"}" - b: 1 - r: 2 - s: 3 - a: 4 - x: "a" - map-m1: 5 - map-m2: 6
- Configuration:
Field names can have . dots, _ underscores, and - hyphens. You must escape slashes in Search and PowerQueries. For example, search the field name app.kubernetes.io/component as app.kubernetes.io\/component.
Example
/* Detailed source-code truncated for AI context efficiency. */Handling `serverHost` Attribute
Based on the given configuration and scenarios, here's the expected behavior:
- Resource:
{'node_id:' 'node-pay-01', 'host.name': 'host-pay-01'}, Log:{'container_id': 'cont-pay-01'}, Env:SERVER_HOST='server-pay-01', Hostname:ip-172-31-27-19- Since the attribute
container_idis set,attributesprocessorwill copy this value to theserverHost. - Used
serverHostwill becont-pay-01.
- Since the attribute
- Resource:
{'node_id': 'node-pay-01', 'host.name': 'host-pay-01'}, Log:{'attribute.foo': 'Bar'}, Env:SERVER_HOST='server-pay-01', Hostname:ip-172-31-27-19- Since the resource attribute
node_idis set,resourceprocessorwill copy this value to theserverHost. - Used
serverHostwill benode-pay-01.
- Since the resource attribute
- Resource:
{'host.name': 'host-pay-01'}, Log:{'attribute.foo': 'Bar'}, Env:SERVER_HOST='server-pay-01', Hostname:ip-172-31-27-19- Since the resource attribute
host.nameis set, it will be used. - Used
serverHostwill behost-pay-01.
- Since the resource attribute
- Resource:
{}, Log:{'attribute.foo': 'Bar'}, Env:SERVER_HOST='server-pay-01', Hostname:ip-172-31-27-19- Since the attribute
container_idis not set, the value from the environmental variableSERVER_HOSTwill be copied to theserverHost. - Used
serverHostwill beserver-pay-01.
- Since the attribute
- Resource:
{}, Log:{'attribute.foo': 'Bar'}, Env:SERVER_HOST='', Hostname:ip-172-31-27-19- Since the attribute
container_idis not set and the environmental variableSERVER_HOSTis empty, thehostnameof the node (ip-172-31-27-19) will be used as the fallback value forserverHost. - Used
serverHostwill beip-172-31-27-19.
- Since the attribute
Metrics
To enable metrics you have to:
- Run collector with enabled feature gate
telemetry.useOtelForInternalMetrics. This can be done by executing it with one additional parameter ---feature-gates=telemetry.useOtelForInternalMetrics. - Enable metrics scraping as part of the configuration and add receiver into services:yaml
receivers: prometheus: config: scrape_configs: - job_name: 'otel-collector' scrape_interval: 5s static_configs: - targets: ['0.0.0.0:8888'] ... service: pipelines: metrics: # add prometheus among metrics receivers receivers: [prometheus] exporters: [otlp_http/prometheus, debug]
Available Metrics
Available metrics contain dataset in their name. There are counters related to the
number of processed events (events), buffers (buffer), sessions (sessions), and transferred bytes (bytes).
There are also histograms related to response times (responseTime) and payload size (payloadSize).
There are several counters related to events/buffers:
enqueued- the number of received entitiesprocessed- the number of entities that were accepted by the next layerdropped- the number of entities that were not accepted by the next layerbroken- the number of entities that were somehow corrupted during processing (should be 0)
The number of entities, that are still in the queue can be computed as enqueued - (processed + dropped + broken).
Overview (`exporter/dorisexporter/README.md`)
Apache Doris Exporter
| Status | |
|---|---|
| Stability | alpha: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @joker-star-l |
| Emeritus | @atoulme |
This exporter supports sending traces, metrics, and logs data to Apache Doris (version >= 2.1.1).
Configuration
The following configuration options are supported:
endpointThe http stream load address.database(default = otel) The database name.usernameThe authentication username.passwordThe authentication password.tablelogs(default = otel_logs) The table name for logs.traces(default = otel_traces) The table name for traces.metrics(default = otel_metrics) The table name for metrics.
create_schema(default = true) Whether databases and tables are created automatically in doris.mysql_endpointThe mysql protocol address of doris. Only use to create the schema; ignored ifcreate_schemais false.history_days(default = 0) Data older than these days will be deleted; ignored ifcreate_schemais false. If set to 0, historical data will not be deleted.create_history_days(default = 0) The number of days in the history partition that was created when the table was created; ignored ifcreate_schemais false. Ifhistory_daysis not 0,create_history_daysneeds to be less than or equal tohistory_days.replication_num(default = 1) The number of replicas of the table; ignored ifcreate_schemais false.timezone(default is the time zone of the opentelemetry collector if IANA Time Zone Database is found, else is UTC) The time zone of doris, e.g. Asia/Shanghai.log_response(default = false) Whether to log the response of doris stream load.label_prefix(default = open_telemetry) the prefix of the label in doris stream load. The final generated label is {label_prefix}{db}{table}{yyyyMMddHHmmss}{uuid}.headers(default is empty map) The headers of doris stream load. Details: header parameters and group commit.log_progress_interval(default = 10) The interval, in seconds, between statistical logs. When it is less than or equal to 0, the statistical log is not printed.sending_queuedetails hereenabled(default = true)num_consumers(default = 10) Number of consumers that dequeue batches; ignored ifenabledis false.queue_size(default = 1000) Maximum number of batches kept in memory before dropping; ignored ifenabledis false.
retry_on_failuredetails hereenabled(default = true)initial_interval(default = 5s) Time to wait after the first failure before retrying; ignored ifenabledis false.max_interval(default = 30s) The upper bound on backoff; ignored ifenabledis false.max_elapsed_time(default = 300s) The maximum amount of time spent trying to send a batch; ignored ifenabledis false. If set to 0, the retries are never stopped.
The Doris exporter supports common HTTP Configuration Settings, except for compression (all requests are uncompressed). As a consequence of supporting confighttp, the Doris exporter also supports common TLS Configuration Settings.
The Doris exporter sets timeout (HTTP request timeout) to 60s by default. All other defaults are as defined by confighttp.
Example:
exporters:
doris:
endpoint: http://localhost:8030
database: otel
username: admin
password: admin
table:
logs: otel_logs
traces: otel_traces
metrics: otel_metrics
create_schema: true
mysql_endpoint: localhost:9030
history_days: 0
create_history_days: 0
replication_num: 1
timezone: Asia/Shanghai
timeout: 5s
sending_queue:
enabled: true
num_consumers: 10
queue_size: 1000
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300sNotes
Time Zone
The Doris exporter uses IANA Time Zone Database (known as tzdata) to handle time zones, so make sure tzdata is on your system.
For example, when you use docker, you should add option
-v your/path/to/tzdata:/usr/share/zoneinfowhen running the container.Traces schema
Besides the span columns, the traces table has an
is_rootcolumn (1 for spans without a parent) and two
synchronous materialized views:_servicesgroups service, instance and span name, answering catalog queries such asSELECT DISTINCT service_name._summaryaggregates each trace bytrace_idand day (s_start_time,s_end_time,s_span_count,s_error_count,s_first_root= earliest root span as<timestamp>|<service_name>|,s_max_span_duration). Trace-list queries that group bytrace_id, date_trunc(timestamp, 'day')are rewritten to this view by Doris.
Doris builds a synchronous view in the background and rejects a second one while the first is building,
so the exporter creates them one after the other. Tables created by older versions are not altered.
Overview (`exporter/elasticsearchexporter/README.md`)
Elasticsearch Exporter
| Status | |
|---|---|
| Stability | development: profiles |
| beta: traces, logs, metrics | |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @JaredTan95, @blakerouse, @carsonip, @lahsivjar |
This exporter supports sending logs, metrics, traces and profiles to Elasticsearch.
The Exporter is API-compatible with Elasticsearch 7.17.x, 8.x, and 9.x. Certain features of the exporter,
such as the otel mapping mode, may require newer versions of Elasticsearch. Limited effort will
be made to support EOL versions of Elasticsearch -- see https://www.elastic.co/support/eol.
Configuration options
Exactly one of the following settings is required:
endpoint(no default): The target Elasticsearch URL to which data will be sent
(e.g.https://elasticsearch:9200)endpoints(no default): A list of Elasticsearch URLs to which data will be sent,
attempted in round-robin ordercloudid(no default): The Elastic Cloud ID
of the Elastic Cloud Cluster to which data will be sent (e.g.foo:YmFyLmNsb3VkLmVzLmlvJGFiYzEyMyRkZWY0NTY=)
When the above settings are missing, endpoints will default to the
comma-separated ELASTICSEARCH_URL environment variable.
Elasticsearch credentials may be configured via Authentication configuration settings.
As a shortcut, the following settings are also supported:
user(optional): Username used for HTTP Basic Authentication.password(optional): Password used for HTTP Basic Authentication.api_key(optional): Elasticsearch API Key in "encoded" format (e.g.VFR2WU41VUJIbG9SbGJUdVFrMFk6NVVhVDE3SDlSQS0wM1Rxb24xdXFldw==).
Example:
exporters:
elasticsearch:
endpoint: https://elastic.example.com:9200
auth:
authenticator: basicauth
extensions:
basicauth:
client_auth:
username: elastic
password: changeme
Β·Β·Β·Β·Β·Β·
service:
extensions: [basicauth]
pipelines:
logs:
receivers: [otlp]
exporters: [elasticsearch]
traces:
receivers: [otlp]
exporters: [elasticsearch]Advanced configuration
HTTP settings
The Elasticsearch exporter supports common HTTP Configuration Settings. Gzip compression is enabled by default. To disable compression, set compression to none. Default Compression Level is set to 1 (gzip.BestSpeed).
As a consequence of supporting confighttp, the Elasticsearch exporter also supports common TLS Configuration Settings.
timeout: 90sThe Elasticsearch exporter sets timeout (HTTP request timeout) to 90s by default.
Note that this is per request and is independent between HTTP request retries.
All other defaults are as defined by confighttp.
Queuing and batching
The Elasticsearch exporter supports the common sending_queue settings which
supports both queueing and batching. The default sending queue is configured to do async batching
with the following configuration:
sending_queue:
enabled: true
sizer: requests
num_consumers: 10
queue_size: 10
batch:
flush_timeout: 10s
min_size: 1e+6 // 1MB
max_size: 5e+6 // 5MB
sizer: bytesThe default configurations are chosen to be closer to the defaults with the exporter's previous inbuilt batching feature. The exporterhelper documentation provides more details on the sending_queue settings.
Elasticsearch document routing
Documents are statically or dynamically routed to the target index / data stream in the following order. The first routing mode that applies will be used.
- "Static mode": Route to
logs_indexfor log records,metrics_indexfor data points andtraces_indexfor spans, if these configs are not empty respectively. [^3] - "Dynamic - Index attribute mode": Route to index name specified in
elasticsearch.indexattribute (precedence: log record / data point / span attribute > scope attribute > resource attribute) if the attribute exists. [^3] - "Dynamic - Data stream routing mode": Route to data stream constructed from
${data_stream.type}-${data_stream.dataset}-${data_stream.namespace},
wheredata_stream.typeislogsfor log records,metricsfor data points, andtracesfor spans, and is static. [^3]
In a special case withmapping::mode: bodymap,data_stream.typefield (valid values:logs,metrics,traces,profiles,synthetics) can be dynamically set from attributes.
The resulting documents will contain the correspondingdata_stream.*fields, see restrictions applied to Data Stream Fields.data_stream.datasetordata_stream.namespacein attributes (precedence: log record / data point / span attribute > scope attribute > resource attribute)Otherwise, if a scope attribute with the name
encoding.formatexists and contains a string value,data_stream.datasetwill be set to this value.Note that while enabled by default, this behaviour is considered experimental. Some encoding extensions set this field (e.g. awslogsencodingextension), but it is not yet part of Semantic Conventions. There is the potential that the name of this routing field evolves as the discussion progresses in SemConv.
Otherwise, if scope name matches regex
/receiver/(\w*receiver)or/connector/(\w*connector),data_stream.datasetwill be capture group #1Otherwise,
data_stream.datasetfalls back togenericanddata_stream.namespacefalls back todefault.
[^3]: See additional handling in Document routing exceptions for OTel data mode
This can be customised through the following settings:
logs_index(optional): The index or data stream name to publish logs (and span events in OTel mapping mode) to.logs_indexshould be empty unless all logs should be sent to the same index.logs_dynamic_index(optional): uses resource, scope, or log record attributes to dynamically construct index name.enabled(DEPRECATED): No-op. Documents are now always routed dynamically unlesslogs_indexis not empty. Will be removed in a future version.
metrics_index(optional): The index or data stream name to publish metrics to.metrics_indexshould be empty unless all metrics should be sent to the same index. Note that metrics support is currently in development.metrics_dynamic_index(optional): uses resource, scope or data point attributes to dynamically construct index name.enabled(DEPRECATED): No-op. Documents are now always routed dynamically unlessmetrics_indexis not empty. Will be removed in a future version.
traces_index(optional): The index or data stream name to publish traces to.traces_indexshould be empty unless all traces should be sent to the same index.traces_dynamic_index(optional): uses resource, scope, or span attributes to dynamically construct index name.enabled(DEPRECATED): No-op. Documents are now always routed dynamically unlesstraces_indexis not empty. Will be removed in a future version.
logstash_format(optional): Logstash format compatibility. Logs, metrics and traces can be written into an index in Logstash format.enabled(default=false): Enable/disable Logstash format compatibility. Whenlogstash_format::enabledistrue, the index name is composed using the above dynamic routing rules as prefix and the date as suffix,
e.g: If the computed index name islogs-generic-default, the resulting index will belogs-generic-default-YYYY.MM.DD.
The last string appended belongs to the date when the data is being generated.prefix_separator(default=-): Set a separator between logstash_prefix and date.date_format(default=%Y.%m.%d): Time format (based on strftime) to generate the second part of the Index name.
logs_dynamic_id(optional): Dynamically determines the document ID to be used in Elasticsearch based on a log record attribute.enabled(default=false): Enable/Disable dynamic ID for log records. Ifelasticsearch.document_idexists and is not an empty string in the log record attributes, it will be used as the document ID. Otherwise, the document ID will be generated by Elasticsearch. The attributeelasticsearch.document_idis removed from the final document when theotelmapping mode is used. See Setting a document id dynamically.
traces_dynamic_id(optional): Dynamically determines the document ID to be used in Elasticsearch based on a span attribute.enabled(default=false): Enable/Disable dynamic ID for spans. Ifelasticsearch.document_idexists and is not an empty string in the span attributes, it will be used as the document ID. For span events, this only applies when usingotelmapping mode (where span events are stored as separate documents). Otherwise, the document ID will be generated by Elasticsearch. The attributeelasticsearch.document_idis removed from the final document when theotelmapping mode is used. See Setting a document id dynamically.
Document routing exceptions for OTel data mode
In OTel mapping mode (mapping::mode: otel), there is special handling in addition to the above document routing rules in Elasticsearch document routing.
The order to determine the routing mode is the same as Elasticsearch document routing.
- "Static mode": Span events are separate documents routed to
logs_indexif non-empty. - "Dynamic - Index attribute mode": Span events are separate documents routed using attribute
elasticsearch.index(precedence: span event attribute > scope attribute > resource attribute) if the attribute exists. - "Dynamic - Data stream routing mode":
- For all documents,
data_stream.datasetwill always be appended with.otel. - A special case to (3)(1) in Elasticsearch document routing, span events are separate documents that have
data_stream.type: logsand are routed using data stream attributes (precedence: span event attribute > scope attribute > resource attribute)
Elasticsearch document mapping
The Elasticsearch exporter supports several document schemas and preprocessing
behaviours, which may be configured through the following settings:
mapping:mode(DEPRECATED): The mapping mode if supplied via config file is ignored. Use theX-Elastic-Mapping-Modeclient metadata key or theelastic.mapping.modescope attribute instead. If not specified via these methods, the default mapping mode isotel.allowed_modes(defaults to all mapping modes): A list of allowed mapping modes.
Ifotelis included in the list, it is used as the default mapping mode.
Otherwise, the first entry in the list is used as the default.
The mapping mode can be controlled via the client metadata key X-Elastic-Mapping-Mode,
e.g. via HTTP headers, gRPC metadata.
It is possible to restrict which mapping modes may be requested by configuringmapping::allowed_modes, which defaults to all mapping modes. Keep in mind that not all
processors or exporter configurations will maintain client metadata.
The mapping mode can also be controlled via the scope attribute elastic.mapping.mode.
If specified, this takes precedence over the X-Elastic-Mapping-Mode client metadata.
If any scope has an invalid mapping mode, the exporter will reject the entire batch.
The attribute will be excluded from the final document.
Valid mapping modes are:
noneecsotelrawbodymap
See below for a description of each mapping mode.
Migration: Setting mapping mode via scope attribute
Since the mapping::mode config option is deprecated, use the following method to set the mapping mode:
Use scope attribute via transform processor
This approach sets the elastic.mapping.mode scope attribute on the telemetry data.
processors:
transform:
log_statements:
- context: scope
statements:
- set(attributes["elastic.mapping.mode"], "otel")
trace_statements:
- context: scope
statements:
- set(attributes["elastic.mapping.mode"], "otel")
metric_statements:
- context: scope
statements:
- set(attributes["elastic.mapping.mode"], "otel")
exporters:
elasticsearch:
endpoint: https://elasticsearch:9200
service:
pipelines:
logs:
receivers: [otlp]
processors: [transform]
exporters: [elasticsearch][!NOTE]
The scope attributeelastic.mapping.modetakes precedence over theX-Elastic-Mapping-Modeclient metadata.
The attribute will be excluded from the final document sent to Elasticsearch.
[!NOTE]
otelandecsmapping modes require Elasticsearch 8.12 or above[^1].otelmode works best with Elasticsearch 8.16 or above[^2].
[^1]: as OTel and ECS mapping modes rely on the require_data_stream bulk action metadata, available since Elasticsearch 8.12
[^2]: Elasticsearch 8.16 contains a built-in otel-data plugin
OTel mapping mode
The default and recommended "OTel-native" mapping mode.
In otel mapping mode, the Elasticsearch Exporter stores documents in Elastic's preferred
"OTel-native" schema. In this mapping mode, documents use the original attribute names and
closely follows the event structure from the OTLP events.
There is special treatment for the following attributes: data_stream.type, data_stream.dataset,
and data_stream.namespace. Instead of serializing these values under the *attributes.* namespace,
they are put at the root of the document, to conform with the conventions of the data stream naming
scheme that maps these as constant_keyword fields.
data_stream.dataset will always be appended with .otel if dynamic data stream routing mode is active.
Span events are stored in separate documents. They will be routed with data_stream.type set tologs if dynamic data stream routing mode is active.
Attribute elasticsearch.index will be removed from the final document if exists.
| Signal | Supported |
|---|---|
| Logs | :white_check_mark: |
| Traces | :white_check_mark: |
| Metrics | :white_check_mark: |
| Profiles | :white_check_mark: |
ECS mapping mode
[!WARNING]
The ECS mode mapping mode is currently undergoing changes, and its behaviour is unstable.
In ecs mapping mode, the Elasticsearch Exporter maps fields from
OpenTelemetry Semantic Conventions (version 1.22.0) to Elastic Common Schema where possible.
This mode may be used for compatibility with existing dashboards that work with ECS.
| Signal | ecs |
|---|---|
| Logs | :white_check_mark: |
| Traces | :white_check_mark: |
| Metrics | :white_check_mark: |
| Profiles | :no_entry_sign: |
In ECS mapping mode, span events are extracted as separate ECS-formatted log documents following
the APM data stream convention:
- Span events named
exceptionwithexception.typeorexception.messagepresent are routed
tologs-apm.error-<namespace>. - All other span events are routed to
logs-apm.app.<service_name>-<namespace>.
Bodymap mapping mode
[!WARNING]
The Bodymap mode mapping mode is currently undergoing changes, and its behaviour is unstable.
In bodymap mapping mode, the Elasticsearch Exporter supports only logs and will take the "body"
of a log record as the exact content of the Elasticsearch document without any transformation.
This mapping mode is intended for use cases where the client wishes to have complete control over
the Elasticsearch document structure.
| Signal | bodymap |
|---|---|
| Logs | :white_check_mark: |
| Traces | :no_entry_sign: |
| Metrics | :no_entry_sign: |
| Profiles | :no_entry_sign: |
Default (none) mapping mode
In the none mapping mode the Elasticsearch Exporter produces documents with the original
field names of from the OTLP data structures.
| Signal | none |
|---|---|
| Logs | :white_check_mark: |
| Traces | :white_check_mark: |
| Metrics | :no_entry_sign: |
| Profiles | :no_entry_sign: |
Raw mapping mode
The raw mapping mode is identical to none, except for two differences:
- In
nonemode attributes are mapped with anAttributes.prefix,
while inrawmode they are not. - In
nonemode span events are mapped with anEvents.prefix,
while inrawmode they are not.
| Signal | raw |
|---|---|
| Logs | :white_check_mark: |
| Traces | :white_check_mark: |
| Metrics | :no_entry_sign: |
| Profiles | :no_entry_sign: |
Elasticsearch ingest pipeline
Documents may be optionally passed through an Elasticsearch Ingest pipeline prior to indexing.
This can be configured through the following settings:
pipeline(optional): ID of an Elasticsearch Ingest pipeline used for processing documents published by the exporter.logs_dynamic_pipeline(optional): Dynamically determines the ingest pipeline to be used in Elasticsearch based on attributes in the log signal.enabled(default=false): Enable/Disable dynamic pipeline. Ifelasticsearch.ingest_pipelineattribute exists in the log record attributes and is not an empty string, it will be used as the Elasticsearch ingest pipeline. This currently only applies to the log signal. The attributeelasticsearch.ingest_pipelineis removed from the final document when theotelmapping mode is used.
Elasticsearch bulk indexing
The Elasticsearch exporter uses the Elasticsearch Bulk API for indexing documents.
The behaviour of this bulk indexing can be configured with the following settings:
The deprecated num_workers and flush settings have been removed. Existing configurations should use these replacements:
| Removed setting | Replacement |
|---|---|
num_workers |
sending_queue::num_consumers |
flush::interval |
sending_queue::batch::flush_timeout |
flush::bytes |
sending_queue::batch::max_size with sending_queue::batch::sizer set to bytes |
retry: Elasticsearch bulk request retry settingsenabled(default=true): Enable/Disable request retry on error. Failed requests are retried with exponential backoff.max_requests(DEPRECATED, use retry::max_retries instead): Number of HTTP request retries including the initial attempt. If used,retry::max_retrieswill be set tomax_requests - 1.max_retries(default=2): Number of HTTP request retries. To disable retries, setretry::enabledtofalseinstead of settingmax_retriesto0.initial_interval(default=100ms): Initial waiting time if a HTTP request failed.max_interval(default=1m): Max waiting time if a HTTP request failed.retry_on_status(default=[429]): Status codes that trigger request level retries. To avoid duplicates, it defaults to[429].retry_on_document_status(default=same asretry_on_status): Status codes that trigger document level retries for failed documents in successful bulk HTTP responses. Set to[]to disable document level retries by status code while keeping request level retries configured throughretry_on_status.
sending_queue: Configures the queueing and batching behaviour. Below are the defaults (which may vary from standard defaults), for full configuration check theexporterhelperdocs.enabled(default=true): Enable queueing and batching behaviour.num_consumers(default=10): Number of consumers that dequeue batches.wait_for_result(default=false): Iftrue, blocks incoming requests until processed.block_on_overflow(default=false): Iftrue, blocks the request until the queue has space.sizer(default=requests): Measure queueing by requests.queue_size(default=10): Maximum size the queue can accept.batch:flush_timeout(default=10s): Time after which batch is exported irrespective of other settings.sizer(default=bytes): Size batches by bytes. Note that bytes here are based on the pdata model and not on the NDJSON docs that will constitute the bulk indexer requests. To address this discrepancy, the bulk indexers could also flush when their size exceeds the configured max_size due to size of pdata model being smaller than their corresponding NDJSON encoding.min_size(default=1MB): Min size of the batch.max_size(default=5MB): Max size of the batch. This value should be much lower than Elasticsearch'shttp.max_content_lengthconfig to avoid HTTP 413 Entity Too Large error. It is recommended to keep this value under 5MB.
Bulk indexing error response
With Elasticsearch 8.18+, a new query parameter include_source_on_error
allows users to receive the source document in the error response, if there were any parsing errors in the bulk request.
In the exporter, the equivalent configuration is also named include_source_on_error.
include_source_on_error:true: Enables bulk index responses to include source document on error. Requires Elasticsearch 8.18+. WARNING: the exporter may log error responses containing request payload, causing potential sensitive data to be exposed in logs.false: Disables including source document on bulk index error responses. Requires Elasticsearch 8.18+.null(default): Backward-compatible option for older Elasticsearch versions. By default, the error reason is discarded from bulk index responses entirely, i.e. only error type is returned.
Elasticsearch node discovery
The Elasticsearch Exporter will regularly check Elasticsearch for available nodes.
Newly discovered nodes will automatically be used for load balancing.
Settings related to node discovery are:
discover:on_start(optional): If enabled the exporter queries Elasticsearch
for all known nodes in the cluster on startup.interval(optional): Interval to update the list of Elasticsearch nodes.
Node discovery can be disabled by setting discover.interval to 0.
Elasticsearch version detection
On startup, the Elasticsearch Exporter queries each configured endpoint for its
version and build flavor and logs the result. This information is used to
automatically enable features supported by the connected Elasticsearch version,
so no per-feature configuration is required.
version_detection:enabled(defaulttrue): If enabled, the exporter queries Elasticsearch
at startup to detect its version and build flavor. When disabled, the
exporter does not query Elasticsearch and assumes only the baseline
capability set is available.
The query is best-effort: if it fails (for example, when Elasticsearch is
temporarily unreachable), startup is not blocked. Version detection cannot be
performed when the endpoint is resolved at request time (for example, when a
routing middleware rewrites the destination per request).
Telemetry settings
The Elasticsearch Exporter's own telemetry settings for testing and debugging purposes.
β οΈ This is experimental and may change at any time.
telemetry:log_request_body(default=false): Logs Elasticsearch client request body as a field in a log line at DEBUG level. It requiresservice::telemetry::logs::levelto be set todebug. WARNING: Enabling this config may expose sensitive data.log_response_body(default=false): Logs Elasticsearch client response body as a field in a log line at DEBUG level. It requiresservice::telemetry::logs::levelto be set todebug. WARNING: Enabling this config may expose sensitive data.log_failed_docs_input(default=false): Include the input (action line and document line) causing indexing error underinputfield in a log line at DEBUG level. It requiresservice::telemetry::logs::levelto be set todebug. WARNING: Enabling this config may expose sensitive data.log_failed_docs_input_rate_limit(default="1s"): Rate limiting of logs emitted bylog_failed_docs_inputconfig, e.g. "1s" means roughly 1 log line per second. A zero or negative value disables rate limiting.include_destination_index(default=false): Adds thedb.collection.nameattribute to theotelcol.elasticsearch.docs.processedmetric, based on the_indexof each document in the bulk response. For backing and failure store indices, the.ds-/.fs-prefix and the date and generation suffix are stripped, leaving the data stream name. WARNING: it multiplies the number of metric series by the number of destination indices, which can be high with dynamic index names.
Metadata keys
Metadata keys are a list of client metadata keys that the exporter uses to partition batches
when sending_queue is enabled with batching support and enrich internal telemetry.
β οΈ This is experimental and may change at any time.
metadata_keys(optional): List of metadata keys that will be used to partition the data
into batches if sending_queue is enabled with batching support. With
batching enabled only these metadata keys are guaranteed to be propagated. The keys will also
be used to enrich the exporter's internal telemetry if defined. The keys are extracted from
the client metadata available via the context and added to the internal telemetry as attributes.
NOTE: The metadata keys are converted to lower case as key lookups for client metadata is case insensitive. This means that the metric produced by internal telemetry will also have the attribute in lower case.
Exporting metrics
Metrics support is currently in development.
The metric types supported are:
- Gauge
- Sum
- Histogram (Delta temporality only)
- Exponential histogram (Delta temporality only)
- Summary
Histogram storage
In OTel mapping mode, OTLP exponential histograms are stored in Elasticsearch's
native exponential_histogram
field when connected to Elasticsearch 9.3.0 or later. This preserves the
exponential bucket layout (scale, zero bucket, positive/negative buckets, sum,
min, max) losslessly.
This is enabled automatically via version detection: when
version detection is disabled (version_detection.enabled: false) or the
connected Elasticsearch is older than 9.3.0, exponential histograms fall back to
a T-Digest histogram field. Explicit-bucket histograms are always stored as ahistogram field.
Per-data-point mapping hints still apply and take precedence: histogram:raw
stores a histogram field using raw bucket bounds, and aggregate_metric_double
stores a {sum, value_count} summary. The native exponential_histogram field
is only used in OTel mapping mode.
Metrics dynamic templates
For metrics, the exporter sends per-document dynamic_templates with each bulk index action so that Elasticsearch can apply the correct mapping to metric fields. It uses the bulk API dynamic_templates parameter:
A map from the full name of fields to the name of dynamic templates. It defaults to an empty map. If a name matches a dynamic template, that template will be applied regardless of other match predicates defined in the template. If a field is already defined in the mapping, then this parameter won't be used.
The index template must define dynamic templates whose names match the values sent by the exporter. Behavior depends on the mapping mode:
| Mapping mode | Field path in document | Template names sent | Notes |
|---|---|---|---|
| OTel | metrics.<metric name> |
histogram, exponential_histogram, summary, gauge_double, gauge_long, counter_double, counter_long |
The OTel data plugin defines more specific templates. exponential_histogram requires Elasticsearch 9.3.0 or later. |
| ECS | metric.<metric name> |
histogram_metrics, summary_metrics, double_metrics |
Relies on core templates in metrics@mappings. Intended to match the APM metrics ingest pipeline. |
- OTel: Each metric is written under the
metricsobject; the bulk action maps full field names (e.g.metrics.my_metric) to one of the OTel template names above based on metric type (histogram, summary, gauge, or counter) and value type. - ECS: Each metric is written as a top-level field
metric.<name>; the bulk action maps that field name to one of the ECS/APM template names (histogram_metrics,summary_metrics, ordouble_metricsfor gauges and counters).
Bulk Response Filter Path
The Elasticsearch bulk API accepts a filter_path parameter. This can be used to reduce the response returned by Elasticsearch. The exporter uses a default filter_path that is set by the go-docappender. The default is currently items.*._index,items.*.status,items.*.failure_store,items.*.error.type,items.*.error.reason and is defined by the DefaultFilterPath in the go-docappnder package.
If you want to change the filter_path you may do so by setting bulk_response_filter_path to the desired string in the configuration.
[!NOTE]
Ifitems.*._index.itemsis not in the BulkResponseFilterPath than for any failed documents, the exporter will not be able to log the index to which the document was being written to.
[!NOTE]
Ifitems.*._index.itemsis not in the BulkResponseFilterPath than the exporter will log rejection of duplicates to ".profiling-stackframes" which were previously suppressed.
Exporting profiles
Profiles support is currently in development, and should not be used in
production. Profiles only support the OTel mapping mode.
Example:
exporters:
elasticsearch:
endpoint: https://elastic.example.com:9200
mapping:
mode: otel[!IMPORTANT]
For the Elasticsearch Exporter to be able to export Profiles data, Universal Profiling needs to be installed in the database.
See the Universal Profiling getting started documentation
You will need to use the Elasticsearch endpoint, with an Elasticsearch API key.
OTel profiling datastreams
In otel mapping mode, profiling signals are ingested into OTel-native Elasticsearch datastreams.
Each profiling signal type is written to a dedicated backing index:
| Signal type | Index pattern |
|---|---|
| Stack traces | profiling-stacktraces.otel-default |
| Stack frames | profiling-stackframes.otel-default |
| Executables | profiling-executables.otel-default |
| Trace events | profiling-events-all.otel-default |
| Downsampled trace events | profiling-events-5powNN.otel-default (NN from 01 to 11) |
| Host metadata | profiling-hosts.otel-default |
[!NOTE]
Symbolization (resolving unsymbolized stack frames to human-readable function names and file locations)
is not yet supported in OTel profiling datastream mode.
[!WARNING]
The.otel-defaultprofiling datastream index templates are only available in Elasticsearch 9.6.0 and later.
If you send profiles with the default OTel mapping mode to an older cluster, documents will be rejected
withindex_not_found_exception(HTTP 404) and profiling data will be lost.To continue sending profiles to Elasticsearch < 9.6.0, restrict the exporter to ECS mode:
yamlmapping: allowed_modes: [ecs]This is a breaking change for existing OTel-mode profiling users (profiles are still in tech preview):
the backing indices are different from the ECS-schema indices used by prior versions,
and existing profiling data in the old indices is not migrated automatically.
ECS Mapping
elasticsearchexporter follows ECS mapping defined here: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model-appendix.md#elastic-common-schema
When mode is set to ecs, elasticsearchexporter performs conversions for resource-level and record-level (log or trace) attributes from their Semantic Conventions (SemConv) names to equivalent Elastic Common Schema (ECS) names.
If the target ECS field name is specified as an empty string (""), the converter will neither convert the SemConv key to the equivalent ECS name nor pass through the SemConv key as-is to become the ECS name.
When "Preserved" is true, the attribute will be preserved in the payload and duplicated as mapped to its ECS equivalent.
When more than one SemConv attribute maps to the same ECS attribute, the converter will map all attributes to the same ECS name.
This is mean to support backwards compatibility for SemConv attributes that have been renamed/deprecated.
The value of the last-mapped attribute will take precedence.
It is recommended to enrich events using the elasticapmprocessor to ensure index documents contain all required Elastic fields to power the Kibana UI.
Resource attribute mapping
| Semantic Convention Name | ECS Name | Preserve | Skip if exists |
|---|---|---|---|
| client.address | client.ip | false | false |
| cloud.platform | cloud.service.name | false | false |
| container.image.tags | container.image.tag | false | false |
| deployment.environment | service.environment | false | false |
| deployment.environment.name | service.environment | false | false |
| faas.instance | faas.id | false | false |
| faas.trigger | faas.trigger.type | false | false |
| host.arch | host.architecture | false | false |
| host.hostname | host.hostname | true | true |
| k8s.cluster.name | orchestrator.cluster.name | false | false |
| k8s.container.name | kubernetes.container.name | false | false |
| k8s.cronjob.name | kubernetes.cronjob.name | false | false |
| k8s.daemonset.name | kubernetes.daemonset.name | false | false |
| k8s.deployment.name | kubernetes.deployment.name | false | false |
| k8s.job.name | kubernetes.job.name | false | false |
| k8s.namespace.name | kubernetes.namespace | false | false |
| k8s.node.name | kubernetes.node.name | false | false |
| k8s.pod.name | kubernetes.pod.name | false | false |
| k8s.pod.uid | kubernetes.pod.uid | false | false |
| k8s.replicaset.name | kubernetes.replicaset.name | false | false |
| k8s.statefulset.name | kubernetes.statefulset.name | false | false |
| os.description | host.os.full | false | false |
| os.name | host.os.name | false | false |
| os.type | host.os.platform | false | false |
| os.version | host.os.version | false | false |
| process.command_line | process.args | false | false |
| process.executable.name | process.title | false | false |
| process.executable.path | process.executable | false | false |
| process.parent.pid | process.parent.pid | false | false |
| process.runtime.name | service.runtime.name | false | false |
| process.runtime.version | service.runtime.version | false | false |
| service.instance.id | service.node.name | false | false |
| source.address | source.ip | false | false |
| telemetry.distro.name | "" | false | false |
| telemetry.distro.version | "" | false | false |
| telemetry.sdk.language | service.language.name | false | false |
| telemetry.sdk.name | "" | false | false |
| telemetry.sdk.version | service.language.version | false | false |
Log record attribute mapping
| Semantic Convention Name | ECS Name | Preserve |
|---|---|---|
| event.name | event.action | false |
| exception.message | error.message | false |
| exception.stacktrace | error.stacktrace | false |
| exception.type | error.type | false |
| exception.escaped | event.error.exception.handled | false |
| http.response.body.size | http.response.encoded_body_size | false |
Span attribute mapping
| Semantic Convention Name | ECS Name | Preserve |
|---|---|---|
| db.system | span.db.type | false |
| db.namespace | span.db.instance | false |
| db.query.text | span.db.statement | false |
| http.response.body.size | http.response.encoded_body_size | false |
Compound Mapping
There are ECS fields that are not mapped easily 1 to 1 but require more advanced logic.
`host.name` and `host.hostname`
Maintains the SemConv Value host.name as ECS Value host.name and maps it to ECS Value host.hostname, if this does not already exist.
`@timestamp`
In case the record contains timestamp, this value is used. Otherwise, the observed timestamp is used.
Setting a document id dynamically
The logs_dynamic_id and traces_dynamic_id settings allow users to set the document ID dynamically based on log record, span, or span event attributes.
Besides the ability to control the document ID, these settings also work as a deduplication mechanism, as Elasticsearch will refuse to index a document with the same ID.
For logs, the log record attribute elasticsearch.document_id can be set explicitly by a processor based on the log record.
For traces, the span attribute elasticsearch.document_id (or span event attribute for span events) can be set explicitly by a processor based on the span or span event.
As an example, the transform processor can create this attribute dynamically for logs:
processors:
transform/es-doc-id:
error_mode: ignore
log_statements:
- context: log
condition: attributes["event_name"] != null && attributes["event_creation_time"] != null
statements:
- set(attributes["elasticsearch.document_id"], Concat(["log", attributes["event_name"], attributes["event_creation_time"], "-"))For traces, you can use the transform processor to set the document ID based on trace and span IDs to ensure uniqueness:
exporters:
elasticsearch:
mapping:
mode: otel # Required for span events to be separate documents
traces_dynamic_id:
enabled: true
processors:
transform/es-doc-id-traces:
error_mode: ignore
trace_statements:
- context: span
statements:
# Set ID for spans
- set(attributes["elasticsearch.document_id"], Concat([trace_id.string, span_id.string], "-"))
- context: spanevent
statements:
# Set ID for span events (only works in otel mapping mode)
- set(attributes["elasticsearch.document_id"], Concat([trace_id.string, span_id.string, name], "-"))Note: Span events are only stored as separate documents in otel mapping mode. In other mapping modes (ecs, bodymap, raw), span events are embedded within the span document and will not have separate document IDs.
Known issues
version_conflict_engine_exception
Symptom: elasticsearchexporter logs an error "failed to index document" with error.type "version_conflict_engine_exception" and error.reason containing "version conflict, document already exists".
This happens when the target data stream is a TSDB metrics data stream (e.g. using OTel mapping mode sending to a 8.16+ Elasticsearch, or ECS mapping mode sending to system integration data streams).
Elasticsearch Time Series Data Streams requires that there must only be one document per timestamp with the same dimensions.
The purpose is to avoid duplicate data when re-trying a batch of metrics that were previously sent but failed to be indexed.
The dimensions are mostly made up of resource attributes, scope attributes, scope name, attributes, and the unit.
The exporter can only group metrics with the same dimensions into the same document if they arrive in the same batch.
To ensure metrics are not dropped even if they arrive in different batches in the exporter, the exporter adds a fingerprint of the metric names to the document in the otel mapping mode.
Note that this functionality requires both
- minimum Elasticsearch Exporter version 0.121.0
- minimum Elasticsearch version 8.17.6, 8.18.1, 8.19.0, 9.0.1, or 9.1.0
If you are on an earlier version of Elasticsearch, either update your cluster or install this custom component template:
PUT _component_template/metrics-otel@custom
{
"template": {
"mappings": {
"properties": {
"_metric_names_hash": {
"type": "keyword",
"time_series_dimension": true
}
}
}
}
}After installing this component template, if you've previously ingested data, you'll need to wait until the old index of the time series data stream reaches its end_time. This can take up to 30 minutes by default. See time series index look-ahead time for more information.
While in most situations, this error is just a sign that Elasticsearch's duplicate detection is working as intended, the data may be classified as a duplicate while it was not.
This implies data is lost.
If the data is not sent in
otelmapping mode tometrics-*.otel-*data streams, the metrics name fingerprint is not applied.
This can happen for OTel host and k8s metrics that theelasticinframetricsprocessorhas translated to the format the host and k8s dashboards in Kibana can consume.
If these metrics arrive in theelasticsearchexporterin different batches, they will not be grouped to the same document.
This can cause theversion_conflict_engine_exceptionerror.
Try to remove thebatchprocessorfrom the pipeline (or setsend_batch_max_size: 0) to ensure metrics are not split into different batches.
This gives the exporter the opportunity to group all related metrics into the same document.Otherwise, check your metrics pipeline setup for misconfiguration that causes an actual violation of the single writer principle.
This means that the same metric with the same dimensions is sent from multiple sources, which is not allowed in the OTel metrics data model.
flush failed (400) illegal_argument_exception
Symptom: bulk indexer logs an error that indicates "bulk indexer flush error" with bulk request returning HTTP 400 and an error type of illegal_argument_exception, similar to the following.
error [email protected]/bulkindexer.go:343 bulk indexer flush error
{
"otelcol.component.id": "elasticsearch",
"otelcol.component.kind": "Exporter",
"otelcol.signal": "logs",
"error": "flush failed (400): {\"error\":{\"type\":\"illegal_argument_exception\",\"caused_by\":{}}}"
}In this scenario, Elasticsearch may reject the bulk request because the require_data_stream bulk action metadata is not supported.
This may happen when you use OTel mapping mode (the default mapping mode from v0.122.0, or explicitly by configuring mapping::mode: otel) or ECS mapping mode, and send data to Elasticsearch version < 8.12.
To resolve this, upgrade Elasticsearch to 8.12+; for OTel mapping mode, 8.16+ is recommended.
Alternatively, try other mapping modes, but the document structure will be different.
"dropping cumulative temporality histogram" and "dropping cumulative temporality exponential histogram"
Symptom: elasticsearchexporter logs a warning dropping cumulative temporarily histogram similar to:
warn [email protected]/exporter.go:340 validation errors
{
"resource": {
"service.instance.id": "33ffe7e8-e944-4f92-8fce-9094f4b61d1d",
"service.name": "./elastic-agent",
"service.version": "9.1.5"
},
"otelcol.component.id": "elasticsearch/otel",
"otelcol.component.kind": "exporter",
"otelcol.signal": "metrics",
"error": "dropping cumulative temporality histogram \"http.client.request.duration\""
}This issue occurs because Elasticsearch does not support cumulative temporality for histograms.
As a workaround, you can either:
- Export histogram metrics using delta temporality, or
- Apply a
cumulativetodeltaprocessor.
For more details, see Metrics data ingestion.
Overview (`exporter/faroexporter/README.md`)
Faro Exporter
| Status | |
|---|---|
| Stability | alpha: logs, traces |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @dehaansa, @rlankfo, @mar4uk |
The Faro exporter sends telemetry data to a Faro endpoint.
Configuration
The following settings are required:
endpoint(no default): The URL to send telemetry data to (e.g., https://faro.example.com/collect).
The following settings can be optionally configured:
timeout(default = 30s),sending_queueandretry_on_failuresettings as provided by Exporter Helper.read_buffer_size(default = 0): Size of the buffer used to read the response body.write_buffer_size(default = 512 KiB): Size of the buffer used to write the request body.headers(default ={}): Additional headers to send with the request.compression(default = gzip): Compression method to use for the request body. Supported values:none,gzip.
Example:
exporters:
faro:
endpoint: https://faro.example.com/collect
timeout: 10s
headers:
X-API-Key: "my-api-key"The full list of settings exposed for this exporter are documented here with detailed sample configurations here.
Getting Started
The following settings are required:
endpoint(no default): URL to which the exporter is going to send Faro telemetry data. For example:https://faro.example.com/collect.
To use TLS, specify https:// as the protocol scheme in the URL passed to the endpoint property.
See Advanced Configuration for more TLS options.
Example:
exporters:
faro:
endpoint: "https://faro.example.com/collect"
faro/tlsnoverify:
endpoint: "https://faro.example.com/collect"
tls:
insecure_skip_verify: truePropagating the `X-Faro-Session-Id` header
If using the faro exporter component to send telemetry data to the Grafana Cloud Collector Endpoint for Frontend Observability, make sure to propagate the X-Faro-Session-Id header.
Grafana Cloud's Faro collector validates the session at the HTTP level and rejects requests that do
not carry an X-Faro-Session-Id header (HTTP 400, missing X-Faro-Session-Id header). The Faro Web
SDK sends this header on every request to the Faro receiver, but the exporter does
not forward incoming request headers automatically.
To propagate the session id from the incoming request onto the outgoing export, use the
headers_setter extension with from_context, and set include_metadata: true on
the receiver so the header is available to the pipeline:
receivers:
faro:
include_metadata: true
cors:
allowed_origins:
- '*'
allowed_headers:
- 'X-Faro-Session-Id'
- 'Content-Type'
extensions:
headers_setter:
headers:
- action: insert
key: X-Faro-Session-Id
from_context: X-Faro-Session-Id
exporters:
faro:
endpoint: 'https://faro-collector-<region>.grafana.net/collect/<app-key>'
auth:
authenticator: headers_setter
service:
extensions: [headers_setter]
pipelines:
traces:
receivers: [faro]
exporters: [faro]
logs:
receivers: [faro]
exporters: [faro]If a batch processor is present in the pipeline, add X-Faro-Session-Id to itsmetadata_keys so the metadata is preserved through batching.
When using Grafana Alloy, the equivalent is the otelcol.auth.headers
component with from_context = "X-Faro-Session-Id" and include_metadata = true onotelcol.receiver.faro.
For a complete preprocessing example (including PII redaction and event filtering), see the Grafana
Cloud Process Faro telemetry documentation.
Advanced Configuration
Several helper files are leveraged to provide additional capabilities automatically:
Overview (`exporter/fileexporter/README.md`)
File Exporter
| Status | |
|---|---|
| Stability | development: profiles |
| alpha: traces, metrics, logs | |
| Distributions | core, contrib, k8s |
| Issues | |
| Code coverage | |
| Code Owners | @paulojmdias | Seeking more code owners! |
| Emeritus | @atingchen |
Writes telemetry data to files on disk.
Use the OTLP JSON File receiver to read the data back into the collector. It only reads uncompressed, newline-delimited OTLP JSON (the default format: json without compression or encoding, see File Format).
The exporter supports the following features:
Writing pipeline data to a file.
Rotation of telemetry files.
Compressing the telemetry data before exporting.
Writing into multiple files, where the file path is determined by a resource attribute.
Please note that there is no guarantee that exact field names will remain stable.
The official opentelemetry-collector-contrib container does not have a writable filesystem by default since it's built on the scratch layer.
As such, you will need to create a writable directory for the path. You could do this by mounting a volume with flags such as rw or rwZ.
On Linux, and given a otel-collector-config.yaml with a file exporter whose path is prefixed with /file-exporter,
# linux needs +x to list a directory. You can use a+ instead of o+ for the mode if you want to ensure your user and group has access.
mkdir --mode o+rwx file-exporter
# z is an SELinux construct that is ignored on other systems
docker run -v "./file-exporter:/file-exporter:rwz" -v "otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml" otel/opentelemetry-collector-contrib:latestNote this same syntax for volumes will work with docker-compose.
You could also modify the base image and manually build your own container to have a writeable directory or change the runas uid if needed, but this is more involved.
Configuration options:
The following settings are required:
path[no default]: where to write information.
The following settings are optional:
rotationsettings to rotate telemetry files. Rotation is only enabled whenrotation:is present in the config.- max_megabytes: [default: 100]: the maximum size in megabytes of the telemetry file before it is rotated.
- max_days: [no default (unlimited)]: the maximum number of days to retain rotated telemetry files based on the timestamp encoded in their filename. This only controls retention, it does not trigger rotation.
- max_backups: [default: 100]: the maximum number of rotated telemetry files to retain.
- localtime : [default: false (use UTC)] whether or not the timestamps in backup files is formatted according to the host's local time.
format[default: json]: the data format of encoded telemetry data, eitherjsonorproto.encoding[default: none]: if specified, uses an encoding extension to encode telemetry data instead of the built-informatmarshaler. How records are delimited in the file still depends onformat, see File Format.append[default:false] defines whether append to the file (true) or truncate (false).append: truecannot be combined withrotation.compression[no default]: the compression algorithm used when exporting telemetry data to file. Supported compression algorithms:zstdcompression_paramslevel(default = 0, which uses the zstd default level3): the compression level used when exporting telemetry data. Only applied when theexporter.file.nativeCompressionfeature gate is enabled, see Known limitations.- The following are valid combinations of
compressionandlevel:zstd- SpeedFastest:
1 - SpeedDefault:
3 - SpeedBetterCompression:
6 - SpeedBestCompression:
11
- SpeedFastest:
- The following are valid combinations of
flush_interval[default: 1s]:time.Durationinterval between flushes of the write buffer. See time.ParseDuration for valid formats.- A value without a unit is in nanoseconds, so always specify one (for example
5s). 0is treated as the default (1s); buffering cannot be disabled.- Ignored when
rotationis set and theexporter.file.nativeCompressionfeature gate is disabled, as writes are not buffered in that case. - With the
exporter.file.nativeCompressionfeature gate enabled and withoutrotation, each flush finalizes a zstd frame. Withrotation, each batch is written as its own frame and flushing is a no-op.
- A value without a unit is in nanoseconds, so always specify one (for example
create_directory[default: false]: when set, the exporter will create the parent directory of the configuredpathif it does not exist.directory_permissions[default: 0755]: file mode (octal string) used when creating directories, minus the process umask. Can only be set whencreate_directoryistrue. This also applies to directories created bygroup_by.group_byenables writing to separate files based on a resource attribute.- enabled: [default: false] enables group_by. When enabled,
pathmust contain exactly one*and must not start with it. - resource_attribute: [default: fileexporter.path_segment]: specifies the name of the resource attribute that contains the path segment of the file to write to. The final path will be the
pathconfig value, with the*replaced with the value of this resource attribute. - max_open_files: [default: 100]: specifies the maximum number of open file descriptors for the output files.
- enabled: [default: false] enables group_by. When enabled,
File Rotation
Telemetry data is exported to a single file by default.fileexporter only enables file rotation when the user specifies rotation: in the config. However, if specified, related default settings would apply.
Telemetry is first written to a file that exactly matches the path setting.
When writing the next batch would make the file exceed max_megabytes, the file is rotated. Rotation is size-based only; max_days and max_backups only control how many rotated files are kept.
When a file is rotated, it is renamed by putting the current time and the rotation reason
in the name immediately before the file's extension (or the end of the filename if there's no extension).
A new telemetry file will be created at the original path.
For example, if your path is data.json and rotation is triggered, this file will be renamed to data-2022-09-14T05-02-14.173-size.json, and a new telemetry file created with data.json.
Rotated files from older collector versions (named without the -size suffix, e.g. data-2022-09-14T05-02-14.173.json) are renamed to the new format on startup, so max_days and max_backups keep applying to them.
File Compression
Telemetry data is compressed according to the compression setting.fileexporter does not compress data by default.
[!NOTE]
An alpha feature gateexporter.file.nativeCompressionis available that switches from
per-message compression to native file-level compression, producing standard.zstfiles
compatible with tools likezstd -d. See Feature Gates for details.
Currently, fileexporter support the zstd compression algorithm, and we will support more compression algorithms in the future.
File Format
Telemetry data is encoded according to the format (or encoding) setting and then written to the file. How each batch is delimited depends on format, encoding, compression and the exporter.file.nativeCompression feature gate:
exporter.file.nativeCompression |
compression |
format / encoding |
Written to the file |
|---|---|---|---|
| any | none | json, no encoding |
Newline-delimited OTLP JSON, one line per batch |
| any | none | json + encoding |
Encoder output followed by \n per batch (no length prefix) |
| any | none | proto, with or without encoding |
Length-prefixed messages |
| disabled | zstd |
any | Each batch compressed on its own, then length-prefixed. Not readable by zstd -d |
| enabled | zstd |
json, no encoding |
Newline-delimited OTLP JSON inside a standard zstd stream |
| enabled | zstd |
proto, or any encoding |
Length-prefixed messages inside a standard zstd stream |
Length-prefixed means each encoded message is preceded by 4 bytes (a big-endian unsigned 32 bit integer) holding the number of bytes in the message. To read the messages back, read the size, then read that many bytes into a separate buffer and parse from that buffer.
When using an encoding extension that produces binary output without compression, set format: proto to get length-prefixed framing; otherwise records can't be reliably split back apart.
Group by attribute
By specifying group_by.resource_attribute in the config, the exporter will determine a filepath for each telemetry record, by substituting the value of the resource attribute into the path configuration value.
The final path is guaranteed to start with the prefix part of the path config value (the part before the * character). For example if path is "/data/*.json", and the resource attribute value is "../etc/my_config", then the final path will be sanitized to "/data/etc/my_config.json".
The final path can contain path separators (/). The exporter will create missing directories recursively (similarly to mkdir -p), regardless of create_directory.
Resources that do not have the attribute, or where its value is not a string, are dropped.
When more than max_open_files files are in use, the least recently used file is closed and reopened on its next write. Unless append: true or rotation is set, reopening truncates the file and its earlier content is lost, so keep max_open_files above the number of distinct attribute values or set append: true.
Grouping by attribute currently only supports a single resource attribute. If you would like to use multiple attributes, please use Transform processor create a routing key. If you would like to use a non-resource level (eg: Log/Metric/DataPoint) attribute, please use Group by Attributes processor first.
Known limitations
appendandrotationcannot be used together.- With
rotationand theexporter.file.nativeCompressionfeature gate disabled:- writes are not buffered and
flush_intervalhas no effect; - a single batch larger than
max_megabytesis rejected with an error. With the feature gate enabled, such a batch is split across multiple zstd frames instead.
- writes are not buffered and
group_bydrops resources without the configured attribute (or with a non-string value), logging this only atdebuglevel.group_byalways creates missing directories, whatever the value ofcreate_directory.- With
group_by, a file evicted because ofmax_open_filesis truncated when reopened, unlessappend: trueorrotationis set. - Without the
exporter.file.nativeCompressionfeature gate,compression_params.levelis ignored and the zstd default level is used. - Files are not fsynced. Written data may be lost if the host crashes before the OS flushes it to disk.
- The exporter does not support
sending_queue,retry_on_failureortimeout.
Telemetry
The exporter does not emit metrics of its own. Use the standard exporter metrics to monitor it, such as otelcol_exporter_sent_spans, otelcol_exporter_sent_metric_points, otelcol_exporter_sent_log_records and their otelcol_exporter_send_failed_* counterparts.
Example:
exporters:
file/no_rotation:
path: ./foo
file/rotation_with_default_settings:
path: ./foo
rotation:
file/rotation_with_custom_settings:
path: ./foo
rotation:
max_megabytes: 10
max_days: 3
max_backups: 3
localtime: true
format: proto
compression: zstd
compression_params:
level: 6
file/flush_every_5_seconds:
path: ./foo
flush_interval: 5s
# Writes one file per service, e.g. ./data/checkout.json, ./data/cart.json
file/group_by_service:
path: ./data/*.json
group_by:
enabled: true
resource_attribute: service.name
max_open_files: 50Native file-level compression, readable with zstd -d (requires starting the collector with --feature-gates=exporter.file.nativeCompression):
exporters:
file/native_zstd:
path: ./foo.jsonl.zst
compression: zstd
compression_params:
level: 3Get Started in an existing cluster
We will follow the documentation to first install the operator in an existing cluster
and then create an OpenTelemetry Collector (otelcol) instance,
mounting an additional volume under /data under which the file exporter will write metrics.json:
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: fileexporter
spec:
config: |
receivers:
otlp:
protocols:
grpc:
http:
processors:
exporters:
debug:
file:
path: /data/metrics.json
service:
pipelines:
metrics:
receivers: [otlp]
processors: []
exporters: [debug,file]
volumes:
- name: file
emptyDir: {}
volumeMounts:
- name: file
mountPath: /data
EOFOverview (`exporter/googlecloudexporter/README.md`)
Google Cloud Exporter
| Status | |
|---|---|
| Stability | beta: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @aabmass, @dashpole, @braydonk, @jsuereth, @psx95, @ridwanmsharif |
This exporter can be used to send metrics to Google Cloud Monitoring
(formerly Stackdriver), traces to Google Cloud Trace,
and logs to Google Cloud Logging.
To learn more about instrumentation and observability, including opinionated recommendations
for Google Cloud Observability, visit Instrumentation and
observability.
Getting started
Prerequisite: Authenticating
In general, authenticating with the Collector exporter follows the same steps as
any other app using the steps documented for Application Default
Credentials. This
section explains the specific use cases relevant to the exporter.
The exporter relies on GCP client libraries to send data to Google Cloud. Use of these libraries requires the caller (the Collector) to be authenticated with a GCP account and project. This should be done using a GCP service account with at minimum the following IAM roles (depending on the type of data you wish to send):
The Compute Engine default service account has all of these permissions by default, but if you are running on a different platform or with a different GCP service account you will need to ensure your service account has these permissions.
Options for different environments
Depending on the environment where your Collector is running, you can authenticate one of several ways:
GCE instances
On GCE it is recommended to use the GCP service account associated with your instance. If this is the Compute Engine default service account or another GCP service account with the sufficient IAM permissions, then there is nothing additional you need to do to authenticate the Collector process. Simply run the Collector on your instance, and it will inherit these permissions.
GKE / Workload Identity
On GKE clusters with Workload Identity enabled (including GKE Autopilot), follow the steps to configure a Workload Identity ServiceAccount in your cluster (if you do not already have one). Then, deploy the Collector as you would with any other workload, setting the serviceAccountName field in the Collector Podβs .spec to the WI-enabled ServiceAccount.
In non-WI clusters, you can use the GCP service account associated with the node the same way as in the instructions for GCE instances above.
Non-GCP (AWS, Azure, on-prem, etc.) or alternative service accounts
In non-GCP environments, a service account key or credentials file is required. The exporter will automatically look for this file using the GOOGLE_APPLICATION_CREDENTIALS environment variable or, if that is unset, one of the other known locations. Note that when using this approach, you may need to explicitly set the project option in the exporterβs config.
When running the Collector in a Docker container, a credentials file can be passed to the container via volume mounts and environment variables at runtime like so:
docker run \
--volume ~/service-account-key.json:/etc/otelcol-contrib/key.json \
--volume $(pwd)/config.yaml:/etc/otelcol-contrib/config.yaml \
--env GOOGLE_APPLICATION_CREDENTIALS=/etc/otelcol-contrib/key.json \
--expose 4317 \
--expose 55681 \
--rm \
otel/opentelemetry-collector-contribUsing gcloud auth application-default login
Using gcloud auth application-default login to authenticate is not recommended for production use. Instead, itβs best to use a GCP service account through one of the methods listed above. The gcloud auth command can be useful for development and testing on a user account, and authenticating with it follows the same approach as the service account key method above.
These instructions are to get you up and running quickly with the GCP exporter in a local development environment. We'll also point out alternatives that may be more suitable for CI or production.
Obtain a Collector binary. Pull a binary or Docker image for the
OpenTelemetry contrib collector which includes the GCP exporter plugin
through one of the following:- Download a binary or package of the OpenTelemetry
Collector Contrib
that is appropriate for your platform, and includes the Google Cloud
exporter. - Pull a Docker image with
docker pull otel/opentelemetry-collector-contrib - Create your own main package in Go, that pulls in just the plugins you need.
- Use the OpenTelemetry Collector
Builder
to generate the Go main package andgo.mod.
- Download a binary or package of the OpenTelemetry
Create a configuration file
config.yaml. The example below shows a minimal recommended configuration that receives OTLP and sends data to GCP, in addition to verbose logging to help understand what is going on. It uses application default credentials (which we will set up in the next step).Note that this configuration includes the recommended
memory_limiterplugins, which avoid high latency for reporting telemetry, and ensure that the collector itself will stay stable (not run out of memory) by dropping telemetry if needed.yamlreceivers: otlp: protocols: grpc: http: exporters: googlecloud: log: default_log_name: opentelemetry.io/collector-exported-log processors: memory_limiter: check_interval: 1s limit_percentage: 65 spike_limit_percentage: 20 resource_detection: detectors: [gcp] timeout: 10s service: pipelines: traces: receivers: [otlp] processors: [memory_limiter] exporters: [googlecloud] metrics: receivers: [otlp] processors: [memory_limiter] exporters: [googlecloud] logs: receivers: [otlp] processors: [memory_limiter] exporters: [googlecloud]Set up credentials.
Enable billing in your GCP project.
Enable the Cloud Metrics and Cloud Trace APIs.
Ensure that your user GCP user has (at minimum)
roles/monitoring.metricWriterandroles/cloudtrace.agent. You can learn about metric-related and trace-related IAM in the GCP documentation.Obtain credentials using one of the methods in the Authenticating
section above.
Run the collector. The following runs the collector in the foreground, so please execute it in a separate terminal.
sh./otelcol-contrib --config=config.yamlAlternatives
If you obtained OS-specific packages or built your own binary in step 1, you'll need to follow the appropriate conventions for running the collector.
Gather telemetry. Run an application that can submit OTLP-formatted metrics and traces, and configure it to send them to
127.0.0.1:4317(for gRPC) or127.0.0.1:55681(for HTTP).Alternatives
Set up the host metrics receiver, which will gather telemetry from the host without needing an external application to submit telemetry.
Set up an application-specific receiver, such as the Nginx receiver, and run the corresponding application.
Set up a receiver for some other protocol (such Prometheus, StatsD, Zipkin or Jaeger), and run an application that speaks one of those protocols.
View telemetry in GCP. Use the GCP metrics explorer and trace overview to view your newly submitted telemetry.
Configuration reference
The following configuration options are supported:
project(default = Fetch from Credentials): GCP project identifier.destination_project_quota(optional, default = false): Counts quota against the project to which the data is sent (as opposed to the project associated with the Collector's service account. For example, when settingproject_idor using multi-project export.user_agent(default =collector description/version os/arch, i.e.opentelemetry-collector-contrib/v0.139.0 linux/amd64): Override the user agent string sent on requests to Cloud Monitoring (currently only applies to metrics). Specify{{version}}to include the application version number.timeout(default =12s) The timeout for requests to Google Cloud Platform APIs, specified in Go Time Duration format.impersonate(optional): Configuration for service account impersonationtarget_principal: TargetPrincipal is the email address of the service account to impersonate.subject: (optional) Subject is the sub field of a JWT. This field should only be set if you wish to impersonate as a user. This feature is useful when using domain wide delegation.delegates: (default = []) Delegates are the service account email addresses in a delegation chain. Each service account must be granted roles/iam.serviceAccountTokenCreator on the next service account in the chain.
metric(optional): Configuration for sending metrics to Google Cloud Monitoring.prefix(default =workload.googleapis.com): The prefix to add to metrics.endpoint(default =monitoring.googleapis.com): Endpoint where metric data is going to be sent to.use_insecure(default = false): If true, disables gRPC client transport security. Only has effect if Endpoint is not "".compression(optional, supported values: [gzip]): Compression format for Metrics gRPC requests. Defaults to no compression.grpc_pool_size(optional): Sets the size of the connection pool in the GCP client. Defaults to a single connection.known_domains(default = [googleapis.com, kubernetes.io, istio.io, knative.dev]): If a metric belongs to one of these domains it does not get a prefix.skip_create_descriptor(default = false): If set to true, do not send metric descriptors to Google Cloud Monitoring.instrumentation_library_labels(default = true): If true, the exporter will copy the OTLPInstrumentationScope.Nameto a labelinstrumentation_sourceandInstrumentationScope.Versionto a labelinstrumentation_versionlabels on metrics.service_resource_labels(default = true): If true, the exporter will copy the Semantic Conventionsservice.name,service.namespace, andservice.instance.idfrom OTLP Resource Attributes into the Google Cloud Monitoring timeseries metric labels. These labels will be the same as the Semantic Conventions with.replaced by_.create_metric_descriptor_buffer_size(default = 10): Buffer size for the channel which asynchronously calls CreateMetricDescriptor.resource_filters(default = []): If provided, resource attributes matching any filter will be included in metric labels. Can be defined byprefix,regex, orprefixANDregex.prefix: Match resource keys by prefix.regex: Match resource keys by regex.
cumulative_normalization(default = true): If true, normalizes cumulative metrics without start times or with explicit reset points by subtracting subsequent points from the initial point. It is enabled by default. Since it caches starting points, it may result in increased memory usage.sum_of_squared_deviation(default = false): If true, enables calculation of an estimated sum of squared deviation. It is an estimate, and is not exact.create_service_timeseries(default = false): If true, this will send all timeseries usingCreateServiceTimeSeries. Implicitly, this setsskip_create_descriptorto true.experimental_wal(default = []): If provided, enables use of a write ahead
log for time series requests.directory(default =./): Path to local directory for WAL file.max_backoff(default =1h): Max duration to retry requests on network errors (UNAVAILABLEorDEADLINE_EXCEEDED).
trace(optional): Configuration for sending traces to Google Cloud Trace.endpoint(default =cloudtrace.googleapis.com): Endpoint where trace data is going to be sent to.use_insecure(default = false): If true, disables gRPC client transport security. Only has effect if Endpoint is not "".grpc_pool_size(optional): Sets the size of the connection pool in the GCP client. Defaults to a single connection.attribute_mappings(optional): AttributeMappings determines how to map from OpenTelemetry attribute keys to Google Cloud Trace keys. By default, it changeshttpandservicekeys so that they appear more prominently in the UI.key: The OpenTelemetry attribute keyreplacement: The replacement attribute sent to Google Cloud Trace
log(optional): Configuration for sending logs to Google Cloud Logging.endpoint(default =logging.googleapis.com): Endpoint where log data is going to be sent to.use_insecure(default = false): If true, disables gRPC client transport security. Only has effect if Endpoint is not "".compression(optional, Supported values: [gzip]): Compression format for Logs gRPC requests. Defaults to no compression.grpc_pool_size(optional): Sets the size of the connection pool in the GCP client. Defaults to a single connection.default_log_name(optional): Defines a default name for log entries. If left unset, and a log entry does not have thegcp.log_nameattribute set, the exporter will return an error processing that entry.resource_filters(default = []): If provided, Resource Attributes matching any filter will be included in log entry labels. Can be defined byprefix,regex, orprefixANDregex.prefix: Match resource keys by prefix.regex: Match resource keys by regex.
sending_queue(optional): Configuration for how to buffer data before sending. Note: Thesending_queueis provided (and documented) by the Exporter Helper
Beyond standard YAML configuration as outlined in the section above,
exporters that leverage the net/http package (all do today) also respect the
following proxy environment variables:
- HTTP_PROXY
- HTTPS_PROXY
- NO_PROXY
If set at Collector start time then exporters, regardless of protocol,
will or will not proxy traffic as defined by these environment variables.
Monitored Resources
For metrics and logs, this exporter maps the OpenTelemetry Resource to a Google
Cloud Logging or
Monitoring Monitored Resource.
The complete mapping logic can be found in resourcemapping.go.
That may be the most helpful reference if you want to map to a specific monitored
resource.
On GCP
If running on GCP, using the GCP resource detector, as shown above, will populate
the resource attributes required to map to the appropriate monitored resource.
Off GCP
If you are not running on GCP, you still need to choose a GCP zone or
region to send telemetry to
by setting cloud.availability_zone or cloud.region. In addition, you should use the detector associated with other cloud providers, if applicable.
If running on Kubernetes, it is recommended to additionally set k8s.pod.name,k8s.namespace.name, and k8s.container.name using the k8sattributes processor.
If you are getting "duplicate timeseries encountered" errors, it is likely because
you are missing a required resource attribute, causing a metric from two different
instances of an application to end up with the same monitored resource.
Preventing metric label collisions
The metrics exporter can add metric labels to timeseries, such as when settingmetric.service_resource_labels, metric.instrumentation_library_labels (both
on by default), or when using metric.resource_filters to convert resource
attributes to metric labels.
However, if your metrics already contain any of these labels they will fail to
export to Google Cloud with a Duplicate label key encountered error. Such
labels from the default features above include:
service_nameservice_namespaceservice_instance_idinstrumentation_sourceinstrumentation_version
(Note that these are the sanitized versions of OpenTelemetry attributes, with . replaced by _ to be compatible with Cloud Monitoring. For example, service_name comes from the service.name resource attribute.)
To prevent this, it's recommended to use the transform processor in your collector config to rename existing metric labels to preserve them, for example:
processors:
transform:
metric_statements:
- context: datapoint
statements:
- set(attributes["exported_service_name"], attributes["service_name"])
- delete_key(attributes, "service_name")
- set(attributes["exported_service_namespace"], attributes["service_namespace"])
- delete_key(attributes, "service_namespace")
- set(attributes["exported_service_instance_id"], attributes["service_instance_id"])
- delete_key(attributes, "service_instance_id")
- set(attributes["exported_instrumentation_source"], attributes["instrumentation_source"])
- delete_key(attributes, "instrumentation_source")
- set(attributes["exported_instrumentation_version"], attributes["instrumentation_version"])
- delete_key(attributes, "instrumentation_version")Note It is not recommended to use these transformations with the googlecloud
exporter in a logging or trace pipeline.
The same method can be used for any resource attributes being filtered to metric
labels, or metric labels which might collide with the GCP monitored resource
used with resource detection.
Keep in mind that your conflicting attributes may contain dots instead of
underscores (eg, service.name), but these will still collide once all
attributes are normalized to metric labels. In this case you will need to update
the collector config above appropriately.
Logging Example
The logging exporter processes OpenTelemetry log entries and exports them to GCP Cloud Logging. Logs can be collected using one
of the opentelemetry-collector-contrib log receivers, such as the filelogreceiver.
Log entries must contain any Cloud Logging-specific fields as a matching OpenTelemetry attribute (as shown in examples from the
logs data model).
These attributes can be parsed using the various log operators available upstream.
For example, the following config parses the HTTPRequest field from Apache log entries saved in /var/log/apache.log.
It also parses out the timestamp and inserts a non-default log_name attribute and GCP MonitoredResource attribute.
receivers:
file_log:
include: [ /var/log/apache.log ]
start_at: beginning
operators:
- id: http_request_parser
type: regex_parser
regex: '(?m)^(?P<remoteIp>[^ ]*) (?P<host>[^ ]*) (?P<user>[^ ]*) \[(?P<time>[^\]]*)\] "(?P<requestMethod>\S+)(?: +(?P<requestUrl>[^\"]*?)(?: +(?P<protocol>\S+))?)?" (?P<status>[^ ]*) (?P<responseSize>[^ ]*)(?: "(?P<referer>[^\"]*)" "(?P<userAgent>[^\"]*)")?$'
parse_to: attributes["gcp.http_request"]
timestamp:
parse_from: attributes["gcp.http_request"].time
layout_type: strptime
layout: '%d/%b/%Y:%H:%M:%S %z'
converter:
max_flush_count: 100
flush_interval: 100ms
exporters:
googlecloud:
project: my-gcp-project
log:
default_log_name: opentelemetry.io/collector-exported-log
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 65
spike_limit_percentage: 20
resource_detection:
detectors: [gcp]
timeout: 10s
attributes:
# Override the default log name. `gcp.log_name` takes precedence
# over the `default_log_name` specified in the exporter.
actions:
- key: gcp.log_name
action: insert
value: apache-access-log
service:
logs:
receivers: [file_log]
processors: [memory_limiter, resource_detection, attributes]
exporters: [googlecloud]This would parse logs of the following example structure:
127.0.0.1 - - [26/Apr/2022:22:53:36 +0800] "GET / HTTP/1.1" 200 1247To the following GCP entry structure:
{
"logName": "projects/my-gcp-project/logs/apache-access-log",
"resource": {
"type": "gce_instance",
"labels": {
"instance_id": "",
"zone": ""
}
},
"textPayload": "127.0.0.1 - - [26/Apr/2022:22:53:36 +0800] \"GET / HTTP/1.1\" 200 1247",
"timestamp": "2022-05-02T12:16:14.574548493Z",
"httpRequest": {
"requestMethod": "GET",
"requestUrl": "/",
"status": 200,
"responseSize": "1247",
"remoteIp": "127.0.0.1",
"protocol": "HTTP/1.1"
}
}The logging exporter also supports the full range of GCP log severity levels,
which differ from the available OpenTelemetry log severity levels.
To accommodate this, the following mapping is used to equate an incoming OpenTelemetry SeverityNumber
to a matching GCP log severity:
OTel SeverityNumber/Name |
GCP severity level |
|---|---|
| Undefined | Default |
| 1-4 / Trace | Debug |
| 5-8 / Debug | Debug |
| 9-10 / Info | Info |
| 11-12 / Info | Notice |
| 13-16 / Warn | Warning |
| 17-20 / Error | Error |
| 21-22 / Fatal | Critical |
| 23 / Fatal | Alert |
| 24 / Fatal | Emergency |
The upstream severity parser (along
with the regex parser) allows for
additional flexibility in parsing log severity from incoming entries.
Multi-Project exporting
By default, the exporter sends telemetry to the project specified by project in the configuration. This can be overridden on a per-metrics basis using the gcp.project.id resource attribute. For example, if a metric has a label project, you could use the groupbyattrs processor to promote it to a resource label, and the resource processor to rename the attribute from project to gcp.project.id.
Multi-Project quota usage
The gcp.project.id label can be combined with the destination_project_quota option to attribute quota usage to the project parsed by the label. This feature is currently only available
for traces and metrics. The Collector's default service account will need roles/serviceusage.serviceUsageConsumer IAM permissions in the destination quota project.
Note that this option will not work if a quota project is already defined in your Collector's GCP credentials. In this case, the telemetry will fail to export with a "project not found" error.
This can be done by manually editing your ADC file (if it exists) to remove the quota_project_id entry line.
Features and Feature-Gates
See the Collector feature gates for an overview of feature gates in the collector.
Overview (`exporter/googlecloudpubsubexporter/README.md`)
Google Cloud Pub/Sub Exporter
| Status | |
|---|---|
| Stability | beta: traces, metrics, logs |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @alexvanboxel, @braydonk, @dpaasman00 |
β οΈ This is a community-provided module. It has been developed and extensively tested at Collibra, but it is not officially supported by GCP.
This exporter sends OTLP messages to a Google Cloud Pubsub topic.
The following configuration options are supported:
project(Optional): The Google Cloud Project of the topics.topic(Required): The topic name to send OTLP data over. The topic name should be a fully qualified resource
name (eg:projects/otel-project/topics/otlp).compression(Optional): Set the payload compression, onlygzipis supported. Default is no compression.watermarkBehaviour of how thece-timeattribute is set (see watermark section for more info)behavior(Optional):currentsets thece-timeattribute to the system clock,earliestsets the attribute to
the smallest timestamp of all the messages.allow_drift(Optional): The maximum difference thece-timeattribute can be set from the system clock. When the
drift is set to 0, the maximum drift from the clock is allowed (only applicable toearliest).
endpoint(Optional): Override the default Pubsub Endpoint, useful when connecting to the PubSub emulator instance
or switching between global and regional service endpoints.insecure(Optional): Allows performing βinsecureβ SSL connections and transfers, useful when connecting to a local
emulator instance. Only has effect if Endpoint is not ""ordering: Configures the PubSub ordering feature, see
ordering section for more info.enabled(default =false): Enables the ordering. Default is disabled.from_resource_attribute(no default): resource attribute that will be used as the ordering key. Required whenordering.enabledistrue. If the resource attribute is missing or has an empty value, the messages will not be
ordered for this resource.remove_resource_attribute(default =false): if the ordering key resource attribute specifiedfrom_resource_attributeshould be removed from the resource attributes.
traces,metricsandlogs(Optional): Allows overriding the standard OTLP Protobuf
encoding and the message attributes.
attributes.encoding(Optional): An encoding extension, if not specified it uses the default Protobuf marshaller.attributes(Optional): Attributes that will be added to the Pub/Sub message.
exporters:
googlecloudpubsub:
project: my-project
topic: projects/my-project/topics/otlp-tracesPubsub topic
The Google Cloud Pubsub exporter doesn't automatically create topics, it expects the topic
to be created upfront. Security wise it's best to give the collector its own service account and give the
topic Pub/Sub Publisher permission.
Messages
The message published on the topic are CloudEvent compliance and uses the binary content mode
defined in the
Google Cloud Pub/Sub Protocol Binding for CloudEvents
.
The data field is either a ExportTraceServiceRequest, ExportMetricsServiceRequest or ExportLogsServiceRequest for
traces, metrics or logs respectively. Each message is accompanied by the following attributes:
| attributes | description |
|---|---|
| ce-specversion | Follow version 1.0 of the CloudEvent spec |
| ce-source | The source is this /opentelemetry/collector/googlecloudpubsub/<version> exporter |
| ce-id | a random UUID to uniquely define the message |
| ce-time | a watermark indicating when the events, encapsulated in the OTLP message, where generated. The behavior will depend on the watermark setting in the configuration |
| ce-type | depending on the data org.opentelemetry.otlp.traces.v1, org.opentelemetry.otlp.metrics.v1 or org.opentelemetry.otlp.logs.v1 |
| content-type | the content type is application/protobuf |
| content-encoding | indicates that payload is compressed. Only gzip compression is supported |
Compression
By default, the messages are not compressed. By compressing the messages, the cost of Pubsub can be reduced to
up to 20% of the cost. This can be done by setting the compression to gzip.
exporters:
googlecloudpubsub:
project: my-project
topic: projects/my-project/topics/otlp-traces
compression: gzipThe exporter will add the content-encoding attribute to the message. The receiver will look at this attribute
to detect the compression that is used on the payload.
Only gzip is supported.
Watermark
A watermark is a threshold that indicates where streaming processing frameworks (like Apache Beam) expects all the
data in a window to have arrived. If new data arrives with a timestamp that's in the window but older than the
watermark, the data is considered late data. The watermark section will change the behaviour of the ce-time
attribute of the message. If you don't use such frameworks you can ignore the section and the ce-time will
be set to the current time, but to have a more reliable watermark behaviour in such streaming it's better to set
the ce-time attribute to the earliest timestamp of the messages embedded in the Pubsub message.
Setting the behaviour to earliest will scan all the embedded message before sending the actual Pubsub message to
figure out what the earliest timestamp is. You have to set allow_drift, the allowed maximum for the ce-time
timestamp , if you want to behaviour to have effect as the default is 0s.
exporters:
googlecloudpubsub:
project: my-project
topic: projects/my-project/topics/otlp-traces
watermark:
behavior: earliest
allow_drift: 1hThe default behavior is that the watermark is set to the current time of the processor. This timestamp will not differ
that much as the timestamp that is attached to a Pubsub message. Most users that don't do anything outside using Pubsub
as a global distribution system will not need anything else.
If you use Google Cloud Dataflow and want to rely on the advanced streaming
feature you may want to change the behavior of the watermark and de-duplication. You can leverage the unique id (ce-id)
and a timestamp (ce-time) attributes on the message. In Apache Beam (the framework used by Dataflow) you can set the
attributes names on the Pubsub connector
via the .withTimestampAttribute("ce-time") and .withIdAttribute("ce-id") methods. A good settings for this
scenario is behavior: earliest with a reasonable allow_drift of 1h.
Allowed behavior values are current or earliest. For allow_drift the default is 0s, so make sure to set the
value.
Ordering
When ordering is enabled (ordering.enabled), you are required to specify a resource attribute key that will be used as
the ordering key (ordering.from_resource_attribute). If this resource attribute is only meant to be used as an
ordering key, you may want to choose to get this resource attribute key (ordering.from_resource_attribute) removed
before publishing to PubSub by enabling the ordering.remove_resource_attribute configuration.
exporters:
googlecloudpubsub:
project: my-project
topic: projects/my-project/topics/otlp-traces
ordering:
enabled: true
from_resource_attribute: some.resource.attribute.key
remove_resource_attribute: trueNotes
While the PubSub topic doesn't require any configuration for ordering, you will need to enable ordering on your
subscription(s) if you need it. Enabling ordering on a subscription is only possible at creation.
For composite ordering keys you'd need to compose the resource attribute value before exporting e.g., by using a
transform processor
.
Empty values in the ordering key are accepted but won't be ordered, see PubSub ordering documentation
for more details.
PubSub requires one publish request per ordering key value, so this exporter groups the signals per ordering key before
publishing.
Encoding and message attributes
The traces, metrics and logs section allows you to specify Encoding Extensions for marshalling the messages on
the topic and the attributes on the Pub/Sub message. All the signals have the same config options.
It's important to note that when you use an extension all the CloudEvent attributes are removed as you use your own
encoder as the exporter can't know what valute to set. You have the opportunity to manually set them.
extensions:
otlp_encoding:
protocol: otlp_json
exporters:
googlecloudpubsub:
project: my-project
topic: projects/my-project/topics/otlp-traces
traces:
encoding: otlp_encoding
attributes:
"ce-type": "org.opentelemetry.otlp.traces.v1"
"content-type": "application/json"The encoding option allows you to specify Encoding Extensions for marshalling the messages on the topic. An
extension need to be configured in the extensions section, and added to pipeline in the collectors configuration file.
The attributes option allows you to set any attributes, the values are key/value pairs. You can avoid the removal of
CloudEvent attributes if you manually specify the ce-type and content-type to an appropriate value for the chosen
encoding.
Overview (`exporter/googlecloudstorageexporter/README.md`)
Google Cloud Storage Exporter
| Status | |
|---|---|
| Stability | development: traces |
| alpha: logs | |
| Distributions | contrib |
| Issues | |
| Code coverage | |
| Code Owners | @constanca-m, @braydonk | Seeking more code owners! |
This exporter writes received OpenTelemetry data to a cloud storage bucket.
Configuration
| Name | Description | Required | Default |
|---|---|---|---|
encoding |
The encoding extension ID to use for marshaling logs and traces. If left empty, plog.JSONMarshaler will be used for logs and ptrace.JSONMarshaler will be used for traces. |
No | |
bucket.project_id |
The project where the bucket will be created or where it exists. If left empty, it will query the metadata endpoint. It requires the collector to be running in a Google Cloud environment. | No | |
bucket.name |
Name for the bucket storage. | Yes | |
bucket.file_prefix |
Prefix for the created filename. This prefix is applied after the partition path (if any). | No | logs |
bucket.partition |
Configuration for time-based partitioning. See below for details. | No | |
bucket.reuse_if_exists |
Controls bucket creation behavior. If true, checks if bucket exists and uses it (requires storage.buckets.get permission on the bucket); fails if bucket doesn't exist. If false, attempts to create bucket; fails if bucket already exists (requires storage.buckets.create permission at project level). Set to true when the service account lacks project-level bucket creation permissions but has bucket-level permissions. |
No | false |
bucket.region |
Region where the bucket will be created or where it exists. If left empty, it will query the metadata endpoint. It requires the collector to be running in a Google Cloud environment. | Yes | |
bucket.compression |
Compression algorithm used to compress data before uploading. Valid values are gzip, zstd, or no value set for no compression. |
No | |
resource_attrs_to_gcs |
Mapping of GCS upload configuration values to resource attribute values. See resource_attrs_to_gcs below. | No | |
timeout |
Time to wait per individual attempt to send data to the backend. See exporterhelper docs for details. |
No | 5s |
retry_on_failure |
Configuration for how to retry failed requests. See exporterhelper docs for details. |
No | |
sending_queue |
Configuration for the internal sending queue. See exporterhelper docs for details. |
No |
Partition Configuration
The bucket.partition configuration allows you to organize files into time-based folders.
| Name | Description | Required | Default |
|---|---|---|---|
format |
Time format string for time-based partitions. If set, formatted UTC time is prepended to the filename. Supports strftime format (e.g., year=%Y/month=%m). |
No | |
prefix |
Prefix for the partition folder structure. If set, this value is prepended to the partition path. | No |
resource_attrs_to_gcs
| Name | Description | Required | Default |
|---|---|---|---|
prefix |
Resource attribute whose value is inserted as a partition path segment between bucket.partition.prefix and the time-based bucket.partition.format. If the attribute is present on the data, its value is used; otherwise the segment is omitted. |
No |
When resource_attrs_to_gcs.prefix is configured, a partition segment is derived from the
specified resource attribute, allowing data to be routed into per-attribute folders (for
example, one folder per host or service). The resulting layout is/<attribute value>//..., so the existingbucket.partition.prefix is preserved and the attribute segment is appended after it.
The attribute value is stringified, so non-string attributes are converted to their string
form (for example, the int 42 becomes 42 and a bool becomes true); complex types such
as maps or slices render as their textual representation and are not recommended.
Because resource attribute values are arbitrary and may be untrusted, the value is
normalized with the standard library path.Clean before being used as an object-name
segment: duplicate slashes are collapsed and empty, . and .. segments are removed
(so the value cannot traverse above its segment root). Leading and trailing / are
trimmed, while internal / are preserved so a value can span multiple folder levels
(e.g. service-a/logs). If the value normalizes to an empty string, no extra segment is
added. Note that high-cardinality attribute values produce a correspondingly large number
of object key prefixes.
Note: the attribute value is read from the first resource of each exported batch. If a batch can contain
multiple distinct attribute values and you need strict per-value routing, separate the
data upstream first using theroutingconnector
orgroupbyattrsprocessor.
Example
Here is an example configuration for this exporter:
exporters:
google_cloud_storage:
encoding: text_encoding
bucket:
name: bucket-test
project_id: project-test
reuse_if_exists: true
region: europe-west1
file_prefix: app-logs
partition:
prefix: archive
format: "year=%Y/month=%m/day=%d/hour=%H"
extensions:
# text encoding to ensure only the body is placed in the bucket
text_encoding:Routing by Resource Attribute
This configuration writes each service's data into its own folder by deriving a partition
segment from the service.name resource attribute, while keeping a static storage prefix:
exporters:
google_cloud_storage:
bucket:
name: archive-bucket
region: europe-west1
file_prefix: logs
partition:
prefix: storage
format: "%Y-%m-%d/%H"
resource_attrs_to_gcs:
prefix: service.nameGiven a resource with service.name = serviceA, an object is written to:
storage/serviceA/2026-06-17/14/logs_<uuid>If the service.name attribute is absent, the attribute segment is omitted and the object
is written to storage/2026-06-17/14/logs_.
Resiliency Settings
This exporter supports standard OpenTelemetry Collector resiliency settings. You can configure timeouts, retry behaviors, and a sending queue to ensure reliable data delivery to Google Cloud Storage.
exporters:
google_cloud_storage:
bucket:
name: bucket-test
region: europe-west1
timeout: 5s
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
sending_queue:
enabled: true
num_consumers: 10
queue_size: 1000For more details on how to configure these specific sections, refer to the exporterhelper configuration documentation.
Retry Behavior
This exporter utilizes two independent layers of retries:
Google Cloud SDK Retries (always on): The underlying Google Cloud Go SDK automatically retries transient errors (like network blips) in the background. By default, the SDK handles its own exponential backoff and idempotency checks.
Exporter Helper Retries (optional via retry_on_failure): This is the OpenTelemetry-level retry mechanism. It integrates with the sending queue to ensure data is not dropped during prolonged outages.
Important Notes on Retries:
If the Google Cloud SDK determines an error is permanent (e.g., unauthorized access) or not idempotent, the exporter will immediately wrap it as a permanent error. This halts the retry_on_failure loop and drops the payload to prevent infinite queue blocking. You can find more information on what the SDK considers retryable in the Google Cloud Storage Retry Strategy documentation.
Because file names are generated dynamically using a UUID and timestamp, each retry attempt by the OpenTelemetry retry_on_failure mechanism generates a new filename. In rare cases (such as when GCS commits an object but returns a transient error before the client receives acknowledgment) this can result in duplicate blobs in GCS.
Compression Example
exporters:
google_cloud_storage:
bucket:
name: compressed-logs-bucket
project_id: my-project
region: us-central1
compression: gzip
file_prefix: logs
partition:
format: "year=%Y/month=%m/day=%d"Using with Bucket-Level Permissions Only
When the service account lacks project-level bucket creation permissions but has bucket-level permissions:
exporters:
google_cloud_storage:
bucket:
name: existing-bucket
project_id: my-project
region: us-central1
reuse_if_exists: true
file_prefix: collector-logsWith reuse_if_exists: true, the exporter checks if the bucket exists using storage.buckets.get permission on that specific bucket (not project-level). If the bucket doesn't exist, the exporter will fail with an error. This allows service accounts with only bucket-level permissions to work without requiring project-level bucket creation permissions.
Overview (`exporter/googlemanagedprometheusexporter/README.md`)
Google Cloud Managed Prometheus Exporter
| Status | |
|---|---|
| Stability | beta: metrics |
| Distributions | contrib |
| Issues | [](https://git |