use dragonfly_api::common::v2::{Range, TrafficType};
use dragonfly_client_config::{
dfdaemon::Config, BUILD_PLATFORM, CARGO_PKG_VERSION, GIT_COMMIT_DATE, GIT_COMMIT_SHORT_HASH,
};
use dragonfly_client_util::shutdown;
use lazy_static::lazy_static;
use prometheus::{
exponential_buckets, gather, Encoder, HistogramOpts, HistogramVec, IntCounterVec, IntGaugeVec,
Opts, Registry, TextEncoder,
};
use std::net::SocketAddr;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::mpsc;
use tracing::{error, info, instrument, warn};
use warp::{Filter, Rejection, Reply};
const DOWNLOAD_TASK_LEVEL1_DURATION_THRESHOLD: Duration = Duration::from_millis(500);
const UPLOAD_TASK_LEVEL1_DURATION_THRESHOLD: Duration = Duration::from_millis(500);
lazy_static! {
pub static ref REGISTRY: Registry = Registry::new();
pub static ref VERSION_GAUGE: IntGaugeVec =
IntGaugeVec::new(
Opts::new("version", "Version info of the service.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["git_version", "git_commit", "platform", "build_time"]
).expect("metric can be created");
pub static ref UPLOAD_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("upload_task_total", "Counter of the number of the upload task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app"]
).expect("metric can be created");
pub static ref UPLOAD_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("upload_task_failure_total", "Counter of the number of failed of the upload task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app"]
).expect("metric can be created");
pub static ref CONCURRENT_UPLOAD_TASK_GAUGE: IntGaugeVec =
IntGaugeVec::new(
Opts::new("concurrent_upload_task_total", "Gauge of the number of concurrent of the upload task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app"]
).expect("metric can be created");
pub static ref UPLOAD_TASK_DURATION: HistogramVec =
HistogramVec::new(
HistogramOpts::new("upload_task_duration_milliseconds", "Histogram of the upload task duration.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME).buckets(exponential_buckets(1.0, 2.0, 24).unwrap()),
&["task_type", "task_size_level"]
).expect("metric can be created");
pub static ref DOWNLOAD_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("download_task_total", "Counter of the number of the download task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app", "priority"]
).expect("metric can be created");
pub static ref DOWNLOAD_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("download_task_failure_total", "Counter of the number of failed of the download task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app", "priority"]
).expect("metric can be created");
pub static ref PREFETCH_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("prefetch_task_total", "Counter of the number of the prefetch task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app", "priority"]
).expect("metric can be created");
pub static ref PREFETCH_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("prefetch_task_failure_total", "Counter of the number of failed of the prefetch task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app", "priority"]
).expect("metric can be created");
pub static ref CONCURRENT_DOWNLOAD_TASK_GAUGE: IntGaugeVec =
IntGaugeVec::new(
Opts::new("concurrent_download_task_total", "Gauge of the number of concurrent of the download task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type", "tag", "app", "priority"]
).expect("metric can be created");
pub static ref CONCURRENT_UPLOAD_PIECE_GAUGE: IntGaugeVec =
IntGaugeVec::new(
Opts::new("concurrent_upload_piece_total", "Gauge of the number of concurrent of the upload piece.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref DOWNLOAD_TRAFFIC: IntCounterVec =
IntCounterVec::new(
Opts::new("download_traffic", "Counter of the number of the download traffic.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref UPLOAD_TRAFFIC: IntCounterVec =
IntCounterVec::new(
Opts::new("upload_traffic", "Counter of the number of the upload traffic.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref DOWNLOAD_TASK_DURATION: HistogramVec =
HistogramVec::new(
HistogramOpts::new("download_task_duration_milliseconds", "Histogram of the download task duration.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME).buckets(exponential_buckets(1.0, 2.0, 24).unwrap()),
&["task_type", "task_size_level"]
).expect("metric can be created");
pub static ref BACKEND_REQUEST_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("backend_request_total", "Counter of the number of the backend request.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["scheme", "method"]
).expect("metric can be created");
pub static ref BACKEND_REQUEST_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("backend_request_failure_total", "Counter of the number of failed of the backend request.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["scheme", "method"]
).expect("metric can be created");
pub static ref BACKEND_REQUEST_DURATION: HistogramVec =
HistogramVec::new(
HistogramOpts::new("backend_request_duration_milliseconds", "Histogram of the backend request duration.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME).buckets(exponential_buckets(1.0, 2.0, 24).unwrap()),
&["scheme", "method"]
).expect("metric can be created");
pub static ref PROXY_REQUEST_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("proxy_request_total", "Counter of the number of the proxy request.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref PROXY_REQUEST_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("proxy_request_failure_total", "Counter of the number of failed of the proxy request.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref PROXY_REQUEST_VIA_DFDAEMON_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("proxy_request_via_dfdaemon_total", "Counter of the number of the proxy request via dfdaemon.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref UPDATE_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("update_task_total", "Counter of the number of the update task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref UPDATE_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("update_task_failure_total", "Counter of the number of failed of the update task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref STAT_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("stat_task_total", "Counter of the number of the stat task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref STAT_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("stat_task_failure_total", "Counter of the number of failed of the stat task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref STAT_LOCAL_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("stat_local_task_total", "Counter of the number of the stat local task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref STAT_LOCAL_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("stat_local_task_failure_total", "Counter of the number of failed of the stat local task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref LIST_TASK_ENTRIES_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("list_task_entries_total", "Counter of the number of the list task entries.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref LIST_TASK_ENTRIES_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("list_task_entries_failure_total", "Counter of the number of failed of the list task entries.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref DELETE_TASK_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("delete_task_total", "Counter of the number of the delete task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref DELETE_TASK_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("delete_task_failure_total", "Counter of the number of failed of the delete task.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&["type"]
).expect("metric can be created");
pub static ref DELETE_HOST_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("delete_host_total", "Counter of the number of the delete host.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref DELETE_HOST_FAILURE_COUNT: IntCounterVec =
IntCounterVec::new(
Opts::new("delete_host_failure_total", "Counter of the number of failed of the delete host.").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref DISK_SPACE: IntGaugeVec =
IntGaugeVec::new(
Opts::new("disk_space_total", "Gauge of the disk space in bytes").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
pub static ref DISK_USAGE_SPACE: IntGaugeVec =
IntGaugeVec::new(
Opts::new("disk_usage_space_total", "Gauge of the disk usage space in bytes").namespace(dragonfly_client_config::SERVICE_NAME).subsystem(dragonfly_client_config::NAME),
&[]
).expect("metric can be created");
}
fn register_custom_metrics() {
REGISTRY
.register(Box::new(VERSION_GAUGE.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DOWNLOAD_TASK_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DOWNLOAD_TASK_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(PREFETCH_TASK_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(PREFETCH_TASK_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(CONCURRENT_DOWNLOAD_TASK_GAUGE.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(CONCURRENT_UPLOAD_PIECE_GAUGE.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DOWNLOAD_TRAFFIC.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(UPLOAD_TRAFFIC.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DOWNLOAD_TASK_DURATION.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(BACKEND_REQUEST_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(BACKEND_REQUEST_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(BACKEND_REQUEST_DURATION.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(PROXY_REQUEST_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(PROXY_REQUEST_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(PROXY_REQUEST_VIA_DFDAEMON_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(UPDATE_TASK_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(UPDATE_TASK_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(STAT_TASK_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(STAT_TASK_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(LIST_TASK_ENTRIES_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(LIST_TASK_ENTRIES_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DELETE_TASK_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DELETE_TASK_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DELETE_HOST_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DELETE_HOST_FAILURE_COUNT.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DISK_SPACE.clone()))
.expect("metric can be registered");
REGISTRY
.register(Box::new(DISK_USAGE_SPACE.clone()))
.expect("metric can be registered");
}
fn reset_custom_metrics() {
VERSION_GAUGE.reset();
DOWNLOAD_TASK_COUNT.reset();
DOWNLOAD_TASK_FAILURE_COUNT.reset();
PREFETCH_TASK_COUNT.reset();
PREFETCH_TASK_FAILURE_COUNT.reset();
CONCURRENT_DOWNLOAD_TASK_GAUGE.reset();
CONCURRENT_UPLOAD_PIECE_GAUGE.reset();
DOWNLOAD_TRAFFIC.reset();
UPLOAD_TRAFFIC.reset();
DOWNLOAD_TASK_DURATION.reset();
BACKEND_REQUEST_COUNT.reset();
BACKEND_REQUEST_FAILURE_COUNT.reset();
BACKEND_REQUEST_DURATION.reset();
PROXY_REQUEST_COUNT.reset();
PROXY_REQUEST_FAILURE_COUNT.reset();
PROXY_REQUEST_VIA_DFDAEMON_COUNT.reset();
UPDATE_TASK_COUNT.reset();
UPDATE_TASK_FAILURE_COUNT.reset();
STAT_TASK_COUNT.reset();
STAT_TASK_FAILURE_COUNT.reset();
LIST_TASK_ENTRIES_COUNT.reset();
LIST_TASK_ENTRIES_FAILURE_COUNT.reset();
DELETE_TASK_COUNT.reset();
DELETE_TASK_FAILURE_COUNT.reset();
DELETE_HOST_COUNT.reset();
DELETE_HOST_FAILURE_COUNT.reset();
DISK_SPACE.reset();
DISK_USAGE_SPACE.reset();
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TaskSize {
Level0,
Level1,
Level2,
Level3,
Level4,
Level5,
Level6,
Level7,
Level8,
Level9,
Level10,
Level11,
Level12,
Level13,
Level14,
Level15,
Level16,
Level17,
Level18,
Level19,
Level20,
}
impl std::fmt::Display for TaskSize {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
TaskSize::Level0 => write!(f, "0"),
TaskSize::Level1 => write!(f, "1"),
TaskSize::Level2 => write!(f, "2"),
TaskSize::Level3 => write!(f, "3"),
TaskSize::Level4 => write!(f, "4"),
TaskSize::Level5 => write!(f, "5"),
TaskSize::Level6 => write!(f, "6"),
TaskSize::Level7 => write!(f, "7"),
TaskSize::Level8 => write!(f, "8"),
TaskSize::Level9 => write!(f, "9"),
TaskSize::Level10 => write!(f, "10"),
TaskSize::Level11 => write!(f, "11"),
TaskSize::Level12 => write!(f, "12"),
TaskSize::Level13 => write!(f, "13"),
TaskSize::Level14 => write!(f, "14"),
TaskSize::Level15 => write!(f, "15"),
TaskSize::Level16 => write!(f, "16"),
TaskSize::Level17 => write!(f, "17"),
TaskSize::Level18 => write!(f, "18"),
TaskSize::Level19 => write!(f, "19"),
TaskSize::Level20 => write!(f, "20"),
}
}
}
impl TaskSize {
pub fn calculate_size_level(size: u64) -> Self {
match size {
0 => TaskSize::Level0,
size if size < 1024 * 1024 => TaskSize::Level1,
size if size < 4 * 1024 * 1024 => TaskSize::Level2,
size if size < 8 * 1024 * 1024 => TaskSize::Level3,
size if size < 16 * 1024 * 1024 => TaskSize::Level4,
size if size < 32 * 1024 * 1024 => TaskSize::Level5,
size if size < 64 * 1024 * 1024 => TaskSize::Level6,
size if size < 128 * 1024 * 1024 => TaskSize::Level7,
size if size < 256 * 1024 * 1024 => TaskSize::Level8,
size if size < 512 * 1024 * 1024 => TaskSize::Level9,
size if size < 1024 * 1024 * 1024 => TaskSize::Level10,
size if size < 4 * 1024 * 1024 * 1024 => TaskSize::Level11,
size if size < 8 * 1024 * 1024 * 1024 => TaskSize::Level12,
size if size < 16 * 1024 * 1024 * 1024 => TaskSize::Level13,
size if size < 32 * 1024 * 1024 * 1024 => TaskSize::Level14,
size if size < 64 * 1024 * 1024 * 1024 => TaskSize::Level15,
size if size < 128 * 1024 * 1024 * 1024 => TaskSize::Level16,
size if size < 256 * 1024 * 1024 * 1024 => TaskSize::Level17,
size if size < 512 * 1024 * 1024 * 1024 => TaskSize::Level18,
size if size < 1024 * 1024 * 1024 * 1024 => TaskSize::Level19,
_ => TaskSize::Level20,
}
}
}
pub fn collect_upload_task_started_metrics(typ: i32, tag: &str, app: &str) {
let typ = typ.to_string();
UPLOAD_TASK_COUNT.with_label_values(&[&typ, tag, app]).inc();
CONCURRENT_UPLOAD_TASK_GAUGE
.with_label_values(&[&typ, tag, app])
.inc();
}
pub fn collect_upload_task_finished_metrics(
typ: i32,
tag: &str,
app: &str,
content_length: u64,
cost: Duration,
) {
let task_size = TaskSize::calculate_size_level(content_length);
if task_size == TaskSize::Level1 && cost > UPLOAD_TASK_LEVEL1_DURATION_THRESHOLD {
warn!(
"upload task, cost: {:?}, size: {} bytes",
cost, content_length,
);
}
let typ = typ.to_string();
let task_size = task_size.to_string();
UPLOAD_TASK_DURATION
.with_label_values(&[&typ, &task_size])
.observe(cost.as_millis() as f64);
CONCURRENT_UPLOAD_TASK_GAUGE
.with_label_values(&[&typ, tag, app])
.dec();
}
pub fn collect_upload_task_failure_metrics(typ: i32, tag: &str, app: &str) {
let typ = typ.to_string();
UPLOAD_TASK_FAILURE_COUNT
.with_label_values(&[&typ, tag, app])
.inc();
CONCURRENT_UPLOAD_TASK_GAUGE
.with_label_values(&[&typ, tag, app])
.dec();
}
pub fn collect_download_task_started_metrics(typ: i32, tag: &str, app: &str, priority: &str) {
let typ = typ.to_string();
DOWNLOAD_TASK_COUNT
.with_label_values(&[&typ, tag, app, priority])
.inc();
CONCURRENT_DOWNLOAD_TASK_GAUGE
.with_label_values(&[&typ, tag, app, priority])
.inc();
}
pub fn collect_download_task_finished_metrics(
typ: i32,
tag: &str,
app: &str,
priority: &str,
content_length: u64,
range: Option<Range>,
cost: Duration,
) {
let size = match range {
Some(range) => range.length,
None => content_length,
};
let task_size = TaskSize::calculate_size_level(size);
if task_size == TaskSize::Level1 && cost > DOWNLOAD_TASK_LEVEL1_DURATION_THRESHOLD {
warn!("download task, cost: {:?}, size: {} bytes", cost, size,);
}
let typ = typ.to_string();
let task_size = task_size.to_string();
DOWNLOAD_TASK_DURATION
.with_label_values(&[&typ, &task_size])
.observe(cost.as_millis() as f64);
CONCURRENT_DOWNLOAD_TASK_GAUGE
.with_label_values(&[&typ, tag, app, priority])
.dec();
}
pub fn collect_download_task_failure_metrics(typ: i32, tag: &str, app: &str, priority: &str) {
let typ = typ.to_string();
DOWNLOAD_TASK_FAILURE_COUNT
.with_label_values(&[&typ, tag, app, priority])
.inc();
CONCURRENT_DOWNLOAD_TASK_GAUGE
.with_label_values(&[&typ, tag, app, priority])
.dec();
}
pub fn collect_prefetch_task_started_metrics(typ: i32, tag: &str, app: &str, priority: &str) {
PREFETCH_TASK_COUNT
.with_label_values(&[typ.to_string().as_str(), tag, app, priority])
.inc();
}
pub fn collect_prefetch_task_failure_metrics(typ: i32, tag: &str, app: &str, priority: &str) {
PREFETCH_TASK_FAILURE_COUNT
.with_label_values(&[typ.to_string().as_str(), tag, app, priority])
.inc();
}
pub fn collect_download_piece_traffic_metrics(typ: &TrafficType, length: u64) {
DOWNLOAD_TRAFFIC
.with_label_values(&[typ.as_str_name()])
.inc_by(length);
}
pub fn collect_upload_piece_started_metrics() {
CONCURRENT_UPLOAD_PIECE_GAUGE.with_label_values(&[]).inc();
}
pub fn collect_upload_piece_finished_metrics() {
CONCURRENT_UPLOAD_PIECE_GAUGE.with_label_values(&[]).dec();
}
pub fn collect_upload_piece_traffic_metrics(length: u64) {
UPLOAD_TRAFFIC.with_label_values(&[]).inc_by(length);
}
pub fn collect_upload_piece_failure_metrics() {
CONCURRENT_UPLOAD_PIECE_GAUGE.with_label_values(&[]).dec();
}
pub fn collect_backend_request_started_metrics(scheme: &str, method: &str) {
BACKEND_REQUEST_COUNT
.with_label_values(&[scheme, method])
.inc();
}
pub fn collect_backend_request_failure_metrics(scheme: &str, method: &str) {
BACKEND_REQUEST_FAILURE_COUNT
.with_label_values(&[scheme, method])
.inc();
}
pub fn collect_backend_request_finished_metrics(scheme: &str, method: &str, cost: Duration) {
BACKEND_REQUEST_DURATION
.with_label_values(&[scheme, method])
.observe(cost.as_millis() as f64);
}
pub fn collect_proxy_request_started_metrics() {
PROXY_REQUEST_COUNT.with_label_values(&[]).inc();
}
pub fn collect_proxy_request_failure_metrics() {
PROXY_REQUEST_FAILURE_COUNT.with_label_values(&[]).inc();
}
pub fn collect_proxy_request_via_dfdaemon_metrics() {
PROXY_REQUEST_VIA_DFDAEMON_COUNT
.with_label_values(&[])
.inc();
}
pub fn collect_update_task_started_metrics(typ: i32) {
UPDATE_TASK_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_update_task_failure_metrics(typ: i32) {
UPDATE_TASK_FAILURE_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_stat_task_started_metrics(typ: i32) {
STAT_TASK_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_stat_task_failure_metrics(typ: i32) {
STAT_TASK_FAILURE_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_stat_local_task_started_metrics(typ: i32) {
STAT_LOCAL_TASK_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_stat_local_task_failure_metrics(typ: i32) {
STAT_LOCAL_TASK_FAILURE_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_list_task_entries_started_metrics(typ: i32) {
LIST_TASK_ENTRIES_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_list_task_entries_failure_metrics(typ: i32) {
LIST_TASK_ENTRIES_FAILURE_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_delete_task_started_metrics(typ: i32) {
DELETE_TASK_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_delete_task_failure_metrics(typ: i32) {
DELETE_TASK_FAILURE_COUNT
.with_label_values(&[typ.to_string().as_str()])
.inc();
}
pub fn collect_delete_host_started_metrics() {
DELETE_HOST_COUNT.with_label_values(&[]).inc();
}
pub fn collect_delete_host_failure_metrics() {
DELETE_HOST_FAILURE_COUNT.with_label_values(&[]).inc();
}
pub fn collect_disk_metrics(path: &Path) {
let stats = match fs2::statvfs(path) {
Ok(stats) => stats,
Err(err) => {
error!("failed to get disk space: {}", err);
return;
}
};
let total_space = stats.total_space();
let available_space = stats.available_space();
let usage_space = total_space - available_space;
DISK_SPACE.with_label_values(&[]).set(total_space as i64);
DISK_USAGE_SPACE
.with_label_values(&[])
.set(usage_space as i64);
}
#[derive(Debug)]
pub struct Metrics {
config: Arc<Config>,
shutdown: shutdown::Shutdown,
_shutdown_complete: mpsc::UnboundedSender<()>,
}
impl Metrics {
pub fn new(
config: Arc<Config>,
shutdown: shutdown::Shutdown,
shutdown_complete_tx: mpsc::UnboundedSender<()>,
) -> Self {
Self {
config,
shutdown,
_shutdown_complete: shutdown_complete_tx,
}
}
pub async fn run(&self) {
let mut shutdown = self.shutdown.clone();
register_custom_metrics();
VERSION_GAUGE
.get_metric_with_label_values(&[
CARGO_PKG_VERSION,
GIT_COMMIT_SHORT_HASH,
BUILD_PLATFORM,
GIT_COMMIT_DATE,
])
.unwrap()
.set(1);
let config = self.config.clone();
let addr = SocketAddr::new(
self.config.metrics.server.ip.unwrap(),
self.config.metrics.server.port,
);
let get_metrics_route = warp::path!("metrics")
.and(warp::get())
.and(warp::path::end())
.and_then(move || Self::get_metrics_handler(config.clone()));
let delete_metrics_route = warp::path!("metrics")
.and(warp::delete())
.and(warp::path::end())
.and_then(Self::delete_metrics_handler);
let metrics_routes = get_metrics_route.or(delete_metrics_route);
info!("metrics server listening on {}", addr);
tokio::select! {
_ = warp::serve(metrics_routes).run(addr) => {
info!("metrics server ended");
}
_ = shutdown.recv() => {
info!("metrics server shutting down");
}
}
}
#[instrument(skip_all)]
async fn get_metrics_handler(config: Arc<Config>) -> Result<impl Reply, Rejection> {
collect_disk_metrics(config.storage.dir.as_path());
let encoder = TextEncoder::new();
let mut buf = Vec::new();
if let Err(err) = encoder.encode(®ISTRY.gather(), &mut buf) {
error!("could not encode custom metrics: {}", err);
};
let mut res = match String::from_utf8(buf.clone()) {
Ok(v) => v,
Err(err) => {
error!("custom metrics could not be from_utf8'd: {}", err);
String::default()
}
};
buf.clear();
let mut buf = Vec::new();
if let Err(err) = encoder.encode(&gather(), &mut buf) {
error!("could not encode prometheus metrics: {}", err);
};
let res_custom = match String::from_utf8(buf.clone()) {
Ok(v) => v,
Err(err) => {
error!("prometheus metrics could not be from_utf8'd: {}", err);
String::default()
}
};
buf.clear();
res.push_str(&res_custom);
Ok(res)
}
#[instrument(skip_all)]
async fn delete_metrics_handler() -> Result<impl Reply, Rejection> {
reset_custom_metrics();
Ok(Vec::new())
}
}