]> git.sesse.net Git - nageru/blob - metrics.cpp
Add some base x264 metrics.
[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 namespace {
13
14 string serialize_name(const string &name, const vector<pair<string, string>> &labels)
15 {
16         if (labels.empty()) {
17                 return "nageru_" + name;
18         }
19
20         string label_str;
21         for (const pair<string, string> &label : labels) {
22                 if (!label_str.empty()) {
23                         label_str += ",";
24                 }
25                 label_str += label.first + "=\"" + label.second + "\"";
26         }
27         return "nageru_" + name + "{" + label_str + "}";
28 }
29
30 }  // namespace
31
32 void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *location, Metrics::Type type)
33 {
34         Metric metric;
35         metric.data_type = DATA_TYPE_INT64;
36         metric.name = name;
37         metric.labels = labels;
38         metric.location_int64 = location;
39
40         lock_guard<mutex> lock(mu);
41         metrics.push_back(metric);
42         assert(types.count(name) == 0 || types[name] == type);
43         types[name] = type;
44 }
45
46 void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<double> *location, Metrics::Type type)
47 {
48         Metric metric;
49         metric.data_type = DATA_TYPE_DOUBLE;
50         metric.name = name;
51         metric.labels = labels;
52         metric.location_double = location;
53
54         lock_guard<mutex> lock(mu);
55         metrics.push_back(metric);
56         assert(types.count(name) == 0 || types[name] == type);
57         types[name] = type;
58 }
59
60 void Metrics::add_histogram(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *location, size_t num_elements)
61 {
62         Histogram histogram;
63         histogram.name = name;
64         histogram.labels = labels;
65         histogram.location_int64 = location;
66         histogram.num_elements = num_elements;
67
68         lock_guard<mutex> lock(mu);
69         histograms.push_back(histogram);
70 }
71
72 string Metrics::serialize() const
73 {
74         stringstream ss;
75         ss.imbue(locale("C"));
76         ss.precision(20);
77
78         lock_guard<mutex> lock(mu);
79         for (const auto &name_and_type : types) {
80                 if (name_and_type.second == TYPE_GAUGE) {
81                         ss << "# TYPE nageru_" << name_and_type.first << " gauge\n";
82                 }
83         }
84         for (const Metric &metric : metrics) {
85                 string name = serialize_name(metric.name, metric.labels);
86
87                 if (metric.data_type == DATA_TYPE_INT64) {
88                         ss << name << " " << metric.location_int64->load() << "\n";
89                 } else {
90                         ss << name << " " << metric.location_double->load() << "\n";
91                 }
92         }
93         for (const Histogram &histogram : histograms) {
94                 ss << "# TYPE nageru_" << histogram.name << " histogram\n";
95
96                 int64_t sum = 0, count = 0;
97                 for (size_t i = 0; i < histogram.num_elements; ++i) {
98                         char buf[16];
99                         snprintf(buf, sizeof(buf), "%lu", i);
100                         vector<pair<string, string>> labels = histogram.labels;
101                         labels.emplace_back("le", buf);
102
103                         int64_t val = histogram.location_int64[i].load();
104                         sum += i * val;
105                         count += val;
106                         ss << serialize_name(histogram.name + "_bucket", labels) << " " << count << "\n";
107                 }
108
109                 ss << serialize_name(histogram.name + "_sum", histogram.labels) << " " << sum << "\n";
110                 ss << serialize_name(histogram.name + "_count", histogram.labels) << " " << count << "\n";
111         }
112
113         return ss.str();
114 }