Skip to content

Improve Log Attributes API #4416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: feat/logs-attributes-in-api
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 42 additions & 6 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -2658,6 +2658,34 @@ public final class io/sentry/SentryAppStartProfilingOptions$JsonKeys {
public fun <init> ()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 <init> ()V
public fun now ()Lio/sentry/SentryDate;
Expand Down Expand Up @@ -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 <init> (Lio/sentry/SentryAttributeType;Ljava/lang/Object;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Object;)V
public fun getType ()Ljava/lang/String;
public fun getUnknown ()Ljava/util/Map;
Expand Down Expand Up @@ -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
}
Expand All @@ -4723,16 +4751,25 @@ public abstract interface class io/sentry/logger/ILoggerBatchProcessor {
public abstract fun close (Z)V
}

public final class io/sentry/logger/LogParams {
public fun <init> ()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 <init> (Lio/sentry/Scopes;)V
public fun debug (Ljava/lang/String;[Ljava/lang/Object;)V
public fun error (Ljava/lang/String;[Ljava/lang/Object;)V
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
}
Expand All @@ -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
}
Expand Down
57 changes: 57 additions & 0 deletions sentry/src/main/java/io/sentry/SentryAttribute.java
Original file line number Diff line number Diff line change
@@ -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);
}
Comment on lines +33 to +36
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We call this in sentry/src/main/java/io/sentry/SentryAttributes.java when building attributes from a Map.
As we take in a generic Map, the key for an entry could be null.
We should check for nulls either here (making the name param nullable and e.g. not constructing the attribute if it is) or in sentry/src/main/java/io/sentry/SentryAttributes.java when iterating the entry set.


public static @NotNull SentryAttribute booleanAttribute(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L: how about boolean, integer, etc. instead?

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);
}
}
15 changes: 15 additions & 0 deletions sentry/src/main/java/io/sentry/SentryAttributeType.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
44 changes: 44 additions & 0 deletions sentry/src/main/java/io/sentry/SentryAttributes.java
Original file line number Diff line number Diff line change
@@ -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<SentryAttribute> attributes;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we change this to Map<String, SentryAttribute>?
Now it's possible to add multiple times the same attribute, but only the last one will actually be sent


private SentryAttributes(final @NotNull List<SentryAttribute> attributes) {
this.attributes = attributes;
}

public void add(final @Nullable SentryAttribute attribute) {
if (attribute == null) {
return;
}
attributes.add(attribute);
}

public @NotNull List<SentryAttribute> getAttributes() {
return attributes;
}

public static @NotNull SentryAttributes of(SentryAttribute... attributes) {
return new SentryAttributes(Arrays.asList(attributes));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where we use this class, we rely on this.attributes not containing nulls, however one or more elements in the list could be null and we would include them in the list, risking a NPE down the line.

}

public static @NotNull SentryAttributes fromMap(final @Nullable Map<String, Object> attributes) {
if (attributes == null) {
return new SentryAttributes(new ArrayList<>());
}
SentryAttributes sentryAttributes = new SentryAttributes(new ArrayList<>(attributes.size()));
for (Map.Entry<String, Object> attribute : attributes.entrySet()) {
sentryAttributes.add(SentryAttribute.named(attribute.getKey(), attribute.getValue()));
}
Comment on lines +38 to +40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, we could filter for nulls here.


return sentryAttributes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
10 changes: 1 addition & 9 deletions sentry/src/main/java/io/sentry/logger/ILoggerApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -31,15 +30,8 @@ void log(
@Nullable Object... args);

void log(
@Nullable Map<String, Object> attributes,
@NotNull SentryLogLevel level,
@Nullable String message,
@Nullable Object... args);

void log(
@Nullable Map<String, Object> attributes,
@NotNull SentryLogLevel level,
@Nullable SentryDate timestamp,
@NotNull LogParams params,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L: should it be named SentryLogParams or SentryLogParameters maybe?

@Nullable String message,
@Nullable Object... args);
}
42 changes: 42 additions & 0 deletions sentry/src/main/java/io/sentry/logger/LogParams.java
Original file line number Diff line number Diff line change
@@ -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;
}
Comment on lines +29 to +37
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this not directly the constructor?


public static @NotNull LogParams create(final @Nullable SentryAttributes attributes) {
return create(null, attributes);
}
}
Loading
Loading