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
|
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
// @@ begin lint list maintained by maint/add_warning @@
#![allow(renamed_and_removed_lints)] // @@REMOVE_WHEN(ci_arti_stable)
#![allow(unknown_lints)] // @@REMOVE_WHEN(ci_arti_nightly)
#![warn(missing_docs)]
#![warn(noop_method_call)]
#![warn(unreachable_pub)]
#![warn(clippy::all)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::cargo_common_metadata)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::checked_conversions)]
#![allow(clippy::cognitive_complexity)] // See arti#2556
#![deny(clippy::debug_assert_with_mut_call)]
#![deny(clippy::exhaustive_enums)]
#![deny(clippy::exhaustive_structs)]
#![deny(clippy::expl_impl_clone_on_copy)]
#![deny(clippy::fallible_impl_from)]
#![deny(clippy::implicit_clone)]
#![deny(clippy::large_stack_arrays)]
#![warn(clippy::manual_ok_or)]
#![deny(clippy::missing_docs_in_private_items)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::needless_pass_by_value)]
#![warn(clippy::option_option)]
#![deny(clippy::print_stderr)]
#![deny(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![deny(clippy::ref_option_ref)]
#![warn(clippy::semicolon_if_nothing_returned)]
#![warn(clippy::trait_duplication_in_bounds)]
#![deny(clippy::unchecked_time_subtraction)]
#![deny(clippy::unnecessary_wraps)]
#![warn(clippy::unseparated_literal_suffix)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::mod_module_files)]
#![allow(clippy::let_unit_value)] // This can reasonably be done for explicitness
#![allow(clippy::uninlined_format_args)]
#![allow(clippy::significant_drop_in_scrutinee)] // arti/-/merge_requests/588/#note_2812945
#![allow(clippy::result_large_err)] // temporary workaround for arti#587
#![allow(clippy::needless_raw_string_hashes)] // complained-about code is fine, often best
#![allow(clippy::needless_lifetimes)] // See arti#1765
#![allow(mismatched_lifetime_syntaxes)] // temporary workaround for arti#2060
#![allow(clippy::collapsible_if)] // See arti#2342
#![deny(clippy::unused_async)]
#![deny(clippy::string_slice)] // See arti#2571
//! <!-- @@ end lint list maintained by maint/add_warning @@ -->
/// Implementation notes
///
/// We build our logging in a few layers.
///
/// At the lowest level, there is a [`Loggable`] trait, for events which can
/// accumulate and eventually be flushed; this combines with the
/// [`RateLim`](ratelim::RateLim) structure, which is responsible for managing
/// the decision of when to flush these [`Loggable`]s.
///
/// The role of RateLim is to decide
/// when to flush the information in a `Loggable`,
/// and to flush the `Loggable` as needed.
/// The role of a `Loggable` is to
/// accumulate information
/// and to know how to flush that information as a log message
/// when it is told to do so.
///
/// One layer up, there is [`LogState`](logstate::LogState), which is used to to
/// implement `Loggable` as used by [`log_ratelim!`].
/// It can remember the name of an activity, accumulate
/// successes and failures, and remember an error and associated message.
///
/// The highest layer is the [`log_ratelim!`] macro, which uses
/// [`RateLim`](ratelim::RateLim) and [`LogState`](logstate::LogState) to record
/// successes and failures, and launch background tasks as needed.
mod implementation_notes {}
mod logstate;
mod macros;
mod ratelim;
use std::time::Duration;
pub use ratelim::rt::{InstallRuntimeError, install_runtime};
/// Re-exports for macros.
#[doc(hidden)]
pub mod macro_prelude {
pub use crate::{
Activity, Loggable,
logstate::LogState,
ratelim::{RateLim, rt::rt_support},
};
pub use std::sync::LazyLock;
pub use std::sync::{Arc, Mutex, Weak};
pub use tor_error::ErrorReport;
pub use tracing;
/// Alias to force use of RandomState, regardless of features enabled in `weak_tables`.
///
/// See <https://github.com/tov/weak-table-rs/issues/23> for discussion.
pub type WeakValueHashMap<K, V> = weak_table::WeakValueHashMap<K, V, std::hash::RandomState>;
}
/// A group of events that can be logged singly or in a summary over a period of time.
#[doc(hidden)]
pub trait Loggable: 'static + Send {
/// Log these events immediately, if there is anything to log.
///
/// The `summarizing` argument is the amount of time that this `Loggable``
/// has been accumulating information.
///
/// Implementations should return `Active` if they have logged that
/// some activity happened, and `Dormant` if they had nothing to log, or
/// if they are logging "I didn't see that problem for a while."
///
/// After a `Loggable` has been dormant for a while, its timer will be reset.
fn flush(&mut self, summarizing: Duration) -> Activity;
}
/// A description of the whether a `Loggable` had something to say.
#[doc(hidden)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[allow(clippy::exhaustive_enums)] // okay, since this is doc(hidden).
pub enum Activity {
/// There was a failure to report
Active,
/// There is nothing to report (no successes or failures).
Dormant,
/// There is a possible resolution to report (>0 successes and no failures).
AppearsResolved,
}
|