All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.opentelemetry.sdk.metrics.internal.exemplar.ReservoirCell Maven / Gradle / Ivy

/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.sdk.metrics.internal.exemplar;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.metrics.data.DoubleExemplarData;
import io.opentelemetry.sdk.metrics.data.ExemplarData;
import io.opentelemetry.sdk.metrics.data.LongExemplarData;
import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData;
import io.opentelemetry.sdk.metrics.internal.data.ImmutableLongExemplarData;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A Reservoir cell pre-allocated memories for Exemplar data.
 *
 * 

We only allocate new objects during collection. This class should NOT cause allocations during * sampling or within the synchronous metric hot-path. * *

Allocations are acceptable in the {@link #getAndResetDouble(Attributes)} and {@link * #getAndResetLong(Attributes)} collection methods. */ class ReservoirCell { private final Clock clock; @Nullable private Attributes attributes; private SpanContext spanContext = SpanContext.getInvalid(); private long recordTime; // Cell stores either long or double values, but must not store both private long longValue; private double doubleValue; ReservoirCell(Clock clock) { this.clock = clock; } /** * Record the long measurement to the cell. * *

Must be used in tandem with {@link #getAndResetLong(Attributes)}. {@link * #recordDoubleMeasurement(double, Attributes, Context)} and {@link * #getAndResetDouble(Attributes)} must not be used when a cell is recording longs. */ synchronized void recordLongMeasurement(long value, Attributes attributes, Context context) { this.longValue = value; offerMeasurement(attributes, context); } /** * Record the long measurement to the cell. * *

Must be used in tandem with {@link #getAndResetDouble(Attributes)}. {@link * #recordLongMeasurement(long, Attributes, Context)} and {@link #getAndResetLong(Attributes)} * must not be used when a cell is recording longs. */ synchronized void recordDoubleMeasurement(double value, Attributes attributes, Context context) { this.doubleValue = value; offerMeasurement(attributes, context); } private void offerMeasurement(Attributes attributes, Context context) { this.attributes = attributes; // High precision time is not worth the additional performance expense it incurs for exemplars this.recordTime = clock.now(/* highPrecision= */ false); Span current = Span.fromContext(context); if (current.getSpanContext().isValid()) { this.spanContext = current.getSpanContext(); } } /** * Retrieve the cell's {@link ExemplarData}. * *

Must be used in tandem with {@link #recordLongMeasurement(long, Attributes, Context)}. */ @Nullable synchronized LongExemplarData getAndResetLong(Attributes pointAttributes) { Attributes attributes = this.attributes; if (attributes == null) { return null; } LongExemplarData result = ImmutableLongExemplarData.create( filtered(attributes, pointAttributes), recordTime, spanContext, longValue); reset(); return result; } /** * Retrieve the cell's {@link ExemplarData}. * *

Must be used in tandem with {@link #recordDoubleMeasurement(double, Attributes, Context)}. */ @Nullable synchronized DoubleExemplarData getAndResetDouble(Attributes pointAttributes) { Attributes attributes = this.attributes; if (attributes == null) { return null; } DoubleExemplarData result = ImmutableDoubleExemplarData.create( filtered(attributes, pointAttributes), recordTime, spanContext, doubleValue); reset(); return result; } synchronized void reset() { this.attributes = null; this.longValue = 0; this.doubleValue = 0; this.spanContext = SpanContext.getInvalid(); this.recordTime = 0; } /** Returns filtered attributes for exemplars. */ private static Attributes filtered(Attributes original, Attributes metricPoint) { if (metricPoint.isEmpty()) { return original; } Set> metricPointKeys = metricPoint.asMap().keySet(); return original.toBuilder().removeIf(metricPointKeys::contains).build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy