Skip to content

Commit

Permalink
Add Otel SpanLink use case into the sample app
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusc83 committed Apr 18, 2024
1 parent 94c4b4d commit 989c4e0
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ internal class SpansPayloadAssert(actual: JsonObject) :
}

fun hasGenericLinkedAttribute(key: String, value: List<String>): SpanAssert {
value.forEachIndexed { index, it ->
hasGenericLinkedAttribute("$key.$index", it)
value.forEachIndexed { index, valueAtIndex ->
hasGenericLinkedAttribute("$key.$index", valueAtIndex)
}
return this
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal class OtelTracesFragment : Fragment(), View.OnClickListener {
val rootView = inflater.inflate(R.layout.fragment_otel_traces, container, false)
rootView.findViewById<Button>(R.id.start_async_operation).setOnClickListener(this)
rootView.findViewById<Button>(R.id.start_chained_contexts_test).setOnClickListener(this)
rootView.findViewById<Button>(R.id.start_linked_spans_test).setOnClickListener(this)
progressBarAsync = rootView.findViewById(R.id.spinner_async)
return rootView
}
Expand Down Expand Up @@ -74,6 +75,14 @@ internal class OtelTracesFragment : Fragment(), View.OnClickListener {
}
)
}
R.id.start_linked_spans_test -> {
progressBarAsync.visibility = View.VISIBLE
viewModel.startLinkedSpans(
onDone = {
progressBarAsync.visibility = View.INVISIBLE
}
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.lifecycle.ViewModel
import com.datadog.android.log.Logger
import com.datadog.android.sample.BuildConfig
import io.opentelemetry.api.GlobalOpenTelemetry
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
Expand All @@ -22,6 +23,7 @@ internal class OtelTracesViewModel : ViewModel() {

private var asyncOperationTask: AsyncTask<Unit, Unit, Unit>? = null
private var chainedContextsTask: AsyncTask<Unit, Unit, Unit>? = null
private var linkedSpansTask: AsyncTask<Unit, Unit, Unit>? = null

fun startAsyncOperation(
onProgress: (Int) -> Unit = {},
Expand All @@ -31,16 +33,22 @@ internal class OtelTracesViewModel : ViewModel() {
asyncOperationTask?.execute()
}

fun stopAsyncOperations() {
asyncOperationTask?.cancel(true)
chainedContextsTask?.cancel(true)
}

fun startChainedContexts(onDone: () -> Unit = {}) {
chainedContextsTask = ChainedContextsTask(onDone)
chainedContextsTask?.execute()
}

fun startLinkedSpans(onDone: () -> Unit = {}) {
linkedSpansTask = LinkedSpansTask(onDone)
linkedSpansTask?.execute()
}

fun stopAsyncOperations() {
asyncOperationTask?.cancel(true)
chainedContextsTask?.cancel(true)
linkedSpansTask?.cancel(true)
}

// region AsyncOperationTask

private class AsyncOperationTask(
Expand All @@ -62,7 +70,7 @@ internal class OtelTracesViewModel : ViewModel() {
.build()
.apply {
addTag(ATTR_FLAVOR, BuildConfig.FLAVOR)
addTag("build_type", BuildConfig.BUILD_TYPE)
addTag(BUILD_TYPE, BuildConfig.BUILD_TYPE)
}
}

Expand Down Expand Up @@ -110,6 +118,10 @@ internal class OtelTracesViewModel : ViewModel() {
}
}

// endregion

// region ChainedContextsTask

private class ChainedContextsTask(
val onDone: () -> Unit
) : AsyncTask<Unit, Unit, Unit>() {
Expand All @@ -122,7 +134,7 @@ internal class OtelTracesViewModel : ViewModel() {
private val context: Context =
Context.current().with(emailKey, email).with(usernameKey, username)
val startSpan: Span = tracer
.spanBuilder("submitForm")
.spanBuilder("submitForm with chained contexts")
.setParent(context)
.startSpan()
val scope: Scope = startSpan.makeCurrent()
Expand All @@ -134,7 +146,7 @@ internal class OtelTracesViewModel : ViewModel() {
.build()
.apply {
addTag(ATTR_FLAVOR, BuildConfig.FLAVOR)
addTag("build_type", BuildConfig.BUILD_TYPE)
addTag(BUILD_TYPE, BuildConfig.BUILD_TYPE)
}
}

Expand Down Expand Up @@ -170,7 +182,69 @@ internal class OtelTracesViewModel : ViewModel() {

// endregion

// region LinkedSpansTask

private class LinkedSpansTask(
val onDone: () -> Unit
) : AsyncTask<Unit, Unit, Unit>() {
private val email = "[email protected]"
private val username = "John Doe"
private val tracer: Tracer = GlobalOpenTelemetry.get()
.getTracer("spanLinks")
val startSpan: Span = tracer
.spanBuilder("submitForm with linked spans")
.startSpan()
val scope: Scope = startSpan.makeCurrent()

private val logger: Logger by lazy {
Logger.Builder()
.setName("chained-contexts-task")
.setLogcatLogsEnabled(true)
.build()
.apply {
addTag(ATTR_FLAVOR, BuildConfig.FLAVOR)
addTag(BUILD_TYPE, BuildConfig.BUILD_TYPE)
}
}

@Suppress("MagicNumber")
@Deprecated("Deprecated in Java")
override fun doInBackground(vararg params: Unit?) {
val processingFormSpan = tracer
.spanBuilder("processingForm")
.setParent(Context.current().with(startSpan))
.startSpan()
val formScope = processingFormSpan.makeCurrent()
val attributes = Attributes
.builder()
.put("email", email)
.put("username", username)
.build()
val processingSanitization = tracer
.spanBuilder("formSanitization")
.addLink(processingFormSpan.spanContext, attributes)
.startSpan()
logger.v("Sanitizing email")
logger.v("Sanitizing username")
Thread.sleep(2000)
processingSanitization.end()
Thread.sleep(5000)
formScope.close()
processingFormSpan.end()
}

@Deprecated("Deprecated in Java")
override fun onPostExecute(result: Unit?) {
scope.close()
startSpan.end()
onDone()
}
}

// endregion

companion object {
const val ATTR_FLAVOR = "flavor"
private const val BUILD_TYPE = "build_type"
private const val ATTR_FLAVOR = "flavor"
}
}
26 changes: 25 additions & 1 deletion sample/kotlin/src/main/res/layout/fragment_otel_traces.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/chained_contexts_test"/>

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/linked_spans_test"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="16dp"
android:layout_margin="8dp"
android:text="@string/linked_spans_test"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/start_chained_contexts_test"/>

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/start_linked_spans_test"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="@string/start_linked_spans_test"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/linked_spans_test"/>

<ProgressBar
android:id="@+id/spinner_async"
android:layout_width="0dp"
Expand All @@ -67,9 +90,10 @@
android:max="100"
android:min="0"
style="?android:attr/progressBarStyleHorizontal"
android:layout_marginTop="@dimen/default_padding"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/start_chained_contexts_test"
app:layout_constraintTop_toBottomOf="@id/start_linked_spans_test"
android:visibility="invisible"/>

</androidx.constraintlayout.widget.ConstraintLayout>
2 changes: 2 additions & 0 deletions sample/kotlin/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,6 @@
<string name="start_chained_contexts_test">Start Chained Contexts Test</string>
<string name="start_async_operation">Start Async Operation</string>
<string name="chained_contexts_test">Chained Otel Contexts Test</string>
<string name="linked_spans_test">Linked Spans Test</string>
<string name="start_linked_spans_test">Start Linked Spans Test</string>
</resources>

0 comments on commit 989c4e0

Please sign in to comment.