240 lines
6.0 KiB
Rust
240 lines
6.0 KiB
Rust
//! Prometheus 指标模块
|
||
//!
|
||
//! 提供 Prometheus 指标的定义、记录和导出功能。
|
||
//! 使用 `metrics` crate 作为 facade,`metrics-exporter-prometheus` 作为后端。
|
||
|
||
use metrics::{
|
||
counter, describe_counter, describe_gauge, describe_histogram, gauge, histogram, Unit,
|
||
};
|
||
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
|
||
use std::time::Duration;
|
||
use tracing::info;
|
||
|
||
// ============= 指标名称常量 =============
|
||
|
||
/// HTTP 请求总数
|
||
pub const HTTP_REQUESTS_TOTAL: &str = "http_requests_total";
|
||
/// HTTP 请求耗时
|
||
pub const HTTP_REQUEST_DURATION_SECONDS: &str = "http_request_duration_seconds";
|
||
|
||
/// gRPC 请求总数
|
||
pub const GRPC_REQUESTS_TOTAL: &str = "grpc_requests_total";
|
||
/// gRPC 请求耗时
|
||
pub const GRPC_REQUEST_DURATION_SECONDS: &str = "grpc_request_duration_seconds";
|
||
|
||
/// Agent 任务总数
|
||
pub const AGENT_TASKS_TOTAL: &str = "agent_tasks_total";
|
||
/// Agent 任务耗时
|
||
pub const AGENT_TASK_DURATION_SECONDS: &str = "agent_task_duration_seconds";
|
||
/// 活跃任务数
|
||
pub const AGENT_ACTIVE_TASKS: &str = "agent_active_tasks";
|
||
|
||
// ============= 初始化 =============
|
||
|
||
/// Initializing Prometheus 指标系统
|
||
///
|
||
/// 安装 Prometheus recorder 并返回 handle,用于渲染指标。
|
||
///
|
||
/// # Returns
|
||
///
|
||
/// 返回 `PrometheusHandle`,可通过 `render()` 方法获取 Prometheus 格式的指标文本。
|
||
///
|
||
/// # Example
|
||
///
|
||
/// ```no_run
|
||
/// use rcoder_telemetry::prometheus::init_prometheus;
|
||
///
|
||
/// fn main() {
|
||
/// let handle = init_prometheus().expect("Failed to init prometheus");
|
||
/// let metrics_text = handle.render();
|
||
/// println!("{}", metrics_text);
|
||
/// }
|
||
/// ```
|
||
pub fn init_prometheus() -> anyhow::Result<PrometheusHandle> {
|
||
let handle = PrometheusBuilder::new()
|
||
.install_recorder()
|
||
.map_err(|e| anyhow::anyhow!("Failed to install Prometheus recorder: {}", e))?;
|
||
|
||
// 注册指标描述
|
||
register_metric_descriptions();
|
||
|
||
info!("[Prometheus] Metrics system initialization completed");
|
||
|
||
Ok(handle)
|
||
}
|
||
|
||
/// 注册指标描述(元数据)
|
||
fn register_metric_descriptions() {
|
||
// HTTP 指标
|
||
describe_counter!(
|
||
HTTP_REQUESTS_TOTAL,
|
||
Unit::Count,
|
||
"Total number of HTTP requests"
|
||
);
|
||
describe_histogram!(
|
||
HTTP_REQUEST_DURATION_SECONDS,
|
||
Unit::Seconds,
|
||
"HTTP request duration in seconds"
|
||
);
|
||
|
||
// gRPC 指标
|
||
describe_counter!(
|
||
GRPC_REQUESTS_TOTAL,
|
||
Unit::Count,
|
||
"Total number of gRPC requests"
|
||
);
|
||
describe_histogram!(
|
||
GRPC_REQUEST_DURATION_SECONDS,
|
||
Unit::Seconds,
|
||
"gRPC request duration in seconds"
|
||
);
|
||
|
||
// Agent 指标
|
||
describe_counter!(
|
||
AGENT_TASKS_TOTAL,
|
||
Unit::Count,
|
||
"Total number of agent tasks"
|
||
);
|
||
describe_histogram!(
|
||
AGENT_TASK_DURATION_SECONDS,
|
||
Unit::Seconds,
|
||
"Agent task duration in seconds"
|
||
);
|
||
describe_gauge!(
|
||
AGENT_ACTIVE_TASKS,
|
||
Unit::Count,
|
||
"Current number of active agent tasks"
|
||
);
|
||
}
|
||
|
||
// ============= HTTP 指标 =============
|
||
|
||
/// 记录 HTTP 请求
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `method` - HTTP 方法(GET, POST 等)
|
||
/// * `path` - 请求路径
|
||
/// * `status` - 响应状态码
|
||
pub fn record_http_request(method: &str, path: &str, status: u16) {
|
||
counter!(
|
||
HTTP_REQUESTS_TOTAL,
|
||
"method" => method.to_string(),
|
||
"path" => path.to_string(),
|
||
"status" => status.to_string()
|
||
)
|
||
.increment(1);
|
||
}
|
||
|
||
/// 记录 HTTP 请求耗时
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `method` - HTTP 方法
|
||
/// * `path` - 请求路径
|
||
/// * `duration` - 请求耗时
|
||
pub fn record_http_duration(method: &str, path: &str, duration: Duration) {
|
||
histogram!(
|
||
HTTP_REQUEST_DURATION_SECONDS,
|
||
"method" => method.to_string(),
|
||
"path" => path.to_string()
|
||
)
|
||
.record(duration.as_secs_f64());
|
||
}
|
||
|
||
// ============= gRPC 指标 =============
|
||
|
||
/// 记录 gRPC 请求
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `method` - gRPC 方法名(如 "Chat", "SubscribeProgress")
|
||
/// * `status` - 状态("ok", "error")
|
||
pub fn record_grpc_request(method: &str, status: &str) {
|
||
counter!(
|
||
GRPC_REQUESTS_TOTAL,
|
||
"method" => method.to_string(),
|
||
"status" => status.to_string()
|
||
)
|
||
.increment(1);
|
||
}
|
||
|
||
/// 记录 gRPC 请求耗时
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `method` - gRPC 方法名
|
||
/// * `duration` - 请求耗时
|
||
pub fn record_grpc_duration(method: &str, duration: Duration) {
|
||
histogram!(
|
||
GRPC_REQUEST_DURATION_SECONDS,
|
||
"method" => method.to_string()
|
||
)
|
||
.record(duration.as_secs_f64());
|
||
}
|
||
|
||
// ============= Agent 指标 =============
|
||
|
||
/// 记录 Agent 任务
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `project_id` - 项目 ID
|
||
/// * `status` - 任务状态("success", "error", "timeout")
|
||
pub fn record_agent_task(project_id: &str, status: &str) {
|
||
counter!(
|
||
AGENT_TASKS_TOTAL,
|
||
"project_id" => project_id.to_string(),
|
||
"status" => status.to_string()
|
||
)
|
||
.increment(1);
|
||
}
|
||
|
||
/// 记录 Agent 任务耗时
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `project_id` - 项目 ID
|
||
/// * `duration` - 任务耗时
|
||
pub fn record_agent_task_duration(project_id: &str, duration: Duration) {
|
||
histogram!(
|
||
AGENT_TASK_DURATION_SECONDS,
|
||
"project_id" => project_id.to_string()
|
||
)
|
||
.record(duration.as_secs_f64());
|
||
}
|
||
|
||
/// 设置活跃任务数
|
||
///
|
||
/// # Arguments
|
||
///
|
||
/// * `count` - 当前活跃任务数
|
||
pub fn set_active_tasks(count: u64) {
|
||
gauge!(AGENT_ACTIVE_TASKS).set(count as f64);
|
||
}
|
||
|
||
/// 增加活跃任务数
|
||
pub fn inc_active_tasks() {
|
||
gauge!(AGENT_ACTIVE_TASKS).increment(1.0);
|
||
}
|
||
|
||
/// 减少活跃任务数
|
||
pub fn dec_active_tasks() {
|
||
gauge!(AGENT_ACTIVE_TASKS).decrement(1.0);
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
// 注意:这些测试需要先初始化 metrics recorder
|
||
// 在实际测试中,可能需要使用 mock recorder
|
||
|
||
#[test]
|
||
fn test_metric_names() {
|
||
assert_eq!(HTTP_REQUESTS_TOTAL, "http_requests_total");
|
||
assert_eq!(GRPC_REQUESTS_TOTAL, "grpc_requests_total");
|
||
assert_eq!(AGENT_ACTIVE_TASKS, "agent_active_tasks");
|
||
}
|
||
}
|