Skip to content

Commit

Permalink
Switch to zio/monix FiberRef for contextual logging (#2)
Browse files Browse the repository at this point in the history
* ThreadLocal with zio & monix \o/

* Add support for Contextual Logger with Kleisli

* Restore all the code

* Final touches

* Upgrade to sbt 1.3.8

* Introduce modules directory

* Upgrade dependencies

* Try cross test in CI

* Verify formatting
  • Loading branch information
taig committed Feb 5, 2020
1 parent 5717d4e commit f6f09c8
Show file tree
Hide file tree
Showing 28 changed files with 369 additions and 355 deletions.
10 changes: 8 additions & 2 deletions .gitlab-ci.yml
Expand Up @@ -19,11 +19,17 @@ docker:
- docker build --cache-from $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:$CI_COMMIT_SHA .
- docker push $CONTAINER_IMAGE

test:
format:
stage: test
image: $CONTAINER_IMAGE:$CI_COMMIT_SHA
script:
- sbt -Dmode=strict test publishLocal
- sbt -Dmode=strict scalafmtCheckAll

unit:
stage: test
image: $CONTAINER_IMAGE:$CI_COMMIT_SHA
script:
- sbt -Dmode=strict +test publishLocal

artifacts:
stage: deploy
Expand Down
80 changes: 44 additions & 36 deletions README.md
Expand Up @@ -39,72 +39,80 @@ libraryDependencies ++=
## Usage

```scala
import cats.effect.{ExitCode, IO, IOApp}
import java.util.UUID

import cats.effect.ExitCode
import cats.implicits._
import io.circe.JsonObject
import io.circe.syntax._
import io.taig.flog.algebra.{ContextualLogger, Logger}
import io.taig.flog.data.Scope
import io.taig.flog.interop.monix._
import monix.eval._

import scala.io.Source
import io.circe.syntax._

object Main extends IOApp {
def loadWebsite(url: String, logger: Logger[IO]): IO[String] =
object Playground extends TaskApp {
def loadWebsite(url: String, logger: Logger[Task]): Task[String] =
for {
_ <- logger.info(
Scope.Root / "request",
message = url
)
body <- IO(Source.fromURL(url).mkString)
body <- Task(Source.fromURL(url))
.bracket(source => Task(source.mkString))(
source => Task(source.close())
)
_ <- logger.info(
Scope.Root / "response",
message = url,
payload = JsonObject("body" -> (body.take(100) + "...").asJson)
)
} yield body

override def run(args: List[String]): IO[ExitCode] =
WriterLogger.stdOut[IO]
// Prefix all log events with the "load" scope
.map(_.prefix(Scope.Root / "load"))
// Create a reporting Tracer that automatically logs failures
.map(Tracer.reporting)
.flatMap { tracer =>
tracer.run(logger => loadWebsite(url = "https://typelevel.org", logger)) *>
tracer.run(logger => loadWebsite(url = "foobar", logger))
}.attempt.as(ExitCode.Success)
def app(logger: Logger[Task]): Task[Unit] =
(loadWebsite(url = "https://typelevel.org", logger) *>
loadWebsite(url = "foobar", logger)).void
.onErrorHandleWith { throwable =>
logger.error(message = "Execution failed", throwable = throwable.some)
}

override def run(args: List[String]): Task[ExitCode] =
(for {
// Pick a simple std out logger ...
stdOutLogger <- Logger.stdOut[Task]
// ... and lift it into contextual mode (which is only possible with
// monix.eval.Task and ZIO)
contextualLogger <- ContextualLogger[Task](stdOutLogger)
uuid <- Task(UUID.randomUUID())
_ <- contextualLogger.locally(_.trace(uuid))(app(contextualLogger))
} yield ExitCode.Success)
.executeWithOptions(_.enableLocalContextPropagation)
}
```

```
[2019-09-20 10:15:48.919][info][load / request] https://typelevel.org
[2020-02-05 18:57:13.504][info][request] https://typelevel.org
{
"trace" : "1125b13f-69fc-4883-9f54-ca092a74455c"
"trace" : "95cf9ca5-9e10-4451-9d61-111f8850ca0a"
}
[2019-09-20 10:15:49.263][info][load / response] https://typelevel.org
[2020-02-05 18:57:13.659][info][response] https://typelevel.org
{
"trace" : "1125b13f-69fc-4883-9f54-ca092a74455c",
"trace" : "95cf9ca5-9e10-4451-9d61-111f8850ca0a",
"body" : "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" co..."
}
[2019-09-20 10:15:49.264][info][load / request] foobar
[2020-02-05 18:57:13.659][info][request] foobar
{
"trace" : "64aae8ad-0bdf-4ce9-ba8e-9d4e99842e7d"
"trace" : "95cf9ca5-9e10-4451-9d61-111f8850ca0a"
}
[2019-09-20 10:15:49.265][failure][load]
[2020-02-05 18:57:13.661][error][/] Execution failed
{
"trace" : "64aae8ad-0bdf-4ce9-ba8e-9d4e99842e7d"
"trace" : "95cf9ca5-9e10-4451-9d61-111f8850ca0a"
}
java.net.MalformedURLException: no protocol: foobar
at java.net.URL.<init>(URL.java:593)
at java.net.URL.<init>(URL.java:490)
at java.net.URL.<init>(URL.java:439)
at java.net.URL.<init>(URL.java:610)
at java.net.URL.<init>(URL.java:507)
at java.net.URL.<init>(URL.java:456)
at scala.io.Source$.fromURL(Source.scala:132)
at io.taig.flog.Main$.$anonfun$loadWebsite$4(Main.scala:17)
at cats.effect.internals.IORunLoop$.cats$effect$internals$IORunLoop$$loop(IORunLoop.scala:87)
at cats.effect.internals.IORunLoop$RestartCallback.signal(IORunLoop.scala:355)
at cats.effect.internals.IORunLoop$RestartCallback.apply(IORunLoop.scala:376)
at cats.effect.internals.IORunLoop$RestartCallback.apply(IORunLoop.scala:316)
at cats.effect.internals.IOShift$Tick.run(IOShift.scala:36)
at cats.effect.internals.PoolUtils$$anon$2$$anon$3.run(PoolUtils.scala:51)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[...]
```
48 changes: 44 additions & 4 deletions build.sbt
@@ -1,22 +1,35 @@
import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType}

