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

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

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

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

/**
 * A circle-buffer-backed exponential counter.
 *
 * 

The first recorded value becomes the 'baseIndex'. Going backwards leads to start/stop index * *

This expand start/End index as it sees values. * *

This class is NOT thread-safe. It is expected to be behind a synchronized incrementer. * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time */ public class AdaptingCircularBufferCounter implements ExponentialCounter { private static final int NULL_INDEX = Integer.MIN_VALUE; private int endIndex = NULL_INDEX; private int startIndex = NULL_INDEX; private int baseIndex = NULL_INDEX; private final AdaptingIntegerArray backing; /** Constructs a circular buffer that will hold at most {@code maxSize} buckets. */ public AdaptingCircularBufferCounter(int maxSize) { this.backing = new AdaptingIntegerArray(maxSize); } /** (Deep)-Copies the values from another exponential counter. */ public AdaptingCircularBufferCounter(ExponentialCounter toCopy) { // If toCopy is an AdaptingCircularBuffer, just do a copy of the underlying array // and baseIndex. if (toCopy instanceof AdaptingCircularBufferCounter) { this.backing = ((AdaptingCircularBufferCounter) toCopy).backing.copy(); this.startIndex = toCopy.getIndexStart(); this.endIndex = toCopy.getIndexEnd(); this.baseIndex = ((AdaptingCircularBufferCounter) toCopy).baseIndex; } else { // Copy values from some other implementation of ExponentialCounter. this.backing = new AdaptingIntegerArray(toCopy.getMaxSize()); this.startIndex = NULL_INDEX; this.baseIndex = NULL_INDEX; this.endIndex = NULL_INDEX; for (int i = toCopy.getIndexStart(); i <= toCopy.getIndexEnd(); i++) { long val = toCopy.get(i); this.increment(i, val); } } } @Override public int getIndexStart() { return startIndex; } @Override public int getIndexEnd() { return endIndex; } @Override public boolean increment(int index, long delta) { if (baseIndex == NULL_INDEX) { startIndex = index; endIndex = index; baseIndex = index; backing.increment(0, delta); return true; } if (index > endIndex) { // Move end, check max size if ((long) index - startIndex + 1 > backing.length()) { return false; } endIndex = index; } else if (index < startIndex) { // Move end, check max size if ((long) endIndex - index + 1 > backing.length()) { return false; } startIndex = index; } int realIdx = toBufferIndex(index); backing.increment(realIdx, delta); return true; } @Override public long get(int index) { if (index < startIndex || index > endIndex) { return 0; } return backing.get(toBufferIndex(index)); } @Override public boolean isEmpty() { return baseIndex == NULL_INDEX; } @Override public int getMaxSize() { return backing.length(); } @Override public void clear() { this.backing.clear(); this.baseIndex = NULL_INDEX; this.endIndex = NULL_INDEX; this.startIndex = NULL_INDEX; } private int toBufferIndex(int index) { // Figure out the index relative to the start of the circular buffer. int result = index - baseIndex; if (result >= backing.length()) { result -= backing.length(); } else if (result < 0) { result += backing.length(); } return result; } @Override public String toString() { StringBuilder result = new StringBuilder("{"); for (int i = startIndex; i <= endIndex && startIndex != NULL_INDEX; i++) { if (i != startIndex) { result.append(','); } result.append(i).append('=').append(get(i)); } return result.append("}").toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy