]> git.sesse.net Git - nageru/blob - metrics.cpp
Rework metrics serialization.
[nageru] / metrics.cpp
1 #include "metrics.h"
2
3 #include <assert.h>
4
5 #include <locale>
6 #include <sstream>
7
8 using namespace std;
9
10 Metrics global_metrics;
11
12 void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *location, Metrics::Type type)
13 {
14         Metric metric;
15         metric.data_type = DATA_TYPE_INT64;
16         metric.name = name;
17         metric.labels = labels;
18         metric.location_int64 = location;
19
20         lock_guard<mutex> lock(mu);
21         metrics.push_back(metric);
22         assert(types.count(name) == 0 || types[name] == type);
23         types[name] = type;
24 }
25
26 void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<double> *location, Metrics::Type type)
27 {
28         Metric metric;
29         metric.data_type = DATA_TYPE_DOUBLE;
30         metric.name = name;
31         metric.labels = labels;
32         metric.location_double = location;
33
34         lock_guard<mutex> lock(mu);
35         metrics.push_back(metric);
36         assert(types.count(name) == 0 || types[name] == type);
37         types[name] = type;
38 }
39
40 string Metrics::serialize() const
41 {
42         stringstream ss;
43         ss.imbue(locale("C"));
44         ss.precision(20);
45
46         lock_guard<mutex> lock(mu);
47         for (const auto &name_and_type : types) {
48                 if (name_and_type.second == TYPE_GAUGE) {
49                         ss << "# TYPE nageru_" << name_and_type.first << " gauge\n";
50                 }
51         }
52         for (const Metric &metric : metrics) {
53                 string name;
54                 if (metric.labels.empty()) {
55                         name = "nageru_" + metric.name;
56                 } else {
57                         name = "nageru_" + metric.name + "{";
58                         bool first = true;
59                         for (const pair<string, string> &label : metric.labels) {
60                                 if (!first) {
61                                         name += ",";
62                                 }
63                                 first = false;
64                                 name += label.first + "=\"" + label.second + "\"";
65                         }
66                         name += "}";
67                 }
68
69                 if (metric.data_type == DATA_TYPE_INT64) {
70                         ss << "nageru_" << name << " " << metric.location_int64->load() << "\n";
71                 } else {
72                         ss << "nageru_" << name << " " << metric.location_double->load() << "\n";
73                 }
74         }
75
76         return ss.str();
77 }