Skip to content

Instantly share code, notes, and snippets.

@kovacshuni
Created December 22, 2020 00:36
Show Gist options
  • Save kovacshuni/d905d6e587093e8091705445b6b289df to your computer and use it in GitHub Desktop.
Save kovacshuni/d905d6e587093e8091705445b6b289df to your computer and use it in GitHub Desktop.
tagless-final-logging-testing
package com.hunorkovacs.catsi
import cats.effect.Sync
import cats.Applicative
import org.log4s.{getLogger, Logger => Log4sLogger}
trait Logger[F[_]] {
def trace(str: String): F[Unit]
def debug(str: String): F[Unit]
def info(str: String): F[Unit]
def warning(str: String): F[Unit]
def error(str: String): F[Unit]
def error(str: String, t: Throwable): F[Unit]
val underlying: Option[Log4sLogger]
def to[G[_] : Sync]: Logger[G]
def subLogger(name: String): Logger[F]
}
object Logger {
def apply[F[_] : Logger]: Logger[F] = implicitly[Logger[F]]
def logger[F[_] : Sync](name: String): Logger[F] = loggerInst[F](getLogger(name))
def loggerInst[F[_] : Sync](log: Log4sLogger): Logger[F] = new Logger[F] {
override val underlying: Option[Log4sLogger] = Some(log)
override def trace(str: String): F[Unit] = Sync[F].delay {
log.trace(str)
}
override def debug(str: String): F[Unit] = Sync[F].delay {
log.debug(str)
}
override def info(str: String): F[Unit] = Sync[F].delay {
log.info(str)
}
override def warning(str: String): F[Unit] = Sync[F].delay {
log.warn(str)
}
override def error(str: String): F[Unit] = Sync[F].delay {
log.error(str)
}
override def error(str: String, t: Throwable): F[Unit] = Sync[F].delay {
log.error(t)(str)
}
override def to[G[_] : Sync]: Logger[G] =
loggerInst[G](log)
override def subLogger(name: String): Logger[F] =
loggerInst(getLogger(s"${log.name}.$name"))
}
def noop[F[_] : Applicative]: Logger[F] = new Logger[F] {
override def trace(str: String): F[Unit] = Applicative[F].unit
override def debug(str: String): F[Unit] = Applicative[F].unit
override def info(str: String): F[Unit] = Applicative[F].unit
override def warning(str: String): F[Unit] = Applicative[F].unit
override def error(str: String): F[Unit] = Applicative[F].unit
override def error(str: String, t: Throwable): F[Unit] = Applicative[F].unit
override val underlying: Option[Log4sLogger] = None
override def to[G[_] : Sync]: Logger[G] = null
override def subLogger(name: String): Logger[F] = this
}
}
package com.hunorkovacs.catsi
import cats.data.Writer
import cats.effect.Sync
import org.log4s.{getLogger, Logger => Log4sLogger}
import WriterLogger._
class WriterLogger extends Logger[WF] {
override def trace(str: String): WF[Unit] = myUnit
override def debug(str: String): WF[Unit] = myUnit
override def info(str: String): WF[Unit] = Writer[String, Unit](str, ())
override def warning(str: String): WF[Unit] = myUnit
override def error(str: String): WF[Unit] = myUnit
override def error(str: String, t: Throwable): WF[Unit] = myUnit
override val underlying: Option[Log4sLogger] = None
override def to[G[_]: Sync]: Logger[G] = null
override def subLogger(name: String): Logger[WF] = this
private def myUnit: Writer[String, Unit] = Writer[String, Unit]("", ())
}
object WriterLogger {
type WF[A] = Writer[String, A]
}
package com.hunorkovacs.catsi
import cats.implicits._
import com.hunorkovacs.catsi.WriterLogger
import com.hunorkovacs.catsi.WriterLogger._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class WriterMonadTest extends AnyFlatSpec with Matchers {
"WriterMonad" should
"return the result of the told input" in {
val logger: WriterLogger = new WriterLogger()
val result: WF[Unit] = logger.info("aaa")
result.written shouldBe ("aaa")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment