From 35f2efc5601b144c949f3dc92063ac8df1fd2793 Mon Sep 17 00:00:00 2001 From: Ben Plommer Date: Tue, 23 Aug 2022 18:08:52 +0100 Subject: [PATCH] Simplify lifting `String => F[Unit]` to `Logger`/`LoggerFactory` --- .../org/typelevel/log4cats/ErrorLogger.scala | 8 +++++++ .../typelevel/log4cats/LoggerFactory.scala | 15 +++++++++++-- .../typelevel/log4cats/SelfAwareLogger.scala | 9 ++++++++ .../log4cats/SelfAwareStructuredLogger.scala | 21 +++++++++++++++++++ .../typelevel/log4cats/StructuredLogger.scala | 13 ++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/core/shared/src/main/scala/org/typelevel/log4cats/ErrorLogger.scala b/core/shared/src/main/scala/org/typelevel/log4cats/ErrorLogger.scala index 0b5ecc0f..9139afd6 100644 --- a/core/shared/src/main/scala/org/typelevel/log4cats/ErrorLogger.scala +++ b/core/shared/src/main/scala/org/typelevel/log4cats/ErrorLogger.scala @@ -28,6 +28,14 @@ trait ErrorLogger[F[_]] { } object ErrorLogger { + trait Fallback[F[_]] extends ErrorLogger[F] { _: MessageLogger[F] => + final def error(t: Throwable)(message: => String): F[Unit] = error(message) + final def warn(t: Throwable)(message: => String): F[Unit] = warn(message) + final def info(t: Throwable)(message: => String): F[Unit] = info(message) + final def debug(t: Throwable)(message: => String): F[Unit] = debug(message) + final def trace(t: Throwable)(message: => String): F[Unit] = trace(message) + } + def apply[F[_]](implicit ev: ErrorLogger[F]): ErrorLogger[F] = ev private def mapK[G[_], F[_]](f: G ~> F)(logger: ErrorLogger[G]): ErrorLogger[F] = diff --git a/core/shared/src/main/scala/org/typelevel/log4cats/LoggerFactory.scala b/core/shared/src/main/scala/org/typelevel/log4cats/LoggerFactory.scala index 7f5674e7..920147dc 100644 --- a/core/shared/src/main/scala/org/typelevel/log4cats/LoggerFactory.scala +++ b/core/shared/src/main/scala/org/typelevel/log4cats/LoggerFactory.scala @@ -16,9 +16,8 @@ package org.typelevel.log4cats -import cats.Functor +import cats.{~>, Applicative, Functor} import cats.syntax.functor._ -import cats.~> import scala.annotation.implicitNotFound @@ -36,6 +35,18 @@ trait LoggerFactory[F[_]] extends LoggerFactoryGen[F] { object LoggerFactory extends LoggerFactoryGenCompanion { def apply[F[_]: LoggerFactory]: LoggerFactory[F] = implicitly + def const[F[_]]( + logger: SelfAwareStructuredLogger[F] + )(implicit F: Applicative[F]): LoggerFactory[F] = new LoggerFactory[F] { + override def getLoggerFromName(name: String): SelfAwareStructuredLogger[F] = logger + + override def fromName(name: String): F[SelfAwareStructuredLogger[F]] = F.pure(logger) + } + + def liftF[F[_]: Applicative](f: String => F[Unit]): LoggerFactory[F] = const( + SelfAwareStructuredLogger.liftF(f) + ) + private def mapK[F[_]: Functor, G[_]](fk: F ~> G)(lf: LoggerFactory[F]): LoggerFactory[G] = new LoggerFactory[G] { diff --git a/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareLogger.scala b/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareLogger.scala index 7c85caa2..aa20e93d 100644 --- a/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareLogger.scala +++ b/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareLogger.scala @@ -32,6 +32,15 @@ trait SelfAwareLogger[F[_]] extends Logger[F] { object SelfAwareLogger { def apply[F[_]](implicit ev: SelfAwareLogger[F]): SelfAwareLogger[F] = ev + trait Stubbed[F[_]] extends SelfAwareLogger[F] { + protected def F: Applicative[F] + def isTraceEnabled: F[Boolean] = F.pure(true) + def isDebugEnabled: F[Boolean] = F.pure(true) + def isInfoEnabled: F[Boolean] = F.pure(true) + def isWarnEnabled: F[Boolean] = F.pure(true) + def isErrorEnabled: F[Boolean] = F.pure(true) + } + private def mapK[G[_], F[_]](f: G ~> F)(logger: SelfAwareLogger[G]): SelfAwareLogger[F] = new SelfAwareLogger[F] { def isTraceEnabled: F[Boolean] = diff --git a/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareStructuredLogger.scala b/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareStructuredLogger.scala index f143960a..96c5270d 100644 --- a/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareStructuredLogger.scala +++ b/core/shared/src/main/scala/org/typelevel/log4cats/SelfAwareStructuredLogger.scala @@ -38,6 +38,27 @@ trait SelfAwareStructuredLogger[F[_]] extends SelfAwareLogger[F] with Structured } object SelfAwareStructuredLogger { + trait Simple[F[_]] + extends SelfAwareStructuredLogger[F] + with StructuredLogger.Fallback[F] + with ErrorLogger.Fallback[F] + with SelfAwareLogger.Stubbed[F] + + def liftF[F[_]: Applicative](f: String => F[Unit]): SelfAwareStructuredLogger[F] = + new SelfAwareStructuredLogger.Simple[F] { + override protected def F: Applicative[F] = implicitly + + override def error(message: => String): F[Unit] = f(message) + + override def warn(message: => String): F[Unit] = f(message) + + override def info(message: => String): F[Unit] = f(message) + + override def debug(message: => String): F[Unit] = f(message) + + override def trace(message: => String): F[Unit] = f(message) + } + def apply[F[_]](implicit ev: SelfAwareStructuredLogger[F]): SelfAwareStructuredLogger[F] = ev def withContext[F[_]]( diff --git a/core/shared/src/main/scala/org/typelevel/log4cats/StructuredLogger.scala b/core/shared/src/main/scala/org/typelevel/log4cats/StructuredLogger.scala index 14abbbe9..554b6253 100644 --- a/core/shared/src/main/scala/org/typelevel/log4cats/StructuredLogger.scala +++ b/core/shared/src/main/scala/org/typelevel/log4cats/StructuredLogger.scala @@ -48,6 +48,19 @@ trait StructuredLogger[F[_]] extends Logger[F] { } object StructuredLogger { + trait Fallback[F[_]] extends StructuredLogger[F] { + def trace(ctx: Map[String, String])(msg: => String): F[Unit] = trace(msg) + def trace(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] = trace(t)(msg) + def debug(ctx: Map[String, String])(msg: => String): F[Unit] = debug(msg) + def debug(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] = debug(t)(msg) + def info(ctx: Map[String, String])(msg: => String): F[Unit] = info(msg) + def info(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] = info(t)(msg) + def warn(ctx: Map[String, String])(msg: => String): F[Unit] = warn(msg) + def warn(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] = warn(t)(msg) + def error(ctx: Map[String, String])(msg: => String): F[Unit] = error(msg) + def error(ctx: Map[String, String], t: Throwable)(msg: => String): F[Unit] = error(t)(msg) + } + def apply[F[_]](implicit ev: StructuredLogger[F]): StructuredLogger[F] = ev def withContext[F[_]](sl: StructuredLogger[F])(ctx: Map[String, String]): StructuredLogger[F] =