From fa233cf3a43aaeca89ae2f183470460d8bf8282c Mon Sep 17 00:00:00 2001 From: Ruslans Tarasovs Date: Tue, 7 Jan 2025 16:29:27 +0200 Subject: [PATCH] Add documentation for `Log` and `LogOf`. --- .../com/evolutiongaming/catshelper/Log.scala | 12 ++++++ .../evolutiongaming/catshelper/LogOf.scala | 37 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/core/src/main/scala/com/evolutiongaming/catshelper/Log.scala b/core/src/main/scala/com/evolutiongaming/catshelper/Log.scala index 19d4477..0692f2a 100644 --- a/core/src/main/scala/com/evolutiongaming/catshelper/Log.scala +++ b/core/src/main/scala/com/evolutiongaming/catshelper/Log.scala @@ -11,6 +11,18 @@ import org.slf4j.{Logger, MDC} import scala.annotation.tailrec import scala.collection.immutable.SortedMap +/** Context specific logger instance. + * + * Use [[LogOf]] to create the new instances of the class. + * + * The recommendation is to avoid passing `Log` instances implicitly as there + * could be multiple instances of `Log`, which could lead to confusion and + * log messages attributed to the wrong class, which leaked its own `Log` + * instances accidentially. + * + * @see [[LogOf]] for usage examples. + * @see [[org.slf4j.Logger]] for a typical underlying implementation. + */ trait Log[F[_]] { @inline def trace(msg: => String): F[Unit] = trace(msg, mdc = Log.Mdc.empty) diff --git a/core/src/main/scala/com/evolutiongaming/catshelper/LogOf.scala b/core/src/main/scala/com/evolutiongaming/catshelper/LogOf.scala index e3b91d7..8b38f4d 100644 --- a/core/src/main/scala/com/evolutiongaming/catshelper/LogOf.scala +++ b/core/src/main/scala/com/evolutiongaming/catshelper/LogOf.scala @@ -8,6 +8,43 @@ import org.slf4j.{ILoggerFactory, LoggerFactory} import scala.reflect.ClassTag +/** Factory of [[Log]] instances. + * + * The intented usage is to have a single instance of `LogOf` in the + * application and use it to create `Log` instances for each class. + * + * The following could be written somewhere in the application initialization + * code such as [[cats.effect.IOApp]] instance: + * {{{ + * implicit val logOf = LogOf.slf4j[F] + * }}} + * + * Then the typical example could look like following: + * {{{ + * class UserService[F[_]: Monad](log: Log[F]) { + * + * def create(user: User): F[Unit] = { + * for { + * _ <- log.info(s"Creating user...") + * _ <- ... + * } yield () + * } + * } + * + * object UserService { + * + * def of[F[_]: LogOf]: F[UserService[F]] = { + * for { + * log <- LogOf[F].forClass[UserService] + * service = new UserService[F](log) + * } yield service + * } + * + * } + * }}} + * + * @see [[org.slf4j.LoggerFactory]] for a typical underlying implementation. + */ trait LogOf[F[_]] { def apply(source: String): F[Log[F]]