]> git.sesse.net Git - nageru/blobdiff - metrics.cpp
Update the queue length metric after trimming, not before.
[nageru] / metrics.cpp
index db3c4b8c4da97c571f264c0b7f1eb60810d3208b..5079acb2064e5515a1a549af00c35924edcc57dd 100644 (file)
@@ -19,9 +19,14 @@ double get_timestamp_for_metrics()
 }
 
 string Metrics::serialize_name(const string &name, const vector<pair<string, string>> &labels)
+{
+       return "nageru_" + name + serialize_labels(labels);
+}
+
+string Metrics::serialize_labels(const vector<pair<string, string>> &labels)
 {
        if (labels.empty()) {
-               return "nageru_" + name;
+               return "";
        }
 
        string label_str;
@@ -31,7 +36,7 @@ string Metrics::serialize_name(const string &name, const vector<pair<string, str
                }
                label_str += label.first + "=\"" + label.second + "\"";
        }
-       return "nageru_" + name + "{" + label_str + "}";
+       return "{" + label_str + "}";
 }
 
 void Metrics::add(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *location, Metrics::Type type)
@@ -58,10 +63,11 @@ void Metrics::add(const string &name, const vector<pair<string, string>> &labels
        types[name] = type;
 }
 
-void Metrics::add(const string &name, const vector<pair<string, string>> &labels, Histogram *location)
+void Metrics::add(const string &name, const vector<pair<string, string>> &labels, Histogram *location, Laziness laziness)
 {
        Metric metric;
        metric.data_type = DATA_TYPE_HISTOGRAM;
+       metric.laziness = laziness;
        metric.location_histogram = location;
 
        lock_guard<mutex> lock(mu);
@@ -70,6 +76,22 @@ void Metrics::add(const string &name, const vector<pair<string, string>> &labels
        types[name] = TYPE_HISTOGRAM;
 }
 
+void Metrics::remove(const string &name, const vector<pair<string, string>> &labels)
+{
+       lock_guard<mutex> lock(mu);
+
+       auto it = metrics.find(MetricKey(name, labels));
+       assert(it != metrics.end());
+
+       // If this is the last metric with this name, remove the type as well.
+       if (!((it != metrics.begin() && prev(it)->first.name == name) ||
+             (it != metrics.end() && next(it)->first.name == name))) {
+               types.erase(name);
+       }
+
+       metrics.erase(it);
+}
+
 string Metrics::serialize() const
 {
        stringstream ss;
@@ -79,7 +101,7 @@ string Metrics::serialize() const
        lock_guard<mutex> lock(mu);
        auto type_it = types.cbegin();
        for (const auto &key_and_metric : metrics) {
-               const string &name = key_and_metric.first.serialized;
+               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() &&
@@ -97,9 +119,15 @@ string Metrics::serialize() const
                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";
+                       double val = metric.location_double->load();
+                       if (isnan(val)) {
+                               // Prometheus can't handle “-nan”.
+                               ss << name << " NaN\n";
+                       } else {
+                               ss << name << " " << val << "\n";
+                       }
                } else {
-                       ss << metric.location_histogram->serialize(key_and_metric.first.name, key_and_metric.first.labels);
+                       ss << metric.location_histogram->serialize(metric.laziness, key_and_metric.first.name, key_and_metric.first.labels);
                }
        }
 
@@ -148,8 +176,22 @@ void Histogram::count_event(double val)
        sum = sum + val;
 }
 
-string Histogram::serialize(const string &name, const vector<pair<string, string>> &labels) const
+string Histogram::serialize(Metrics::Laziness laziness, const string &name, const vector<pair<string, string>> &labels) const
 {
+       // Check if the histogram is empty and should not be serialized.
+       if (laziness == Metrics::PRINT_WHEN_NONEMPTY && count_after_last_bucket.load() == 0) {
+               bool empty = true;
+               for (size_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx) {
+                       if (buckets[bucket_idx].count.load() != 0) {
+                               empty = false;
+                               break;
+                       }
+               }
+               if (empty) {
+                       return "";
+               }
+       }
+
        stringstream ss;
        ss.imbue(locale("C"));
        ss.precision(20);