package support import cats.effect.IO import cats.effect.kernel.Resource import cats.effect.std.MapRef import java.net.URI import java.util.UUID import natchez.Kernel import natchez.Span import natchez.Span.Options import natchez.TraceValue final class TestSpan private ( val name: String, val rawTraceId: String, val rawSpanId: String, baggage: MapRef[IO, String, Option[TraceValue]], spans: MapRef[IO, String, Option[TestSpan]] ) extends Span[IO]: override def put(fields: (String, TraceValue)*): IO[Unit] = fields.map { case (k, v) => baggage.setKeyValue(k, v) }.sequence.as(()) override def log(fields: (String, TraceValue)*): IO[Unit] = IO.unit override def log(event: String): IO[Unit] = IO.unit override def attachError( err: Throwable, fields: (String, TraceValue)* ): IO[Unit] = IO.unit override def kernel: IO[Kernel] = IO(Kernel(Map.empty)) override def span( name: String, options: Options ): Resource[IO, Span[IO]] = TestSpan .provision(name, rawTraceId, TestSpan.makeSpanId(), spans) .evalTap(span => spans.setKeyValue(name, span)) override def traceId: IO[Option[String]] = IO(Some(rawTraceId)) override def spanId: IO[Option[String]] = IO(Some(rawSpanId)) override def traceUri: IO[Option[URI]] = IO(None) object TestSpan: def initializeRoot( name: String, spans: MapRef[IO, String, Option[TestSpan]] ): IO[TestSpan] = initialize(name, makeTraceId(), makeSpanId(), spans) def initialize( name: String, traceId: String, spanId: String, spans: MapRef[IO, String, Option[TestSpan]] ): IO[TestSpan] = MapRef.apply[IO, String, TraceValue].map { baggage => new TestSpan( name = name, rawTraceId = traceId, rawSpanId = spanId, baggage = baggage, spans = spans ) } def provisionRoot( name: String, spans: MapRef[IO, String, Option[TestSpan]] ): Resource[IO, TestSpan] = provision(name, makeTraceId(), makeSpanId(), spans) def provision( name: String, traceId: String, spanId: String, spans: MapRef[IO, String, Option[TestSpan]] ): Resource[IO, TestSpan] = Resource.make(initialize(name, traceId, spanId, spans))(_ => IO.unit) private def makeTraceId(): String = UUID.randomUUID().toString().filterNot(_ == '-') private def makeSpanId(): String = makeTraceId().take(16) end TestSpan