Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.automattic.android.tracks.crashlogging

interface CrashLogging {

/**
* Records a breadcrumb during the app lifecycle but doesn't report an event. This basically
* adds more context for the next reports created and sent by [sendReport] or an unhandled
Expand Down Expand Up @@ -40,4 +39,9 @@ interface CrashLogging {
tags: Map<String, String> = emptyMap(),
message: String? = null
)

fun sendJavaScriptReport(
jsException: JsException,
callback: JsExceptionCallback
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.automattic.android.tracks.crashlogging

data class JsException(
val type: String,
val message: String,
var stackTrace: List<JsExceptionStackTraceElement>,
val context: Map<String, Any>,
val tags: Map<String, String>,
val isHandled: Boolean,
val handledBy: String
)

data class JsExceptionStackTraceElement(
val fileName: String?,
val lineNumber: Int?,
val colNumber: Int?,
val function: String
)

interface JsExceptionCallback {
fun onReportSent(sent: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ import com.automattic.android.tracks.crashlogging.CrashLogging
import com.automattic.android.tracks.crashlogging.CrashLoggingDataProvider
import com.automattic.android.tracks.crashlogging.CrashLoggingUser
import com.automattic.android.tracks.crashlogging.ExtraKnownKey
import com.automattic.android.tracks.crashlogging.JsException
import com.automattic.android.tracks.crashlogging.JsExceptionCallback
import com.automattic.android.tracks.crashlogging.PerformanceMonitoringConfig.Disabled
import com.automattic.android.tracks.crashlogging.PerformanceMonitoringConfig.Enabled
import com.automattic.android.tracks.crashlogging.eventLevel
import io.sentry.Breadcrumb
import io.sentry.Sentry
import io.sentry.SentryEvent
import io.sentry.SentryLevel
import io.sentry.SentryOptions
import io.sentry.android.fragment.FragmentLifecycleIntegration
import io.sentry.protocol.Mechanism
import io.sentry.protocol.Message
import io.sentry.protocol.SentryException
import io.sentry.protocol.SentryStackFrame
import io.sentry.protocol.SentryStackTrace
import io.sentry.protocol.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
Expand All @@ -24,7 +31,6 @@ internal class SentryCrashLogging constructor(
private val sentryWrapper: SentryErrorTrackerWrapper,
applicationScope: CoroutineScope
) : CrashLogging {

init {
sentryWrapper.initialize(application) { options ->

Expand Down Expand Up @@ -134,6 +140,46 @@ internal class SentryCrashLogging constructor(
sentryWrapper.captureEvent(event)
}

override fun sendJavaScriptReport(
jsException: JsException,
callback: JsExceptionCallback
) {
val frames = jsException.stackTrace.map {
SentryStackFrame().apply {
this.filename = it.fileName
this.function = it.function
this.lineno = it.lineNumber
this.colno = it.colNumber
this.isInApp = true
}
}.toMutableList()

val sentryException = SentryException().apply {
this.type = jsException.type
this.value = jsException.message
this.module = "javascript"
this.stacktrace = SentryStackTrace().apply { this.frames = frames }
this.mechanism = Mechanism().apply {
this.isHandled = jsException.isHandled
this.type = jsException.handledBy
}
}

val event = SentryEvent().apply {
this.message = Message().apply { this.message = message }
this.level = SentryLevel.FATAL
this.platform = "javascript"
this.appendTags(jsException.tags)
this.exceptions = mutableListOf(sentryException)
}

Sentry.configureScope { scope ->
scope.setContexts("react_native_context", jsException.context)
}
sentryWrapper.captureEvent(event)
callback.onReportSent(true)
}

private fun SentryEvent.appendTags(tags: Map<String, String>) {
for ((key, value) in tags) {
this.setTag(key, value)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.example.sampletracksapp

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.automattic.android.tracks.crashlogging.CrashLoggingDataProvider
import com.automattic.android.tracks.crashlogging.CrashLoggingOkHttpInterceptorProvider
import com.automattic.android.tracks.crashlogging.CrashLoggingProvider
import com.automattic.android.tracks.crashlogging.CrashLoggingUser
import com.automattic.android.tracks.crashlogging.EventLevel
import com.automattic.android.tracks.crashlogging.ExtraKnownKey
import com.automattic.android.tracks.crashlogging.JsException
import com.automattic.android.tracks.crashlogging.JsExceptionCallback
import com.automattic.android.tracks.crashlogging.JsExceptionStackTraceElement
import com.automattic.android.tracks.crashlogging.PerformanceMonitoringConfig
import com.automattic.android.tracks.crashlogging.RequestFormatter
import com.automattic.android.tracks.crashlogging.performance.PerformanceMonitoringRepositoryProvider
Expand All @@ -26,7 +30,6 @@ import java.io.IOException
import java.util.Locale

class MainActivity : AppCompatActivity() {

val transactionRepository: PerformanceTransactionRepository =
PerformanceMonitoringRepositoryProvider.createInstance()

Expand Down Expand Up @@ -89,6 +92,31 @@ class MainActivity : AppCompatActivity() {
crashLogging.sendReport(exception = Exception("Exception from Tracks test app"))
}

sendReportWithJavaScriptException.setOnClickListener {
val callback = object : JsExceptionCallback {
override fun onReportSent(sent: Boolean) {
Log.d("JsExceptionCallback", "onReportSent: $sent")
}
}
val jsException = JsException(
type = "Error",
message = "JavaScript exception from Tracks test app",
stackTrace = listOf(
JsExceptionStackTraceElement(
fileName = "file.js",
lineNumber = 1,
colNumber = 1,
function = "function"
)
),
context = mapOf("context" to "value"),
tags = mapOf("tag" to "SomeTag"),
isHandled = true,
handledBy = "SomeHandler"
)
crashLogging.sendJavaScriptReport(jsException, callback)
}

recordBreadcrumbWithMessage.setOnClickListener {
crashLogging.recordEvent(
message = "Custom breadcrumb",
Expand Down
6 changes: 6 additions & 0 deletions sampletracksapp/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
android:layout_height="wrap_content"
android:text="Send report with exception" />

<Button
android:id="@+id/sendReportWithJavaScriptException"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send report with JS exception" />

<View
android:layout_width="match_parent"
android:layout_height="1dp"
Expand Down