1
1
use std:: any:: TypeId ;
2
2
use std:: borrow:: Cow ;
3
+ #[ cfg( feature = "logs" ) ]
4
+ use std:: collections:: BTreeMap ;
3
5
use std:: fmt;
4
6
use std:: panic:: RefUnwindSafe ;
5
7
use std:: sync:: { Arc , RwLock } ;
@@ -21,6 +23,8 @@ use crate::types::{Dsn, Uuid};
21
23
use crate :: SessionMode ;
22
24
use crate :: { ClientOptions , Envelope , Hub , Integration , Scope , Transport } ;
23
25
#[ cfg( feature = "logs" ) ]
26
+ use sentry_types:: protocol:: v7:: Context ;
27
+ #[ cfg( feature = "logs" ) ]
24
28
use sentry_types:: protocol:: v7:: { Log , LogAttribute } ;
25
29
26
30
impl < T : Into < ClientOptions > > From < T > for Client {
@@ -55,6 +59,8 @@ pub struct Client {
55
59
session_flusher : RwLock < Option < SessionFlusher > > ,
56
60
#[ cfg( feature = "logs" ) ]
57
61
logs_batcher : RwLock < Option < LogsBatcher > > ,
62
+ #[ cfg( feature = "logs" ) ]
63
+ default_log_attributes : Option < BTreeMap < String , LogAttribute > > ,
58
64
integrations : Vec < ( TypeId , Arc < dyn Integration > ) > ,
59
65
pub ( crate ) sdk_info : ClientSdkInfo ,
60
66
}
@@ -92,6 +98,8 @@ impl Clone for Client {
92
98
session_flusher,
93
99
#[ cfg( feature = "logs" ) ]
94
100
logs_batcher,
101
+ #[ cfg( feature = "logs" ) ]
102
+ default_log_attributes : self . default_log_attributes . clone ( ) ,
95
103
integrations : self . integrations . clone ( ) ,
96
104
sdk_info : self . sdk_info . clone ( ) ,
97
105
}
@@ -168,16 +176,87 @@ impl Client {
168
176
None
169
177
} ) ;
170
178
171
- Client {
179
+ #[ allow( unused_mut) ]
180
+ let mut client = Client {
172
181
options,
173
182
transport,
174
183
#[ cfg( feature = "release-health" ) ]
175
184
session_flusher,
176
185
#[ cfg( feature = "logs" ) ]
177
186
logs_batcher,
187
+ #[ cfg( feature = "logs" ) ]
188
+ default_log_attributes : None ,
178
189
integrations,
179
190
sdk_info,
191
+ } ;
192
+
193
+ #[ cfg( feature = "logs" ) ]
194
+ client. cache_default_log_attributes ( ) ;
195
+
196
+ client
197
+ }
198
+
199
+ #[ cfg( feature = "logs" ) ]
200
+ fn cache_default_log_attributes ( & mut self ) {
201
+ let mut attributes = BTreeMap :: new ( ) ;
202
+
203
+ if let Some ( environment) = self . options . environment . as_ref ( ) {
204
+ attributes. insert (
205
+ "sentry.environment" . to_owned ( ) ,
206
+ LogAttribute ( environment. clone ( ) . into ( ) ) ,
207
+ ) ;
208
+ }
209
+
210
+ if let Some ( release) = self . options . release . as_ref ( ) {
211
+ attributes. insert (
212
+ "sentry.release" . to_owned ( ) ,
213
+ LogAttribute ( release. clone ( ) . into ( ) ) ,
214
+ ) ;
215
+ }
216
+
217
+ attributes. insert (
218
+ "sentry.sdk.name" . to_owned ( ) ,
219
+ LogAttribute ( self . sdk_info . name . to_owned ( ) . into ( ) ) ,
220
+ ) ;
221
+
222
+ attributes. insert (
223
+ "sentry.sdk.version" . to_owned ( ) ,
224
+ LogAttribute ( self . sdk_info . version . to_owned ( ) . into ( ) ) ,
225
+ ) ;
226
+
227
+ // Process a fake event through integrations, so that `ContextIntegration` (if available)
228
+ // provides the OS Context.
229
+ // This is needed as that integration adds the OS Context to events using an event
230
+ // processor, which logs don't go through.
231
+ // We cannot get the `ContextIntegration` directly, as its type lives in `sentry-contexts`,
232
+ // which `sentry-core` doesn't depend on.
233
+ let mut fake_event = Event :: default ( ) ;
234
+ for ( _, integration) in self . integrations . iter ( ) {
235
+ if let Some ( res) = integration. process_event ( fake_event. clone ( ) , & self . options ) {
236
+ fake_event = res;
237
+ }
238
+ }
239
+
240
+ if let Some ( Context :: Os ( os) ) = fake_event. contexts . get ( "os" ) {
241
+ if let Some ( name) = os. name . as_ref ( ) {
242
+ attributes. insert ( "os.name" . to_owned ( ) , LogAttribute ( name. to_owned ( ) . into ( ) ) ) ;
243
+ }
244
+ if let Some ( version) = os. version . as_ref ( ) {
245
+ attributes. insert (
246
+ "os.version" . to_owned ( ) ,
247
+ LogAttribute ( version. to_owned ( ) . into ( ) ) ,
248
+ ) ;
249
+ }
180
250
}
251
+
252
+ if let Some ( server) = & self . options . server_name {
253
+ attributes. insert (
254
+ "server.address" . to_owned ( ) ,
255
+ LogAttribute ( server. clone ( ) . into ( ) ) ,
256
+ ) ;
257
+ }
258
+
259
+ self . default_log_attributes = Some ( attributes) ;
181
260
}
182
261
183
262
pub ( crate ) fn get_integration < I > ( & self ) -> Option < & I >
@@ -413,60 +492,18 @@ impl Client {
413
492
fn prepare_log ( & self , mut log : Log , scope : & Scope ) -> Option < Log > {
414
493
scope. apply_to_log ( & mut log, self . options . send_default_pii ) ;
415
494
416
- self . set_log_default_attributes ( & mut log) ;
495
+ if let Some ( default_attributes) = self . default_log_attributes . clone ( ) {
496
+ for ( key, val) in default_attributes. into_iter ( ) {
497
+ log. attributes . entry ( key) . or_insert ( val) ;
498
+ }
499
+ }
417
500
418
501
if let Some ( ref func) = self . options . before_send_log {
419
502
log = func ( log) ?;
420
503
}
421
504
422
505
Some ( log)
423
506
}
424
-
425
- #[ cfg( feature = "logs" ) ]
426
- fn set_log_default_attributes ( & self , log : & mut Log ) {
427
- if !log. attributes . contains_key ( "sentry.environment" ) {
428
- if let Some ( environment) = self . options . environment . as_ref ( ) {
429
- log. attributes . insert (
430
- "sentry.environment" . to_owned ( ) ,
431
- LogAttribute ( environment. clone ( ) . into ( ) ) ,
432
- ) ;
433
- }
434
- }
435
-
436
- if !log. attributes . contains_key ( "sentry.release" ) {
437
- if let Some ( release) = self . options . release . as_ref ( ) {
438
- log. attributes . insert (
439
- "sentry.release" . to_owned ( ) ,
440
- LogAttribute ( release. clone ( ) . into ( ) ) ,
441
- ) ;
442
- }
443
- }
444
-
445
- if !log. attributes . contains_key ( "sentry.sdk.name" ) {
446
- log. attributes . insert (
447
- "sentry.sdk.name" . to_owned ( ) ,
448
- LogAttribute ( self . sdk_info . name . to_owned ( ) . into ( ) ) ,
449
- ) ;
450
- }
451
-
452
- if !log. attributes . contains_key ( "sentry.sdk.version" ) {
453
- log. attributes . insert (
454
- "sentry.sdk.version" . to_owned ( ) ,
455
- LogAttribute ( self . sdk_info . version . to_owned ( ) . into ( ) ) ,
456
- ) ;
457
- }
458
-
459
- // TODO: set OS (and Rust?) context
460
-
461
- if !log. attributes . contains_key ( "server.address" ) {
462
- if let Some ( server) = & self . options . server_name {
463
- log. attributes . insert (
464
- "server.address" . to_owned ( ) ,
465
- LogAttribute ( server. clone ( ) . into ( ) ) ,
466
- ) ;
467
- }
468
- }
469
- }
470
507
}
471
508
472
509
// Make this unwind safe. It's not out of the box because of the
0 commit comments