Skip to content

Commit

Permalink
Add logging derivator docs, fix LoggingBiMid
Browse files Browse the repository at this point in the history
  • Loading branch information
Odomontois committed Mar 24, 2021
1 parent 5b7efba commit 5f8a415
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,43 @@ import tofu.logging.bi.LoggingBiMidBuilder
import derevo.PassTypeArgs
import derevo.ParamRequire

/** Default logging derivation mechanism unary effect algebras,,
* adds logging around successful invocation of each method at DEBUG level
* class name is not printed by default
*
* for customization create object with same parents and abstract type member Result
* and redefine [onEnter] and [onLeave] methods of the LoggingMidBuilder trait
*/
object loggingMid
extends LoggingMidBuilder.Default 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 with errors derivation mechanism for unary effect algebras,
* adds logging around invocation of each method at DEBUG level and error alert at ERROR level
* class name is not printed by default
*
* for customization create object with same parents and abstract type member Result
* and redefine [onEnter], [onLeave] and [onFault] methods of the LoggingErrMidBuilder trait
*/
object loggingMidTry
extends LoggingErrMidBuilder.DefaultImpl[Throwable] with DerivationKN3[LoggingErrMid.Try] with PassTypeArgs
with ParamRequire[Loggable] {
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
* class name is not printed by default
*
* for customization create object with same parents and abstract type member Result
* and redefine [onEnter], [onLeave] methods of the LoggingBiMidBuilder trait
*/
object loggingBiMid
extends LoggingBiMidBuilder.Default with DerivationKN11[LoggingBiMid.Of] with PassTypeArgs
with ParamRequire[Loggable] {
with ParamRequire[Loggable] {
type Result[E, A] = LoggingBiMid[E, A]
def instance[U[f[_, _]]]: U[LoggingBiMid] =
macro HigherKindedMacros.bifactorizeThis[U]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class LoggingMidSuite extends AnyFunSuite {
assert(result === Left(MissingName()))
assert(
logs === Vector(
s"[Debug] <$GreeterName> entering $GreeterName.hello ()",
s"[Error] <$GreeterName> error during $GreeterName.hello () error is $ErrName"
s"[Debug] <$GreeterName> entering hello ()",
s"[Error] <$GreeterName> error during hello () error is $ErrName"
)
)
}
Expand All @@ -71,10 +71,10 @@ class LoggingMidSuite extends AnyFunSuite {

assert(
logs === Vector(
s"[Debug] <$GreeterName> entering $GreeterName.setName (name = Tofu)",
s"[Debug] <$GreeterName> leaving $GreeterName.setName (name = Tofu) with result ()",
s"[Debug] <$GreeterName> entering $GreeterName.hello ()",
s"[Debug] <$GreeterName> leaving $GreeterName.hello () with result Hello, Tofu"
s"[Debug] <$GreeterName> entering setName (name = Tofu)",
s"[Debug] <$GreeterName> leaving setName (name = Tofu) with result ()",
s"[Debug] <$GreeterName> entering hello ()",
s"[Debug] <$GreeterName> leaving hello () with result Hello, Tofu"
)
)
}
Expand Down
3 changes: 2 additions & 1 deletion logging/structured/src/main/scala/tofu/logging/Logging.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ object Logging {

type ForService[F[_], Svc] <: Logging[F]

type Safe[F[_, _]] = Logging[F[Nothing, *]]
type Safe[F[_, _]] = Logging[F[Nothing, *]]
type SafeBase[F[_, _]] = LoggingBase[F[Nothing, *]]

def apply[F[_]](implicit logging: Logging[F]): Logging[F] = logging

Expand Down
16 changes: 13 additions & 3 deletions logging/structured/src/main/scala/tofu/logging/LoggingMid.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import tofu.higherKind.derived.HigherKindedMacros
import tofu.Errors
import tofu.syntax.handle._

/** Logging middleware */
/** Logging middleware
* Alg[LoggingMid] is a special form of implicit evidence of injectable logging support
* generally you don't need `Logging` instance to derive this
* so choice of logging postponed until this middleware is attached to the core instance
*/
abstract class LoggingMid[A] {
def around[F[_]: Monad: LoggingBase](fa: F[A]): F[A]

Expand All @@ -25,10 +29,12 @@ object LoggingMid extends LoggingMidBuilder.DefaultImpl {
}

/** Logging middleware generator */

trait LoggingMidBuilder {

/** do some logging upon enter to method invocation */
def onEnter[F[_]: LoggingBase](cls: Class[_], method: String, args: Seq[(String, LoggedValue)]): F[Unit]

/** do some logging after leaving method invocation with known result */
def onLeave[F[_]: LoggingBase](
cls: Class[_],
method: String,
Expand Down Expand Up @@ -73,7 +79,11 @@ object LoggingMidBuilder {
class DefaultImpl extends Default
}

/** Logging middleware */
/** Logging middleware supporting error reporting
* Alg[LoggingErrMid[E, *]] is a special form of implicit evidence of injectable logging support
* generally you don't need `Logging` instance to derive this
* so choice of logging postponed until this middleware is attached to the core instance
*/
abstract class LoggingErrMid[E, A] extends LoggingMid[A] {
def aroundErr[F[_]: Monad: Errors[*[_], E]: LoggingBase](fa: F[A]): F[A]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,32 @@ import tofu.higherKind.bi.BiMid
import tofu.logging.{LogRenderer, Loggable, LoggedValue, Logging}
import tofu.syntax.bindInv._

/** logging middleware for binary tc parameterized traits */
/** Logging middleware for binary typeconstructor parameterized algebras
* Alg[LoggingBiMid] is a special form of implicit evidence of injectable logging support
* generally you don't need `Logging` instance to derive this
* so choice of logging postponed until this middleware is attached to the core instance
*/
abstract class LoggingBiMid[E, A] {
def around[F[+_, +_]: Bind: Logging.Safe](fa: F[E, A]): F[E, A]
def around[F[+_, +_]: Bind: Logging.SafeBase](fa: F[E, A]): F[E, A]

def toMid[F[+_, +_]: Bind: Logging.Safe]: BiMid[F, E, A] = fx => around(fx)
def toMid[F[+_, +_]: Bind: Logging.SafeBase]: BiMid[F, E, A] = fx => around(fx)
}

object LoggingBiMid extends LoggingBiMidBuilder.Default {
type Of[U[_[_, _]]] = U[LoggingBiMid]
}

abstract class LoggingBiMidBuilder {
def onEnter[F[+_, +_]: Logging.Safe](

/** do some logging upon enter to method invocation */
def onEnter[F[+_, +_]: Logging.SafeBase](
cls: Class[_],
method: String,
args: Seq[(String, LoggedValue)]
): F[Nothing, Unit]

def onLeave[F[+_, +_]: Logging.Safe](
/** do some logging after leaving method invocation with known result or error */
def onLeave[F[+_, +_]: Logging.SafeBase](
cls: Class[_],
method: String,
args: Seq[(String, LoggedValue)],
Expand All @@ -45,7 +52,7 @@ abstract class LoggingBiMidBuilder {
def result: LoggingBiMid[Err, Res] = new LoggingBiMid[Err, Res] {
private[this] val argSeq = args.toSeq

def around[F[+_, +_]: Bind: Logging.Safe](fa: F[Err, Res]): F[Err, Res] =
def around[F[+_, +_]: Bind: Logging.SafeBase](fa: F[Err, Res]): F[Err, Res] =
onEnter(cls, method, argSeq) *>
fa.tapBoth(
err => onLeave(cls, method, argSeq, err, ok = false),
Expand All @@ -62,8 +69,8 @@ abstract class LoggingBiMidBuilder {
object LoggingBiMidBuilder {
class Default extends LoggingBiMidBuilder {
def onEnter[F[_, _]](cls: Class[_], method: String, args: Seq[(String, LoggedValue)])(implicit
F: Logging.Safe[F]
): F[Nothing, Unit] = F.debug("entering {}.{} {}", cls.getName(), method, new ArgsLoggable(args))
F: Logging.SafeBase[F]
): F[Nothing, Unit] = F.debug("entering {} {}", cls.getName(), method, new ArgsLoggable(args))

def onLeave[F[_, _]](
cls: Class[_],
Expand All @@ -72,9 +79,12 @@ object LoggingBiMidBuilder {
res: LoggedValue,
ok: Boolean,
)(implicit
F: Logging.Safe[F]
F: Logging.SafeBase[F]
): F[Nothing, Unit] =
F.debug("leaving {}.{} {}", cls.getName(), method, new ArgsLoggable(args))
if (ok)
F.debug("leaving {} {} result is {}", method, new ArgsLoggable(args), res)
else
F.error("error during {} {} error is {}", method, new ArgsLoggable(args), res)
}

class ArgsLoggable(values: Seq[(String, LoggedValue)]) extends LoggedValue {
Expand Down

0 comments on commit 5f8a415

Please sign in to comment.