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

io.opentelemetry.sdk.metrics.internal.state.AsynchronousMetricStorage Maven / Gradle / Ivy

There is a newer version: 1.44.1
Show newest version
/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

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

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.internal.ThrottlingLogger;
import io.opentelemetry.sdk.metrics.View;
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
import io.opentelemetry.sdk.metrics.data.ExemplarData;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.data.PointData;
import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator;
import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor;
import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter;
import io.opentelemetry.sdk.metrics.internal.export.RegisteredReader;
import io.opentelemetry.sdk.metrics.internal.view.AttributesProcessor;
import io.opentelemetry.sdk.metrics.internal.view.RegisteredView;
import 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 RegisteredReader registeredReader; private final MetricDescriptor metricDescriptor; private final AggregationTemporality aggregationTemporality; private final Aggregator aggregator; private final AttributesProcessor attributesProcessor; private Map points = new HashMap<>(); private Map lastPoints = new HashMap<>(); // Only populated if aggregationTemporality == DELTA private AsynchronousMetricStorage( RegisteredReader registeredReader, MetricDescriptor metricDescriptor, Aggregator aggregator, AttributesProcessor attributesProcessor) { this.registeredReader = registeredReader; this.metricDescriptor = metricDescriptor; this.aggregationTemporality = registeredReader .getReader() .getAggregationTemporality(metricDescriptor.getSourceInstrument().getType()); 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( RegisteredReader registeredReader, RegisteredView registeredView, InstrumentDescriptor instrumentDescriptor) { View view = registeredView.getView(); MetricDescriptor metricDescriptor = MetricDescriptor.create(view, registeredView.getViewSourceInfo(), instrumentDescriptor); Aggregator aggregator = ((AggregatorFactory) view.getAggregation()) .createAggregator(instrumentDescriptor, ExemplarFilter.alwaysOff()); return new AsynchronousMetricStorage<>( registeredReader, metricDescriptor, aggregator, registeredView.getViewAttributesProcessor()); } /** * Record callback measurement from {@link ObservableLongMeasurement} or {@link * ObservableDoubleMeasurement}. */ void record(Measurement measurement) { Context context = Context.current(); Attributes processedAttributes = attributesProcessor.process(measurement.attributes(), context); long start = aggregationTemporality == AggregationTemporality.DELTA ? registeredReader.getLastCollectEpochNanos() : measurement.startEpochNanos(); measurement = measurement.hasDoubleValue() ? Measurement.doubleMeasurement( start, measurement.epochNanos(), measurement.doubleValue(), processedAttributes) : Measurement.longMeasurement( start, measurement.epochNanos(), measurement.longValue(), processedAttributes); recordPoint(aggregator.toPoint(measurement)); } private void recordPoint(T point) { Attributes attributes = point.getAttributes(); if (points.size() >= MetricStorage.MAX_CARDINALITY) { throttlingLogger.log( Level.WARNING, "Instrument " + metricDescriptor.getSourceInstrument().getName() + " has exceeded the maximum allowed cardinality (" + MetricStorage.MAX_CARDINALITY + ")."); return; } // Check there is not already a recording for the attributes if (points.containsKey(attributes)) { throttlingLogger.log( Level.WARNING, "Instrument " + metricDescriptor.getSourceInstrument().getName() + " has recorded multiple values for the same attributes."); return; } points.put(attributes, point); } @Override public MetricDescriptor getMetricDescriptor() { return metricDescriptor; } /** Returns the registered reader this storage is associated with. */ public RegisteredReader getRegisteredReader() { return registeredReader; } @Override public MetricData collect( Resource resource, InstrumentationScopeInfo instrumentationScopeInfo, long startEpochNanos, long epochNanos) { Map result; if (aggregationTemporality == AggregationTemporality.DELTA) { Map points = this.points; Map lastPoints = this.lastPoints; lastPoints.entrySet().removeIf(entry -> !points.containsKey(entry.getKey())); points.forEach( (k, v) -> lastPoints.compute(k, (k2, v2) -> v2 == null ? v : aggregator.diff(v2, v))); result = lastPoints; this.lastPoints = points; } else { result = points; } this.points = new HashMap<>(); return aggregator.toMetricData( resource, instrumentationScopeInfo, metricDescriptor, result.values(), aggregationTemporality); } @Override public boolean isEmpty() { return aggregator == Aggregator.drop(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy