Skip to content

Commit

Permalink
feat: Add source_type when sent from cross platform logs
Browse files Browse the repository at this point in the history
Send `source_type` as a property on `error` when the attribute `_dd.error.source_type` is set on the log.
  • Loading branch information
fuzzybinary committed Feb 29, 2024
1 parent 9c75335 commit 36c5012
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 8 deletions.
1 change: 1 addition & 0 deletions dd-sdk-android-core/api/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ object com.datadog.android.log.LogAttributes
const val USR_ID: String
const val USR_NAME: String
const val VARIANT: String
const val SOURCE_TYPE: String
enum com.datadog.android.privacy.TrackingConsent
- GRANTED
- NOT_GRANTED
Expand Down
1 change: 1 addition & 0 deletions dd-sdk-android-core/api/dd-sdk-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,7 @@ public final class com/datadog/android/log/LogAttributes {
public static final field RUM_VIEW_ID Ljava/lang/String;
public static final field SERVICE_NAME Ljava/lang/String;
public static final field SOURCE Ljava/lang/String;
public static final field SOURCE_TYPE Ljava/lang/String;
public static final field STATUS Ljava/lang/String;
public static final field USR_ATTRIBUTES_GROUP Ljava/lang/String;
public static final field USR_EMAIL Ljava/lang/String;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,10 @@ object LogAttributes {
* This value is filled automatically by the [Logger].
*/
const val VARIANT: String = "variant"

/**
* The source type of an error. Used by cross platform tools to indicate the language
* or platform that the error originates from, such as Flutter or React Native (String).
*/
const val SOURCE_TYPE: String = "_dd.error.source.type"
}
2 changes: 1 addition & 1 deletion features/dd-sdk-android-logs/api/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ data class com.datadog.android.log.model.LogEvent
fun fromJson(kotlin.String): Network
fun fromJsonObject(com.google.gson.JsonObject): Network
data class Error
constructor(kotlin.String? = null, kotlin.String? = null, kotlin.String? = null, kotlin.collections.List<Thread>? = null)
constructor(kotlin.String? = null, kotlin.String? = null, kotlin.String? = null, kotlin.String? = null, kotlin.collections.List<Thread>? = null)
fun toJson(): com.google.gson.JsonElement
companion object
fun fromJson(kotlin.String): Error
Expand Down
13 changes: 8 additions & 5 deletions features/dd-sdk-android-logs/api/dd-sdk-android-logs.api
Original file line number Diff line number Diff line change
Expand Up @@ -194,24 +194,27 @@ public final class com/datadog/android/log/model/LogEvent$Device$Companion {
public final class com/datadog/android/log/model/LogEvent$Error {
public static final field Companion Lcom/datadog/android/log/model/LogEvent$Error$Companion;
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/util/List;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Lcom/datadog/android/log/model/LogEvent$Error;
public static synthetic fun copy$default (Lcom/datadog/android/log/model/LogEvent$Error;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lcom/datadog/android/log/model/LogEvent$Error;
public final fun component4 ()Ljava/lang/String;
public final fun component5 ()Ljava/util/List;
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Lcom/datadog/android/log/model/LogEvent$Error;
public static synthetic fun copy$default (Lcom/datadog/android/log/model/LogEvent$Error;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lcom/datadog/android/log/model/LogEvent$Error;
public fun equals (Ljava/lang/Object;)Z
public static final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/log/model/LogEvent$Error;
public static final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/log/model/LogEvent$Error;
public final fun getKind ()Ljava/lang/String;
public final fun getMessage ()Ljava/lang/String;
public final fun getSourceType ()Ljava/lang/String;
public final fun getStack ()Ljava/lang/String;
public final fun getThreads ()Ljava/util/List;
public fun hashCode ()I
public final fun setKind (Ljava/lang/String;)V
public final fun setMessage (Ljava/lang/String;)V
public final fun setSourceType (Ljava/lang/String;)V
public final fun setStack (Ljava/lang/String;)V
public final fun toJson ()Lcom/google/gson/JsonElement;
public fun toString ()Ljava/lang/String;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@
"description": "The error stack trace",
"readOnly": false
},
"source_type": {
"type": "string",
"description": "The source_type of the error (e.g. 'android', 'flutter', 'react-native')",
"readOnly": false
},
"threads": {
"type": "array",
"description": "Description of each thread in the process when error happened.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,19 @@ internal class DatadogLogGenerator(
userInfo: UserInfo?,
networkInfo: NetworkInfo?
): LogEvent {
val mutableAttributes = attributes.toMutableMap()
val error = if (errorKind != null || errorMessage != null || errorStack != null) {
LogEvent.Error(kind = errorKind, message = errorMessage, stack = errorStack)
val sourceType = mutableAttributes.remove(LogAttributes.SOURCE_TYPE) as? String
LogEvent.Error(kind = errorKind, message = errorMessage, stack = errorStack,
sourceType = sourceType)
} else {
null
}
return internalGenerateLog(
level,
message,
error,
attributes,
mutableAttributes,
tags,
timestamp,
threadName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import fr.xgouchet.elmyr.annotation.StringForgery
import fr.xgouchet.elmyr.annotation.StringForgeryType
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
import fr.xgouchet.elmyr.junit5.ForgeExtension
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -314,6 +315,70 @@ internal class DatadogLogGeneratorTest {
)
}

@Test
fun `M note add sourceType W creating the Log { source_type attribute not set }`() {
// WHEN
val log = testedLogGenerator.generateLog(
fakeLevel,
fakeLogMessage,
fakeThrowable,
fakeAttributes,
fakeTags,
fakeTimestamp,
fakeThreadName,
fakeDatadogContext,
attachNetworkInfo = true,
fakeLoggerName
)

// THEN
assertThat(log).hasError(
LogEvent.Error(
kind = fakeThrowable.javaClass.canonicalName,
stack = fakeThrowable.stackTraceToString(),
message = fakeThrowable.message,
sourceType = null,
threads = null
)
)
}

@Test
fun `M add sourceType W creating the Log { source_type attribute set }`(
forge: Forge
) {
// WHEN
val modifiedAttributes = fakeAttributes.toMutableMap().apply {
put(LogAttributes.SOURCE_TYPE, "fake_source_type")
}
val log = testedLogGenerator.generateLog(
fakeLevel,
fakeLogMessage,
fakeThrowable.javaClass.canonicalName,
fakeThrowable.message,
fakeThrowable.stackTraceToString(),
modifiedAttributes,
fakeTags,
fakeTimestamp,
fakeThreadName,
fakeDatadogContext,
attachNetworkInfo = true,
fakeLoggerName
)

// THEN
assertThat(log).hasError(
LogEvent.Error(
kind = fakeThrowable.javaClass.canonicalName,
stack = fakeThrowable.stackTraceToString(),
message = fakeThrowable.message,
sourceType = "fake_source_type",
threads = null
)
)
assertThat(log.additionalProperties).doesNotContainKey(LogAttributes.SOURCE_TYPE)
}

@Test
fun `M add the thread dump W creating the Log`(
@Forgery fakeThreads: List<ThreadDump>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ internal class LogEventSerializerTest {
val errorMessage = errorInfo.message
val errorKind = errorInfo.kind
val errorStack = errorInfo.stack
val errorSourceType = errorInfo.sourceType
if (errorMessage != null) {
hasField(KEY_MESSAGE, errorMessage)
} else {
Expand All @@ -325,6 +326,11 @@ internal class LogEventSerializerTest {
} else {
doesNotHaveField(KEY_STACK)
}
if (errorSourceType != null) {
hasField(KEY_SOURCE_TYPE, errorSourceType)
} else {
doesNotHaveField(KEY_SOURCE_TYPE)
}
}

// endregion
Expand All @@ -337,6 +343,7 @@ internal class LogEventSerializerTest {
private const val KEY_MESSAGE = "message"
private const val KEY_KIND = "kind"
private const val KEY_STACK = "stack"
private const val KEY_SOURCE_TYPE = "source_type"
private const val KEY_ERROR = "error"
private const val KEY_VERSION = "version"
private const val KEY_THREAD_NAME = "thread_name"
Expand Down

0 comments on commit 36c5012

Please sign in to comment.