-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracing a Resource While Staying in Resource #194
Comments
This behavior was supported in the very first draft. Turned out it does not work the way we want with There are a few discussions regarding this topic: |
So we can't trace the lifetime of an http4s client resource? I'm not sure I'm following. |
We will eliminate To summarize: it's not possible to trace the resource now (e.g. different stages: acquire, use, release; and stay within the resource), and will not be possible in the future because the API is bound to the |
Warning The code below provides a leaky abstraction, please don't use it However, there is a workaround to make it work by manually manipulating the context: class IOLocalTracer[F[_]: Monad: LiftIO, Ctx](underlying: Tracer[F], ioLocal: IOLocal[Ctx]) extends Tracer[F] {
def meta: Tracer.Meta[F] = underlying.meta
... // forward all other methods
def spanBuilder(name: String): SpanBuilder[F] =
DelegateSpanBuilder(underlying.spanBuilder(name), ioLocal)
}
case class DelegateSpanBuilder[F[_]: Monad: LiftIO, Ctx](
builder: SpanBuilder[F],
ioLocal: IOLocal[Ctx]
) extends SpanBuilder[F] {
def addAttribute[A](attribute: Attribute[A]): SpanBuilder[F] = copy(builder.addAttribute(attribute))
... // forward all other methods
def build: SpanOps[F] = {
val b = builder.build
new SpanOps[F] {
def resource: Resource[F, SpanOps.Res[F]] =
for {
res <- b.resource
// manually set the context
_ <- Resource.make(
ioLocal.get.to[F] <* res.trace(ioLocal.get.to[F]).flatMap(ioLocal.set(_).to[F])
)(ioLocal.set(_).to[F])
} yield res
def use[A](f: Span[F] => F[A]): F[A] = b.use(f)
def use_ : F[Unit] = b.use_
}
}
} And wire everything together: IOLocal(Context.root).flatMap { implicit ioLocal =>
OtelJava.autoConfigured[IO]().use { otel4s =>
otel4s.tracerProvider.get("tracer").flatMap { t =>
implicit val tracer: Tracer[IO] = new IOLocalTracer(t, ioLocal)
Tracer[IO].span("test").resource.use { _ =>
Tracer[IO].currentSpanContext.debug() // prints the current span
}
}
}
} Technically, we can do something similar under the hood. For example, if we detect that Downsides:
|
So here is an approach I found that was able to get correct resource timing.
https://github.com/ChristopherDavenport/natchez-http4s-otel/blob/otel2/core/src/main/scala/io/chrisdavenport/natchezhttp4sotel/ClientMiddleware.scala#L76-L87
I was wondering how I was supposed to trace for the lifetime of a resource while staying in Resource?
Client are
Request[F] => Resource[F, Response[F]]
so we dont want to directly use the resource in line.I assumed I would use
wrapResource
on spanBuilder, but theuse
seems to still collapse toF
rather than maintaining the resource that's necessary to preserve the live tcp connection.Hoping that someone might have an approach to how to best preserve the resource while tracing a resource?
The text was updated successfully, but these errors were encountered: