Skip to content

Commit c6f23ec

Browse files
Add device and OS attributes to logs (#4493)
* Add user id, username and email to log attributes * changelog * use enum for attribute type * no longer check isSendDefaultPii * Format code * ignore IntelliJ / Android Studio run configs * suppress deprecation warning for user.name * Add device and OS attributes to logs * changelog * add method impl for MainEventProcessor * use device and os info more directly * Format code * update changelog * api --------- Co-authored-by: Sentry Github Bot <[email protected]>
1 parent bb0801b commit c6f23ec

File tree

7 files changed

+120
-0
lines changed

7 files changed

+120
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
SentryUserFeedbackDialog.Builder(context).create().show()
2626
```
2727
- Add `user.id`, `user.name` and `user.email` to log attributes ([#4486](https://github.com/getsentry/sentry-java/pull/4486))
28+
- User `name` attribute has been deprecated, please use `username` instead ([#4486](https://github.com/getsentry/sentry-java/pull/4486))
29+
- Add device (`device.brand`, `device.model` and `device.family`) and OS (`os.name` and `os.version`) attributes to logs ([#4493](https://github.com/getsentry/sentry-java/pull/4493))
2830
- Serialize `preContext` and `postContext` in `SentryStackFrame` ([#4482](https://github.com/getsentry/sentry-java/pull/4482))
2931

3032
### Internal

sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
import android.content.Context;
44
import android.content.pm.PackageInfo;
55
import android.content.pm.PackageManager;
6+
import android.os.Build;
67
import io.sentry.DateUtils;
78
import io.sentry.EventProcessor;
89
import io.sentry.Hint;
910
import io.sentry.IpAddressUtils;
11+
import io.sentry.NoOpLogger;
12+
import io.sentry.SentryAttributeType;
1013
import io.sentry.SentryBaseEvent;
1114
import io.sentry.SentryEvent;
1215
import io.sentry.SentryLevel;
16+
import io.sentry.SentryLogEvent;
17+
import io.sentry.SentryLogEventAttributeValue;
1318
import io.sentry.SentryReplayEvent;
1419
import io.sentry.android.core.internal.util.AndroidThreadChecker;
1520
import io.sentry.android.core.performance.AppStartMetrics;
@@ -23,6 +28,7 @@
2328
import io.sentry.protocol.SentryTransaction;
2429
import io.sentry.protocol.User;
2530
import io.sentry.util.HintUtils;
31+
import io.sentry.util.LazyEvaluator;
2632
import io.sentry.util.Objects;
2733
import java.util.Collections;
2834
import java.util.List;
@@ -42,6 +48,8 @@ final class DefaultAndroidEventProcessor implements EventProcessor {
4248
private final @NotNull BuildInfoProvider buildInfoProvider;
4349
private final @NotNull SentryAndroidOptions options;
4450
private final @NotNull Future<DeviceInfoUtil> deviceInfoUtil;
51+
private final @NotNull LazyEvaluator<String> deviceFamily =
52+
new LazyEvaluator<>(() -> ContextUtils.getFamily(NoOpLogger.getInstance()));
4553

4654
public DefaultAndroidEventProcessor(
4755
final @NotNull Context context,
@@ -81,6 +89,13 @@ public DefaultAndroidEventProcessor(
8189
return event;
8290
}
8391

92+
@Override
93+
public @Nullable SentryLogEvent process(@NotNull SentryLogEvent event) {
94+
setDevice(event);
95+
setOs(event);
96+
return event;
97+
}
98+
8499
/**
85100
* The last exception is usually used for picking the issue title, but the convention is to send
86101
* inner exceptions first, e.g. [inner, outer] This doesn't work very well on Android, as some
@@ -199,6 +214,34 @@ private void mergeOS(final @NotNull SentryBaseEvent event) {
199214
}
200215
}
201216

217+
private void setDevice(final @NotNull SentryLogEvent event) {
218+
try {
219+
event.setAttribute(
220+
"device.brand",
221+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.BRAND));
222+
event.setAttribute(
223+
"device.model",
224+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.MODEL));
225+
event.setAttribute(
226+
"device.family",
227+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily.getValue()));
228+
} catch (Throwable e) {
229+
options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve device info", e);
230+
}
231+
}
232+
233+
private void setOs(final @NotNull SentryLogEvent event) {
234+
try {
235+
event.setAttribute(
236+
"os.name", new SentryLogEventAttributeValue(SentryAttributeType.STRING, "Android"));
237+
event.setAttribute(
238+
"os.version",
239+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.VERSION.RELEASE));
240+
} catch (Throwable e) {
241+
options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve os system", e);
242+
}
243+
}
244+
202245
// Data to be applied to events that was created in the running process
203246
private void processNonCachedEvent(
204247
final @NotNull SentryBaseEvent event, final @NotNull Hint hint) {

sentry/api/sentry.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ public final class io/sentry/EnvelopeSender : io/sentry/IEnvelopeSender {
458458
public abstract interface class io/sentry/EventProcessor {
459459
public fun getOrder ()Ljava/lang/Long;
460460
public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
461+
public fun process (Lio/sentry/SentryLogEvent;)Lio/sentry/SentryLogEvent;
461462
public fun process (Lio/sentry/SentryReplayEvent;Lio/sentry/Hint;)Lio/sentry/SentryReplayEvent;
462463
public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction;
463464
}
@@ -1284,6 +1285,7 @@ public final class io/sentry/MainEventProcessor : io/sentry/EventProcessor, java
12841285
public fun close ()V
12851286
public fun getOrder ()Ljava/lang/Long;
12861287
public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent;
1288+
public fun process (Lio/sentry/SentryLogEvent;)Lio/sentry/SentryLogEvent;
12871289
public fun process (Lio/sentry/SentryReplayEvent;Lio/sentry/Hint;)Lio/sentry/SentryReplayEvent;
12881290
public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction;
12891291
}
@@ -3143,6 +3145,7 @@ public final class io/sentry/SentryLogEvent : io/sentry/JsonSerializable, io/sen
31433145
public fun getTimestamp ()Ljava/lang/Double;
31443146
public fun getUnknown ()Ljava/util/Map;
31453147
public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V
3148+
public fun setAttribute (Ljava/lang/String;Lio/sentry/SentryLogEventAttributeValue;)V
31463149
public fun setAttributes (Ljava/util/Map;)V
31473150
public fun setBody (Ljava/lang/String;)V
31483151
public fun setLevel (Lio/sentry/SentryLogLevel;)V

sentry/src/main/java/io/sentry/EventProcessor.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ default SentryReplayEvent process(@NotNull SentryReplayEvent event, @NotNull Hin
4545
return event;
4646
}
4747

48+
/**
49+
* May mutate or drop a SentryLogEvent
50+
*
51+
* @param event the SentryLogEvent
52+
* @return the event itself, a mutated SentryLogEvent or null
53+
*/
54+
@Nullable
55+
default SentryLogEvent process(@NotNull SentryLogEvent event) {
56+
return event;
57+
}
58+
4859
/**
4960
* Controls when this EventProcessor is invoked.
5061
*

sentry/src/main/java/io/sentry/MainEventProcessor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ private void processNonCachedEvent(final @NotNull SentryBaseEvent event) {
142142
return event;
143143
}
144144

145+
@Override
146+
public @Nullable SentryLogEvent process(@NotNull SentryLogEvent event) {
147+
return event;
148+
}
149+
145150
private void setCommons(final @NotNull SentryBaseEvent event) {
146151
setPlatform(event);
147152
}

sentry/src/main/java/io/sentry/SentryClient.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,38 @@ private SentryEvent processEvent(
470470
return event;
471471
}
472472

473+
@Nullable
474+
private SentryLogEvent processLogEvent(
475+
@NotNull SentryLogEvent event, final @NotNull List<EventProcessor> eventProcessors) {
476+
for (final EventProcessor processor : eventProcessors) {
477+
try {
478+
event = processor.process(event);
479+
} catch (Throwable e) {
480+
options
481+
.getLogger()
482+
.log(
483+
SentryLevel.ERROR,
484+
e,
485+
"An exception occurred while processing log event by processor: %s",
486+
processor.getClass().getName());
487+
}
488+
489+
if (event == null) {
490+
options
491+
.getLogger()
492+
.log(
493+
SentryLevel.DEBUG,
494+
"Log event was dropped by a processor: %s",
495+
processor.getClass().getName());
496+
options
497+
.getClientReportRecorder()
498+
.recordLostEvent(DiscardReason.EVENT_PROCESSOR, DataCategory.LogItem);
499+
break;
500+
}
501+
}
502+
return event;
503+
}
504+
473505
private @Nullable SentryTransaction processTransaction(
474506
@NotNull SentryTransaction transaction,
475507
final @NotNull Hint hint,
@@ -1138,6 +1170,19 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint
11381170
@ApiStatus.Experimental
11391171
@Override
11401172
public void captureLog(@Nullable SentryLogEvent logEvent, @Nullable IScope scope) {
1173+
if (logEvent != null && scope != null) {
1174+
logEvent = processLogEvent(logEvent, scope.getEventProcessors());
1175+
if (logEvent == null) {
1176+
return;
1177+
}
1178+
}
1179+
1180+
if (logEvent != null) {
1181+
logEvent = processLogEvent(logEvent, options.getEventProcessors());
1182+
if (logEvent == null) {
1183+
return;
1184+
}
1185+
}
11411186

11421187
if (logEvent != null) {
11431188
logEvent = executeBeforeSendLog(logEvent);

sentry/src/main/java/io/sentry/SentryLogEvent.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ public void setAttributes(final @Nullable Map<String, SentryLogEventAttributeVal
7373
this.attributes = attributes;
7474
}
7575

76+
public void setAttribute(
77+
final @Nullable String key, final @Nullable SentryLogEventAttributeValue value) {
78+
if (key == null) {
79+
return;
80+
}
81+
if (this.attributes == null) {
82+
this.attributes = new HashMap<>();
83+
}
84+
this.attributes.put(key, value);
85+
}
86+
7687
public @Nullable Integer getSeverityNumber() {
7788
return severityNumber;
7889
}

0 commit comments

Comments
 (0)