Repository navigation
atecontroller: the :8080 metrics listener follows OTEL_METRICS_EXPORTER #1976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
19344a9
8b4fcb8
76050b9
024ce51
a9ea0d7
a46d59d
5529baa
bec44ef
74b3aaa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -208,17 +208,27 @@ const ( | |
| tracesExporterEnv = "OTEL_TRACES_EXPORTER" | ||
| ) | ||
|
|
||
| // metricsPushEnabled applies OTEL_METRICS_EXPORTER with the shared exporter | ||
| // rules: the OTLP reader is installed while otlp is selected, as it is when the | ||
| // variable is unset. prometheus, the specification's pull exporter, is known | ||
| // only when pullServed, i.e. the component serves its own /metrics; elsewhere | ||
| // it is skipped as unknown, so a push-only component keeps exporting. | ||
| func metricsPushEnabled(ctx context.Context, pullServed bool) bool { | ||
| // metricsExporters applies OTEL_METRICS_EXPORTER with the shared exporter | ||
| // rules. prometheus, the specification's pull exporter, is known only when | ||
| // pullServed, i.e. the component serves its own /metrics; elsewhere it is | ||
| // skipped as unknown, so a push-only component keeps exporting. Unset selects | ||
| // every exporter the component has. | ||
| func metricsExporters(ctx context.Context, pullServed bool) Exporters { | ||
| known := []string{ExporterOTLP} | ||
| def := Exporters{ExporterOTLP: true} | ||
| if pullServed { | ||
| known = append(known, exporterPrometheus) | ||
| def[exporterPrometheus] = true | ||
| } | ||
| return resolveExportersEnv(ctx, metricsExporterEnv, known, Exporters{ExporterOTLP: true}).Has(ExporterOTLP) | ||
| exporters := resolveExportersEnv(ctx, metricsExporterEnv, known, def) | ||
| slog.InfoContext(ctx, "Metrics exporters resolved", slog.String("exporters", exporters.String())) | ||
| return exporters | ||
| } | ||
|
|
||
| // metricsPushEnabled reports whether the OTLP reader is installed: while otlp | ||
| // is selected, as it is when the variable is unset. | ||
| func metricsPushEnabled(ctx context.Context, pullServed bool) bool { | ||
| return metricsExporters(ctx, pullServed).Has(ExporterOTLP) | ||
| } | ||
|
|
||
| // tracesPushEnabled applies OTEL_TRACES_EXPORTER with the shared exporter | ||
|
|
@@ -247,31 +257,45 @@ func InitMetrics(ctx context.Context, serviceName string) (*sdkmetric.MeterProvi | |
| // it does not own (atecontroller: controller-runtime's), so every metric | ||
| // reaches the backend exactly once on whichever path is active. With the OTLP | ||
| // export, reg is bridged onto the push and the OTel instruments stay off it, | ||
| // since the bridge would otherwise push them a second time. When | ||
| // OTEL_METRICS_EXPORTER does not select otlp, nothing is pushed and the OTel | ||
| // instruments register on reg, so its endpoint serves both. | ||
| // since the bridge would otherwise push them a second time. With prometheus | ||
| // alone, nothing is pushed and the OTel instruments register on reg, so its | ||
| // endpoint serves both. | ||
| // | ||
| // servePull reports whether OTEL_METRICS_EXPORTER leaves the scraped endpoint | ||
| // on, which the caller must then serve from reg: unset, prometheus, or a list | ||
| // with it. otlp and none turn it off, and with none no reader is installed. | ||
| // | ||
| // wrapProducer, when non-nil, wraps the bridge producer on the OTLP path, for | ||
| // a rewrite the push backend needs but the scraped endpoint does not. | ||
| func InitMetricsBridged(ctx context.Context, serviceName string, reg interface { | ||
| promclient.Registerer | ||
| promclient.Gatherer | ||
| }, wrapProducer func(sdkmetric.Producer) sdkmetric.Producer) (*sdkmetric.MeterProvider, error) { | ||
| }, wrapProducer func(sdkmetric.Producer) sdkmetric.Producer) (mp *sdkmetric.MeterProvider, servePull bool, err error) { | ||
| if serviceName == "" { | ||
| return nil, fmt.Errorf("serviceName is required") | ||
| return nil, false, fmt.Errorf("serviceName is required") | ||
| } | ||
| if metricsPushEnabled(ctx, true) { | ||
| exporters := metricsExporters(ctx, true) | ||
| servePull = exporters.Has(exporterPrometheus) | ||
| switch { | ||
| case exporters.Has(ExporterOTLP): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this branch :8080 misses
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tracked in #2402, thanks. A fix needs a separate registry to avoid pushing them twice. |
||
| producer := prombridge.NewMetricProducer(prombridge.WithGatherer(reg)) | ||
| if wrapProducer != nil { | ||
| producer = wrapProducer(producer) | ||
| } | ||
| return newMeterProvider(ctx, serviceName, true, false, nil, []sdkmetric.Producer{producer}) | ||
| mp, err = newMeterProvider(ctx, serviceName, true, false, nil, []sdkmetric.Producer{producer}) | ||
| case servePull: | ||
| var promReader *prometheus.Exporter | ||
| if promReader, err = prometheus.New(prometheus.WithRegisterer(reg)); err != nil { | ||
| return nil, false, fmt.Errorf("create Prometheus metric exporter: %w", err) | ||
| } | ||
| mp, err = newMeterProvider(ctx, serviceName, false, false, nil, nil, promReader) | ||
| default: | ||
| mp, err = newMeterProvider(ctx, serviceName, false, false, nil, nil) | ||
| } | ||
| promReader, err := prometheus.New(prometheus.WithRegisterer(reg)) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("create Prometheus metric exporter: %w", err) | ||
| return nil, false, err | ||
| } | ||
| return newMeterProvider(ctx, serviceName, false, false, nil, nil, promReader) | ||
| return mp, servePull, nil | ||
| } | ||
|
|
||
| // InitMetricsPushOnlyVia is InitMetrics without the Prometheus reader, for a | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's log the resolved exporters and whether :8080 is on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a46d59d, thanks.