10#include <userver/utils/impl/internal_tag.hpp>
11#include <userver/utils/statistics/histogram_view.hpp>
12#include <userver/utils/statistics/labels.hpp>
13#include <userver/utils/statistics/rate.hpp>
15USERVER_NAMESPACE_BEGIN
17namespace utils::statistics {
26template <
class Metric>
27constexpr auto HasDumpMetricWriter()
noexcept
28 ->
decltype(DumpMetric(std::declval<Writer&>(), std::declval<
const Metric&>()), std::true_type{}) {
32template <
class Metric,
class... Args>
33constexpr auto HasDumpMetricWriter(Args...)
noexcept {
34 return std::is_arithmetic_v<Metric>;
90 Writer(Writer&& other) =
delete;
91 Writer(
const Writer&) =
delete;
92 Writer& operator=(Writer&&) =
delete;
93 Writer& operator=(
const Writer&) =
delete;
98 [[nodiscard]] Writer
operator[](std::string_view path) &;
101 [[nodiscard]] Writer
operator[](std::string_view path) &&;
107 if constexpr (std::is_arithmetic_v<T> || std::is_same_v<std::decay_t<T>, Rate> || std::is_same_v<std::decay_t<T>, HistogramView> || std::is_same_v<std::decay_t<T>, MetricValue>) {
112 kHasWriterSupport<T>,
113 "Cast the metric to an arithmetic type or provide a "
114 "`void DumpMetric(utils::statistics::Writer& writer, "
115 "const Metric& value)` function for the `Metric` type"
117 DumpMetric(*
this, value);
125 auto new_writer = MakeChild();
126 new_writer.AppendLabelsSpan(labels);
133 ValueWithLabels(value, LabelsSpan{il});
139 ValueWithLabels(value, LabelsSpan{&label, &label + 1});
145 template <
class Func>
146 void WithLabels(
utils::impl::InternalTag, LabelsSpan labels, Func func) {
147 auto new_writer = MakeChild();
148 new_writer.AppendLabelsSpan(labels);
152 template <
class Func>
153 void WithLabels(
utils::impl::InternalTag, std::initializer_list<LabelView> il, Func func) {
154 WithLabels(utils::impl::InternalTag{}, LabelsSpan{il}, func);
157 template <
class Func>
158 void WithLabels(
utils::impl::InternalTag,
const LabelView& label, Func func) {
159 WithLabels(
utils::impl::InternalTag{}, LabelsSpan{&label, &label + 1}, func);
166 explicit operator bool()
const noexcept {
return !!state_; }
169 explicit Writer(impl::WriterState* state)
noexcept;
170 explicit Writer(impl::WriterState& state, LabelsSpan labels);
174 using ULongLong =
unsigned long long;
176 using PathSizeType = std::uint16_t;
177 using LabelsSizeType = std::uint8_t;
179 void Write(
unsigned long long value);
180 void Write(
long long value);
181 void Write(
double value);
182 void Write(
Rate value);
183 void Write(HistogramView value);
184 void Write(MetricValue value);
186 void Write(
float value) { Write(
static_cast<
double>(value)); }
188 void Write(
unsigned long value) { Write(
static_cast<ULongLong>(value)); }
189 void Write(
long value) { Write(
static_cast<
long long>(value)); }
190 void Write(
unsigned int value) { Write(
static_cast<
long long>(value)); }
191 void Write(
int value) { Write(
static_cast<
long long>(value)); }
192 void Write(
unsigned short value) { Write(
static_cast<
long long>(value)); }
193 void Write(
short value) { Write(
static_cast<
long long>(value)); }
198 Writer(Writer& other, MoveTag)
noexcept;
200 Writer MoveOut()
noexcept {
return Writer{*
this, MoveTag{}}; }
202 void ResetState()
noexcept;
203 void ValidateUsage();
205 void AppendPath(std::string_view path);
206 void AppendLabelsSpan(LabelsSpan labels);
208 impl::WriterState* state_;
209 const PathSizeType initial_path_size_;
210 PathSizeType current_path_size_;
211 const LabelsSizeType initial_labels_size_;
212 LabelsSizeType current_labels_size_;
215template <
class Metric>
216void DumpMetric(Writer& writer,
const std::atomic<Metric>& m) {
217 static_assert(std::atomic<Metric>::is_always_lock_free,
"std::atomic misuse");