diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 28a5df0e0b..e553250800 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -2658,6 +2658,34 @@ public final class io/sentry/SentryAppStartProfilingOptions$JsonKeys { public fun ()V } +public final class io/sentry/SentryAttribute { + public static fun booleanAttribute (Ljava/lang/String;Ljava/lang/Boolean;)Lio/sentry/SentryAttribute; + public static fun doubleAttribute (Ljava/lang/String;Ljava/lang/Double;)Lio/sentry/SentryAttribute; + public fun getName ()Ljava/lang/String; + public fun getType ()Lio/sentry/SentryAttributeType; + public fun getValue ()Ljava/lang/Object; + public static fun integerAttribute (Ljava/lang/String;Ljava/lang/Integer;)Lio/sentry/SentryAttribute; + public static fun named (Ljava/lang/String;Ljava/lang/Object;)Lio/sentry/SentryAttribute; + public static fun stringAttribute (Ljava/lang/String;Ljava/lang/String;)Lio/sentry/SentryAttribute; +} + +public final class io/sentry/SentryAttributeType : java/lang/Enum { + public static final field BOOLEAN Lio/sentry/SentryAttributeType; + public static final field DOUBLE Lio/sentry/SentryAttributeType; + public static final field INTEGER Lio/sentry/SentryAttributeType; + public static final field STRING Lio/sentry/SentryAttributeType; + public fun apiName ()Ljava/lang/String; + public static fun valueOf (Ljava/lang/String;)Lio/sentry/SentryAttributeType; + public static fun values ()[Lio/sentry/SentryAttributeType; +} + +public final class io/sentry/SentryAttributes { + public fun add (Lio/sentry/SentryAttribute;)V + public static fun fromMap (Ljava/util/Map;)Lio/sentry/SentryAttributes; + public fun getAttributes ()Ljava/util/List; + public static fun of ([Lio/sentry/SentryAttribute;)Lio/sentry/SentryAttributes; +} + public final class io/sentry/SentryAutoDateProvider : io/sentry/SentryDateProvider { public fun ()V public fun now ()Lio/sentry/SentryDate; @@ -3077,6 +3105,7 @@ public final class io/sentry/SentryLogEvent$JsonKeys { } public final class io/sentry/SentryLogEventAttributeValue : io/sentry/JsonSerializable, io/sentry/JsonUnknown { + public fun (Lio/sentry/SentryAttributeType;Ljava/lang/Object;)V public fun (Ljava/lang/String;Ljava/lang/Object;)V public fun getType ()Ljava/lang/String; public fun getUnknown ()Ljava/util/Map; @@ -4711,9 +4740,8 @@ public abstract interface class io/sentry/logger/ILoggerApi { public abstract fun fatal (Ljava/lang/String;[Ljava/lang/Object;)V public abstract fun info (Ljava/lang/String;[Ljava/lang/Object;)V public abstract fun log (Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V + public abstract fun log (Lio/sentry/SentryLogLevel;Lio/sentry/logger/LogParams;Ljava/lang/String;[Ljava/lang/Object;)V public abstract fun log (Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V - public abstract fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V - public abstract fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V public abstract fun trace (Ljava/lang/String;[Ljava/lang/Object;)V public abstract fun warn (Ljava/lang/String;[Ljava/lang/Object;)V } @@ -4723,6 +4751,16 @@ public abstract interface class io/sentry/logger/ILoggerBatchProcessor { public abstract fun close (Z)V } +public final class io/sentry/logger/LogParams { + public fun ()V + public static fun create (Lio/sentry/SentryAttributes;)Lio/sentry/logger/LogParams; + public static fun create (Lio/sentry/SentryDate;Lio/sentry/SentryAttributes;)Lio/sentry/logger/LogParams; + public fun getAttributes ()Lio/sentry/SentryAttributes; + public fun getTimestamp ()Lio/sentry/SentryDate; + public fun setAttributes (Lio/sentry/SentryAttributes;)V + public fun setTimestamp (Lio/sentry/SentryDate;)V +} + public final class io/sentry/logger/LoggerApi : io/sentry/logger/ILoggerApi { public fun (Lio/sentry/Scopes;)V public fun debug (Ljava/lang/String;[Ljava/lang/Object;)V @@ -4730,9 +4768,8 @@ public final class io/sentry/logger/LoggerApi : io/sentry/logger/ILoggerApi { public fun fatal (Ljava/lang/String;[Ljava/lang/Object;)V public fun info (Ljava/lang/String;[Ljava/lang/Object;)V public fun log (Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V + public fun log (Lio/sentry/SentryLogLevel;Lio/sentry/logger/LogParams;Ljava/lang/String;[Ljava/lang/Object;)V public fun log (Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V - public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V - public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V public fun trace (Ljava/lang/String;[Ljava/lang/Object;)V public fun warn (Ljava/lang/String;[Ljava/lang/Object;)V } @@ -4752,9 +4789,8 @@ public final class io/sentry/logger/NoOpLoggerApi : io/sentry/logger/ILoggerApi public static fun getInstance ()Lio/sentry/logger/NoOpLoggerApi; public fun info (Ljava/lang/String;[Ljava/lang/Object;)V public fun log (Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V + public fun log (Lio/sentry/SentryLogLevel;Lio/sentry/logger/LogParams;Ljava/lang/String;[Ljava/lang/Object;)V public fun log (Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V - public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V - public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V public fun trace (Ljava/lang/String;[Ljava/lang/Object;)V public fun warn (Ljava/lang/String;[Ljava/lang/Object;)V } diff --git a/sentry/src/main/java/io/sentry/SentryAttribute.java b/sentry/src/main/java/io/sentry/SentryAttribute.java new file mode 100644 index 0000000000..4bcef14ee8 --- /dev/null +++ b/sentry/src/main/java/io/sentry/SentryAttribute.java @@ -0,0 +1,57 @@ +package io.sentry; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class SentryAttribute { + + private final @NotNull String name; + private final @Nullable SentryAttributeType type; + private final @Nullable Object value; + + private SentryAttribute( + final @NotNull String name, + final @Nullable SentryAttributeType type, + final @Nullable Object value) { + this.name = name; + this.type = type; + this.value = value; + } + + public @NotNull String getName() { + return name; + } + + public @Nullable SentryAttributeType getType() { + return type; + } + + public @Nullable Object getValue() { + return value; + } + + public static @NotNull SentryAttribute named( + final @NotNull String name, final @Nullable Object value) { + return new SentryAttribute(name, null, value); + } + + public static @NotNull SentryAttribute booleanAttribute( + final @NotNull String name, final @Nullable Boolean value) { + return new SentryAttribute(name, SentryAttributeType.BOOLEAN, value); + } + + public static @NotNull SentryAttribute integerAttribute( + final @NotNull String name, final @Nullable Integer value) { + return new SentryAttribute(name, SentryAttributeType.INTEGER, value); + } + + public static @NotNull SentryAttribute doubleAttribute( + final @NotNull String name, final @Nullable Double value) { + return new SentryAttribute(name, SentryAttributeType.DOUBLE, value); + } + + public static @NotNull SentryAttribute stringAttribute( + final @NotNull String name, final @Nullable String value) { + return new SentryAttribute(name, SentryAttributeType.STRING, value); + } +} diff --git a/sentry/src/main/java/io/sentry/SentryAttributeType.java b/sentry/src/main/java/io/sentry/SentryAttributeType.java new file mode 100644 index 0000000000..a47d7e71f0 --- /dev/null +++ b/sentry/src/main/java/io/sentry/SentryAttributeType.java @@ -0,0 +1,15 @@ +package io.sentry; + +import java.util.Locale; +import org.jetbrains.annotations.NotNull; + +public enum SentryAttributeType { + STRING, + BOOLEAN, + INTEGER, + DOUBLE; + + public @NotNull String apiName() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/sentry/src/main/java/io/sentry/SentryAttributes.java b/sentry/src/main/java/io/sentry/SentryAttributes.java new file mode 100644 index 0000000000..d4165d4f7a --- /dev/null +++ b/sentry/src/main/java/io/sentry/SentryAttributes.java @@ -0,0 +1,44 @@ +package io.sentry; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class SentryAttributes { + + private final @NotNull List attributes; + + private SentryAttributes(final @NotNull List attributes) { + this.attributes = attributes; + } + + public void add(final @Nullable SentryAttribute attribute) { + if (attribute == null) { + return; + } + attributes.add(attribute); + } + + public @NotNull List getAttributes() { + return attributes; + } + + public static @NotNull SentryAttributes of(SentryAttribute... attributes) { + return new SentryAttributes(Arrays.asList(attributes)); + } + + public static @NotNull SentryAttributes fromMap(final @Nullable Map attributes) { + if (attributes == null) { + return new SentryAttributes(new ArrayList<>()); + } + SentryAttributes sentryAttributes = new SentryAttributes(new ArrayList<>(attributes.size())); + for (Map.Entry attribute : attributes.entrySet()) { + sentryAttributes.add(SentryAttribute.named(attribute.getKey(), attribute.getValue())); + } + + return sentryAttributes; + } +} diff --git a/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java b/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java index a733b42ad0..cf92b21de8 100644 --- a/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java +++ b/sentry/src/main/java/io/sentry/SentryLogEventAttributeValue.java @@ -18,6 +18,12 @@ public SentryLogEventAttributeValue(final @NotNull String type, final @Nullable this.value = value; } + public SentryLogEventAttributeValue( + final @NotNull SentryAttributeType type, final @Nullable Object value) { + this.type = type.apiName(); + this.value = value; + } + public @NotNull String getType() { return type; } diff --git a/sentry/src/main/java/io/sentry/logger/ILoggerApi.java b/sentry/src/main/java/io/sentry/logger/ILoggerApi.java index 61ae5219aa..78787ef461 100644 --- a/sentry/src/main/java/io/sentry/logger/ILoggerApi.java +++ b/sentry/src/main/java/io/sentry/logger/ILoggerApi.java @@ -2,7 +2,6 @@ import io.sentry.SentryDate; import io.sentry.SentryLogLevel; -import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,15 +30,8 @@ void log( @Nullable Object... args); void log( - @Nullable Map attributes, @NotNull SentryLogLevel level, - @Nullable String message, - @Nullable Object... args); - - void log( - @Nullable Map attributes, - @NotNull SentryLogLevel level, - @Nullable SentryDate timestamp, + @NotNull LogParams params, @Nullable String message, @Nullable Object... args); } diff --git a/sentry/src/main/java/io/sentry/logger/LogParams.java b/sentry/src/main/java/io/sentry/logger/LogParams.java new file mode 100644 index 0000000000..2e943766e0 --- /dev/null +++ b/sentry/src/main/java/io/sentry/logger/LogParams.java @@ -0,0 +1,42 @@ +package io.sentry.logger; + +import io.sentry.SentryAttributes; +import io.sentry.SentryDate; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class LogParams { + + private @Nullable SentryDate timestamp; + private @Nullable SentryAttributes attributes; + + public @Nullable SentryDate getTimestamp() { + return timestamp; + } + + public void setTimestamp(final @Nullable SentryDate timestamp) { + this.timestamp = timestamp; + } + + public @Nullable SentryAttributes getAttributes() { + return attributes; + } + + public void setAttributes(final @Nullable SentryAttributes attributes) { + this.attributes = attributes; + } + + public static @NotNull LogParams create( + final @Nullable SentryDate timestamp, final @Nullable SentryAttributes attributes) { + final @NotNull LogParams params = new LogParams(); + + params.setTimestamp(timestamp); + params.setAttributes(attributes); + + return params; + } + + public static @NotNull LogParams create(final @Nullable SentryAttributes attributes) { + return create(null, attributes); + } +} diff --git a/sentry/src/main/java/io/sentry/logger/LoggerApi.java b/sentry/src/main/java/io/sentry/logger/LoggerApi.java index 921ebe94b0..3f8d53154f 100644 --- a/sentry/src/main/java/io/sentry/logger/LoggerApi.java +++ b/sentry/src/main/java/io/sentry/logger/LoggerApi.java @@ -5,6 +5,9 @@ import io.sentry.ISpan; import io.sentry.PropagationContext; import io.sentry.Scopes; +import io.sentry.SentryAttribute; +import io.sentry.SentryAttributeType; +import io.sentry.SentryAttributes; import io.sentry.SentryDate; import io.sentry.SentryLevel; import io.sentry.SentryLogEvent; @@ -17,7 +20,6 @@ import io.sentry.util.Platform; import io.sentry.util.TracingUtils; import java.util.HashMap; -import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,7 +68,7 @@ public void log( final @NotNull SentryLogLevel level, final @Nullable String message, final @Nullable Object... args) { - captureLog(null, level, null, message, args); + captureLog(level, LogParams.create(null, null), message, args); } @Override @@ -75,33 +77,22 @@ public void log( final @Nullable SentryDate timestamp, final @Nullable String message, final @Nullable Object... args) { - captureLog(null, level, timestamp, message, args); + captureLog(level, LogParams.create(timestamp, null), message, args); } @Override public void log( - final @Nullable Map attributes, final @NotNull SentryLogLevel level, - final @Nullable SentryDate timestamp, + final @NotNull LogParams params, final @Nullable String message, final @Nullable Object... args) { - captureLog(attributes, level, timestamp, message, args); - } - - @Override - public void log( - final @Nullable Map attributes, - final @NotNull SentryLogLevel level, - final @Nullable String message, - final @Nullable Object... args) { - captureLog(attributes, level, null, message, args); + captureLog(level, params, message, args); } @SuppressWarnings("AnnotateFormatMethod") private void captureLog( - final @Nullable Map attributes, final @NotNull SentryLogLevel level, - final @Nullable SentryDate timestamp, + final @NotNull LogParams params, final @Nullable String message, final @Nullable Object... args) { final @NotNull SentryOptions options = scopes.getOptions(); @@ -124,6 +115,7 @@ private void captureLog( return; } + final @Nullable SentryDate timestamp = params.getTimestamp(); final @NotNull SentryDate timestampToUse = timestamp == null ? options.getDateProvider().now() : timestamp; final @NotNull String messageToUse = maybeFormatMessage(message, args); @@ -140,7 +132,7 @@ private void captureLog( span == null ? propagationContext.getSpanId() : span.getSpanContext().getSpanId(); final SentryLogEvent logEvent = new SentryLogEvent(traceId, timestampToUse, messageToUse, level); - logEvent.setAttributes(createAttributes(attributes, message, spanId, args)); + logEvent.setAttributes(createAttributes(params.getAttributes(), message, spanId, args)); logEvent.setSeverityNumber(level.getSeverityNumber()); scopes.getClient().captureLog(logEvent, combinedScope); @@ -167,24 +159,25 @@ private void captureLog( } private @NotNull HashMap createAttributes( - final @Nullable Map incomingAttributes, + final @Nullable SentryAttributes incomingAttributes, final @NotNull String message, final @NotNull SpanId spanId, final @Nullable Object... args) { final @NotNull HashMap attributes = new HashMap<>(); if (incomingAttributes != null) { - for (Map.Entry attributeEntry : incomingAttributes.entrySet()) { - final @Nullable Object value = attributeEntry.getValue(); - final @NotNull String type = getType(value); - attributes.put(attributeEntry.getKey(), new SentryLogEventAttributeValue(type, value)); + for (SentryAttribute attribute : incomingAttributes.getAttributes()) { + final @Nullable Object value = attribute.getValue(); + final @NotNull SentryAttributeType type = + attribute.getType() == null ? getType(value) : attribute.getType(); + attributes.put(attribute.getName(), new SentryLogEventAttributeValue(type, value)); } } if (args != null) { int i = 0; for (Object arg : args) { - final @NotNull String type = getType(arg); + final @NotNull SentryAttributeType type = getType(arg); attributes.put( "sentry.message.parameter." + i, new SentryLogEventAttributeValue(type, arg)); i++; @@ -238,16 +231,16 @@ private void setServerName( } } - private @NotNull String getType(final @Nullable Object arg) { + private @NotNull SentryAttributeType getType(final @Nullable Object arg) { if (arg instanceof Boolean) { - return "boolean"; + return SentryAttributeType.BOOLEAN; } if (arg instanceof Integer) { - return "integer"; + return SentryAttributeType.INTEGER; } if (arg instanceof Number) { - return "double"; + return SentryAttributeType.DOUBLE; } - return "string"; + return SentryAttributeType.STRING; } } diff --git a/sentry/src/main/java/io/sentry/logger/NoOpLoggerApi.java b/sentry/src/main/java/io/sentry/logger/NoOpLoggerApi.java index f9218be8be..f4f2a3959d 100644 --- a/sentry/src/main/java/io/sentry/logger/NoOpLoggerApi.java +++ b/sentry/src/main/java/io/sentry/logger/NoOpLoggerApi.java @@ -2,7 +2,6 @@ import io.sentry.SentryDate; import io.sentry.SentryLogLevel; -import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -65,18 +64,8 @@ public void log( @Override public void log( - @Nullable Map attributes, @NotNull SentryLogLevel level, - @Nullable String message, - @Nullable Object... args) { - // do nothing - } - - @Override - public void log( - @Nullable Map attributes, - @NotNull SentryLogLevel level, - @Nullable SentryDate timestamp, + @NotNull LogParams params, @Nullable String message, @Nullable Object... args) { // do nothing