]> git.sesse.net Git - nageru/blobdiff - metrics.cpp
Rework metrics serialization.
[nageru] / metrics.cpp
index b721214a1ba3117f31ed06a07e8acbb4c8dec93d..ffa6b57b5dec2c9fe641e1af799b8afd2b98ba6d 100644 (file)
@@ -1,5 +1,7 @@
 #include "metrics.h"
 
+#include <assert.h>
+
 #include <locale>
 #include <sstream>
 
@@ -7,38 +9,68 @@ using namespace std;
 
 Metrics global_metrics;
 
-void Metrics::add(const string &name, atomic<int64_t> *location, Metrics::Type type)
+void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *location, Metrics::Type type)
 {
+       Metric metric;
+       metric.data_type = DATA_TYPE_INT64;
+       metric.name = name;
+       metric.labels = labels;
+       metric.location_int64 = location;
+
        lock_guard<mutex> lock(mu);
-       int_metrics.emplace(name, Metric<int64_t>{ type, location });
+       metrics.push_back(metric);
+       assert(types.count(name) == 0 || types[name] == type);
+       types[name] = type;
 }
 
-void Metrics::add(const string &name, atomic<double> *location, Metrics::Type type)
+void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<double> *location, Metrics::Type type)
 {
+       Metric metric;
+       metric.data_type = DATA_TYPE_DOUBLE;
+       metric.name = name;
+       metric.labels = labels;
+       metric.location_double = location;
+
        lock_guard<mutex> lock(mu);
-       double_metrics.emplace(name, Metric<double>{ type, location });
+       metrics.push_back(metric);
+       assert(types.count(name) == 0 || types[name] == type);
+       types[name] = type;
 }
 
 string Metrics::serialize() const
 {
        stringstream ss;
        ss.imbue(locale("C"));
+       ss.precision(20);
 
        lock_guard<mutex> lock(mu);
-       for (const auto &key_and_value : int_metrics) {
-               if (key_and_value.second.type == TYPE_GAUGE) {
-                       ss << "# TYPE nageru_" << key_and_value.first << " gauge\n";
+       for (const auto &name_and_type : types) {
+               if (name_and_type.second == TYPE_GAUGE) {
+                       ss << "# TYPE nageru_" << name_and_type.first << " gauge\n";
                }
-               ss << "nageru_" << key_and_value.first << " " << key_and_value.second.location->load() << "\n";
        }
+       for (const Metric &metric : metrics) {
+               string name;
+               if (metric.labels.empty()) {
+                       name = "nageru_" + metric.name;
+               } else {
+                       name = "nageru_" + metric.name + "{";
+                       bool first = true;
+                       for (const pair<string, string> &label : metric.labels) {
+                               if (!first) {
+                                       name += ",";
+                               }
+                               first = false;
+                               name += label.first + "=\"" + label.second + "\"";
+                       }
+                       name += "}";
+               }
 
-//     ss.precision(20);
-//     ss << scientific;
-       for (const auto &key_and_value : double_metrics) {
-               if (key_and_value.second.type == TYPE_GAUGE) {
-                       ss << "# TYPE nageru_" << key_and_value.first << " gauge\n";
+               if (metric.data_type == DATA_TYPE_INT64) {
+                       ss << "nageru_" << name << " " << metric.location_int64->load() << "\n";
+               } else {
+                       ss << "nageru_" << name << " " << metric.location_double->load() << "\n";
                }
-               ss << "nageru_" << key_and_value.first << " " << key_and_value.second.location->load() << "\n";
        }
 
        return ss.str();