-
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
[WIP] Mostly complete Tracer impl for F -> OptionT #261
Conversation
def wrapResource[A](resource: Resource[OptionT[F, *], A])(implicit | ||
ev: Result =:= Span[OptionT[F, *]] | ||
): Aux[OptionT[F, *], Span.Res[OptionT[F, *], A]] = | ||
??? | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method in particular seems impossible to implement for multiple reasons. for one, the underlying builder
expects Resource[F, A]
, but all we have is Resource[OptionT[F, *], A]
. our resource may not actually contain a value—how would we pass OptionT(F[None])
to the underlying builder
? on top of this, the current implementation/method only handles Span
, not Span.Res
. I made an attempt at generifying it as S[F] <: Span[F]
(happy to provide this branch if wanted), but that ends up not working either because you no longer have a clear underlying builder.Result
type (among other complications).
thoughts?
This inability to implement the transformer instances complicates http4s tracing. We can do it with the Natchez encoding of @iRevive, do you see a clever way around this, or do we need to revisit this resource encoding? |
I will take a look in the upcoming week. By the way, is there an example where the I guess, is it relevant in some internals? |
@iRevive http4s defines the following type aliases: type Http[F[_], G[_]] = Kleisli[F, Request[G], Response[G]]
type HttpApp[F[_]] = Http[F, F]
type HttpRoutes[F[_]] = Http[OptionT[F, *], F] where in order to write code tracing for an example use case, see here which is implemented with natchez and here which could not implement tracing for |
Since this is a forward-facing project, I do want to point out a couple things ...
We have a proposal in Cats MTL so you can have typed errors in This is important because
Along these lines, we also have a proposal in http4s for a |
We can make an instance of import cats.data.{EitherT, OptionT}
import cats.effect._
import io.opentelemetry.api.GlobalOpenTelemetry
import org.typelevel.otel4s.java.OtelJava
import org.typelevel.otel4s.trace.Tracer
object Example extends IOApp.Simple {
def work[F[_]: Async: Tracer] =
Tracer[F].span("work").surround(Async[F].delay(println("I'm working")))
def tracerResource[F[_]: Async: LiftIO]: Resource[F, Tracer[F]] =
Resource
.eval(Async[F].delay(GlobalOpenTelemetry.get))
.evalMap(OtelJava.forAsync[F])
.evalMap(_.tracerProvider.get("example"))
type Maybe[F[_], A] = OptionT[F, A]
type Effect[F[_], Error, A] = EitherT[Maybe[F, *], Error, A]
def run: IO[Unit] =
tracerResource[Effect[IO, String, *]]
.use { implicit tracer => work[Effect[IO, String, *]] }
.value
.value
.flatMap {
case Some(Right(result)) => IO.println(s"Success [$result]")
case Some(Left(error)) => IO.println(s"Error [$error]")
case None => IO.println("Undefined :(")
}
} |
We can have a more generalized alternative over trait Tracer[F[_]] {
def translate[G[_]](fk: F ~> G, gk: G ~> F): Tracer[F] = ???
} This, unfortunately, does not solve the underlying issue since we still cannot define But now I wonder which laws the As Chris pointed out, since we need both So my approach does not solve the original problem. |
Is the vision that in a world with The proposed MTL middlewares in http4s look something like this when they consider both request and response: def apply[F[_], G[_]](http: F[Response[G]])(
implicit F: MonadCancelThrow[F], A: Ask[F, Request[G]]): F[Response[G]]
The most generic signature of the otel4s middleware currently looks like1: def buildTracedF[F[_], G[_]: MonadCancelThrow: Tracer](fk: F ~> G)(f: Http[G, F]): Http[G, F] That's hardcoded to def buildTracedF[F[_], G[_]](fk: F ~> G)(http: G[Response[F]])(
implicit G: MonadCancelThrow[G], A: Ask[G, Request[F]], T: Tracer[G]): G[Response[F]]
I think we have to solve this, or else abandon the MTL middleware approach and harcode everything to a blessed monad stack ... which leads back to me thinking maybe Natchez's Footnotes
|
To keep this moving: should we draft a PR that moves back toward the |
I imagine if we move to a |
Yeah, in this case we can completely drop: type Result <: Span[F]
type Builder = SpanBuilder.Aux[F, Result] |
closing as obsolete |
This is an incomplete implementation of a transformation from
Tracer[F]
to
Tracer[OptionT[F, *]]
. Unfortunately, I do not believe the current designof
Tracer
allows this implementation to be completed.