Skip to main content

sentinel_core/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3
4//! # Sentinel in Rust
5//!
6//! Sentinel takes "flow" as breakthrough point, and works on multiple fields including **flow control**,
7//! **traffic shaping**, **circuit breaking** and **system adaptive protection**,
8//! to guarantee reliability and resilience for microservices.
9//!
10//! Sentinel adopts Chain-of-Responsibility pattern. The user-defined rules will be automatically checked via slots in `base::SlotChain`.
11//! Generally, there are several steps when using Sentienl:
12//! 1. Add dependancy and initialize configurations on Sentinel.
13//! 2. Define a resource to be protected and build Sentinel entry.
14//! 3. Load the rules defined for each resource.
15//! 4. Write the codes at entry and exit points.
16//!
17//! Thorough examples have been provided in our [repository](https://github.com/sentinel-group/sentinel-rust).
18//!
19//! ## Add Dependency
20//!
21//! Add the dependency in `Cargo.toml`:
22//!
23//! ```toml
24//! [dependencies]
25//! sentinel-core = { version = "0.1.0", features = ["full"] }
26//! ```
27//!
28//! Optional features lists:
29//! - macro:Support procedural macro, simplify the resource and rule definitions, refer to [example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/rules/flow/macro.rs).
30//! - async:Support asynchronous resources, refer to [example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/rules/flow/tokio.rs).
31//! - exporter:Export metric statistics to Prometheus, refer to [example](https://github.com/sentinel-group/sentinel-rust/tree/main/examples/exporter/prometheus) and [Sentinel Prometheus Metrics Definitions](https://github.com/sentinel-group/sentinel-rust/blob/main/sentinel-core/src/exporter.rs).
32//! - logger_env: Use `env_logger` to initialize logging.
33//! - logger_log4rs: Use `log4rs` to initialize logging.
34//! - ds_consul: Use [Consul](https://www.consul.io/) to configure rules dynamically.
35//! - ds_etcdv3:Use [etcd](https://etcd.io/) to configure rules dynamically.
36//! - ds_k8s:Use k8s to configure rules dynamically.
37//! - metric_log: Store formatted logs on Sentinel resources.
38//!
39//! ## General Configurations and Initialization
40//!
41//! Sentinel needs to be initialized. The `api` module provides following interfaces:
42//!
43//! - `init_default()`: Load configurations from environment variable. For undefined configurations, use default values.
44//! - `init_with_config_file(config_path: &mut String)`: Load configurations from a YAML file, refer to [example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/config/from_yaml/from_yaml.rs)。。
45//! - `init_with_config(config_entity: ConfigEntity)`: Use hand-crafted `ConfigEntity` to initialize Sentinel,refer to [example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/config/from_entity/from_entity.rs)。。
46//!
47//!
48//! Example:
49//!
50//! ```rust
51//! use sentinel_rs::{init_default, logging};
52//! init_default().unwrap_or_else(|err| logging::error!("{:?}", err));
53//! ```
54//!
55//! ## Resouce Definition
56//!
57//! A snippet of codes is regarded as resources in Sentinel, which can be protected by defining their entries.
58//!
59//! By constructing `EntryBuilder` and calling the `build()` method, we create `Entry`.
60//!
61//! Example:
62//!
63//! If the calling is blocked, `build()` will return an error.
64//!
65//! ```rust
66//! use sentinel_core::base;
67//! use sentinel_core::api::EntryBuilder;
68//! let entry_builder = EntryBuilder::new(res_name.clone())
69//! 	.with_traffic_type(base::TrafficType::Inbound);
70//! if let Ok(entry) = entry_builder.build() {
71//! 	// The request is allowed to be processed.
72//! 	// after finish the logic, exit the entry.
73//!     entry.borrow().exit()
74//! } else {
75//! 	// The request is blocked.
76//! 	// you do not need to call `exit()` on entry now.
77//! }
78//! ```
79//!
80//! ## Load Sentinel Rules
81//!
82//! ### Manually Create Sentinel Entry and Load Rules
83//!
84//! Sentinel supports loading hand-crafted rules.
85//! The method `load_rules()` will overload all of the rules defined before.
86//! The method `append_rules()` will append rules incrementally.
87//! Currently, this is the only way to define several rules for a single resource.
88//! For example:
89//!  
90//! ```rust
91//! flow::load_rules(vec![Arc::new(flow::Rule {
92//!     resource: "example".into(),
93//!     threshold: 10.0,
94//!     calculate_strategy: flow::CalculateStrategy::Direct,
95//!     control_strategy: flow::ControlStrategy::Reject,
96//!     ..Default::default()
97//! })]);
98//! ```
99//!
100//! ### Via Attribute-Like Macros
101//! We also provide macros to help you define Sentinel resources and load rules easily:
102//!
103//! ```rust
104//! #[flow(threshold=10.0, calculate_strategy=Direct)]
105//! pub fn task() -> u32 {}
106//! ```
107//! When using macro, the resource name will be automatically generated as the method name.
108//! Since there is not function overloading in Rust, the resource name will be unique.
109//! Sentinel will check if the rule with the same resource name has been loaded.
110//!
111//! In the example above, the macro modify the function signature of `task`,
112//! returning `Result<u32, String>` in the new one.
113//! Then, it appends rules to the rule manager, call `EntryBuilder` to create Sentinel entry,
114//! check if the entry pass the rule checking. If the tasks is carried successfully,
115//! it will return an `Ok(u32)`. Otherwise, `Err(String)` will be returned.
116//!
117//! The shortcoming is that there is no way to define several rules on a single resource with this macro.
118//!
119//! ### Via Dynamic Datasource
120//!
121//! Sentinel supports use dynamically load Sentinel rules, refer to
122//!
123//! - [etcd example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/datasources/etcdv3.rs)
124//! - [consul example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/datasources/consul.rs)。
125//! - [k8s example](https://github.com/sentinel-group/sentinel-rust/blob/main/examples/datasources/k8s.rs)。
126//!
127//! ## More Resources
128//!
129//! See the [**Wiki**](https://github.com/sentinel-group/sentinel-rust/wiki) for
130//! full documentation, examples, blog posts, operational details and other information.
131//!
132//! See the [Sentinel](https://sentinelguard.io/en-us/) for the document website.
133//!
134//! See the [中文文档](https://sentinelguard.io/zh-cn/) for document in Chinese.
135//!
136// This module is not intended to be part of the public API. In general, any
137// `doc(hidden)` code is not part of Sentinel's public and stable API.
138#[macro_use]
139#[doc(hidden)]
140pub mod macros;
141
142/// Sentinel API
143pub mod api;
144/// Core implementations of Sentinel, including the statistic structures,
145/// such as the slding window and its underlying LeapArray, the rule managers,
146///  and other utilities on configuration and metric logs.
147/// The rule managers are responsible for managing the flow controller, circuit breaker,
148/// isolation and system status related rules.
149pub mod core;
150/// Adapters for different logging crates.
151pub mod logging;
152cfg_exporter! {
153    /// Metric Exporter implementations. Currently, only Prometheus is supported.
154    pub mod exporter;
155}
156cfg_datasource! {
157    /// Dynamic datasource support for Sentinel rule management.
158    /// Currently, k8s, etcd and consul are supported.
159    pub mod datasource;
160}
161// Utility functions for Sentinel.
162pub mod utils;
163
164// re-export precludes
165pub use crate::core::*;
166pub use api::*;
167
168pub type Result<T> = anyhow::Result<T>;
169pub type Error = anyhow::Error;
170
171// todo: replace useless Arc by ref
172// returning of getter of Arc should be replaced to ref of Arc, too
173// possible use of getter and setter