1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-07-16 13:57:11 +02:00

Update POCO library.

This commit is contained in:
Sandu Liviu Catalin
2023-03-23 20:19:11 +02:00
parent 8d15f4b6e9
commit 233fc103f9
2521 changed files with 257092 additions and 72789 deletions

View File

@ -0,0 +1,105 @@
//
// AtomicFloat.h
//
// Library: Prometheus
// Package: Core
// Module: AtomicFloat
//
// Definition of the AtomicFloat class template.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_AtomicFloat_INCLUDED
#define Prometheus_AtomicFloat_INCLUDED
#include <atomic>
namespace Poco {
namespace Prometheus {
template <typename T>
class AtomicFloat
/// This class provides efficient atomic operations
/// on float and double values.
{
public:
AtomicFloat():
_value{0}
{
}
explicit AtomicFloat(T v):
_value(v)
{
}
AtomicFloat(const AtomicFloat& v):
_value(v.value())
{
}
AtomicFloat& operator = (const AtomicFloat& v)
{
_value.store(v.value());
return *this;
}
AtomicFloat& operator = (T v)
{
_value.store(v);
return *this;
}
operator T () const
{
return _value.load();
}
T value() const
{
return _value.load();
}
AtomicFloat& operator += (T value)
{
T expected = _value.load();
T desired;
do
{
desired = expected + value;
}
while (!_value.compare_exchange_weak(expected, desired));
return *this;
}
AtomicFloat& operator -= (T value)
{
T expected = _value.load();
T desired;
do
{
desired = expected - value;
}
while (!_value.compare_exchange_weak(expected, desired));
return *this;
}
private:
std::atomic<T> _value;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_AtomicFloat_INCLUDED

View File

@ -0,0 +1,151 @@
//
// CallbackMetric.h
//
// Library: Prometheus
// Package: Core
// Module: CallbackMetric
//
// Definition of the CallbackMetric class template.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_CallbackMetric_INCLUDED
#define Prometheus_CallbackMetric_INCLUDED
#include "Poco/Prometheus/Metric.h"
#include "Poco/Prometheus/Exporter.h"
#include <functional>
#include <vector>
namespace Poco {
namespace Prometheus {
template <typename T, Metric::Type metricType>
class CallbackMetric: public Metric
/// A generic Metric implementation where the sample is
/// obtained via a callback function or lambda.
///
/// The callback is invoked whenever the value
/// of the metric is requested. This is typically when
/// the metric is written to an Exporter.
///
/// This is implemented as a template to support both counter and gauge
/// metrics with different underlying types.
///
/// Note that only metric types COUNTER and GAUGE are supported.
///
/// Labels are not supported.
///
/// Example usage:
/// CallbackMetric<Poco::UInt64, Metric::Type::COUNTER> sampleCount(
/// "sample_count"s,
/// []()
/// {
/// return 42;
/// }
/// );
///
/// There are also pre-instantiated types available:
/// - CallbackIntCounter
/// - CallbackIntGauge
/// - CallbackCounter
/// - CallbackGauge
///
/// The following sample types are supported:
/// - Poco::Int32
/// - Poco::UInt32
/// - Poco::Int64
/// - Poco::UInt64
/// - double
{
public:
using Sample = T;
using Callback = std::function<Sample()>;
CallbackMetric(const std::string& name, Callback callback):
Metric(metricType, name),
_callback(callback)
/// Creates a CallbackMetric with the given type and name and
/// registers it with the default registry.
{
}
CallbackMetric(const std::string& name, const std::string& help, Callback callback):
Metric(metricType, name),
_callback(callback)
/// Creates a CallbackMetric with the given type, name and help text, and
/// registers it with the default registry.
{
setHelp(help);
}
CallbackMetric(const std::string& name, Registry* pRegistry, Callback callback):
Metric(metricType, name, pRegistry),
_callback(callback)
/// Creates a CallbackMetric with the given type and name and
/// registers it with the given registry (if not nullptr).
{
}
CallbackMetric(const std::string& name, const std::string& help, Registry* pRegistry, Callback callback):
Metric(metricType, name, pRegistry),
_callback(callback)
/// Creates a CallbackMetric with the given type, name and help text, and
/// registers it with the given registry (if not nullptr).
{
setHelp(help);
}
~CallbackMetric() = default;
/// Destroys the CallbackMetric.
using Metric::help;
CallbackMetric& help(const std::string& text)
/// Sets the CallbackMetric's help text.
///
/// Must only be set once, immediately after creating
/// the CallbackMetric.
{
setHelp(text);
return *this;
}
Sample value() const
/// Invokes the callback function and returns the
/// value returned by it.
{
return _callback();
}
// Collector
void exportTo(Exporter& exporter) const override
{
const std::vector<std::string> EMPTY_VEC;
exporter.writeHeader(*this);
exporter.writeSample(*this, EMPTY_VEC, EMPTY_VEC, _callback(), 0);
}
private:
Callback _callback;
};
using CallbackIntCounter = CallbackMetric<Poco::UInt64, Metric::Type::COUNTER>;
using CallbackIntGauge = CallbackMetric<Poco::Int64, Metric::Type::GAUGE>;
using CallbackCounter = CallbackMetric<double, Metric::Type::COUNTER>;
using CallbackGauge = CallbackMetric<double, Metric::Type::GAUGE>;
} } // namespace Poco::Prometheus
#endif // Prometheus_CallbackMetric_INCLUDED

View File

@ -0,0 +1,114 @@
//
// Collector.h
//
// Library: Prometheus
// Package: Core
// Module: Collector
//
// Definition of the Collector class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Collector_INCLUDED
#define Prometheus_Collector_INCLUDED
#include "Poco/Prometheus/Prometheus.h"
#include "Poco/Prometheus/Registry.h"
namespace Poco {
namespace Prometheus {
class Exporter;
class Registry;
class Prometheus_API Collector
/// This is the base class for all metrics, such as
/// Counter, Gauge and Histogram.
///
/// Collector objects automatically register themselves
/// with the default Registry (unless a nullptr is passed to the
/// constructor's pRegistry parameter), but do not automatically
/// unregister. This brings the danger of dangling pointers if
/// Collector instances are destroyed without being explicitly
/// unregistered first. In most practical cases this is not an
/// issue as Collector instances will be alive for the entire
/// run time of the process. However, it can be an issue if
/// Collector instances are created and destroyed dynamically
/// during the run time of the process.
{
public:
const std::string& name() const;
/// Returns the metric's name.
virtual void exportTo(Exporter& exporter) const = 0;
/// Writes the given Metric to the Exporter.
virtual ~Collector() = default;
/// Destroys the Collector.
protected:
Collector(const std::string& name);
/// Creates a Collector with the given name
/// and registers it with the default Registry.
///
/// The name must be a valid metric name and match the regular
/// expression [a-zA-Z_:][a-zA-Z0-9_:]*.
Collector(const std::string& name, Registry* pRegistry);
/// Creates a Collector with the given name
/// and registers it with the given Registry (if not nullptr).
///
/// The name must be a valid metric name and match the regular
/// expression [a-zA-Z_:][a-zA-Z0-9_:]*.
static const std::string& validateName(const std::string& name);
private:
const std::string _name;
Collector() = delete;
Collector(const Collector&) = delete;
Collector(Collector&&) = delete;
Collector& operator = (const Collector&) = delete;
Collector& operator = (Collector&&) = delete;
};
//
// inlines
//
inline Collector::Collector(const std::string& name):
_name(validateName(name))
{
Registry::defaultRegistry().registerCollector(this);
}
inline Collector::Collector(const std::string& name, Registry* pRegistry):
_name(validateName(name))
{
if (pRegistry) pRegistry->registerCollector(this);
}
inline const std::string& Collector::name() const
{
return _name;
}
} } // namespace Poco::Prometheus
#endif // Prometheus_Collector_INCLUDED

View File

@ -0,0 +1,191 @@
//
// Counter.h
//
// Library: Prometheus
// Package: Core
// Module: Counter
//
// Definition of the Counter class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Counter_INCLUDED
#define Prometheus_Counter_INCLUDED
#include "Poco/Prometheus/LabeledMetricImpl.h"
#include "Poco/Prometheus/AtomicFloat.h"
#include "Poco/Mutex.h"
namespace Poco {
namespace Prometheus {
class Prometheus_API CounterSample
{
public:
CounterSample() = default;
/// Creates the CounterSample.
~CounterSample() = default;
/// Destroys the CounterSample.
double value() const;
/// Returns the counter's current value.
Poco::Timestamp timestamp() const;
/// Returns the sample's timestamp, which in this
/// implementation is always 0.
void inc(double v = 1.0);
/// Increments the counter's current value.
private:
AtomicFloat<double> _value;
CounterSample(const CounterSample&) = delete;
CounterSample(CounterSample&&) = delete;
CounterSample& operator = (const CounterSample&) = delete;
CounterSample& operator = (CounterSample&&) = delete;
};
class Prometheus_API Counter: public LabeledMetricImpl<CounterSample>
/// A generic counter supporting labels.
///
/// To create a Counter with labels and register it
/// with the default Registry:
/// Counter sampleCounter("sample_counter"s, {
/// .help = "A sample counter"s,
/// .labelNames = {"label1"s, "label2"s}
/// });
///
/// To increment a Counter (with labels):
/// sampleCounter.labels({"value1"s, "value2"}).inc();
///
/// To create a Counter without labels and register it
/// with the default Registry:
/// Counter simpleCounter("simple_counter"s);
/// simpleCounter.help("A simple counter"s);
///
/// To increment the value of a Counter (without labels):
/// simpleCounter.inc(42);
{
public:
struct Params
{
std::string help;
std::vector<std::string> labelNames;
};
explicit Counter(const std::string& name);
/// Creates a Counter with the given name and
/// registers it with the default registry.
Counter(const std::string& name, const Params& params);
/// Creates a Counter with the given name and parameters
/// registers it with the default registry.
Counter(const std::string& name, Registry* pRegistry);
/// Creates a Counter with the given name and
/// registers it with the given registry (if not nullptr).
Counter(const std::string& name, const Params& params, Registry* pRegistry);
/// Creates a Counter with the given name and params, and
/// registers it with the given registry (if not nullptr).
~Counter() = default;
/// Destroys the Counter.
using LabeledMetric::help;
Counter& help(const std::string& text);
/// Sets the Counter's help text.
///
/// Must only be set once, immediately after creating
/// the Counter.
using LabeledMetric::labelNames;
Counter& labelNames(const std::vector<std::string>& labelNames);
/// Sets the Counter's label names.
///
/// Must only be set once, immediately after creating
/// the Counter.
double value() const;
/// Returns the counter's current value.
///
/// Can only be used if no labels have been defined.
void inc(double v = 1.0);
/// Increments the counter's current value.
///
/// Can only be used if no labels have been defined.
// Collector
void exportTo(Exporter& exporter) const override;
protected:
// LabeledMetricImpl
std::unique_ptr<CounterSample> createSample() const override;
void writeSample(Exporter& exporter, const std::vector<std::string>& labelValues, const CounterSample& sample) const override;
private:
CounterSample _sample;
};
//
// inlines
//
inline double CounterSample::value() const
{
return _value.value();
}
inline Poco::Timestamp CounterSample::timestamp() const
{
return 0;
}
inline void CounterSample::inc(double v)
{
poco_assert_dbg (v >= 0.0);
_value += v;
}
inline Counter& Counter::help(const std::string& text)
{
setHelp(text);
return *this;
}
inline Counter& Counter::labelNames(const std::vector<std::string>& labelNames)
{
setLabelNames(labelNames);
return *this;
}
inline void Counter::inc(double v)
{
_sample.inc(v);
}
} } // namespace Poco::Prometheus
#endif // Prometheus_Counter_INCLUDED

View File

@ -0,0 +1,76 @@
//
// Exporter.h
//
// Library: Prometheus
// Package: Core
// Module: Exporter
//
// Definition of the Exporter class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Exporter_INCLUDED
#define Prometheus_Exporter_INCLUDED
#include "Poco/Prometheus/Prometheus.h"
#include "Poco/Timestamp.h"
#include <vector>
namespace Poco {
namespace Prometheus {
class Metric;
class Prometheus_API Exporter
/// The Exporter interface is used to format and write metrics
/// to an output stream.
{
public:
virtual void writeHeader(const Metric& metric) = 0;
/// Writes the header (HELP and TYPE in text format).
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, float value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, double value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::UInt32 value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::Int32 value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::UInt64 value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::Int64 value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
virtual void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, const std::string& value, const Poco::Timestamp& timestamp = 0) = 0;
/// Writes a sample for the given metric and the given labels.
protected:
Exporter() = default;
virtual ~Exporter() = default;
Exporter(const Exporter&) = delete;
Exporter(Exporter&&) = delete;
Exporter& operator = (const Exporter&) = delete;
Exporter& operator = (Exporter&&) = delete;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_Exporter_INCLUDED

View File

@ -0,0 +1,273 @@
//
// Gauge.h
//
// Library: Prometheus
// Package: Core
// Module: Gauge
//
// Definition of the Gauge class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Gauge_INCLUDED
#define Prometheus_Gauge_INCLUDED
#include "Poco/Prometheus/LabeledMetricImpl.h"
#include "Poco/Prometheus/AtomicFloat.h"
#include "Poco/Clock.h"
#include "Poco/Mutex.h"
namespace Poco {
namespace Prometheus {
class Prometheus_API GaugeSample
{
public:
GaugeSample() = default;
/// Creates the GaugeSample.
~GaugeSample() = default;
/// Destroys the GaugeSample.
double value() const;
/// Returns the Gauge's current value.
Poco::Timestamp timestamp() const;
/// Returns the sample's timestamp, which in this
/// implementation is always 0.
void inc(double v = 1.0);
/// Increments the Gauge's current value.
void dec(double v = 1.0);
/// Decrements the Gauge's current value.
void set(double v);
/// Sets the Gauge's current value.
void set(Poco::Clock::ClockVal v);
/// Sets the Gauge's current value to the
/// given Clock value, converted to seconds.
void setToCurrentTime();
/// Sets the Gauge's current value to the current epoch time
/// (seconds since midnight January 1st 1970).
private:
AtomicFloat<double> _value;
GaugeSample(const GaugeSample&) = delete;
GaugeSample(GaugeSample&&) = delete;
GaugeSample& operator = (const GaugeSample&) = delete;
GaugeSample& operator = (GaugeSample&&) = delete;
};
class Prometheus_API Gauge: public LabeledMetricImpl<GaugeSample>
/// A generic gauge supporting labels.
///
///
/// To create a Gauge with labels and register it
/// with the default Registry:
/// Gauge sampleGauge("sample_gauge"s, {
/// .help = "A sample gauge"s,
/// .labelNames = {"label1"s, "label2"s}
/// });
///
/// To increment a Gauge (with labels):
/// sampleGauge.labels({"value1"s, "value2"}).inc();
///
/// To create a Gauge without labels and register it
/// with the default Registry:
/// Gauge simpleGauge("simple_gauge"s);
/// simpleGauge.help("A simple gauge"s);
///
/// To set the value of a Gauge (without labels):
/// simpleGauge.set(42);
{
public:
struct Params
{
std::string help;
std::vector<std::string> labelNames;
};
explicit Gauge(const std::string& name);
/// Creates a Gauge with the given name and
/// registers it with the default registry.
Gauge(const std::string& name, const Params& params);
/// Creates a Gauge with the given name and params and
/// registers it with the default registry.
Gauge(const std::string& name, Registry* pRegistry);
/// Creates a Gauge with the given name and
/// registers it with the given registry (if not nullptr).
Gauge(const std::string& name, const Params& params, Registry* pRegistry);
/// Creates a Gauge with the given name and params, and
/// registers it with the given registry (if not nullptr).
~Gauge() = default;
/// Destroys the Gauge.
using LabeledMetric::help;
Gauge& help(const std::string& text);
/// Sets the Gauge's help text.
///
/// Must only be set once, immediately after creating
/// the Gauge.
using LabeledMetric::labelNames;
Gauge& labelNames(const std::vector<std::string>& labelNames);
/// Sets the Gauge's label names.
///
/// Must only be set once, immediately after creating
/// the Gauge.
double value() const;
/// Returns the Gauge's current value.
///
/// Can only be used if no labels have been defined.
void inc(double v = 1.0);
/// Increments the Gauge's current value.
///
/// Can only be used if no labels have been defined.
void dec(double v = 1.0);
/// Decrements the Gauge's current value.
///
/// Can only be used if no labels have been defined.
void set(double v);
/// Sets the Gauge's current value.
///
/// Can only be used if no labels have been defined.
void set(Poco::Clock::ClockVal v);
/// Sets the Gauge's current value to the
/// given Clock value, converted to seconds.
///
/// Can only be used if no labels have been defined.
void setToCurrentTime();
/// Sets the Gauge's current value to the current epoch time
/// (seconds since midnight January 1st 1970).
// Collector
void exportTo(Exporter& exporter) const override;
protected:
// LabeledMetricImpl
std::unique_ptr<GaugeSample> createSample() const override;
void writeSample(Exporter& exporter, const std::vector<std::string>& labelValues, const GaugeSample& sample) const override;
private:
GaugeSample _sample;
};
//
// inlines
//
inline double GaugeSample::value() const
{
return _value.value();
}
inline Poco::Timestamp GaugeSample::timestamp() const
{
return 0;
}
inline void GaugeSample::inc(double v)
{
_value += v;
}
inline void GaugeSample::dec(double v)
{
_value -= v;
}
inline void GaugeSample::set(double v)
{
_value = v;
}
inline void GaugeSample::set(Poco::Clock::ClockVal v)
{
_value = static_cast<double>(v)/Poco::Clock::resolution();
}
inline void GaugeSample::setToCurrentTime()
{
_value = static_cast<double>(Poco::Timestamp().epochMicroseconds()/1000)/1000.0;
}
inline Gauge& Gauge::help(const std::string& text)
{
setHelp(text);
return *this;
}
inline Gauge& Gauge::labelNames(const std::vector<std::string>& labelNames)
{
setLabelNames(labelNames);
return *this;
}
inline void Gauge::inc(double v)
{
_sample.inc(v);
}
inline void Gauge::dec(double v)
{
_sample.dec(v);
}
inline void Gauge::set(double v)
{
_sample.set(v);
}
inline void Gauge::set(Poco::Clock::ClockVal v)
{
_sample.set(v);
}
inline void Gauge::setToCurrentTime()
{
_sample.setToCurrentTime();
}
} } // namespace Poco::Prometheus
#endif // Prometheus_Gauge_INCLUDED

View File

@ -0,0 +1,236 @@
//
// Histogram.h
//
// Library: Prometheus
// Package: Core
// Module: Histogram
//
// Definition of the Histogram class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Histogram_INCLUDED
#define Prometheus_Histogram_INCLUDED
#include "Poco/Prometheus/LabeledMetricImpl.h"
#include "Poco/Clock.h"
#include "Poco/Mutex.h"
#include <vector>
namespace Poco {
namespace Prometheus {
struct Prometheus_API HistogramData
{
std::vector<Poco::UInt64> bucketCounts;
/// Counter for each bucket.
double sum;
/// Sum of all observations.
Poco::UInt64 count;
/// Total number of observations.
};
class Prometheus_API HistogramSample
{
public:
explicit HistogramSample(const std::vector<double>& bucketBounds);
/// Creates the HistogramSample.
~HistogramSample() = default;
/// Destroys the HistogramSample.
void observe(double value);
/// Observes the given amount, by increasing the count
/// in the respective bucket.
void observe(Poco::Clock::ClockVal v);
/// Converts the given Clock time in microseconds to
/// seconds and increases the count in the respective
/// bucket.
///
/// Can only be used if no labels have been defined.
HistogramData data() const;
/// Returns the histogram's data.
const std::vector<double>& bucketBounds() const;
/// Returns the buckets upper bounds;
private:
const std::vector<double>& _bucketBounds;
std::vector<Poco::UInt64> _bucketCounts;
Poco::UInt64 _count = 0;
double _sum = 0.0;
mutable Poco::FastMutex _mutex;
HistogramSample() = delete;
HistogramSample(const HistogramSample&) = delete;
HistogramSample(HistogramSample&&) = delete;
HistogramSample& operator = (const HistogramSample&) = delete;
HistogramSample& operator = (HistogramSample&&) = delete;
};
class Prometheus_API Histogram: public LabeledMetricImpl<HistogramSample>
/// A histogram with a configurable number of buckets.
///
/// To create a Histogram with labels and three buckets, and register it
/// with the default Registry:
/// Histogram sampleHistogram("sample_histogram"s, {
/// .help = "A sample histogram"s,
/// .labelNames = {"label1"s, "label2"s},
/// .buckets = {0.5, 1.0, 5.0}
/// });
///
/// To observe a value with a Histogram (with labels):
/// sampleHistogram.labels({"value1"s, "value2"}).observe(1.5);
///
/// To create a Histogram without labels and register it
/// with the default Registry:
/// Histogram simpleHistogram("simple_histogram"s, {
/// .help = "A simple histogram"s,
/// .buckets = {0.5, 1.0, 5.0}
/// });
///
/// To observe a value with a Histogram (without labels):
/// simpleHistogram.observe(1.5);
{
public:
struct Params
{
std::string help;
std::vector<std::string> labelNames;
std::vector<double> buckets;
};
explicit Histogram(const std::string& name);
/// Creates a Histogram with the given name and
/// registers it with the default registry.
Histogram(const std::string& name, const Params& params);
/// Creates a Histogram with the given name and params, and
/// registers it with the default registry.
Histogram(const std::string& name, Registry* pRegistry);
/// Creates a Histogram with the given name and
/// registers it with the given registry (if not nullptr).
Histogram(const std::string& name, const Params& params, Registry* pRegistry);
/// Creates a Histogram with the given name and params, and
/// registers it with the given registry (if not nullptr).
~Histogram() = default;
/// Destroys the Histogram.
using Metric::help;
Histogram& help(const std::string& text);
/// Sets the Histogram's help text.
///
/// Must only be set once, immediately after creating
/// the Histogram.
using LabeledMetric::labelNames;
Histogram& labelNames(const std::vector<std::string>& labelNames);
/// Sets the Histogram's label names.
///
/// Must only be set once, immediately after creating
/// the Gauge. The label name "le" must not be used
/// as it is reserved for the histogram.
Histogram& buckets(const std::vector<double>& bucketBounds);
/// Sets the Histogram's bucket upper bounds.
///
/// Upper bounds must be strictly ordered from lowest to highest
/// value. The final infinite bucket must not be included.
///
/// Must only be set once, immediately after creating
/// the Histogram.
const std::vector<double> buckets() const;
/// Returns the configured bucket upper bounds.
void observe(double value);
/// Observes the given amount, by increasing the count
/// in the respective bucket.
void observe(Poco::Clock::ClockVal v);
/// Converts the given Clock time in microseconds to
/// seconds and increases the count in the respective
/// bucket.
///
/// Can only be used if no labels have been defined.
HistogramData data() const;
/// Returns the histogram's data.
// LabeledMetricImpl
std::unique_ptr<HistogramSample> createSample() const override;
// Collector
void exportTo(Exporter& exporter) const override;
private:
std::vector<double> _bucketBounds;
mutable Poco::FastMutex _mutex;
};
//
// inlines
//
inline const std::vector<double>& HistogramSample::bucketBounds() const
{
return _bucketBounds;
}
inline HistogramData HistogramSample::data() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
HistogramData data;
data.bucketCounts = _bucketCounts;
data.count = _count;
data.sum = _sum;
return data;
}
inline Histogram& Histogram::help(const std::string& text)
{
setHelp(text);
return *this;
}
inline Histogram& Histogram::labelNames(const std::vector<std::string>& labelNames)
{
setLabelNames(labelNames);
return *this;
}
inline const std::vector<double> Histogram::buckets() const
{
return _bucketBounds;
}
} } // namespace Poco::Prometheus
#endif // Prometheus_Gauge_INCLUDED

View File

@ -0,0 +1,153 @@
//
// IntCounter.h
//
// Library: Prometheus
// Package: Core
// Module: IntCounter
//
// Definition of the IntCounter class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_IntCounter_INCLUDED
#define Prometheus_IntCounter_INCLUDED
#include "Poco/Prometheus/Metric.h"
#include <atomic>
namespace Poco {
namespace Prometheus {
class Registry;
class Prometheus_API IntCounter: public Metric
/// IntCounter is a very low overhead implementation of
/// a Counter, supporting 64-bit unsigned integer values
/// only, using std::atomic
///
/// Labels are not supported.
{
public:
using Sample = Poco::UInt64;
struct Params
{
std::string help;
};
explicit IntCounter(const std::string& name);
/// Creates a IntCounter with the given name and
/// registers it with the default registry.
IntCounter(const std::string& name, const Params& params);
/// Creates a IntCounter with the given name and help text (via params), and
/// registers it with the default registry.
IntCounter(const std::string& name, Registry* pRegistry);
/// Creates a IntCounter with the given name and
/// registers it with the given registry (if not nullptr).
IntCounter(const std::string& name, const Params& params, Registry* pRegistry);
/// Creates a IntCounter with the given name and help text (via params), and
/// registers it with the given registry (if not nullptr).
~IntCounter() = default;
/// Destroys the IntCounter.
using Metric::help;
IntCounter& help(const std::string& text);
/// Sets the IntCounter's help text.
///
/// Must only be set once, immediately after creating
/// the IntCounter.
Sample value() const;
/// Returns the IntCounter's current value.
void inc();
/// Increments the IntCounter's current value by one.
void inc(Sample v);
/// Increments the IntCounter's current value by the given value.
void setToCurrentTime();
/// Sets the Gauge's current value to the current epoch time
/// (seconds since midnight January 1st 1970).
// Collector
void exportTo(Exporter& exporter) const override;
private:
std::atomic<Sample> _value{0};
};
//
// inlines
//
inline IntCounter::IntCounter(const std::string& name):
Metric(Metric::Type::COUNTER, name)
{
}
inline IntCounter::IntCounter(const std::string& name, const Params& params):
Metric(Metric::Type::COUNTER, name)
{
setHelp(params.help);
}
inline IntCounter::IntCounter(const std::string& name, Registry* pRegistry):
Metric(Metric::Type::COUNTER, name, pRegistry)
{
}
inline IntCounter::IntCounter(const std::string& name, const Params& params, Registry* pRegistry):
Metric(Metric::Type::COUNTER, name, pRegistry)
{
setHelp(params.help);
}
inline IntCounter& IntCounter::help(const std::string& text)
{
setHelp(text);
return *this;
}
inline IntCounter::Sample IntCounter::value() const
{
return _value.load(std::memory_order_relaxed);
}
inline void IntCounter::inc()
{
_value.fetch_add(1, std::memory_order_relaxed);
}
inline void IntCounter::inc(IntCounter::Sample v)
{
_value.fetch_add(v, std::memory_order_relaxed);
}
} } // namespace Poco::Prometheus
#endif // Prometheus_IntCounter_INCLUDED

View File

@ -0,0 +1,186 @@
//
// IntGauge.h
//
// Library: Prometheus
// Package: Core
// Module: IntGauge
//
// Definition of the IntGauge class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_IntGauge_INCLUDED
#define Prometheus_IntGauge_INCLUDED
#include "Poco/Prometheus/Metric.h"
#include <atomic>
namespace Poco {
namespace Prometheus {
class Registry;
class Prometheus_API IntGauge: public Metric
/// IntGauge is a very low overhead implementation of
/// a Gauge, supporting 64-bit integer values only,
/// using std::atomic.
///
/// Labels are not supported.
{
public:
using Sample = Poco::Int64;
struct Params
{
std::string help;
};
explicit IntGauge(const std::string& name);
/// Creates a IntGauge with the given name and
/// registers it with the default registry.
IntGauge(const std::string& name, const Params& params);
/// Creates a IntGauge with the given name and help text (via params), and
/// registers it with the default registry.
IntGauge(const std::string& name, Registry* pRegistry);
/// Creates a IntGauge with the given name and
/// registers it with the given registry (if not nullptr).
IntGauge(const std::string& name, const Params& params, Registry* pRegistry);
/// Creates a IntGauge with the given name and help text (via params), and
/// registers it with the given registry (if not nullptr).
~IntGauge() = default;
/// Destroys the IntGauge.
using Metric::help;
IntGauge& help(const std::string& text);
/// Sets the IntGauge's help text.
///
/// Must only be set once, immediately after creating
/// the IntGauge.
Sample value() const;
/// Returns the IntGauge's current value.
void inc();
/// Increments the IntGauge's current value by one.
void dec();
/// Decrements the IntGauge's current value by one.
void inc(Sample v);
/// Increments the IntGauge's current value by the given value.
void dec(Sample v);
/// Increments the IntGauge's current value by the given value.
void set(Sample v);
/// Sets the IntGauge's current value.
void setToCurrentTime();
/// Sets the Gauge's current value to the current epoch time
/// (seconds since midnight January 1st 1970).
// Collector
void exportTo(Exporter& exporter) const override;
private:
std::atomic<Sample> _value{0};
};
//
// inlines
//
inline IntGauge::IntGauge(const std::string& name):
Metric(Metric::Type::GAUGE, name)
{
}
inline IntGauge::IntGauge(const std::string& name, const Params& params):
Metric(Metric::Type::GAUGE, name)
{
setHelp(params.help);
}
inline IntGauge::IntGauge(const std::string& name, Registry* pRegistry):
Metric(Metric::Type::GAUGE, name, pRegistry)
{
}
inline IntGauge::IntGauge(const std::string& name, const Params& params, Registry* pRegistry):
Metric(Metric::Type::GAUGE, name, pRegistry)
{
setHelp(params.help);
}
inline IntGauge& IntGauge::help(const std::string& text)
{
setHelp(text);
return *this;
}
inline IntGauge::Sample IntGauge::value() const
{
return _value.load(std::memory_order_relaxed);
}
inline void IntGauge::inc()
{
_value.fetch_add(1, std::memory_order_relaxed);
}
inline void IntGauge::dec()
{
_value.fetch_sub(1, std::memory_order_relaxed);
}
inline void IntGauge::inc(IntGauge::Sample v)
{
_value.fetch_add(v, std::memory_order_relaxed);
}
inline void IntGauge::dec(IntGauge::Sample v)
{
_value.fetch_sub(v, std::memory_order_relaxed);
}
inline void IntGauge::set(IntGauge::Sample v)
{
_value.exchange(v, std::memory_order_relaxed);
}
inline void IntGauge::setToCurrentTime()
{
set(Poco::Timestamp().epochTime());
}
} } // namespace Poco::Prometheus
#endif // Prometheus_IntGauge_INCLUDED

View File

@ -0,0 +1,95 @@
//
// LabeledMetric.h
//
// Library: Prometheus
// Package: Core
// Module: LabeledMetric
//
// Definition of the LabeledMetric class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_LabeledMetric_INCLUDED
#define Prometheus_LabeledMetric_INCLUDED
#include "Poco/Prometheus/Metric.h"
#include <vector>
namespace Poco {
namespace Prometheus {
class Prometheus_API LabeledMetric: public Metric
/// This class adds support for labels to the
/// basic Metric class.
{
public:
const std::vector<std::string>& labelNames() const;
/// Returns the metric's label names.
protected:
LabeledMetric(Type type, const std::string& name);
/// Creates a LabeledMetric with the given type and name,
/// and registers it with the default Registry.
///
/// The name must be a valid metric name and match the regular
/// expression [a-zA-Z_:][a-zA-Z0-9_:]*.
LabeledMetric(Type type, const std::string& name, Registry* pRegistry);
/// Creates a LabeledMetric with the given type and name,
/// and registers it with the given Registry (if not nullptr).
///
/// The name must be a valid metric name and match the regular
/// expression [a-zA-Z_:][a-zA-Z0-9_:]*.
void setLabelNames(const std::vector<std::string>& labelNames);
/// Sets the metric's label names.
virtual ~LabeledMetric() = default;
/// Destroys the LabeledMetric.
static const std::string& validateLabelName(const std::string& name);
/// Validates the given name against the regular expression
/// defining a valid label name ([a-zA-Z_:][a-zA-Z0-9_:]*).
static const std::vector<std::string> EMPTY_LABEL;
private:
std::vector<std::string> _labelNames;
};
//
// inlines
//
inline LabeledMetric::LabeledMetric(Type type, const std::string& name):
Metric(type, name)
{
}
inline LabeledMetric::LabeledMetric(Type type, const std::string& name, Registry* pRegistry):
Metric(type, name, pRegistry)
{
}
inline const std::vector<std::string>& LabeledMetric::labelNames() const
{
return _labelNames;
}
} } // namespace Poco::Prometheus
#endif // Prometheus_Metric_INCLUDED

View File

@ -0,0 +1,193 @@
//
// LabeledMetricImpl.h
//
// Library: Prometheus
// Package: Core
// Module: LabeledMetric
//
// Definition of the MetricImpl class template.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_LabeledMetricImpl_INCLUDED
#define Prometheus_LabeledMetricImpl_INCLUDED
#include "Poco/Prometheus/LabeledMetric.h"
#include "Poco/Prometheus/Exporter.h"
#include "Poco/AutoPtr.h"
#include "Poco/String.h"
#include "Poco/Format.h"
#include "Poco/Mutex.h"
#include <functional>
#include <memory>
#include <map>
using namespace std::string_literals;
namespace Poco {
namespace Prometheus {
template <typename S>
class LabeledMetricImpl: public LabeledMetric
/// A helper class for implementing LabeledMetric classes such as Counter, Gauge and Histogram.
///
/// This class takes care of managing label values and samples.
{
public:
using Sample = S;
using ProcessingFunction = std::function<void(const std::vector<std::string>&, const Sample&)>;
LabeledMetricImpl(Type type, const std::string& name):
LabeledMetric(type, name)
{
}
LabeledMetricImpl(Type type, const std::string& name, Registry* pRegistry):
LabeledMetric(type, name, pRegistry)
{
}
Sample& labels(const std::vector<std::string>& labelValues)
/// Returns the Sample associated with the given label values.
///
/// If the sample does not exist yet, it is created.
///
/// The returned reference can be cached by the caller.
{
if (labelValues.size() != labelNames().size())
{
if (labelNames().empty())
throw Poco::InvalidArgumentException(Poco::format("Metric %s does not have labels"s, name()));
else
throw Poco::InvalidArgumentException(Poco::format("Metric %s requires label values for %s"s, name(), Poco::cat(", "s, labelNames().begin(), labelNames().end())));
}
Poco::FastMutex::ScopedLock lock(_mutex);
const auto it = _samples.find(labelValues);
if (it != _samples.end())
{
return *it->second;
}
else
{
std::unique_ptr<Sample> pUniqueSample = createSample();
Sample* pSample = pUniqueSample.get();
_samples[labelValues] = std::move(pUniqueSample);
return *pSample;
}
}
const Sample& labels(const std::vector<std::string>& labelValues) const
/// Returns the Sample associated with the given label values.
///
/// If the sample does not exist, a Poco::NotFoundException is thrown.
///
/// The returned reference can be cached by the caller.
{
if (labelValues.size() != labelNames().size())
throw Poco::InvalidArgumentException(Poco::format("Metric %s requires label values for %s"s, name(), Poco::cat(", "s, labelNames().begin(), labelNames().end())));
Poco::FastMutex::ScopedLock lock(_mutex);
const auto it = _samples.find(labelValues);
if (it != _samples.end())
{
return *it->second;
}
else
{
throw Poco::NotFoundException("Label values"s, Poco::cat("|"s, labelValues.begin(), labelValues.end()));
}
}
void remove(const std::vector<std::string>& labelValues)
/// Removes the sample associated with the given label values.
{
if (labelValues.size() != labelNames().size())
throw Poco::InvalidArgumentException(Poco::format("Metric %s requires label values for %s"s, name(), Poco::cat(", "s, labelNames().begin(), labelNames().end())));
if (labelNames().empty())
throw Poco::InvalidAccessException("Metric has no labels"s);
Poco::FastMutex::ScopedLock lock(_mutex);
_samples.erase(labelValues);
}
void clear()
/// Removes all samples.
{
Poco::FastMutex::ScopedLock lock(_mutex);
_samples.clear();
}
std::size_t sampleCount() const
/// Returns the number of samples.
{
Poco::FastMutex::ScopedLock lock(_mutex);
return _samples.size();
}
template <typename Fn>
void forEach(ProcessingFunction func) const
/// Calls the given function for each Sample.
{
Poco::FastMutex::ScopedLock lock(_mutex);
for (const auto& p: _samples)
{
func(p.first, *p.second);
}
}
// Collector
void exportTo(Exporter& exporter) const override
{
Poco::FastMutex::ScopedLock lock(_mutex);
exporter.writeHeader(*this);
for (const auto& p: _samples)
{
this->writeSample(exporter, p.first, *p.second);
}
}
protected:
virtual std::unique_ptr<Sample> createSample() const = 0;
/// Creates a new Sample. Must be overridden by subclasses.
virtual void writeSample(Exporter& exporter, const std::vector<std::string>& labelValues, const Sample& sample) const
/// Writes a Sample to the Exporter.
///
/// Must be overridden by subclasses, unless the subclass
/// overrides the exportTo() method.
///
/// The default implementation does nothing.
{
}
~LabeledMetricImpl() = default;
/// Destroys the LabeledMetricImpl.
private:
std::map<std::vector<std::string>, std::unique_ptr<Sample>> _samples;
mutable Poco::FastMutex _mutex;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_LabeledMetricImpl_INCLUDED

View File

@ -0,0 +1,116 @@
//
// Metric.h
//
// Library: Prometheus
// Package: Core
// Module: Metric
//
// Definition of the Metric class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Metric_INCLUDED
#define Prometheus_Metric_INCLUDED
#include "Poco/Prometheus/Collector.h"
#include "Poco/Prometheus/Registry.h"
namespace Poco {
namespace Prometheus {
class Prometheus_API Metric: public Collector
/// This is the base class for all metrics, such as
/// Counter, Gauge and Histogram.
{
public:
enum class Type
{
COUNTER,
GAUGE,
HISTOGRAM,
SUMMARY,
UNTYPED
};
Type type() const;
/// Returns the metric's type.
const std::string& help() const;
/// Returns the metric's help text.
~Metric() = default;
/// Destroys the Metric.
protected:
Metric(Type type, const std::string& name);
/// Creates a Metric with the given type and name,
/// and registers it with the default Registry.
///
/// The name must be a valid metric name and match the regular
/// expression [a-zA-Z_:][a-zA-Z0-9_:]*.
Metric(Type type, const std::string& name, Registry* pRegistry);
/// Creates a Metric with the given type and name,
/// and registers it with the given Registry (if not nullptr).
///
/// The name must be a valid metric name and match the regular
/// expression [a-zA-Z_:][a-zA-Z0-9_:]*.
void setHelp(const std::string& help);
/// Sets the metric's help text.
private:
const Type _type;
std::string _help;
};
//
// inlines
//
inline Metric::Metric(Type type, const std::string& name):
Collector(name),
_type(type)
{
}
inline Metric::Metric(Type type, const std::string& name, Registry* pRegistry):
Collector(name, pRegistry),
_type(type)
{
}
inline Metric::Type Metric::type() const
{
return _type;
}
inline const std::string& Metric::help() const
{
return _help;
}
inline void Metric::setHelp(const std::string& help)
{
_help = help;
}
} } // namespace Poco::Prometheus
#endif // Prometheus_Metric_INCLUDED

View File

@ -0,0 +1,54 @@
//
// MetricsRequestHandler.h
//
// Library: Prometheus
// Package: HTTP
// Module: MetricsRequestHandler
//
// Definition of the MetricsRequestHandler class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_MetricsRequestHandler_INCLUDED
#define Prometheus_MetricsRequestHandler_INCLUDED
#include "Poco/Prometheus/Prometheus.h"
#include "Poco/Net/HTTPRequestHandler.h"
namespace Poco {
namespace Prometheus {
class Registry;
class Prometheus_API MetricsRequestHandler: public Poco::Net::HTTPRequestHandler
/// This class handles incoming HTTP requests for metrics
/// in the Prometheus text format.
{
public:
MetricsRequestHandler();
/// Creates a HTTPRequestHandler using the default Registry.
MetricsRequestHandler(const Registry& registry);
/// Creates a HTTPRequestHandler using the given Registry.
// Poco::Net::HTTPRequestHandler
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override;
private:
const Registry& _registry;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_MetricsRequestHandler_INCLUDED

View File

@ -0,0 +1,80 @@
//
// MetricsServer.h
//
// Library: Prometheus
// Package: HTTP
// Module: MetricsServer
//
// Definition of the MetricsServer class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_MetricsServer_INCLUDED
#define Prometheus_MetricsServer_INCLUDED
#include "Poco/Prometheus/Prometheus.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/ServerSocket.h"
namespace Poco {
namespace Prometheus {
class Registry;
class Prometheus_API MetricsServer
/// A basic HTTP server for handling Prometheus metrics scraping
/// requests, based on Poco::Net::HTTPServer.
{
public:
static const Poco::UInt16 DEFAULT_PORT; /// 9100
static const std::string DEFAULT_PATH; /// "/metrics"
MetricsServer(Poco::UInt16 port = DEFAULT_PORT, const std::string& path = DEFAULT_PATH);
/// Creates a HTTPServer for serving metrics using the default Registry, listening
/// on the given port number and the given path.
MetricsServer(const Registry& registry, Poco::UInt16 port = DEFAULT_PORT, const std::string& path = DEFAULT_PATH);
/// Creates a HTTPServer for serving metrics using the given Registry, listening
/// on the given port number and the given path.
MetricsServer(const Registry& registry, Poco::Net::ServerSocket& socket, Poco::Net::HTTPServerParams::Ptr pServerParams = defaultParams(), const std::string& path = DEFAULT_PATH);
/// Creates a HTTPServer for serving metrics using the given Registry, listening
/// on the server socket (which can be a properly configured Poco::Net::SecureServerSocket
/// to enable HTTPS), and the given path.
~MetricsServer() = default;
/// Destroys the HTTPServer.
void start();
/// Starts the underlying Poco::Net::HTTPServer.
void stop();
/// Stops the underlying Poco::Net::HTTPServer.
protected:
static Poco::Net::HTTPServerParams::Ptr defaultParams();
private:
Poco::Net::HTTPServer _httpServer;
MetricsServer(const MetricsServer&) = delete;
MetricsServer(MetricsServer&&) = delete;
MetricsServer& operator = (const MetricsServer&) = delete;
MetricsServer& operator = (MetricsServer&&) = delete;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_MetricsServer_INCLUDED

View File

@ -0,0 +1,83 @@
//
// ProcessCollector.h
//
// Library: Prometheus
// Package: Collectors
// Module: ProcessCollector
//
// Definition of the ProcessCollector class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_ProcessCollector_INCLUDED
#define Prometheus_ProcessCollector_INCLUDED
#include "Poco/Prometheus/Collector.h"
#include "Poco/Prometheus/CallbackMetric.h"
#include "Poco/Timestamp.h"
#include <memory>
#include <vector>
namespace Poco {
namespace Prometheus {
class Prometheus_API ProcessCollector: public Collector
/// This Collector provides process-specific metrics:
/// - process_cpu_seconds_total: Total user and system CPU time spent in seconds.
/// - process_max_fds: Maximum number of open file descriptors.
/// - process_start_time_seconds: Start time of the process since unix epoch in seconds
/// (actually, the time the Prometheus library was loaded).
/// - process_up_time_seconds: Up time of the process in seconds
/// (actually, time since the Prometheus library was loaded).
{
public:
ProcessCollector();
/// Creates a default ProcessCollector.
ProcessCollector(const std::string& name, Registry* pRegistry);
/// Creates a custom ProcessCollector with the given name (prefix)
/// and registers it with the given Registry.
~ProcessCollector() = default;
/// Destroys the ProcessCollector.
static Poco::Timestamp startTime();
/// Returns the process start time.
// Collector
void exportTo(Exporter& exporter) const override;
/// Writes the given Metric to the Exporter.
protected:
void buildMetrics();
private:
using MetricPtr = std::unique_ptr<Metric>;
std::vector<MetricPtr> _metrics;
static Poco::Timestamp _startTime;
};
//
// inlines
//
inline Poco::Timestamp ProcessCollector::startTime()
{
return _startTime;
}
} } // namespace Poco::Prometheus
#endif // Prometheus_ProcessCollector_INCLUDED

View File

@ -0,0 +1,62 @@
//
// Prometheus.h
//
// Library: Prometheus
// Package: Core
// Module: Prometheus
//
// Basic definitions for the Poco Prometheus library.
// This file must be the first file included by every other Prometheus
// header file.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Prometheus_INCLUDED
#define Prometheus_Prometheus_INCLUDED
#include "Poco/Foundation.h"
//
// The following block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the Prometheus_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// Prometheus_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
//
#if defined(_WIN32) && defined(POCO_DLL)
#if defined(Prometheus_EXPORTS)
#define Prometheus_API __declspec(dllexport)
#else
#define Prometheus_API __declspec(dllimport)
#endif
#endif
#if !defined(Prometheus_API)
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
#define Prometheus_API __attribute__ ((visibility ("default")))
#else
#define Prometheus_API
#endif
#endif
//
// Automatically link Prometheus library.
//
#if defined(_MSC_VER)
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Prometheus_EXPORTS)
#pragma comment(lib, "PocoPrometheus" POCO_LIB_SUFFIX)
#endif
#endif
#endif // Prometheus_Prometheus_INCLUDED

View File

@ -0,0 +1,101 @@
//
// Registry.h
//
// Library: Prometheus
// Package: Core
// Module: Registry
//
// Definition of the Registry class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_Registry_INCLUDED
#define Prometheus_Registry_INCLUDED
#include "Poco/Prometheus/Prometheus.h"
#include "Poco/Mutex.h"
#include <map>
namespace Poco {
namespace Prometheus {
class Collector;
class Exporter;
class Prometheus_API Registry
/// The metric registry is a collection of all active
/// Collector instances.
///
/// The Registry internally stores plain pointers to Collector
/// objects. Collector objects automatically register themselves
/// with the default Registry (unless a nullptr is passed to the
/// constructor's pRegistry parameter), but do not automatically
/// unregister. This brings the danger of dangling pointers if
/// Collector instances are destroyed without being explicitly
/// unregistered first. In most practical cases this is not an
/// issue as Collector instances will be alive for the entire
/// run time of the process. However, it can be an issue if
/// Collector instances are created and destroyed dynamically
/// during the run time of the process.
{
public:
Registry() = default;
/// Creates the Registry.
~Registry() = default;
/// Destroys the Registry.
void registerCollector(Collector* pCollector);
/// Registers a Collector with the Registry.
///
/// An attempt to register a collector with the name
/// of an already registered collector will fail with
/// a Poco::ExistsException.
void unregisterCollector(Collector* pCollector);
/// Removes a Collector from the Registry.
void unregisterCollector(const std::string& collectorName);
/// Removes the Collector with the given name from the Registry.
///
/// Does nothing if no collector with the given name has been registered.
Collector* findCollector(const std::string& collectorName) const;
/// Looks up the Collector with the given name.
///
/// Returns a pointer to the collector instance if found,
/// otherwise returns a nullptr.
void clear();
/// Removes all Collector instances from the Registry.
void exportTo(Exporter& exporter) const;
/// Exports all registered collector's metrics through the given Exporter.
static Registry& defaultRegistry();
/// Returns the default Registry.
private:
std::map<std::string, Collector*> _collectors;
mutable Poco::FastMutex _mutex;
Registry(const Registry&) = delete;
Registry(Registry&&) = delete;
Registry& operator = (const Registry&) = delete;
Registry& operator = (Registry&&) = delete;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_Metric_INCLUDED

View File

@ -0,0 +1,73 @@
//
// TextExporter.h
//
// Library: Prometheus
// Package: Core
// Module: TextExporter
//
// Definition of the TextExporter class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_TextExporter_INCLUDED
#define Prometheus_TextExporter_INCLUDED
#include "Poco/Prometheus/Exporter.h"
#include "Poco/Prometheus/Metric.h"
#include <ostream>
namespace Poco {
namespace Prometheus {
class Prometheus_API TextExporter: public Exporter
/// Exporter implementation for the Prometheus text format.
///
/// See https://github.com/prometheus/docs/blob/main/content/docs/instrumenting/exposition_formats.md
/// for the specification of the Prometheus text exposition format.
{
public:
explicit TextExporter(std::ostream& ostr);
/// Creates the TextExporter for the given output stream.
TextExporter() = delete;
TextExporter(const TextExporter&) = delete;
TextExporter& operator = (const TextExporter&) = delete;
~TextExporter() = default;
// Exporter
void writeHeader(const Metric& metric) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, float value, const Poco::Timestamp& timestamp = 0) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, double value, const Poco::Timestamp& timestamp = 0) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::UInt32 value, const Poco::Timestamp& timestamp = 0) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::Int32 value, const Poco::Timestamp& timestamp = 0) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::UInt64 value, const Poco::Timestamp& timestamp = 0) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, Poco::Int64 value, const Poco::Timestamp& timestamp = 0) override;
void writeSample(const Metric& metric, const std::vector<std::string>& labelNames, const std::vector<std::string>& labelValues, const std::string& value, const Poco::Timestamp& timestamp = 0) override;
protected:
static const std::string& typeToString(Metric::Type type);
static const std::string COUNTER;
static const std::string GAUGE;
static const std::string HISTOGRAM;
static const std::string SUMMARY;
static const std::string UNTYPED;
private:
std::ostream& _stream;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_TextExporter_INCLUDED

View File

@ -0,0 +1,79 @@
//
// ThreadPoolCollector.h
//
// Library: Prometheus
// Package: Collectors
// Module: ThreadPoolCollector
//
// Definition of the ThreadPoolCollector class.
//
// Copyright (c) 2022, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Prometheus_ThreadPoolCollector_INCLUDED
#define Prometheus_ThreadPoolCollector_INCLUDED
#include "Poco/Prometheus/Collector.h"
#include "Poco/Prometheus/CallbackMetric.h"
#include "Poco/ThreadPool.h"
#include <memory>
#include <vector>
namespace Poco {
namespace Prometheus {
class Prometheus_API ThreadPoolCollector: public Collector
/// This Collector provides Poco::ThreadPool specific metrics:
/// - poco_threadpool_max_threads: Maximum number of threads available in the thread pool (capacity).
/// - poco_threadpool_used_threads: Number of currently used threads.
/// - poco_threadpool_allocated_threads: Number of currently allocated threads.
///
/// Metrics have a single label "name" identifying the thread pool.
/// The name of the default thread pool is "default".
{
public:
ThreadPoolCollector();
/// Creates a default ThreadPoolCollector for the default Poco::ThreadPool.
explicit ThreadPoolCollector(const Poco::ThreadPool& threadPool);
/// Creates a default ThreadPoolCollector for the given Poco::ThreadPool.
/// The Poco::ThreadPool must have a non-empty name and the name must
/// be unique across all ThreadPoolCollector instances.
ThreadPoolCollector(const std::string& name, const Poco::ThreadPool& threadPool, Registry* pRegistry);
/// Creates a custom ThreadPoolCollector with the given name
/// and registers it with the given Registry.
~ThreadPoolCollector() = default;
/// Destroys the ThreadPoolCollector.
// Collector
void exportTo(Exporter& exporter) const override;
/// Writes the given Metric to the Exporter.
protected:
void buildMetrics();
static std::string collectorName(const std::string& threadPoolName);
static const std::string NAME_PREFIX;
private:
using MetricPtr = std::unique_ptr<CallbackIntGauge>;
const std::string _threadPoolName;
const Poco::ThreadPool& _threadPool;
std::vector<MetricPtr> _metrics;
};
} } // namespace Poco::Prometheus
#endif // Prometheus_ThreadPoolCollector_INCLUDED