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