Skip to content

Commit

Permalink
custom log levels, tests are for the weak (#931)
Browse files Browse the repository at this point in the history
Co-authored-by: Simon Nevrev <simon.a.nevrev@nordigy.ru>
  • Loading branch information
mehakun and Simon Nevrev committed May 11, 2022
1 parent d5360aa commit 16da823
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import derevo.DerivationKN11
import tofu.logging.bi.LoggingBiMid
import derevo.PassTypeArgs
import derevo.ParamRequire
import tofu.logging.Logging.Level
import tofu.logging.builder.LoggingMidBuilder
import tofu.logging.builder.LoggingErrMidBuilder
import tofu.logging.builder.LoggingBiMidBuilder
Expand All @@ -27,6 +28,23 @@ object loggingMid
def instance[U[f[_]]]: U[LoggingMid] = macro HigherKindedMacros.factorizeThis[U]
}

/** Default logging derivation mechanism for unary effect algebras
*
* Adds logging around the successful invocation of each method at `logLevel` level.
*
* @note
* Class name is not printed by default.
*
* For customization create an object with the same parents and abstract type member `Result` and redefine [onEnter]
* and [onLeave] methods of the `LoggingMidBuilder` trait.
*/
case class loggingMidCustomLevel(logLevel: Level)
extends LoggingMidBuilder.CustomLevelImpl(logLevel) with DerivationKN3[LoggingMid.Of] with PassTypeArgs
with ParamRequire[Loggable] {
type Result[A] = LoggingMid[A]
def instance[U[f[_]]]: U[LoggingMid] = macro HigherKindedMacros.factorizeThis[U]
}

/** Default logging derivation mechanism for unary effect algebras with error reporting.
*
* Adds logging around the invocation of each method at DEBUG level and error alert at ERROR level
Expand All @@ -43,6 +61,23 @@ object loggingMidTry
def instance[U[f[_]]]: U[Result] = macro HigherKindedMacros.factorizeThis[U]
}

/** Default logging derivation mechanism for unary effect algebras with error reporting.
*
* Adds logging around the invocation of each method at specified `logLevel` and error alert at specified
* `errorLogLevel` level
* @note
* Class name is not printed by default.
*
* For customization create object with the same parents and abstract type member `Result` and redefine [onEnter],
* [onLeave] and [onFault] methods of the `LoggingErrMidBuilder` trait.
*/
case class loggingMidTryCustomLevel(logLevel: Level, errorLogLevel: Level)
extends LoggingErrMidBuilder.CustomLevelImpl[Throwable](logLevel, errorLogLevel)
with DerivationKN3[LoggingErrMid.Try] with PassTypeArgs with ParamRequire[Loggable] {
type Result[A] = LoggingErrMid[Throwable, A]
def instance[U[f[_]]]: U[Result] = macro HigherKindedMacros.factorizeThis[U]
}

