This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class WrappedRunnable(runnable: Runnable, context: LoggingContext) extends Runnable { | |
override def run(): Unit = { | |
LoggingContext.localContext.value = context | |
runnable.run() | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Concurrent extends IOApp { | |
override def run(args: List[String]): IO[ExitCode] = { | |
(0 to 10).toList | |
.parTraverse(run) | |
.as(ExitCode.Success) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Sequential extends IOApp { | |
private val log: Logger[IO] = Slf4jLogger.getLogger[IO].mdc | |
override def run(args: List[String]): IO[ExitCode] = { | |
for { | |
_ <- log.info("Start") | |
user <- op.withLogContext(_.id("1")) | |
_ <- log.info(s"result: $user") | |
_ <- log.info("End") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package object logging { | |
implicit class ContextAwareSync[F[_], A](fa: F[A])(implicit F: Sync[F]) { | |
def withLogContext(f: LoggingContext => LoggingContext): F[A] = | |
F.bracket { | |
LoggingContext.update(f) | |
} { _ => | |
fa | |
} { old => |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MdcLogger[F[_]: Sync](logger: StructuredLogger[F]) extends Logger[F] { | |
@inline | |
private def withCtx(f: LoggingContext => F[Unit]): F[Unit] = | |
LoggingContext.get[F].flatMap(f) | |
override def error(t: Throwable)(message: => String): F[Unit] = | |
withCtx(c => logger.error(c.map, t)(message)) | |
override def error(message: => String): F[Unit] = | |
withCtx(c => logger.error(c.map)(message)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class LoggingContext(map: Map[String, String]) { | |
def id(id: String): LoggingContext = LoggingContext(map + ("id" -> id)) | |
def tpe(tpe: String): LoggingContext = LoggingContext(map + ("type" -> tpe)) | |
} | |
object LoggingContext { | |
def apply(): LoggingContext = LoggingContext(Map()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait StructuredLogger[F[_]] extends Logger[F] { | |
def error(ctx: Map[String, String])(msg: => String): F[Unit] | |
def warn(ctx: Map[String, String])(msg: => String): F[Unit] | |
// ... | |
def error(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] | |
def warn(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Logger[F[_]] { | |
def error(message: => String): F[Unit] | |
def warn(message: => String): F[Unit] | |
// ... etc | |
def error(t: Throwable)(message: => String): F[Unit] | |
def warn(t: Throwable)(message: => String): F[Unit] | |
// ... etc | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Service { | |
def cleanAPI(i: Int): String | |
} | |
object ServiceImplementation { | |
private val ctx: ThreadLocal[String] = new ThreadLocal[String] | |
def setAdditionalArg(arg: String): Unit = ctx.set(arg) | |
} | |
class ServiceImplementation { | |
def cleanAPI(i: Int): String = { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Logging { | |
type IOLog[A] = WriterT[IO, Vector[String], A] | |
val IOLog = WriterT | |
} | |
object Test { | |
def loggedFunc(): IOLog[Int] | |
def plainFunc(i: Int): IO[String] | |
def work(): IOLog[String] = |