Skip to content
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

Fix #3089 'histograms are dissapearing' #3196

Conversation

DraggonFantasy
Copy link

@DraggonFantasy DraggonFantasy commented Feb 22, 2023

Description

This PR fixes #3089 - the problem with histogram metric type when the exporting the metrics with unchanged histogram value crashes the OTEL Collector.

Fixes #3089

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

Setup

Have a running OTEL Collector + Prometheus.
OTEL Collector config:

receivers:
  otlp/2:
    protocols:
      http:
        endpoint: 0.0.0.0:7777

processors:
  batch:

exporters:
  logging:
    verbosity: Detailed

  prometheus:
    endpoint: 0.0.0.0:9997
    namespace: test-space
    const_labels:
      label1: value1
    send_timestamps: true
    metric_expiration: 180m
    resource_to_telemetry_conversion:
      enabled: true

service:
  pipelines:
    metrics:
      receivers: [otlp/2]
      exporters: [logging, prometheus]

Prometheus config:

global:
  scrape_interval:     15s
  external_labels:
    monitor: 'codelab-monitor'
scrape_configs:
  - job_name: 'prometheus'
    scrape_interval: 5s
    static_configs:
      - targets: ['otl-collector:9997']

I've ran the following Python snippet (it's the minimal example I figured out to reproduce the issue):

import time

from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.metrics import get_meter_provider, set_meter_provider
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader

exporter = OTLPMetricExporter(endpoint="http://localhost:7777/v1/metrics")
reader = PeriodicExportingMetricReader(exporter, export_interval_millis=1000)

set_meter_provider(MeterProvider(metric_readers=[reader]))
meter = get_meter_provider().get_meter("myapp", "0.1.2")

histogram = meter.create_histogram(
    "py_histogram",
    unit="ms",
    description="Test histogram",
)

counter = meter.create_counter(
    f"py_counter",
    unit=f"items",
    description=f"Test counter"
)

histogram.record(12)
time.sleep(1)
counter.add(1)

And checked the logs on OTEL collector.
Before the fix:

