Skip to content

Instantly share code, notes, and snippets.

@paulpdaniels
Created December 2, 2022 07:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paulpdaniels/1c8e91fae21a6073b0c70b86a012be73 to your computer and use it in GitHub Desktop.
Save paulpdaniels/1c8e91fae21a6073b0c70b86a012be73 to your computer and use it in GitHub Desktop.
A ZIO2 compatible LogStage encoding
package compat
import izumi.functional.mono.SyncSafe
import izumi.fundamentals.platform.language.CodePositionMaterializer
import izumi.logstage.api.Log
import izumi.logstage.api.Log.{CustomContext, Entry, Level, LogArg, Message}
import izumi.logstage.api.logger.AbstractLogger
import izumi.logstage.api.rendering.AnyEncoded
import izumi.logstage.macros.LogIOMacroMethods._
import logstage.UnsafeLogIO.UnsafeLogIOSyncSafeInstance
import LogZIOAsk.LogZIOAskImpl
import logstage.{IzLogger, LogIO, UnsafeLogIO}
import zio.{UIO, URIO, ZIO, ZLayer}
trait LogZIO extends UnsafeLogIO[UIO] {
self =>
// final def raw: LogIORaw[UIO, AnyEncoded] = new izumi.logstage.api.logger.LogIORaw(this)
final def trace(message: String): UIO[Unit] = macro scTraceMacro[UIO]
final def debug(message: String): UIO[Unit] = macro scDebugMacro[UIO]
final def info(message: String): UIO[Unit] = macro scInfoMacro[UIO]
final def warn(message: String): UIO[Unit] = macro scWarnMacro[UIO]
final def error(message: String): UIO[Unit] = macro scErrorMacro[UIO]
final def crit(message: String): UIO[Unit] = macro scCritMacro[UIO]
def log(entry: Entry): UIO[Unit]
def log(logLevel: Level)(messageThunk: => Message)(implicit pos: CodePositionMaterializer): UIO[Unit]
def withCustomContext(context: CustomContext): LogZIO
final def apply(context: CustomContext): LogZIO = withCustomContext(context)
final def withCustomContext(context: (String, AnyEncoded)*): LogZIO = withCustomContextMap(context.toMap)
final def withCustomContextMap(context: Map[String, AnyEncoded]): LogZIO = withCustomContext(
CustomContext.fromMap(context)
)
final def apply(context: (String, AnyEncoded)*): LogZIO = withCustomContextMap(context.toMap)
final def apply(context: Map[String, AnyEncoded]): LogZIO = withCustomContextMap(context)
}
object LogZIO {
private implicit val zioSyncSafe: SyncSafe[UIO] = new SyncSafe[UIO] {
def syncSafe[A](unexceptionalEff: => A): UIO[A] = ZIO.succeed(unexceptionalEff)
}
object log extends LogZIOAskImpl(identity)
val nullLogger = fromLogger(IzLogger.NullLogger)
val nullLayer = ZLayer.succeed(nullLogger)
def fromLogger(logger: AbstractLogger): LogZIO = {
new UnsafeLogIOSyncSafeInstance[UIO](logger)(SyncSafe[UIO]) with LogZIO {
def log(entry: Log.Entry): UIO[Unit] = ZIO.logAnnotations.map { annotations =>
logger.log(entry.addCustomContext(customContext(annotations)))
}
def log(logLevel: Level)(messageThunk: => Log.Message)(implicit pos: CodePositionMaterializer): UIO[Unit] =
ZIO.logAnnotations.map { annotations =>
logger.withCustomContext(customContext(annotations)).log(logLevel)(messageThunk)
}
def withCustomContext(context: CustomContext): LogZIO =
fromLogger(logger.withCustomContext(context))
private def customContext(annotations: Map[String, String]): CustomContext =
CustomContext(annotations.view.map { case (k, v) => LogArg(Seq(k), v, hiddenName = false, None) }.toSeq)
}
}
}
object LogZIOAsk {
/** Lets you carry LogIO3 capability in environment
*
* {{{
* import logstage.{LogIO3, LogIO3Ask}
* import logstage.LogIO3Ask.log
* import zio.ZIO
*
* def fn[F[-_, +_, +_]: LogIO3Ask]: F[LogIO3Ask.Service[F], Unit] = {
* log.info(s"I'm logging with ${log}stage!")
* }
*
* fn[ZIO]
* }}}
*/
@inline def log(implicit l: LogZIOAskImpl): l.type = l
class LogZIOAskImpl(f: LogZIO => LogZIO) extends LogIO[URIO[LogZIO, *]] {
override final def log(entry: Log.Entry): URIO[LogZIO, Unit] =
ZIO.serviceWithZIO(f(_).log(entry))
override final def log(logLevel: Level)(messageThunk: => Log.Message)(implicit
pos: CodePositionMaterializer
): URIO[LogZIO, Unit] =
ZIO.serviceWithZIO(f(_).log(logLevel)(messageThunk))
override final def unsafeLog(entry: Log.Entry): ZIO[LogZIO, Nothing, Unit] =
ZIO.serviceWithZIO(f(_).log(entry))
override final def acceptable(loggerId: Log.LoggerId, logLevel: Level): ZIO[LogZIO, Nothing, Boolean] =
ZIO.serviceWithZIO(f(_).acceptable(loggerId, logLevel))
override final def acceptable(logLevel: Level)(implicit
pos: CodePositionMaterializer
): ZIO[LogZIO, Nothing, Boolean] =
ZIO.serviceWithZIO(f(_).acceptable(logLevel))
override final def createEntry(logLevel: Level, message: Log.Message)(implicit
pos: CodePositionMaterializer
): ZIO[LogZIO, Nothing, Log.Entry] =
ZIO.serviceWithZIO(f(_).createEntry(logLevel, message))
override final def createContext(logLevel: Level, customContext: CustomContext)(implicit
pos: CodePositionMaterializer
): ZIO[LogZIO, Nothing, Log.Context] =
ZIO.serviceWithZIO(f(_).createContext(logLevel, customContext))
override final def withCustomContext(context: CustomContext): LogIO[URIO[LogZIO, *]] = {
new LogZIOAskImpl(_.withCustomContext(context))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment