org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.state.AsynchronousMetricStorage Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.state;
import org.apache.rocketmq.shaded.io.opentelemetry.api.common.Attributes;
import org.apache.rocketmq.shaded.io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import org.apache.rocketmq.shaded.io.opentelemetry.api.metrics.ObservableLongMeasurement;
import org.apache.rocketmq.shaded.io.opentelemetry.context.Context;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.internal.ThrottlingLogger;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.View;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.data.AggregationTemporality;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.data.ExemplarData;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.data.MetricData;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.export.CollectionInfo;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.view.AttributesProcessor;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.metrics.internal.view.RegisteredView;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.resources.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Stores aggregated {@link MetricData} for asynchronous instruments.
*
* This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
final class AsynchronousMetricStorage implements MetricStorage {
private static final Logger logger = Logger.getLogger(AsynchronousMetricStorage.class.getName());
private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger);
private final MetricDescriptor metricDescriptor;
private final TemporalMetricStorage metricStorage;
private final Aggregator aggregator;
private final AttributesProcessor attributesProcessor;
private Map accumulations = new HashMap<>();
private AsynchronousMetricStorage(
MetricDescriptor metricDescriptor,
Aggregator aggregator,
AttributesProcessor attributesProcessor) {
this.metricDescriptor = metricDescriptor;
this.metricStorage = new TemporalMetricStorage<>(aggregator, /* isSynchronous= */ false);
this.aggregator = aggregator;
this.attributesProcessor = attributesProcessor;
}
/**
* Create an asynchronous storage instance for the {@link View} and {@link InstrumentDescriptor}.
*/
// TODO(anuraaga): The cast to generic type here looks suspicious.
static AsynchronousMetricStorage create(
RegisteredView registeredView, InstrumentDescriptor instrumentDescriptor) {
View view = registeredView.getView();
MetricDescriptor metricDescriptor =
MetricDescriptor.create(view, registeredView.getViewSourceInfo(), instrumentDescriptor);
Aggregator aggregator =
((AggregatorFactory) view.getAggregation())
.createAggregator(instrumentDescriptor, ExemplarFilter.neverSample());
return new AsynchronousMetricStorage<>(
metricDescriptor, aggregator, registeredView.getViewAttributesProcessor());
}
/** Record callback long measurements from {@link ObservableLongMeasurement}. */
void recordLong(long value, Attributes attributes) {
T accumulation = aggregator.accumulateLongMeasurement(value, attributes, Context.current());
if (accumulation != null) {
recordAccumulation(accumulation, attributes);
}
}
/** Record callback double measurements from {@link ObservableDoubleMeasurement}. */
void recordDouble(double value, Attributes attributes) {
T accumulation = aggregator.accumulateDoubleMeasurement(value, attributes, Context.current());
if (accumulation != null) {
recordAccumulation(accumulation, attributes);
}
}
private void recordAccumulation(T accumulation, Attributes attributes) {
Attributes processedAttributes = attributesProcessor.process(attributes, Context.current());
if (accumulations.size() >= MetricStorageUtils.MAX_ACCUMULATIONS) {
throttlingLogger.log(
Level.WARNING,
"Instrument "
+ metricDescriptor.getSourceInstrument().getName()
+ " has exceeded the maximum allowed accumulations ("
+ MetricStorageUtils.MAX_ACCUMULATIONS
+ ").");
return;
}
// Check there is not already a recording for the attributes
if (accumulations.containsKey(attributes)) {
throttlingLogger.log(
Level.WARNING,
"Instrument "
+ metricDescriptor.getSourceInstrument().getName()
+ " has recorded multiple values for the same attributes.");
return;
}
accumulations.put(processedAttributes, accumulation);
}
@Override
public MetricDescriptor getMetricDescriptor() {
return metricDescriptor;
}
@Override
public MetricData collectAndReset(
CollectionInfo collectionInfo,
Resource resource,
InstrumentationScopeInfo instrumentationScopeInfo,
long startEpochNanos,
long epochNanos,
boolean suppressSynchronousCollection) {
AggregationTemporality temporality =
collectionInfo.getAggregationTemporality(metricDescriptor.getSourceInstrument().getType());
Map currentAccumulations = accumulations;
accumulations = new HashMap<>();
return metricStorage.buildMetricFor(
collectionInfo.getCollector(),
resource,
instrumentationScopeInfo,
getMetricDescriptor(),
temporality,
currentAccumulations,
startEpochNanos,
epochNanos);
}
@Override
public boolean isEmpty() {
return aggregator == Aggregator.drop();
}
}