Skip to content

Commit 5130a47

Browse files
authored
Emit log for every instrumentation init event (#836)
* Emit event for every instrumentation initization * Add comment to addEvent method per review
1 parent 9c1061f commit 5130a47

File tree

2 files changed

+38
-23
lines changed

2 files changed

+38
-23
lines changed

instrumentation/startup/src/main/java/io/opentelemetry/android/instrumentation/startup/SdkInitializationEvents.kt

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,19 @@ import io.opentelemetry.api.common.AttributeKey
1414
import io.opentelemetry.api.common.Attributes
1515
import io.opentelemetry.api.common.Value
1616
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder
17+
import io.opentelemetry.api.logs.Logger
1718
import io.opentelemetry.sdk.trace.export.SpanExporter
1819
import java.time.Instant
20+
import java.util.concurrent.ConcurrentLinkedQueue
21+
import java.util.concurrent.atomic.AtomicReference
1922
import java.util.function.Supplier
2023

2124
@AutoService(InitializationEvents::class)
2225
class SdkInitializationEvents(
2326
private val clock: Supplier<Instant> = Supplier { Instant.now() },
2427
) : InitializationEvents {
25-
private val events = mutableListOf<Event>()
28+
private val events = ConcurrentLinkedQueue<Event>()
29+
private val eventLogger = AtomicReference<Logger?>()
2630

2731
override fun sdkInitializationStarted() {
2832
addEvent(RumConstants.Events.INIT_EVENT_STARTED)
@@ -59,23 +63,39 @@ class SdkInitializationEvents(
5963
}
6064

6165
internal fun finish(openTelemetry: OpenTelemetry) {
62-
val loggerProvider = openTelemetry.logsBridge
63-
val logger = loggerProvider.loggerBuilder("otel.initialization.events").build()
64-
events.forEach { event: Event ->
65-
val eventBuilder: ExtendedLogRecordBuilder = logger.logRecordBuilder() as ExtendedLogRecordBuilder
66-
eventBuilder
67-
.setEventName(event.name)
68-
.setTimestamp(event.timestamp)
69-
event.attributes?.let { eventBuilder.setAllAttributes(it) }
70-
eventBuilder.emit()
71-
}
66+
val logger = openTelemetry.logsBridge.loggerBuilder("otel.initialization.events").build()
67+
eventLogger.set(logger)
68+
logger.emitInitEvents()
7269
}
7370

71+
private fun Logger.emitInitEvents() {
72+
do {
73+
events.poll()?.emit(this)
74+
} while (events.isNotEmpty())
75+
}
76+
77+
private fun Event.emit(logger: Logger) {
78+
val eventBuilder: ExtendedLogRecordBuilder = logger.logRecordBuilder() as ExtendedLogRecordBuilder
79+
eventBuilder
80+
.setEventName(name)
81+
.setTimestamp(timestamp)
82+
.apply {
83+
if (attributes != null) {
84+
setAllAttributes(attributes)
85+
}
86+
}.emit()
87+
}
88+
89+
/**
90+
* Add an init event with the given name and attributes. A log will be recorded synchronously if the logger has already been
91+
* initialized (when [finish] is called), or it will be queued up for emission later when [finish] actually gets called.
92+
*/
7493
private fun addEvent(
7594
name: String,
7695
attr: Attributes? = null,
7796
) {
7897
events.add(Event(clock.get(), name, attr))
98+
eventLogger.get()?.emitInitEvents()
7999
}
80100

81101
private data class Event(

instrumentation/startup/src/test/java/io/opentelemetry/android/instrumentation/startup/SdkInitializationEventsTest.kt

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ class SdkInitializationEventsTest {
6262
events.currentNetworkProviderInitialized()
6363
events.networkMonitorInitialized()
6464
events.slowRenderingDetectorInitialized()
65-
events.spanExporterInitialized(exporter)
6665

6766
verify { listOf(processor) wasNot called }
6867
verify(exactly = 0) { exporter.export(any()) }
6968

7069
events.finish(sdk)
70+
events.spanExporterInitialized(exporter)
7171

7272
assertThat(seen).satisfiesExactly(
7373
time(now).named(RumConstants.Events.INIT_EVENT_STARTED),
@@ -83,19 +83,19 @@ class SdkInitializationEventsTest {
8383
)
8484
}
8585

86-
fun time(timeMs: Long): EventAssert = EventAssert(TimeUnit.MILLISECONDS.toNanos(timeMs))
86+
private fun time(timeMs: Long): EventAssert = EventAssert(TimeUnit.MILLISECONDS.toNanos(timeMs))
8787

8888
class EventAssert(
89-
val timeNs: Long,
89+
private val timeNs: Long,
9090
) : Consumer<ReadWriteLogRecord> {
91-
lateinit var name: String
92-
var body: Value<*>? = null
93-
var attrs: Attributes? = null
91+
private lateinit var name: String
92+
private var body: Value<*>? = null
93+
private var attrs: Attributes? = null
9494

9595
override fun accept(log: ReadWriteLogRecord) {
9696
val logData: ExtendedLogRecordData = log.toLogRecordData() as ExtendedLogRecordData
9797
assertThat(logData.timestampEpochNanos).isEqualTo(timeNs)
98-
assertThat(logData.getEventName()).isEqualTo(name)
98+
assertThat(logData.eventName).isEqualTo(name)
9999
if (body == null) {
100100
assertThat(logData.bodyValue).isNull()
101101
} else {
@@ -111,11 +111,6 @@ class SdkInitializationEventsTest {
111111
return this
112112
}
113113

114-
fun withBody(body: Value<*>): EventAssert {
115-
this.body = body
116-
return this
117-
}
118-
119114
fun withAttributes(
120115
key: String,
121116
value: String,

0 commit comments

Comments
 (0)