Skip to content

Commit 5aee114

Browse files
committed
refactor(logs): cache default attributes and add OS attributes
1 parent 2b1455b commit 5aee114

File tree

1 file changed

+85
-48
lines changed

1 file changed

+85
-48
lines changed

sentry-core/src/client.rs

Lines changed: 85 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::any::TypeId;
22
use std::borrow::Cow;
3+
#[cfg(feature = "logs")]
4+
use std::collections::BTreeMap;
35
use std::fmt;
46
use std::panic::RefUnwindSafe;
57
use std::sync::{Arc, RwLock};
@@ -21,6 +23,8 @@ use crate::types::{Dsn, Uuid};
2123
use crate::SessionMode;
2224
use crate::{ClientOptions, Envelope, Hub, Integration, Scope, Transport};
2325
#[cfg(feature = "logs")]
26+
use sentry_types::protocol::v7::Context;
27+
#[cfg(feature = "logs")]
2428
use sentry_types::protocol::v7::{Log, LogAttribute};
2529

2630
impl<T: Into<ClientOptions>> From<T> for Client {
@@ -55,6 +59,8 @@ pub struct Client {
5559
session_flusher: RwLock<Option<SessionFlusher>>,
5660
#[cfg(feature = "logs")]
5761
logs_batcher: RwLock<Option<LogsBatcher>>,
62+
#[cfg(feature = "logs")]
63+
default_log_attributes: Option<BTreeMap<String, LogAttribute>>,
5864
integrations: Vec<(TypeId, Arc<dyn Integration>)>,
5965
pub(crate) sdk_info: ClientSdkInfo,
6066
}
@@ -92,6 +98,8 @@ impl Clone for Client {
9298
session_flusher,
9399
#[cfg(feature = "logs")]
94100
logs_batcher,
101+
#[cfg(feature = "logs")]
102+
default_log_attributes: self.default_log_attributes.clone(),
95103
integrations: self.integrations.clone(),
96104
sdk_info: self.sdk_info.clone(),
97105
}
@@ -168,16 +176,87 @@ impl Client {
168176
None
169177
});
170178

171-
Client {
179+
#[allow(unused_mut)]
180+
let mut client = Client {
172181
options,
173182
transport,
174183
#[cfg(feature = "release-health")]
175184
session_flusher,
176185
#[cfg(feature = "logs")]
177186
logs_batcher,
187+
#[cfg(feature = "logs")]
188+
default_log_attributes: None,
178189
integrations,
179190
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+
}
180250
}
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);
181260
}
182261

183262
pub(crate) fn get_integration<I>(&self) -> Option<&I>
@@ -413,60 +492,18 @@ impl Client {
413492
fn prepare_log(&self, mut log: Log, scope: &Scope) -> Option<Log> {
414493
scope.apply_to_log(&mut log, self.options.send_default_pii);
415494

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+
}
417500

418501
if let Some(ref func) = self.options.before_send_log {
419502
log = func(log)?;
420503
}
421504

422505
Some(log)
423506
}
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-
}
470507
}
471508

472509
// Make this unwind safe. It's not out of the box because of the

0 commit comments

Comments
 (0)