Skip to content

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:

  1. prometheus_core_test
  2. prometheus_pull_internal_test
  3. 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
}
  1. Exposer
    • 包含一个负责监听promethues server拉取请求的webserver和一组uri的Endpoint
    • Client需要通过 RegisterCollectable 注册需要暴露的指标,Exposer将这些指标的地址添加到对应的MetricsHandler的收集列表中。
  2. CivetServer
    • 嵌入式Web服务器
    • 可通过 addHandler 添加uri请求对应的Handler(CivetHandler接口的实现)
  3. Endpoint
    • 包含Exposer中server的引用和一个MetricsHandler指针
    • 构造 Endpoint 时通过 addHandler 向 server 添加 uri 的 MetricsHandler
  4. MetricsHandler
    • 包含 Collectable 的指针数组,保存所有需要监控的指标族的地址
    • 重写 GET 请求的回调函数,在回调函数中遍历数组,收集所有指标样本,序列化后写入到响应体中
  5. MetricFamily
    • 保存收集到的指标数据的结构体,一个 MetricFamily 对象对应一系列同名指标
    • MetricFamily 包含一个 ClientMetric 数组
    • 每个 ClientMetric 是 MetricFamily 的一个指标(根据Label区分的同名指标)
  6. Collectable
    • 所有可被收集的类都需要实现的接口
  7. Family<T>
    • 一系列 T 类型同名指标的集合,包含如下成员:
      • metrics_:哈希表,指标指针字典,索引为 该指标的标签集 生成的 hash
      • labels_:标签集字典,索引为 hash
      • labels_reverse_lookup_:反向查找表,用于移除指标时删除对应的标签集
  8. 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

基于 VitePress 构建