This is an automated email from the ASF dual-hosted git repository.

koushiro pushed a commit to branch unify-layers
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit 42e6f18546b08b0bbff8f736f7ad80b8f0adc68b
Author: koushiro <[email protected]>
AuthorDate: Wed Dec 24 23:44:20 2025 +0800

    chore(layers): unify layer crates and gate dtrace on linux
    
    - add crate-level docs, doc_cfg, and missing_docs lint across layer crates
    - mark layers non_exhaustive and hide internal accessors/wrappers
    - move dtrace dependency to linux target and tidy Cargo.toml/workspace 
dependency specs
---
 core/Cargo.lock                                    |  1 +
 core/Cargo.toml                                    |  4 +-
 .../core/src/docs/performance/http_optimization.md |  2 +-
 core/core/src/docs/upgrade.md                      | 13 ++--
 core/layers/async-backtrace/src/lib.rs             | 38 ++++++----
 core/layers/await-tree/src/lib.rs                  | 25 ++++---
 core/layers/capability-check/src/lib.rs            | 52 ++++++++------
 core/layers/chaos/src/lib.rs                       | 23 +++---
 core/layers/concurrent-limit/src/lib.rs            | 27 ++++---
 core/layers/dtrace/Cargo.toml                      |  7 +-
 core/layers/dtrace/src/lib.rs                      | 42 +++++++----
 core/layers/fastmetrics/Cargo.toml                 |  2 +-
 core/layers/fastmetrics/src/lib.rs                 | 14 ++--
 core/layers/fastrace/src/lib.rs                    | 23 ++++--
 core/layers/hotpath/src/lib.rs                     | 24 +++++--
 core/layers/immutable-index/src/lib.rs             | 23 ++++--
 core/layers/logging/src/lib.rs                     | 16 ++++-
 core/layers/metrics/src/lib.rs                     | 20 +++++-
 core/layers/mime-guess/src/lib.rs                  | 65 +++++++++--------
 core/layers/observe-metrics-common/Cargo.toml      |  5 +-
 core/layers/observe-metrics-common/src/lib.rs      | 35 ++++-----
 core/layers/otelmetrics/Cargo.toml                 |  2 +-
 core/layers/otelmetrics/src/lib.rs                 |  8 ++-
 core/layers/oteltrace/src/lib.rs                   | 20 +++++-
 core/layers/prometheus-client/Cargo.toml           |  2 +-
 core/layers/prometheus-client/src/lib.rs           | 19 ++---
 core/layers/prometheus/Cargo.toml                  |  2 +-
 core/layers/prometheus/src/lib.rs                  | 22 +++---
 core/layers/retry/Cargo.toml                       |  6 +-
 core/layers/retry/src/lib.rs                       | 82 ++++++++++------------
 core/layers/tail-cut/src/lib.rs                    | 35 ++++-----
 core/layers/throttle/Cargo.toml                    |  2 +-
 core/layers/throttle/src/lib.rs                    | 22 +++---
 core/layers/timeout/Cargo.toml                     |  2 +-
 core/layers/timeout/src/lib.rs                     | 32 +++++----
 core/layers/tracing/src/lib.rs                     | 46 +++++++-----
 36 files changed, 471 insertions(+), 292 deletions(-)

diff --git a/core/Cargo.lock b/core/Cargo.lock
index 852e81b01..f9ad9f2f2 100644
--- a/core/Cargo.lock
+++ b/core/Cargo.lock
@@ -5782,6 +5782,7 @@ dependencies = [
  "bytes",
  "opendal-core",
  "probe",
+ "tokio",
 ]
 
 [[package]]
