Skip to content

feat(outputs.opentelemetry): Support dot-separated OpenTelemetry metric names#18680

Open
mchrome wants to merge 5 commits intoinfluxdata:masterfrom
mchrome:feat/18251/Support-dot-separated-OpenTelemetry-metrics-names
Open

feat(outputs.opentelemetry): Support dot-separated OpenTelemetry metric names#18680
mchrome wants to merge 5 commits intoinfluxdata:masterfrom
mchrome:feat/18251/Support-dot-separated-OpenTelemetry-metrics-names

Conversation

@mchrome
Copy link
Copy Markdown

@mchrome mchrome commented Apr 9, 2026

Summary

This is a reopened PR #18252 which was closed due to inactivity. I've personally reviewed the changes in this one and can answer any questions or make changes which may be requested during the review process.

Summary from original PR:

This PR adds support for preserving dot-separated OpenTelemetry metric names in the OpenTelemetry output plugin, addressing issue #18251.

Added a new metric_name_format configuration option that allows users to choose between:

prometheus (default): Converts dots to underscores - maintains backward compatibility
otel: Preserves dot-separated names - enables OpenTelemetry semantic conventions

This PR adds support for preserving dot-separated OpenTelemetry metric names in the OpenTelemetry output plugin

Checklist

Related issues

resolves #18251

@telegraf-tiger telegraf-tiger bot added feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/output 1. Request for new output plugins 2. Issues/PRs that are related to out plugins labels Apr 9, 2026
@telegraf-tiger
Copy link
Copy Markdown
Contributor

telegraf-tiger bot commented Apr 9, 2026

@mchrome
Copy link
Copy Markdown
Author

mchrome commented Apr 13, 2026

@srebhan Could you take a look at this PR?

Copy link
Copy Markdown
Member

@srebhan srebhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mchrome! I do have some comments...

Comment on lines +86 to +90
if o.MetricNameFormat == "" {
o.MetricNameFormat = defaultMetricNameFormat
}
switch o.MetricNameFormat {
case "prometheus", "otel":
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if o.MetricNameFormat == "" {
o.MetricNameFormat = defaultMetricNameFormat
}
switch o.MetricNameFormat {
case "prometheus", "otel":
switch o.MetricNameFormat {
case "":
o.MetricNameFormat = "prometheus"
case "prometheus", "otel":

defaultServiceAddress = "localhost:4317"
defaultTimeout = config.Duration(5 * time.Second)
defaultCompression = "gzip"
defaultMetricNameFormat = "prometheus"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not add constants for this! There is no benefit really!

ServiceAddress: defaultServiceAddress,
Timeout: defaultTimeout,
Compression: defaultCompression,
MetricNameFormat: defaultMetricNameFormat,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be set in Init()!

Comment on lines +345 to +351
// Only check metadata if it exists (for tests that provide headers)
ctxMetadata, ok := metadata.FromIncomingContext(ctx)
require.Equal(m.t, []string{"header1"}, ctxMetadata.Get("test"))
require.True(m.t, ok)
if ok {
if testHeader := ctxMetadata.Get("test"); len(testHeader) > 0 {
require.Equal(m.t, []string{"header1"}, testHeader)
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change necessary?

return pmetricotlp.NewExportResponse(), nil
}

func TestOpenTelemetryMetricNameFormatPrometheus(t *testing.T) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about

Suggested change
func TestOpenTelemetryMetricNameFormatPrometheus(t *testing.T) {
func TestNameFormatPrometheus(t *testing.T) {

Comment on lines +395 to +399
got := m.GotMetrics()
require.Equal(t, 1, got.ResourceMetrics().Len())
require.Equal(t, 1, got.ResourceMetrics().At(0).ScopeMetrics().Len())
require.Equal(t, 1, got.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().Len())
require.Equal(t, "http_server_duration", got.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0).Name())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All other tests compare the JSON representation of the metric. Can we please stick to this? Same for the other tests below.

Comment on lines +191 to +192
metricName := o.transformMetricName(metric.Name())
err := batch.AddPoint(metricName, metric.Tags(), metric.Fields(), metric.Time(), vType)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fold the code in here

Suggested change
metricName := o.transformMetricName(metric.Name())
err := batch.AddPoint(metricName, metric.Tags(), metric.Fields(), metric.Time(), vType)
// Transform the metric name if required
name := metric.Name()
switch o.MetricNameFormat
case "prometheus":
// Prometheus doesn't like dots
name = strings.ReplaceAll(name, ".", "_")
}
err := batch.AddPoint(name, metric.Tags(), metric.Fields(), metric.Time(), vType)

Comment on lines +86 to +88
if o.MetricNameFormat == "" {
o.MetricNameFormat = defaultMetricNameFormat
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this change the existing behavior? In the existing code we do not replace anything in the metric name, do we?

Comment on lines +11 to +13
## Override the default (prometheus) metric name format
## prometheus: converts dots to underscores (default, Prometheus-compatible)
## otel: preserves dot-separated names (OpenTelemetry semantic conventions)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be brief, defaults are documented in the option!

Suggested change
## Override the default (prometheus) metric name format
## prometheus: converts dots to underscores (default, Prometheus-compatible)
## otel: preserves dot-separated names (OpenTelemetry semantic conventions)
## Transform metric names according to the given format, available options:
## prometheus -- converts dots to underscores
## otel -- keep metric names as-is

## Override the default (prometheus) metric name format
## prometheus: converts dots to underscores (default, Prometheus-compatible)
## otel: preserves dot-separated names (OpenTelemetry semantic conventions)
# metric_name_format = "prometheus"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the code before this PR, I don't see where we replace dots with underscores, so you are changing the default behavior and break everyone using this plugin. Am I missing anything?

@srebhan srebhan self-assigned this Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/output 1. Request for new output plugins 2. Issues/PRs that are related to out plugins

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dot-separated OpenTelemetry metric names in OpenTelemetry output plugin

3 participants