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

Data classes for exponential histogram prototype (#3550) #3637

Merged
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics.data;

import com.google.auto.value.AutoValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.concurrent.Immutable;

/**
* DoubleExponentialHistogramBuckets represents either the positive or negative measurements taken
* for a {@link DoubleExponentialHistogramPointData}.
*
* <p>The bucket boundaries are lower-bound inclusive, and are calculated using the {@link
* DoubleExponentialHistogramPointData#getScale()} and the {@link #getOffset()}.
*
* <p>For example, assume {@link DoubleExponentialHistogramPointData#getScale()} is 0, implying
* {@link DoubleExponentialHistogramPointData#getBase()} is 2.0. Then, if <code>offset</code> is 0,
* the bucket lower bounds would be 1.0, 2.0, 4.0, 8.0, etc. If <code>offset</code> is -3, the
* bucket lower bounds would be 0.125, 0.25, 0.5, 1.0, 2,0, etc. If <code>offset</code> is +3, the
* bucket lower bounds would be 8.0, 16.0, 32.0, etc.
*/
@AutoValue
@Immutable
public abstract class DoubleExponentialHistogramBuckets {
DoubleExponentialHistogramBuckets() {}

/**
* Create DoubleExponentialHistogramBuckets.
*
* @param offset Signed integer which shifts the bucket boundaries according to <code>
* lower_bound = base^(offset+i).</code>
* @param bucketCounts List of counts representing number of measurements that fall into each
* bucket.
* @return a DoubleExponentialHistogramBuckets.
*/
public DoubleExponentialHistogramBuckets create(int offset, List<Long> bucketCounts) {
long totalCount = 0;
for (long count : bucketCounts) {
totalCount += count;
}
return new AutoValue_DoubleExponentialHistogramBuckets(
offset, Collections.unmodifiableList(new ArrayList<>(bucketCounts)), totalCount);
}

/**
* The offset shifts the bucket boundaries according to <code>lower_bound = base^(offset+i).
* </code>.
*
* @return the offset.
*/
public abstract int getOffset();

public abstract List<Long> getBucketCounts();

public abstract long getTotalCount();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics.data;

import com.google.auto.value.AutoValue;
import java.util.Collection;
import javax.annotation.concurrent.Immutable;

/**
* A base-2 exponential histogram metric point, as defined by the OpenTelemetry Exponential
* Histogram specification.
*
* <p>See {@link DoubleExponentialHistogramPointData} for more information.
*
* <p>See:
* https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#exponentialhistogram
*
* <p><i>Note: This is called "DoubleExponentialHistogramData" to reflect which primitives are used
* to record it, however "ExponentialHistogram" is the equivalent OTLP type.</i>
*/
@Immutable
@AutoValue
public abstract class DoubleExponentialHistogramData
implements Data<DoubleExponentialHistogramPointData> {
DoubleExponentialHistogramData() {}

/**
* Creates a DoubleExponentialHistogramData.
*
* @param temporality The {@link AggregationTemporality}
* @param points A collection of {@link DoubleExponentialHistogramPointData} to hold measurements
* @return a DoubleExponentialHistogramData
*/
public static DoubleExponentialHistogramData create(
AggregationTemporality temporality, Collection<DoubleExponentialHistogramPointData> points) {
return new AutoValue_DoubleExponentialHistogramData(temporality, points);
}

/**
* Returns the {@code AggregationTemporality} of this metric.
*
* <p>AggregationTemporality describes if the aggregator reports delta changes since last report
* time, or cumulative changes since a fixed start time.
*
* @return the {@code AggregationTemporality} of this metric
*/
public abstract AggregationTemporality getAggregationTemporality();

@Override
public abstract Collection<DoubleExponentialHistogramPointData> getPoints();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics.data;

import com.google.auto.value.AutoValue;
import io.opentelemetry.api.common.Attributes;
import java.util.List;
import javax.annotation.concurrent.Immutable;

/**
* DoubleExponentialHistogramPointData represents an approximate distribution of measurements across
* exponentially increasing bucket boundaries, taken for a {@link DoubleExponentialHistogramData}.
* It contains the necessary information to calculate bucket boundaries and perform aggregation.
*
* <p>The bucket boundaries are calculated using both the scale {@link #getScale()}, and the offset
* {@link DoubleExponentialHistogramBuckets#getOffset()}.
*
* <p>See:
* https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/datamodel.md#exponentialhistogram
*/
@Immutable
@AutoValue
public abstract class DoubleExponentialHistogramPointData implements PointData {

DoubleExponentialHistogramPointData() {}

/**
* Creates a DoubleExponentialHistogramPointData.
*
* @param scale Scale characterises the resolution of the histogram, with larger values of scale
* offering greater precision. Bucket boundaries of the histogram are located at integer
* powers of the base, where <code>base = Math.pow(2, Math.pow(2, -scale))</code>.
* @param sum The sum of all measurements in the histogram.
* @param zeroCount Number of values that are zero.
* @param positiveBuckets Buckets with positive values.
* @param negativeBuckets Buckets with negative values.
* @return a DoubleExponentialHistogramPointData
*/
public static DoubleExponentialHistogramPointData create(
long startEpochNanos,
long epochNanos,
Attributes attributes,
int scale,
double sum,
long zeroCount,
DoubleExponentialHistogramBuckets positiveBuckets,
DoubleExponentialHistogramBuckets negativeBuckets,
List<Exemplar> exemplars) {

long count = zeroCount + positiveBuckets.getTotalCount() + negativeBuckets.getTotalCount();
double base = Math.pow(2, Math.pow(2, -scale));

return new AutoValue_DoubleExponentialHistogramPointData(
startEpochNanos,
epochNanos,
attributes,
scale,
sum,
count,
base,
zeroCount,
positiveBuckets,
negativeBuckets,
exemplars);
}

@Override
public abstract long getStartEpochNanos();

@Override
public abstract long getEpochNanos();

@Override
public abstract Attributes getAttributes();

/**
* Scale characterises the resolution of the histogram, with larger values of scale offering
* greater precision. Bucket boundaries of the histogram are located at integer powers of the
* base, where <code>base = Math.pow(2, Math.pow(2, -scale))</code>.
*
* @return the scale.
*/
public abstract int getScale();

public abstract double getSum();

public abstract long getCount();

public abstract double getBase();

public abstract long getZeroCount();

public abstract DoubleExponentialHistogramBuckets getPositiveBuckets();

public abstract DoubleExponentialHistogramBuckets getNegativeBuckets();

@Override
public abstract List<Exemplar> getExemplars();
}