This is an automated email from the ASF dual-hosted git repository. xuanwo pushed a commit to branch xuanwo/layers-metrics-split in repository https://gitbox.apache.org/repos/asf/opendal.git
commit 0fbb3e404c989f92b4f2ea27f309d77250dc2a05 Author: Xuanwo <[email protected]> AuthorDate: Mon Dec 8 20:58:45 2025 +0800 refactor: split metrics related crates to new crates Signed-off-by: Xuanwo <[email protected]> --- core/Cargo.lock | 64 ++++++++++++++- core/Cargo.toml | 19 +++-- core/core/Cargo.toml | 18 ----- core/core/src/layers/mod.rs | 33 -------- core/core/src/layers/observe/mod.rs | 93 ---------------------- core/core/src/raw/http_util/body.rs | 4 +- core/core/src/raw/http_util/client.rs | 2 +- core/layers/fastmetrics/Cargo.toml | 36 +++++++++ .../fastmetrics/src/lib.rs} | 16 ++-- core/layers/metrics/Cargo.toml | 36 +++++++++ .../metrics.rs => layers/metrics/src/lib.rs} | 8 +- core/layers/observe-metrics-common/Cargo.toml | 36 +++++++++ .../observe-metrics-common/src/lib.rs} | 62 ++++++++++++++- core/layers/otelmetrics/Cargo.toml | 36 +++++++++ .../otelmetrics/src/lib.rs} | 12 +-- core/layers/prometheus-client/Cargo.toml | 36 +++++++++ .../prometheus-client/src/lib.rs} | 12 +-- core/layers/prometheus/Cargo.toml | 36 +++++++++ .../prometheus.rs => layers/prometheus/src/lib.rs} | 20 ++--- core/src/lib.rs | 10 +++ 20 files changed, 393 insertions(+), 196 deletions(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index baa1b2579..0170d4537 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -5478,6 +5478,12 @@ dependencies = [ "opendal-layer-async-backtrace", "opendal-layer-await-tree", "opendal-layer-capability-check", + "opendal-layer-fastmetrics", + "opendal-layer-metrics", + "opendal-layer-observe-metrics-common", + "opendal-layer-otelmetrics", + "opendal-layer-prometheus", + "opendal-layer-prometheus-client", "opendal-service-aliyun-drive", "opendal-service-azblob", "opendal-service-azdls", @@ -5541,7 +5547,6 @@ dependencies = [ "divan", "dotenvy", "etcd-client", - "fastmetrics", "fastpool", "fastrace", "fastrace-jaeger", @@ -5562,7 +5567,6 @@ dependencies = [ "log", "md-5", "mea", - "metrics", "mime_guess", "mini-moka", "moka", @@ -5579,8 +5583,6 @@ dependencies = [ "persy", "pretty_assertions", "probe", - "prometheus 0.14.0", - "prometheus-client", "prost 0.13.5", "quick-xml", "rand 0.8.5", @@ -5676,6 +5678,60 @@ dependencies = [ "tokio", ] +[[package]] +name = "opendal-layer-fastmetrics" +version = "0.55.0" +dependencies = [ + "fastmetrics", + "opendal-core", + "opendal-layer-observe-metrics-common", +] + +[[package]] +name = "opendal-layer-metrics" +version = "0.55.0" +dependencies = [ + "metrics", + "opendal-core", + "opendal-layer-observe-metrics-common", +] + +[[package]] +name = "opendal-layer-observe-metrics-common" +version = "0.55.0" +dependencies = [ + "futures", + "http 1.4.0", + "opendal-core", +] + +[[package]] +name = "opendal-layer-otelmetrics" +version = "0.55.0" +dependencies = [ + "opendal-core", + "opendal-layer-observe-metrics-common", + "opentelemetry", +] + +[[package]] +name = "opendal-layer-prometheus" +version = "0.55.0" +dependencies = [ + "opendal-core", + "opendal-layer-observe-metrics-common", + "prometheus 0.14.0", +] + +[[package]] +name = "opendal-layer-prometheus-client" +version = "0.55.0" +dependencies = [ + "opendal-core", + "opendal-layer-observe-metrics-common", + "prometheus-client", +] + [[package]] name = "opendal-service-aliyun-drive" version = "0.55.0" diff --git a/core/Cargo.toml b/core/Cargo.toml index d087b0414..28b1c63db 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -27,8 +27,6 @@ members = [ "services/aliyun-drive", "services/*", "layers/*", - "layers/await-tree", - "layers/capability-check", ] [workspace.package] @@ -84,7 +82,6 @@ default = [ "reqwest-rustls-tls", "executors-tokio", "services-memory", - "layers-capability-check", ] executors-tokio = ["opendal-core/executors-tokio"] internal-path-cache = ["opendal-core/internal-path-cache"] @@ -94,14 +91,14 @@ layers-await-tree = ["dep:opendal-layer-await-tree"] layers-capability-check = ["dep:opendal-layer-capability-check"] layers-chaos = ["opendal-core/layers-chaos"] layers-dtrace = ["opendal-core/layers-dtrace"] -layers-fastmetrics = ["opendal-core/layers-fastmetrics"] +layers-fastmetrics = ["dep:opendal-layer-fastmetrics"] layers-fastrace = ["opendal-core/layers-fastrace"] -layers-metrics = ["opendal-core/layers-metrics"] +layers-metrics = ["dep:opendal-layer-metrics"] layers-mime-guess = ["opendal-core/layers-mime-guess"] -layers-otel-metrics = ["opendal-core/layers-otel-metrics"] +layers-otel-metrics = ["dep:opendal-layer-otelmetrics"] layers-otel-trace = ["opendal-core/layers-otel-trace"] -layers-prometheus = ["opendal-core/layers-prometheus"] -layers-prometheus-client = ["opendal-core/layers-prometheus-client"] +layers-prometheus = ["dep:opendal-layer-prometheus"] +layers-prometheus-client = ["dep:opendal-layer-prometheus-client"] layers-throttle = ["opendal-core/layers-throttle"] layers-tracing = ["opendal-core/layers-tracing"] reqwest-rustls-tls = ["opendal-core/reqwest-rustls-tls"] @@ -193,6 +190,12 @@ opendal-core = { path = "core", version = "0.55.0", default-features = false } opendal-layer-async-backtrace = { path = "layers/async-backtrace", version = "0.55.0", optional = true, default-features = false } opendal-layer-await-tree = { path = "layers/await-tree", version = "0.55.0", optional = true, default-features = false } opendal-layer-capability-check = { path = "layers/capability-check", version = "0.55.0", optional = true, default-features = false } +opendal-layer-observe-metrics-common = { path = "layers/observe-metrics-common", version = "0.55.0", optional = true, default-features = false } +opendal-layer-metrics = { path = "layers/metrics", version = "0.55.0", optional = true, default-features = false } +opendal-layer-otelmetrics = { path = "layers/otelmetrics", version = "0.55.0", optional = true, default-features = false } +opendal-layer-prometheus = { path = "layers/prometheus", version = "0.55.0", optional = true, default-features = false } +opendal-layer-prometheus-client = { path = "layers/prometheus-client", version = "0.55.0", optional = true, default-features = false } +opendal-layer-fastmetrics = { path = "layers/fastmetrics", version = "0.55.0", optional = true, default-features = false } opendal-service-aliyun-drive = { path = "services/aliyun-drive", version = "0.55.0", optional = true, default-features = false } opendal-service-azblob = { path = "services/azblob", version = "0.55.0", optional = true, default-features = false } opendal-service-azdls = { path = "services/azdls", version = "0.55.0", optional = true, default-features = false } diff --git a/core/core/Cargo.toml b/core/core/Cargo.toml index a268c0478..375ecde7c 100644 --- a/core/core/Cargo.toml +++ b/core/core/Cargo.toml @@ -72,22 +72,12 @@ executors-tokio = ["tokio/rt"] # Enable layers chaos support layers-chaos = ["dep:rand"] -# Enable layers metrics support -layers-metrics = ["dep:metrics"] # Enable layers mime_guess support layers-mime-guess = ["dep:mime_guess"] -# Enable layers prometheus support, with tikv/prometheus-rs crate -layers-prometheus = ["dep:prometheus"] -# Enable layers prometheus support, with prometheus-client crate -layers-prometheus-client = ["dep:prometheus-client"] -# Enable layers fastmetrics support. -layers-fastmetrics = ["dep:fastmetrics"] # Enable layers fastrace support. layers-fastrace = ["dep:fastrace"] # Enable layers tracing support. layers-tracing = ["dep:tracing"] -# Enable layers otelmetrics support. -layers-otel-metrics = ["dep:opentelemetry", "opentelemetry/metrics"] # Enable layers oteltrace support. layers-otel-trace = ["dep:opentelemetry", "opentelemetry/trace"] # Enable layers throttle support. @@ -325,20 +315,12 @@ web-sys = { version = "0.3.77", optional = true, features = [ # Layers # for layers-throttle governor = { version = "0.10.1", optional = true, features = ["std"] } -# for layers-metrics -metrics = { version = "0.24", optional = true } # for layers-mime-guess mime_guess = { version = "2.0.5", optional = true } # for layers-fastrace fastrace = { version = "0.7.14", optional = true } # for layers-opentelemetry opentelemetry = { version = "0.31.0", optional = true } -# for layers-prometheus -prometheus = { version = "0.14", features = ["process"], optional = true } -# for layers-prometheus-client -prometheus-client = { version = "0.24", optional = true } -# for fastmetrics -fastmetrics = { version = "0.4.1", optional = true } # for layers-tracing tracing = { version = "0.1", optional = true } # for layers-dtrace diff --git a/core/core/src/layers/mod.rs b/core/core/src/layers/mod.rs index 85cccd55b..4b1012ff6 100644 --- a/core/core/src/layers/mod.rs +++ b/core/core/src/layers/mod.rs @@ -47,37 +47,11 @@ mod chaos; #[cfg(feature = "layers-chaos")] pub use chaos::ChaosLayer; -#[cfg(feature = "layers-metrics")] -mod metrics; -#[cfg(feature = "layers-metrics")] -pub use self::metrics::MetricsLayer; - #[cfg(feature = "layers-mime-guess")] mod mime_guess; #[cfg(feature = "layers-mime-guess")] pub use self::mime_guess::MimeGuessLayer; -#[cfg(feature = "layers-prometheus")] -mod prometheus; -#[cfg(feature = "layers-prometheus")] -pub use self::prometheus::PrometheusLayer; -#[cfg(feature = "layers-prometheus")] -pub use self::prometheus::PrometheusLayerBuilder; - -#[cfg(feature = "layers-prometheus-client")] -mod prometheus_client; -#[cfg(feature = "layers-prometheus-client")] -pub use self::prometheus_client::PrometheusClientLayer; -#[cfg(feature = "layers-prometheus-client")] -pub use self::prometheus_client::PrometheusClientLayerBuilder; - -#[cfg(feature = "layers-fastmetrics")] -mod fastmetrics; -#[cfg(feature = "layers-fastmetrics")] -pub use self::fastmetrics::FastmetricsLayer; -#[cfg(feature = "layers-fastmetrics")] -pub use self::fastmetrics::FastmetricsLayerBuilder; - mod retry; pub use self::retry::RetryInterceptor; pub use self::retry::RetryLayer; @@ -96,11 +70,6 @@ mod fastrace; #[cfg(feature = "layers-fastrace")] pub use self::fastrace::FastraceLayer; -#[cfg(feature = "layers-otel-metrics")] -mod otelmetrics; -#[cfg(feature = "layers-otel-metrics")] -pub use self::otelmetrics::OtelMetricsLayer; - #[cfg(feature = "layers-otel-trace")] mod oteltrace; #[cfg(feature = "layers-otel-trace")] @@ -116,8 +85,6 @@ mod dtrace; #[cfg(all(target_os = "linux", feature = "layers-dtrace"))] pub use self::dtrace::DtraceLayer; -pub mod observe; - mod correctness_check; pub(crate) use correctness_check::CorrectnessCheckLayer; diff --git a/core/core/src/layers/observe/mod.rs b/core/core/src/layers/observe/mod.rs deleted file mode 100644 index 7837e1e33..000000000 --- a/core/core/src/layers/observe/mod.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -//! OpenDAL Observability -//! -//! This module offers essential components to facilitate the implementation of observability in OpenDAL. -//! -//! # OpenDAL Metrics Reference -//! -//! This document describes all metrics exposed by OpenDAL. -//! -//! ## Operation Metrics -//! -//! These metrics track operations at the storage abstraction level. -//! -//! | Metric Name | Type | Description | Labels | -//! |----------------------------------|-----------|--------------------------------------------------------------------------------------------|-------------------------------------------------| -//! | operation_bytes | Histogram | Current operation size in bytes, represents the size of data being processed | scheme, namespace, root, operation, path | -//! | operation_bytes_rate | Histogram | Histogram of data processing rates in bytes per second within individual operations | scheme, namespace, root, operation, path | -//! | operation_entries | Histogram | Current operation size in entries, represents the entries being processed | scheme, namespace, root, operation, path | -//! | operation_entries_rate | Histogram | Histogram of entries processing rates in entries per second within individual operations | scheme, namespace, root, operation, path | -//! | operation_duration_seconds | Histogram | Duration of operations in seconds, measured from start to completion | scheme, namespace, root, operation, path | -//! | operation_errors_total | Counter | Total number of failed operations | scheme, namespace, root, operation, path, error | -//! | operation_executing | Gauge | Number of operations currently being executed | scheme, namespace, root, operation | -//! | operation_ttfb_seconds | Histogram | Time to first byte in seconds for operations | scheme, namespace, root, operation, path | -//! -//! ## HTTP Metrics -//! -//! These metrics track the underlying HTTP requests made by OpenDAL services that use HTTP. -//! -//! | Metric Name | Type | Description | Labels | -//! |----------------------------------|-----------|--------------------------------------------------------------------------------------------|-------------------------------------------------| -//! | http_connection_errors_total | Counter | Total number of HTTP requests that failed before receiving a response | scheme, namespace, root, operation, error | -//! | http_status_errors_total | Counter | Total number of HTTP requests that received error status codes (non-2xx responses) | scheme, namespace, root, operation, status | -//! | http_executing | Gauge | Number of HTTP requests currently in flight from this client | scheme, namespace, root | -//! | http_request_bytes | Histogram | Histogram of HTTP request body sizes in bytes | scheme, namespace, root, operation | -//! | http_request_bytes_rate | Histogram | Histogram of HTTP request bytes per second rates | scheme, namespace, root, operation | -//! | http_request_duration_seconds | Histogram | Histogram of time spent sending HTTP requests, from first byte sent to first byte received | scheme, namespace, root, operation | -//! | http_response_bytes | Histogram | Histogram of HTTP response body sizes in bytes | scheme, namespace, root, operation | -//! | http_response_bytes_rate | Histogram | Histogram of HTTP response bytes per second rates | scheme, namespace, root, operation | -//! | http_response_duration_seconds | Histogram | Histogram of time spent receiving HTTP responses, from first byte to last byte received | scheme, namespace, root, operation | -//! -//! ## Label Descriptions -//! -//! | Label | Description | Example Values | -//! |-----------|---------------------------------------------------------------|----------------------------------------| -//! | scheme | The storage service scheme | s3, gcs, azblob, fs, memory | -//! | namespace | The storage service namespace (bucket, container, etc.) | my-bucket, my-container | -//! | root | The root path within the namespace | /data, /backup | -//! | operation | The operation being performed | read, write, stat, list, delete | -//! | path | The path of the object being operated on | /path/to/file.txt | -//! | error | The error type or message for error metrics | not_found, permission_denied | -//! | status | The HTTP status code for HTTP error metrics | 404, 403, 500 | -//! -//! ## Metric Types -//! -//! * **Histogram**: Distribution of values with configurable buckets, includes count, sum and quantiles -//! * **Counter**: Cumulative metric that only increases over time (resets on restart) -//! * **Gauge**: Point-in-time metric that can increase and decrease - -mod metrics; - -pub use metrics::DEFAULT_BYTES_BUCKETS; -pub use metrics::DEFAULT_BYTES_RATE_BUCKETS; -pub use metrics::DEFAULT_DURATION_SECONDS_BUCKETS; -pub use metrics::DEFAULT_ENTRIES_BUCKETS; -pub use metrics::DEFAULT_ENTRIES_RATE_BUCKETS; -pub use metrics::DEFAULT_TTFB_BUCKETS; -pub use metrics::LABEL_ERROR; -pub use metrics::LABEL_NAMESPACE; -pub use metrics::LABEL_OPERATION; -pub use metrics::LABEL_ROOT; -pub use metrics::LABEL_SCHEME; -pub use metrics::LABEL_STATUS_CODE; -pub use metrics::MetricLabels; -pub use metrics::MetricValue; -pub use metrics::MetricsAccessor; -pub use metrics::MetricsIntercept; -pub use metrics::MetricsLayer; diff --git a/core/core/src/raw/http_util/body.rs b/core/core/src/raw/http_util/body.rs index 34b1a22e5..f694633db 100644 --- a/core/core/src/raw/http_util/body.rs +++ b/core/core/src/raw/http_util/body.rs @@ -76,7 +76,7 @@ impl HttpBody { /// Map the inner stream. #[cfg(not(target_arch = "wasm32"))] - pub(crate) fn map_inner( + pub fn map_inner( mut self, f: impl FnOnce( Box<dyn Stream<Item = Result<Buffer>> + Send + Sync + Unpin + 'static>, @@ -89,7 +89,7 @@ impl HttpBody { /// Map the inner stream. #[cfg(target_arch = "wasm32")] - pub(crate) fn map_inner( + pub fn map_inner( mut self, f: impl FnOnce( Box<dyn Stream<Item = Result<Buffer>> + Unpin + 'static>, diff --git a/core/core/src/raw/http_util/client.rs b/core/core/src/raw/http_util/client.rs index f00c47443..abab39396 100644 --- a/core/core/src/raw/http_util/client.rs +++ b/core/core/src/raw/http_util/client.rs @@ -91,7 +91,7 @@ impl HttpClient { } /// Get the inner http client. - pub(crate) fn into_inner(self) -> HttpFetcher { + pub fn into_inner(self) -> HttpFetcher { self.fetcher } diff --git a/core/layers/fastmetrics/Cargo.toml b/core/layers/fastmetrics/Cargo.toml new file mode 100644 index 000000000..c60193292 --- /dev/null +++ b/core/layers/fastmetrics/Cargo.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +description = "Apache OpenDAL metrics layer using fastmetrics" +name = "opendal-layer-fastmetrics" + +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +fastmetrics = { version = "0.4.1" } +opendal-core = { path = "../../core", version = "0.55.0", default-features = false } +opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", version = "0.55.0", default-features = false } diff --git a/core/core/src/layers/fastmetrics.rs b/core/layers/fastmetrics/src/lib.rs similarity index 98% rename from core/core/src/layers/fastmetrics.rs rename to core/layers/fastmetrics/src/lib.rs index f3a9f00a7..d6b03f774 100644 --- a/core/core/src/layers/fastmetrics.rs +++ b/core/layers/fastmetrics/src/lib.rs @@ -28,10 +28,9 @@ use fastmetrics::registry::Register; use fastmetrics::registry::Registry; use fastmetrics::registry::RegistryError; use fastmetrics::registry::with_global_registry_mut; - -use crate::layers::observe; -use crate::raw::*; -use crate::*; +use opendal_core::raw::*; +use opendal_core::*; +use opendal_layer_observe_metrics_common as observe; /// Add [fastmetrics](https://docs.rs/fastmetrics/) for every operation. /// @@ -42,7 +41,7 @@ use crate::*; /// ```no_run /// # use fastmetrics::format::text; /// # use log::info; -/// # use opendal_core::layers::FastmetricsLayer; +/// # use opendal_layer_fastmetrics::FastmetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -87,7 +86,7 @@ use crate::*; /// # use fastmetrics::format::text; /// # use fastmetrics::registry::with_global_registry; /// # use log::info; -/// # use opendal_core::layers::FastmetricsLayer; +/// # use opendal_layer_fastmetrics::FastmetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -230,7 +229,7 @@ impl FastmetricsLayerBuilder { /// # Example /// /// ```no_run - /// # use opendal_core::layers::FastmetricsLayer; + /// # use opendal_layer_fastmetrics::FastmetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -325,7 +324,7 @@ impl FastmetricsLayerBuilder { /// # Example /// /// ```no_run - /// # use opendal_core::layers::FastmetricsLayer; + /// # use opendal_layer_fastmetrics::FastmetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -495,6 +494,7 @@ impl observe::MetricsIntercept for FastmetricsInterceptor { self.http_status_errors_total .with_or_new(&labels, |counter| counter.inc()); } + _ => {} }; } } diff --git a/core/layers/metrics/Cargo.toml b/core/layers/metrics/Cargo.toml new file mode 100644 index 000000000..8461ebff6 --- /dev/null +++ b/core/layers/metrics/Cargo.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +description = "Apache OpenDAL metrics layer built on metrics crate" +name = "opendal-layer-metrics" + +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +metrics = "0.24" +opendal-core = { path = "../../core", version = "0.55.0", default-features = false } +opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", version = "0.55.0", default-features = false } diff --git a/core/core/src/layers/metrics.rs b/core/layers/metrics/src/lib.rs similarity index 97% rename from core/core/src/layers/metrics.rs rename to core/layers/metrics/src/lib.rs index 6de9bc347..2d098d5f5 100644 --- a/core/core/src/layers/metrics.rs +++ b/core/layers/metrics/src/lib.rs @@ -19,9 +19,8 @@ use metrics::Label; use metrics::counter; use metrics::gauge; use metrics::histogram; - -use crate::layers::observe; -use crate::raw::*; +use opendal_core::raw::*; +use opendal_layer_observe_metrics_common as observe; /// Add [metrics](https://docs.rs/metrics/) for every operation. /// @@ -38,7 +37,7 @@ use crate::raw::*; /// # Examples /// /// ```no_run -/// # use opendal_core::layers::MetricsLayer; +/// # use opendal_layer_metrics::MetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -148,6 +147,7 @@ impl observe::MetricsIntercept for MetricsInterceptor { observe::MetricValue::HttpStatusErrorsTotal => { counter!(value.name(), labels).increment(1) } + _ => {} } } } diff --git a/core/layers/observe-metrics-common/Cargo.toml b/core/layers/observe-metrics-common/Cargo.toml new file mode 100644 index 000000000..5206cd453 --- /dev/null +++ b/core/layers/observe-metrics-common/Cargo.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +description = "Apache OpenDAL observe metrics common components" +name = "opendal-layer-observe-metrics-common" + +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +futures = { version = "0.3", default-features = false, features = ["std", "async-await"] } +http = { workspace = true } +opendal-core = { path = "../../core", version = "0.55.0", default-features = false } diff --git a/core/core/src/layers/observe/metrics.rs b/core/layers/observe-metrics-common/src/lib.rs similarity index 85% rename from core/core/src/layers/observe/metrics.rs rename to core/layers/observe-metrics-common/src/lib.rs index 82f390453..d03480204 100644 --- a/core/core/src/layers/observe/metrics.rs +++ b/core/layers/observe-metrics-common/src/lib.rs @@ -15,6 +15,63 @@ // specific language governing permissions and limitations // under the License. +//! OpenDAL Observability +//! +//! This module offers essential components to facilitate the implementation of observability in OpenDAL. +//! +//! # OpenDAL Metrics Reference +//! +//! This document describes all metrics exposed by OpenDAL. +//! +//! ## Operation Metrics +//! +//! These metrics track operations at the storage abstraction level. +//! +//! | Metric Name | Type | Description | Labels | +//! |----------------------------------|-----------|--------------------------------------------------------------------------------------------|-------------------------------------------------| +//! | operation_bytes | Histogram | Current operation size in bytes, represents the size of data being processed | scheme, namespace, root, operation, path | +//! | operation_bytes_rate | Histogram | Histogram of data processing rates in bytes per second within individual operations | scheme, namespace, root, operation, path | +//! | operation_entries | Histogram | Current operation size in entries, represents the entries being processed | scheme, namespace, root, operation, path | +//! | operation_entries_rate | Histogram | Histogram of entries processing rates in entries per second within individual operations | scheme, namespace, root, operation, path | +//! | operation_duration_seconds | Histogram | Duration of operations in seconds, measured from start to completion | scheme, namespace, root, operation, path | +//! | operation_errors_total | Counter | Total number of failed operations | scheme, namespace, root, operation, path, error | +//! | operation_executing | Gauge | Number of operations currently being executed | scheme, namespace, root, operation | +//! | operation_ttfb_seconds | Histogram | Time to first byte in seconds for operations | scheme, namespace, root, operation, path | +//! +//! ## HTTP Metrics +//! +//! These metrics track the underlying HTTP requests made by OpenDAL services that use HTTP. +//! +//! | Metric Name | Type | Description | Labels | +//! |----------------------------------|-----------|--------------------------------------------------------------------------------------------|-------------------------------------------------| +//! | http_connection_errors_total | Counter | Total number of HTTP requests that failed before receiving a response | scheme, namespace, root, operation, error | +//! | http_status_errors_total | Counter | Total number of HTTP requests that received error status codes (non-2xx responses) | scheme, namespace, root, operation, status | +//! | http_executing | Gauge | Number of HTTP requests currently in flight from this client | scheme, namespace, root | +//! | http_request_bytes | Histogram | Histogram of HTTP request body sizes in bytes | scheme, namespace, root, operation | +//! | http_request_bytes_rate | Histogram | Histogram of HTTP request bytes per second rates | scheme, namespace, root, operation | +//! | http_request_duration_seconds | Histogram | Histogram of time spent sending HTTP requests, from first byte sent to first byte received | scheme, namespace, root, operation | +//! | http_response_bytes | Histogram | Histogram of HTTP response body sizes in bytes | scheme, namespace, root, operation | +//! | http_response_bytes_rate | Histogram | Histogram of HTTP response bytes per second rates | scheme, namespace, root, operation | +//! | http_response_duration_seconds | Histogram | Histogram of time spent receiving HTTP responses, from first byte to last byte received | scheme, namespace, root, operation | +//! +//! ## Label Descriptions +//! +//! | Label | Description | Example Values | +//! |-----------|---------------------------------------------------------------|----------------------------------------| +//! | scheme | The storage service scheme | s3, gcs, azblob, fs, memory | +//! | namespace | The storage service namespace (bucket, container, etc.) | my-bucket, my-container | +//! | root | The root path within the namespace | /data, /backup | +//! | operation | The operation being performed | read, write, stat, list, delete | +//! | path | The path of the object being operated on | /path/to/file.txt | +//! | error | The error type or message for error metrics | not_found, permission_denied | +//! | status | The HTTP status code for HTTP error metrics | 404, 403, 500 | +//! +//! ## Metric Types +//! +//! * **Histogram**: Distribution of values with configurable buckets, includes count, sum and quantiles +//! * **Counter**: Cumulative metric that only increases over time (resets on restart) +//! * **Gauge**: Point-in-time metric that can increase and decrease + use std::fmt::Debug; use std::fmt::Formatter; use std::pin::Pin; @@ -26,9 +83,8 @@ use std::task::ready; use futures::Stream; use futures::StreamExt; use http::StatusCode; - -use crate::raw::*; -use crate::*; +use opendal_core::raw::*; +use opendal_core::*; const KIB: f64 = 1024.0; const MIB: f64 = 1024.0 * KIB; diff --git a/core/layers/otelmetrics/Cargo.toml b/core/layers/otelmetrics/Cargo.toml new file mode 100644 index 000000000..3441b07a1 --- /dev/null +++ b/core/layers/otelmetrics/Cargo.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +description = "Apache OpenDAL OpenTelemetry metrics layer" +name = "opendal-layer-otelmetrics" + +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +opendal-core = { path = "../../core", version = "0.55.0", default-features = false } +opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", version = "0.55.0", default-features = false } +opentelemetry = { version = "0.31.0", default-features = false, features = ["metrics"] } diff --git a/core/core/src/layers/otelmetrics.rs b/core/layers/otelmetrics/src/lib.rs similarity index 98% rename from core/core/src/layers/otelmetrics.rs rename to core/layers/otelmetrics/src/lib.rs index cd4962abb..5b084a59c 100644 --- a/core/core/src/layers/otelmetrics.rs +++ b/core/layers/otelmetrics/src/lib.rs @@ -15,21 +15,20 @@ // specific language governing permissions and limitations // under the License. +use opendal_core::raw::*; +use opendal_layer_observe_metrics_common as observe; use opentelemetry::KeyValue; use opentelemetry::metrics::Counter; use opentelemetry::metrics::Histogram; use opentelemetry::metrics::Meter; use opentelemetry::metrics::UpDownCounter; -use crate::layers::observe; -use crate::raw::*; - /// Add [opentelemetry::metrics](https://docs.rs/opentelemetry/latest/opentelemetry/metrics/index.html) for every operation. /// /// # Examples /// /// ```no_run -/// # use opendal_core::layers::OtelMetricsLayer; +/// # use opendal_layer_otelmetrics::OtelMetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -53,7 +52,7 @@ impl OtelMetricsLayer { /// # Examples /// /// ```no_run - /// # use opendal_core::layers::OtelMetricsLayer; + /// # use opendal_layer_otelmetrics::OtelMetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -150,7 +149,7 @@ impl OtelMetricsLayerBuilder { /// # Examples /// /// ```no_run - /// # use opendal_core::layers::OtelMetricsLayer; + /// # use opendal_layer_otelmetrics::OtelMetricsLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -421,6 +420,7 @@ impl observe::MetricsIntercept for OtelMetricsInterceptor { observe::MetricValue::HttpStatusErrorsTotal => { self.http_status_errors_total.add(1, &attributes) } + _ => {} } } } diff --git a/core/layers/prometheus-client/Cargo.toml b/core/layers/prometheus-client/Cargo.toml new file mode 100644 index 000000000..2fe48a82a --- /dev/null +++ b/core/layers/prometheus-client/Cargo.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +description = "Apache OpenDAL metrics layer using prometheus-client" +name = "opendal-layer-prometheus-client" + +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +opendal-core = { path = "../../core", version = "0.55.0", default-features = false } +opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", version = "0.55.0", default-features = false } +prometheus-client = { version = "0.24" } diff --git a/core/core/src/layers/prometheus_client.rs b/core/layers/prometheus-client/src/lib.rs similarity index 98% rename from core/core/src/layers/prometheus_client.rs rename to core/layers/prometheus-client/src/lib.rs index 1198cd582..85f31848b 100644 --- a/core/core/src/layers/prometheus_client.rs +++ b/core/layers/prometheus-client/src/lib.rs @@ -17,6 +17,9 @@ use std::fmt; +use opendal_core::raw::*; +use opendal_core::*; +use opendal_layer_observe_metrics_common as observe; use prometheus_client::encoding::EncodeLabel; use prometheus_client::encoding::EncodeLabelSet; use prometheus_client::encoding::LabelSetEncoder; @@ -29,10 +32,6 @@ use prometheus_client::registry::Metric; use prometheus_client::registry::Registry; use prometheus_client::registry::Unit; -use crate::layers::observe; -use crate::raw::*; -use crate::*; - /// Add [prometheus-client](https://docs.rs/prometheus-client) for every operation. /// /// # Prometheus Metrics @@ -44,7 +43,7 @@ use crate::*; /// /// ```no_run /// # use log::info; -/// # use opendal_core::layers::PrometheusClientLayer; +/// # use opendal_layer_prometheus_client::PrometheusClientLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -181,7 +180,7 @@ impl PrometheusClientLayerBuilder { /// # Example /// /// ```no_run - /// # use opendal_core::layers::PrometheusClientLayer; + /// # use opendal_layer_prometheus_client::PrometheusClientLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -477,6 +476,7 @@ impl observe::MetricsIntercept for PrometheusClientInterceptor { observe::MetricValue::HttpStatusErrorsTotal => { self.http_status_errors_total.get_or_create(&labels).inc(); } + _ => {} }; } } diff --git a/core/layers/prometheus/Cargo.toml b/core/layers/prometheus/Cargo.toml new file mode 100644 index 000000000..45f588a22 --- /dev/null +++ b/core/layers/prometheus/Cargo.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[package] +description = "Apache OpenDAL Prometheus metrics layer" +name = "opendal-layer-prometheus" + +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +opendal-core = { path = "../../core", version = "0.55.0", default-features = false } +opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", version = "0.55.0", default-features = false } +prometheus = { version = "0.14", features = ["process"] } diff --git a/core/core/src/layers/prometheus.rs b/core/layers/prometheus/src/lib.rs similarity index 98% rename from core/core/src/layers/prometheus.rs rename to core/layers/prometheus/src/lib.rs index eb6dfae4a..003e3d5ed 100644 --- a/core/core/src/layers/prometheus.rs +++ b/core/layers/prometheus/src/lib.rs @@ -15,6 +15,10 @@ // specific language governing permissions and limitations // under the License. +use opendal_core::raw::Access; +use opendal_core::raw::*; +use opendal_core::*; +use opendal_layer_observe_metrics_common as observe; use prometheus::HistogramVec; use prometheus::Registry; use prometheus::core::AtomicI64; @@ -25,11 +29,6 @@ use prometheus::register_histogram_vec_with_registry; use prometheus::register_int_counter_vec_with_registry; use prometheus::register_int_gauge_vec_with_registry; -use crate::layers::observe; -use crate::raw::Access; -use crate::raw::*; -use crate::*; - /// Add [prometheus](https://docs.rs/prometheus) for every operation. /// /// # Prometheus Metrics @@ -43,7 +42,7 @@ use crate::*; /// /// ```no_run /// # use log::info; -/// # use opendal_core::layers::PrometheusLayer; +/// # use opendal_layer_prometheus::PrometheusLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -94,7 +93,7 @@ use crate::*; /// ```no_run /// # use std::sync::OnceLock; /// # use log::info; -/// # use opendal_core::layers::PrometheusLayer; +/// # use opendal_layer_prometheus::PrometheusLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -146,7 +145,7 @@ impl PrometheusLayer { /// # Example /// /// ```no_run - /// # use opendal_core::layers::PrometheusLayer; + /// # use opendal_layer_prometheus::PrometheusLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -261,7 +260,7 @@ impl PrometheusLayerBuilder { /// # Example /// /// ```no_run - /// # use opendal_core::layers::PrometheusLayer; + /// # use opendal_layer_prometheus::PrometheusLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -499,7 +498,7 @@ impl PrometheusLayerBuilder { /// # Example /// /// ```no_run - /// # use opendal_core::layers::PrometheusLayer; + /// # use opendal_layer_prometheus::PrometheusLayer; /// # use opendal_core::services; /// # use opendal_core::Operator; /// # use opendal_core::Result; @@ -624,6 +623,7 @@ impl observe::MetricsIntercept for PrometheusInterceptor { .http_status_errors_total .with_label_values(&labels.values()) .inc(), + _ => {} } } } diff --git a/core/src/lib.rs b/core/src/lib.rs index c6872d9c7..f4604e167 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -52,4 +52,14 @@ pub mod layers { pub use opendal_layer_await_tree::*; #[cfg(feature = "layers-capability-check")] pub use opendal_layer_capability_check::*; + #[cfg(feature = "layers-fastmetrics")] + pub use opendal_layer_fastmetrics::*; + #[cfg(feature = "layers-metrics")] + pub use opendal_layer_metrics::*; + #[cfg(feature = "layers-otel-metrics")] + pub use opendal_layer_otelmetrics::*; + #[cfg(feature = "layers-prometheus")] + pub use opendal_layer_prometheus::*; + #[cfg(feature = "layers-prometheus-client")] + pub use opendal_layer_prometheus_client::*; }
