Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,34 @@ otelcol.exporter.prometheus "<LABEL>" {

You can use the following arguments with `otelcol.exporter.prometheus`:

| Name | Type | Description | Default | Required |
| ---------------------------------- | ----------------------- | ----------------------------------------------------------------- | ------- | -------- |
| `forward_to` | `list(MetricsReceiver)` | Where to forward converted Prometheus metrics. | | yes |
| `add_metric_suffixes` | `bool` | Whether to add type and unit suffixes to metric names. | `true` | no |
| `gc_frequency` | `duration` | How often to clean up stale metrics from memory. | `"5m"` | no |
| `include_scope_info` | `bool` | Whether to include `otel_scope_info` metrics. | `false` | no |
| `include_scope_labels` | `bool` | Whether to include additional OTLP labels in all metrics. | `true` | no |
| `include_target_info` | `bool` | Whether to include `target_info` metrics. | `true` | no |
| `resource_to_telemetry_conversion` | `bool` | Whether to convert OTel resource attributes to Prometheus labels. | `false` | no |
| Name | Type | Description | Default | Required |
| ---------------------------------- | ----------------------- | ------------------------------------------------------------------------------ | ------- | -------- |
| `forward_to` | `list(MetricsReceiver)` | Where to forward converted Prometheus metrics. | | yes |
| `add_metric_suffixes` | `bool` | Whether to add type and unit suffixes to metric names. | `true` | no |
| `gc_frequency` | `duration` | How often to clean up stale metrics from memory. | `"5m"` | no |
| `honor_metadata` | `bool` | (Experimental) Whether to send metric metadata to downstream components. | `false` | no |
| `include_scope_info` | `bool` | Whether to include `otel_scope_info` metrics. | `false` | no |
| `include_scope_labels` | `bool` | Whether to include additional OTLP labels in all metrics. | `true` | no |
| `include_target_info` | `bool` | Whether to include `target_info` metrics. | `true` | no |
| `resource_to_telemetry_conversion` | `bool` | Whether to convert OTel resource attributes to Prometheus labels. | `false` | no |

By default, OpenTelemetry resources are converted into `target_info` metrics.
OpenTelemetry instrumentation scopes are converted into `otel_scope_info` metrics.
Set the `include_scope_info` and `include_target_info` arguments to `false`, respectively, to disable the custom metrics.

{{< admonition type="warning" >}}
**EXPERIMENTAL**: The `honor_metadata` argument is an [experimental][] feature.
If you enable this argument, resource consumption may increase, particularly if you ingest many metrics with different names.
Some downstream components aren't compatible with Prometheus metadata.
The following components are compatible:

* `otelcol.receiver.prometheus`
* `prometheus.remote_write` only when configured for Remote Write v2.
* `prometheus.write_queue`

[experimental]: ../../../get-started/configuration-syntax/expressions/function_calls/#experimental-functions
{{< /admonition >}}

When `include_scope_labels` is `true` the `otel_scope_name` and `otel_scope_version` labels are added to every converted metric sample.

When `include_target_info` is true, OpenTelemetry Collector resources are converted into `target_info` metrics.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type Options struct {
AddMetricSuffixes bool
// ResourceToTelemetryConversion controls whether to convert resource attributes to Prometheus-compatible datapoint attributes
ResourceToTelemetryConversion bool
HonorMetadata bool
}

var _ consumer.Metrics = (*Converter)(nil)
Expand Down Expand Up @@ -136,13 +137,18 @@ func (conv *Converter) consumeResourceMetrics(app storage.Appender, rm pmetric.R
resAttrs := rm.Resource().Attributes()
memResource := conv.getOrCreateResource(rm.Resource())

if conv.getOpts().IncludeTargetInfo {
if err := resourceMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write target_info metadata", "err", err)
}
opts := conv.getOpts()
if opts.IncludeTargetInfo {
// Write series data first, so the series exists before we write metadata.
if err := memResource.WriteTo(app, time.Now()); err != nil {
level.Error(conv.log).Log("msg", "failed to write target_info metric", "err", err)
}
// Write metadata after series data, so the series exists in the appender.
if opts.HonorMetadata {
if err := resourceMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write target_info metadata", "err", err)
}
}
}

for smcount := 0; smcount < rm.ScopeMetrics().Len(); smcount++ {
Expand Down Expand Up @@ -228,13 +234,18 @@ func (conv *Converter) consumeScopeMetrics(app storage.Appender, memResource *me
})
memScope := conv.getOrCreateScope(memResource, sm.Scope())

if conv.getOpts().IncludeScopeInfo {
if err := scopeMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write otel_scope_info metadata", "err", err)
}
opts := conv.getOpts()
if opts.IncludeScopeInfo {
// Write series data first, so the series exists before we write metadata.
if err := memScope.WriteTo(app, time.Now()); err != nil {
level.Error(conv.log).Log("msg", "failed to write otel_scope_info metric", "err", err)
}
// Write metadata after series data, so the series exists in the appender.
if opts.HonorMetadata {
if err := scopeMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write otel_scope_info metadata", "err", err)
}
}
}

for mcount := 0; mcount < sm.Metrics().Len(); mcount++ {
Expand Down Expand Up @@ -307,10 +318,8 @@ func (conv *Converter) consumeGauge(app storage.Appender, memResource *memorySer
Unit: m.Unit(),
Help: m.Description(),
})
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}

// Write series data first, so the series exists before we write metadata.
for dpcount := 0; dpcount < m.Gauge().DataPoints().Len(); dpcount++ {
dp := m.Gauge().DataPoints().At(dpcount)

Expand All @@ -323,6 +332,13 @@ func (conv *Converter) consumeGauge(app storage.Appender, memResource *memorySer
level.Error(conv.log).Log("msg", "failed to write metric sample", metricName, "err", err)
}
}

// Write metadata after series data, so the series exists in the appender.
if conv.getOpts().HonorMetadata {
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}
}
}

type otelcolDataPoint interface {
Expand Down Expand Up @@ -442,10 +458,8 @@ func (conv *Converter) consumeSum(app storage.Appender, memResource *memorySerie
Unit: m.Unit(),
Help: m.Description(),
})
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}

// Write series data first, so the series exists before we write metadata.
for dpcount := 0; dpcount < m.Sum().DataPoints().Len(); dpcount++ {
dp := m.Sum().DataPoints().At(dpcount)

Expand All @@ -468,6 +482,13 @@ func (conv *Converter) consumeSum(app storage.Appender, memResource *memorySerie
}
}
}

// Write metadata after series data, so the series exists in the appender.
if conv.getOpts().HonorMetadata {
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}
}
}

func (conv *Converter) consumeHistogram(app storage.Appender, memResource *memorySeries, memScope *memorySeries, m pmetric.Metric, resAttrs pcommon.Map) {
Expand All @@ -485,10 +506,8 @@ func (conv *Converter) consumeHistogram(app storage.Appender, memResource *memor
Unit: m.Unit(),
Help: m.Description(),
})
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}

// Write series data first, so the series exists before we write metadata.
for dpcount := 0; dpcount < m.Histogram().DataPoints().Len(); dpcount++ {
dp := m.Histogram().DataPoints().At(dpcount)

Expand Down Expand Up @@ -604,6 +623,13 @@ func (conv *Converter) consumeHistogram(app storage.Appender, memResource *memor
}
}
}

// Write metadata after series data, so the series exists in the appender.
if conv.getOpts().HonorMetadata {
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}
}
}

func (conv *Converter) consumeExponentialHistogram(app storage.Appender, memResource *memorySeries, memScope *memorySeries, m pmetric.Metric, resAttrs pcommon.Map) {
Expand All @@ -619,10 +645,8 @@ func (conv *Converter) consumeExponentialHistogram(app storage.Appender, memReso
Unit: m.Unit(),
Help: m.Description(),
})
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}

// Write series data first, so the series exists before we write metadata.
for dpcount := 0; dpcount < m.ExponentialHistogram().DataPoints().Len(); dpcount++ {
dp := m.ExponentialHistogram().DataPoints().At(dpcount)

Expand Down Expand Up @@ -657,6 +681,13 @@ func (conv *Converter) consumeExponentialHistogram(app storage.Appender, memReso
}
}
}

// Write metadata after series data, so the series exists in the appender.
if conv.getOpts().HonorMetadata {
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}
}
}

// Convert Otel Exemplar to Prometheus Exemplar.
Expand Down Expand Up @@ -695,10 +726,8 @@ func (conv *Converter) consumeSummary(app storage.Appender, memResource *memoryS
Unit: m.Unit(),
Help: m.Description(),
})
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}

// Write series data first, so the series exists before we write metadata.
for dpcount := 0; dpcount < m.Summary().DataPoints().Len(); dpcount++ {
dp := m.Summary().DataPoints().At(dpcount)

Expand Down Expand Up @@ -743,6 +772,13 @@ func (conv *Converter) consumeSummary(app storage.Appender, memResource *memoryS
}
}
}

// Write metadata after series data, so the series exists in the appender.
if conv.getOpts().HonorMetadata {
if err := metricMD.WriteTo(app, time.Now()); err != nil {
level.Warn(conv.log).Log("msg", "failed to write metric family metadata", "metric name", metricName, "err", err)
}
}
}

// GC cleans up stale metrics which have not been updated in the time specified
Expand Down
Loading
Loading