From cdd285dec8bb469f4f4b459db3a0391793db0362 Mon Sep 17 00:00:00 2001 From: houseme Date: Tue, 13 May 2025 09:17:52 +0800 Subject: [PATCH] add metric --- Cargo.lock | 2 +- README_ZH.md | 2 - crates/event-notifier/Cargo.toml | 1 - crates/obs/Cargo.toml | 1 + crates/obs/src/lib.rs | 1 + crates/obs/src/metrics/entry/description.rs | 12 + crates/obs/src/metrics/entry/descriptor.rs | 44 +++ crates/obs/src/metrics/entry/metric_name.rs | 321 ++++++++++++++++++++ crates/obs/src/metrics/entry/metric_type.rs | 28 ++ crates/obs/src/metrics/entry/mod.rs | 32 ++ crates/obs/src/metrics/entry/namespace.rs | 25 ++ crates/obs/src/metrics/entry/subsystem.rs | 79 +++++ crates/obs/src/metrics/mod.rs | 10 + crates/obs/src/metrics/request.rs | 109 +++++++ rustfs/src/admin/mod.rs | 4 +- rustfs/src/admin/rpc.rs | 2 +- 16 files changed, 666 insertions(+), 7 deletions(-) create mode 100644 crates/obs/src/metrics/entry/description.rs create mode 100644 crates/obs/src/metrics/entry/descriptor.rs create mode 100644 crates/obs/src/metrics/entry/metric_name.rs create mode 100644 crates/obs/src/metrics/entry/metric_type.rs create mode 100644 crates/obs/src/metrics/entry/mod.rs create mode 100644 crates/obs/src/metrics/entry/namespace.rs create mode 100644 crates/obs/src/metrics/entry/subsystem.rs create mode 100644 crates/obs/src/metrics/mod.rs create mode 100644 crates/obs/src/metrics/request.rs diff --git a/Cargo.lock b/Cargo.lock index fa09fb754..9a073fe0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7347,7 +7347,6 @@ dependencies = [ "axum", "config", "dotenvy", - "http", "rdkafka", "reqwest", "rumqttc", @@ -7391,6 +7390,7 @@ dependencies = [ "async-trait", "chrono", "config", + "lazy_static", "local-ip-address", "nvml-wrapper", "opentelemetry", diff --git a/README_ZH.md b/README_ZH.md index b0fd4816a..3bdf32999 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -113,5 +113,3 @@ export RUSTFS_OBS_CONFIG="./deploy/config/obs.toml" | use_stdout | 是否输出到控制台 | true/false | | logger_level | 日志级别 | info | | local_logging_enable | 控制台是否答应日志 | true/false | - -``` \ No newline at end of file diff --git a/crates/event-notifier/Cargo.toml b/crates/event-notifier/Cargo.toml index 8d9acd9a0..3d46c72ee 100644 --- a/crates/event-notifier/Cargo.toml +++ b/crates/event-notifier/Cargo.toml @@ -35,7 +35,6 @@ rdkafka = { workspace = true, features = ["tokio"], optional = true } [dev-dependencies] tokio = { workspace = true, features = ["test-util"] } tracing-subscriber = { workspace = true } -http = { workspace = true } axum = { workspace = true } dotenvy = "0.15.7" diff --git a/crates/obs/Cargo.toml b/crates/obs/Cargo.toml index 12c9831ec..77b891747 100644 --- a/crates/obs/Cargo.toml +++ b/crates/obs/Cargo.toml @@ -21,6 +21,7 @@ rustfs-config = { workspace = true } async-trait = { workspace = true } chrono = { workspace = true } config = { workspace = true } +lazy_static = { workspace = true } local-ip-address = { workspace = true } nvml-wrapper = { workspace = true, optional = true } opentelemetry = { workspace = true } diff --git a/crates/obs/src/lib.rs b/crates/obs/src/lib.rs index 6a8f6219a..a355e3578 100644 --- a/crates/obs/src/lib.rs +++ b/crates/obs/src/lib.rs @@ -32,6 +32,7 @@ mod config; mod entry; mod global; mod logger; +mod metrics; mod sinks; mod system; mod telemetry; diff --git a/crates/obs/src/metrics/entry/description.rs b/crates/obs/src/metrics/entry/description.rs new file mode 100644 index 000000000..c7d1becff --- /dev/null +++ b/crates/obs/src/metrics/entry/description.rs @@ -0,0 +1,12 @@ +use crate::metrics::{MetricName, MetricNamespace, MetricSubsystem, MetricType}; + +/// The metric description describes the metric +/// It contains the namespace, subsystem, name, help text, and type of the metric +#[derive(Debug, Clone)] +pub struct MetricDescription { + pub namespace: MetricNamespace, + pub subsystem: MetricSubsystem, + pub name: MetricName, + pub help: String, + pub metric_type: MetricType, +} diff --git a/crates/obs/src/metrics/entry/descriptor.rs b/crates/obs/src/metrics/entry/descriptor.rs new file mode 100644 index 000000000..808c0e37a --- /dev/null +++ b/crates/obs/src/metrics/entry/descriptor.rs @@ -0,0 +1,44 @@ +use crate::metrics::{MetricName, MetricType}; +use std::collections::HashSet; + +/// MetricDescriptor - Indicates the metric descriptor +#[derive(Debug, Clone)] +pub struct MetricDescriptor { + pub name: MetricName, + pub metric_type: MetricType, + pub help: String, + pub variable_labels: Vec, + + // internal values for management: + label_set: Option>, +} + +impl MetricDescriptor { + /// Create a new metric descriptor + pub fn new(name: MetricName, metric_type: MetricType, help: String, variable_labels: Vec) -> Self { + Self { + name, + metric_type, + help, + variable_labels, + label_set: None, + } + } + + /// Check whether the label is in the label set + pub fn has_label(&mut self, label: &str) -> bool { + self.get_label_set().contains(label) + } + + /// Gets a collection of tags, and creates if it doesn't exist + pub fn get_label_set(&mut self) -> &HashSet { + if self.label_set.is_none() { + let mut set = HashSet::with_capacity(self.variable_labels.len()); + for label in &self.variable_labels { + set.insert(label.clone()); + } + self.label_set = Some(set); + } + self.label_set.as_ref().unwrap() + } +} diff --git a/crates/obs/src/metrics/entry/metric_name.rs b/crates/obs/src/metrics/entry/metric_name.rs new file mode 100644 index 000000000..842d707c9 --- /dev/null +++ b/crates/obs/src/metrics/entry/metric_name.rs @@ -0,0 +1,321 @@ +/// The metric name is the individual name of the metric +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MetricName { + // 通用指标名称 + AuthTotal, + CanceledTotal, + ErrorsTotal, + HeaderTotal, + HealTotal, + HitsTotal, + InflightTotal, + InvalidTotal, + LimitTotal, + MissedTotal, + WaitingTotal, + IncomingTotal, + ObjectTotal, + VersionTotal, + DeleteMarkerTotal, + OfflineTotal, + OnlineTotal, + OpenTotal, + ReadTotal, + TimestampTotal, + WriteTotal, + Total, + FreeInodes, + + // 失败统计指标 + LastMinFailedCount, + LastMinFailedBytes, + LastHourFailedCount, + LastHourFailedBytes, + TotalFailedCount, + TotalFailedBytes, + + // 工作线程指标 + CurrActiveWorkers, + AvgActiveWorkers, + MaxActiveWorkers, + RecentBacklogCount, + CurrInQueueCount, + CurrInQueueBytes, + ReceivedCount, + SentCount, + CurrTransferRate, + AvgTransferRate, + MaxTransferRate, + CredentialErrors, + + // 链接延迟指标 + CurrLinkLatency, + AvgLinkLatency, + MaxLinkLatency, + + // 链接状态指标 + LinkOnline, + LinkOfflineDuration, + LinkDowntimeTotalDuration, + + // 队列指标 + AvgInQueueCount, + AvgInQueueBytes, + MaxInQueueCount, + MaxInQueueBytes, + + // 代理请求指标 + ProxiedGetRequestsTotal, + ProxiedHeadRequestsTotal, + ProxiedPutTaggingRequestsTotal, + ProxiedGetTaggingRequestsTotal, + ProxiedDeleteTaggingRequestsTotal, + ProxiedGetRequestsFailures, + ProxiedHeadRequestsFailures, + ProxiedPutTaggingRequestFailures, + ProxiedGetTaggingRequestFailures, + ProxiedDeleteTaggingRequestFailures, + + // 字节相关指标 + FreeBytes, + ReadBytes, + RcharBytes, + ReceivedBytes, + LatencyMilliSec, + SentBytes, + TotalBytes, + UsedBytes, + WriteBytes, + WcharBytes, + + // 延迟指标 + LatencyMicroSec, + LatencyNanoSec, + + // 信息指标 + CommitInfo, + UsageInfo, + VersionInfo, + + // 分布指标 + SizeDistribution, + VersionDistribution, + TtfbDistribution, + TtlbDistribution, + + // 时间指标 + LastActivityTime, + StartTime, + UpTime, + Memory, + Vmemory, + Cpu, + + // 过期和转换指标 + ExpiryMissedTasks, + ExpiryMissedFreeVersions, + ExpiryMissedTierJournalTasks, + ExpiryNumWorkers, + TransitionMissedTasks, + TransitionedBytes, + TransitionedObjects, + TransitionedVersions, + + // Tier 请求指标 + TierRequestsSuccess, + TierRequestsFailure, + + // KMS 指标 + KmsOnline, + KmsRequestsSuccess, + KmsRequestsError, + KmsRequestsFail, + KmsUptime, + + // Webhook 指标 + WebhookOnline, + + // API 拒绝指标 + ApiRejectedAuthTotal, + ApiRejectedHeaderTotal, + ApiRejectedTimestampTotal, + ApiRejectedInvalidTotal, + + // API 请求指标 + ApiRequestsWaitingTotal, + ApiRequestsIncomingTotal, + ApiRequestsInFlightTotal, + ApiRequestsTotal, + ApiRequestsErrorsTotal, + ApiRequests5xxErrorsTotal, + ApiRequests4xxErrorsTotal, + ApiRequestsCanceledTotal, + + // API 分布指标 + ApiRequestsTTFBSecondsDistribution, + + // API 流量指标 + ApiTrafficSentBytes, + ApiTrafficRecvBytes, + + // 自定义指标 + Custom(String), +} + +impl MetricName { + pub fn as_str(&self) -> String { + match self { + Self::AuthTotal => "auth_total".to_string(), + Self::CanceledTotal => "canceled_total".to_string(), + Self::ErrorsTotal => "errors_total".to_string(), + Self::HeaderTotal => "header_total".to_string(), + Self::HealTotal => "heal_total".to_string(), + Self::HitsTotal => "hits_total".to_string(), + Self::InflightTotal => "inflight_total".to_string(), + Self::InvalidTotal => "invalid_total".to_string(), + Self::LimitTotal => "limit_total".to_string(), + Self::MissedTotal => "missed_total".to_string(), + Self::WaitingTotal => "waiting_total".to_string(), + Self::IncomingTotal => "incoming_total".to_string(), + Self::ObjectTotal => "object_total".to_string(), + Self::VersionTotal => "version_total".to_string(), + Self::DeleteMarkerTotal => "deletemarker_total".to_string(), + Self::OfflineTotal => "offline_total".to_string(), + Self::OnlineTotal => "online_total".to_string(), + Self::OpenTotal => "open_total".to_string(), + Self::ReadTotal => "read_total".to_string(), + Self::TimestampTotal => "timestamp_total".to_string(), + Self::WriteTotal => "write_total".to_string(), + Self::Total => "total".to_string(), + Self::FreeInodes => "free_inodes".to_string(), + + Self::LastMinFailedCount => "last_minute_failed_count".to_string(), + Self::LastMinFailedBytes => "last_minute_failed_bytes".to_string(), + Self::LastHourFailedCount => "last_hour_failed_count".to_string(), + Self::LastHourFailedBytes => "last_hour_failed_bytes".to_string(), + Self::TotalFailedCount => "total_failed_count".to_string(), + Self::TotalFailedBytes => "total_failed_bytes".to_string(), + + Self::CurrActiveWorkers => "current_active_workers".to_string(), + Self::AvgActiveWorkers => "average_active_workers".to_string(), + Self::MaxActiveWorkers => "max_active_workers".to_string(), + Self::RecentBacklogCount => "recent_backlog_count".to_string(), + Self::CurrInQueueCount => "last_minute_queued_count".to_string(), + Self::CurrInQueueBytes => "last_minute_queued_bytes".to_string(), + Self::ReceivedCount => "received_count".to_string(), + Self::SentCount => "sent_count".to_string(), + Self::CurrTransferRate => "current_transfer_rate".to_string(), + Self::AvgTransferRate => "average_transfer_rate".to_string(), + Self::MaxTransferRate => "max_transfer_rate".to_string(), + Self::CredentialErrors => "credential_errors".to_string(), + + Self::CurrLinkLatency => "current_link_latency_ms".to_string(), + Self::AvgLinkLatency => "average_link_latency_ms".to_string(), + Self::MaxLinkLatency => "max_link_latency_ms".to_string(), + + Self::LinkOnline => "link_online".to_string(), + Self::LinkOfflineDuration => "link_offline_duration_seconds".to_string(), + Self::LinkDowntimeTotalDuration => "link_downtime_duration_seconds".to_string(), + + Self::AvgInQueueCount => "average_queued_count".to_string(), + Self::AvgInQueueBytes => "average_queued_bytes".to_string(), + Self::MaxInQueueCount => "max_queued_count".to_string(), + Self::MaxInQueueBytes => "max_queued_bytes".to_string(), + + Self::ProxiedGetRequestsTotal => "proxied_get_requests_total".to_string(), + Self::ProxiedHeadRequestsTotal => "proxied_head_requests_total".to_string(), + Self::ProxiedPutTaggingRequestsTotal => "proxied_put_tagging_requests_total".to_string(), + Self::ProxiedGetTaggingRequestsTotal => "proxied_get_tagging_requests_total".to_string(), + Self::ProxiedDeleteTaggingRequestsTotal => "proxied_delete_tagging_requests_total".to_string(), + Self::ProxiedGetRequestsFailures => "proxied_get_requests_failures".to_string(), + Self::ProxiedHeadRequestsFailures => "proxied_head_requests_failures".to_string(), + Self::ProxiedPutTaggingRequestFailures => "proxied_put_tagging_requests_failures".to_string(), + Self::ProxiedGetTaggingRequestFailures => "proxied_get_tagging_requests_failures".to_string(), + Self::ProxiedDeleteTaggingRequestFailures => "proxied_delete_tagging_requests_failures".to_string(), + + Self::FreeBytes => "free_bytes".to_string(), + Self::ReadBytes => "read_bytes".to_string(), + Self::RcharBytes => "rchar_bytes".to_string(), + Self::ReceivedBytes => "received_bytes".to_string(), + Self::LatencyMilliSec => "latency_ms".to_string(), + Self::SentBytes => "sent_bytes".to_string(), + Self::TotalBytes => "total_bytes".to_string(), + Self::UsedBytes => "used_bytes".to_string(), + Self::WriteBytes => "write_bytes".to_string(), + Self::WcharBytes => "wchar_bytes".to_string(), + + Self::LatencyMicroSec => "latency_us".to_string(), + Self::LatencyNanoSec => "latency_ns".to_string(), + + Self::CommitInfo => "commit_info".to_string(), + Self::UsageInfo => "usage_info".to_string(), + Self::VersionInfo => "version_info".to_string(), + + Self::SizeDistribution => "size_distribution".to_string(), + Self::VersionDistribution => "version_distribution".to_string(), + Self::TtfbDistribution => "seconds_distribution".to_string(), + Self::TtlbDistribution => "ttlb_seconds_distribution".to_string(), + + Self::LastActivityTime => "last_activity_nano_seconds".to_string(), + Self::StartTime => "starttime_seconds".to_string(), + Self::UpTime => "uptime_seconds".to_string(), + Self::Memory => "resident_memory_bytes".to_string(), + Self::Vmemory => "virtual_memory_bytes".to_string(), + Self::Cpu => "cpu_total_seconds".to_string(), + + Self::ExpiryMissedTasks => "expiry_missed_tasks".to_string(), + Self::ExpiryMissedFreeVersions => "expiry_missed_freeversions".to_string(), + Self::ExpiryMissedTierJournalTasks => "expiry_missed_tierjournal_tasks".to_string(), + Self::ExpiryNumWorkers => "expiry_num_workers".to_string(), + Self::TransitionMissedTasks => "transition_missed_immediate_tasks".to_string(), + + Self::TransitionedBytes => "transitioned_bytes".to_string(), + Self::TransitionedObjects => "transitioned_objects".to_string(), + Self::TransitionedVersions => "transitioned_versions".to_string(), + + Self::TierRequestsSuccess => "requests_success".to_string(), + Self::TierRequestsFailure => "requests_failure".to_string(), + + Self::KmsOnline => "online".to_string(), + Self::KmsRequestsSuccess => "request_success".to_string(), + Self::KmsRequestsError => "request_error".to_string(), + Self::KmsRequestsFail => "request_failure".to_string(), + Self::KmsUptime => "uptime".to_string(), + + Self::WebhookOnline => "online".to_string(), + + Self::ApiRejectedAuthTotal => "rejected_auth_total".to_string(), + Self::ApiRejectedHeaderTotal => "rejected_header_total".to_string(), + Self::ApiRejectedTimestampTotal => "rejected_timestamp_total".to_string(), + Self::ApiRejectedInvalidTotal => "rejected_invalid_total".to_string(), + + Self::ApiRequestsWaitingTotal => "waiting_total".to_string(), + Self::ApiRequestsIncomingTotal => "incoming_total".to_string(), + Self::ApiRequestsInFlightTotal => "inflight_total".to_string(), + Self::ApiRequestsTotal => "total".to_string(), + Self::ApiRequestsErrorsTotal => "errors_total".to_string(), + Self::ApiRequests5xxErrorsTotal => "5xx_errors_total".to_string(), + Self::ApiRequests4xxErrorsTotal => "4xx_errors_total".to_string(), + Self::ApiRequestsCanceledTotal => "canceled_total".to_string(), + + Self::ApiRequestsTTFBSecondsDistribution => "ttfb_seconds_distribution".to_string(), + + Self::ApiTrafficSentBytes => "traffic_sent_bytes".to_string(), + Self::ApiTrafficRecvBytes => "traffic_received_bytes".to_string(), + + Self::Custom(name) => name.clone(), + } + } +} + +impl From for MetricName { + fn from(s: String) -> Self { + Self::Custom(s) + } +} + +impl From<&str> for MetricName { + fn from(s: &str) -> Self { + Self::Custom(s.to_string()) + } +} diff --git a/crates/obs/src/metrics/entry/metric_type.rs b/crates/obs/src/metrics/entry/metric_type.rs new file mode 100644 index 000000000..163cc9099 --- /dev/null +++ b/crates/obs/src/metrics/entry/metric_type.rs @@ -0,0 +1,28 @@ +/// MetricType - Indicates the type of indicator +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MetricType { + Counter, + Gauge, + Histogram, +} + +impl MetricType { + /// convert the metric type to a string representation + pub fn as_str(&self) -> &'static str { + match self { + Self::Counter => "counter", + Self::Gauge => "gauge", + Self::Histogram => "histogram", + } + } + + /// Convert the metric type to the Prometheus value type + /// In a Rust implementation, this might return the corresponding Prometheus Rust client type + pub fn to_prom(&self) -> &'static str { + match self { + Self::Counter => "counter_value", + Self::Gauge => "gauge_value", + Self::Histogram => "counter_value", // 直方图在 Prometheus 中仍使用 counter 值 + } + } +} diff --git a/crates/obs/src/metrics/entry/mod.rs b/crates/obs/src/metrics/entry/mod.rs new file mode 100644 index 000000000..440eb7f00 --- /dev/null +++ b/crates/obs/src/metrics/entry/mod.rs @@ -0,0 +1,32 @@ +use crate::metrics::{MetricDescriptor, MetricName, MetricType}; + +pub(crate) mod description; +pub(crate) mod descriptor; +pub(crate) mod metric_name; +pub(crate) mod metric_type; +pub(crate) mod namespace; +pub(crate) mod subsystem; + +/// Represents a range label constant +pub const RANGE_LABEL: &str = "range"; +pub const SERVER_NAME: &str = "server"; + +/// Create a new counter metric descriptor +pub fn new_counter_md(name: impl Into, help: impl Into, labels: &[&str]) -> MetricDescriptor { + MetricDescriptor::new( + name.into(), + MetricType::Counter, + help.into(), + labels.iter().map(|&s| s.to_string()).collect(), + ) +} + +/// Create a new gauge metric descriptor +pub fn new_gauge_md(name: impl Into, help: impl Into, labels: &[&str]) -> MetricDescriptor { + MetricDescriptor::new( + name.into(), + MetricType::Gauge, + help.into(), + labels.iter().map(|&s| s.to_string()).collect(), + ) +} diff --git a/crates/obs/src/metrics/entry/namespace.rs b/crates/obs/src/metrics/entry/namespace.rs new file mode 100644 index 000000000..85c487b4f --- /dev/null +++ b/crates/obs/src/metrics/entry/namespace.rs @@ -0,0 +1,25 @@ +/// The metric namespace is the top-level grouping created by the metric name +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MetricNamespace { + Bucket, + Cluster, + Heal, + InterNode, + Node, + RustFS, + S3, +} + +impl MetricNamespace { + pub fn as_str(&self) -> &'static str { + match self { + Self::Bucket => "rustfs_bucket", + Self::Cluster => "rustfs_cluster", + Self::Heal => "rustfs_heal", + Self::InterNode => "rustfs_inter_node", + Self::Node => "rustfs_node", + Self::RustFS => "rustfs", + Self::S3 => "rustfs_s3", + } + } +} diff --git a/crates/obs/src/metrics/entry/subsystem.rs b/crates/obs/src/metrics/entry/subsystem.rs new file mode 100644 index 000000000..91d3f9e3d --- /dev/null +++ b/crates/obs/src/metrics/entry/subsystem.rs @@ -0,0 +1,79 @@ +/// The metrics subsystem is a subgroup of metrics within a namespace +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MetricSubsystem { + Cache, + CapacityRaw, + CapacityUsable, + Drive, + Interface, + Memory, + CpuAvg, + StorageClass, + FileDescriptor, + GoRoutine, + Io, + Nodes, + Objects, + Bucket, + Process, + Replication, + Requests, + RequestsRejected, + Time, + Ttfb, + Traffic, + Software, + Syscall, + Usage, + Quota, + Ilm, + Tier, + Scanner, + Iam, + Kms, + Notify, + Lambda, + Audit, + Webhook, +} + +impl MetricSubsystem { + pub fn as_str(&self) -> &'static str { + match self { + Self::Cache => "cache", + Self::CapacityRaw => "capacity_raw", + Self::CapacityUsable => "capacity_usable", + Self::Drive => "drive", + Self::Interface => "if", + Self::Memory => "mem", + Self::CpuAvg => "cpu_avg", + Self::StorageClass => "storage_class", + Self::FileDescriptor => "file_descriptor", + Self::GoRoutine => "go_routine", + Self::Io => "io", + Self::Nodes => "nodes", + Self::Objects => "objects", + Self::Bucket => "bucket", + Self::Process => "process", + Self::Replication => "replication", + Self::Requests => "requests", + Self::RequestsRejected => "requests_rejected", + Self::Time => "time", + Self::Ttfb => "requests_ttfb", + Self::Traffic => "traffic", + Self::Software => "software", + Self::Syscall => "syscall", + Self::Usage => "usage", + Self::Quota => "quota", + Self::Ilm => "ilm", + Self::Tier => "tier", + Self::Scanner => "scanner", + Self::Iam => "iam", + Self::Kms => "kms", + Self::Notify => "notify", + Self::Lambda => "lambda", + Self::Audit => "audit", + Self::Webhook => "webhook", + } + } +} diff --git a/crates/obs/src/metrics/mod.rs b/crates/obs/src/metrics/mod.rs new file mode 100644 index 000000000..37d684a1e --- /dev/null +++ b/crates/obs/src/metrics/mod.rs @@ -0,0 +1,10 @@ +mod entry; +mod request; + +pub use entry::description::MetricDescription; +pub use entry::descriptor::MetricDescriptor; +pub use entry::metric_name::MetricName; +pub use entry::metric_type::MetricType; +pub use entry::namespace::MetricNamespace; +pub use entry::subsystem::MetricSubsystem; +pub use entry::{new_counter_md, new_gauge_md}; diff --git a/crates/obs/src/metrics/request.rs b/crates/obs/src/metrics/request.rs new file mode 100644 index 000000000..5b9d0f3b2 --- /dev/null +++ b/crates/obs/src/metrics/request.rs @@ -0,0 +1,109 @@ +use crate::metrics::{new_counter_md, new_gauge_md, MetricDescriptor, MetricName}; + +/// Predefined API metric descriptors +lazy_static::lazy_static! { + pub static ref API_REJECTED_AUTH_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRejectedAuthTotal.as_str(), + "Total number of requests rejected for auth failure", + &["type"] + ); + + pub static ref API_REJECTED_HEADER_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRejectedHeaderTotal.as_str(), + "Total number of requests rejected for invalid header", + &["type"] + ); + + pub static ref API_REJECTED_TIMESTAMP_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRejectedTimestampTotal.as_str(), + "Total number of requests rejected for invalid timestamp", + &["type"] + ); + + pub static ref API_REJECTED_INVALID_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRejectedInvalidTotal.as_str(), + "Total number of invalid requests", + &["type"] + ); + + pub static ref API_REQUESTS_WAITING_TOTAL_MD: MetricDescriptor = + new_gauge_md( + MetricName::ApiRequestsWaitingTotal.as_str(), + "Total number of requests in the waiting queue", + &["type"] + ); + + pub static ref API_REQUESTS_INCOMING_TOTAL_MD: MetricDescriptor = + new_gauge_md( + MetricName::ApiRequestsIncomingTotal.as_str(), + "Total number of incoming requests", + &["type"] + ); + + pub static ref API_REQUESTS_IN_FLIGHT_TOTAL_MD: MetricDescriptor = + new_gauge_md( + MetricName::ApiRequestsInFlightTotal.as_str(), + "Total number of requests currently in flight", + &["name", "type"] + ); + + pub static ref API_REQUESTS_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRequestsTotal.as_str(), + "Total number of requests", + &["name", "type"] + ); + + pub static ref API_REQUESTS_ERRORS_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRequestsErrorsTotal.as_str(), + "Total number of requests with (4xx and 5xx) errors", + &["name", "type"] + ); + + pub static ref API_REQUESTS_5XX_ERRORS_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRequests5xxErrorsTotal.as_str(), + "Total number of requests with 5xx errors", + &["name", "type"] + ); + + pub static ref API_REQUESTS_4XX_ERRORS_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRequests4xxErrorsTotal.as_str(), + "Total number of requests with 4xx errors", + &["name", "type"] + ); + + pub static ref API_REQUESTS_CANCELED_TOTAL_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRequestsCanceledTotal.as_str(), + "Total number of requests canceled by the client", + &["name", "type"] + ); + + pub static ref API_REQUESTS_TTFB_SECONDS_DISTRIBUTION_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiRequestsTTFBSecondsDistribution.as_str(), + "Distribution of time to first byte across API calls", + &["name", "type", "le"] + ); + + pub static ref API_TRAFFIC_SENT_BYTES_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiTrafficSentBytes.as_str(), + "Total number of bytes sent", + &["type"] + ); + + pub static ref API_TRAFFIC_RECV_BYTES_MD: MetricDescriptor = + new_counter_md( + MetricName::ApiTrafficRecvBytes.as_str(), + "Total number of bytes received", + &["type"] + ); +} diff --git a/rustfs/src/admin/mod.rs b/rustfs/src/admin/mod.rs index f0229f201..01021a99f 100644 --- a/rustfs/src/admin/mod.rs +++ b/rustfs/src/admin/mod.rs @@ -13,7 +13,7 @@ use handlers::{ use hyper::Method; use router::{AdminOperation, S3Router}; -use rpc::regist_rpc_route; +use rpc::register_rpc_route; use s3s::route::S3Route; const ADMIN_PREFIX: &str = "/rustfs/admin"; @@ -24,7 +24,7 @@ pub fn make_admin_route() -> Result { // 1 r.insert(Method::POST, "/", AdminOperation(&sts::AssumeRoleHandle {}))?; - regist_rpc_route(&mut r)?; + register_rpc_route(&mut r)?; register_user_route(&mut r)?; r.insert( diff --git a/rustfs/src/admin/rpc.rs b/rustfs/src/admin/rpc.rs index 5fc85da86..6fca3066f 100644 --- a/rustfs/src/admin/rpc.rs +++ b/rustfs/src/admin/rpc.rs @@ -22,7 +22,7 @@ use tokio_util::io::StreamReader; pub const RPC_PREFIX: &str = "/rustfs/rpc"; -pub fn regist_rpc_route(r: &mut S3Router) -> Result<()> { +pub fn register_rpc_route(r: &mut S3Router) -> Result<()> { r.insert( Method::GET, format!("{}{}", RPC_PREFIX, "/read_file_stream").as_str(),