Skip to content
Closed
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
Expand Up @@ -11,8 +11,8 @@ import io.embrace.android.embracesdk.internal.spans.EmbraceTracer
import io.embrace.android.embracesdk.internal.spans.InternalTracer
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.embrace.opentelemetry.kotlin.logging.Logger
import io.embrace.opentelemetry.kotlin.tracing.Tracer
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.api.trace.TracerProvider

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import io.embrace.android.embracesdk.internal.spans.InternalTracer
import io.embrace.android.embracesdk.internal.utils.EmbTrace
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.embrace.opentelemetry.kotlin.logging.Logger
import io.embrace.opentelemetry.kotlin.tracing.Tracer
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.api.trace.TracerProvider
import io.opentelemetry.sdk.common.Clock

Expand Down Expand Up @@ -76,7 +76,12 @@ internal class OpenTelemetryModuleImpl(
}

override val sdkTracer: Tracer by lazy {
otelSdkWrapper.sdkTracer
EmbTrace.trace("otel-tracer-init") {
otelSdkWrapper.kotlinApi.tracerProvider.getTracer(
name = otelSdkConfig.sdkName,
version = otelSdkConfig.sdkVersion,
)
}
}

private var sensitiveKeysBehavior: SensitiveKeysBehavior? = null
Expand Down Expand Up @@ -158,7 +163,7 @@ internal class OpenTelemetryModuleImpl(

override val externalTracerProvider: TracerProvider by lazy {
EmbTracerProvider(
sdkTracerProvider = otelSdkWrapper.sdkTracerProvider,
sdkTracerProvider = otelSdkWrapper.kotlinApi.tracerProvider,
spanService = spanService,
clock = openTelemetryClock,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import io.embrace.android.embracesdk.internal.spans.CurrentSessionSpanImpl.Compa
import io.embrace.android.embracesdk.internal.telemetry.TelemetryService
import io.embrace.android.embracesdk.spans.EmbraceSpan
import io.embrace.android.embracesdk.spans.ErrorCode
import io.opentelemetry.api.trace.Tracer
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.opentelemetry.sdk.common.Clock
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
Expand All @@ -42,14 +42,15 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalApi::class)
internal class CurrentSessionSpanImplTests {
private lateinit var spanRepository: SpanRepository
private lateinit var spanSink: SpanSink
private lateinit var telemetryService: TelemetryService
private lateinit var openTelemetryClock: Clock
private lateinit var currentSessionSpan: CurrentSessionSpanImpl
private lateinit var spanService: SpanService
private lateinit var tracer: Tracer
private lateinit var tracer: io.embrace.opentelemetry.kotlin.tracing.Tracer
private val clock = FakeClock(1000L)

@Before
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
package io.embrace.android.embracesdk.internal.otel

import io.embrace.android.embracesdk.internal.otel.wrapper.OtelJavaSpanKind
import io.embrace.android.embracesdk.internal.otel.wrapper.OtelJavaStatusCode
import io.embrace.android.embracesdk.internal.payload.Span
import io.embrace.opentelemetry.kotlin.StatusCode
import io.embrace.opentelemetry.kotlin.tracing.SpanKind
import io.opentelemetry.api.common.AttributeKey

internal fun StatusCode.toOtelJava(): io.opentelemetry.api.trace.StatusCode = when (this) {
is StatusCode.Unset -> io.opentelemetry.api.trace.StatusCode.UNSET
is StatusCode.Ok -> io.opentelemetry.api.trace.StatusCode.OK
is StatusCode.Error -> io.opentelemetry.api.trace.StatusCode.ERROR
internal fun StatusCode.toOtelJava(): OtelJavaStatusCode = when (this) {
is StatusCode.Unset -> OtelJavaStatusCode.UNSET
is StatusCode.Ok -> OtelJavaStatusCode.OK
is StatusCode.Error -> OtelJavaStatusCode.ERROR
}

internal fun io.opentelemetry.api.trace.StatusCode.toOtelKotlin(): StatusCode = when (this) {
io.opentelemetry.api.trace.StatusCode.UNSET -> StatusCode.Unset
io.opentelemetry.api.trace.StatusCode.OK -> StatusCode.Ok
io.opentelemetry.api.trace.StatusCode.ERROR -> StatusCode.Error(null)
internal fun OtelJavaStatusCode.toOtelKotlin(): StatusCode = when (this) {
OtelJavaStatusCode.UNSET -> StatusCode.Unset
OtelJavaStatusCode.OK -> StatusCode.Ok
OtelJavaStatusCode.ERROR -> StatusCode.Error(null)
}

fun io.opentelemetry.api.trace.SpanKind.toOtelKotlin(): SpanKind = when (this) {
io.opentelemetry.api.trace.SpanKind.SERVER -> SpanKind.SERVER
io.opentelemetry.api.trace.SpanKind.CLIENT -> SpanKind.CLIENT
io.opentelemetry.api.trace.SpanKind.PRODUCER -> SpanKind.PRODUCER
io.opentelemetry.api.trace.SpanKind.CONSUMER -> SpanKind.CONSUMER
io.opentelemetry.api.trace.SpanKind.INTERNAL -> SpanKind.INTERNAL
fun OtelJavaSpanKind.toOtelKotlin(): SpanKind = when (this) {
OtelJavaSpanKind.SERVER -> SpanKind.SERVER
OtelJavaSpanKind.CLIENT -> SpanKind.CLIENT
OtelJavaSpanKind.PRODUCER -> SpanKind.PRODUCER
OtelJavaSpanKind.CONSUMER -> SpanKind.CONSUMER
OtelJavaSpanKind.INTERNAL -> SpanKind.INTERNAL
}

fun StatusCode.toEmbracePayload(): Span.Status = when (this) {
is StatusCode.Error -> io.embrace.android.embracesdk.internal.payload.Span.Status.ERROR
StatusCode.Ok -> io.embrace.android.embracesdk.internal.payload.Span.Status.OK
StatusCode.Unset -> io.embrace.android.embracesdk.internal.payload.Span.Status.UNSET
is StatusCode.Error -> Span.Status.ERROR
StatusCode.Ok -> Span.Status.OK
StatusCode.Unset -> Span.Status.UNSET
}

internal fun String.toOtelJavaAttributeKey() = AttributeKey.stringKey(this)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.embrace.android.embracesdk.internal.otel.impl

import io.embrace.android.embracesdk.internal.otel.spans.OtelSpanCreator
import io.embrace.android.embracesdk.internal.otel.spans.SpanService
import io.embrace.android.embracesdk.internal.otel.toOtelKotlin
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
Expand Down Expand Up @@ -49,7 +50,7 @@ class EmbSpanBuilder(
setAttribute(key.key, value.toString())

override fun setSpanKind(spanKind: SpanKind): SpanBuilder {
otelSpanStartArgs.spanKind = spanKind
otelSpanStartArgs.spanKind = spanKind.toOtelKotlin()
return this
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import io.embrace.android.embracesdk.internal.otel.schema.EmbType
import io.embrace.android.embracesdk.internal.otel.sdk.otelSpanCreator
import io.embrace.android.embracesdk.internal.otel.spans.SpanService
import io.embrace.android.embracesdk.internal.otel.spans.getEmbraceSpan
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.opentelemetry.api.trace.SpanBuilder
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
import io.opentelemetry.sdk.common.Clock

@OptIn(ExperimentalApi::class)
class EmbTracer(
private val sdkTracer: Tracer,
private val sdkTracer: io.embrace.opentelemetry.kotlin.tracing.Tracer,
private val spanService: SpanService,
private val clock: Clock,
) : Tracer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ package io.embrace.android.embracesdk.internal.otel.impl

import io.embrace.android.embracesdk.internal.otel.sdk.TracerKey
import io.embrace.android.embracesdk.internal.otel.spans.SpanService
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.api.trace.TracerBuilder
import io.opentelemetry.api.trace.TracerProvider
import io.opentelemetry.sdk.common.Clock
import java.util.concurrent.ConcurrentHashMap

@OptIn(ExperimentalApi::class)
class EmbTracerProvider(
private val sdkTracerProvider: TracerProvider,
private val sdkTracerProvider: io.embrace.opentelemetry.kotlin.tracing.TracerProvider,
private val spanService: SpanService,
private val clock: Clock,
) : TracerProvider {
Expand Down Expand Up @@ -45,14 +47,11 @@ class EmbTracerProvider(
return tracer
}

private fun buildSdkTracer(key: TracerKey): Tracer {
val builder = sdkTracerProvider.tracerBuilder(key.instrumentationScopeName)
key.instrumentationScopeVersion?.apply {
builder.setInstrumentationVersion(this)
}
key.schemaUrl?.apply {
builder.setSchemaUrl(this)
}
return builder.build()
private fun buildSdkTracer(key: TracerKey): io.embrace.opentelemetry.kotlin.tracing.Tracer {
return sdkTracerProvider.getTracer(
name = key.instrumentationScopeName,
version = key.instrumentationScopeVersion,
schemaUrl = key.schemaUrl
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import io.embrace.android.embracesdk.internal.otel.spans.OtelSpanCreator
import io.embrace.android.embracesdk.internal.otel.spans.OtelSpanStartArgs
import io.embrace.android.embracesdk.spans.AutoTerminationMode
import io.embrace.android.embracesdk.spans.EmbraceSpan
import io.opentelemetry.api.trace.Tracer
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.embrace.opentelemetry.kotlin.tracing.Tracer

/**
* Creates a new [OtelSpanCreator] that marks the resulting span as private if [internal] is true
*/
@OptIn(ExperimentalApi::class)
fun Tracer.otelSpanCreator(
name: String,
type: EmbType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,24 @@ import io.embrace.android.embracesdk.internal.otel.sdk.hasEmbraceAttribute
import io.embrace.android.embracesdk.internal.otel.sdk.id.OtelIds
import io.embrace.android.embracesdk.internal.otel.sdk.otelSpanCreator
import io.embrace.android.embracesdk.internal.otel.sdk.setEmbraceAttribute
import io.embrace.android.embracesdk.internal.otel.sdk.toStringMap
import io.embrace.android.embracesdk.internal.otel.toEmbracePayload
import io.embrace.android.embracesdk.internal.otel.toOtelJava
import io.embrace.android.embracesdk.internal.otel.wrapper.KotlinSpanContextWrapper
import io.embrace.android.embracesdk.internal.payload.Attribute
import io.embrace.android.embracesdk.internal.utils.EmbTrace
import io.embrace.android.embracesdk.internal.utils.truncatedStacktraceText
import io.embrace.android.embracesdk.spans.AutoTerminationMode
import io.embrace.android.embracesdk.spans.EmbraceSpan
import io.embrace.android.embracesdk.spans.EmbraceSpanEvent
import io.embrace.android.embracesdk.spans.ErrorCode
import io.embrace.opentelemetry.kotlin.ExperimentalApi
import io.embrace.opentelemetry.kotlin.StatusCode
import io.embrace.opentelemetry.kotlin.k2j.tracing.SpanAdapter
import io.embrace.opentelemetry.kotlin.k2j.tracing.SpanContextAdapter
import io.embrace.opentelemetry.kotlin.tracing.Span
import io.embrace.opentelemetry.kotlin.tracing.Tracer
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanContext
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
import io.opentelemetry.sdk.common.Clock
import io.opentelemetry.semconv.ExceptionAttributes
Expand All @@ -40,6 +44,7 @@ import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicReference

@OptIn(ExperimentalApi::class)
class EmbraceSpanFactoryImpl(
private val tracer: Tracer,
private val openTelemetryClock: Clock,
Expand Down Expand Up @@ -83,6 +88,7 @@ class EmbraceSpanFactoryImpl(
}
}

@OptIn(ExperimentalApi::class)
private class EmbraceSpanImpl(
private val otelSpanCreator: OtelSpanCreator,
private val openTelemetryClock: Clock,
Expand Down Expand Up @@ -126,7 +132,7 @@ private class EmbraceSpanImpl(
override val parent: EmbraceSpan? = otelSpanCreator.spanStartArgs.parentContext.getEmbraceSpan()

override val spanContext: SpanContext?
get() = startedSpan.get()?.spanContext
get() = startedSpan.get()?.spanContext?.let(::KotlinSpanContextWrapper)

override val traceId: String?
get() = spanContext?.traceId
Expand All @@ -135,7 +141,7 @@ private class EmbraceSpanImpl(
get() = spanContext?.spanId

override val isRecording: Boolean
get() = startedSpan.get()?.isRecording == true
get() = startedSpan.get()?.isRecording() == true

override fun start(startTimeMs: Long?): Boolean {
EmbTrace.trace("span-start") {
Expand All @@ -151,15 +157,15 @@ private class EmbraceSpanImpl(
val newSpan = EmbTrace.trace("otel-span-start") {
otelSpanCreator.startSpan(attemptedStartTimeMs)
}
if (newSpan.isRecording) {
if (newSpan.isRecording()) {
startedSpan.set(newSpan)
} else {
return false
}

spanRepository.trackStartedSpan(this)
updatedName?.let { newName ->
newSpan.updateName(newName)
newSpan.name = newName
}
spanStartTimeMs = attemptedStartTimeMs
spanRepository.notifySpanUpdate()
Expand Down Expand Up @@ -196,7 +202,7 @@ private class EmbraceSpanImpl(
}

EmbTrace.trace("otel-span-end") {
spanToStop.end(attemptedEndTimeMs, TimeUnit.MILLISECONDS)
spanToStop.end(TimeUnit.MILLISECONDS.toNanos(attemptedEndTimeMs))
}

successful = !isRecording
Expand Down Expand Up @@ -272,7 +278,7 @@ private class EmbraceSpanImpl(
startedSpan.get()?.let { sdkSpan ->
synchronized(startedSpan) {
status = statusCode.toEmbracePayload()
sdkSpan.setStatus(statusCode.toOtelJava(), description)
sdkSpan.status = statusCode
spanRepository.notifySpanUpdate()
}
}
Expand Down Expand Up @@ -301,7 +307,7 @@ private class EmbraceSpanImpl(
synchronized(startedSpan) {
if (!spanStarted() || isRecording) {
updatedName = newName
startedSpan.get()?.updateName(newName)
startedSpan.get()?.name = newName
spanRepository.notifySpanUpdate()
return true
}
Expand All @@ -322,7 +328,11 @@ private class EmbraceSpanImpl(
}

override fun asNewContext(): Context? = startedSpan.get()?.run {
otelSpanCreator.spanStartArgs.parentContext.with(this)
if (this is SpanAdapter) {
otelSpanCreator.spanStartArgs.parentContext.with(this.impl)
} else {
null
}
}

override fun snapshot(): io.embrace.android.embracesdk.internal.payload.Span? {
Expand Down Expand Up @@ -405,10 +415,10 @@ private class EmbraceSpanImpl(

private fun populateAttributes(spanToStop: Span) {
systemAttributes.forEach { systemAttribute ->
spanToStop.setAttribute(systemAttribute.key, systemAttribute.value)
spanToStop.setStringAttribute(systemAttribute.key, systemAttribute.value)
}
customAttributes.redactIfSensitive().forEach { attribute ->
spanToStop.setAttribute(attribute.key, attribute.value)
spanToStop.setStringAttribute(attribute.key, attribute.value)
}
}

Expand All @@ -423,14 +433,17 @@ private class EmbraceSpanImpl(
}

spanToStop.addEvent(
event.name,
eventAttributes,
event.timestampNanos,
TimeUnit.NANOSECONDS
)
name = event.name,
timestamp = event.timestampNanos
) {
eventAttributes.toStringMap().forEach { entry ->
setStringAttribute(entry.key, entry.value)
}
}
}
}

@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
private fun populateLinks(spanToStop: Span) {
val redactedCustomLinks = customLinks.map { it.copy(attributes = it.attributes.redactIfSensitive()) }

Expand All @@ -440,7 +453,11 @@ private class EmbraceSpanImpl(
} else {
Attributes.empty()
}
spanToStop.addLink(it.spanContext, linkAttributes)
spanToStop.addLink(SpanContextAdapter(it.spanContext)) {
linkAttributes.toStringMap().forEach { entry ->
setStringAttribute(entry.key, entry.value)
}
}
}
}
}
Loading
Loading