-
Notifications
You must be signed in to change notification settings - Fork 33
Add helpers to construct Trace backed by IOLocal
#729
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
Conversation
|
Thanks for this @mrdziuban! Last time I looked at this, the Also for this to work properly with the Http4s module, you need to have a |
Yes, absolutely love this PR and the fact someone else is excited about this possibility. I have played with
I implemented a |
|
Thanks for the explanation @ybasket! All we should need is a |
|
Thanks all for the feedback, and thank you @ybasket for the enhancements! I've just added your commits here. @janstenpickle there were a couple |
modules/base-laws/src/test/scala/io/janstenpickle/trace4cats/base/context/laws/LiftTests.scala
Outdated
Show resolved
Hide resolved
modules/base/src/main/scala/io/janstenpickle/trace4cats/base/context/Lift.scala
Outdated
Show resolved
Hide resolved
...les/base-laws/src/test/scala/io/janstenpickle/trace4cats/base/context/laws/UnliftTests.scala
Outdated
Show resolved
Hide resolved
modules/base/src/main/scala/io/janstenpickle/trace4cats/base/context/Lift.scala
Outdated
Show resolved
Hide resolved
modules/base/src/main/scala/io/janstenpickle/trace4cats/base/context/Unlift.scala
Outdated
Show resolved
Hide resolved
modules/cats-effect/src/main/scala/io/janstenpickle/trace4cats/cats/effect/DischargeSpan.scala
Outdated
Show resolved
Hide resolved
modules/cats-effect/src/main/scala/io/janstenpickle/trace4cats/cats/effect/DischargeSpan.scala
Outdated
Show resolved
Hide resolved
...les/cats-effect/src/main/scala/io/janstenpickle/trace4cats/cats/effect/LocalForIOLocal.scala
Outdated
Show resolved
Hide resolved
modules/cats-effect/src/main/scala/io/janstenpickle/trace4cats/cats/effect/package.scala
Outdated
Show resolved
Hide resolved
|
Sorry for short and shallow comments. I will return later with concrete suggestions. |
|
No problem! I may not be super active or responsive the next few days but will keep my eye on this and add relevant changes (including the context bound changes) next week |
7b13b5a to
eca8723
Compare
|
@mrdziuban I rebased your branch on master and added 2 new commits with fixes to base(-laws) and cio modules. The review is not finished though as I have a few questions for @ybasket and want to try the |
catostrophe
left a comment
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.
I left some comments for @mrdziuban and @ybasket
|
|
||
| class IdTests extends BaseSuite { | ||
| implicit val cogenOption2Option: Cogen[Option ~> Option] = | ||
| Cogen(k => k(Some(0)).size.toLong) |
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.
@mrdziuban I changed this line as there may be 2 instances of Option ~> Option
| import io.janstenpickle.trace4cats.base.context.laws.discipline.UnliftTests | ||
| import org.scalacheck.Cogen | ||
|
|
||
| class IdTests extends BaseSuite { |
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.
I renamed the file as it tests laws for F <~> F which we call identity.
| implicit val cogenOption2Option: Cogen[Option ~> Option] = | ||
| Cogen(k => k(Some(0)).size.toLong) | ||
|
|
||
| checkAll("Option <~> Option", UnliftTests[Option, Option].unlift[String, Int]) |
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.
@mrdziuban UnliftTests extends LiftTests, so we need only 1 file and 1 test invokation, not two.
| def provide[A](fa: Kleisli[F, R, A])(r: R): F[A] = fa.run(r) | ||
| } | ||
|
|
||
| implicit def idInstance[F[_]: Monad]: Unlift[F, F] = new Unlift[F, F] { |
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.
@mrdziuban ContextRoot is the root trait for the whole hierarchy, so it is best to put instances in its companion - it will be summonable for any descendant typeclass.
| @@ -0,0 +1,9 @@ | |||
| package io.janstenpickle.trace4cats.base.context | |||
|
|
|||
| object IdInstanceSummonTest { | |||
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.
@mrdziuban Summon tests - we just check that our instance is discoverable by the compiler
| import cats.effect.{IO, IOLocal} | ||
| import io.janstenpickle.trace4cats.base.context.Provide | ||
|
|
||
| private[trace4cats] class ProvideForIOLocal[Ctx](rootCtx: IOLocal[Ctx]) extends Provide[IO, IO, Ctx] { |
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.
@mrdziuban We need just one implementation, no more need for IdLift/IdUnlift mixins.
|
|
||
| def lift[A](la: IO[A]): IO[A] = la | ||
| def ask[R1 >: Ctx]: IO[R1] = rootCtx.get | ||
| def local[A](fa: IO[A])(f: Ctx => Ctx): IO[A] = rootCtx.get.flatMap { parent => |
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.
@mrdziuban This instance seems fine but it must be tested against ProvideLaws. So we need tests just as we have them in the zio module.
| import io.janstenpickle.trace4cats.base.optics.Lens | ||
| import io.janstenpickle.trace4cats.inject.Trace | ||
|
|
||
| package object effect { |
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.
@mrdziuban I simplified this file as I could. Still need time to check how these instances are usable
...es/cats-effect-io/src/main/scala/io/janstenpickle/trace4cats/cats/effect/DischargeSpan.scala
Outdated
Show resolved
Hide resolved
|
|
||
| def zoom[R1](g: Getter[R, R1]): Ask[F, R1] = new Ask[F, R1] { | ||
| def F: Monad[F] = self.F | ||
| val F: Monad[F] = self.F |
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.
Ignore all these def to val changes. It's my old debt.
| import io.janstenpickle.trace4cats.base.optics.Lens | ||
| import io.janstenpickle.trace4cats.inject.Trace | ||
|
|
||
| package object effect { |
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.
@ybasket please double check my changes here. I hope I didn't break anything
|
I think I'll be ready to merge this PR when we have law tests for the Provide instance. Does anyone want to add them? I'll have some spare time in a few days only. |
@catostrophe I tried to add them in ybasket@330fa65. The test passes, but I'm afraid it's at least partially non-sensical. I had to implement an instance of |
|
@ybasket hey! You should have got an ability to push to contributors fork branches. Please check and push your commits straight to this PR. I will review them a bit later and apply fix if any needed. |
Oh, thank you for the honour 😊 |
|
Will review it tonight. Sorry for the delay |
Instances of Provide and a Trace instance for an IOLocal that contains a context from which a Span[IO] can be extracted.
DischargeSpan is a root span that spans new (non-discharge) root spans as children. Useful for situations where you have to construct resources in a traced type and need to "discharge" the tracing without having all children being linked to this long-lived artifact span.
By using Lens.focus, both classes can be merged into one.
1. Move one single instance to ContextRoot 2. Remove IdLift, IdUnlift traits 3. Add summon tests for idInstance 4. Fix law tests for idInstance 5. Override defs with vals where needed
1. Change bounds on F in DischargeSpan 2. Replace LocalForIOLocal with ProvideForIOLocal 3. Simplify instance providers in package object
Provide a law test for Provide on IOLocal – somewhat dummy implementation as not all signatures make sense for IO. Test passes, but its value is questionable.
d768950 to
c34da14
Compare
c34da14 to
784b7b3
Compare
|
I refactored the module. I did it in the same way as we have it in the zio integration. Still no law tests. Still working on it. |
...-io/src/main/scala/io/janstenpickle/trace4cats/base/context/io/IOLocalContextInstances.scala
Show resolved
Hide resolved
...s/inject-io/src/main/scala/io/janstenpickle/trace4cats/inject/io/IOLocalTraceInstances.scala
Show resolved
Hide resolved
|
|
||
| import _root_.io.janstenpickle.trace4cats.base.context.io.IOLocalContextInstances | ||
|
|
||
| package object io extends IOLocalTraceInstances with IOLocalContextInstances |
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.
The usage will be as follows:
package my.app
import cats.effect.{IO, IOApp, IOLocal}
import io.janstenpickle.trace4cats.Span
import io.janstenpickle.trace4cats.base.context.Provide
import io.janstenpickle.trace4cats.inject.{EntryPoint, Trace}
import io.janstenpickle.trace4cats.kernel.{SpanCompleter, SpanSampler}
// this imports both provide and trace instances for IOLocal
import io.janstenpickle.trace4cats.inject.io._
object Test extends IOApp.Simple {
def run: IO[Unit] = {
val spanCompleter = SpanCompleter.empty[IO]
Span.discharge(SpanSampler.always[IO], spanCompleter).flatMap { span =>
IOLocal(span).map { ioLocal =>
implicit val trace: Trace[IO] = ioLocalTrace(ioLocal)
implicit val provide: Provide[IO, IO, Span[IO]] = ioLocalProvide(ioLocal)
Fibonacci(EntryPoint[IO](SpanSampler.always[IO], spanCompleter))
}
}
}
}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.
Looks good, I'll try it on the demo repo later!
Once this PR is merged I'd like to experiment with adding some helper for this as good parts of this snippet will always be the same, so we can make user code nicer by introducing some IOLocalHelper (better name to be found) that creates the discharge span and the IOLocal and returns type class instances ready to use. Especially on Scala 3 (context functions), this could simplify usage noticeably.
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.
@ybasket We can include a syntax extension for Span.type. So it may look as:
val x = Span.dischargeIOLocal(sampler, completer) : IO[IOLocal[Span[IO]]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.
If you don't mind, let's put it in a separate PR? I just want to release something we can play with.
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.
Yes, definitely follow-up PR(s) for anything that's not in here yet.
|
I improved tests a bit (by adding more sensical arb instances), but I still can't get why |
Following up on #723, this adds a new
cats-effectmodule withioLocalTracehelper methods for constructing aTrace[IO]backed by anIOLocal[Span[IO]]