]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/core/src/text_serializer.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / prometheus-cpp / core / src / text_serializer.cc
diff --git a/ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/core/src/text_serializer.cc b/ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/core/src/text_serializer.cc
new file mode 100644 (file)
index 0000000..d26d3e5
--- /dev/null
@@ -0,0 +1,204 @@
+#include "prometheus/text_serializer.h"
+
+#include <cmath>
+#include <limits>
+#include <locale>
+#include <ostream>
+#include <string>
+
+#include "prometheus/client_metric.h"
+#include "prometheus/metric_family.h"
+#include "prometheus/metric_type.h"
+
+namespace prometheus {
+
+namespace {
+
+// Write a double as a string, with proper formatting for infinity and NaN
+void WriteValue(std::ostream& out, double value) {
+  if (std::isnan(value)) {
+    out << "Nan";
+  } else if (std::isinf(value)) {
+    out << (value < 0 ? "-Inf" : "+Inf");
+  } else {
+    out << value;
+  }
+}
+
+void WriteValue(std::ostream& out, const std::string& value) {
+  for (auto c : value) {
+    switch (c) {
+      case '\n':
+        out << '\\' << 'n';
+        break;
+
+      case '\\':
+        out << '\\' << c;
+        break;
+
+      case '"':
+        out << '\\' << c;
+        break;
+
+      default:
+        out << c;
+        break;
+    }
+  }
+}
+
+// Write a line header: metric name and labels
+template <typename T = std::string>
+void WriteHead(std::ostream& out, const MetricFamily& family,
+               const ClientMetric& metric, const std::string& suffix = "",
+               const std::string& extraLabelName = "",
+               const T& extraLabelValue = T()) {
+  out << family.name << suffix;
+  if (!metric.label.empty() || !extraLabelName.empty()) {
+    out << "{";
+    const char* prefix = "";
+
+    for (auto& lp : metric.label) {
+      out << prefix << lp.name << "=\"";
+      WriteValue(out, lp.value);
+      out << "\"";
+      prefix = ",";
+    }
+    if (!extraLabelName.empty()) {
+      out << prefix << extraLabelName << "=\"";
+      WriteValue(out, extraLabelValue);
+      out << "\"";
+    }
+    out << "}";
+  }
+  out << " ";
+}
+
+// Write a line trailer: timestamp
+void WriteTail(std::ostream& out, const ClientMetric& metric) {
+  if (metric.timestamp_ms != 0) {
+    out << " " << metric.timestamp_ms;
+  }
+  out << "\n";
+}
+
+void SerializeCounter(std::ostream& out, const MetricFamily& family,
+                      const ClientMetric& metric) {
+  WriteHead(out, family, metric);
+  WriteValue(out, metric.counter.value);
+  WriteTail(out, metric);
+}
+
+void SerializeGauge(std::ostream& out, const MetricFamily& family,
+                    const ClientMetric& metric) {
+  WriteHead(out, family, metric);
+  WriteValue(out, metric.gauge.value);
+  WriteTail(out, metric);
+}
+
+void SerializeSummary(std::ostream& out, const MetricFamily& family,
+                      const ClientMetric& metric) {
+  auto& sum = metric.summary;
+  WriteHead(out, family, metric, "_count");
+  out << sum.sample_count;
+  WriteTail(out, metric);
+
+  WriteHead(out, family, metric, "_sum");
+  WriteValue(out, sum.sample_sum);
+  WriteTail(out, metric);
+
+  for (auto& q : sum.quantile) {
+    WriteHead(out, family, metric, "", "quantile", q.quantile);
+    WriteValue(out, q.value);
+    WriteTail(out, metric);
+  }
+}
+
+void SerializeUntyped(std::ostream& out, const MetricFamily& family,
+                      const ClientMetric& metric) {
+  WriteHead(out, family, metric);
+  WriteValue(out, metric.untyped.value);
+  WriteTail(out, metric);
+}
+
+void SerializeHistogram(std::ostream& out, const MetricFamily& family,
+                        const ClientMetric& metric) {
+  auto& hist = metric.histogram;
+  WriteHead(out, family, metric, "_count");
+  out << hist.sample_count;
+  WriteTail(out, metric);
+
+  WriteHead(out, family, metric, "_sum");
+  WriteValue(out, hist.sample_sum);
+  WriteTail(out, metric);
+
+  double last = -std::numeric_limits<double>::infinity();
+  for (auto& b : hist.bucket) {
+    WriteHead(out, family, metric, "_bucket", "le", b.upper_bound);
+    last = b.upper_bound;
+    out << b.cumulative_count;
+    WriteTail(out, metric);
+  }
+
+  if (last != std::numeric_limits<double>::infinity()) {
+    WriteHead(out, family, metric, "_bucket", "le", "+Inf");
+    out << hist.sample_count;
+    WriteTail(out, metric);
+  }
+}
+
+void SerializeFamily(std::ostream& out, const MetricFamily& family) {
+  if (!family.help.empty()) {
+    out << "# HELP " << family.name << " " << family.help << "\n";
+  }
+  switch (family.type) {
+    case MetricType::Counter:
+      out << "# TYPE " << family.name << " counter\n";
+      for (auto& metric : family.metric) {
+        SerializeCounter(out, family, metric);
+      }
+      break;
+    case MetricType::Gauge:
+      out << "# TYPE " << family.name << " gauge\n";
+      for (auto& metric : family.metric) {
+        SerializeGauge(out, family, metric);
+      }
+      break;
+    case MetricType::Summary:
+      out << "# TYPE " << family.name << " summary\n";
+      for (auto& metric : family.metric) {
+        SerializeSummary(out, family, metric);
+      }
+      break;
+    case MetricType::Untyped:
+      out << "# TYPE " << family.name << " untyped\n";
+      for (auto& metric : family.metric) {
+        SerializeUntyped(out, family, metric);
+      }
+      break;
+    case MetricType::Histogram:
+      out << "# TYPE " << family.name << " histogram\n";
+      for (auto& metric : family.metric) {
+        SerializeHistogram(out, family, metric);
+      }
+      break;
+  }
+}
+}  // namespace
+
+void TextSerializer::Serialize(std::ostream& out,
+                               const std::vector<MetricFamily>& metrics) const {
+  auto saved_locale = out.getloc();
+  auto saved_precision = out.precision();
+
+  out.imbue(std::locale::classic());
+  out.precision(std::numeric_limits<double>::max_digits10 - 1);
+
+  for (auto& family : metrics) {
+    SerializeFamily(out, family);
+  }
+
+  out.imbue(saved_locale);
+  out.precision(saved_precision);
+}
+}  // namespace prometheus