configuration-otl-collector-1  | 2023-02-22T22:56:21.074Z	info	MetricsExporter	{"kind": "exporter", "data_type": "metrics", "name": "logging", "#metrics": 1}
configuration-otl-collector-1  | 2023-02-22T22:56:21.074Z	info	ResourceMetrics #0
configuration-otl-collector-1  | Resource SchemaURL: 
configuration-otl-collector-1  | Resource attributes:
configuration-otl-collector-1  |      -> telemetry.sdk.language: Str(python)
configuration-otl-collector-1  |      -> telemetry.sdk.name: Str(opentelemetry)
configuration-otl-collector-1  |      -> telemetry.sdk.version: Str(1.15.0)
configuration-otl-collector-1  |      -> service.name: Str(unknown_service)
configuration-otl-collector-1  | ScopeMetrics #0
configuration-otl-collector-1  | ScopeMetrics SchemaURL: 
configuration-otl-collector-1  | InstrumentationScope myapp 0.1.2
configuration-otl-collector-1  | Metric #0
configuration-otl-collector-1  | Descriptor:
configuration-otl-collector-1  |      -> Name: py_histogram
configuration-otl-collector-1  |      -> Description: Test histogram
configuration-otl-collector-1  |      -> Unit: ms
configuration-otl-collector-1  |      -> DataType: Histogram
configuration-otl-collector-1  |      -> AggregationTemporality: Cumulative
configuration-otl-collector-1  | HistogramDataPoints #0
configuration-otl-collector-1  | StartTimestamp: 2023-02-22 22:56:20.032467796 +0000 UTC
configuration-otl-collector-1  | Timestamp: 2023-02-22 22:56:21.032682472 +0000 UTC
configuration-otl-collector-1  | Count: 1
configuration-otl-collector-1  | Sum: 12.000000
configuration-otl-collector-1  | Min: 12.000000
configuration-otl-collector-1  | Max: 12.000000
configuration-otl-collector-1  | ExplicitBounds #0: 0.000000
configuration-otl-collector-1  | ExplicitBounds #1: 5.000000
configuration-otl-collector-1  | ExplicitBounds #2: 10.000000
configuration-otl-collector-1  | ExplicitBounds #3: 25.000000
configuration-otl-collector-1  | ExplicitBounds #4: 50.000000
configuration-otl-collector-1  | ExplicitBounds #5: 75.000000
configuration-otl-collector-1  | ExplicitBounds #6: 100.000000
configuration-otl-collector-1  | ExplicitBounds #7: 250.000000
configuration-otl-collector-1  | ExplicitBounds #8: 500.000000
configuration-otl-collector-1  | ExplicitBounds #9: 750.000000
configuration-otl-collector-1  | ExplicitBounds #10: 1000.000000
configuration-otl-collector-1  | ExplicitBounds #11: 2500.000000
configuration-otl-collector-1  | ExplicitBounds #12: 5000.000000
configuration-otl-collector-1  | ExplicitBounds #13: 7500.000000
configuration-otl-collector-1  | ExplicitBounds #14: 10000.000000
configuration-otl-collector-1  | Buckets #0, Count: 0
configuration-otl-collector-1  | Buckets #1, Count: 0
configuration-otl-collector-1  | Buckets #2, Count: 0
configuration-otl-collector-1  | Buckets #3, Count: 1
configuration-otl-collector-1  | Buckets #4, Count: 0
configuration-otl-collector-1  | Buckets #5, Count: 0
configuration-otl-collector-1  | Buckets #6, Count: 0
configuration-otl-collector-1  | Buckets #7, Count: 0
configuration-otl-collector-1  | Buckets #8, Count: 0
configuration-otl-collector-1  | Buckets #9, Count: 0
configuration-otl-collector-1  | Buckets #10, Count: 0
configuration-otl-collector-1  | Buckets #11, Count: 0
configuration-otl-collector-1  | Buckets #12, Count: 0
configuration-otl-collector-1  | Buckets #13, Count: 0
configuration-otl-collector-1  | Buckets #14, Count: 0
configuration-otl-collector-1  | Buckets #15, Count: 0
configuration-otl-collector-1  | 	{"kind": "exporter", "data_type": "metrics", "name": "logging"}
configuration-otl-collector-1  | 2023-02-22T22:56:21.075Z	info	MetricsExporter	{"kind": "exporter", "data_type": "metrics", "name": "logging", "#metrics": 2}
configuration-otl-collector-1  | 2023-02-22T22:56:21.075Z	info	ResourceMetrics #0
configuration-otl-collector-1  | Resource SchemaURL: 
configuration-otl-collector-1  | Resource attributes:
configuration-otl-collector-1  |      -> telemetry.sdk.language: Str(python)
configuration-otl-collector-1  |      -> telemetry.sdk.name: Str(opentelemetry)
configuration-otl-collector-1  |      -> telemetry.sdk.version: Str(1.15.0)
configuration-otl-collector-1  |      -> service.name: Str(unknown_service)
configuration-otl-collector-1  | ScopeMetrics #0
configuration-otl-collector-1  | ScopeMetrics SchemaURL: 
configuration-otl-collector-1  | InstrumentationScope myapp 0.1.2
configuration-otl-collector-1  | Metric #0
configuration-otl-collector-1  | Descriptor:
configuration-otl-collector-1  |      -> Name: py_histogram
configuration-otl-collector-1  |      -> Description: Test histogram
configuration-otl-collector-1  |      -> Unit: ms
configuration-otl-collector-1  |      -> DataType: Empty
configuration-otl-collector-1  | Metric #1
configuration-otl-collector-1  | Descriptor:
configuration-otl-collector-1  |      -> Name: py_counter
configuration-otl-collector-1  |      -> Description: Test counter
configuration-otl-collector-1  |      -> Unit: items
configuration-otl-collector-1  |      -> DataType: Sum
configuration-otl-collector-1  |      -> IsMonotonic: true
configuration-otl-collector-1  |      -> AggregationTemporality: Cumulative
configuration-otl-collector-1  | NumberDataPoints #0
configuration-otl-collector-1  | StartTimestamp: 2023-02-22 22:56:21.033651214 +0000 UTC
configuration-otl-collector-1  | Timestamp: 2023-02-22 22:56:21.074523435 +0000 UTC
configuration-otl-collector-1  | Value: 1
configuration-otl-collector-1  | 	{"kind": "exporter", "data_type": "metrics", "name": "logging"}
configuration-otl-collector-1  | 2023-02-22T22:56:21.075Z	error	prometheusexporter@v0.71.0/accumulator.go:105	failed to translate metric	{"kind": "exporter", "data_type": "metrics", "name": "prometheus", "data_type": "\u0000", "metric_name": "py_histogram"}
configuration-otl-collector-1  | github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter.(*lastValueAccumulator).addMetric
configuration-otl-collector-1  | 	github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter@v0.71.0/accumulator.go:105
configuration-otl-collector-1  | github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter.(*lastValueAccumulator).Accumulate
configuration-otl-collector-1  | 	github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter@v0.71.0/accumulator.go:82
configuration-otl-collector-1  | github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter.(*collector).processMetrics
configuration-otl-collector-1  | 	github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter@v0.71.0/collector.go:67
configuration-otl-collector-1  | github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter.(*prometheusExporter).ConsumeMetrics
configuration-otl-collector-1  | 	github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter@v0.71.0/prometheus.go:96
configuration-otl-collector-1  | go.opentelemetry.io/collector/exporter/exporterhelper.(*metricsRequest).Export
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/exporter/exporterhelper/metrics.go:65
configuration-otl-collector-1  | go.opentelemetry.io/collector/exporter/exporterhelper.(*timeoutSender).send
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/exporter/exporterhelper/common.go:208
configuration-otl-collector-1  | go.opentelemetry.io/collector/exporter/exporterhelper.(*retrySender).send
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/exporter/exporterhelper/queued_retry.go:365
configuration-otl-collector-1  | go.opentelemetry.io/collector/exporter/exporterhelper.(*metricsSenderWithObservability).send
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/exporter/exporterhelper/metrics.go:136
configuration-otl-collector-1  | go.opentelemetry.io/collector/exporter/exporterhelper.(*queuedRetrySender).send
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/exporter/exporterhelper/queued_retry.go:301
configuration-otl-collector-1  | go.opentelemetry.io/collector/exporter/exporterhelper.NewMetricsExporter.func2
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/exporter/exporterhelper/metrics.go:116
configuration-otl-collector-1  | go.opentelemetry.io/collector/consumer.ConsumeMetricsFunc.ConsumeMetrics
configuration-otl-collector-1  | 	go.opentelemetry.io/collector/consumer@v0.71.0/metrics.go:36
configuration-otl-collector-1  | github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry.(*wrapperMetricsExporter).ConsumeMetrics
configuration-otl-collector-1  | 	github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry@v0.71.0/resource_to_telemetry.go:43
configuration-otl-collector-1  | go.opentelemetry.io/collector/service/internal/fanoutconsumer.(*metricsConsumer).ConsumeMetrics
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/service/internal/fanoutconsumer/metrics.go:77
configuration-otl-collector-1  | go.opentelemetry.io/collector/receiver/otlpreceiver/internal/metrics.(*Receiver).Export
configuration-otl-collector-1  | 	go.opentelemetry.io/collector/receiver/otlpreceiver@v0.71.0/internal/metrics/otlp.go:54
configuration-otl-collector-1  | go.opentelemetry.io/collector/receiver/otlpreceiver.handleMetrics
configuration-otl-collector-1  | 	go.opentelemetry.io/collector/receiver/otlpreceiver@v0.71.0/otlphttp.go:73
configuration-otl-collector-1  | go.opentelemetry.io/collector/receiver/otlpreceiver.(*otlpReceiver).registerMetricsConsumer.func1
configuration-otl-collector-1  | 	go.opentelemetry.io/collector/receiver/otlpreceiver@v0.71.0/otlp.go:235
configuration-otl-collector-1  | net/http.HandlerFunc.ServeHTTP
configuration-otl-collector-1  | 	net/http/server.go:2109
configuration-otl-collector-1  | net/http.(*ServeMux).ServeHTTP
configuration-otl-collector-1  | 	net/http/server.go:2487
configuration-otl-collector-1  | go.opentelemetry.io/collector/config/confighttp.(*decompressor).wrap.func1
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/config/confighttp/compression.go:162
configuration-otl-collector-1  | net/http.HandlerFunc.ServeHTTP
configuration-otl-collector-1  | 	net/http/server.go:2109
configuration-otl-collector-1  | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp.(*Handler).ServeHTTP
configuration-otl-collector-1  | 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.39.0/handler.go:213
configuration-otl-collector-1  | go.opentelemetry.io/collector/config/confighttp.(*clientInfoHandler).ServeHTTP
configuration-otl-collector-1  | 	go.opentelemetry.io/collector@v0.71.0/config/confighttp/clientinfohandler.go:39
configuration-otl-collector-1  | net/http.serverHandler.ServeHTTP
configuration-otl-collector-1  | 	net/http/server.go:2947
configuration-otl-collector-1  | net/http.(*conn).serve
configuration-otl-collector-1  | 	net/http/server.go:1991

