Skip to content

Commit 9cc652c

Browse files
authored
Merge 7d5276d into 604a261
2 parents 604a261 + 7d5276d commit 9cc652c

5 files changed

Lines changed: 136 additions & 0 deletions

File tree

CHANGELOG.md

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

33
## Unreleased
44

5+
### Features
6+
7+
- Add session replay id to Sentry Logs ([#4740](https://github.com/getsentry/sentry-java/pull/4740))
8+
59
### Fixes
610

711
- Start performance collection on AppStart continuous profiling ([#4752](https://github.com/getsentry/sentry-java/pull/4752))

sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/MainActivity.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.sentry.ISpan;
1313
import io.sentry.MeasurementUnit;
1414
import io.sentry.Sentry;
15+
import io.sentry.SentryLogLevel;
1516
import io.sentry.UpdateStatus;
1617
import io.sentry.instrumentation.file.SentryFileOutputStream;
1718
import io.sentry.protocol.Feedback;
@@ -340,7 +341,10 @@ public void run() {
340341
});
341342
});
342343

344+
Sentry.logger().log(SentryLogLevel.INFO, "Creating content view");
343345
setContentView(binding.getRoot());
346+
347+
Sentry.logger().log(SentryLogLevel.INFO, "MainActivity created");
344348
}
345349

346350
private void stackOverflow() {

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,26 @@ private void captureLog(
211211
"sentry.environment",
212212
new SentryLogEventAttributeValue(SentryAttributeType.STRING, environment));
213213
}
214+
215+
final @Nullable SentryId scopeReplayId = scopes.getCombinedScopeView().getReplayId();
216+
if (!scopeReplayId.equals(SentryId.EMPTY_ID)) {
217+
attributes.put(
218+
"sentry.replay_id",
219+
new SentryLogEventAttributeValue(SentryAttributeType.STRING, scopeReplayId.toString()));
220+
} else {
221+
final @Nullable SentryId controllerReplayId =
222+
scopes.getOptions().getReplayController().getReplayId();
223+
if (!controllerReplayId.equals(SentryId.EMPTY_ID)) {
224+
attributes.put(
225+
"sentry.replay_id",
226+
new SentryLogEventAttributeValue(
227+
SentryAttributeType.STRING, controllerReplayId.toString()));
228+
attributes.put(
229+
"sentry._internal.replay_is_buffering",
230+
new SentryLogEventAttributeValue(SentryAttributeType.BOOLEAN, true));
231+
}
232+
}
233+
214234
final @Nullable String release = scopes.getOptions().getRelease();
215235
if (release != null) {
216236
attributes.put(

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.sentry
22

33
import io.sentry.Scope.IWithSession
4+
import io.sentry.protocol.SentryId
45
import kotlin.test.assertEquals
56
import kotlin.test.assertNull
67
import kotlin.test.assertSame
@@ -120,4 +121,9 @@ class NoOpScopeTest {
120121
}
121122

122123
@Test fun `clone returns the same instance`() = assertSame(NoOpScope.getInstance(), sut.clone())
124+
125+
@Test
126+
fun `getReplayId returns empty id`() {
127+
assertEquals(SentryId.EMPTY_ID, sut.replayId)
128+
}
123129
}

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

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,6 +2927,108 @@ class ScopesTest {
29272927
)
29282928
}
29292929

2930+
@Test
2931+
fun `adds session replay id to log attributes`() {
2932+
val (sut, mockClient) = getEnabledScopes { it.logs.isEnabled = true }
2933+
val replayId = SentryId()
2934+
sut.scope.replayId = replayId
2935+
sut.logger().log(SentryLogLevel.WARN, "log message")
2936+
2937+
verify(mockClient)
2938+
.captureLog(
2939+
check {
2940+
assertEquals("log message", it.body)
2941+
val logReplayId = it.attributes?.get("sentry.replay_id")!!
2942+
assertEquals(replayId.toString(), logReplayId.value)
2943+
},
2944+
anyOrNull(),
2945+
)
2946+
}
2947+
2948+
@Test
2949+
fun `missing session replay id do not break attributes`() {
2950+
val (sut, mockClient) = getEnabledScopes { it.logs.isEnabled = true }
2951+
sut.logger().log(SentryLogLevel.WARN, "log message")
2952+
2953+
verify(mockClient)
2954+
.captureLog(
2955+
check {
2956+
assertEquals("log message", it.body)
2957+
val logReplayId = it.attributes?.get("sentry.replay_id")
2958+
assertNull(logReplayId)
2959+
},
2960+
anyOrNull(),
2961+
)
2962+
}
2963+
2964+
@Test
2965+
fun `does not add session replay buffering to log attributes if no replay id in scope and in controller`() {
2966+
val (sut, mockClient) = getEnabledScopes { it.logs.isEnabled = true }
2967+
2968+
sut.logger().log(SentryLogLevel.WARN, "log message")
2969+
assertEquals(SentryId.EMPTY_ID, sut.options.replayController.replayId)
2970+
2971+
verify(mockClient)
2972+
.captureLog(
2973+
check {
2974+
assertEquals("log message", it.body)
2975+
val logReplayId = it.attributes?.get("sentry.replay_id")
2976+
val logReplayType = it.attributes?.get("sentry._internal.replay_is_buffering")
2977+
assertNull(logReplayId)
2978+
assertNull(logReplayType)
2979+
},
2980+
anyOrNull(),
2981+
)
2982+
}
2983+
2984+
@Test
2985+
fun `does not add session replay buffering to log attributes if replay id in scope`() {
2986+
val (sut, mockClient) = getEnabledScopes { it.logs.isEnabled = true }
2987+
val replayId = SentryId()
2988+
sut.scope.replayId = replayId
2989+
2990+
sut.logger().log(SentryLogLevel.WARN, "log message")
2991+
2992+
verify(mockClient)
2993+
.captureLog(
2994+
check {
2995+
assertEquals("log message", it.body)
2996+
val logReplayId = it.attributes?.get("sentry.replay_id")
2997+
val logReplayType = it.attributes?.get("sentry._internal.replay_is_buffering")
2998+
assertEquals(replayId.toString(), logReplayId!!.value)
2999+
assertNull(logReplayType)
3000+
},
3001+
anyOrNull(),
3002+
)
3003+
}
3004+
3005+
@Test
3006+
fun `adds session replay buffering to log attributes if replay id in controller and not in scope`() {
3007+
val mockReplayController = mock<ReplayController>()
3008+
val (sut, mockClient) =
3009+
getEnabledScopes {
3010+
it.logs.isEnabled = true
3011+
it.setReplayController(mockReplayController)
3012+
}
3013+
val replayId = SentryId()
3014+
sut.scope.replayId = SentryId.EMPTY_ID
3015+
whenever(mockReplayController.replayId).thenReturn(replayId)
3016+
3017+
sut.logger().log(SentryLogLevel.WARN, "log message")
3018+
3019+
verify(mockClient)
3020+
.captureLog(
3021+
check {
3022+
assertEquals("log message", it.body)
3023+
val logReplayId = it.attributes?.get("sentry.replay_id")
3024+
val logReplayType = it.attributes?.get("sentry._internal.replay_is_buffering")!!
3025+
assertEquals(replayId.toString(), logReplayId!!.value)
3026+
assertTrue(logReplayType.value as Boolean)
3027+
},
3028+
anyOrNull(),
3029+
)
3030+
}
3031+
29303032
// endregion
29313033

29323034
@Test

0 commit comments

Comments
 (0)