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

Add capability to have configurable aggregation temporality for OTLP Registry #3625

Merged
merged 20 commits into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5615949
Add capability to have configurable aggregation temporality for OTLP …
lenin-jaganathan Feb 9, 2023
2212f84
Set isDeltaAggregationTemporality in Constructor and avoid re-evaluat…
lenin-jaganathan Feb 17, 2023
d8e4ee8
Fix copyright issues
lenin-jaganathan Feb 17, 2023
2664f89
Make getAggregationTemporality return AggregationTemporality enum.
lenin-jaganathan Feb 17, 2023
7854a88
Add tests for delta registry
lenin-jaganathan Feb 18, 2023
487af47
Add AggregationTemporality Enum
lenin-jaganathan Feb 22, 2023
a83564a
Calculate TimeUnixNano once per publishing interval
lenin-jaganathan Feb 23, 2023
dc2dd6b
Add tests for Histograms.
lenin-jaganathan Feb 23, 2023
8b8c350
Refactor AggregationTemporality.java
lenin-jaganathan Feb 24, 2023
490b2a3
Merge branch 'main' into otlp_stepregistry
jonatan-ivanov Mar 21, 2023
6d9f226
auto-formatting
jonatan-ivanov Mar 21, 2023
cfd491f
Merge branch 'main' into otlp_stepregistry
jonatan-ivanov Mar 28, 2023
2076bb2
Polish
jonatan-ivanov Mar 28, 2023
65831a8
Add Lenin Jaganathan as @author
jonatan-ivanov Mar 29, 2023
789b82b
Polish
lenin-jaganathan Mar 29, 2023
08e43c2
Add the word cumulative to meter names
jonatan-ivanov Mar 31, 2023
8f51093
Add integration tests for delta
jonatan-ivanov Mar 31, 2023
7d1cf36
Set higher timeout for OTLP integration tests
jonatan-ivanov Mar 31, 2023
95cb710
CumulativeMetrics will use config.wallTime() as metric time and Delta…
lenin-jaganathan Apr 1, 2023
0db0221
Revert "Add integration tests for delta"
lenin-jaganathan Apr 2, 2023
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
@@ -0,0 +1,51 @@
/*
* Copyright 2023 VMware, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micrometer.registry.otlp;

/**
* AggregationTemporality defines the way additive values are expressed.
*
* @see <a href=
* "https://opentelemetry.io/docs/reference/specification/metrics/data-model/#temporality">OTLP
* Temporality</a>
* @author Lenin Jaganathan
* @since 1.11.0
*/
public enum AggregationTemporality {

/**
* Reported values do not incorporate previous measurements.
*/
DELTA,

/**
* Reported values incorporate previous measurements.
*/
CUMULATIVE;

public static io.opentelemetry.proto.metrics.v1.AggregationTemporality toOtlpAggregationTemporality(
AggregationTemporality aggregationTemporality) {
switch (aggregationTemporality) {
case DELTA:
return io.opentelemetry.proto.metrics.v1.AggregationTemporality.AGGREGATION_TEMPORALITY_DELTA;
case CUMULATIVE:
return io.opentelemetry.proto.metrics.v1.AggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE;
default:
return io.opentelemetry.proto.metrics.v1.AggregationTemporality.UNRECOGNIZED;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
import static io.micrometer.core.instrument.config.MeterRegistryConfigValidator.*;
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getString;
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getUrlString;
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getEnum;

/**
* Config for {@link OtlpMeterRegistry}.
*
* @author Tommy Ludwig
* @author Lenin Jaganathan
* @since 1.9.0
*/
public interface OtlpConfig extends PushRegistryConfig {
Expand Down Expand Up @@ -88,6 +90,21 @@ default Map<String, String> resourceAttributes() {
return resourceAttributes;
}

/**
* {@link AggregationTemporality} of the OtlpMeterRegistry. This determines whether
* the meters should be cumulative(AGGREGATION_TEMPORALITY_CUMULATIVE) or
* step/delta(AGGREGATION_TEMPORALITY_DELTA).
* @return the aggregationTemporality for OtlpRegistry
* @see <a href=
* "https://opentelemetry.io/docs/reference/specification/metrics/data-model/#temporality">OTLP
* Temporality</a>
* @since 1.11.0
*/
default AggregationTemporality aggregationTemporality() {
return getEnum(this, AggregationTemporality.class, "aggregationTemporality")
.orElse(AggregationTemporality.CUMULATIVE);
}

/**
* Additional headers to send with exported metrics. This may be needed for
* authorization headers, for example.
Expand Down Expand Up @@ -128,7 +145,8 @@ default Map<String, String> headers() {
@Override
default Validated<?> validate() {
return checkAll(this, c -> PushRegistryConfig.validate(c), checkRequired("url", OtlpConfig::url),
check("resourceAttributes", OtlpConfig::resourceAttributes));
check("resourceAttributes", OtlpConfig::resourceAttributes),
check("aggregationTemporality", OtlpConfig::aggregationTemporality));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@

import java.util.concurrent.TimeUnit;

class OtlpCounter extends CumulativeCounter implements StartTimeAwareMeter {
class OtlpCumulativeCounter extends CumulativeCounter implements StartTimeAwareMeter {

private final long startTimeNanos;

OtlpCounter(Id id, Clock clock) {
OtlpCumulativeCounter(Id id, Clock clock) {
super(id);
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 VMware, Inc.
* Copyright 2023 VMware, Inc.
jonatan-ivanov marked this conversation as resolved.
Show resolved Hide resolved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,7 +23,7 @@
import java.time.Duration;
import java.util.concurrent.TimeUnit;

class OtlpDistributionSummary extends CumulativeDistributionSummary implements StartTimeAwareMeter {
class OtlpCumulativeDistributionSummary extends CumulativeDistributionSummary implements StartTimeAwareMeter {

private static final CountAtBucket[] EMPTY_HISTOGRAM = new CountAtBucket[0];

Expand All @@ -32,19 +32,13 @@ class OtlpDistributionSummary extends CumulativeDistributionSummary implements S
@Nullable
private final Histogram monotonicBucketCountHistogram;

OtlpDistributionSummary(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig, double scale,
boolean supportsAggregablePercentiles) {
OtlpCumulativeDistributionSummary(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig,
double scale, boolean supportsAggregablePercentiles) {
super(id, clock, DistributionStatisticConfig.builder()
.percentilesHistogram(false) // avoid
// a
// histogram
// for
// percentiles/SLOs
// in
// the
// super
.serviceLevelObjectives() // we will use a different implementation here
// instead
// avoid a histogram for percentiles/SLOs in the super
.percentilesHistogram(false)
// we will use a different implementation here instead
.serviceLevelObjectives()
.build()
.merge(distributionStatisticConfig), scale, false);
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
Expand All @@ -55,10 +49,8 @@ class OtlpDistributionSummary extends CumulativeDistributionSummary implements S
if (distributionStatisticConfig.isPublishingHistogram()) {
this.monotonicBucketCountHistogram = new TimeWindowFixedBoundaryHistogram(clock,
DistributionStatisticConfig.builder()
.expiry(Duration.ofDays(1825)) // effectively
// never
// roll
// over
// effectively never roll over
.expiry(Duration.ofDays(1825))
.bufferLength(1)
.build()
.merge(distributionStatisticConfig),
Expand All @@ -84,13 +76,9 @@ public HistogramSnapshot takeSnapshot() {
return snapshot;
}

CountAtBucket[] histogramCounts = this.monotonicBucketCountHistogram.takeSnapshot(0, 0, 0).histogramCounts();
Copy link
Contributor

Choose a reason for hiding this comment

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

Not necessarily related to this PR, and might be addressed in a follow-up (also untested, I just happen to have fixed a similar bug recently): the fact that super.takeSnapshot() and monotonicBucketCountHistogram.takeSnapshot() are not synchronized might lead to discrepancies between the count and the bucket counts if some other thread records data in the time between the two method calls.

return new HistogramSnapshot(snapshot.count(), snapshot.total(), snapshot.max(), snapshot.percentileValues(),
histogramCounts(), snapshot::outputSummary);
}

private CountAtBucket[] histogramCounts() {
return this.monotonicBucketCountHistogram == null ? EMPTY_HISTOGRAM
: this.monotonicBucketCountHistogram.takeSnapshot(0, 0, 0).histogramCounts();
histogramCounts, snapshot::outputSummary);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import java.util.concurrent.TimeUnit;
import java.util.function.ToDoubleFunction;

class OtlpFunctionCounter<T> extends CumulativeFunctionCounter<T> implements StartTimeAwareMeter {
class OtlpCumulativeFunctionCounter<T> extends CumulativeFunctionCounter<T> implements StartTimeAwareMeter {

private final long startTimeNanos;

OtlpFunctionCounter(Id id, T obj, ToDoubleFunction<T> f, Clock clock) {
OtlpCumulativeFunctionCounter(Id id, T obj, ToDoubleFunction<T> f, Clock clock) {
super(id, obj, f);
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
import java.util.function.ToDoubleFunction;
import java.util.function.ToLongFunction;

class OtlpFunctionTimer<T> extends CumulativeFunctionTimer<T> implements StartTimeAwareMeter {
class OtlpCumulativeFunctionTimer<T> extends CumulativeFunctionTimer<T> implements StartTimeAwareMeter {

private final long startTimeNanos;

OtlpFunctionTimer(Id id, T obj, ToLongFunction<T> countFunction, ToDoubleFunction<T> totalTimeFunction,
OtlpCumulativeFunctionTimer(Id id, T obj, ToLongFunction<T> countFunction, ToDoubleFunction<T> totalTimeFunction,
TimeUnit totalTimeFunctionUnit, TimeUnit baseTimeUnit, Clock clock) {
super(id, obj, countFunction, totalTimeFunction, totalTimeFunctionUnit, baseTimeUnit);
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@

import java.util.concurrent.TimeUnit;

class OtlpLongTaskTimer extends CumulativeHistogramLongTaskTimer implements StartTimeAwareMeter {
class OtlpCumulativeLongTaskTimer extends CumulativeHistogramLongTaskTimer implements StartTimeAwareMeter {

private final long startTimeNanos;

OtlpLongTaskTimer(Id id, Clock clock, TimeUnit baseTimeUnit,
OtlpCumulativeLongTaskTimer(Id id, Clock clock, TimeUnit baseTimeUnit,
DistributionStatisticConfig distributionStatisticConfig) {
super(id, clock, baseTimeUnit, distributionStatisticConfig);
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 VMware, Inc.
* Copyright 2023 VMware, Inc.
shakuzen marked this conversation as resolved.
Show resolved Hide resolved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,26 +25,20 @@
import java.time.Duration;
import java.util.concurrent.TimeUnit;

class OtlpTimer extends CumulativeTimer implements StartTimeAwareMeter {
class OtlpCumulativeTimer extends CumulativeTimer implements StartTimeAwareMeter {

private final long startTimeNanos;

@Nullable
private final Histogram monotonicCountBucketHistogram;

OtlpTimer(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector,
TimeUnit baseTimeUnit) {
OtlpCumulativeTimer(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig,
PauseDetector pauseDetector, TimeUnit baseTimeUnit) {
super(id, clock, DistributionStatisticConfig.builder()
.percentilesHistogram(false) // avoid
// a
// histogram
// for
// percentiles/SLOs
// in
// the
// super
.serviceLevelObjectives() // we will use a different implementation here
// instead
// avoid a histogram for percentiles/SLOs in the super
.percentilesHistogram(false)
// we will use a different implementation here instead
.serviceLevelObjectives()
.build()
.merge(distributionStatisticConfig), pauseDetector, baseTimeUnit, false);
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
Expand All @@ -54,10 +48,8 @@ class OtlpTimer extends CumulativeTimer implements StartTimeAwareMeter {
if (distributionStatisticConfig.isPublishingHistogram()) {
this.monotonicCountBucketHistogram = new TimeWindowFixedBoundaryHistogram(clock,
DistributionStatisticConfig.builder()
.expiry(Duration.ofDays(1825)) // effectively
// never
// roll
// over
// effectively never roll over
.expiry(Duration.ofDays(1825))
.bufferLength(1)
.build()
.merge(distributionStatisticConfig),
Expand Down
Loading