After the fix:

configuration-otl-collector-1  | 2023-02-22T22:57:18.991Z	info	MetricsExporter	{"kind": "exporter", "data_type": "metrics", "name": "logging", "#metrics": 1}
configuration-otl-collector-1  | 2023-02-22T22:57:18.991Z	info	ResourceMetrics #0
configuration-otl-collector-1  | Resource SchemaURL: 
configuration-otl-collector-1  | Resource attributes:
configuration-otl-collector-1  |      -> telemetry.sdk.language: Str(python)
configuration-otl-collector-1  |      -> telemetry.sdk.name: Str(opentelemetry)
configuration-otl-collector-1  |      -> telemetry.sdk.version: Str(1.15.0)
configuration-otl-collector-1  |      -> service.name: Str(unknown_service)
configuration-otl-collector-1  | ScopeMetrics #0
configuration-otl-collector-1  | ScopeMetrics SchemaURL: 
configuration-otl-collector-1  | InstrumentationScope myapp 0.1.2
configuration-otl-collector-1  | Metric #0
configuration-otl-collector-1  | Descriptor:
configuration-otl-collector-1  |      -> Name: py_histogram
configuration-otl-collector-1  |      -> Description: Test histogram
configuration-otl-collector-1  |      -> Unit: ms
configuration-otl-collector-1  |      -> DataType: Histogram
configuration-otl-collector-1  |      -> AggregationTemporality: Cumulative
configuration-otl-collector-1  | HistogramDataPoints #0
configuration-otl-collector-1  | StartTimestamp: 2023-02-22 22:57:17.949824054 +0000 UTC
configuration-otl-collector-1  | Timestamp: 2023-02-22 22:57:18.949918969 +0000 UTC
configuration-otl-collector-1  | Count: 1
configuration-otl-collector-1  | Sum: 12.000000
configuration-otl-collector-1  | Min: 12.000000
configuration-otl-collector-1  | Max: 12.000000
configuration-otl-collector-1  | ExplicitBounds #0: 0.000000
configuration-otl-collector-1  | ExplicitBounds #1: 5.000000
configuration-otl-collector-1  | ExplicitBounds #2: 10.000000
configuration-otl-collector-1  | ExplicitBounds #3: 25.000000
configuration-otl-collector-1  | ExplicitBounds #4: 50.000000
configuration-otl-collector-1  | ExplicitBounds #5: 75.000000
configuration-otl-collector-1  | ExplicitBounds #6: 100.000000
configuration-otl-collector-1  | ExplicitBounds #7: 250.000000
configuration-otl-collector-1  | ExplicitBounds #8: 500.000000
configuration-otl-collector-1  | ExplicitBounds #9: 750.000000
configuration-otl-collector-1  | ExplicitBounds #10: 1000.000000
configuration-otl-collector-1  | ExplicitBounds #11: 2500.000000
configuration-otl-collector-1  | ExplicitBounds #12: 5000.000000
configuration-otl-collector-1  | ExplicitBounds #13: 7500.000000
configuration-otl-collector-1  | ExplicitBounds #14: 10000.000000
configuration-otl-collector-1  | Buckets #0, Count: 0
configuration-otl-collector-1  | Buckets #1, Count: 0
configuration-otl-collector-1  | Buckets #2, Count: 0
configuration-otl-collector-1  | Buckets #3, Count: 1
configuration-otl-collector-1  | Buckets #4, Count: 0
configuration-otl-collector-1  | Buckets #5, Count: 0
configuration-otl-collector-1  | Buckets #6, Count: 0
configuration-otl-collector-1  | Buckets #7, Count: 0
configuration-otl-collector-1  | Buckets #8, Count: 0
configuration-otl-collector-1  | Buckets #9, Count: 0
configuration-otl-collector-1  | Buckets #10, Count: 0
configuration-otl-collector-1  | Buckets #11, Count: 0
configuration-otl-collector-1  | Buckets #12, Count: 0
configuration-otl-collector-1  | Buckets #13, Count: 0
configuration-otl-collector-1  | Buckets #14, Count: 0
configuration-otl-collector-1  | Buckets #15, Count: 0
configuration-otl-collector-1  | 	{"kind": "exporter", "data_type": "metrics", "name": "logging"}
configuration-otl-collector-1  | 2023-02-22T22:57:18.992Z	info	MetricsExporter	{"kind": "exporter", "data_type": "metrics", "name": "logging", "#metrics": 2}
configuration-otl-collector-1  | 2023-02-22T22:57:18.992Z	info	ResourceMetrics #0
configuration-otl-collector-1  | Resource SchemaURL: 
configuration-otl-collector-1  | Resource attributes:
configuration-otl-collector-1  |      -> telemetry.sdk.language: Str(python)
configuration-otl-collector-1  |      -> telemetry.sdk.name: Str(opentelemetry)
configuration-otl-collector-1  |      -> telemetry.sdk.version: Str(1.15.0)
configuration-otl-collector-1  |      -> service.name: Str(unknown_service)
configuration-otl-collector-1  | ScopeMetrics #0
configuration-otl-collector-1  | ScopeMetrics SchemaURL: 
configuration-otl-collector-1  | InstrumentationScope myapp 0.1.2
configuration-otl-collector-1  | Metric #0
configuration-otl-collector-1  | Descriptor:
configuration-otl-collector-1  |      -> Name: py_histogram
configuration-otl-collector-1  |      -> Description: Test histogram
configuration-otl-collector-1  |      -> Unit: ms
configuration-otl-collector-1  |      -> DataType: Histogram
configuration-otl-collector-1  |      -> AggregationTemporality: Cumulative
configuration-otl-collector-1  | HistogramDataPoints #0
configuration-otl-collector-1  | StartTimestamp: 2023-02-22 22:57:17.949824054 +0000 UTC
configuration-otl-collector-1  | Timestamp: 2023-02-22 22:57:18.949918969 +0000 UTC
configuration-otl-collector-1  | Count: 1
configuration-otl-collector-1  | Sum: 12.000000
configuration-otl-collector-1  | Min: 12.000000
configuration-otl-collector-1  | Max: 12.000000
configuration-otl-collector-1  | ExplicitBounds #0: 0.000000
configuration-otl-collector-1  | ExplicitBounds #1: 5.000000
configuration-otl-collector-1  | ExplicitBounds #2: 10.000000
configuration-otl-collector-1  | ExplicitBounds #3: 25.000000
configuration-otl-collector-1  | ExplicitBounds #4: 50.000000
configuration-otl-collector-1  | ExplicitBounds #5: 75.000000
configuration-otl-collector-1  | ExplicitBounds #6: 100.000000
configuration-otl-collector-1  | ExplicitBounds #7: 250.000000
configuration-otl-collector-1  | ExplicitBounds #8: 500.000000
configuration-otl-collector-1  | ExplicitBounds #9: 750.000000
configuration-otl-collector-1  | ExplicitBounds #10: 1000.000000
configuration-otl-collector-1  | ExplicitBounds #11: 2500.000000
configuration-otl-collector-1  | ExplicitBounds #12: 5000.000000
configuration-otl-collector-1  | ExplicitBounds #13: 7500.000000
configuration-otl-collector-1  | ExplicitBounds #14: 10000.000000
configuration-otl-collector-1  | Buckets #0, Count: 0
configuration-otl-collector-1  | Buckets #1, Count: 0
configuration-otl-collector-1  | Buckets #2, Count: 0
configuration-otl-collector-1  | Buckets #3, Count: 1
configuration-otl-collector-1  | Buckets #4, Count: 0
configuration-otl-collector-1  | Buckets #5, Count: 0
configuration-otl-collector-1  | Buckets #6, Count: 0
configuration-otl-collector-1  | Buckets #7, Count: 0
configuration-otl-collector-1  | Buckets #8, Count: 0
configuration-otl-collector-1  | Buckets #9, Count: 0
configuration-otl-collector-1  | Buckets #10, Count: 0
configuration-otl-collector-1  | Buckets #11, Count: 0
configuration-otl-collector-1  | Buckets #12, Count: 0
configuration-otl-collector-1  | Buckets #13, Count: 0
configuration-otl-collector-1  | Buckets #14, Count: 0
configuration-otl-collector-1  | Buckets #15, Count: 0
configuration-otl-collector-1  | Metric #1
configuration-otl-collector-1  | Descriptor:
configuration-otl-collector-1  |      -> Name: py_counter
configuration-otl-collector-1  |      -> Description: Test counter
configuration-otl-collector-1  |      -> Unit: items
configuration-otl-collector-1  |      -> DataType: Sum
configuration-otl-collector-1  |      -> IsMonotonic: true
configuration-otl-collector-1  |      -> AggregationTemporality: Cumulative
configuration-otl-collector-1  | NumberDataPoints #0
configuration-otl-collector-1  | StartTimestamp: 2023-02-22 22:57:18.951057692 +0000 UTC
configuration-otl-collector-1  | Timestamp: 2023-02-22 22:57:18.991621073 +0000 UTC
configuration-otl-collector-1  | Value: 1
configuration-otl-collector-1  | 	{"kind": "exporter", "data_type": "metrics", "name": "logging"}

