X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=metrics.cpp;h=3fadb72907d9afdc5e2574269c57badd539eba6f;hb=1836dccf699779d9092a75755cec96cea1734a2a;hp=1f3f8a1c18b6478b2c7d5b3956137a3aa67169d9;hpb=1df7849fad1d0647a02951abaa60f9e4f40ce360;p=nageru diff --git a/metrics.cpp b/metrics.cpp index 1f3f8a1..3fadb72 100644 --- a/metrics.cpp +++ b/metrics.cpp @@ -4,19 +4,29 @@ #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; @@ -26,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; } @@ -49,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; } @@ -63,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; } @@ -80,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); } } @@ -160,13 +169,13 @@ string Histogram::serialize(const string &name, const vector