35#include <unordered_map>
44namespace kcenon {
namespace monitoring {
70 default:
return "unknown";
111 timestamp_us = std::chrono::duration_cast<std::chrono::microseconds>(
112 std::chrono::system_clock::now().time_since_epoch()).count();
117 timestamp_us = std::chrono::duration_cast<std::chrono::microseconds>(
118 std::chrono::system_clock::now().time_since_epoch()).count();
123 timestamp_us = std::chrono::duration_cast<std::chrono::microseconds>(
124 std::chrono::system_clock::now().time_since_epoch()).count();
131 if (std::holds_alternative<double>(
value)) {
132 return std::get<double>(
value);
133 }
else if (std::holds_alternative<int64_t>(
value)) {
134 return static_cast<double>(std::get<int64_t>(
value));
143 if (std::holds_alternative<int64_t>(
value)) {
144 return std::get<int64_t>(
value);
145 }
else if (std::holds_alternative<double>(
value)) {
146 return static_cast<int64_t
>(std::get<double>(
value));
155 if (std::holds_alternative<std::string>(
value)) {
156 return std::get<std::string>(
value);
157 }
else if (std::holds_alternative<double>(
value)) {
158 return std::to_string(std::get<double>(
value));
159 }
else if (std::holds_alternative<int64_t>(
value)) {
160 return std::to_string(std::get<int64_t>(
value));
169 return std::chrono::system_clock::time_point(
177 return std::holds_alternative<double>(
value) ||
178 std::holds_alternative<int64_t>(
value);
186 if (std::holds_alternative<std::string>(
value)) {
187 base_size += std::get<std::string>(
value).capacity();
220 total +=
metric.memory_footprint();
288 if (value <= bucket.upper_bound) {
306 {0.005, 0}, {0.01, 0}, {0.025, 0}, {0.05, 0}, {0.075, 0},
307 {0.1, 0}, {0.25, 0}, {0.5, 0}, {0.75, 0}, {1.0, 0},
308 {2.5, 0}, {5.0, 0}, {7.5, 0}, {10.0, 0},
309 {std::numeric_limits<double>::infinity(), 0}
321 double min_value = (std::numeric_limits<double>::max)();
322 double max_value = (std::numeric_limits<double>::lowest)();
347 min_value = (std::numeric_limits<double>::max)();
348 max_value = (std::numeric_limits<double>::lowest)();
366 double min_value = (std::numeric_limits<double>::max)();
367 double max_value = (std::numeric_limits<double>::lowest)();
396 samples.push_back(duration_ms);
399 size_t idx =
static_cast<size_t>(rand()) %
total_count;
409 template<
typename Rep,
typename Period>
410 void record(std::chrono::duration<Rep, Period> duration) {
411 auto ms = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() / 1000.0;
421 if (
samples.empty())
return 0.0;
427 double rank = (percentile / 100.0) * (
samples.size() - 1);
428 size_t lower_idx =
static_cast<size_t>(rank);
429 size_t upper_idx = lower_idx + 1;
430 double fraction = rank - lower_idx;
432 if (upper_idx >=
samples.size()) {
492 double min() const noexcept {
499 double max() const noexcept {
507 if (
samples.size() < 2)
return 0.0;
510 double variance = 0.0;
511 for (
double sample :
samples) {
512 double diff = sample - avg;
513 variance += diff * diff;
516 return std::sqrt(variance);
527 min_value = (std::numeric_limits<double>::max)();
528 max_value = (std::numeric_limits<double>::lowest)();
566 auto& mutable_samples =
const_cast<std::vector<double>&
>(
samples);
567 std::sort(mutable_samples.begin(), mutable_samples.end());
568 const_cast<bool&
>(
sorted) =
true;
585 auto end = std::chrono::steady_clock::now();
597 std::chrono::steady_clock::time_point
start_;
605 uint32_t hash = 2166136261U;
606 for (
char c : name) {
607 hash ^=
static_cast<uint32_t
>(c);
618 size_t tag_count = 0) {
622 static_cast<uint8_t
>((std::min)(tag_count,
size_t(255)))
RAII timer scope for automatic duration recording with timer_data.
timer_scope(timer_scope &&)=delete
std::chrono::steady_clock::time_point start_
timer_scope(timer_data &timer)
timer_scope & operator=(const timer_scope &)=delete
timer_scope(const timer_scope &)=delete
timer_scope & operator=(timer_scope &&)=delete
Monitoring system specific error codes.
metric_type
Metric types supported by exporters.
@ timer
StatsD-specific timer metric.
@ gauge
Instantaneous value that can go up and down.
@ counter
Monotonically increasing counter.
@ summary
Pre-calculated quantiles and count/sum.
@ histogram
Distribution of values with buckets.
uint32_t hash_metric_name(const std::string &name) noexcept
Hash function for metric names.
constexpr const char * metric_type_to_string(metric_type type) noexcept
Convert metric type to string.
metric_metadata create_metric_metadata(const std::string &name, metric_type type, size_t tag_count=0)
Create metric metadata from name and type.
@ gauge
Instantaneous value that can go up and down.
@ counter
Monotonically increasing counter.
@ histogram
Distribution of values with buckets.
Result pattern type definitions for monitoring system.
Memory-efficient metric value storage.
compact_metric_value(const metric_metadata &meta, double val) noexcept
size_t memory_footprint() const noexcept
Get memory footprint in bytes.
std::variant< double, int64_t, std::string > value_type
compact_metric_value(const metric_metadata &meta, std::string val) noexcept
compact_metric_value(const metric_metadata &meta, int64_t val) noexcept
compact_metric_value() noexcept
double as_double() const
Get value as double.
std::string as_string() const
Get value as string.
std::chrono::system_clock::time_point get_timestamp() const
Get timestamp as time_point.
bool is_numeric() const noexcept
Check if metric is numeric.
int64_t as_int64() const
Get value as integer.
Bucket for histogram metrics.
histogram_bucket(double bound=0.0, uint64_t cnt=0) noexcept
bool operator<(const histogram_bucket &other) const noexcept
Histogram data with buckets.
double mean() const noexcept
Get mean value.
void init_standard_buckets()
Initialize standard buckets.
std::vector< histogram_bucket > buckets
void add_sample(double value)
Add value to histogram.
Batch of metrics for efficient processing.
void clear()
Clear all metrics.
std::vector< compact_metric_value > metrics
size_t size() const noexcept
Get number of metrics in batch.
void add_metric(compact_metric_value &&metric)
Add metric to batch.
size_t memory_footprint() const noexcept
Get batch size in bytes.
bool empty() const noexcept
Check if batch is empty.
void reserve(size_t count)
Reserve space for metrics.
std::chrono::system_clock::time_point batch_timestamp
Basic metric structure for interface compatibility.
Summary statistics for metrics.
void reset()
Reset summary.
void add_sample(double value)
Add sample to summary.
double mean() const noexcept
Get mean value.
Get snapshot of current statistics.
Timer data with percentile calculations.
snapshot get_snapshot() const
double p99() const
Get p99 value.
double p90() const
Get p90 value.
uint64_t count() const noexcept
Get sample count.
void record(std::chrono::duration< Rep, Period > duration)
Record a duration using chrono duration.
double mean() const noexcept
Get mean value.
void ensure_sorted() const
double p95() const
Get p95 value.
std::vector< double > samples
double stddev() const
Get standard deviation.
double max() const noexcept
Get maximum recorded value.
double get_percentile(double percentile) const
Get percentile value (0-100)
double median() const
Get median (p50)
double p999() const
Get p999 value (99.9th percentile)
void record(double duration_ms)
Record a duration sample (in milliseconds)
timer_data(size_t reservoir_size)
Construct timer with custom reservoir size.
timer_data()
Construct timer with default reservoir size.
static constexpr size_t DEFAULT_RESERVOIR_SIZE
void reset()
Reset all data.
double min() const noexcept
Get minimum recorded value.