Prometheus Client Library for Modern C++
#Prometheus
项目链接:jupp0r/prometheus-cpp: Prometheus Client Library for Modern C++ (github.com)
简介
适用于现代 C++ 的 Prometheus 客户端库旨在实现 C++ 服务的Metric驱动开发。它实现了Promethues数据模型(Prometheus Data Model),可用于收集和暴露度量指标。
Requirements
兼容 C++11 的编译器。
Building
prometheus-cpp 支持 CMake 和 bazel 两种构建方式,CMake 是使用 prometheus-cpp 是首选方式,因为三个 prometheus-cpp 库之间的所有依赖关系都能得到正确处理。
cmake/project-import 目录包含一个示例项目和最小 CMakeLists.txt。
SHELL
# fetch third-party dependencies
git submodule init
git submodule update
mkdir _build
cd _build
# run cmake
cmake .. -DBUILD_SHARED_LIBS=ON -DENABLE_PUSH=OFF -DENABLE_COMPRESSION=OFF
# build
cmake --build . --parallel 4
# run tests
ctest -V ^084657
运行三个 test:
- prometheus_core_test
- prometheus_pull_internal_test
- prometheus_pull_test
Exposer 设计实现
plantuml
class Exposer
class CivetServer
class Endpoint
class Registry
class MetricsHandler
class CivetHandler
interface Collectable
class "Famliy<T>" << template >>
class "Famliy<Counter>"
class "Famliy<Gauge>"
class "Famliy<Summary>"
class "Famliy<Histogram>"
struct MetricFamily
struct ClientMetric
class Counter
class Gauge
class Summary
class Histogram
Exposer "1" o-- "1" CivetServer
Exposer "1" *-- "n" Endpoint
Endpoint "1" o-- "1" Registry
Endpoint "1" *-- "1" MetricsHandler
Collectable <|.. Registry
Collectable <|.. "Famliy<T>"
CivetHandler <|-- MetricsHandler
MetricsHandler "1" o-- "n" Collectable
CivetHandler <.. CivetServer
CivetServer "1" --o "n" Endpoint
Registry "1" o-- "n" "Famliy<Counter>"
Registry "1" o-- "n" "Famliy<Gauge>"
Registry "1" o-- "n" "Famliy<Summary>"
Registry "1" o-- "n" "Famliy<Histogram>"
MetricFamily <.. Collectable
ClientMetric <.. MetricFamily
"Famliy<T>" <.. "Famliy<Counter>"
"Famliy<T>" <.. "Famliy<Gauge>"
"Famliy<T>" <.. "Famliy<Summary>"
"Famliy<T>" <.. "Famliy<Histogram>"
Counter <.. "Famliy<Counter>"
Gauge <.. "Famliy<Gauge>"
Summary <.. "Famliy<Summary>"
Histogram <.. "Famliy<Histogram>"
interface Collectable
{
+ {abstract} vector<MetricFamily> Collect() const = 0
}
class Exposer
{
+ void RegisterCollectable(const weak_ptr<Collectable>&, cosnt string)
+ void RemoveCollectable(const weak_ptr<Collectable>&, cosnt string)
+ vector<int> GetListeningPorts() const
- Endpoint& GetEndpointForUri(cosnt string)
- unique_ptr<CivetServer> server_
- vector<unique_ptr<Endpoint>> endpoints_
}
class CivetServer
{
+ void addHandler(string &uri, CivetHandler *handler)
}
class Endpoint
{
+ void RegisterCollectable(const std::weak_ptr<Collectable>&)
+ void RemoveCollectable(const std::weak_ptr<Collectable>&)
+ string& GetURI() const
- CivetServer& server_
- const string uri_;
- shared_ptr<Registry> endpoint_registry_
- unique_ptr<MetricsHandler> metrics_handler_
}
class MetricsHandler
{
+ void RegisterCollectable(const std::weak_ptr<Collectable>&)
+ void RemoveCollectable(const std::weak_ptr<Collectable>&)
+ bool handleGet(CivetServer*, mg_connection*)
- vector<weak_ptr<Collectable>> collectables_
- Family<Counter>& bytes_transferred_family_
- Counter& bytes_transferred_
- Family<Counter>& num_scrapes_family_
- Counter& num_scrapes_
- Family<Summary>& request_latencies_family_
- Summary& request_latencies_
}
note left of MetricsHandler::handleGet
Callback method for
http GET request.
end note
note left of MetricsHandler::RegisterCollectable
pushback
end note
note left of "Famliy<T>"
combine values with the
same name, but distinct
label dimensions
end note
class Registry
{
- const InsertBehavior insert_behavior_
- vector<unique_ptr<Family<Counter>>> counters_
- vector<unique_ptr<Family<Gauge>>> gauges_
- vector<unique_ptr<Family<Histogram>>> histograms_
- vector<unique_ptr<Family<Summary>>> summaries_
- mutable mutex mutex_
}
class "Famliy<T>"
{
- unordered_map<size_t, unique_ptr<T>> metrics_
- unordered_map<size_t, map<string, string>> labels_
- unordered_map<T*, std::size_t> labels_reverse_lookup_
- const string name_
- const string help_
- const map<string, string> constant_labels_
- mutable mutex mutex_;
}
struct MetricFamily
{
+ string name
+ string help
+ MetricType type
+ vector<ClientMetric> metric
}
struct ClientMetric
{
+ struct Label
+ struct Counter
+ struct Gauge
+ struct Summary
+ struct Histogram
+ vector<Label> label
+ Counter counter
+ Gauge gauge
+ Summary summary
+ Histogram histogram
} - Exposer
- 包含一个负责监听promethues server拉取请求的webserver和一组uri的Endpoint
- Client需要通过
RegisterCollectable注册需要暴露的指标,Exposer将这些指标的地址添加到对应的MetricsHandler的收集列表中。
- CivetServer
- 嵌入式Web服务器
- 可通过
addHandler添加uri请求对应的Handler(CivetHandler接口的实现)
- Endpoint
- 包含Exposer中server的引用和一个MetricsHandler指针
- 构造 Endpoint 时通过
addHandler向 server 添加 uri 的 MetricsHandler
- MetricsHandler
- 包含 Collectable 的指针数组,保存所有需要监控的指标族的地址
- 重写 GET 请求的回调函数,在回调函数中遍历数组,收集所有指标样本,序列化后写入到响应体中
- MetricFamily
- 保存收集到的指标数据的结构体,一个 MetricFamily 对象对应一系列同名指标
- MetricFamily 包含一个 ClientMetric 数组
- 每个 ClientMetric 是 MetricFamily 的一个指标(根据Label区分的同名指标)
- Collectable
- 所有可被收集的类都需要实现的接口
- Family<T>
- 一系列 T 类型同名指标的集合,包含如下成员:
- metrics_:哈希表,指标指针字典,索引为 该指标的标签集 生成的 hash
- labels_:标签集字典,索引为 hash
- labels_reverse_lookup_:反向查找表,用于移除指标时删除对应的标签集
- 一系列 T 类型同名指标的集合,包含如下成员:
- Registry
- 保存所有通过该 Registry 注册暴露的各类指标族指针
流程
exposer 工作流程
plantuml
participant "promethues server" as PSer
participant client
participant exposer
collections endpoints
participant endpoint
participant metrics_handler
client -> exposer : create an http server,\n bind_address
|||
client -> exposer : create a metrics registry,\n ask the exposer to scrape\n the registry on incoming\n HTTP requests
exposer -> endpoints : GetEndpointForUri
group not found
endpoints -> endpoint : Endpoint(*server_, uri)
endpoint -> metrics_handler : MetricsHandler()
endpoint --> exposer : addHandler(uri, handler)
endpoint -> endpoints : pushback
end
endpoints -> exposer : return endpoint
exposer -> endpoint : RegisterCollectable
endpoint -> metrics_handler : RegisterCollectable
note over metrics_handler: pushback
|||
PSer -> exposer : Http GET Request
exposer -> metrics_handler : (uri, handler)
note over metrics_handler: CollectMetrics\n Serialize
metrics_handler -> PSer : Http Response