val CatsEffectVersion = "2.0.0"
val CatsEffectVersion = "2.1.0"
val CirceVersion = "0.12.3"
val GoogleApiClientVersion = "1.25.1"
val GoogleApiServicesSheetsVersion = "v4-rev581-1.25.0"
val GoogleCloudLoggingVersion = "1.99.0"
val GoogleCloudLoggingVersion = "1.100.0"
val GoogleOauthClientJettyVersion = "1.25.0"
val MonixVersion = "3.1.0"
val ScalaCollectionCompatVersion = "2.1.3"
val ScalatestVersion = "3.1.0"
val Slf4jVersion = "1.7.29"
val Slf4jVersion = "1.7.30"
val ZioVersion = "1.0.0-RC17"

lazy val flog = project
.in(file("."))
.settings(noPublishSettings)
.aggregate(core.jvm, core.js, slf4j, sheets, stackdriver)
.aggregate(
core.jvm,
core.js,
zio.jvm,
monix.jvm,
monix.js,
zio.js,
slf4j,
sheets,
stackdriver
)

lazy val core = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("modules/core"))
.settings(sonatypePublishSettings)
.settings(
libraryDependencies ++=
Expand All @@ -26,7 +39,32 @@ lazy val core = crossProject(JVMPlatform, JSPlatform)
Nil
)

lazy val zio = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("modules/interop-zio"))
.settings(sonatypePublishSettings)
.settings(
libraryDependencies ++=
"dev.zio" %%% "zio" % ZioVersion ::
Nil,
name := "interop-zio"
)
.dependsOn(core)

lazy val monix = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("modules/interop-monix"))
.settings(sonatypePublishSettings)
.settings(
libraryDependencies ++=
"io.monix" %%% "monix" % MonixVersion ::
Nil,
name := "interop-monix"
)
.dependsOn(core)

lazy val slf4j = project
.in(file("modules/slf4j"))
.settings(sonatypePublishSettings)
.settings(
libraryDependencies ++=
Expand All @@ -36,6 +74,7 @@ lazy val slf4j = project
.dependsOn(core.jvm)

lazy val sheets = project
.in(file("modules/sheets"))
.settings(sonatypePublishSettings)
.settings(
libraryDependencies ++=
Expand All @@ -48,6 +87,7 @@ lazy val sheets = project
.dependsOn(core.jvm)

lazy val stackdriver = project
.in(file("modules/stackdriver"))
.settings(sonatypePublishSettings)
.settings(
libraryDependencies ++=
Expand Down
153 changes: 0 additions & 153 deletions core/src/main/scala/io/taig/flog/Logger.scala

This file was deleted.

0 comments on commit f6f09c8

Please sign in to comment.