Skip to content

Commit 5ca032d

Browse files
committed
Extend Logs API to allow passing in attributes
1 parent eda4283 commit 5ca032d

File tree

5 files changed

+184
-4
lines changed

5 files changed

+184
-4
lines changed

sentry/api/sentry.api

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4712,6 +4712,8 @@ public abstract interface class io/sentry/logger/ILoggerApi {
47124712
public abstract fun info (Ljava/lang/String;[Ljava/lang/Object;)V
47134713
public abstract fun log (Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V
47144714
public abstract fun log (Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V
4715+
public abstract fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V
4716+
public abstract fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V
47154717
public abstract fun trace (Ljava/lang/String;[Ljava/lang/Object;)V
47164718
public abstract fun warn (Ljava/lang/String;[Ljava/lang/Object;)V
47174719
}
@@ -4729,6 +4731,8 @@ public final class io/sentry/logger/LoggerApi : io/sentry/logger/ILoggerApi {
47294731
public fun info (Ljava/lang/String;[Ljava/lang/Object;)V
47304732
public fun log (Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V
47314733
public fun log (Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V
4734+
public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V
4735+
public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V
47324736
public fun trace (Ljava/lang/String;[Ljava/lang/Object;)V
47334737
public fun warn (Ljava/lang/String;[Ljava/lang/Object;)V
47344738
}
@@ -4749,6 +4753,8 @@ public final class io/sentry/logger/NoOpLoggerApi : io/sentry/logger/ILoggerApi
47494753
public fun info (Ljava/lang/String;[Ljava/lang/Object;)V
47504754
public fun log (Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V
47514755
public fun log (Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V
4756+
public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Lio/sentry/SentryDate;Ljava/lang/String;[Ljava/lang/Object;)V
4757+
public fun log (Ljava/util/Map;Lio/sentry/SentryLogLevel;Ljava/lang/String;[Ljava/lang/Object;)V
47524758
public fun trace (Ljava/lang/String;[Ljava/lang/Object;)V
47534759
public fun warn (Ljava/lang/String;[Ljava/lang/Object;)V
47544760
}

sentry/src/main/java/io/sentry/logger/ILoggerApi.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.sentry.SentryDate;
44
import io.sentry.SentryLogLevel;
5+
import java.util.Map;
56
import org.jetbrains.annotations.ApiStatus;
67
import org.jetbrains.annotations.NotNull;
78
import org.jetbrains.annotations.Nullable;
@@ -28,4 +29,17 @@ void log(
2829
@Nullable SentryDate timestamp,
2930
@Nullable String message,
3031
@Nullable Object... args);
32+
33+
void log(
34+
@Nullable Map<String, Object> attributes,
35+
@NotNull SentryLogLevel level,
36+
@Nullable String message,
37+
@Nullable Object... args);
38+
39+
void log(
40+
@Nullable Map<String, Object> attributes,
41+
@NotNull SentryLogLevel level,
42+
@Nullable SentryDate timestamp,
43+
@Nullable String message,
44+
@Nullable Object... args);
3145
}

sentry/src/main/java/io/sentry/logger/LoggerApi.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.sentry.util.Platform;
1818
import io.sentry.util.TracingUtils;
1919
import java.util.HashMap;
20+
import java.util.Map;
2021
import org.jetbrains.annotations.ApiStatus;
2122
import org.jetbrains.annotations.NotNull;
2223
import org.jetbrains.annotations.Nullable;
@@ -65,7 +66,7 @@ public void log(
6566
final @NotNull SentryLogLevel level,
6667
final @Nullable String message,
6768
final @Nullable Object... args) {
68-
log(level, null, message, args);
69+
captureLog(null, level, null, message, args);
6970
}
7071

7172
@Override
@@ -74,11 +75,31 @@ public void log(
7475
final @Nullable SentryDate timestamp,
7576
final @Nullable String message,
7677
final @Nullable Object... args) {
77-
captureLog(level, timestamp, message, args);
78+
captureLog(null, level, timestamp, message, args);
79+
}
80+
81+
@Override
82+
public void log(
83+
final @Nullable Map<String, Object> attributes,
84+
final @NotNull SentryLogLevel level,
85+
final @Nullable SentryDate timestamp,
86+
final @Nullable String message,
87+
final @Nullable Object... args) {
88+
captureLog(attributes, level, timestamp, message, args);
89+
}
90+
91+
@Override
92+
public void log(
93+
final @Nullable Map<String, Object> attributes,
94+
final @NotNull SentryLogLevel level,
95+
final @Nullable String message,
96+
final @Nullable Object... args) {
97+
captureLog(attributes, level, null, message, args);
7898
}
7999

80100
@SuppressWarnings("AnnotateFormatMethod")
81101
private void captureLog(
102+
final @Nullable Map<String, Object> attributes,
82103
final @NotNull SentryLogLevel level,
83104
final @Nullable SentryDate timestamp,
84105
final @Nullable String message,
@@ -119,7 +140,7 @@ private void captureLog(
119140
span == null ? propagationContext.getSpanId() : span.getSpanContext().getSpanId();
120141
final SentryLogEvent logEvent =
121142
new SentryLogEvent(traceId, timestampToUse, messageToUse, level);
122-
logEvent.setAttributes(createAttributes(message, spanId, args));
143+
logEvent.setAttributes(createAttributes(attributes, message, spanId, args));
123144
logEvent.setSeverityNumber(level.getSeverityNumber());
124145

125146
scopes.getClient().captureLog(logEvent, combinedScope);
@@ -146,8 +167,20 @@ private void captureLog(
146167
}
147168

148169
private @NotNull HashMap<String, SentryLogEventAttributeValue> createAttributes(
149-
final @NotNull String message, final @NotNull SpanId spanId, final @Nullable Object... args) {
170+
final @Nullable Map<String, Object> incomingAttributes,
171+
final @NotNull String message,
172+
final @NotNull SpanId spanId,
173+
final @Nullable Object... args) {
150174
final @NotNull HashMap<String, SentryLogEventAttributeValue> attributes = new HashMap<>();
175+
176+
if (incomingAttributes != null) {
177+
for (Map.Entry<String, Object> attributeEntry : incomingAttributes.entrySet()) {
178+
final @Nullable Object value = attributeEntry.getValue();
179+
final @NotNull String type = getType(value);
180+
attributes.put(attributeEntry.getKey(), new SentryLogEventAttributeValue(type, value));
181+
}
182+
}
183+
151184
if (args != null) {
152185
int i = 0;
153186
for (Object arg : args) {

sentry/src/main/java/io/sentry/logger/NoOpLoggerApi.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.sentry.SentryDate;
44
import io.sentry.SentryLogLevel;
5+
import java.util.Map;
56
import org.jetbrains.annotations.ApiStatus;
67
import org.jetbrains.annotations.NotNull;
78
import org.jetbrains.annotations.Nullable;
@@ -61,4 +62,23 @@ public void log(
6162
@Nullable Object... args) {
6263
// do nothing
6364
}
65+
66+
@Override
67+
public void log(
68+
@Nullable Map<String, Object> attributes,
69+
@NotNull SentryLogLevel level,
70+
@Nullable String message,
71+
@Nullable Object... args) {
72+
// do nothing
73+
}
74+
75+
@Override
76+
public void log(
77+
@Nullable Map<String, Object> attributes,
78+
@NotNull SentryLogLevel level,
79+
@Nullable SentryDate timestamp,
80+
@Nullable String message,
81+
@Nullable Object... args) {
82+
// do nothing
83+
}
6484
}

sentry/src/test/java/io/sentry/ScopesTest.kt

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,6 +2628,113 @@ class ScopesTest {
26282628
)
26292629
}
26302630

2631+
@Test
2632+
fun `creating log with timestamp works`() {
2633+
val (sut, mockClient) = getEnabledScopes {
2634+
it.logs.isEnabled = true
2635+
}
2636+
2637+
sut.logger().log(SentryLogLevel.WARN, SentryLongDate(123), "log message")
2638+
2639+
verify(mockClient).captureLog(
2640+
check {
2641+
assertEquals("log message", it.body)
2642+
assertEquals(0.000000123, it.timestamp)
2643+
assertEquals(SentryLogLevel.WARN, it.level)
2644+
assertEquals(13, it.severityNumber)
2645+
},
2646+
anyOrNull()
2647+
)
2648+
}
2649+
2650+
@Test
2651+
fun `creating log with attributes works`() {
2652+
val (sut, mockClient) = getEnabledScopes {
2653+
it.logs.isEnabled = true
2654+
}
2655+
2656+
sut.logger().log(mapOf("attrname1" to "attrval1"), SentryLogLevel.WARN, "log message")
2657+
2658+
verify(mockClient).captureLog(
2659+
check {
2660+
assertEquals("log message", it.body)
2661+
assertEquals(SentryLogLevel.WARN, it.level)
2662+
assertEquals(13, it.severityNumber)
2663+
2664+
val attr1 = it.attributes?.get("attrname1")!!
2665+
assertEquals("attrval1", attr1.value)
2666+
assertEquals("string", attr1.type)
2667+
},
2668+
anyOrNull()
2669+
)
2670+
}
2671+
2672+
@Test
2673+
fun `creating log with attributes and timestamp works`() {
2674+
val (sut, mockClient) = getEnabledScopes {
2675+
it.logs.isEnabled = true
2676+
}
2677+
2678+
sut.logger().log(mapOf("attrname1" to "attrval1"), SentryLogLevel.WARN, SentryLongDate(123), "log message")
2679+
2680+
verify(mockClient).captureLog(
2681+
check {
2682+
assertEquals("log message", it.body)
2683+
assertEquals(0.000000123, it.timestamp)
2684+
assertEquals(SentryLogLevel.WARN, it.level)
2685+
assertEquals(13, it.severityNumber)
2686+
2687+
val attr1 = it.attributes?.get("attrname1")!!
2688+
assertEquals("attrval1", attr1.value)
2689+
assertEquals("string", attr1.type)
2690+
},
2691+
anyOrNull()
2692+
)
2693+
}
2694+
2695+
@Test
2696+
fun `creating log with attributes and timestamp and format string works`() {
2697+
val (sut, mockClient) = getEnabledScopes {
2698+
it.logs.isEnabled = true
2699+
}
2700+
2701+
sut.logger().log(mapOf("attrname1" to "attrval1"), SentryLogLevel.WARN, SentryLongDate(123), "log %s %d %b %.0f", "message", 1, true, 3.2)
2702+
2703+
verify(mockClient).captureLog(
2704+
check {
2705+
assertEquals("log message 1 true 3", it.body)
2706+
assertEquals(0.000000123, it.timestamp)
2707+
assertEquals(SentryLogLevel.WARN, it.level)
2708+
assertEquals(13, it.severityNumber)
2709+
2710+
val attr1 = it.attributes?.get("attrname1")!!
2711+
assertEquals("attrval1", attr1.value)
2712+
assertEquals("string", attr1.type)
2713+
2714+
val template = it.attributes?.get("sentry.message.template")!!
2715+
assertEquals("log %s %d %b %.0f", template.value)
2716+
assertEquals("string", template.type)
2717+
2718+
val param0 = it.attributes?.get("sentry.message.parameter.0")!!
2719+
assertEquals("message", param0.value)
2720+
assertEquals("string", param0.type)
2721+
2722+
val param1 = it.attributes?.get("sentry.message.parameter.1")!!
2723+
assertEquals(1, param1.value)
2724+
assertEquals("integer", param1.type)
2725+
2726+
val param2 = it.attributes?.get("sentry.message.parameter.2")!!
2727+
assertEquals(true, param2.value)
2728+
assertEquals("boolean", param2.type)
2729+
2730+
val param3 = it.attributes?.get("sentry.message.parameter.3")!!
2731+
assertEquals(3.2, param3.value)
2732+
assertEquals("double", param3.type)
2733+
},
2734+
anyOrNull()
2735+
)
2736+
}
2737+
26312738
@Test
26322739
fun `creating log with without args does not add template attribute`() {
26332740
val (sut, mockClient) = getEnabledScopes {

0 commit comments

Comments
 (0)