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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//! Client configuration.
use std::path::PathBuf;
use std::sync::Arc;
use crate::integration::Integration;
use crate::protocol::ErrorEvent;
use crate::transport::TransportFactory;
/// Default ingest host.
pub const DEFAULT_HOST: &str = "https://api.allstak.sa";
/// How sessions map to units of work.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SessionMode {
/// One session for the whole process lifetime (services / daemons).
#[default]
Application,
/// One session per request / unit of work (web middleware).
Request,
}
type BeforeSend = Arc<dyn Fn(ErrorEvent) -> Option<ErrorEvent> + Send + Sync>;
type BeforeBreadcrumb =
Arc<dyn Fn(crate::protocol::Breadcrumb) -> Option<crate::protocol::Breadcrumb> + Send + Sync>;
/// All knobs controlling a [`crate::Client`].
#[derive(Clone)]
pub struct ClientOptions {
/// Ingest API key (sent as `X-AllStak-Key`).
pub api_key: String,
/// Ingest host. Defaults to [`DEFAULT_HOST`].
pub host: String,
/// Release identifier (version) for this build.
pub release: Option<String>,
/// Deployment environment. Defaults from `debug_assertions`.
pub environment: Option<String>,
/// Logical service name attached to spans/logs.
pub server_name: Option<String>,
/// Fraction of error events to keep (0.0..=1.0).
pub sample_rate: f32,
/// Fraction of transactions to keep when no sampler is set.
pub traces_sample_rate: f32,
/// Ring-buffer cap for breadcrumbs.
pub max_breadcrumbs: usize,
/// Attach a backtrace to message events even without an error.
pub attach_stacktrace: bool,
/// Send identifying PII. When `false`, payloads are value-scrubbed.
pub send_default_pii: bool,
/// Module prefixes always marked in-app.
pub in_app_include: Vec<String>,
/// Module prefixes always marked not-in-app.
pub in_app_exclude: Vec<String>,
/// Final per-event hook; receives a sanitized event when
/// `send_default_pii` is false. Return `None` to drop. The SDK scrubs again
/// after the hook before persistence/network delivery.
pub before_send: Option<BeforeSend>,
/// Per-breadcrumb hook; return `None` to drop.
pub before_breadcrumb: Option<BeforeBreadcrumb>,
/// Emit internal debug logging to stderr.
pub debug: bool,
/// How long [`crate::ClientInitGuard`] waits to flush on drop.
pub shutdown_timeout: std::time::Duration,
/// Open a session at init / end it on shutdown.
pub auto_session_tracking: bool,
/// Application- vs request-scoped sessions.
pub session_mode: SessionMode,
/// Install the built-in integrations (panic, etc.).
pub default_integrations: bool,
/// Additional integrations run in the event pipeline.
pub integrations: Vec<Arc<dyn Integration>>,
/// Factory used to build the transport. `None` uses the default.
pub transport: Option<Arc<dyn TransportFactory>>,
/// Bounded queue capacity for the transport worker.
pub transport_queue_size: usize,
/// Persist retryable transport failures to disk for replay on the next init.
pub enable_offline_queue: bool,
/// Directory for persisted envelopes. `None` uses a temp-dir AllStak path.
pub offline_queue_dir: Option<PathBuf>,
/// Maximum persisted envelope count. Oldest entries are removed first.
pub offline_queue_max_events: usize,
/// Maximum persisted queue bytes. Oldest entries are removed first.
pub offline_queue_max_bytes: u64,
}
impl std::fmt::Debug for ClientOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ClientOptions")
.field("host", &self.host)
.field("release", &self.release)
.field("environment", &self.environment)
.field("sample_rate", &self.sample_rate)
.field("traces_sample_rate", &self.traces_sample_rate)
.field("max_breadcrumbs", &self.max_breadcrumbs)
.field("send_default_pii", &self.send_default_pii)
.field("auto_session_tracking", &self.auto_session_tracking)
.field("session_mode", &self.session_mode)
.field("integrations", &self.integrations.len())
.finish_non_exhaustive()
}
}
impl Default for ClientOptions {
fn default() -> Self {
ClientOptions {
api_key: String::new(),
host: DEFAULT_HOST.to_string(),
release: None,
environment: None,
server_name: None,
sample_rate: 1.0,
traces_sample_rate: 0.0,
max_breadcrumbs: 100,
attach_stacktrace: false,
send_default_pii: false,
in_app_include: Vec::new(),
in_app_exclude: Vec::new(),
before_send: None,
before_breadcrumb: None,
debug: false,
shutdown_timeout: std::time::Duration::from_secs(2),
auto_session_tracking: true,
session_mode: SessionMode::Application,
default_integrations: true,
integrations: Vec::new(),
transport: None,
transport_queue_size: 1000,
enable_offline_queue: true,
offline_queue_dir: None,
offline_queue_max_events: 100,
offline_queue_max_bytes: 5 * 1024 * 1024,
}
}
}
impl ClientOptions {
/// Resolved environment, defaulting from `debug_assertions`.
pub fn resolved_environment(&self) -> String {
self.environment.clone().unwrap_or_else(|| {
if cfg!(debug_assertions) {
"development".to_string()
} else {
"production".to_string()
}
})
}
}
/// Anything that can be turned into [`ClientOptions`].
///
/// Accepts a bare api key string, a `(api_key, ClientOptions)` tuple, or an
/// already-built `ClientOptions`.
pub trait IntoClientOptions {
/// Convert into resolved options.
fn into_client_options(self) -> ClientOptions;
}
impl IntoClientOptions for ClientOptions {
fn into_client_options(self) -> ClientOptions {
self
}
}
impl IntoClientOptions for &str {
fn into_client_options(self) -> ClientOptions {
ClientOptions {
api_key: self.to_string(),
..ClientOptions::default()
}
}
}
impl IntoClientOptions for String {
fn into_client_options(self) -> ClientOptions {
ClientOptions {
api_key: self,
..ClientOptions::default()
}
}
}
impl IntoClientOptions for (&str, ClientOptions) {
fn into_client_options(self) -> ClientOptions {
let (api_key, mut opts) = self;
opts.api_key = api_key.to_string();
opts
}
}
impl IntoClientOptions for (String, ClientOptions) {
fn into_client_options(self) -> ClientOptions {
let (api_key, mut opts) = self;
opts.api_key = api_key;
opts
}
}