@@ -12,6 +12,8 @@ import com.datadog.android.api.InternalLogger
1212import com.datadog.android.api.feature.Feature
1313import com.datadog.android.api.feature.FeatureScope
1414import com.datadog.android.api.feature.FeatureSdkCore
15+ import com.datadog.android.core.internal.CoreFeature
16+ import com.datadog.android.core.internal.DatadogCore
1517import com.datadog.android.core.internal.metrics.MethodCalledTelemetry
1618import com.datadog.android.core.metrics.TelemetryMetricType
1719import com.datadog.android.internal.attributes.LocalAttribute
@@ -105,8 +107,7 @@ internal class SdkInternalLoggerTest {
105107 forge : Forge
106108 ) {
107109 // Given
108- val mockLambda: () -> String = mock()
109- whenever(mockLambda.invoke()) doReturn fakeMessage
110+ val mockLambda = mockMessageLambda(fakeMessage)
110111 val fakeLevel = forge.aValueFrom(InternalLogger .Level ::class .java)
111112 val fakeThrowable = forge.aNullable { forge.aThrowable() }
112113 whenever(mockUserLogHandler.canLog(any())) doReturn true
@@ -134,8 +135,7 @@ internal class SdkInternalLoggerTest {
134135 forge : Forge
135136 ) {
136137 // Given
137- val mockLambda: () -> String = mock()
138- whenever(mockLambda.invoke()) doReturn fakeMessage
138+ val mockLambda = mockMessageLambda(fakeMessage)
139139 val fakeLevel = forge.aValueFrom(InternalLogger .Level ::class .java)
140140 val fakeThrowable = forge.aNullable { forge.aThrowable() }
141141 whenever(mockUserLogHandler.canLog(any())) doReturn true
@@ -186,12 +186,10 @@ internal class SdkInternalLoggerTest {
186186
187187 @Test
188188 fun `M not evaluate lambda W log { USER target }` (
189- @StringForgery fakeMessage : String ,
190189 forge : Forge
191190 ) {
192191 // Given
193- val mockLambda: () -> String = mock()
194- whenever(mockLambda.invoke()) doReturn fakeMessage
192+ val mockLambda = mockMessageLambda(forge.aString())
195193 val fakeLevel = forge.aValueFrom(InternalLogger .Level ::class .java)
196194 val fakeThrowable = forge.aNullable { forge.aThrowable() }
197195 whenever(mockUserLogHandler.canLog(any())) doReturn false
@@ -217,8 +215,7 @@ internal class SdkInternalLoggerTest {
217215 forge : Forge
218216 ) {
219217 // Given
220- val mockLambda: () -> String = mock()
221- whenever(mockLambda.invoke()) doReturn fakeMessage
218+ val mockLambda = mockMessageLambda(fakeMessage)
222219 val fakeLevel = forge.aValueFrom(InternalLogger .Level ::class .java)
223220 val fakeThrowable = forge.aNullable { forge.aThrowable() }
224221 whenever(mockMaintainerLogHandler.canLog(any())) doReturn true
@@ -245,8 +242,7 @@ internal class SdkInternalLoggerTest {
245242 forge : Forge
246243 ) {
247244 // Given
248- val mockLambda: () -> String = mock()
249- whenever(mockLambda.invoke()) doReturn fakeMessage
245+ val mockLambda = mockMessageLambda(fakeMessage)
250246 val fakeLevel = forge.aValueFrom(InternalLogger .Level ::class .java)
251247 val fakeThrowable = forge.aNullable { forge.aThrowable() }
252248 whenever(mockMaintainerLogHandler.canLog(any())) doReturn true
@@ -276,8 +272,7 @@ internal class SdkInternalLoggerTest {
276272 forge : Forge
277273 ) {
278274 // Given
279- val mockLambda: () -> String = mock()
280- whenever(mockLambda.invoke()) doReturn fakeMessage
275+ val mockLambda = mockMessageLambda(fakeMessage)
281276 val fakeLevel = forge.anElementFrom(InternalLogger .Level .INFO , InternalLogger .Level .DEBUG )
282277
283278 // When
@@ -306,8 +301,7 @@ internal class SdkInternalLoggerTest {
306301 val fakeAdditionalProperties = forge.aMap {
307302 forge.anAlphabeticalString() to forge.aNullable { anAlphabeticalString() }
308303 }
309- val mockLambda: () -> String = mock()
310- whenever(mockLambda.invoke()) doReturn fakeMessage
304+ val mockLambda = mockMessageLambda(fakeMessage)
311305 val fakeLevel = forge.anElementFrom(InternalLogger .Level .INFO , InternalLogger .Level .DEBUG )
312306
313307 // When
@@ -334,8 +328,7 @@ internal class SdkInternalLoggerTest {
334328 forge : Forge
335329 ) {
336330 // Given
337- val mockLambda: () -> String = mock()
338- whenever(mockLambda.invoke()) doReturn fakeMessage
331+ val mockLambda = mockMessageLambda(fakeMessage)
339332 val fakeLevel = forge.anElementFrom(InternalLogger .Level .INFO , InternalLogger .Level .DEBUG )
340333
341334 // When
@@ -363,8 +356,7 @@ internal class SdkInternalLoggerTest {
363356 ) {
364357 // Given
365358 val fakeAdditionalProperties = forge.exhaustiveAttributes()
366- val mockLambda: () -> String = mock()
367- whenever(mockLambda.invoke()) doReturn fakeMessage
359+ val mockLambda = mockMessageLambda(fakeMessage)
368360 val fakeLevel = forge.anElementFrom(InternalLogger .Level .WARN , InternalLogger .Level .ERROR )
369361
370362 // When
@@ -392,8 +384,7 @@ internal class SdkInternalLoggerTest {
392384 ) {
393385 // Given
394386 val fakeAdditionalProperties = forge.exhaustiveAttributes()
395- val mockLambda: () -> String = mock()
396- whenever(mockLambda.invoke()) doReturn fakeMessage
387+ val mockLambda = mockMessageLambda(fakeMessage)
397388 val fakeLevel = forge.aValueFrom(InternalLogger .Level ::class .java)
398389 val fakeThrowable = forge.aThrowable()
399390
@@ -422,8 +413,7 @@ internal class SdkInternalLoggerTest {
422413 forge : Forge
423414 ) {
424415 // Given
425- val mockLambda: () -> String = mock()
426- whenever(mockLambda.invoke()) doReturn fakeMessage
416+ val mockLambda = mockMessageLambda(fakeMessage)
427417 val fakeLevel = forge.anElementFrom(InternalLogger .Level .INFO , InternalLogger .Level .DEBUG )
428418
429419 // When
@@ -455,8 +445,7 @@ internal class SdkInternalLoggerTest {
455445 val fakeAdditionalProperties = forge.exhaustiveAttributes().also {
456446 it[LocalAttribute .Key .REPORTING_SAMPLING_RATE .toString()] = samplingRate
457447 }
458- val mockLambda: () -> String = mock()
459- whenever(mockLambda.invoke()) doReturn fakeMessage
448+ val mockLambda = mockMessageLambda(fakeMessage)
460449
461450 // When
462451 testedInternalLogger.logMetric(
@@ -481,10 +470,7 @@ internal class SdkInternalLoggerTest {
481470 forge : Forge
482471 ) {
483472 // Given
484- val mockLambda: () -> String = mock {
485- on { invoke() } doReturn forge.aString()
486- }
487- whenever(mockLambda.invoke()) doReturn forge.aString()
473+ val mockLambda = mockMessageLambda(forge.aString())
488474
489475 // When
490476 val samplingRate = 100.0f
@@ -518,6 +504,86 @@ internal class SdkInternalLoggerTest {
518504 }
519505 }
520506
507+ @Test
508+ fun `M use bypass metric telemetry sample rate W logMetric() {bypass is set}` (
509+ @StringForgery fakeMessage : String ,
510+ @FloatForgery(min = 0.0f , max = 100.0f ) fakeSampleRate : Float
511+ ) {
512+ // Given
513+ val bypassSampleRate = 100.0f
514+ givenLoggerWithMetricTelemetrySampleRateBypass(bypassSampleRate)
515+
516+ val mockLambda = mockMessageLambda(fakeMessage)
517+
518+ // When
519+ testedInternalLogger.logMetric(
520+ mockLambda,
521+ emptyMap(),
522+ fakeSampleRate,
523+ null
524+ )
525+
526+ // Then
527+ argumentCaptor<InternalTelemetryEvent > {
528+ verify(mockRumFeatureScope).sendEvent(capture())
529+ val metricEvent = firstValue as InternalTelemetryEvent .Metric
530+
531+ assertThat(
532+ metricEvent.additionalProperties?.get(LocalAttribute .Key .REPORTING_SAMPLING_RATE .toString())
533+ ).isEqualTo(bypassSampleRate)
534+ }
535+ }
536+
537+ @Test
538+ fun `M use hardcoded sample rate W logMetric() {bypass is null}` (
539+ @StringForgery fakeMessage : String
540+ ) {
541+ // Given
542+ val hardcodedSampleRate = 100.0f
543+ givenLoggerWithMetricTelemetrySampleRateBypass(null )
544+
545+ val mockLambda = mockMessageLambda(fakeMessage)
546+
547+ // When
548+ testedInternalLogger.logMetric(
549+ mockLambda,
550+ emptyMap(),
551+ hardcodedSampleRate,
552+ null
553+ )
554+
555+ // Then
556+ argumentCaptor<InternalTelemetryEvent > {
557+ verify(mockRumFeatureScope).sendEvent(capture())
558+ val metricEvent = firstValue as InternalTelemetryEvent .Metric
559+
560+ assertThat(
561+ metricEvent.additionalProperties?.get(LocalAttribute .Key .REPORTING_SAMPLING_RATE .toString())
562+ ).isEqualTo(hardcodedSampleRate)
563+ }
564+ }
565+
566+ @Test
567+ fun `M not send metric W logMetric() {bypass rate is 0}` (
568+ forge : Forge
569+ ) {
570+ // Given
571+ givenLoggerWithMetricTelemetrySampleRateBypass(0.0f )
572+
573+ val mockLambda = mockMessageLambda(forge.aString())
574+
575+ // When
576+ testedInternalLogger.logMetric(
577+ mockLambda,
578+ emptyMap(),
579+ 100.0f ,
580+ null
581+ )
582+
583+ // Then
584+ verify(mockRumFeatureScope, never()).sendEvent(any())
585+ }
586+
521587 @Test
522588 fun `M creationSampleRate is sent if present W logApiUsage() {sampling 100 percent}` (
523589 forge : Forge
@@ -635,8 +701,7 @@ internal class SdkInternalLoggerTest {
635701 ) {
636702 // Given
637703 val fakeAdditionalProperties = forge.exhaustiveAttributes()
638- val mockLambda: () -> String = mock()
639- whenever(mockLambda.invoke()) doReturn fakeMessage
704+ val mockLambda = mockMessageLambda(fakeMessage)
640705 val repeatCount = 100
641706 val expectedCallCount = (repeatCount * fakeSampleRate / 100f ).toInt()
642707 val marginOfError = (repeatCount * 0.25f ).toInt()
@@ -662,8 +727,7 @@ internal class SdkInternalLoggerTest {
662727 ) {
663728 // Given
664729 val fakeAdditionalProperties = forge.exhaustiveAttributes()
665- val mockLambda: () -> String = mock()
666- whenever(mockLambda.invoke()) doReturn fakeMessage
730+ val mockLambda = mockMessageLambda(fakeMessage)
667731
668732 // When
669733 testedInternalLogger.logMetric(
@@ -685,8 +749,7 @@ internal class SdkInternalLoggerTest {
685749 // Given
686750 whenever(mockSdkCore.getFeature(Feature .RUM_FEATURE_NAME )) doReturn null
687751 val fakeAdditionalProperties = forge.exhaustiveAttributes()
688- val mockLambda: () -> String = mock()
689- whenever(mockLambda.invoke()) doReturn fakeMessage
752+ val mockLambda = mockMessageLambda(fakeMessage)
690753
691754 // When
692755 assertDoesNotThrow {
@@ -815,6 +878,26 @@ internal class SdkInternalLoggerTest {
815878 assertThat(sampleCount).isCloseTo(expectedSampledCount, offset(margin))
816879 }
817880
881+ private fun mockMessageLambda (returnValue : String ): () -> String {
882+ val mockLambda: () -> String = mock()
883+ whenever(mockLambda.invoke()) doReturn returnValue
884+ return mockLambda
885+ }
886+
887+ private fun givenLoggerWithMetricTelemetrySampleRateBypass (sampleRate : Float? ) {
888+ val mockDatadogCore: DatadogCore = mock()
889+ val mockCoreFeature: CoreFeature = mock()
890+ whenever(mockDatadogCore.coreFeature) doReturn mockCoreFeature
891+ whenever(mockCoreFeature.metricTelemetrySampleRateBypass) doReturn sampleRate
892+ whenever(mockDatadogCore.getFeature(Feature .RUM_FEATURE_NAME )) doReturn mockRumFeatureScope
893+
894+ testedInternalLogger = SdkInternalLogger (
895+ sdkCore = mockDatadogCore,
896+ userLogHandlerFactory = { mockUserLogHandler },
897+ maintainerLogHandlerFactory = { mockMaintainerLogHandler }
898+ )
899+ }
900+
818901 private fun InternalLogger.Level.toLogLevel (): Int {
819902 return when (this ) {
820903 InternalLogger .Level .VERBOSE -> Log .VERBOSE
0 commit comments