Skip to content
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

Implementation for cats-effect 3 #188

Merged
merged 4 commits into from
May 5, 2021
Merged

Conversation

arixmkii
Copy link
Contributor

@arixmkii arixmkii commented Mar 4, 2021

Fixes #182

Important version bumps:

  • cats-core 2.4.2
  • cats-effect 3.0.0-RC2
  • scala 2.13.5
  • prometheus 0.10.0

Additionally fixed some warnings generated by source3 checks.

@@ -79,17 +79,17 @@ sealed abstract class Gauge[F[_]]{
object Gauge {

// Convenience
def incIn[E, F[_]: Bracket[?[_], E], A](g: Gauge[F], fa: F[A]): F[A] =
Bracket[F, E].bracket(g.inc)(_ => fa)(_ => g.dec)
def incIn[E, F[_]: MonadCancel[*[_], E], A](g: Gauge[F], fa: F[A]): F[A] =
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's even a pattern in CE3 itself to use MonadCancel[*[_], _] in these situations (if E isn't part of the signature otherwise).

Also I think *[_] isn't supported by -Ykind-projector in dotty so might just want to pass an explicit implicit :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hope I understood explicit implicit thing correctly here :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, i meant passing the MonadCancel instamce using an implicit clause, as opposed to a context bound. Sorry for the confusion.

That way it'd be MonadCancel[F, _] I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is how I read this and moved MonadCancel to implicit parameter with the second type parameter unlocked.

@@ -203,7 +203,7 @@ object Gauge {
case x: UnlabelledGaugeImpl[_, _] => x.underlying
case x: MapKUnlabelledGauge[_, _, _] => asJavaUnlabelled(x.base)
}
def asJava[F[_]: ApplicativeError[?[_], Throwable]](c: Gauge[F]): F[JGauge] = c match {
def asJava[F[_]: ApplicativeError[*[_], Throwable]](c: Gauge[F]): F[JGauge] = c match {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use ApplicativeThrow

Bracket[F, E].bracket(Clock[F].monotonic(unit))
{_: Long => fa}
{start: Long => Clock[F].monotonic(unit).flatMap(now => h.observe((now - start).toDouble))}
def timed[E, F[_]: MonadCancel[*[_], E]: Clock, A](h: Histogram[F], fa: F[A], unit: TimeUnit): F[A] =
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try fa.timed, it's in CE syntax: typelevel/cats-effect#1677

val test = for {
cr <- CollectorRegistry.build[IO]
gauge <- Gauge.noLabels[IO](cr, Name("boo"), "Boo Gauge")
defer <- Deferred[IO, Unit]
fib <- gauge.incByIn(defer.get, 10).start
_ <- Timer[IO].sleep(1.second)
_ <- Temporal[IO].sleep(1.second)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just IO.sleep would be good too btw

Base automatically changed from master to main March 19, 2021 19:11
@arixmkii
Copy link
Contributor Author

  • Bumped ce to 3.0-RC3;
  • Added OpenMetrics support from prometheus simple-client version 0.10;
  • Used .timed from ce and relaxed MonadCancel requirement to just FlatMap for Summary and Histogram;
  • Removed unnecessary instance summon in Spec file.

@arixmkii
Copy link
Contributor Author

@kubukoz There is a difference between the old implementation of Timed using bracket (MonadCancel) and the one in ce3. The old implementation persists time metrics for failed (and I guess also for canceled) effect.

Example app:

import cats.effect.{ExitCode, IO, IOApp}
import io.chrisdavenport.epimetheus.{CollectorRegistry, Histogram, Name}

import scala.concurrent.duration._

object SummaryApp extends IOApp {

  override def run(args: List[String]): IO[ExitCode] =
    for {
      r <- CollectorRegistry.build[IO]
      hist <- Histogram.noLabels(r, Name("hist"), "help")
      _ <- Histogram.timedSeconds(hist, IO.sleep(4.3.seconds)
        .map(_ => throw new RuntimeException()))
        .handleErrorWith(_ => IO.unit)
      _ <- r.write004.map(println)
    } yield ExitCode.Success

}

This will have no data in registry for timed used from ce3.

I can see reasons to have measured successes only and all the effects, so, for me it is not clear which one is more valid than another. May be @ChristopherDavenport could comment and then I will update the scaladoc part.

Or may be we should expose both APIs for the user and may be even promote bracket version to ce3. 🤷

@kubukoz
Copy link

kubukoz commented Mar 23, 2021

Good catch, I didn't think of that. It's probably best to keep the timing method as it was, then.

@arixmkii
Copy link
Contributor Author

Reverted timed to their bracket version.

@kubukoz
Copy link

kubukoz commented Apr 1, 2021

Any blockers on this one?

@ybasket
Copy link
Contributor

ybasket commented May 4, 2021

Looks good to me – thank you @arixmkii 👍

Hope it gets merged soon-ish, I came here because epimetheus (and -http4s) is one of my last blockers on CE3 adoption.

@ChristopherDavenport ChristopherDavenport merged commit 4851e2a into davenverse:main May 5, 2021
@kubukoz
Copy link

kubukoz commented May 22, 2021

Can we get a milestone with this? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide cats-effect 3 builds
4 participants