diff --git a/core/Cargo.toml b/core/Cargo.toml
index f3f58c972..12caac5c0 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -207,7 +207,6 @@ opendal-layer-await-tree = { path = "layers/await-tree", 
version = "0.55.0", opt
 opendal-layer-capability-check = { path = "layers/capability-check", version = 
"0.55.0", optional = true, default-features = false }
 opendal-layer-chaos = { path = "layers/chaos", version = "0.55.0", optional = 
true, default-features = false }
 opendal-layer-concurrent-limit = { path = "layers/concurrent-limit", version = 
"0.55.0", optional = true, default-features = false }
-opendal-layer-dtrace = { path = "layers/dtrace", 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-layer-fastrace = { path = "layers/fastrace", version = "0.55.0", 
optional = true, default-features = false }
 opendal-layer-hotpath = { path = "layers/hotpath", version = "0.55.0", 
optional = true, default-features = false }
@@ -287,6 +286,9 @@ opendal-service-webhdfs = { path = "services/webhdfs", 
version = "0.55.0", optio
 opendal-service-yandex-disk = { path = "services/yandex-disk", version = 
"0.55.0", optional = true, default-features = false }
 opendal-testkit = { path = "testkit", version = "0.55.0", optional = true }
 
+[target.'cfg(target_os = "linux")'.dependencies]
+opendal-layer-dtrace = { path = "layers/dtrace", version = "0.55.0", optional 
= true, default-features = false }
+
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 opendal-service-opfs = { path = "services/opfs", version = "0.55.0", optional 
= true, default-features = false }
 
diff --git a/core/core/src/docs/performance/http_optimization.md 
b/core/core/src/docs/performance/http_optimization.md
index 95aa84dbc..83e2b6df5 100644
--- a/core/core/src/docs/performance/http_optimization.md
+++ b/core/core/src/docs/performance/http_optimization.md
@@ -93,7 +93,7 @@ In addition to the options mentioned above, 
`Xuanwo/reqwest-hickory-resolver` al
 
 `reqwest` didn't set a default timeout for HTTP requests. This means that if a 
request hangs or takes too long to complete, it can block the entire process, 
leading to performance degradation or even application crashes.
 
-It's recommended to set a connect timeout for HTTP requests to prevent this 
issue. 
+It's recommended to set a connect timeout for HTTP requests to prevent this 
issue.
 
 ```rust
 let client = reqwest::ClientBuilder::new()
diff --git a/core/core/src/docs/upgrade.md b/core/core/src/docs/upgrade.md
index 53654435f..ae1e8aeb7 100644
--- a/core/core/src/docs/upgrade.md
+++ b/core/core/src/docs/upgrade.md
@@ -56,7 +56,7 @@ OpenDAL v0.54 implements 
[RFC-6213](https://opendal.apache.org/docs/rust/opendal
 New APIs added:
 
 - `read_options(path, ReadOptions)`
-- `write_options(path, data, WriteOptions)`  
+- `write_options(path, data, WriteOptions)`
 - `list_options(path, ListOptions)`
 - `stat_options(path, StatOptions)`
 - `delete_options(path, DeleteOptions)`
@@ -70,7 +70,7 @@ let options = ReadOptions::new()
     .if_match("etag");
 let data = op.read_options("path/to/file", options).await?;
 
-// Write with options  
+// Write with options
 let options = WriteOptions::new()
     .content_type("text/plain")
     .cache_control("max-age=3600");
@@ -118,7 +118,7 @@ New options-based presign APIs have been exposed:
 ```rust
 let options = PresignOptions::new()
     .expire(Duration::from_secs(3600));
-    
+
 let url = op.presign_read_options("path/to/file", options).await?;
 ```
 
@@ -171,7 +171,6 @@ For example:
 - `Operation::ReaderRead` has been merged into `Operation::Read`
 - `Operation::BlockingRead` has been merged into `Operation::Read`
 
-
 # Upgrade to v0.52
 
 ## Public API
@@ -636,7 +635,7 @@ After [RFC: List 
Prefix](crate::docs::rfcs::rfc_3243_list_prefix) landed, we hav
 Here are the behavior list:
 
 | Case                   | Path            | Result                            
         |
-|------------------------|-----------------|--------------------------------------------|
+| ---------------------- | --------------- | 
------------------------------------------ |
 | stat existing dir      | `abc/`          | Metadata with dir mode            
         |
 | stat existing file     | `abc/def_file`  | Metadata with file mode           
         |
 | stat dir without `/`   | `abc/def_dir`   | Error `NotFound` or metadata with 
dir mode |
@@ -773,8 +772,6 @@ OpenDAL v0.40 removed the origin `range_read` and 
`range_reader` interfaces, ple
 + let reader = op.reader_with(path).range(range_start..range_end).await?;
 ```
 
-
-
 ## Raw API
 
 ### RFC-3017 Remove Write Copy From
@@ -962,7 +959,7 @@ More details could be found at [RFC: Remove Object 
Concept][crate::docs::rfcs::r
 To upgrade to OpenDAL v0.30, users need to make the following changes:
 
 - regex replace `object\((.*)\).reader\(\)` to `reader($1)`
-       - replace the function on your case, it's recommended to do it one by 
one
+  - replace the function on your case, it's recommended to do it one by one
 - rename `ObjectMetakey` => `Metakey`
 - rename `ObjectMode` => `EntryMode`
 - replace `ErrorKind::ObjectXxx` to `ErrorKind::Xxx`
diff --git a/core/layers/async-backtrace/src/lib.rs 
b/core/layers/async-backtrace/src/lib.rs
index 2f9d67f58..f8222097a 100644
--- a/core/layers/async-backtrace/src/lib.rs
+++ b/core/layers/async-backtrace/src/lib.rs
@@ -15,7 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use opendal_core::raw::oio;
+//! Async backtrace layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use opendal_core::raw::*;
 use opendal_core::*;
 
@@ -29,30 +33,39 @@ use opendal_core::*;
 /// # Examples
 ///
 /// ```no_run
-/// use opendal_layer_async_backtrace::AsyncBacktraceLayer;
-/// use opendal_core::services;
-/// use opendal_core::Operator;
-/// use opendal_core::Result;
-///
+/// # use opendal_core::services;
+/// # use opendal_core::Operator;
+/// # use opendal_core::Result;
+/// # use opendal_layer_async_backtrace::AsyncBacktraceLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(AsyncBacktraceLayer::default())
+///     .layer(AsyncBacktraceLayer::new())
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 #[derive(Clone, Default)]
-pub struct AsyncBacktraceLayer;
+#[non_exhaustive]
+pub struct AsyncBacktraceLayer {}
+
+impl AsyncBacktraceLayer {
+    /// Create a new [`AsyncBacktraceLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
 
 impl<A: Access> Layer<A> for AsyncBacktraceLayer {
     type LayeredAccess = AsyncBacktraceAccessor<A>;
 
-    fn layer(&self, accessor: A) -> Self::LayeredAccess {
-        AsyncBacktraceAccessor { inner: accessor }
+    fn layer(&self, inner: A) -> Self::LayeredAccess {
+        AsyncBacktraceAccessor { inner }
     }
 }
 
-#[derive(Debug, Clone)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct AsyncBacktraceAccessor<A: Access> {
     inner: A,
 }
@@ -121,6 +134,7 @@ impl<A: Access> LayeredAccess for AsyncBacktraceAccessor<A> 
{
     }
 }
 
+#[doc(hidden)]
 pub struct AsyncBacktraceWrapper<R> {
     inner: R,
 }
diff --git a/core/layers/await-tree/src/lib.rs 
b/core/layers/await-tree/src/lib.rs
index b17eec518..1b98de408 100644
--- a/core/layers/await-tree/src/lib.rs
+++ b/core/layers/await-tree/src/lib.rs
@@ -15,9 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Await tree layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use await_tree::InstrumentAwait;
 use futures::Future;
-
 use opendal_core::raw::*;
 use opendal_core::*;
 
@@ -32,37 +36,39 @@ use opendal_core::*;
 /// # Examples
 ///
 /// ```no_run
-/// # use opendal_layer_await_tree::AwaitTreeLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_await_tree::AwaitTreeLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
 ///     .layer(AwaitTreeLayer::new())
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 #[derive(Clone, Default)]
+#[non_exhaustive]
 pub struct AwaitTreeLayer {}
 
 impl AwaitTreeLayer {
-    /// Create a new `AwaitTreeLayer`.
+    /// Create a new [`AwaitTreeLayer`].
     pub fn new() -> Self {
-        Self {}
+        Self::default()
     }
 }
 
 impl<A: Access> Layer<A> for AwaitTreeLayer {
     type LayeredAccess = AwaitTreeAccessor<A>;
 
-    fn layer(&self, accessor: A) -> Self::LayeredAccess {
-        AwaitTreeAccessor { inner: accessor }
+    fn layer(&self, inner: A) -> Self::LayeredAccess {
+        AwaitTreeAccessor { inner }
     }
 }
 
-#[derive(Debug, Clone)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct AwaitTreeAccessor<A: Access> {
     inner: A,
 }
@@ -139,6 +145,7 @@ impl<A: Access> LayeredAccess for AwaitTreeAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct AwaitTreeWrapper<R> {
     inner: R,
 }
diff --git a/core/layers/capability-check/src/lib.rs 
b/core/layers/capability-check/src/lib.rs
index 5d09ef1ae..b0ba046f0 100644
--- a/core/layers/capability-check/src/lib.rs
+++ b/core/layers/capability-check/src/lib.rs
@@ -15,12 +15,17 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Capability check layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::fmt::Debug;
 use std::fmt::Formatter;
 use std::sync::Arc;
 
 use opendal_core::raw::*;
-use opendal_core::{Error, ErrorKind, Result};
+use opendal_core::*;
 
 /// Add an extra capability check layer for every operation
 ///
@@ -38,24 +43,31 @@ use opendal_core::{Error, ErrorKind, Result};
 /// 2. OpenDAL doesn't apply this checker by default. Users can enable this 
layer if they want to
 ///    enforce stricter requirements.
 ///
-/// # examples
+/// # Examples
 ///
 /// ```no_run
-/// # use opendal_layer_capability_check::CapabilityCheckLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_capability_check::CapabilityCheckLayer;
+/// #
 /// # fn main() -> Result<()> {
-/// use opendal_layer_capability_check::CapabilityCheckLayer;
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(CapabilityCheckLayer)
+///     .layer(CapabilityCheckLayer::new())
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
-#[derive(Default)]
-pub struct CapabilityCheckLayer;
+#[derive(Clone, Default)]
+#[non_exhaustive]
+pub struct CapabilityCheckLayer {}
+
+impl CapabilityCheckLayer {
+    /// Create a new [`CapabilityCheckLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
 
 impl<A: Access> Layer<A> for CapabilityCheckLayer {
     type LayeredAccess = CapabilityAccessor<A>;
@@ -67,11 +79,20 @@ impl<A: Access> Layer<A> for CapabilityCheckLayer {
     }
 }
 
+#[doc(hidden)]
 pub struct CapabilityAccessor<A: Access> {
     info: Arc<AccessorInfo>,
     inner: A,
 }
 
+impl<A: Access> Debug for CapabilityAccessor<A> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("CapabilityCheckAccessor")
+            .field("inner", &self.inner)
+            .finish_non_exhaustive()
+    }
+}
+
 fn new_unsupported_error(info: &AccessorInfo, op: Operation, args: &str) -> 
Error {
     let scheme = info.scheme();
     let op = op.into_static();
@@ -83,14 +104,6 @@ fn new_unsupported_error(info: &AccessorInfo, op: 
Operation, args: &str) -> Erro
     .with_operation(op)
 }
 
-impl<A: Access> Debug for CapabilityAccessor<A> {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("CapabilityCheckAccessor")
-            .field("inner", &self.inner)
-            .finish_non_exhaustive()
-    }
-}
-
 impl<A: Access> LayeredAccess for CapabilityAccessor<A> {
     type Inner = A;
     type Reader = A::Reader;
@@ -154,9 +167,6 @@ impl<A: Access> LayeredAccess for CapabilityAccessor<A> {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use opendal_core::Capability;
-    use opendal_core::ErrorKind;
-    use opendal_core::Operator;
 
     #[derive(Debug)]
     struct MockService {
@@ -188,7 +198,7 @@ mod tests {
     fn new_test_operator(capability: Capability) -> Operator {
         let srv = MockService { capability };
 
-        Operator::from_inner(Arc::new(srv)).layer(CapabilityCheckLayer)
+        Operator::from_inner(Arc::new(srv)).layer(CapabilityCheckLayer::new())
     }
 
     #[tokio::test]
diff --git a/core/layers/chaos/src/lib.rs b/core/layers/chaos/src/lib.rs
index 9334b7917..f9c82b1ea 100644
--- a/core/layers/chaos/src/lib.rs
+++ b/core/layers/chaos/src/lib.rs
@@ -15,14 +15,18 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Chaos layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::sync::Arc;
 use std::sync::Mutex;
 
-use rand::prelude::*;
-use rand::rngs::StdRng;
-
 use opendal_core::raw::*;
 use opendal_core::*;
+use rand::prelude::*;
+use rand::rngs::StdRng;
 
 /// Inject chaos into underlying services for robustness test.
 ///
@@ -44,25 +48,25 @@ use opendal_core::*;
 /// # Examples
 ///
 /// ```no_run
-/// # use opendal_layer_chaos::ChaosLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_chaos::ChaosLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
 ///     .layer(ChaosLayer::new(0.1))
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct ChaosLayer {
     error_ratio: f64,
 }
 
 impl ChaosLayer {
-    /// Create a new chaos layer with specified error ratio.
+    /// Create a new [`ChaosLayer`] with specified error ratio.
     ///
     /// # Panics
     ///
@@ -88,6 +92,7 @@ impl<A: Access> Layer<A> for ChaosLayer {
     }
 }
 
+#[doc(hidden)]
 #[derive(Debug)]
 pub struct ChaosAccessor<A> {
     inner: A,
@@ -127,7 +132,7 @@ impl<A: Access> LayeredAccess for ChaosAccessor<A> {
     }
 }
 
-/// ChaosReader will inject error into read operations.
+#[doc(hidden)]
 pub struct ChaosReader<R> {
     inner: R,
     rng: Arc<Mutex<StdRng>>,
diff --git a/core/layers/concurrent-limit/src/lib.rs 
b/core/layers/concurrent-limit/src/lib.rs
index bde32113e..53c15b208 100644
--- a/core/layers/concurrent-limit/src/lib.rs
+++ b/core/layers/concurrent-limit/src/lib.rs
@@ -15,7 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt::Debug;
+//! Concurrent request limit layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::pin::Pin;
 use std::sync::Arc;
 use std::task::Context;
@@ -25,7 +29,6 @@ use futures::Stream;
 use futures::StreamExt;
 use mea::semaphore::OwnedSemaphorePermit;
 use mea::semaphore::Semaphore;
-
 use opendal_core::raw::*;
 use opendal_core::*;
 
@@ -46,27 +49,27 @@ use opendal_core::*;
 /// Add a concurrent limit layer to the operator:
 ///
 /// ```no_run
-/// # use opendal_layer_concurrent_limit::ConcurrentLimitLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_concurrent_limit::ConcurrentLimitLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
 ///     .layer(ConcurrentLimitLayer::new(1024))
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 ///
 /// Share a concurrent limit layer between the operators:
 ///
 /// ```no_run
-/// # use opendal_layer_concurrent_limit::ConcurrentLimitLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_concurrent_limit::ConcurrentLimitLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let limit = ConcurrentLimitLayer::new(1024);
 ///
@@ -76,8 +79,7 @@ use opendal_core::*;
 /// let _operator_b = Operator::new(services::Memory::default())?
 ///     .layer(limit.clone())
 ///     .finish();
-///
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 #[derive(Clone)]
@@ -128,6 +130,7 @@ impl<A: Access> Layer<A> for ConcurrentLimitLayer {
     }
 }
 
+#[doc(hidden)]
 pub struct ConcurrentLimitHttpFetcher {
     inner: HttpFetcher,
     http_semaphore: Option<Arc<Semaphore>>,
@@ -153,7 +156,7 @@ impl HttpFetch for ConcurrentLimitHttpFetcher {
     }
 }
 
-pub struct ConcurrentLimitStream<S> {
+struct ConcurrentLimitStream<S> {
     inner: S,
     // Hold on this permit until this reader has been dropped.
     _permit: OwnedSemaphorePermit,
@@ -170,7 +173,8 @@ where
     }
 }
 
-#[derive(Debug, Clone)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct ConcurrentLimitAccessor<A: Access> {
     inner: A,
     semaphore: Arc<Semaphore>,
@@ -236,6 +240,7 @@ impl<A: Access> LayeredAccess for 
ConcurrentLimitAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct ConcurrentLimitWrapper<R> {
     inner: R,
 
diff --git a/core/layers/dtrace/Cargo.toml b/core/layers/dtrace/Cargo.toml
index 3db823637..0f6153630 100644
--- a/core/layers/dtrace/Cargo.toml
+++ b/core/layers/dtrace/Cargo.toml
@@ -30,10 +30,11 @@ version = { workspace = true }
 [package.metadata.docs.rs]
 all-features = true
 
-[dependencies]
+[target.'cfg(target_os = "linux")'.dependencies]
 bytes = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = 
false }
-probe = { version = "0.5.1" }
+probe = "0.5.1"
 
-[dev-dependencies]
+[target.'cfg(target_os = "linux")'.dev-dependencies]
 opendal-core = { path = "../../core", version = "0.55.0" }
+tokio = { workspace = true, features = ["macros", "rt-multi-thread"]}
diff --git a/core/layers/dtrace/src/lib.rs b/core/layers/dtrace/src/lib.rs
index c0c292f1a..adaa98ea6 100644
--- a/core/layers/dtrace/src/lib.rs
+++ b/core/layers/dtrace/src/lib.rs
@@ -15,16 +15,20 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Dtrace layer implementation for Apache OpenDAL.
+
+#![cfg(target_os = "linux")]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::ffi::CString;
 use std::fmt::Debug;
 use std::fmt::Formatter;
 
 use bytes::Buf;
-use probe::probe_lazy;
-
-use opendal_core::raw::Access;
 use opendal_core::raw::*;
 use opendal_core::*;
+use probe::probe_lazy;
 
 /// Support User Statically-Defined Tracing(aka USDT) on Linux
 ///
@@ -72,17 +76,17 @@ use opendal_core::*;
 ///
 /// Example:
 ///
-/// ```ignore
-/// # use opendal::layers::DtraceLayer;
-/// # use opendal::services;
-/// # use opendal::Operator;
-/// # use opendal::Result;
-///
+/// ```no_run
+/// # use opendal_core::services;
+/// # use opendal_core::Operator;
+/// # use opendal_core::Result;
+/// # use opendal_layer_dtrace::DtraceLayer;
+/// #
 /// # #[tokio::main]
 /// # async fn main() -> Result<()> {
 /// // `Accessor` provides the low level APIs, we will use `Operator` normally.
-/// let op: Operator = Operator::new(services::Fs::default().root("/tmp"))?
-///     .layer(DtraceLayer::default())
+/// let op: Operator = Operator::new(services::Memory::default().root("/tmp"))?
+///     .layer(DtraceLayer::new())
 ///     .finish();
 ///
 /// let path = "/tmp/test.txt";
@@ -91,7 +95,7 @@ use opendal_core::*;
 ///     op.write(path, bs).await?;
 ///     op.read(path).await?;
 /// }
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 ///
@@ -122,9 +126,16 @@ use opendal_core::*;
 ///     Arguments: -8@%rax
 ///   stapsdt              0x0000003c       NT_STAPSDT (SystemTap probe 
descriptors)
 /// ```
-#[derive(Default, Debug, Clone)]
+#[derive(Clone, Default)]
+#[non_exhaustive]
 pub struct DtraceLayer {}
 
+impl DtraceLayer {
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
+
 impl<A: Access> Layer<A> for DtraceLayer {
     type LayeredAccess = DTraceAccessor<A>;
     fn layer(&self, inner: A) -> Self::LayeredAccess {
@@ -132,7 +143,7 @@ impl<A: Access> Layer<A> for DtraceLayer {
     }
 }
 
-#[derive(Clone)]
+#[doc(hidden)]
 pub struct DTraceAccessor<A: Access> {
     inner: A,
 }
@@ -218,13 +229,14 @@ impl<A: Access> LayeredAccess for DTraceAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct DtraceLayerWrapper<R> {
     inner: R,
     path: String,
 }
 
 impl<R> DtraceLayerWrapper<R> {
-    pub fn new(inner: R, path: &String) -> Self {
+    fn new(inner: R, path: &String) -> Self {
         Self {
             inner,
             path: path.to_string(),
diff --git a/core/layers/fastmetrics/Cargo.toml 
b/core/layers/fastmetrics/Cargo.toml
index fc9b43fc1..65fb4e36f 100644
--- a/core/layers/fastmetrics/Cargo.toml
+++ b/core/layers/fastmetrics/Cargo.toml
@@ -31,7 +31,7 @@ version = { workspace = true }
 all-features = true
 
 [dependencies]
-fastmetrics = { version = "0.4.1" }
+fastmetrics = "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/layers/fastmetrics/src/lib.rs 
b/core/layers/fastmetrics/src/lib.rs
index bf39d055b..3c6435748 100644
--- a/core/layers/fastmetrics/src/lib.rs
+++ b/core/layers/fastmetrics/src/lib.rs
@@ -15,7 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt;
+//! Metrics layer (using the [fastmetrics](https://docs.rs/fastmetrics/) 
crate) implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
 
 use fastmetrics::encoder::EncodeLabelSet;
 use fastmetrics::encoder::LabelSetEncoder;
@@ -124,7 +127,7 @@ use opendal_layer_observe_metrics_common as observe;
 /// println!("{}", output);
 /// # Ok(())
 /// # }
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct FastmetricsLayer {
     interceptor: FastmetricsInterceptor,
 }
@@ -324,11 +327,11 @@ impl FastmetricsLayerBuilder {
     /// # Example
     ///
     /// ```no_run
-    /// # use opendal_layer_fastmetrics::FastmetricsLayer;
     /// # use opendal_core::services;
     /// # use opendal_core::Operator;
     /// # use opendal_core::Result;
-    ///
+    /// # use opendal_layer_fastmetrics::FastmetricsLayer;
+    /// #
     /// # fn main() -> Result<()> {
     /// // Pick a builder and configure it.
     /// let builder = services::Memory::default();
@@ -354,6 +357,7 @@ impl MetricFactory<Histogram> for HistogramFactory {
     }
 }
 
+#[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct FastmetricsInterceptor {
     operation_bytes: Family<OperationLabels, Histogram, HistogramFactory>,
@@ -506,7 +510,7 @@ struct OperationLabels {
 }
 
 impl EncodeLabelSet for OperationLabels {
-    fn encode(&self, encoder: &mut dyn LabelSetEncoder) -> fmt::Result {
+    fn encode(&self, encoder: &mut dyn LabelSetEncoder) -> std::fmt::Result {
         encoder.encode(&(observe::LABEL_SCHEME, self.labels.scheme))?;
         encoder.encode(&(observe::LABEL_NAMESPACE, 
self.labels.namespace.as_ref()))?;
         if !self.disable_label_root {
diff --git a/core/layers/fastrace/src/lib.rs b/core/layers/fastrace/src/lib.rs
index 681425a12..8a3ebd805 100644
--- a/core/layers/fastrace/src/lib.rs
+++ b/core/layers/fastrace/src/lib.rs
@@ -15,7 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt::Debug;
+//! Fastrace layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::future::Future;
 use std::sync::Arc;
 
@@ -37,7 +41,7 @@ use opendal_core::*;
 /// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(FastraceLayer)
+///     .layer(FastraceLayer::new())
 ///     .finish();
 /// # Ok(())
 /// # }
@@ -63,7 +67,7 @@ use opendal_core::*;
 ///         async {
 ///             let _ = dotenvy::dotenv();
 ///             let op = Operator::new(services::Memory::default())?
-///                 .layer(FastraceLayer)
+///                 .layer(FastraceLayer::new())
 ///                 .finish();
 ///             op.write("test", "0".repeat(16 * 1024 * 1024).into_bytes())
 ///                 .await?;
@@ -99,7 +103,16 @@ use opendal_core::*;
 /// ```
 ///
 /// For real-world usage, please take a look at 
[`fastrace-datadog`](https://crates.io/crates/fastrace-datadog) or 
[`fastrace-jaeger`](https://crates.io/crates/fastrace-jaeger) .
-pub struct FastraceLayer;
+#[derive(Clone, Default)]
+#[non_exhaustive]
+pub struct FastraceLayer {}
+
+impl FastraceLayer {
+    /// Create a new [`FastraceLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
 
 impl<A: Access> Layer<A> for FastraceLayer {
     type LayeredAccess = FastraceAccessor<A>;
@@ -109,6 +122,7 @@ impl<A: Access> Layer<A> for FastraceLayer {
     }
 }
 
+#[doc(hidden)]
 #[derive(Debug)]
 pub struct FastraceAccessor<A> {
     inner: A,
@@ -208,6 +222,7 @@ impl<A: Access> LayeredAccess for FastraceAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct FastraceWrapper<R> {
     span: Span,
     inner: R,
diff --git a/core/layers/hotpath/src/lib.rs b/core/layers/hotpath/src/lib.rs
index 6e29b8e2b..85daf53fb 100644
--- a/core/layers/hotpath/src/lib.rs
+++ b/core/layers/hotpath/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Hotpath layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::pin::Pin;
 use std::task::Context;
 use std::task::Poll;
@@ -65,13 +70,22 @@ const LABEL_HTTP_BODY_POLL: &str = "opendal.http.body.poll";
 /// # async fn main() -> Result<()> {
 /// let _guard = hotpath::FunctionsGuardBuilder::new("opendal").build();
 /// let op = Operator::new(services::Memory::default())?
-///     .layer(HotpathLayer)
+///     .layer(HotpathLayer::new())
 ///     .finish();
 /// op.write("test", "hello").await?;
 /// # Ok(())
 /// # }
 /// ```
-pub struct HotpathLayer;
+#[derive(Clone, Default)]
+#[non_exhaustive]
+pub struct HotpathLayer {}
+
+impl HotpathLayer {
+    /// Create a new [`HotpathLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
 
 impl<A: Access> Layer<A> for HotpathLayer {
     type LayeredAccess = HotpathAccessor<A>;
@@ -88,6 +102,7 @@ impl<A: Access> Layer<A> for HotpathLayer {
     }
 }
 
+#[doc(hidden)]
 #[derive(Debug)]
 pub struct HotpathAccessor<A> {
     inner: A,
@@ -154,6 +169,7 @@ impl<A: Access> LayeredAccess for HotpathAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct HotpathWrapper<R> {
     inner: R,
 }
@@ -207,7 +223,7 @@ impl<R: oio::Delete> oio::Delete for HotpathWrapper<R> {
     }
 }
 
-pub struct HotpathHttpFetcher {
+struct HotpathHttpFetcher {
     inner: HttpFetcher,
 }
 
@@ -221,7 +237,7 @@ impl HttpFetch for HotpathHttpFetcher {
     }
 }
 
-pub struct HotpathStream<S> {
+struct HotpathStream<S> {
     inner: S,
 }
 
diff --git a/core/layers/immutable-index/src/lib.rs 
b/core/layers/immutable-index/src/lib.rs
index 82edc5013..aae2df6fe 100644
--- a/core/layers/immutable-index/src/lib.rs
+++ b/core/layers/immutable-index/src/lib.rs
@@ -15,8 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Immutable index layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::collections::HashSet;
-use std::fmt::Debug;
 use std::vec::IntoIter;
 
 use opendal_core::raw::*;
@@ -28,7 +32,7 @@ use opendal_core::*;
 ///
 /// # Examples
 ///
-/// ```rust, no_run
+/// ```no_run
 /// # use std::collections::HashMap;
 /// #
 /// # use opendal_core::services;
@@ -37,7 +41,7 @@ use opendal_core::*;
 /// # use opendal_layer_immutable_index::ImmutableIndexLayer;
 /// #
 /// # fn main() -> Result<()> {
-/// let mut iil = ImmutableIndexLayer::default();
+/// let mut iil = ImmutableIndexLayer::new();
 ///
 /// for i in ["file", "dir/", "dir/file", "dir_without_prefix/file"] {
 ///     iil.insert(i.to_string())
@@ -49,11 +53,18 @@ use opendal_core::*;
 /// # Ok(())
 /// # }
 /// ```
-#[derive(Default, Debug, Clone)]
+#[derive(Clone, Default)]
 pub struct ImmutableIndexLayer {
     vec: Vec<String>,
 }
 
+impl ImmutableIndexLayer {
+    /// Create a new [`ImmutableIndexLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
+
 impl ImmutableIndexLayer {
     /// Insert a key into index.
     pub fn insert(&mut self, key: String) {
@@ -87,7 +98,8 @@ impl<A: Access> Layer<A> for ImmutableIndexLayer {
     }
 }
 
-#[derive(Debug, Clone)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct ImmutableIndexAccessor<A: Access> {
     inner: A,
     vec: Vec<String>,
@@ -180,6 +192,7 @@ impl<A: Access> LayeredAccess for ImmutableIndexAccessor<A> 
{
     }
 }
 
+#[doc(hidden)]
 pub struct ImmutableDir {
     idx: IntoIter<String>,
 }
diff --git a/core/layers/logging/src/lib.rs b/core/layers/logging/src/lib.rs
index 34e112fc1..47c5c2b74 100644
--- a/core/layers/logging/src/lib.rs
+++ b/core/layers/logging/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Logging layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::fmt::Debug;
 use std::fmt::Display;
 use std::sync::Arc;
@@ -105,7 +110,7 @@ use opendal_core::*;
 /// # Ok(())
 /// # }
 /// ```
-#[derive(Debug)]
+#[derive(Clone)]
 pub struct LoggingLayer<I = DefaultLoggingInterceptor> {
     logger: I,
 }
@@ -167,7 +172,7 @@ pub trait LoggingInterceptor: Debug + Clone + Send + Sync + 
Unpin + 'static {
 }
 
 /// The DefaultLoggingInterceptor will log the message by the standard logging 
macro.
-#[derive(Debug, Copy, Clone, Default)]
+#[derive(Clone, Copy, Debug, Default)]
 pub struct DefaultLoggingInterceptor;
 
 impl LoggingInterceptor for DefaultLoggingInterceptor {
@@ -229,7 +234,8 @@ impl Display for LoggingContext<'_> {
     }
 }
 
-#[derive(Clone, Debug)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct LoggingAccessor<A: Access, I: LoggingInterceptor> {
     inner: A,
 
@@ -538,6 +544,7 @@ impl<A: Access, I: LoggingInterceptor> LayeredAccess for 
LoggingAccessor<A, I> {
     }
 }
 
+#[doc(hidden)]
 pub struct LoggingReader<R, I: LoggingInterceptor> {
     info: Arc<AccessorInfo>,
     logger: I,
@@ -595,6 +602,7 @@ impl<R: oio::Read, I: LoggingInterceptor> oio::Read for 
LoggingReader<R, I> {
     }
 }
 
+#[doc(hidden)]
 pub struct LoggingWriter<W, I> {
     info: Arc<AccessorInfo>,
     logger: I,
@@ -694,6 +702,7 @@ impl<W: oio::Write, I: LoggingInterceptor> oio::Write for 
LoggingWriter<W, I> {
     }
 }
 
+#[doc(hidden)]
 pub struct LoggingLister<P, I: LoggingInterceptor> {
     info: Arc<AccessorInfo>,
     logger: I,
@@ -748,6 +757,7 @@ impl<P: oio::List, I: LoggingInterceptor> oio::List for 
LoggingLister<P, I> {
     }
 }
 
+#[doc(hidden)]
 pub struct LoggingDeleter<D, I: LoggingInterceptor> {
     info: Arc<AccessorInfo>,
     logger: I,
diff --git a/core/layers/metrics/src/lib.rs b/core/layers/metrics/src/lib.rs
index 5c12b7b17..09511cc59 100644
--- a/core/layers/metrics/src/lib.rs
+++ b/core/layers/metrics/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Metrics layer (using the [metrics](https://docs.rs/metrics/) crate) 
implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use metrics::Label;
 use metrics::counter;
 use metrics::gauge;
@@ -46,7 +51,7 @@ use opendal_layer_observe_metrics_common as observe;
 /// let _ = Operator::new(services::Memory::default())?
 ///     .layer(MetricsLayer::default())
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 ///
@@ -75,9 +80,17 @@ use opendal_layer_observe_metrics_common as observe;
 /// let (recorder, exporter) = builder.build().expect("failed to build 
recorder/exporter");
 /// let recorder = builder.build_recorder().expect("failed to build recorder");
 /// ```
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Default)]
+#[non_exhaustive]
 pub struct MetricsLayer {}
 
+impl MetricsLayer {
+    /// Create a new [`MetricsLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
+
 impl<A: Access> Layer<A> for MetricsLayer {
     type LayeredAccess = observe::MetricsAccessor<A, MetricsInterceptor>;
 
@@ -87,8 +100,9 @@ impl<A: Access> Layer<A> for MetricsLayer {
     }
 }
 
+#[doc(hidden)]
 #[derive(Clone, Debug)]
-pub struct MetricsInterceptor {}
+pub struct MetricsInterceptor;
 
 impl observe::MetricsIntercept for MetricsInterceptor {
     fn observe(&self, labels: observe::MetricLabels, value: 
observe::MetricValue) {
diff --git a/core/layers/mime-guess/src/lib.rs 
b/core/layers/mime-guess/src/lib.rs
index 6448a5e81..a7a068b4b 100644
--- a/core/layers/mime-guess/src/lib.rs
+++ b/core/layers/mime-guess/src/lib.rs
@@ -15,8 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use opendal_core::Result;
+//! MIME guess layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use opendal_core::raw::*;
+use opendal_core::*;
 
 /// A layer that can automatically set `Content-Type` based on the file 
extension in the path.
 ///
@@ -52,15 +57,22 @@ use opendal_core::raw::*;
 /// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(MimeGuessLayer::default())
+///     .layer(MimeGuessLayer::new())
 ///     .finish();
 /// # Ok(())
 /// # }
 /// ```
-#[derive(Debug, Clone, Default)]
+#[derive(Clone, Default)]
 #[non_exhaustive]
 pub struct MimeGuessLayer {}
 
+impl MimeGuessLayer {
+    /// Create a new [`MimeGuessLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
+
 impl<A: Access> Layer<A> for MimeGuessLayer {
     type LayeredAccess = MimeGuessAccessor<A>;
 
@@ -69,7 +81,8 @@ impl<A: Access> Layer<A> for MimeGuessLayer {
     }
 }
 
-#[derive(Clone, Debug)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct MimeGuessAccessor<A: Access>(A);
 
 fn mime_from_path(path: &str) -> Option<&str> {
@@ -142,9 +155,6 @@ impl<A: Access> LayeredAccess for MimeGuessAccessor<A> {
 #[cfg(test)]
 mod tests {
     use futures::TryStreamExt;
-    use opendal_core::Metadata;
-    use opendal_core::Operator;
-    use opendal_core::services::Memory;
 
     use super::*;
 
@@ -153,46 +163,35 @@ mod tests {
     const HTML: &str = "text/html";
 
     #[tokio::test]
-    async fn test_async() {
-        let op = Operator::new(Memory::default())
-            .unwrap()
-            .layer(MimeGuessLayer::default())
+    async fn test_async() -> Result<()> {
+        let op = Operator::new(services::Memory::default())?
+            .layer(MimeGuessLayer::new())
             .finish();
 
-        op.write("test0.html", DATA).await.unwrap();
-        assert_eq!(
-            op.stat("test0.html").await.unwrap().content_type(),
-            Some(HTML)
-        );
+        op.write("test0.html", DATA).await?;
+        assert_eq!(op.stat("test0.html").await?.content_type(), Some(HTML));
 
-        op.write("test1.asdfghjkl", DATA).await.unwrap();
-        assert_eq!(
-            op.stat("test1.asdfghjkl").await.unwrap().content_type(),
-            None
-        );
+        op.write("test1.asdfghjkl", DATA).await?;
+        assert_eq!(op.stat("test1.asdfghjkl").await?.content_type(), None);
 
         op.write_with("test2.html", DATA)
             .content_type(CUSTOM)
-            .await
-            .unwrap();
-        assert_eq!(
-            op.stat("test2.html").await.unwrap().content_type(),
-            Some(CUSTOM)
-        );
+            .await?;
+        assert_eq!(op.stat("test2.html").await?.content_type(), Some(CUSTOM));
 
-        let entries: Vec<Metadata> = op
+        let entries = op
             .lister_with("")
-            .await
-            .unwrap()
+            .await?
             .and_then(|entry| {
                 let op = op.clone();
                 async move { op.stat(entry.path()).await }
             })
-            .try_collect()
-            .await
-            .unwrap();
+            .try_collect::<Vec<_>>()
+            .await?;
         assert_eq!(entries[0].content_type(), Some(HTML));
         assert_eq!(entries[1].content_type(), None);
         assert_eq!(entries[2].content_type(), Some(CUSTOM));
+
+        Ok(())
     }
 }
diff --git a/core/layers/observe-metrics-common/Cargo.toml 
b/core/layers/observe-metrics-common/Cargo.toml
index 2446de6ca..2f7744fb7 100644
--- a/core/layers/observe-metrics-common/Cargo.toml
+++ b/core/layers/observe-metrics-common/Cargo.toml
@@ -31,9 +31,6 @@ version = { workspace = true }
 all-features = true
 
 [dependencies]
-futures = { version = "0.3", default-features = false, features = [
-  "std",
-  "async-await",
-] }
+futures = { workspace = true }
 http = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = 
false }
diff --git a/core/layers/observe-metrics-common/src/lib.rs 
b/core/layers/observe-metrics-common/src/lib.rs
index d03480204..caf8580eb 100644
--- a/core/layers/observe-metrics-common/src/lib.rs
+++ b/core/layers/observe-metrics-common/src/lib.rs
@@ -17,7 +17,7 @@
 
 //! OpenDAL Observability
 //!
-//! This module offers essential components to facilitate the implementation 
of observability in OpenDAL.
+//! This library offers essential components to facilitate the implementation 
of observability in OpenDAL.
 //!
 //! # OpenDAL Metrics Reference
 //!
@@ -34,9 +34,9 @@
 //! | 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        |
+//! | 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
 //!
@@ -46,13 +46,13 @@
 //! 
|----------------------------------|-----------|--------------------------------------------------------------------------------------------|-------------------------------------------------|
 //! | 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_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              |
+//! | 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
 //!
@@ -72,6 +72,9 @@
 //! * **Counter**: Cumulative metric that only increases over time (resets on 
restart)
 //! * **Gauge**: Point-in-time metric that can increase and decrease
 
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::fmt::Debug;
 use std::fmt::Formatter;
 use std::pin::Pin;
@@ -201,7 +204,7 @@ pub static LABEL_ERROR: &str = "error";
 pub static LABEL_STATUS_CODE: &str = "status_code";
 
 /// MetricLabels are the labels for the metrics.
-#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
 pub struct MetricLabels {
     /// The storage scheme identifier (e.g., "s3", "gcs", "azblob", "fs").
     /// Used to differentiate between different storage backends.
@@ -257,7 +260,7 @@ impl MetricLabels {
 /// Every metrics impls SHOULD implement observe over the MetricValue to make
 /// sure they provide the consistent metrics for users.
 #[non_exhaustive]
-#[derive(Debug, Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub enum MetricValue {
     /// Record the size of data processed in bytes.
     /// Metrics impl: Update a Histogram with the given byte count.
@@ -466,8 +469,7 @@ impl<A: Access, I: MetricsIntercept> Layer<A> for 
MetricsLayer<I> {
     }
 }
 
-/// The metrics http fetcher for opendal.
-pub struct MetricsHttpFetcher<I: MetricsIntercept> {
+struct MetricsHttpFetcher<I: MetricsIntercept> {
     inner: HttpFetcher,
     info: Arc<AccessorInfo>,
     interceptor: I,
@@ -541,7 +543,7 @@ impl<I: MetricsIntercept> HttpFetch for 
MetricsHttpFetcher<I> {
     }
 }
 
-pub struct MetricsStream<S, I> {
+struct MetricsStream<S, I> {
     inner: S,
     interceptor: I,
 
@@ -591,7 +593,7 @@ where
     }
 }
 
-/// The metrics accessor for opendal.
+#[doc(hidden)]
 pub struct MetricsAccessor<A: Access, I: MetricsIntercept> {
     inner: A,
     info: Arc<AccessorInfo>,
@@ -862,6 +864,7 @@ impl<A: Access, I: MetricsIntercept> LayeredAccess for 
MetricsAccessor<A, I> {
     }
 }
 
+#[doc(hidden)]
 pub struct MetricsWrapper<R, I: MetricsIntercept> {
     inner: R,
     interceptor: I,
diff --git a/core/layers/otelmetrics/Cargo.toml 
b/core/layers/otelmetrics/Cargo.toml
index 4a07fbbb8..ca2db89c8 100644
--- a/core/layers/otelmetrics/Cargo.toml
+++ b/core/layers/otelmetrics/Cargo.toml
@@ -32,7 +32,7 @@ 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 }
+opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", 
version = "0.55.0" }
 opentelemetry = { version = "0.31.0", default-features = false, features = [
   "metrics",
 ] }
diff --git a/core/layers/otelmetrics/src/lib.rs 
b/core/layers/otelmetrics/src/lib.rs
index b52602631..26c5f673e 100644
--- a/core/layers/otelmetrics/src/lib.rs
+++ b/core/layers/otelmetrics/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! OpenTelemetry metrics layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use opendal_core::raw::*;
 use opendal_layer_observe_metrics_common as observe;
 use opentelemetry::KeyValue;
@@ -41,7 +46,7 @@ use opentelemetry::metrics::UpDownCounter;
 /// # Ok(())
 /// # }
 /// ```
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct OtelMetricsLayer {
     interceptor: OtelMetricsInterceptor,
 }
@@ -339,6 +344,7 @@ impl<A: Access> Layer<A> for OtelMetricsLayer {
     }
 }
 
+#[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct OtelMetricsInterceptor {
     operation_bytes: Histogram<u64>,
diff --git a/core/layers/oteltrace/src/lib.rs b/core/layers/oteltrace/src/lib.rs
index 570a74d2a..170e1f270 100644
--- a/core/layers/oteltrace/src/lib.rs
+++ b/core/layers/oteltrace/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! OpenTelemetry trace layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::future::Future;
 use std::sync::Arc;
 
@@ -43,12 +48,21 @@ use opentelemetry::trace::Tracer;
 /// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(OtelTraceLayer)
+///     .layer(OtelTraceLayer::new())
 ///     .finish();
 /// # Ok(())
 /// # }
 /// ```
-pub struct OtelTraceLayer;
+#[derive(Clone, Default)]
+#[non_exhaustive]
+pub struct OtelTraceLayer {}
+
+impl OtelTraceLayer {
+    /// Create a new [`OtelTraceLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
 
 impl<A: Access> Layer<A> for OtelTraceLayer {
     type LayeredAccess = OtelTraceAccessor<A>;
@@ -58,6 +72,7 @@ impl<A: Access> Layer<A> for OtelTraceLayer {
     }
 }
 
+#[doc(hidden)]
 #[derive(Debug)]
 pub struct OtelTraceAccessor<A> {
     inner: A,
@@ -164,6 +179,7 @@ impl<A: Access> LayeredAccess for OtelTraceAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct OtelTraceWrapper<R> {
     _span: BoxedSpan,
     inner: R,
diff --git a/core/layers/prometheus-client/Cargo.toml 
b/core/layers/prometheus-client/Cargo.toml
index e52043a5e..50d7cdf3c 100644
--- a/core/layers/prometheus-client/Cargo.toml
+++ b/core/layers/prometheus-client/Cargo.toml
@@ -32,7 +32,7 @@ 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 }
+opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", 
version = "0.55.0" }
 prometheus-client = { version = "0.24" }
 
 [dev-dependencies]
diff --git a/core/layers/prometheus-client/src/lib.rs 
b/core/layers/prometheus-client/src/lib.rs
index 85f31848b..1b5841d8b 100644
--- a/core/layers/prometheus-client/src/lib.rs
+++ b/core/layers/prometheus-client/src/lib.rs
@@ -15,10 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt;
+//! Metrics layer (using the 
[prometheus-client](https://docs.rs/prometheus-client) crate) implementation 
for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
 
 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;
@@ -43,11 +45,11 @@ use prometheus_client::registry::Unit;
 ///
 /// ```no_run
 /// # use log::info;
-/// # use opendal_layer_prometheus_client::PrometheusClientLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_prometheus_client::PrometheusClientLayer;
+/// #
 /// # #[tokio::main]
 /// # async fn main() -> Result<()> {
 /// let mut registry = prometheus_client::registry::Registry::default();
@@ -74,7 +76,7 @@ use prometheus_client::registry::Unit;
 /// # Ok(())
 /// # }
 /// ```
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct PrometheusClientLayer {
     interceptor: PrometheusClientInterceptor,
 }
@@ -180,11 +182,11 @@ impl PrometheusClientLayerBuilder {
     /// # Example
     ///
     /// ```no_run
-    /// # use opendal_layer_prometheus_client::PrometheusClientLayer;
     /// # use opendal_core::services;
     /// # use opendal_core::Operator;
     /// # use opendal_core::Result;
-    ///
+    /// # use opendal_layer_prometheus_client::PrometheusClientLayer;
+    /// #
     /// # #[tokio::main]
     /// # async fn main() -> Result<()> {
     /// // Pick a builder and configure it.
@@ -378,6 +380,7 @@ impl MetricConstructor<Histogram> for HistogramConstructor {
     }
 }
 
+#[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct PrometheusClientInterceptor {
     operation_bytes: Family<OperationLabels, Histogram, HistogramConstructor>,
@@ -488,7 +491,7 @@ struct OperationLabels {
 }
 
 impl EncodeLabelSet for OperationLabels {
-    fn encode(&self, encoder: &mut LabelSetEncoder<'_>) -> Result<(), 
fmt::Error> {
+    fn encode(&self, encoder: &mut LabelSetEncoder<'_>) -> std::fmt::Result {
         (observe::LABEL_SCHEME, 
self.labels.scheme).encode(encoder.encode_label())?;
         (observe::LABEL_NAMESPACE, self.labels.namespace.as_ref())
             .encode(encoder.encode_label())?;
diff --git a/core/layers/prometheus/Cargo.toml 
b/core/layers/prometheus/Cargo.toml
index 28ff38674..9482fc3bf 100644
--- a/core/layers/prometheus/Cargo.toml
+++ b/core/layers/prometheus/Cargo.toml
@@ -32,7 +32,7 @@ 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 }
+opendal-layer-observe-metrics-common = { path = "../observe-metrics-common", 
version = "0.55.0" }
 prometheus = { version = "0.14", features = ["process"] }
 
 [dev-dependencies]
diff --git a/core/layers/prometheus/src/lib.rs 
b/core/layers/prometheus/src/lib.rs
index b1c6fe027..81680c99f 100644
--- a/core/layers/prometheus/src/lib.rs
+++ b/core/layers/prometheus/src/lib.rs
@@ -15,7 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use opendal_core::raw::Access;
+//! Metrics layer (using the [prometheus](https://docs.rs/prometheus) crate) 
implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use opendal_core::raw::*;
 use opendal_core::*;
 use opendal_layer_observe_metrics_common as observe;
@@ -45,8 +49,8 @@ use prometheus::register_int_gauge_vec_with_registry;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-/// # use prometheus::Encoder;
 /// # use opendal_layer_prometheus::PrometheusLayer;
+/// # use prometheus::Encoder;
 /// #
 /// # #[tokio::main]
 /// # async fn main() -> Result<()> {
@@ -92,13 +96,14 @@ use prometheus::register_int_gauge_vec_with_registry;
 ///
 /// ```no_run
 /// # use std::sync::OnceLock;
+/// #
 /// # use log::info;
-/// # use opendal_layer_prometheus::PrometheusLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
+/// # use opendal_layer_prometheus::PrometheusLayer;
 /// # use prometheus::Encoder;
-///
+/// #
 /// fn global_prometheus_layer() -> &'static PrometheusLayer {
 ///     static GLOBAL: OnceLock<PrometheusLayer> = OnceLock::new();
 ///     GLOBAL.get_or_init(|| {
@@ -134,7 +139,7 @@ use prometheus::register_int_gauge_vec_with_registry;
 /// # Ok(())
 /// # }
 /// ```
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct PrometheusLayer {
     interceptor: PrometheusInterceptor,
 }
@@ -145,10 +150,10 @@ impl PrometheusLayer {
     /// # Example
     ///
     /// ```no_run
-    /// # use opendal_layer_prometheus::PrometheusLayer;
     /// # use opendal_core::services;
     /// # use opendal_core::Operator;
     /// # use opendal_core::Result;
+    /// # use opendal_layer_prometheus::PrometheusLayer;
     /// #
     /// # #[tokio::main]
     /// # async fn main() -> Result<()> {
@@ -260,10 +265,10 @@ impl PrometheusLayerBuilder {
     /// # Example
     ///
     /// ```no_run
-    /// # use opendal_layer_prometheus::PrometheusLayer;
     /// # use opendal_core::services;
     /// # use opendal_core::Operator;
     /// # use opendal_core::Result;
+    /// # use opendal_layer_prometheus::PrometheusLayer;
     /// #
     /// # #[tokio::main]
     /// # async fn main() -> Result<()> {
@@ -498,10 +503,10 @@ impl PrometheusLayerBuilder {
     /// # Example
     ///
     /// ```no_run
-    /// # use opendal_layer_prometheus::PrometheusLayer;
     /// # use opendal_core::services;
     /// # use opendal_core::Operator;
     /// # use opendal_core::Result;
+    /// # use opendal_layer_prometheus::PrometheusLayer;
     /// #
     /// # #[tokio::main]
     /// # async fn main() -> Result<()> {
@@ -528,6 +533,7 @@ fn parse_prometheus_error(err: prometheus::Error) -> Error {
     Error::new(ErrorKind::Unexpected, err.to_string()).set_source(err)
 }
 
+#[doc(hidden)]
 #[derive(Clone, Debug)]
 pub struct PrometheusInterceptor {
     operation_bytes: HistogramVec,
diff --git a/core/layers/retry/Cargo.toml b/core/layers/retry/Cargo.toml
index 03c0a0b34..dffaafade 100644
--- a/core/layers/retry/Cargo.toml
+++ b/core/layers/retry/Cargo.toml
@@ -37,10 +37,10 @@ opendal-core = { path = "../../core", version = "0.55.0", 
default-features = fal
 
 [dev-dependencies]
 bytes = { workspace = true }
-futures = { workspace = true, default-features = true }
+futures = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0" }
-opendal-layer-logging = { path = "../logging", version = "0.55.0", 
default-features = false }
-opendal-layer-timeout = { path = "../timeout", version = "0.55.0", 
default-features = false }
+opendal-layer-logging = { path = "../logging", version = "0.55.0" }
+opendal-layer-timeout = { path = "../timeout", version = "0.55.0" }
 tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
 tracing-subscriber = { version = "0.3", features = [
   "env-filter",
diff --git a/core/layers/retry/src/lib.rs b/core/layers/retry/src/lib.rs
index 1ba9e5864..4ffeafc2f 100644
--- a/core/layers/retry/src/lib.rs
+++ b/core/layers/retry/src/lib.rs
@@ -15,8 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Retry layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::fmt::Debug;
-use std::fmt::Formatter;
 use std::sync::Arc;
 
 use backon::ExponentialBuilder;
@@ -56,10 +60,10 @@ use opendal_core::*;
 /// # fn main() -> Result<()> {
 /// let op = Operator::new(services::Memory::default())?
 ///     // This is fine, since timeout happen during retry.
-///     .layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
-///     .layer(RetryLayer::new())
+///     
.layer(TimeoutLayer::default().with_io_timeout(Duration::from_nanos(1)))
+///     .layer(RetryLayer::default())
 ///     // This is wrong. Since timeout layer will drop future, leaving retry 
layer in a bad state.
-///     .layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
+///     
.layer(TimeoutLayer::default().with_io_timeout(Duration::from_nanos(1)))
 ///     .finish();
 /// # Ok(())
 /// # }
@@ -75,7 +79,7 @@ use opendal_core::*;
 /// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(RetryLayer::new())
+///     .layer(RetryLayer::default())
 ///     .finish();
 /// # Ok(())
 /// # }
@@ -106,7 +110,7 @@ use opendal_core::*;
 ///
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(RetryLayer::new().with_notify(MyRetryInterceptor))
+///     .layer(RetryLayer::default().with_notify(MyRetryInterceptor))
 ///     .finish();
 /// # Ok(())
 /// # }
@@ -135,18 +139,7 @@ impl Default for RetryLayer {
 }
 
 impl RetryLayer {
-    /// Create a new retry layer.
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use opendal_core::services;
-    /// use opendal_core::Operator;
-    /// use opendal_layer_retry::RetryLayer;
-    ///
-    /// let _ = Operator::new(services::Memory::default())
-    ///     .expect("must init")
-    ///     .layer(RetryLayer::new());
-    /// ```
+    /// Create a new [`RetryLayer`].
     pub fn new() -> RetryLayer {
         Self::default()
     }
@@ -164,7 +157,7 @@ impl<I: RetryInterceptor> RetryLayer<I> {
     ///
     /// let _ = Operator::new(services::Memory::default())
     ///     .expect("must init")
-    ///     .layer(RetryLayer::new().with_notify(notify))
+    ///     .layer(RetryLayer::default().with_notify(notify))
     ///     .finish();
     /// ```
     pub fn with_notify<NI: RetryInterceptor>(self, notify: NI) -> 
RetryLayer<NI> {
@@ -269,6 +262,7 @@ impl RetryInterceptor for DefaultRetryInterceptor {
     }
 }
 
+#[doc(hidden)]
 pub struct RetryAccessor<A: Access, I: RetryInterceptor> {
     inner: Arc<A>,
     builder: ExponentialBuilder,
@@ -276,7 +270,7 @@ pub struct RetryAccessor<A: Access, I: RetryInterceptor> {
 }
 
 impl<A: Access, I: RetryInterceptor> Debug for RetryAccessor<A, I> {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("RetryAccessor")
             .field("inner", &self.inner)
             .finish_non_exhaustive()
@@ -375,6 +369,7 @@ impl<A: Access, I: RetryInterceptor> LayeredAccess for 
RetryAccessor<A, I> {
     }
 }
 
+#[doc(hidden)]
 pub struct RetryReader<A, R> {
     inner: Arc<A>,
     reader: Option<R>,
@@ -415,6 +410,7 @@ impl<A: Access> oio::Read for RetryReader<A, A::Reader> {
     }
 }
 
+#[doc(hidden)]
 pub struct RetryWrapper<R, I> {
     inner: Option<R>,
     notify: Arc<I>,
@@ -840,20 +836,19 @@ mod tests {
     }
 
     #[tokio::test]
-    async fn test_retry_read() {
+    async fn test_retry_read() -> Result<()> {
         let _ = tracing_subscriber::fmt()
             .with_max_level(LevelFilter::TRACE)
             .with_test_writer()
             .try_init();
 
         let builder = MockBuilder::default();
-        let op = Operator::new(builder.clone())
-            .unwrap()
+        let op = Operator::new(builder.clone())?
             .layer(LoggingLayer::default())
-            .layer(RetryLayer::new())
+            .layer(RetryLayer::default())
             .finish();
 
-        let r = op.reader("retryable_error").await.unwrap();
+        let r = op.reader("retryable_error").await?;
         let mut content = Vec::new();
         let size = r
             .read_into(&mut content, ..)
@@ -863,49 +858,49 @@ mod tests {
         assert_eq!(content, "Hello, World!".as_bytes());
         // The error is retryable, we should request it 3 times.
         assert_eq!(*builder.attempt.lock().unwrap(), 5);
+        Ok(())
     }
 
     /// This test is used to reproduce the panic issue while composing retry 
layer with timeout layer.
     #[tokio::test]
-    async fn test_retry_write_fail_on_close() {
+    async fn test_retry_write_fail_on_close() -> Result<()> {
         let _ = tracing_subscriber::fmt()
             .with_max_level(LevelFilter::TRACE)
             .with_test_writer()
             .try_init();
 
         let builder = MockBuilder::default();
-        let op = Operator::new(builder.clone())
-            .unwrap()
+        let op = Operator::new(builder.clone())?
             .layer(
-                RetryLayer::new()
+                RetryLayer::default()
                     .with_min_delay(Duration::from_millis(1))
                     .with_max_delay(Duration::from_millis(1))
                     .with_jitter(),
             )
             // Uncomment this to reproduce timeout layer panic.
-            // 
.layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
+            // 
.layer(TimeoutLayer::default().with_io_timeout(Duration::from_nanos(1)))
             .layer(LoggingLayer::default())
             .finish();
 
-        let mut w = op.writer("test_write").await.unwrap();
-        w.write("aaa").await.unwrap();
-        w.write("bbb").await.unwrap();
+        let mut w = op.writer("test_write").await?;
+        w.write("aaa").await?;
+        w.write("bbb").await?;
         match w.close().await {
             Ok(_) => (),
             Err(_) => {
-                w.abort().await.unwrap();
+                w.abort().await?;
             }
         };
+        Ok(())
     }
 
     #[tokio::test]
-    async fn test_retry_list() {
+    async fn test_retry_list() -> Result<()> {
         let _ = tracing_subscriber::fmt().with_test_writer().try_init();
 
         let builder = MockBuilder::default();
-        let op = Operator::new(builder.clone())
-            .unwrap()
-            .layer(RetryLayer::new())
+        let op = Operator::new(builder.clone())?
+            .layer(RetryLayer::default())
             .finish();
 
         let expected = vec!["hello", "world", "2023/", "0208/"];
@@ -920,25 +915,26 @@ mod tests {
         }
 
         assert_eq!(actual, expected);
+        Ok(())
     }
 
     #[tokio::test]
-    async fn test_retry_batch() {
+    async fn test_retry_batch() -> Result<()> {
         let _ = tracing_subscriber::fmt().with_test_writer().try_init();
 
         let builder = MockBuilder::default();
         // set to a lower delay to make it run faster
-        let op = Operator::new(builder.clone())
-            .unwrap()
+        let op = Operator::new(builder.clone())?
             .layer(
-                RetryLayer::new()
+                RetryLayer::default()
                     .with_min_delay(Duration::from_secs_f32(0.1))
                     .with_max_times(5),
             )
             .finish();
 
         let paths = vec!["hello", "world", "test", "batch"];
-        op.delete_stream(stream::iter(paths)).await.unwrap();
+        op.delete_stream(stream::iter(paths)).await?;
         assert_eq!(*builder.attempt.lock().unwrap(), 5);
+        Ok(())
     }
 }
diff --git a/core/layers/tail-cut/src/lib.rs b/core/layers/tail-cut/src/lib.rs
index 3ecaedbaa..fd473ac3b 100644
--- a/core/layers/tail-cut/src/lib.rs
+++ b/core/layers/tail-cut/src/lib.rs
@@ -15,8 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Tail cut layer (that automatically cancels long-tail requests) 
implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::fmt::Debug;
-use std::fmt::Formatter;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
 
@@ -74,7 +78,7 @@ impl Default for TailCutLayerBuilder {
 }
 
 impl TailCutLayerBuilder {
-    /// Create a new builder with default settings.
+    /// Create a new [`TailCutLayerBuilder`] with default settings.
     pub fn new() -> Self {
         Self::default()
     }
@@ -263,23 +267,23 @@ pub struct TailCutLayer {
     stats: Arc<TailCutStats>,
 }
 
+impl Default for TailCutLayer {
+    fn default() -> Self {
+        Self::builder().build()
+    }
+}
+
 impl TailCutLayer {
-    /// Create a builder to configure the layer.
+    /// Create a new [`TailCutLayerBuilder`] to configure the layer.
     pub fn builder() -> TailCutLayerBuilder {
-        TailCutLayerBuilder::new()
+        TailCutLayerBuilder::default()
     }
 
-    /// Create a layer with default settings.
+    /// Create a new [`TailCutLayer`].
     ///
     /// This is equivalent to `TailCutLayer::builder().build()`.
     pub fn new() -> Self {
-        Self::builder().build()
-    }
-}
-
-impl Default for TailCutLayer {
-    fn default() -> Self {
-        Self::new()
+        Self::default()
     }
 }
 
@@ -295,8 +299,7 @@ impl<A: Access> Layer<A> for TailCutLayer {
     }
 }
 
-/// Accessor that implements tail cut logic.
-#[derive(Clone)]
+#[doc(hidden)]
 pub struct TailCutAccessor<A: Access> {
     inner: A,
     config: Arc<TailCutConfig>,
@@ -304,7 +307,7 @@ pub struct TailCutAccessor<A: Access> {
 }
 
 impl<A: Access> Debug for TailCutAccessor<A> {
-    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("TailCutAccessor")
             .field("config", &self.config)
             .finish_non_exhaustive()
@@ -441,7 +444,7 @@ impl<A: Access> LayeredAccess for TailCutAccessor<A> {
     }
 }
 
-/// Wrapper for IO operations (Reader, Writer, Lister, Deleter).
+#[doc(hidden)]
 pub struct TailCutWrapper<R> {
     inner: R,
     size: Option<u64>,
diff --git a/core/layers/throttle/Cargo.toml b/core/layers/throttle/Cargo.toml
index 89e322184..03e72dc7b 100644
--- a/core/layers/throttle/Cargo.toml
+++ b/core/layers/throttle/Cargo.toml
@@ -31,7 +31,7 @@ version = { workspace = true }
 all-features = true
 
 [dependencies]
-governor = { version = "0.10.1", features = ["std"] }
+governor = "0.10.1"
 opendal-core = { path = "../../core", version = "0.55.0", default-features = 
false }
 
 [dev-dependencies]
diff --git a/core/layers/throttle/src/lib.rs b/core/layers/throttle/src/lib.rs
index 2127855f7..3e8d7b644 100644
--- a/core/layers/throttle/src/lib.rs
+++ b/core/layers/throttle/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Throttle layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::num::NonZeroU32;
 use std::sync::Arc;
 
@@ -24,7 +29,6 @@ use governor::clock::DefaultClock;
 use governor::middleware::NoOpMiddleware;
 use governor::state::InMemoryState;
 use governor::state::NotKeyed;
-
 use opendal_core::raw::*;
 use opendal_core::*;
 
@@ -49,17 +53,17 @@ use opendal_core::*;
 /// This example limits bandwidth to 10 KiB/s and burst size to 10 MiB.
 ///
 /// ```no_run
-/// # use opendal_layer_throttle::ThrottleLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_throttle::ThrottleLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())
 ///     .expect("must init")
 ///     .layer(ThrottleLayer::new(10 * 1024, 10000 * 1024))
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 #[derive(Clone)]
@@ -86,12 +90,12 @@ impl ThrottleLayer {
 impl<A: Access> Layer<A> for ThrottleLayer {
     type LayeredAccess = ThrottleAccessor<A>;
 
-    fn layer(&self, accessor: A) -> Self::LayeredAccess {
+    fn layer(&self, inner: A) -> Self::LayeredAccess {
         let rate_limiter = Arc::new(RateLimiter::direct(
             Quota::per_second(self.bandwidth).allow_burst(self.burst),
         ));
         ThrottleAccessor {
-            inner: accessor,
+            inner,
             rate_limiter,
         }
     }
@@ -102,7 +106,8 @@ impl<A: Access> Layer<A> for ThrottleLayer {
 /// Read more about 
[Middleware](https://docs.rs/governor/latest/governor/middleware/index.html)
 type SharedRateLimiter = Arc<RateLimiter<NotKeyed, InMemoryState, 
DefaultClock, NoOpMiddleware>>;
 
-#[derive(Debug, Clone)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct ThrottleAccessor<A: Access> {
     inner: A,
     rate_limiter: SharedRateLimiter,
@@ -146,13 +151,14 @@ impl<A: Access> LayeredAccess for ThrottleAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct ThrottleWrapper<R> {
     inner: R,
     limiter: SharedRateLimiter,
 }
 
 impl<R> ThrottleWrapper<R> {
-    pub fn new(inner: R, rate_limiter: SharedRateLimiter) -> Self {
+    fn new(inner: R, rate_limiter: SharedRateLimiter) -> Self {
         Self {
             inner,
             limiter: rate_limiter,
diff --git a/core/layers/timeout/Cargo.toml b/core/layers/timeout/Cargo.toml
index 20099fb22..ae581e9e8 100644
--- a/core/layers/timeout/Cargo.toml
+++ b/core/layers/timeout/Cargo.toml
@@ -37,5 +37,5 @@ tokio = { workspace = true, features = ["time"] }
 [dev-dependencies]
 futures = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0" }
-opendal-layer-retry = { path = "../retry", version = "0.55.0", 
default-features = false }
+opendal-layer-retry = { path = "../retry", version = "0.55.0" }
 tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
diff --git a/core/layers/timeout/src/lib.rs b/core/layers/timeout/src/lib.rs
index dc6c881c3..2cd56bf70 100644
--- a/core/layers/timeout/src/lib.rs
+++ b/core/layers/timeout/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Timeout layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::future::Future;
 use std::sync::Arc;
 use std::time::Duration;
@@ -63,10 +68,10 @@ use opendal_core::*;
 /// # fn main() -> Result<()> {
 /// let op = Operator::new(services::Memory::default())?
 ///     // This is fine, since timeout happen during retry.
-///     .layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
-///     .layer(RetryLayer::new())
+///     
.layer(TimeoutLayer::default().with_io_timeout(Duration::from_nanos(1)))
+///     .layer(RetryLayer::default())
 ///     // This is wrong. Since timeout layer will drop future, leaving retry 
layer in a bad state.
-///     .layer(TimeoutLayer::new().with_io_timeout(Duration::from_nanos(1)))
+///     
.layer(TimeoutLayer::default().with_io_timeout(Duration::from_nanos(1)))
 ///     .finish();
 /// # Ok(())
 /// # }
@@ -127,7 +132,7 @@ impl Default for TimeoutLayer {
 }
 
 impl TimeoutLayer {
-    /// Create a new `TimeoutLayer` with default settings.
+    /// Create a new [`TimeoutLayer`] with default settings.
     pub fn new() -> Self {
         Self::default()
     }
@@ -167,7 +172,8 @@ impl<A: Access> Layer<A> for TimeoutLayer {
     }
 }
 
-#[derive(Debug, Clone)]
+#[doc(hidden)]
+#[derive(Debug)]
 pub struct TimeoutAccessor<A: Access> {
     inner: A,
 
@@ -262,13 +268,13 @@ impl<A: Access> LayeredAccess for TimeoutAccessor<A> {
     }
 }
 
-pub struct TimeoutExecutor {
+struct TimeoutExecutor {
     exec: Arc<dyn Execute>,
     timeout: Duration,
 }
 
 impl TimeoutExecutor {
-    pub fn new(exec: Arc<dyn Execute>, timeout: Duration) -> Self {
+    fn new(exec: Arc<dyn Execute>, timeout: Duration) -> Self {
         Self { exec, timeout }
     }
 }
@@ -283,6 +289,7 @@ impl Execute for TimeoutExecutor {
     }
 }
 
+#[doc(hidden)]
 pub struct TimeoutWrapper<R> {
     inner: R,
 
@@ -353,12 +360,9 @@ impl<R: oio::Delete> oio::Delete for TimeoutWrapper<R> {
 
 #[cfg(test)]
 mod tests {
-    use std::future::Future;
     use std::future::pending;
 
     use futures::StreamExt;
-    use opendal_core::raw::*;
-    use opendal_core::*;
     use tokio::time::sleep;
     use tokio::time::timeout;
 
@@ -423,7 +427,7 @@ mod tests {
     async fn test_operation_timeout() {
         let srv = MockService;
         let op = Operator::from_inner(Arc::new(srv))
-            .layer(TimeoutLayer::new().with_timeout(Duration::from_secs(1)));
+            
.layer(TimeoutLayer::default().with_timeout(Duration::from_secs(1)));
 
         let fut = async {
             let res = op.delete("test").await;
@@ -442,7 +446,7 @@ mod tests {
     async fn test_io_timeout() {
         let srv = MockService;
         let op = Operator::from_inner(Arc::new(srv))
-            
.layer(TimeoutLayer::new().with_io_timeout(Duration::from_secs(1)));
+            
.layer(TimeoutLayer::default().with_io_timeout(Duration::from_secs(1)));
 
         let reader = op.reader("test").await.unwrap();
 
@@ -457,7 +461,7 @@ mod tests {
     async fn test_list_timeout() {
         let srv = MockService;
         let op = Operator::from_inner(Arc::new(srv)).layer(
-            TimeoutLayer::new()
+            TimeoutLayer::default()
                 .with_timeout(Duration::from_secs(1))
                 .with_io_timeout(Duration::from_secs(1)),
         );
@@ -476,7 +480,7 @@ mod tests {
         use oio::List;
 
         let acc = MockService;
-        let timeout_layer = TimeoutLayer::new()
+        let timeout_layer = TimeoutLayer::default()
             .with_timeout(Duration::from_secs(1))
             .with_io_timeout(Duration::from_secs(1));
         let timeout_acc = timeout_layer.layer(acc);
diff --git a/core/layers/tracing/src/lib.rs b/core/layers/tracing/src/lib.rs
index e7fadf54f..01139944d 100644
--- a/core/layers/tracing/src/lib.rs
+++ b/core/layers/tracing/src/lib.rs
@@ -15,6 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+//! Tracing layer implementation for Apache OpenDAL.
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(missing_docs)]
+
 use std::fmt::Debug;
 use std::pin::Pin;
 use std::task::Context;
@@ -22,13 +27,12 @@ use std::task::Poll;
 
 use futures::Stream;
 use futures::StreamExt;
+use opendal_core::raw::*;
+use opendal_core::*;
 use tracing::Level;
 use tracing::Span;
 use tracing::span;
 
-use opendal_core::raw::*;
-use opendal_core::*;
-
 /// Add [tracing](https://docs.rs/tracing/) for every operation.
 ///
 /// # Examples
@@ -36,16 +40,16 @@ use opendal_core::*;
 /// ## Basic Setup
 ///
 /// ```no_run
-/// # use opendal_layer_tracing::TracingLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
 /// # use opendal_core::Result;
-///
+/// # use opendal_layer_tracing::TracingLayer;
+/// #
 /// # fn main() -> Result<()> {
 /// let _ = Operator::new(services::Memory::default())?
-///     .layer(TracingLayer)
+///     .layer(TracingLayer::new())
 ///     .finish();
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 ///
@@ -53,15 +57,15 @@ use opendal_core::*;
 ///
 /// ```no_run
 /// # use anyhow::Result;
-/// # use opendal_layer_tracing::TracingLayer;
 /// # use opendal_core::services;
 /// # use opendal_core::Operator;
+/// # use opendal_layer_tracing::TracingLayer;
 /// # use opentelemetry::KeyValue;
 /// # use opentelemetry_sdk::trace;
 /// # use opentelemetry_sdk::Resource;
 /// # use tracing_subscriber::prelude::*;
 /// # use tracing_subscriber::EnvFilter;
-///
+/// #
 /// # fn main() -> Result<()> {
 /// use opentelemetry::trace::TracerProvider;
 /// let tracer_provider = 
opentelemetry_sdk::trace::SdkTracerProvider::builder()
@@ -92,7 +96,7 @@ use opendal_core::*;
 ///
 ///         let _ = dotenvy::dotenv();
 ///         let op = Operator::new(services::Memory::default())?
-///             .layer(TracingLayer)
+///             .layer(TracingLayer::new())
 ///             .finish();
 ///
 ///         op.write("test", "0".repeat(16 * 1024 * 1024).into_bytes())
@@ -107,8 +111,7 @@ use opendal_core::*;
 /// // This will invoke the shutdown method on all span processors.
 /// // span processors should export remaining spans before return.
 /// tracer_provider.shutdown()?;
-///
-/// Ok(())
+/// # Ok(())
 /// # }
 /// ```
 ///
@@ -128,7 +131,7 @@ use opendal_core::*;
 /// # use tracing::span::Id;
 /// # use tracing::span::Record;
 /// # use tracing::subscriber::Subscriber;
-///
+/// #
 /// # pub struct FooSubscriber;
 /// # impl Subscriber for FooSubscriber {
 /// #   fn enabled(&self, _: &Metadata) -> bool { false }
@@ -146,7 +149,16 @@ use opendal_core::*;
 /// ```
 ///
 /// For real-world usage, please take a look at 
[`tracing-opentelemetry`](https://crates.io/crates/tracing-opentelemetry).
-pub struct TracingLayer;
+#[derive(Clone, Default)]
+#[non_exhaustive]
+pub struct TracingLayer {}
+
+impl TracingLayer {
+    /// Create a new [`TracingLayer`].
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
 
 impl<A: Access> Layer<A> for TracingLayer {
     type LayeredAccess = TracingAccessor<A>;
@@ -165,7 +177,7 @@ impl<A: Access> Layer<A> for TracingLayer {
     }
 }
 
-pub struct TracingHttpFetcher {
+struct TracingHttpFetcher {
     inner: HttpFetcher,
 }
 
@@ -184,7 +196,7 @@ impl HttpFetch for TracingHttpFetcher {
     }
 }
 
-pub struct TracingStream<S> {
+struct TracingStream<S> {
     inner: S,
     span: Span,
 }
@@ -201,6 +213,7 @@ where
     }
 }
 
+#[doc(hidden)]
 #[derive(Debug)]
 pub struct TracingAccessor<A> {
     inner: A,
@@ -287,6 +300,7 @@ impl<A: Access> LayeredAccess for TracingAccessor<A> {
     }
 }
 
+#[doc(hidden)]
 pub struct TracingWrapper<R> {
     span: Span,
     inner: R,

Reply via email to