/** Default logging with errors derivation mechanism for binary effect algebras.
*
* Adds logging around invocation of each method at DEBUG level and error alert at ERROR level
Expand All @@ -59,3 +94,21 @@ object loggingBiMid
def instance[U[f[_, _]]]: U[LoggingBiMid] =
macro HigherKindedMacros.bifactorizeThis[U]
}

/** Default logging with errors derivation mechanism for binary effect algebras.
*
* Adds logging around the invocation of each method at specified `logLevel` and error alert at specified
* `errorLogLevel` level
* @note
* Class name is not printed by default.
*
* For customization create object with the same parents and abstract type member `Result` and redefine [onEnter],
* [onLeave] methods of the `LoggingBiMidBuilder` trait.
*/
case class loggingBiMidCustomLevel(logLevel: Level, errorLogLevel: Level)
extends LoggingBiMidBuilder.CustomLogLevel(logLevel, errorLogLevel) with DerivationKN11[LoggingBiMid.Of]
with PassTypeArgs with ParamRequire[Loggable] {
type Result[E, A] = LoggingBiMid[E, A]
def instance[U[f[_, _]]]: U[LoggingBiMid] =
macro HigherKindedMacros.bifactorizeThis[U]
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package tofu.logging
package builder
import scala.collection.mutable.Buffer
import scala.reflect.ClassTag

import tofu.control.Bind
import tofu.logging.Logging.Level
import tofu.logging.bi.LoggingBiMid
import tofu.logging.impl.ArgsLoggable
import tofu.logging.{Loggable, LoggedValue, Logging}
import tofu.syntax.bindInv._

import scala.collection.mutable.Buffer
import scala.reflect.ClassTag

trait BiBuilder[+T[_, _]] {
def prepare[Alg[_[_, _]]](implicit Alg: ClassTag[Alg[Any]]): BiPrepared[Alg, T]
}
Expand Down Expand Up @@ -71,24 +72,26 @@ abstract class LoggingBiMidBuilder extends BiBuilder[LoggingBiMid] {
}

object LoggingBiMidBuilder {
class Default extends LoggingBiMidBuilder {
def onEnter[F[_, _]](cls: Class[_], method: String, args: Seq[(String, LoggedValue)])(implicit

class CustomLogLevel(logLevel: Level, errorLogLevel: Level) extends LoggingBiMidBuilder {

override def onEnter[F[+_, +_]](cls: Class[_], method: String, args: Seq[(String, LoggedValue)])(implicit
F: Logging.SafeBase[F]
): F[Nothing, Unit] = F.debug("entering {} {}", method, new ArgsLoggable(args))
): F[Nothing, Unit] = F.write(logLevel, "entering {} {}", method, new ArgsLoggable(args))

def onLeave[F[_, _]](
override def onLeave[F[+_, +_]](
cls: Class[_],
method: String,
args: Seq[(String, LoggedValue)],
res: LoggedValue,
ok: Boolean,
ok: Boolean
)(implicit
F: Logging.SafeBase[F]
): F[Nothing, Unit] =
if (ok)
F.debug("leaving {} {} result is {}", method, new ArgsLoggable(args), res)
else
F.error("error during {} {} error is {}", method, new ArgsLoggable(args), res)
): F[Nothing, Unit] = if (ok)
F.write(logLevel, "leaving {} {} result is {}", method, new ArgsLoggable(args), res)
else
F.write(errorLogLevel, "error during {} {} error is {}", method, new ArgsLoggable(args), res)
}
class Default extends CustomLogLevel(Logging.Debug, Logging.Error)

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ package builder

import scala.collection.mutable
import scala.reflect.ClassTag

import tofu.syntax.monadic._
import cats.Monad
import tofu.Errors
import tofu.syntax.handle._
import impl.ArgsLoggable
import tofu.logging.Logging.Level
import tofu.logging.LoggingBase

trait Builder[+T[_]] {
def prepare[Alg[_[_]]](implicit Alg: ClassTag[Alg[Any]]): Prepared[Alg, T]
}

trait Method[U[f[_]], Res, +T[_]] {
def arg[A: Loggable](name: String, a: A): Method[U, Res, T]

def result: T[Res]
}

Expand Down Expand Up @@ -48,8 +50,10 @@ trait LoggingMidBuilder extends Builder[LoggingMid] {
args += (name -> a)
this
}
def result: LoggingMid[Res] = new LoggingMid[Res] {
private[this] val argSeq = args.toSeq

def result: LoggingMid[Res] = new LoggingMid[Res] {
private[this] val argSeq = args.toSeq

def around[F[_]: Monad: LoggingBase](fa: F[Res]): F[Res] =
onEnter(cls, method, argSeq) *> fa.flatTap(res => onLeave(cls, method, argSeq, res))
}
Expand All @@ -72,6 +76,23 @@ object LoggingMidBuilder {
}

class DefaultImpl extends Default

trait CustomLevel extends LoggingMidBuilder {
def onLog[F[_]](message: String, values: LoggedValue*)(implicit F: LoggingBase[F]): F[Unit]

def onEnter[F[_]](cls: Class[_], method: String, args: Seq[(String, LoggedValue)])(implicit
F: LoggingBase[F]
): F[Unit] = onLog("entering {} {}", method, new ArgsLoggable(args))

def onLeave[F[_]](cls: Class[_], method: String, args: Seq[(String, LoggedValue)], res: LoggedValue)(implicit
F: LoggingBase[F]
): F[Unit] = onLog("leaving {} {} with result {}", method, new ArgsLoggable(args), res)
}

class CustomLevelImpl(logLevel: Level) extends CustomLevel {
override def onLog[F[_]](message: String, values: LoggedValue*)(implicit F: LoggingBase[F]): F[Unit] =
F.write(logLevel, message, values)
}
}

trait LoggingErrMidBuilder[E] extends LoggingMidBuilder with Builder[LoggingErrMid[E, *]] {
Expand All @@ -90,7 +111,8 @@ trait LoggingErrMidBuilder[E] extends LoggingMidBuilder with Builder[LoggingErrM
args: mutable.Buffer[(String, LoggedValue)]
) extends MethodImpl[U, Res](cls, method, args) with Method[U, Res, LoggingErrMid[E, *]] {
override def result: LoggingErrMid[E, Res] = new LoggingErrMid[E, Res] {
private[this] val argSeq = args.toSeq
private[this] val argSeq = args.toSeq

def aroundErr[F[_]: Monad: Errors[*[_], E]: LoggingBase](fa: F[Res]): F[Res] =
onEnter(cls, method, argSeq) *>
fa.onError(onFault(cls, method, argSeq, _: E))
Expand All @@ -117,5 +139,27 @@ object LoggingErrMidBuilder {
F.error("error during {} {} error is {}", method, new ArgsLoggable(args), err)

}

class DefaultImpl[E](implicit val errLoggable: Loggable[E]) extends Default[E]

trait CustomLevel[E] extends LoggingMidBuilder.CustomLevel with LoggingErrMidBuilder[E] {
implicit def errLoggable: Loggable[E]

def onFaultLog[F[_]: LoggingBase](message: String, values: LoggedValue*): F[Unit]

def onFault[F[_]](
cls: Class[_],
method: String,
args: Seq[(String, LoggedValue)],
err: E
)(implicit F: LoggingBase[F]): F[Unit] =
onFaultLog("error during {} {} error is {}", method, new ArgsLoggable(args), err)

}

class CustomLevelImpl[E](logLevel: Level, errorLogLevel: Level)(implicit val errLoggable: Loggable[E])
extends LoggingMidBuilder.CustomLevelImpl(logLevel) with CustomLevel[E] {
override def onFaultLog[F[_]](message: String, values: LoggedValue*)(implicit F: LoggingBase[F]): F[Unit] =
F.write(errorLogLevel, message, values)
}
}

0 comments on commit 16da823

Please sign in to comment.