org.http4k.tracing.TracerBullet.kt Maven / Gradle / Ivy
package org.http4k.tracing
import org.http4k.events.Event
import org.http4k.events.MetadataEvent
import org.http4k.filter.TraceId
import org.http4k.tracing.CollectEvents.Collect
import org.http4k.tracing.CollectEvents.Drop
import org.http4k.tracing.tracer.TreeWalker
/**
* Entry--point for creating Trace from a list of MetadataEvents. Provide a Tracer for each of the
* implementations that you want to support.
*/
class TracerBullet(private val tracers: List) {
constructor(vararg tracers: Tracer) : this(tracers.toList())
operator fun invoke(events: List): List =
events.filterIsInstance().removeUnrenderedEvents().buildTree()
.flatMap { event -> tracers.flatMap { it(event, Tracer.TreeWalker(tracers)) } }
}
internal fun List.buildTree(): List {
val eventsByParent = groupBy { it.traces()?.parentSpanId }
fun createEventNodes(parentService: TraceId?): List =
(eventsByParent[parentService] ?: emptyList()).map { EventNode(it, createEventNodes(it.traces()?.spanId)) }
val rootEvents = filter { event ->
eventsByParent.none { it.value.any { it.traces()?.spanId == event.traces()?.parentSpanId } }
}
return rootEvents.map { EventNode(it, createEventNodes(it.traces()?.spanId))
}
}
private enum class CollectEvents { Collect, Drop }
private fun List.removeUnrenderedEvents(): List {
fun List.andNext(collectEvents: CollectEvents) = this to collectEvents
val collectElements = if (any { it.event == StartRendering }) Drop else Collect
return fold(Pair(listOf(), collectElements)) { acc, event ->
when (acc.second) {
Collect -> when (event.event) {
StopRendering -> acc.first.andNext(Drop)
else -> (acc.first + event).andNext(Collect)
}
Drop -> when (event.event) {
StartRendering -> acc.first.andNext(Collect)
else -> acc.first.andNext(Drop)
}
}
}.first
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy