X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=metrics.cpp;h=3fadb72907d9afdc5e2574269c57badd539eba6f;hb=1836dccf699779d9092a75755cec96cea1734a2a;hp=3468ed766b17cbd11b987fcaac03ddfd8414dd51;hpb=c574aef4437253dcf0e6c1fed4c9cab1033b33f9;p=nageru diff --git a/metrics.cpp b/metrics.cpp index 3468ed7..3fadb72 100644 --- a/metrics.cpp +++ b/metrics.cpp @@ -1,21 +1,32 @@ #include "metrics.h" #include +#include #include +#include #include #include using namespace std; +using namespace std::chrono; Metrics global_metrics; -namespace { +double get_timestamp_for_metrics() +{ + return duration(system_clock::now().time_since_epoch()).count(); +} -string serialize_name(const string &name, const vector> &labels) +string Metrics::serialize_name(const string &name, const vector> &labels) +{ + return "nageru_" + name + serialize_labels(labels); +} + +string Metrics::serialize_labels(const vector> &labels) { if (labels.empty()) { - return "nageru_" + name; + return ""; } string label_str; @@ -25,21 +36,17 @@ string serialize_name(const string &name, const vector> &la } label_str += label.first + "=\"" + label.second + "\""; } - return "nageru_" + name + "{" + label_str + "}"; + return "{" + label_str + "}"; } -} // namespace - void Metrics::add(const string &name, const vector> &labels, atomic *location, Metrics::Type type) { Metric metric; metric.data_type = DATA_TYPE_INT64; - metric.name = name; - metric.labels = labels; metric.location_int64 = location; lock_guard lock(mu); - metrics.push_back(metric); + metrics.emplace(MetricKey(name, labels), metric); assert(types.count(name) == 0 || types[name] == type); types[name] = type; } @@ -48,12 +55,10 @@ void Metrics::add(const string &name, const vector> &labels { Metric metric; metric.data_type = DATA_TYPE_DOUBLE; - metric.name = name; - metric.labels = labels; metric.location_double = location; lock_guard lock(mu); - metrics.push_back(metric); + metrics.emplace(MetricKey(name, labels), metric); assert(types.count(name) == 0 || types[name] == type); types[name] = type; } @@ -62,12 +67,10 @@ void Metrics::add(const string &name, const vector> &labels { Metric metric; metric.data_type = DATA_TYPE_HISTOGRAM; - metric.name = name; - metric.labels = labels; metric.location_histogram = location; lock_guard lock(mu); - metrics.push_back(metric); + metrics.emplace(MetricKey(name, labels), metric); assert(types.count(name) == 0 || types[name] == TYPE_HISTOGRAM); types[name] = TYPE_HISTOGRAM; } @@ -79,22 +82,29 @@ string Metrics::serialize() const ss.precision(20); lock_guard lock(mu); - for (const auto &name_and_type : types) { - if (name_and_type.second == TYPE_GAUGE) { - ss << "# TYPE nageru_" << name_and_type.first << " gauge\n"; - } else if (name_and_type.second == TYPE_HISTOGRAM) { - ss << "# TYPE nageru_" << name_and_type.first << " histogram\n"; + auto type_it = types.cbegin(); + for (const auto &key_and_metric : metrics) { + string name = "nageru_" + key_and_metric.first.name + key_and_metric.first.serialized_labels; + const Metric &metric = key_and_metric.second; + + if (type_it != types.cend() && + key_and_metric.first.name == type_it->first) { + // It's the first time we print out any metric with this name, + // so add the type header. + if (type_it->second == TYPE_GAUGE) { + ss << "# TYPE nageru_" << type_it->first << " gauge\n"; + } else if (type_it->second == TYPE_HISTOGRAM) { + ss << "# TYPE nageru_" << type_it->first << " histogram\n"; + } + ++type_it; } - } - for (const Metric &metric : metrics) { - string name = serialize_name(metric.name, metric.labels); if (metric.data_type == DATA_TYPE_INT64) { ss << name << " " << metric.location_int64->load() << "\n"; } else if (metric.data_type == DATA_TYPE_DOUBLE) { ss << name << " " << metric.location_double->load() << "\n"; } else { - ss << metric.location_histogram->serialize(metric.name, metric.labels); + ss << metric.location_histogram->serialize(key_and_metric.first.name, key_and_metric.first.labels); } } @@ -119,6 +129,15 @@ void Histogram::init_uniform(size_t num_buckets) } } +void Histogram::init_geometric(double min, double max, size_t num_buckets) +{ + this->num_buckets = num_buckets; + buckets.reset(new Bucket[num_buckets]); + for (size_t i = 0; i < num_buckets; ++i) { + buckets[i].val = min * pow(max / min, double(i) / (num_buckets - 1)); + } +} + void Histogram::count_event(double val) { Bucket ref_bucket; @@ -150,13 +169,13 @@ string Histogram::serialize(const string &name, const vector