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

io.opentelemetry.sdk.metrics.internal.view.AttributesProcessor Maven / Gradle / Ivy

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

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

import static io.opentelemetry.sdk.metrics.internal.view.NoopAttributesProcessor.NOOP;

import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import javax.annotation.concurrent.Immutable;

/**
 * An AttributesProcessor is used to define the actual set of attributes that will be used in a
 * Metric vs. the inbound set of attributes from a measurement.
 *
 * 

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ @Immutable public abstract class AttributesProcessor { AttributesProcessor() {} /** * Manipulates a set of attributes, returning the desired set. * * @param incoming Attributes associated with an incoming measurement. * @param context The context associated with the measurement. */ public abstract Attributes process(Attributes incoming, Context context); /** * If true, this ensures the `Context` argument of the attributes processor is always accurate. * This will prevents bound instruments from pre-locking their metric-attributes and defer until * context is available. */ public abstract boolean usesContext(); /** Joins this attribute processor with another that operates after this one. */ public AttributesProcessor then(AttributesProcessor other) { if (other == NOOP) { return this; } if (this == NOOP) { return other; } if (other instanceof JoinedAttributesProcessor) { return ((JoinedAttributesProcessor) other).prepend(this); } return new JoinedAttributesProcessor(Arrays.asList(this, other)); } /** No-op version of attributes processor, returns what it gets. */ public static AttributesProcessor noop() { return NOOP; } /** * Creates a processor which filters down attributes from a measurement. * * @param nameFilter a filter for which attribute keys to preserve. */ public static AttributesProcessor filterByKeyName(Predicate nameFilter) { return new AttributeKeyFilteringProcessor(nameFilter); } /** * Creates a processor which appends values from {@link Baggage}. * *

These attributes will not override those attributes provided by instrumentation. * * @param nameFilter a filter for which baggage keys to select. */ public static AttributesProcessor appendBaggageByKeyName(Predicate nameFilter) { return new BaggageAppendingAttributesProcessor(nameFilter); } /** * Creates a processor which appends (exactly) the given attributes. * *

These attributes will not override those attributes provided by instrumentation. * * @param attributes Attributes to append to measurements. */ public static AttributesProcessor append(Attributes attributes) { return new AppendingAttributesProcessor(attributes); } /** Creates a {@link Predicate} which tests if the {@code set} includes the input. */ public static Predicate setIncludes(Set set) { return new SetIncludesPredicate(set); } /** Predicate which tests if the {@code set} includes the input. */ private static class SetIncludesPredicate implements Predicate { private final Set set; private SetIncludesPredicate(Set set) { this.set = set; } @Override public boolean test(String s) { return set.contains(s); } @Override public String toString() { return "SetIncludesPredicate{set=" + set + "}"; } } /** * Processor which filters attributes according to a {@link AttributeKey#getKey()} {@link * Predicate}. */ private static class AttributeKeyFilteringProcessor extends AttributesProcessor { private final Predicate nameFilter; private AttributeKeyFilteringProcessor(Predicate nameFilter) { this.nameFilter = nameFilter; } @Override public Attributes process(Attributes incoming, Context context) { return incoming.toBuilder() .removeIf(attributeKey -> !nameFilter.test(attributeKey.getKey())) .build(); } @Override public boolean usesContext() { return false; } @Override public String toString() { return "AttributeKeyFilteringProcessor{nameFilter=" + nameFilter + "}"; } } /** Processor which appends a static set of {@link Attributes}. */ private static class AppendingAttributesProcessor extends AttributesProcessor { private final Attributes additionalAttributes; private AppendingAttributesProcessor(Attributes additionalAttributes) { this.additionalAttributes = additionalAttributes; } @Override public Attributes process(Attributes incoming, Context context) { return additionalAttributes.toBuilder().putAll(incoming).build(); } @Override public boolean usesContext() { return false; } @Override public String toString() { return "AppendingAttributesProcessor{additionalAttributes=" + additionalAttributes + "}"; } } /** Processor which appends entries from {@link Baggage} with keys that match a predicate. */ private static final class BaggageAppendingAttributesProcessor extends AttributesProcessor { private final Predicate nameFilter; private BaggageAppendingAttributesProcessor(Predicate nameFilter) { this.nameFilter = nameFilter; } @Override public Attributes process(Attributes incoming, Context context) { AttributesBuilder result = Attributes.builder(); Baggage.fromContext(context) .forEach( (k, v) -> { if (nameFilter.test(k)) { result.put(k, v.getValue()); } }); // Override any baggage keys with existing keys. result.putAll(incoming); return result.build(); } @Override public boolean usesContext() { return true; } @Override public String toString() { return "BaggageAppendingAttributesProcessor{nameFilter=" + nameFilter + "}"; } } /** A {@link AttributesProcessor} that runs a sequence of processors. */ @Immutable private static final class JoinedAttributesProcessor extends AttributesProcessor { private final Collection processors; private final boolean usesContextCache; JoinedAttributesProcessor(Collection processors) { this.processors = processors; this.usesContextCache = processors.stream().map(AttributesProcessor::usesContext).reduce(false, (l, r) -> l || r); } @Override public Attributes process(Attributes incoming, Context context) { Attributes result = incoming; for (AttributesProcessor processor : processors) { result = processor.process(result, context); } return result; } @Override public boolean usesContext() { return usesContextCache; } @Override public AttributesProcessor then(AttributesProcessor other) { List newList = new ArrayList<>(processors); if (other instanceof JoinedAttributesProcessor) { newList.addAll(((JoinedAttributesProcessor) other).processors); } else { newList.add(other); } return new JoinedAttributesProcessor(newList); } AttributesProcessor prepend(AttributesProcessor other) { List newList = new ArrayList<>(processors.size() + 1); newList.add(other); newList.addAll(processors); return new JoinedAttributesProcessor(newList); } @Override public String toString() { return "JoinedAttributesProcessor{processors=" + processors + "}"; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy