Skip to content

Commit 0687e2d

Browse files
committed
RUM-12069: Add service name to ddtags of LogEvent
1 parent 2a08737 commit 0687e2d

9 files changed

Lines changed: 192 additions & 57 deletions

File tree

dd-sdk-android-core/api/apiSurface

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ object com.datadog.android.log.LogAttributes
378378
const val APPLICATION_PACKAGE: String
379379
const val APPLICATION_VERSION: String
380380
const val ENV: String
381+
const val SERVICE: String
381382
const val DATE: String
382383
const val DB_INSTANCE: String
383384
const val DB_OPERATION: String

dd-sdk-android-core/api/dd-sdk-android-core.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,7 @@ public final class com/datadog/android/log/LogAttributes {
10211021
public static final field RUM_APPLICATION_ID Ljava/lang/String;
10221022
public static final field RUM_SESSION_ID Ljava/lang/String;
10231023
public static final field RUM_VIEW_ID Ljava/lang/String;
1024+
public static final field SERVICE Ljava/lang/String;
10241025
public static final field SERVICE_NAME Ljava/lang/String;
10251026
public static final field SOURCE Ljava/lang/String;
10261027
public static final field SOURCE_TYPE Ljava/lang/String;

dd-sdk-android-core/src/main/kotlin/com/datadog/android/log/LogAttributes.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,17 @@ object LogAttributes {
3737
const val APPLICATION_VERSION: String = "version"
3838

3939
/**
40-
* The custom environment name. (Number)
40+
* The custom environment name. (String)
4141
* This value is filled automatically by the [Logger].
4242
*/
4343
const val ENV: String = "env"
4444

45+
/**
46+
* The service name. (String)
47+
* This value is filled automatically by the [Logger].
48+
*/
49+
const val SERVICE: String = "service"
50+
4551
/**
4652
* The date when the log is fired as an ISO-8601 String. (String)
4753
* This value is filled automatically by the [Logger].

features/dd-sdk-android-logs/src/main/kotlin/com/datadog/android/log/internal/domain/DatadogLogGenerator.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,15 @@ internal class DatadogLogGenerator(
260260
}
261261
}
262262

263+
private fun serviceTag(datadogContext: DatadogContext): String? {
264+
val service = datadogContext.service
265+
return if (service.isNotEmpty()) {
266+
"${LogAttributes.SERVICE}:$service"
267+
} else {
268+
null
269+
}
270+
}
271+
263272
private fun resolveNetworkInfo(
264273
datadogContext: DatadogContext,
265274
networkInfo: NetworkInfo?
@@ -316,6 +325,9 @@ internal class DatadogLogGenerator(
316325
variantTag(datadogContext)?.let {
317326
combinedTags.add(it)
318327
}
328+
serviceTag(datadogContext)?.let {
329+
combinedTags.add(it)
330+
}
319331

320332
return combinedTags
321333
}

features/dd-sdk-android-logs/src/test/kotlin/com/datadog/android/log/internal/LogsFeatureTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@ internal class LogsFeatureTest {
460460
setOf(
461461
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
462462
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
463-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
463+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
464+
"${LogAttributes.SERVICE}:${fakeDatadogContext.service}"
464465
)
465466
)
466467
}

features/dd-sdk-android-logs/src/test/kotlin/com/datadog/android/log/internal/domain/DatadogLogGeneratorTest.kt

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import fr.xgouchet.elmyr.annotation.StringForgery
2525
import fr.xgouchet.elmyr.annotation.StringForgeryType
2626
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
2727
import fr.xgouchet.elmyr.junit5.ForgeExtension
28-
import org.assertj.core.api.Assertions
2928
import org.assertj.core.api.Assertions.assertThat
3029
import org.junit.jupiter.api.BeforeEach
3130
import org.junit.jupiter.api.Test
@@ -737,7 +736,7 @@ internal class DatadogLogGeneratorTest {
737736

738737
// THEN
739738
val deserializedTags = log.ddtags.split(",")
740-
Assertions.assertThat(deserializedTags)
739+
assertThat(deserializedTags)
741740
.contains("${LogAttributes.ENV}:${fakeDatadogContext.env}")
742741
}
743742

@@ -765,7 +764,8 @@ internal class DatadogLogGeneratorTest {
765764
// THEN
766765
val expectedTags = fakeTags +
767766
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}" +
768-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
767+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}" +
768+
"${LogAttributes.SERVICE}:${fakeDatadogContext.service}"
769769
assertThat(log).hasExactlyTags(expectedTags)
770770
}
771771

@@ -787,7 +787,7 @@ internal class DatadogLogGeneratorTest {
787787

788788
// THEN
789789
val deserializedTags = log.ddtags.split(",")
790-
Assertions.assertThat(deserializedTags)
790+
assertThat(deserializedTags)
791791
.contains("${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}")
792792
}
793793

@@ -815,7 +815,8 @@ internal class DatadogLogGeneratorTest {
815815
// THEN
816816
val expectedTags = fakeTags +
817817
"${LogAttributes.ENV}:${fakeDatadogContext.env}" +
818-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
818+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}" +
819+
"${LogAttributes.SERVICE}:${fakeDatadogContext.service}"
819820
assertThat(log).hasExactlyTags(expectedTags)
820821
}
821822

@@ -837,7 +838,7 @@ internal class DatadogLogGeneratorTest {
837838

838839
// THEN
839840
val deserializedTags = log.ddtags.split(",")
840-
Assertions.assertThat(deserializedTags)
841+
assertThat(deserializedTags)
841842
.contains("${LogAttributes.VARIANT}:${fakeDatadogContext.variant}")
842843
}
843844

@@ -865,7 +866,59 @@ internal class DatadogLogGeneratorTest {
865866
// THEN
866867
val expectedTags = fakeTags +
867868
"${LogAttributes.ENV}:${fakeDatadogContext.env}" +
868-
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}"
869+
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}" +
870+
"${LogAttributes.SERVICE}:${fakeDatadogContext.service}"
871+
assertThat(log).hasExactlyTags(expectedTags)
872+
}
873+
874+
@Test
875+
fun `M add the serviceTag W not empty`() {
876+
// When
877+
val log = testedLogGenerator.generateLog(
878+
fakeLevel,
879+
fakeLogMessage,
880+
fakeThrowable,
881+
fakeAttributes,
882+
fakeTags,
883+
fakeTimestamp,
884+
fakeThreadName,
885+
fakeDatadogContext,
886+
attachNetworkInfo = true,
887+
fakeLoggerName
888+
)
889+
890+
// Then
891+
val deserializedTags = log.ddtags.split(",")
892+
assertThat(deserializedTags)
893+
.contains("${LogAttributes.SERVICE}:${fakeDatadogContext.service}")
894+
}
895+
896+
@Test
897+
fun `M not add the serviceTag W empty`() {
898+
// Given
899+
fakeDatadogContext = fakeDatadogContext.copy(
900+
service = ""
901+
)
902+
903+
// When
904+
val log = testedLogGenerator.generateLog(
905+
fakeLevel,
906+
fakeLogMessage,
907+
fakeThrowable,
908+
fakeAttributes,
909+
fakeTags,
910+
fakeTimestamp,
911+
fakeThreadName,
912+
fakeDatadogContext,
913+
attachNetworkInfo = true,
914+
fakeLoggerName
915+
)
916+
917+
// Then
918+
val expectedTags = fakeTags +
919+
"${LogAttributes.ENV}:${fakeDatadogContext.env}" +
920+
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}" +
921+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
869922
assertThat(log).hasExactlyTags(expectedTags)
870923
}
871924

@@ -906,7 +959,7 @@ internal class DatadogLogGeneratorTest {
906959
)
907960

908961
// THEN
909-
Assertions.assertThat(log.additionalProperties).containsAllEntriesOf(
962+
assertThat(log.additionalProperties).containsAllEntriesOf(
910963
mapOf(
911964
LogAttributes.DD_TRACE_ID to fakeTraceId,
912965
LogAttributes.DD_SPAN_ID to fakeSpanId
@@ -1036,7 +1089,7 @@ internal class DatadogLogGeneratorTest {
10361089
)
10371090

10381091
// THEN
1039-
Assertions.assertThat(log.additionalProperties).containsAllEntriesOf(
1092+
assertThat(log.additionalProperties).containsAllEntriesOf(
10401093
mapOf(
10411094
LogAttributes.RUM_APPLICATION_ID to fakeRumApplicationId,
10421095
LogAttributes.RUM_SESSION_ID to fakeRumSessionId,

features/dd-sdk-android-logs/src/test/kotlin/com/datadog/android/log/internal/logger/DatadogLogHandlerTest.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ internal class DatadogLogHandlerTest {
121121
fakeAttributes = forge.aMap { anAlphabeticalString() to anInt() }
122122
fakeTags = forge.aList { anAlphabeticalString() }.toSet()
123123
fakeDatadogContext = fakeDatadogContext.copy(
124+
service = fakeServiceName,
124125
time = fakeDatadogContext.time.copy(
125126
serverTimeOffsetMs = 0L
126127
),
@@ -209,7 +210,8 @@ internal class DatadogLogHandlerTest {
209210
fakeTags + setOf(
210211
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
211212
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
212-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
213+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
214+
"${LogAttributes.SERVICE}:$fakeServiceName"
213215
)
214216
)
215217
.doesNotHaveError()
@@ -290,7 +292,8 @@ internal class DatadogLogHandlerTest {
290292
fakeTags + setOf(
291293
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
292294
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
293-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
295+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
296+
"${LogAttributes.SERVICE}:$fakeServiceName"
294297
)
295298
)
296299
.hasError(
@@ -355,7 +358,8 @@ internal class DatadogLogHandlerTest {
355358
fakeTags + setOf(
356359
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
357360
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
358-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
361+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
362+
"${LogAttributes.SERVICE}:$fakeServiceName"
359363
)
360364
)
361365
.hasError(
@@ -614,7 +618,8 @@ internal class DatadogLogHandlerTest {
614618
fakeTags + setOf(
615619
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
616620
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
617-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
621+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
622+
"${LogAttributes.SERVICE}:$fakeServiceName"
618623
)
619624
)
620625
}
@@ -676,7 +681,8 @@ internal class DatadogLogHandlerTest {
676681
fakeTags + setOf(
677682
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
678683
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
679-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
684+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
685+
"${LogAttributes.SERVICE}:$fakeServiceName"
680686
)
681687
)
682688
}
@@ -736,7 +742,8 @@ internal class DatadogLogHandlerTest {
736742
fakeTags + setOf(
737743
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
738744
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
739-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
745+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
746+
"${LogAttributes.SERVICE}:$fakeServiceName"
740747
)
741748
)
742749
}
@@ -794,7 +801,8 @@ internal class DatadogLogHandlerTest {
794801
setOf(
795802
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
796803
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
797-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
804+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
805+
"${LogAttributes.SERVICE}:$fakeServiceName"
798806
)
799807
)
800808
.doesNotHaveError()
@@ -1104,7 +1112,8 @@ internal class DatadogLogHandlerTest {
11041112
fakeTags + setOf(
11051113
"${LogAttributes.ENV}:${fakeDatadogContext.env}",
11061114
"${LogAttributes.APPLICATION_VERSION}:${fakeDatadogContext.version}",
1107-
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}"
1115+
"${LogAttributes.VARIANT}:${fakeDatadogContext.variant}",
1116+
"${LogAttributes.SERVICE}:$fakeServiceName"
11081117
)
11091118
)
11101119
}

features/dd-sdk-android-webview/src/main/kotlin/com/datadog/android/webview/internal/log/WebViewLogEventConsumer.kt

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,38 +100,58 @@ internal class WebViewLogEventConsumer(
100100
}
101101

102102
private fun addDdTags(event: JsonObject, datadogContext: DatadogContext) {
103-
val sdkDdTags = "${LogAttributes.APPLICATION_VERSION}:${datadogContext.version}" +
104-
",${LogAttributes.ENV}:${datadogContext.env}"
105-
var eventDdTags: String? = null
106-
try {
107-
eventDdTags = event.get(DDTAGS_KEY_NAME)?.asString
103+
val sdkDdTags = mapOf(
104+
LogAttributes.APPLICATION_VERSION to datadogContext.version,
105+
LogAttributes.ENV to datadogContext.env,
106+
LogAttributes.VARIANT to datadogContext.variant,
107+
LogAttributes.SERVICE to datadogContext.service
108+
)
109+
val eventDdTags = try {
110+
event.get(DDTAGS_KEY_NAME)?.asString?.let {
111+
it.split(DDTAGS_SEPARATOR)
112+
.mapNotNull { tag ->
113+
@Suppress("UnsafeThirdPartyFunctionCall") // safe indexOf invocation
114+
val splitIndex = tag.indexOf(":")
115+
if (splitIndex == -1 || splitIndex == tag.lastIndex) {
116+
null
117+
} else {
118+
@Suppress("UnsafeThirdPartyFunctionCall") // safe substring invocations
119+
tag.substring(0, splitIndex) to tag.substring(splitIndex + 1)
120+
}
121+
}
122+
.associate { it }
123+
}.orEmpty()
108124
} catch (e: ClassCastException) {
109125
sdkCore.internalLogger.log(
110126
InternalLogger.Level.ERROR,
111127
listOf(InternalLogger.Target.MAINTAINER, InternalLogger.Target.TELEMETRY),
112128
{ JSON_PARSING_ERROR_MESSAGE },
113129
e
114130
)
131+
emptyMap<String, String>()
115132
} catch (e: IllegalStateException) {
116133
sdkCore.internalLogger.log(
117134
InternalLogger.Level.ERROR,
118135
listOf(InternalLogger.Target.MAINTAINER, InternalLogger.Target.TELEMETRY),
119136
{ JSON_PARSING_ERROR_MESSAGE },
120137
e
121138
)
139+
emptyMap<String, String>()
122140
} catch (e: UnsupportedOperationException) {
123141
sdkCore.internalLogger.log(
124142
InternalLogger.Level.ERROR,
125143
listOf(InternalLogger.Target.MAINTAINER, InternalLogger.Target.TELEMETRY),
126144
{ JSON_PARSING_ERROR_MESSAGE },
127145
e
128146
)
147+
emptyMap<String, String>()
129148
}
130-
if (eventDdTags.isNullOrEmpty()) {
131-
event.addProperty(DDTAGS_KEY_NAME, sdkDdTags)
132-
} else {
133-
event.addProperty(DDTAGS_KEY_NAME, sdkDdTags + DDTAGS_SEPARATOR + eventDdTags)
134-
}
149+
event.addProperty(
150+
DDTAGS_KEY_NAME,
151+
(eventDdTags + sdkDdTags)
152+
.map { "${it.key}:${it.value}" }
153+
.joinToString(DDTAGS_SEPARATOR)
154+
)
135155
}
136156

137157
companion object {

0 commit comments

Comments
 (0)