Skip to content

Commit ab4d726

Browse files
[receiver/datadog] Add initial support for metrics (#33631)
**Description:** This PR adds the initial structure required to add support for metrics in the Datadog receiver. This is the first of several PRs which will add support for v1 and v2 series endpoints, service checks, as well as sketches. The full version of the code can be found in the `cedwards/datadog-metrics-receiver-full` branch, or in Grafana Alloy: https://github.com/grafana/alloy/tree/main/internal/etc/datadogreceiver **Link to tracking Issue:** #18278 **Testing:** Unit tests have been added. More thorough tests will be included in follow-up PRs as the remaining functionality is added. **Documentation:** Updated README --------- Co-authored-by: Juraci Paixão Kröhling <[email protected]>
1 parent 976d653 commit ab4d726

File tree

15 files changed

+318
-54
lines changed

15 files changed

+318
-54
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: datadogreceiver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add support for metrics in Datadog receiver
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [18278]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

exporter/elasticsearchexporter/integrationtest/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,5 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/span
270270
replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl => ../../../pkg/ottl
271271

272272
replace github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector => ../../../connector/routingconnector
273+
274+
replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics => ../../../internal/exp/metrics

receiver/datadogreceiver/README.md

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,50 @@
1-
# Datadog APM Receiver
1+
# Datadog Receiver
22

33
<!-- status autogenerated section -->
44
| Status | |
55
| ------------- |-----------|
6-
| Stability | [alpha]: traces |
6+
| Stability | [development]: metrics |
7+
| | [alpha]: traces |
78
| Distributions | [contrib] |
89
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Areceiver%2Fdatadog%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Areceiver%2Fdatadog) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Areceiver%2Fdatadog%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Areceiver%2Fdatadog) |
910
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@boostchicken](https://www.github.com/boostchicken), [@gouthamve](https://www.github.com/gouthamve), [@jpkrohling](https://www.github.com/jpkrohling), [@MovieStoreGuy](https://www.github.com/MovieStoreGuy) |
1011

12+
[development]: https://github.com/open-telemetry/opentelemetry-collector#development
1113
[alpha]: https://github.com/open-telemetry/opentelemetry-collector#alpha
1214
[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
1315
<!-- end autogenerated section -->
1416

1517
## Overview
16-
Accepts traces in the Datadog APM format.
17-
### Supported Datadog APIs
18-
19-
- v0.3 (msgpack and json)
20-
- v0.4 (msgpack and json)
21-
- v0.5 (msgpack custom format)
22-
- v0.6
23-
- v0.7
18+
19+
The Datadog receiver enables translation between Datadog and OpenTelemetry-compatible backends.
20+
It currently has support for Datadog's APM traces and Datadog metrics.
21+
2422
## Configuration
2523

26-
Example:
24+
Configuration wise is very simple, just need to specify where the Datadog receiver should listen and the read timeout.
25+
26+
Then, the receiver must be configured in the pipeline where it will be used.
27+
2728

2829
```yaml
2930
receivers:
3031
datadog:
3132
endpoint: localhost:8126
3233
read_timeout: 60s
34+
35+
exporters:
36+
debug:
37+
38+
service:
39+
pipelines:
40+
metrics:
41+
receivers: [datadog]
42+
exporters: [debug]
43+
traces:
44+
receivers: [datadog]
45+
exporters: [debug]
3346
```
47+
3448
### read_timeout (Optional)
3549
The read timeout of the HTTP Server
3650
@@ -45,3 +59,33 @@ https://github.com/open-telemetry/opentelemetry-collector/tree/main/config/confi
4559
### Default Attributes
4660
4761
- `dd.span.Resource`: The datadog resource name (as distinct from the span name)
62+
63+
### Datadog's API support
64+
65+
**Traces**
66+
67+
| Datadog API Endpoint | Status | Notes |
68+
|----------------------|---------|------------------------------|
69+
| /v0.3/traces | Alpha | Support for msgpack and json |
70+
| /v0.4/traces | Alpha | Support for msgpack and json |
71+
| /v0.5/traces | Alpha | Msgpack custom format |
72+
| /v0.7/traces | Alpha | |
73+
| /api/v0.2/traces | Alpha | |
74+
75+
**Metrics**
76+
77+
| Datadog API Endpoint | Status | Notes |
78+
|-----------------------------|-------------|-------|
79+
| /api/v1/series | Development | |
80+
| /api/v2/series | Development | |
81+
| /api/v1/check_run | Development | |
82+
| /api/v1/sketches | Development | |
83+
| /api/beta/sketches | Development | |
84+
| /api/v1/distribution_points | Development | |
85+
| /intake | Development | |
86+
87+
### Temporality considerations
88+
89+
Some backends use a different [timestamp temporality](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#temporality) than Datadog uses. Both delta and cumulative temporalities are allowed in the spec.
90+
In order to store metrics on these backends, the receiver will need to translate the timestamps.
91+
For backends that use cumulative temporality, a [delta to cumulative processor](../../processor/deltatocumulativeprocessor/README.md) can be configured in the pipeline.

receiver/datadogreceiver/factory.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func NewFactory() receiver.Factory {
2121
return receiver.NewFactory(
2222
metadata.Type,
2323
createDefaultConfig,
24+
receiver.WithMetrics(createMetricsReceiver, metadata.MetricsStability),
2425
receiver.WithTraces(createTracesReceiver, metadata.TracesStability))
2526

2627
}
@@ -34,12 +35,33 @@ func createDefaultConfig() component.Config {
3435
}
3536
}
3637

37-
func createTracesReceiver(_ context.Context, params receiver.Settings, cfg component.Config, consumer consumer.Traces) (r receiver.Traces, err error) {
38+
func createTracesReceiver(_ context.Context, params receiver.Settings, cfg component.Config, consumer consumer.Traces) (receiver.Traces, error) {
39+
var err error
3840
rcfg := cfg.(*Config)
39-
r = receivers.GetOrAdd(cfg, func() component.Component {
40-
dd, _ := newDataDogReceiver(rcfg, consumer, params)
41+
r := receivers.GetOrAdd(rcfg, func() (dd component.Component) {
42+
dd, err = newDataDogReceiver(rcfg, params)
4143
return dd
4244
})
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
r.Unwrap().(*datadogReceiver).nextTracesConsumer = consumer
50+
return r, nil
51+
}
52+
53+
func createMetricsReceiver(_ context.Context, params receiver.Settings, cfg component.Config, consumer consumer.Metrics) (receiver.Metrics, error) {
54+
var err error
55+
rcfg := cfg.(*Config)
56+
r := receivers.GetOrAdd(cfg, func() (dd component.Component) {
57+
dd, err = newDataDogReceiver(rcfg, params)
58+
return dd
59+
})
60+
if err != nil {
61+
return nil, err
62+
}
63+
64+
r.Unwrap().(*datadogReceiver).nextMetricsConsumer = consumer
4365
return r, nil
4466
}
4567

receiver/datadogreceiver/factory_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,22 @@ import (
1212
"go.opentelemetry.io/collector/receiver/receivertest"
1313
)
1414

15-
func TestCreateReceiver(t *testing.T) {
15+
func TestCreateTracesReceiver(t *testing.T) {
1616
factory := NewFactory()
1717
cfg := factory.CreateDefaultConfig()
1818
cfg.(*Config).Endpoint = "http://localhost:0"
1919

2020
tReceiver, err := factory.CreateTracesReceiver(context.Background(), receivertest.NewNopSettings(), cfg, consumertest.NewNop())
2121
assert.NoError(t, err)
22-
assert.NotNil(t, tReceiver, "receiver creation failed")
22+
assert.NotNil(t, tReceiver, "traces receiver creation failed")
23+
}
24+
25+
func TestCreateMetricsReceiver(t *testing.T) {
26+
factory := NewFactory()
27+
cfg := factory.CreateDefaultConfig()
28+
cfg.(*Config).Endpoint = "http://localhost:0"
29+
30+
tReceiver, err := factory.CreateMetricsReceiver(context.Background(), receivertest.NewNopSettings(), cfg, consumertest.NewNop())
31+
assert.NoError(t, err)
32+
assert.NotNil(t, tReceiver, "metrics receiver creation failed")
2333
}

receiver/datadogreceiver/generated_component_test.go

Lines changed: 7 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

receiver/datadogreceiver/go.mod

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.21.0
44

55
require (
66
github.com/DataDog/datadog-agent/pkg/proto v0.56.0-devel.0.20240621152414-10454a30138d
7+
github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.104.0
78
github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.104.0
89
github.com/stretchr/testify v1.9.0
910
github.com/vmihailenco/msgpack/v4 v4.3.13
@@ -17,6 +18,7 @@ require (
1718
go.opentelemetry.io/otel/metric v1.27.0
1819
go.opentelemetry.io/otel/trace v1.27.0
1920
go.uber.org/goleak v1.3.0
21+
go.uber.org/zap v1.27.0
2022
google.golang.org/protobuf v1.34.2
2123
)
2224

@@ -43,6 +45,7 @@ require (
4345
github.com/mitchellh/reflectwalk v1.0.2 // indirect
4446
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4547
github.com/modern-go/reflect2 v1.0.2 // indirect
48+
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.104.0 // indirect
4649
github.com/philhofer/fwd v1.1.2 // indirect
4750
github.com/pmezard/go-difflib v1.0.0 // indirect
4851
github.com/prometheus/client_golang v1.19.1 // indirect
@@ -68,7 +71,6 @@ require (
6871
go.opentelemetry.io/otel/sdk v1.27.0 // indirect
6972
go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect
7073
go.uber.org/multierr v1.11.0 // indirect
71-
go.uber.org/zap v1.27.0 // indirect
7274
golang.org/x/net v0.26.0 // indirect
7375
golang.org/x/sys v0.21.0 // indirect
7476
golang.org/x/text v0.16.0 // indirect
@@ -84,3 +86,11 @@ retract (
8486
v0.76.2
8587
v0.76.1
8688
)
89+
90+
replace github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics => ../../internal/exp/metrics
91+
92+
replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest => ../../pkg/pdatatest
93+
94+
replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden => ../../pkg/golden
95+
96+
replace github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil => ../../pkg/pdatautil

receiver/datadogreceiver/internal/metadata/generated_status.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

receiver/datadogreceiver/metadata.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ status:
55
class: receiver
66
stability:
77
alpha: [traces]
8+
development: [metrics]
89
distributions: [contrib]
910
codeowners:
1011
active: [boostchicken, gouthamve, jpkrohling, MovieStoreGuy]
12+
13+
tests:
14+
skip_lifecycle: true # Skip lifecycle tests since there are multiple receivers that run on the same port
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package datadogreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/datadogreceiver"
5+
import (
6+
"sync"
7+
8+
"go.opentelemetry.io/collector/component"
9+
"go.opentelemetry.io/collector/pdata/pcommon"
10+
11+
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics/identity"
12+
)
13+
14+
type MetricsTranslator struct {
15+
sync.RWMutex
16+
buildInfo component.BuildInfo
17+
lastTs map[identity.Stream]pcommon.Timestamp
18+
}
19+
20+
func newMetricsTranslator() *MetricsTranslator {
21+
return &MetricsTranslator{
22+
lastTs: make(map[identity.Stream]pcommon.Timestamp),
23+
}
24+
}

0 commit comments

Comments
 (0)