Skip to content

Commit

Permalink
Make EmbType a TelemetryType and make TelemetryType an EmbraceAttribu…
Browse files Browse the repository at this point in the history
…te (#531)

## Goal

Make TelemetryType an EmbraceAttribute and make EmbType a TelemetryType. Convert usage to the the new interfaces to avoid the hardcoding of `emb.` and telemetry type attribute name and values everywhere.

## Testing

Existing tests cover this. A later PR will add helpers to make usage and testing easier.
  • Loading branch information
bidetofevil committed Mar 11, 2024
2 parents 11625ab + c526787 commit 2a1b4ba
Show file tree
Hide file tree
Showing 19 changed files with 79 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ internal class LogEventData(
val severity: Severity,
val message: String
) {
val attributes = schemaType.attrs.plus(Pair("emb.type", schemaType.telemetryType.description))
val attributes = schemaType.attrs.plus(Pair(schemaType.telemetryType.otelAttributeName(), schemaType.telemetryType.attributeValue))
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ internal class SpanEventData(
val schemaType: SchemaType,
val spanStartTimeMs: Long
) {
val attributes = schemaType.attrs.plus(Pair("emb.type", schemaType.telemetryType.description))
val attributes = schemaType.attrs.plus(Pair(schemaType.telemetryType.otelAttributeName(), schemaType.telemetryType.attributeValue))
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ internal class StartSpanData(
val schemaType: SchemaType,
val spanStartTimeMs: Long,
) {
val attributes = schemaType.attrs.plus(Pair("emb.type", schemaType.telemetryType.description))
val attributes = schemaType.attrs.plus(Pair(schemaType.telemetryType.otelAttributeName(), schemaType.telemetryType.attributeValue))
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
package io.embrace.android.embracesdk.arch.schema

import io.embrace.android.embracesdk.internal.spans.toEmbraceAttributeName

internal sealed class EmbType {
internal sealed class EmbType(type: String, subtype: String?) : TelemetryType {
override val attributeName: String = "type"
override val attributeValue = type + (subtype?.run { ".$this" } ?: "")

/**
* Keys that track how fast a time interval is. Only applies to spans.
*/
internal object Performance : TelemetryType {
override val description: String = "performance"
internal sealed class Performance(subtype: String?) : EmbType("performance", subtype) {

internal object Default : Performance(null)

internal object Network : Performance("network")
}

/**
* Keys that track a point in time & is visual in nature. Applies to spans, logs, and span events.
*/
internal sealed class Ux(subtype: String) : TelemetryType {
internal sealed class Ux(subtype: String) : EmbType("ux", subtype) {

internal object Session : Ux("session")

internal object View : Ux("view")

override val description = "ux.$subtype"
}

/**
* Keys that track a point in time that is not visual in nature. Applies to spans, logs, and span events.
*/
internal sealed class System(subtype: String) : TelemetryType {
internal sealed class System(subtype: String) : EmbType("system", subtype) {

internal object Breadcrumb : System("breadcrumb")

internal object Log : System("log")
internal object Exit : System("exit")

override val description = "system.$subtype"
internal object Exit : System("exit")
}
}

Expand All @@ -39,11 +42,4 @@ internal sealed class EmbType {
* a visual event around a UI element. ux is the type, and view is the subtype. This tells the
* backend that it can assume the data in the event follows a particular schema.
*/
internal interface TelemetryType {
val description: String

/**
* Return the key name used by this attribute when is used inside of OpenTelemetry objects
*/
fun attributeName(): String = "type".toEmbraceAttributeName()
}
internal interface TelemetryType : EmbraceAttribute
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ internal fun createRootSpanBuilder(
* Sets and returns the [TelemetryType] attribute for the given [SpanBuilder]
*/
internal fun SpanBuilder.setType(value: TelemetryType): SpanBuilder {
setAttribute(value.attributeName(), value.description)
setAttribute(value.otelAttributeName(), value.attributeValue)
return this
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal interface SpanService : Initializable {
fun createSpan(
name: String,
parent: EmbraceSpan? = null,
type: TelemetryType = EmbType.Performance,
type: TelemetryType = EmbType.Performance.Default,
internal: Boolean = true
): EmbraceSpan?

Expand All @@ -29,7 +29,7 @@ internal interface SpanService : Initializable {
name: String,
parent: EmbraceSpan? = null,
startTimeMs: Long? = null,
type: TelemetryType = EmbType.Performance,
type: TelemetryType = EmbType.Performance.Default,
internal: Boolean = true
): EmbraceSpan? {
createSpan(
Expand All @@ -53,7 +53,7 @@ internal interface SpanService : Initializable {
fun <T> recordSpan(
name: String,
parent: EmbraceSpan? = null,
type: TelemetryType = EmbType.Performance,
type: TelemetryType = EmbType.Performance.Default,
internal: Boolean = true,
attributes: Map<String, String> = emptyMap(),
events: List<EmbraceSpanEvent> = emptyList(),
Expand All @@ -69,7 +69,7 @@ internal interface SpanService : Initializable {
startTimeMs: Long,
endTimeMs: Long,
parent: EmbraceSpan? = null,
type: TelemetryType = EmbType.Performance,
type: TelemetryType = EmbType.Performance.Default,
internal: Boolean = true,
attributes: Map<String, String> = emptyMap(),
events: List<EmbraceSpanEvent> = emptyList(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.embrace.android.embracesdk.arch

import io.embrace.android.embracesdk.arch.datasource.startSpanCapture
import io.embrace.android.embracesdk.arch.destination.StartSpanData
import io.embrace.android.embracesdk.arch.schema.EmbType
import io.embrace.android.embracesdk.arch.schema.SchemaType
import io.embrace.android.embracesdk.fakes.FakeClock
import io.embrace.android.embracesdk.fakes.injection.FakeInitModule
Expand All @@ -25,7 +26,7 @@ internal class SpanDataSourceKtTest {
SchemaType.ViewBreadcrumb("my-view"),
1500000000000
)
assertEquals("ux.view", data.attributes["emb.type"])
assertEquals(EmbType.Ux.View.attributeValue, data.attributes[EmbType.Ux.View.otelAttributeName()])
assertEquals("my-view", data.attributes["view.name"])

val span = service.startSpanCapture("") { data }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.ActivityManager
import android.app.ApplicationExitInfo
import com.google.common.util.concurrent.MoreExecutors
import io.embrace.android.embracesdk.Severity
import io.embrace.android.embracesdk.arch.schema.EmbType
import io.embrace.android.embracesdk.config.remote.AppExitInfoConfig
import io.embrace.android.embracesdk.config.remote.RemoteConfig
import io.embrace.android.embracesdk.fakes.FakeConfigService
Expand Down Expand Up @@ -360,7 +361,7 @@ internal class AeiDataSourceImplTest {
val logEventData = logWriter.logEvents.single()
assertEquals("aei-record", logEventData.schemaType.name)
assertEquals(Severity.INFO, logEventData.severity)
assertEquals("system.exit", logEventData.attributes["emb.type"])
assertEquals(EmbType.System.Exit.attributeValue, logEventData.attributes[EmbType.System.Exit.otelAttributeName()])
return logEventData.attributes
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.embrace.android.embracesdk.capture.crumbs

import io.embrace.android.embracesdk.arch.schema.EmbType
import io.embrace.android.embracesdk.fakes.FakeConfigService
import io.embrace.android.embracesdk.fakes.FakeCurrentSessionSpan
import io.embrace.android.embracesdk.internal.clock.millisToNanos
Expand Down Expand Up @@ -35,7 +36,7 @@ internal class CustomBreadcrumbDataSourceTest {
assertEquals(15000000000.millisToNanos(), spanStartTimeMs)
assertEquals(
mapOf(
"emb.type" to "system.breadcrumb",
EmbType.System.Breadcrumb.otelAttributeName() to EmbType.System.Breadcrumb.attributeValue,
"message" to "Hello, world!"
),
attributes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ internal class FragmentBreadcrumbDataSourceTest {

val span = spanService.createdSpans.single()
assertEquals("view-breadcrumb", span.name)
assertEquals(EmbType.Performance, span.type)
assertEquals(EmbType.Performance.Default, span.type)
assertTrue(span.isRecording)
assertEquals(
mapOf(
"view.name" to "my_fragment",
"emb.type" to "ux.view"
EmbType.Ux.View.otelAttributeName() to EmbType.Ux.View.attributeValue,
),
span.attributes
)
Expand All @@ -54,12 +54,12 @@ internal class FragmentBreadcrumbDataSourceTest {

val span = spanService.createdSpans.single()
assertEquals("view-breadcrumb", span.name)
assertEquals(EmbType.Performance, span.type)
assertEquals(EmbType.Performance.Default, span.type)
assertFalse(span.isRecording)
assertEquals(
mapOf(
"view.name" to "my_fragment",
"emb.type" to "ux.view"
EmbType.Ux.View.otelAttributeName() to EmbType.Ux.View.attributeValue,
),
span.attributes
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ internal class StartupServiceImplTest {
assertEquals(startTimeMillis, startTimeNanos.nanosToMillis())
assertEquals(endTimeMillis, endTimeNanos.nanosToMillis())
assertEquals(
EmbType.Performance.description,
attributes[EmbType.Performance.attributeName()]
EmbType.Performance.Default.attributeValue,
attributes[EmbType.Performance.Default.otelAttributeName()]
)
assertTrue(isPrivate())
assertEquals(StatusCode.OK, status)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import io.opentelemetry.sdk.trace.IdGenerator
internal class FakeEmbraceSpan(
override val parent: EmbraceSpan?,
val name: String? = null,
val type: TelemetryType = EmbType.Performance,
val type: TelemetryType = EmbType.Performance.Default,
val internal: Boolean = true
) : EmbraceSpan {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.embrace.android.embracesdk.fixtures

import io.embrace.android.embracesdk.arch.schema.EmbType
import io.embrace.android.embracesdk.internal.spans.EmbraceSpanData
import io.embrace.android.embracesdk.internal.spans.EmbraceSpanImpl
import io.embrace.android.embracesdk.spans.EmbraceSpanEvent
Expand Down Expand Up @@ -30,7 +31,10 @@ internal val testSpan = EmbraceSpanData(
)
)
),
attributes = mapOf(Pair("emb.sequence_id", "3"), Pair("emb.type", "performance"))
attributes = mapOf(
Pair("emb.sequence_id", "3"),
EmbType.Performance.Default.otelAttributeName() to EmbType.Performance.Default.attributeValue,
)
)

private fun createMapOfSize(size: Int): Map<String, String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.google.common.util.concurrent.MoreExecutors
import io.embrace.android.embracesdk.Embrace.AppFramework
import io.embrace.android.embracesdk.LogExceptionType
import io.embrace.android.embracesdk.Severity
import io.embrace.android.embracesdk.arch.schema.EmbType
import io.embrace.android.embracesdk.config.ConfigService
import io.embrace.android.embracesdk.config.remote.LogRemoteConfig
import io.embrace.android.embracesdk.config.remote.RemoteConfig
Expand Down Expand Up @@ -103,7 +104,7 @@ internal class EmbraceLogServiceTest {
assertNotNull(third.attributes["emb.log_id"])
assertEquals("session-123", third.attributes["emb.session_id"])
assertNull(third.attributes["emb.exception_type"])
assertEquals("system.log", third.attributes["emb.type"])
assertEquals(EmbType.System.Log.attributeValue, third.attributes[EmbType.System.Log.otelAttributeName()])
}

@Test
Expand Down Expand Up @@ -132,11 +133,11 @@ internal class EmbraceLogServiceTest {
assertNotNull(log.attributes["emb.log_id"])
assertEquals("session-123", log.attributes["emb.session_id"])
assertEquals("none", log.attributes["emb.exception_type"])
assertEquals("system.log", log.attributes["emb.type"])
assertEquals(EmbType.System.Log.attributeValue, log.attributes[EmbType.System.Log.otelAttributeName()])
}

@Test
fun `Embrace properties can not be overriden by custom properties`() {
fun `Embrace properties can not be overridden by custom properties`() {
val logService = getLogService()
val props = mapOf("emb.session_id" to "session-456")
logService.log("Hello world", Severity.INFO, props)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ internal class CurrentSessionSpanImplTests {
val lastFlushedSpan = flushedSpans[0]
with(lastFlushedSpan) {
assertEquals("emb-session", name)
assertEquals(EmbType.Ux.Session.description, attributes[EmbType.Ux.Session.attributeName()])
assertEquals(EmbType.Ux.Session.attributeValue, attributes[EmbType.Ux.Session.otelAttributeName()])
assertEquals(StatusCode.OK, status)
assertFalse(isKey())
assertEquals(cause.attributeValue, attributes[cause.otelAttributeName()])
Expand Down Expand Up @@ -191,7 +191,13 @@ internal class CurrentSessionSpanImplTests {
val testEvent = span.events.single()
assertEquals("custom-breadcrumb", testEvent.name)
assertEquals(1000, testEvent.timestampNanos.nanosToMillis())
assertEquals(mapOf("emb.type" to "system.breadcrumb", "message" to "test-event"), testEvent.attributes)
assertEquals(
mapOf(
EmbType.System.Breadcrumb.otelAttributeName() to EmbType.System.Breadcrumb.attributeValue,
"message" to "test-event"
),
testEvent.attributes
)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ internal class EmbraceSpanServiceTest {
val expectedName = "test-span"
val expectedStartTimeMs = clock.now()
val expectedEndTimeMs = expectedStartTimeMs + 100L
val expectedType = EmbType.Performance
val expectedType = EmbType.Performance.Default
val expectedAttributes = mapOf(
Pair("attribute1", "value1"),
Pair("attribute2", "value2")
Expand Down Expand Up @@ -88,8 +88,8 @@ internal class EmbraceSpanServiceTest {
assertEquals(expectedStartTimeMs, startTimeNanos.nanosToMillis())
assertEquals(expectedEndTimeMs, endTimeNanos.nanosToMillis())
assertEquals(
EmbType.Performance.description,
attributes[EmbType.Performance.attributeName()]
EmbType.Performance.Default.attributeValue,
attributes[EmbType.Performance.Default.otelAttributeName()]
)
expectedAttributes.forEach {
assertEquals(it.value, attributes[it.key])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,8 @@ internal class EmbraceTracerTest {
val currentSpan = currentSpans[0]
assertEquals(name, currentSpan.name)
assertEquals(
EmbType.Performance.description,
currentSpan.attributes[EmbType.Performance.attributeName()]
EmbType.Performance.Default.attributeValue,
currentSpan.attributes[EmbType.Performance.Default.otelAttributeName()]
)
assertEquals(if (traceRoot) "true" else null, currentSpan.attributes["emb.key"])
errorCode?.run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ internal class InternalTracerTest {
val expectedName = "test-span"
val expectedStartTimeMs = clock.now()
val expectedEndTimeMs = expectedStartTimeMs + 100L
val expectedType = EmbType.Performance
val expectedType = EmbType.Performance.Default
val expectedAttributes = mapOf(
Pair("attribute1", "value1"),
Pair("attribute2", "value2")
Expand All @@ -235,8 +235,8 @@ internal class InternalTracerTest {
assertEquals(expectedStartTimeMs, startTimeNanos.nanosToMillis())
assertEquals(expectedEndTimeMs, endTimeNanos.nanosToMillis())
assertEquals(
expectedType.description,
attributes[expectedType.attributeName()]
expectedType.attributeValue,
attributes[expectedType.otelAttributeName()]
)
assertEquals("true", attributes["emb.key"])
expectedAttributes.forEach {
Expand Down Expand Up @@ -278,8 +278,8 @@ internal class InternalTracerTest {
val currentSpan = currentSpans[0]
assertEquals(name, currentSpan.name)
assertEquals(
EmbType.Performance.description,
currentSpan.attributes[EmbType.Performance.attributeName()]
EmbType.Performance.Default.attributeValue,
currentSpan.attributes[EmbType.Performance.Default.otelAttributeName()]
)
assertEquals(if (traceRoot) "true" else null, currentSpan.attributes["emb.key"])
errorCode?.run {
Expand Down
Loading

0 comments on commit 2a1b4ba

Please sign in to comment.