Also ran unit tests to make sure that the change doesn't break anything.

Does This PR Require a Contrib Repo Change?

  • Yes. - Link to PR:
  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

@DraggonFantasy DraggonFantasy requested a review from a team February 22, 2023 23:27
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Feb 22, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: DraggonFantasy (e40098a)

@@ -275,7 +275,7 @@ def collect(
"""
with self._lock:
if not any(self._bucket_counts):
return None
return self._previous_point
Copy link
Member

Choose a reason for hiding this comment

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

This is incorrect; we can't return the previous point always.

Copy link
Author

Choose a reason for hiding this comment

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

Could you please suggest what cases should I consider to make the correct change?

Copy link
Member

Choose a reason for hiding this comment

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

I will look closely at the linked issue to see the correct fix, but the issue with returning self._previous_point is when the temporality is delta and no measurement is recorded, it will return an incorrect result.

Copy link
Author

@DraggonFantasy DraggonFantasy Mar 23, 2023

Choose a reason for hiding this comment

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

I can try to make it return a new HistogramDataPoint with value 0 or something like that, but I've tested the solution with AggregationTemporality.Delta and it seems to work

Here's the code I used for test:

import time

from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.metrics import get_meter_provider, set_meter_provider
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.metrics import (
    Histogram,
)
from opentelemetry.sdk.metrics.export import AggregationTemporality


exporter = OTLPMetricExporter(endpoint="http://localhost:4445/v1/metrics",
                              preferred_temporality={
                                  Histogram: AggregationTemporality.DELTA,
                              })
reader = PeriodicExportingMetricReader(exporter, export_interval_millis=1000)

set_meter_provider(MeterProvider(metric_readers=[reader]))
meter = get_meter_provider().get_meter("myapp", "0.1.2")

histogram = meter.create_histogram(
    "py_histogram",
    unit="ms",
    description="Test histogram",
)

counter = meter.create_counter(
    f"py_counter",
    unit=f"items",
    description=f"Test counter"
)

histogram.record(12)
time.sleep(1)
counter.add(1)
time.sleep(1)
counter.add(1)
time.sleep(1)
counter.add(1)
time.sleep(1)
counter.add(1)
time.sleep(1)

Here's logs from running this code:
otel-log.txt

Copy link

@wosc wosc Jun 28, 2023

Choose a reason for hiding this comment

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

I don't know if this helps, but I'm currently trying this approach, so the metrics are always present, but possibly with zero values:

diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
index ae21db90..25f03f69 100644
--- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
+++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/aggregation.py
@@ -289,9 +289,6 @@ class _ExplicitBucketHistogramAggregation(_Aggregation[HistogramPoint]):
         Atomically return a point for the current value of the metric.
         """
         with self._lock:
-            if not any(self._bucket_counts):
-                return None
-
             bucket_counts = self._bucket_counts
             start_time_unix_nano = self._start_time_unix_nano
             sum_ = self._sum
@@ -316,6 +313,9 @@ class _ExplicitBucketHistogramAggregation(_Aggregation[HistogramPoint]):
             max=max_,
         )

+        if not any(bucket_counts):
+            self._previous_point = None
+            return current_point
+
         if self._previous_point is None or (
             self._instrument_temporality is aggregation_temporality
         ):

Copy link

@wosc wosc Jun 29, 2023

Choose a reason for hiding this comment

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

Hrm, never mind, returning zero values like this does not fix my issue, that the count in Prometheus shows lots of wrong, way too large values. see next comment

Copy link

Choose a reason for hiding this comment

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

I recently came back to this, and have edited my above Diff: Also resetting _previous_point seems to do the right thing for me.

@mplachter
Copy link

Any update on this?

@lzchen
Copy link
Contributor

lzchen commented Aug 16, 2023

@DraggonFantasy
Are you still working on this?

@ocelotl
Copy link
Contributor

ocelotl commented Feb 10, 2024

#3089 was fixed by #3429, closing.

@ocelotl ocelotl closed this Feb 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Prometheus exporter - Histograms are disappearing.
6 participants