All Downloads are FREE. Search and download functionalities are using the official Maven repository.

trace4cats.meta.TracedSpanExporter.scala Maven / Gradle / Ivy

package trace4cats.meta

import cats.Applicative
import cats.effect.kernel.{Clock, Concurrent, Deferred}
import cats.syntax.flatMap._
import cats.syntax.functor._
import fs2.Chunk
import trace4cats.StreamSpanExporter
import trace4cats.kernel.{SpanExporter, SpanSampler}
import trace4cats.model._

object TracedSpanExporter {
  private final val spanName = "trace4cats.export.batch"
  private final val spanKind = SpanKind.Producer

  def apply[F[_]: Concurrent: Clock: TraceId.Gen: SpanId.Gen](
    name: String,
    attributes: Map[String, AttributeValue],
    process: TraceProcess,
    sampler: SpanSampler[F],
    underlying: SpanExporter[F, Chunk],
  ): StreamSpanExporter[F] =
    new StreamSpanExporter[F] {
      override def exportBatch(batch: Batch[Chunk]): F[Unit] = for {
        context <- SpanContext.root[F]
        sample <- sampler.shouldSample(None, context.traceId, spanName, spanKind)
        _ <- sample match {
          case SampleDecision.Drop => underlying.exportBatch(batch)
          case SampleDecision.Include =>
            val (batchSize, links) = MetaTraceUtil.extractMetadata(batch.spans)

            for {
              metaSpanPromise <- Deferred[F, CompletedSpan]

              spans <- MetaTraceUtil
                .trace[F](
                  context,
                  spanName,
                  spanKind,
                  Map[String, AttributeValue]("exporter.name" -> name, "batch.size" -> batchSize) ++ attributes,
                  links,
                  builder => metaSpanPromise.complete(builder.build(process)).void
                )
                .use(meta => Applicative[F].pure(batch.spans.map(span => span.copy(metaTrace = Some(meta)))))

              metaSpan <- metaSpanPromise.get
              _ <- exportBatch(Batch(Chunk.concat(List(spans, Chunk.singleton(metaSpan)), spans.size + 1)))
            } yield ()

            MetaTraceUtil
              .trace[F](
                context,
                spanName,
                spanKind,
                Map[String, AttributeValue]("exporter.name" -> name, "batch.size" -> batchSize) ++ attributes,
                links,
                builder => underlying.exportBatch(Batch(Chunk.singleton(builder.build(process))))
              )
              .use(meta => underlying.exportBatch(Batch(batch.spans.map(span => span.copy(metaTrace = Some(meta))))))
        }
      } yield ()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy