Skip to content

Unseal SpanProcessor and other traits #1090

@rochala

Description

@rochala

Hey, I'm currently implementing async-profiler profiling data to be linked with the traces.
This is one case in which custom SpanProcessor may actually be useful to be provided.
Obviously we can work around this by writing a wrapper around TracerProvider to call required methods by ourselves. See:

https://github.com/grafana/otel-profiling-java/blob/6ddc19fe2e37ad1b60ec26baf613a049c2be30e5/src/main/java/io/otel/pyroscope/PyroscopeOtelSpanProcessor.java#L8

  class ProfilingSpanProcessor(localSpan: LocalSpan) extends SpanProcessor[IO] {

    override def name: String = "ProfilingSpanProcessor"

    override def onStart: OnStart[IO] = new OnStart[IO] {
      override def apply(parentContext: Option[SpanContext], span: SpanRef[IO]): IO[Unit] = {
        val spanIdStr = span.context.spanIdHex
        val spanId = java.lang.Long.parseUnsignedLong(spanIdStr, 16)
        for {
          _ <- span.addAttributes(Seq(Attribute("pyroscope.profile.id", spanIdStr)))
          _ <- IO(localSpan.set(Some(TraceSpan(spanId))))
        } yield ()
      }
    }

    override def onEnd: OnEnd[IO] = new OnEnd[IO] {
      override def apply(span: SpanData): IO[Unit] = IO(localSpan.set(None))
    }

    override def forceFlush: IO[Unit] = IO.unit

  }

I've also created a discussion that shows the concrete use case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions