Rust语言之Prometheus系统监控工具包的使用详解

 更新时间:2023年10月06日 08:30:03   作者:Pomelo_刘金  
Prometheus 是一个开源的系统监控和警报工具包,最初是由SoundCloud构建的,随着时间的发展,Prometheus已经具有适用于各种使用场景的版本,为了开发者方便开发,更是有各种语言版本的Prometheus的开发工具包,本文主要介绍Rust版本的Prometheus开发工具包

1. Prometheus 简介

Prometheus 是一个开源的系统监控和警报工具包,最初是由 SoundCloud 构建的。Prometheus 的主要优势在于其多维数据模型和灵活的查询语言,能够实现高效的数据存储和查询。

随着时间的发展,Prometheus已经具有适用于各种操作系统、各种使用场景的版本。为了开发者方便开发,更是有各种语言版本的Prometheus的开发工具包(本文主要介绍Rust版本的Prometheus开发工具包)

本文章具体介绍两个部分的使用:

  • Exporter:用于产生和发送信息

  • Prometheus:用于接收和展示信息

1.1 Exporter

在整个Prometheus 的使用中,Exporter是最基础和重要的部分,Prometheus只是负责接收并展示你想知道的信息,但是信息究竟从何而来呢?是的,消息由Exporter产生,并发送给Prometheus保存和记录。

广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter。而Exporter的一个实例称为target,Prometheus通过轮询的方式定期从这些target中获取样本数据。也就是说可以同时有多个Exporter给同一个Prometheus发送需要记录的信息。

其实对于Prometheus工具包的使用具体也在这一部分,通过工具包创建一个又一个Exporter从而完整的记录你想记录的任何信息,那问题来了Exporter结构应该是怎样的呢?究竟是使用工具包提供的api写在自己的程序里面,还是完全隔离开,写一个独立的Exporter程序呢?

从Exporter的运行方式上来讲,又可以分为:

  • 独立使用的

以Node Exporter为例,由于操作系统本身并不直接支持Prometheus,同时用户也无法通过直接从操作系统层面上提供对Prometheus的支持。因此,用户只能通过独立运行一个程序的方式,通过操作系统提供的相关接口,将系统的运行状态数据转换为可供Prometheus读取的监控数据。 除了Node Exporter以外,比如MySQL Exporter、Redis Exporter等都是通过这种方式实现的。 这些Exporter程序扮演了一个中间代理人的角色。

  • 集成到应用中的

为了能够更好的监控系统的内部运行状态,有些开源项目如Kubernetes,ETCD等直接在代码中使用了Prometheus的Client Library,提供了对Prometheus的直接支持。这种方式打破的监控的界限,让应用程序可以直接将内部的运行状态暴露给Prometheus,适合于一些需要更多自定义监控指标需求的项目。

1.2 安装 Prometheus

Prometheus主要用来显示从Exporter发送的信息,并且Prometheus可以在本地运行,只需下载对应的版本。

https://prometheus.io/download/

按照安装指南完成安装与配置。

我下载的是Linux,64位系统的版本:prometheus-2.47.0.linux-amd64.tar.gz

输入指令解压文件

tar -zxvf prometheus-2.47.0.linux-amd64.tar.gz

进入 Prometheus 目录

cd prometheus-2.47.0.linux-amd64

运行 Prometheus

./prometheus

现在 Prometheus 应该已经开始运行,并在默认的 9090 端口上监听。你可以在 Web 浏览器中通过访问 http://<你的服务器IP>:9090 来访问 Prometheus 的 Web 界面。

配置 Prometheus

Prometheus 通常还需要一个配置文件,例如 prometheus.yml,来定义如何执行服务发现和数据采集。在 Prometheus 目录中,你通常会找到一个示例配置文件,你可以根据自己的需要对其进行修改。

2.Prometheus 库的基本使用

2.1 创建新的 Rust 项目

使用 Cargo 创建一个新项目:

cargo new prometheus_example
cd prometheus_example

配置项目依赖,在 Cargo.toml 文件中加入 Prometheus 库:

[dependencies]
prometheus = "0.13.3"

0.13.3是写这篇文章时的最新版本。也许现在版本已经更新,建议使用最新的版本哦

https://docs.rs/prometheus/0.13.3/prometheus/

2.2 创建和配置 Prometheus 计数器

简单的 初始化 一个 计数器,并配置标签和值:

use prometheus::{Counter, Registry};
let reg = Registry::new();
let counter = Counter::new("example_counter", "An example counter").unwrap();
reg.register(Box::new(counter.clone())).unwrap();

也可以通过官方的的例子自定义Registry实例和counter实例

// 使用 `lazy_static!` 定义静态 `IntCounter`。
lazy_static! {
    static ref CUSTOM_COUNTER: IntCounter = IntCounter::new("custom", "dedicated counter").unwrap();
}
// Register custom metrics to a custom registry.
let mut labels = HashMap::new();
//这部分代码创建了一个带有自定义前缀“myprefix”的 `Registry`,并为它分配了一个标签,标签的键是“mykey”,值是“myvalue”。
labels.insert("mykey".to_string(), "myvalue".to_string());
let custom_registry = Registry::new_custom(Some("myprefix".to_string()),Some(labels)).unwrap();
//这一行调用了下面定义的 `custom_metrics` 函数,并将先前创建的 `custom_registry` 作为参数传递给它。
custom_metrics(&custom_registry);
/// Custom metrics, to be collected by a dedicated registry.
fn custom_metrics(registry: &Registry) {
    registry.register(Box::new(CUSTOM_COUNTER.clone())).unwrap();
    CUSTOM_COUNTER.inc_by(42);
    assert_eq!(CUSTOM_COUNTER.get(), 42);
}
//在这个函数中:
//  `CUSTOM_COUNTER` 被注册到了传递进来的 `Registry` 中。
//   然后,`CUSTOM_COUNTER` 的值增加了42。
//   最后,使用 `assert_eq!` 宏来验证 `CUSTOM_COUNTER` 的值是否确实为42。

通过上面的方式生成的metrics可以打印出来

// Print metrics for the custom registry.
let mut buffer = Vec::<u8>::new();
let encoder = prometheus::TextEncoder::new();
encoder
    .encode(&custom_registry.gather(), &mut buffer)
    .unwrap();
println!("## Custom registry");
println!("{}", String::from_utf8(buffer.clone()).unwrap());

打印结果:

## Custom registry
# HELP myprefix_custom dedicated counter
# TYPE myprefix_custom counter
myprefix_custom 42

3. 数据收集和展示

3.1通过web服务提供查询数据的接口给 Prometheus

因为 Prometheus 主要是通过 HTTP 协议来抓取(scrape)应用暴露出的指标(metrics)的,但这并不意味着你的应用必须是一个完整的 web 服务。你只需要为你的应用添加一个简单的 HTTP 服务器来暴露指标。这样的 HTTP 服务器通常非常轻量,对你的应用几乎没有什么影响。

可以使用warp的轻量级web框架,也可以使用最近刚推出的评价还不错的一个web框架,当然选用什么框架都看个人习惯。

我将用warp举例 在Cargo.toml文件中添加依赖

[dependencies]
warp = "0.3" 
tokio = { version = "1", features = ["full"] }

接下来,用warp创建一个简单的web服务:这个服务会在 http://[127:0:0:1]:8080/test 上暴露你的 Prometheus 指标:

use prometheus::{Encoder, TextEncoder};
use warp::Filter;
use std::collections::HashMap;
use prometheus::{Registry, IntCounter};
use std::sync::Arc;
use tokio::sync::RwLock;
lazy_static! {
    static ref CUSTOM_COUNTER: IntCounter = IntCounter::new("custom", "dedicated counter").unwrap();
#[tokio::main]
async fn main() {
let mut labels = HashMap::new();
labels.insert("mykey".to_string(), "myvalue".to_string());
let custom_registry = Registry::new_custom(Some("myprefix".to_string()),Some(labels)).unwrap();
custom_metrics(&custom_registry);
fn custom_metrics(registry: &Registry) {
    registry.register(Box::new(CUSTOM_COUNTER.clone())).unwrap();
    CUSTOM_COUNTER.inc_by(42);
    assert_eq!(CUSTOM_COUNTER.get(), 42);
}
let custom_registry = Arc::new(RwLock::new(custom_registry));
// 创建一个 warp filter,该 filter 会暴露 Prometheus 指标。
    let consensus_route = warp::path!("test").map(move || {
        GET_BLOCK_COUNTER.inc();
        SEND_TX_COUNTER.inc();
        let buffer = metrics_encode(Consensus_registry.clone());
        warp::reply::with_header(buffer, "Content-Type", "text/plain")
    });
    let routes=rpc_route.or(consensus_route);
    warp::serve(routes).run(([127, 0, 0, 1], 8080)).await;

在配置文件中添加刚刚写的web服务的网址,使打开prometheus可以定时访问这个地址从而获取信息。 文件编辑好后,保存,退出,重新运行prometheus就会去监控这个地址了。

3.2. 监控信息

打开浏览器,访问localhost:9090地址,会出现prometheus的监控画面

在搜索栏中输入想要监控的信息:myprefix_custom,点击Execute,便可以看到想要查询的信息,数量等

以上就是Rust语言之Prometheus系统监控工具包的使用详解的详细内容,更多关于Rust Prometheus工具包使用的资料请关注脚本之家其它相关文章!

相关文章

  • Rust 多线程编程的实现

    Rust 多线程编程的实现

    在rust中,多线程编程不算困难,但是也需要留心和别的编程语言中不同的地方,本文主要介绍了Rust 多线程编程的实现,感兴趣的可以了解一下
    2023-12-12
  • Rust 累计时间长度的操作方法

    Rust 累计时间长度的操作方法

    在Rust中,如果你想要记录累计时间,通常可以使用标准库中的std::time::Duration类型,这篇文章主要介绍了Rust如何累计时间长度,需要的朋友可以参考下
    2024-05-05
  • Rust使用kind进行异常处理(错误的分类与传递)

    Rust使用kind进行异常处理(错误的分类与传递)

    Rust 有一套独特的处理异常情况的机制,它并不像其它语言中的 try 机制那样简单,这篇文章主要介绍了Rust指南错误的分类与传递以及使用kind进行异常处理,需要的朋友可以参考下
    2022-09-09
  • 深入探究在Rust中函数、方法和关联函数有什么区别

    深入探究在Rust中函数、方法和关联函数有什么区别

    在 Rust 中,函数、方法和关联函数都是用来封装行为的,它们之间的区别主要在于它们的定义和调用方式,本文将通过一个简单的rust代码示例来给大家讲讲Rust中函数、方法和关联函数区别,需要的朋友可以参考下
    2023-08-08
  • rust 如何使用文件锁防止应用多开

    rust 如何使用文件锁防止应用多开

    这篇文章主要介绍了rust 如何使用文件锁防止应用多开,本文给出了进程只能单开的方法,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-04-04
  • rust 创建多线程web server的详细过程

    rust 创建多线程web server的详细过程

    web server 中主要的两个协议是 http 和 tcp,tcp 是底层协议,http 是构建在 tcp 之上的,本篇文章重点给大家介绍rust 创建多线程web server的详细过程,感兴趣的朋友跟随小编一起看看吧
    2023-11-11
  • rust中间件actix_web在项目中的使用实战

    rust中间件actix_web在项目中的使用实战

    这篇文章主要介绍了rust中间件在项目中的使用实战,包括自定义中间件,日志中间件,Default headers,用户会话,错误处理的用法实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Rust突破编译器限制构造可修改的全局变量

    Rust突破编译器限制构造可修改的全局变量

    这篇文章主要为大家介绍了Rust突破编译器限制构造可修改的全局变量示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 如何使用rust实现简单的单链表

    如何使用rust实现简单的单链表

    实现单链表在别的语言里面可能是一件简单的事情,单对于Rust来说,绝对不简单,下面这篇文章主要给大家介绍了关于如何使用rust实现简单的单链表的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • 使用Rust语言管理Node.js版本

    使用Rust语言管理Node.js版本

    这篇文章主要介绍一个使用 Rust 进行编写的一体化版本管理工具 Rtx,比如使用它来管理 Node.js 版本,它很简单易用,使用了它,就可以抛弃掉 nvm 了,文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下
    2023-12-12

最新评论