// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include #include #include #include #include #include #include "opentelemetry/nostd/variant.h" #include "opentelemetry/sdk/metrics/data/circular_buffer.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace sdk { namespace metrics { namespace { struct AdaptingIntegerArrayIncrement { size_t index; uint64_t count; template uint64_t operator()(std::vector &backing) { const uint64_t result = backing[index] + count; if OPENTELEMETRY_LIKELY_CONDITION (result <= uint64_t(std::numeric_limits::max())) { backing[index] = static_cast(result); return 0; } return result; } }; struct AdaptingIntegerArrayGet { size_t index; template uint64_t operator()(const std::vector &backing) { return backing[index]; } }; struct AdaptingIntegerArraySize { template size_t operator()(const std::vector &backing) { return backing.size(); } }; struct AdaptingIntegerArrayClear { template void operator()(std::vector &backing) { backing.assign(backing.size(), static_cast(0)); } }; struct AdaptingIntegerArrayCopy { template void operator()(const std::vector &from, std::vector &to) { for (size_t i = 0; i < from.size(); i++) { to[i] = static_cast(from[i]); } } }; } // namespace void AdaptingIntegerArray::Increment(size_t index, uint64_t count) { /* May or may not fit */ const uint64_t result = nostd::visit(AdaptingIntegerArrayIncrement{index, count}, backing_); if OPENTELEMETRY_LIKELY_CONDITION (result == 0) { return; } EnlargeToFit(result); /* Must fit, buffer was enlarged for the value to store */ OPENTELEMETRY_MAYBE_UNUSED const uint64_t result2 = nostd::visit(AdaptingIntegerArrayIncrement{index, count}, backing_); assert(result2 == 0); } uint64_t AdaptingIntegerArray::Get(size_t index) const { return nostd::visit(AdaptingIntegerArrayGet{index}, backing_); } size_t AdaptingIntegerArray::Size() const { return nostd::visit(AdaptingIntegerArraySize{}, backing_); } void AdaptingIntegerArray::Clear() { nostd::visit(AdaptingIntegerArrayClear{}, backing_); } void AdaptingIntegerArray::EnlargeToFit(uint64_t value) { const size_t backing_size = Size(); decltype(backing_) backing; if (value <= std::numeric_limits::max()) { backing = std::vector(backing_size, 0); } else if (value <= std::numeric_limits::max()) { backing = std::vector(backing_size, 0); } else { backing = std::vector(backing_size, 0); } nostd::visit(AdaptingIntegerArrayCopy{}, backing_, backing); backing_ = std::move(backing); } void AdaptingCircularBufferCounter::Clear() { start_index_ = kNullIndex; end_index_ = kNullIndex; base_index_ = kNullIndex; backing_.Clear(); } bool AdaptingCircularBufferCounter::Increment(int32_t index, uint64_t delta) { if (Empty()) { start_index_ = index; end_index_ = index; base_index_ = index; backing_.Increment(0, delta); return true; } if (index > end_index_) { // Move end, check max size. if (index + 1 > static_cast(backing_.Size()) + start_index_) { return false; } end_index_ = index; } else if (index < start_index_) { // Move end, check max size. if (end_index_ + 1 > static_cast(backing_.Size()) + index) { return false; } start_index_ = index; } backing_.Increment(ToBufferIndex(index), delta); return true; } uint64_t AdaptingCircularBufferCounter::Get(int32_t index) const { if (index < start_index_ || index > end_index_) { return 0; } return backing_.Get(ToBufferIndex(index)); } size_t AdaptingCircularBufferCounter::ToBufferIndex(int32_t index) const { // Figure out the index relative to the start of the circular buffer. if (index < base_index_) { // If index is before the base one, wrap around. return static_cast(index + backing_.Size() - base_index_); } return static_cast(index - base_index_); } } // namespace metrics } // namespace sdk OPENTELEMETRY_END_NAMESPACE