Skip to content

Commit

Permalink
[exporter/datadog] Add telemetry metric for runtime metrics (open-tel…
Browse files Browse the repository at this point in the history
…emetry#23138)

* Add telemetry metric

* Change DefaultMetrics function signature

* Update metadata type

* Update test

* Add changelog

* PR comments

* Update exporter/datadogexporter/internal/metrics/consumer.go

Co-authored-by: Yang Song <[email protected]>

---------

Co-authored-by: Yang Song <[email protected]>
  • Loading branch information
2 people authored and Caleb-Hurshman committed Jul 6, 2023
1 parent c9c0162 commit 3fc35fa
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 24 deletions.
20 changes: 20 additions & 0 deletions .chloggen/stanley.liu_add-telemetry-metric.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Use this changelog template to create an entry for release notes.
# If your change doesn't affect end users, such as a test fix or a tooling change,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: exporter/datadog

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Adds metric otel.datadog_exporter.runtime_metrics.running to track when the Datadog Exporter receives a payload containing runtime metrics.

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [23138]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
17 changes: 12 additions & 5 deletions exporter/datadogexporter/internal/metrics/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,28 +54,35 @@ func (c *Consumer) toDataType(dt metrics.DataType) (out datadogV2.MetricIntakeTy
}

// runningMetrics gets the running metrics for the exporter.
func (c *Consumer) runningMetrics(timestamp uint64, buildInfo component.BuildInfo) (series []datadogV2.MetricSeries) {
func (c *Consumer) runningMetrics(timestamp uint64, buildInfo component.BuildInfo, metadata metrics.Metadata) (series []datadogV2.MetricSeries) {
buildTags := TagsFromBuildInfo(buildInfo)
for host := range c.seenHosts {
// Report the host as running
runningMetric := DefaultMetrics("metrics", host, timestamp, buildInfo)
runningMetric := DefaultMetrics("metrics", host, timestamp, buildTags)
series = append(series, runningMetric...)
}

for tag := range c.seenTags {
runningMetrics := DefaultMetrics("metrics", "", timestamp, buildInfo)
runningMetrics := DefaultMetrics("metrics", "", timestamp, buildTags)
for i := range runningMetrics {
runningMetrics[i].Tags = append(runningMetrics[i].Tags, tag)
}
series = append(series, runningMetrics...)
}

for _, lang := range metadata.Languages {
tags := append(buildTags, "language:"+lang) // nolint
runningMetric := DefaultMetrics("runtime_metrics", "", timestamp, tags)
series = append(series, runningMetric...)
}

return
}

// All gets all metrics (consumed metrics and running metrics).
func (c *Consumer) All(timestamp uint64, buildInfo component.BuildInfo, tags []string) ([]datadogV2.MetricSeries, sketches.SketchSeriesList, []pb.ClientStatsPayload) {
func (c *Consumer) All(timestamp uint64, buildInfo component.BuildInfo, tags []string, metadata metrics.Metadata) ([]datadogV2.MetricSeries, sketches.SketchSeriesList, []pb.ClientStatsPayload) {
series := c.ms
series = append(series, c.runningMetrics(timestamp, buildInfo)...)
series = append(series, c.runningMetrics(timestamp, buildInfo, metadata)...)
if len(tags) == 0 {
return series, c.sl, c.as
}
Expand Down
13 changes: 7 additions & 6 deletions exporter/datadogexporter/internal/metrics/consumer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ func TestRunningMetrics(t *testing.T) {

ctx := context.Background()
consumer := NewConsumer()
_, err := tr.MapMetrics(ctx, ms, consumer)
metadata, err := tr.MapMetrics(ctx, ms, consumer)
assert.NoError(t, err)

var runningHostnames []string
for _, metric := range consumer.runningMetrics(0, component.BuildInfo{}) {
for _, metric := range consumer.runningMetrics(0, component.BuildInfo{}, metadata) {
for _, res := range metric.Resources {
runningHostnames = append(runningHostnames, *res.Name)
}
Expand Down Expand Up @@ -104,10 +104,10 @@ func TestTagsMetrics(t *testing.T) {

ctx := context.Background()
consumer := NewConsumer()
_, err := tr.MapMetrics(ctx, ms, consumer)
metadata, err := tr.MapMetrics(ctx, ms, consumer)
assert.NoError(t, err)

runningMetrics := consumer.runningMetrics(0, component.BuildInfo{})
runningMetrics := consumer.runningMetrics(0, component.BuildInfo{}, metadata)
var runningTags []string
var runningHostnames []string
for _, metric := range runningMetrics {
Expand All @@ -123,15 +123,16 @@ func TestTagsMetrics(t *testing.T) {
}

func TestConsumeAPMStats(t *testing.T) {
var md metrics.Metadata
c := NewConsumer()
for _, sp := range testutil.StatsPayloads {
c.ConsumeAPMStats(sp)
}
require.Len(t, c.as, len(testutil.StatsPayloads))
require.ElementsMatch(t, c.as, testutil.StatsPayloads)
_, _, out := c.All(0, component.BuildInfo{}, []string{})
_, _, out := c.All(0, component.BuildInfo{}, []string{}, md)
require.ElementsMatch(t, out, testutil.StatsPayloads)
_, _, out = c.All(0, component.BuildInfo{}, []string{"extra:key"})
_, _, out = c.All(0, component.BuildInfo{}, []string{"extra:key"}, md)
var copies []pb.ClientStatsPayload
for _, sp := range testutil.StatsPayloads {
sp.Tags = append(sp.Tags, "extra:key")
Expand Down
21 changes: 13 additions & 8 deletions exporter/datadogexporter/internal/metrics/series.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,7 @@ func NewCount(name string, ts uint64, value float64, tags []string) datadogV2.Me
}

// DefaultMetrics creates built-in metrics to report that an exporter is running
func DefaultMetrics(exporterType string, hostname string, timestamp uint64, buildInfo component.BuildInfo) []datadogV2.MetricSeries {
var tags []string
if buildInfo.Version != "" {
tags = append(tags, "version:"+buildInfo.Version)
}
if buildInfo.Command != "" {
tags = append(tags, "command:"+buildInfo.Command)
}
func DefaultMetrics(exporterType string, hostname string, timestamp uint64, tags []string) []datadogV2.MetricSeries {
metrics := []datadogV2.MetricSeries{
NewGauge(fmt.Sprintf("otel.datadog_exporter.%s.running", exporterType), timestamp, 1.0, tags),
}
Expand All @@ -73,3 +66,15 @@ func DefaultMetrics(exporterType string, hostname string, timestamp uint64, buil
}
return metrics
}

// TagsFromBuildInfo returns a list of tags derived from buildInfo to be used when creating metrics
func TagsFromBuildInfo(buildInfo component.BuildInfo) []string {
var tags []string
if buildInfo.Version != "" {
tags = append(tags, "version:"+buildInfo.Version)
}
if buildInfo.Command != "" {
tags = append(tags, "command:"+buildInfo.Command)
}
return tags
}
24 changes: 23 additions & 1 deletion exporter/datadogexporter/internal/metrics/series_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestDefaultMetrics(t *testing.T) {
Command: "otelcontribcol",
}

ms := DefaultMetrics("metrics", "test-host", uint64(2e9), buildInfo)
ms := DefaultMetrics("metrics", "test-host", uint64(2e9), TagsFromBuildInfo(buildInfo))

assert.Equal(t, "otel.datadog_exporter.metrics.running", ms[0].Metric)
// Assert metrics list length (should be 1)
Expand All @@ -61,3 +61,25 @@ func TestDefaultMetrics(t *testing.T) {
// Assert no other tags are set
assert.ElementsMatch(t, []string{"version:1.0", "command:otelcontribcol"}, ms[0].Tags)
}

func TestDefaultMetricsWithRuntimeMetrics(t *testing.T) {
buildInfo := component.BuildInfo{
Version: "1.0",
Command: "otelcontribcol",
}

tags := append(TagsFromBuildInfo(buildInfo), "language:go")
ms := DefaultMetrics("runtime_metrics", "test-host", uint64(2e9), tags)

assert.Equal(t, "otel.datadog_exporter.runtime_metrics.running", ms[0].Metric)
// Assert metrics list length (should be 1)
assert.Equal(t, 1, len(ms))
// Assert timestamp
assert.Equal(t, int64(2), *ms[0].Points[0].Timestamp)
// Assert value (should always be 1.0)
assert.Equal(t, 1.0, *ms[0].Points[0].Value)
// Assert hostname tag is set
assert.Equal(t, "test-host", *ms[0].Resources[0].Name)
// Assert no other tags are set
assert.ElementsMatch(t, []string{"version:1.0", "command:otelcontribcol", "language:go"}, ms[0].Tags)
}
4 changes: 2 additions & 2 deletions exporter/datadogexporter/metrics_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func (exp *metricsExporter) PushMetricsData(ctx context.Context, md pmetric.Metr
} else {
consumer = metrics.NewZorkianConsumer()
}
_, err := exp.tr.MapMetrics(ctx, md, consumer)
metadata, err := exp.tr.MapMetrics(ctx, md, consumer)
if err != nil {
return fmt.Errorf("failed to map metrics: %w", err)
}
Expand All @@ -203,7 +203,7 @@ func (exp *metricsExporter) PushMetricsData(ctx context.Context, md pmetric.Metr
var sp []pb.ClientStatsPayload
if isMetricExportV2Enabled() {
var ms []datadogV2.MetricSeries
ms, sl, sp = consumer.(*metrics.Consumer).All(exp.getPushTime(), exp.params.BuildInfo, tags)
ms, sl, sp = consumer.(*metrics.Consumer).All(exp.getPushTime(), exp.params.BuildInfo, tags, metadata)
ms = metrics.PrepareSystemMetrics(ms)
ms = metrics.PrepareContainerMetrics(ms)

Expand Down
5 changes: 3 additions & 2 deletions exporter/datadogexporter/traces_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,15 @@ func (exp *traceExporter) consumeTraces(

func (exp *traceExporter) exportUsageMetrics(ctx context.Context, hosts map[string]struct{}, tags map[string]struct{}) {
now := pcommon.NewTimestampFromTime(time.Now())
buildTags := metrics.TagsFromBuildInfo(exp.params.BuildInfo)
var err error
if isMetricExportV2Enabled() {
series := make([]datadogV2.MetricSeries, 0, len(hosts)+len(tags))
for host := range hosts {
series = append(series, metrics.DefaultMetrics("traces", host, uint64(now), exp.params.BuildInfo)...)
series = append(series, metrics.DefaultMetrics("traces", host, uint64(now), buildTags)...)
}
for tag := range tags {
ms := metrics.DefaultMetrics("traces", "", uint64(now), exp.params.BuildInfo)
ms := metrics.DefaultMetrics("traces", "", uint64(now), buildTags)
for i := range ms {
ms[i].Tags = append(ms[i].Tags, tag)
}
Expand Down

0 comments on commit 3fc35fa

Please sign in to comment.