diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f9a7cf9ab..b53015bbe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ SentryUserFeedbackDialog.Builder(context).create().show() ``` - Add `user.id`, `user.name` and `user.email` to log attributes ([#4486](https://github.com/getsentry/sentry-java/pull/4486)) +- User `name` attribute has been deprecated, please use `username` instead ([#4486](https://github.com/getsentry/sentry-java/pull/4486)) +- 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)) - Serialize `preContext` and `postContext` in `SentryStackFrame` ([#4482](https://github.com/getsentry/sentry-java/pull/4482)) ### Internal diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java b/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java index 646f3c91dc..9409c29b0d 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java @@ -3,13 +3,18 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.os.Build; import io.sentry.DateUtils; import io.sentry.EventProcessor; import io.sentry.Hint; import io.sentry.IpAddressUtils; +import io.sentry.NoOpLogger; +import io.sentry.SentryAttributeType; import io.sentry.SentryBaseEvent; import io.sentry.SentryEvent; import io.sentry.SentryLevel; +import io.sentry.SentryLogEvent; +import io.sentry.SentryLogEventAttributeValue; import io.sentry.SentryReplayEvent; import io.sentry.android.core.internal.util.AndroidThreadChecker; import io.sentry.android.core.performance.AppStartMetrics; @@ -23,6 +28,7 @@ import io.sentry.protocol.SentryTransaction; import io.sentry.protocol.User; import io.sentry.util.HintUtils; +import io.sentry.util.LazyEvaluator; import io.sentry.util.Objects; import java.util.Collections; import java.util.List; @@ -42,6 +48,8 @@ final class DefaultAndroidEventProcessor implements EventProcessor { private final @NotNull BuildInfoProvider buildInfoProvider; private final @NotNull SentryAndroidOptions options; private final @NotNull Future deviceInfoUtil; + private final @NotNull LazyEvaluator deviceFamily = + new LazyEvaluator<>(() -> ContextUtils.getFamily(NoOpLogger.getInstance())); public DefaultAndroidEventProcessor( final @NotNull Context context, @@ -81,6 +89,13 @@ public DefaultAndroidEventProcessor( return event; } + @Override + public @Nullable SentryLogEvent process(@NotNull SentryLogEvent event) { + setDevice(event); + setOs(event); + return event; + } + /** * The last exception is usually used for picking the issue title, but the convention is to send * 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) { } } + private void setDevice(final @NotNull SentryLogEvent event) { + try { + event.setAttribute( + "device.brand", + new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.BRAND)); + event.setAttribute( + "device.model", + new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.MODEL)); + event.setAttribute( + "device.family", + new SentryLogEventAttributeValue(SentryAttributeType.STRING, deviceFamily.getValue())); + } catch (Throwable e) { + options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve device info", e); + } + } + + private void setOs(final @NotNull SentryLogEvent event) { + try { + event.setAttribute( + "os.name", new SentryLogEventAttributeValue(SentryAttributeType.STRING, "Android")); + event.setAttribute( + "os.version", + new SentryLogEventAttributeValue(SentryAttributeType.STRING, Build.VERSION.RELEASE)); + } catch (Throwable e) { + options.getLogger().log(SentryLevel.ERROR, "Failed to retrieve os system", e); + } + } + // Data to be applied to events that was created in the running process private void processNonCachedEvent( final @NotNull SentryBaseEvent event, final @NotNull Hint hint) { diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 4e38e81feb..c68bcbab7f 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -458,6 +458,7 @@ public final class io/sentry/EnvelopeSender : io/sentry/IEnvelopeSender { public abstract interface class io/sentry/EventProcessor { public fun getOrder ()Ljava/lang/Long; public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent; + public fun process (Lio/sentry/SentryLogEvent;)Lio/sentry/SentryLogEvent; public fun process (Lio/sentry/SentryReplayEvent;Lio/sentry/Hint;)Lio/sentry/SentryReplayEvent; public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction; } @@ -1284,6 +1285,7 @@ public final class io/sentry/MainEventProcessor : io/sentry/EventProcessor, java public fun close ()V public fun getOrder ()Ljava/lang/Long; public fun process (Lio/sentry/SentryEvent;Lio/sentry/Hint;)Lio/sentry/SentryEvent; + public fun process (Lio/sentry/SentryLogEvent;)Lio/sentry/SentryLogEvent; public fun process (Lio/sentry/SentryReplayEvent;Lio/sentry/Hint;)Lio/sentry/SentryReplayEvent; public fun process (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Hint;)Lio/sentry/protocol/SentryTransaction; } @@ -3143,6 +3145,7 @@ public final class io/sentry/SentryLogEvent : io/sentry/JsonSerializable, io/sen public fun getTimestamp ()Ljava/lang/Double; public fun getUnknown ()Ljava/util/Map; public fun serialize (Lio/sentry/ObjectWriter;Lio/sentry/ILogger;)V + public fun setAttribute (Ljava/lang/String;Lio/sentry/SentryLogEventAttributeValue;)V public fun setAttributes (Ljava/util/Map;)V public fun setBody (Ljava/lang/String;)V public fun setLevel (Lio/sentry/SentryLogLevel;)V diff --git a/sentry/src/main/java/io/sentry/EventProcessor.java b/sentry/src/main/java/io/sentry/EventProcessor.java index 3ee289a8fa..b258132edf 100644 --- a/sentry/src/main/java/io/sentry/EventProcessor.java +++ b/sentry/src/main/java/io/sentry/EventProcessor.java @@ -45,6 +45,17 @@ default SentryReplayEvent process(@NotNull SentryReplayEvent event, @NotNull Hin return event; } + /** + * May mutate or drop a SentryLogEvent + * + * @param event the SentryLogEvent + * @return the event itself, a mutated SentryLogEvent or null + */ + @Nullable + default SentryLogEvent process(@NotNull SentryLogEvent event) { + return event; + } + /** * Controls when this EventProcessor is invoked. * diff --git a/sentry/src/main/java/io/sentry/MainEventProcessor.java b/sentry/src/main/java/io/sentry/MainEventProcessor.java index 7f44d61df4..ddf7b3828e 100644 --- a/sentry/src/main/java/io/sentry/MainEventProcessor.java +++ b/sentry/src/main/java/io/sentry/MainEventProcessor.java @@ -142,6 +142,11 @@ private void processNonCachedEvent(final @NotNull SentryBaseEvent event) { return event; } + @Override + public @Nullable SentryLogEvent process(@NotNull SentryLogEvent event) { + return event; + } + private void setCommons(final @NotNull SentryBaseEvent event) { setPlatform(event); } diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index 95ceacef88..617083b1a3 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -470,6 +470,38 @@ private SentryEvent processEvent( return event; } + @Nullable + private SentryLogEvent processLogEvent( + @NotNull SentryLogEvent event, final @NotNull List eventProcessors) { + for (final EventProcessor processor : eventProcessors) { + try { + event = processor.process(event); + } catch (Throwable e) { + options + .getLogger() + .log( + SentryLevel.ERROR, + e, + "An exception occurred while processing log event by processor: %s", + processor.getClass().getName()); + } + + if (event == null) { + options + .getLogger() + .log( + SentryLevel.DEBUG, + "Log event was dropped by a processor: %s", + processor.getClass().getName()); + options + .getClientReportRecorder() + .recordLostEvent(DiscardReason.EVENT_PROCESSOR, DataCategory.LogItem); + break; + } + } + return event; + } + private @Nullable SentryTransaction processTransaction( @NotNull SentryTransaction transaction, final @NotNull Hint hint, @@ -1138,6 +1170,19 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint @ApiStatus.Experimental @Override public void captureLog(@Nullable SentryLogEvent logEvent, @Nullable IScope scope) { + if (logEvent != null && scope != null) { + logEvent = processLogEvent(logEvent, scope.getEventProcessors()); + if (logEvent == null) { + return; + } + } + + if (logEvent != null) { + logEvent = processLogEvent(logEvent, options.getEventProcessors()); + if (logEvent == null) { + return; + } + } if (logEvent != null) { logEvent = executeBeforeSendLog(logEvent); diff --git a/sentry/src/main/java/io/sentry/SentryLogEvent.java b/sentry/src/main/java/io/sentry/SentryLogEvent.java index 61065ff666..2afcf57a1d 100644 --- a/sentry/src/main/java/io/sentry/SentryLogEvent.java +++ b/sentry/src/main/java/io/sentry/SentryLogEvent.java @@ -73,6 +73,17 @@ public void setAttributes(final @Nullable Map(); + } + this.attributes.put(key, value); + } + public @Nullable Integer getSeverityNumber() { return severityNumber; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy