Skip to content

Commit 3c30ab3

Browse files
authored
Merge pull request #2061 from DataDog/jmoskovich/limit-all-telemetryevents
Limit total telemetry events sent per session
2 parents f1b5178 + 45c2ff7 commit 3c30ab3

File tree

2 files changed

+37
-111
lines changed

2 files changed

+37
-111
lines changed

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/telemetry/internal/TelemetryEventHandler.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ internal class TelemetryEventHandler(
3838

3939
private var trackNetworkRequests = false
4040

41-
private val seenInCurrentSession = mutableSetOf<TelemetryEventId>()
41+
private val eventIDsSeenInCurrentSession = mutableSetOf<TelemetryEventId>()
42+
private var totalEventsSeenInCurrentSession = 0
4243

4344
@WorkerThread
4445
fun handleEvent(
@@ -47,7 +48,8 @@ internal class TelemetryEventHandler(
4748
) {
4849
if (!canWrite(event)) return
4950

50-
seenInCurrentSession.add(event.identity)
51+
eventIDsSeenInCurrentSession.add(event.identity)
52+
totalEventsSeenInCurrentSession++
5153

5254
sdkCore.getFeature(Feature.RUM_FEATURE_NAME)?.withWriteContext { datadogContext, eventBatchWriter ->
5355
val timestamp = event.eventTime.timestamp + datadogContext.time.serverTimeOffsetMs
@@ -105,7 +107,8 @@ internal class TelemetryEventHandler(
105107
}
106108

107109
override fun onSessionStarted(sessionId: String, isDiscarded: Boolean) {
108-
seenInCurrentSession.clear()
110+
eventIDsSeenInCurrentSession.clear()
111+
totalEventsSeenInCurrentSession = 0
109112
}
110113

111114
// region private
@@ -120,7 +123,7 @@ internal class TelemetryEventHandler(
120123

121124
val eventIdentity = event.identity
122125

123-
if (!event.isMetric && seenInCurrentSession.contains(eventIdentity)) {
126+
if (!event.isMetric && eventIDsSeenInCurrentSession.contains(eventIdentity)) {
124127
sdkCore.internalLogger.log(
125128
InternalLogger.Level.INFO,
126129
InternalLogger.Target.MAINTAINER,
@@ -129,7 +132,7 @@ internal class TelemetryEventHandler(
129132
return false
130133
}
131134

132-
if (seenInCurrentSession.size >= maxEventCountPerSession) {
135+
if (totalEventsSeenInCurrentSession >= maxEventCountPerSession) {
133136
sdkCore.internalLogger.log(
134137
InternalLogger.Level.INFO,
135138
InternalLogger.Target.MAINTAINER,

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/telemetry/internal/TelemetryEventHandlerTest.kt

Lines changed: 29 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -686,13 +686,18 @@ internal class TelemetryEventHandlerTest {
686686
}
687687

688688
@Test
689-
fun `M not write events over the limit W handleEvent(SendTelemetry)`(forge: Forge) {
689+
fun `M not write events over the limit W handleEvent(SendTelemetry)`() {
690690
// Given
691-
val events = forge.aList(size = MAX_EVENTS_PER_SESSION_TEST * 5) { createRumRawTelemetryEvent() }
692-
// remove unwanted identity collisions
693-
.groupBy { it.identity }.map { it.value.first() }
694-
val extraNumber = events.size - MAX_EVENTS_PER_SESSION_TEST
695-
val expectedInvocations = MAX_EVENTS_PER_SESSION_TEST
691+
val event = RumRawEvent.SendTelemetry(
692+
TelemetryType.DEBUG,
693+
"Metric event",
694+
null,
695+
null,
696+
coreConfiguration = null,
697+
additionalProperties = null,
698+
isMetric = true
699+
)
700+
val events = (0..MAX_EVENTS_PER_SESSION_TEST).map { event }
696701

697702
// When
698703
events.forEach {
@@ -701,122 +706,40 @@ internal class TelemetryEventHandlerTest {
701706

702707
// Then
703708
mockInternalLogger.verifyLog(
704-
InternalLogger.Level.INFO,
705-
InternalLogger.Target.MAINTAINER,
706-
TelemetryEventHandler.MAX_EVENT_NUMBER_REACHED_MESSAGE,
707-
mode = times(extraNumber)
709+
level = InternalLogger.Level.INFO,
710+
target = InternalLogger.Target.MAINTAINER,
711+
message = TelemetryEventHandler.MAX_EVENT_NUMBER_REACHED_MESSAGE
708712
)
709-
710-
argumentCaptor<Any> {
711-
verify(mockWriter, times(expectedInvocations))
712-
.write(eq(mockEventBatchWriter), capture(), eq(EventType.TELEMETRY))
713-
allValues.withIndex().forEach {
714-
when (val capturedValue = it.value) {
715-
is TelemetryDebugEvent -> {
716-
assertDebugEventMatchesRawEvent(
717-
capturedValue,
718-
events[it.index],
719-
fakeRumContext
720-
)
721-
}
722-
723-
is TelemetryErrorEvent -> {
724-
assertErrorEventMatchesRawEvent(
725-
capturedValue,
726-
events[it.index],
727-
fakeRumContext
728-
)
729-
}
730-
731-
is TelemetryConfigurationEvent -> {
732-
assertConfigEventMatchesRawEvent(
733-
capturedValue,
734-
events[it.index],
735-
fakeRumContext
736-
)
737-
}
738-
739-
else -> throw IllegalArgumentException(
740-
"Unexpected type=${lastValue::class.jvmName} of the captured value."
741-
)
742-
}
743-
}
744-
}
745713
}
746714

747715
@Test
748716
fun `M continue writing events after new session W handleEvent(SendTelemetry)`(forge: Forge) {
749717
// Given
750-
val eventMap = mutableMapOf<TelemetryEventId, RumRawEvent.SendTelemetry>()
751-
while (eventMap.size <= MAX_EVENTS_PER_SESSION_TEST) {
752-
val candidate = forge.createRumRawTelemetryEvent()
753-
val id = candidate.identity
754-
eventMap[id] = candidate
755-
}
756-
val eventsInOldSession = eventMap.map { it.value }
757-
val extraNumber = eventsInOldSession.size - MAX_EVENTS_PER_SESSION_TEST
758-
759-
val eventsInNewSession = forge.aList(
760-
size = forge.anInt(1, MAX_EVENTS_PER_SESSION_TEST)
761-
) { createRumRawTelemetryEvent() }
762-
// remove unwanted identity collisions
763-
.groupBy { it.identity }.map { it.value.first() }
764-
765-
val expectedEvents = eventsInOldSession
766-
.take(MAX_EVENTS_PER_SESSION_TEST) + eventsInNewSession
767-
val expectedInvocations = expectedEvents.size
718+
val event = RumRawEvent.SendTelemetry(
719+
TelemetryType.DEBUG,
720+
"Metric event",
721+
null,
722+
null,
723+
coreConfiguration = null,
724+
additionalProperties = null,
725+
isMetric = true // important because non-metric events can only be seen once
726+
)
727+
val eventsInOldSession = (0..MAX_EVENTS_PER_SESSION_TEST / 2).map { event }
728+
val eventsInNewSession = (0..MAX_EVENTS_PER_SESSION_TEST / 2).map { event }
768729

769-
// When
770730
eventsInOldSession.forEach {
771731
testedTelemetryHandler.handleEvent(it, mockWriter)
772732
}
733+
734+
// When
773735
testedTelemetryHandler.onSessionStarted(forge.aString(), forge.aBool())
736+
774737
eventsInNewSession.forEach {
775738
testedTelemetryHandler.handleEvent(it, mockWriter)
776739
}
777740

778741
// Then
779-
mockInternalLogger.verifyLog(
780-
InternalLogger.Level.INFO,
781-
InternalLogger.Target.MAINTAINER,
782-
TelemetryEventHandler.MAX_EVENT_NUMBER_REACHED_MESSAGE,
783-
mode = times(extraNumber)
784-
)
785-
argumentCaptor<Any> {
786-
verify(mockWriter, times(expectedInvocations))
787-
.write(eq(mockEventBatchWriter), capture(), eq(EventType.TELEMETRY))
788-
allValues.withIndex().forEach {
789-
when (val capturedValue = it.value) {
790-
is TelemetryDebugEvent -> {
791-
assertDebugEventMatchesRawEvent(
792-
capturedValue,
793-
expectedEvents[it.index],
794-
fakeRumContext
795-
)
796-
}
797-
798-
is TelemetryErrorEvent -> {
799-
assertErrorEventMatchesRawEvent(
800-
capturedValue,
801-
expectedEvents[it.index],
802-
fakeRumContext
803-
)
804-
}
805-
806-
is TelemetryConfigurationEvent -> {
807-
assertConfigEventMatchesRawEvent(
808-
capturedValue,
809-
expectedEvents[it.index],
810-
fakeRumContext
811-
)
812-
}
813-
814-
else -> throw IllegalArgumentException(
815-
"Unexpected type=${lastValue::class.jvmName} of the captured value."
816-
)
817-
}
818-
}
819-
}
742+
verifyNoMoreInteractions(mockInternalLogger)
820743
}
821744

822745
@Test

0 commit comments

Comments
 (0)