From 429e5c6a3652fc4349c8e71700327494f22ee79b Mon Sep 17 00:00:00 2001 From: "Brian P. Holt" Date: Tue, 10 Jan 2023 18:09:50 -0600 Subject: [PATCH] provide a LoggerFactory[F] given a Trace[F] --- .../typelevel/log4cats/natchez/package.scala | 84 ++++++++++++------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/core/shared/src/main/scala/org/typelevel/log4cats/natchez/package.scala b/core/shared/src/main/scala/org/typelevel/log4cats/natchez/package.scala index b812848..7914985 100644 --- a/core/shared/src/main/scala/org/typelevel/log4cats/natchez/package.scala +++ b/core/shared/src/main/scala/org/typelevel/log4cats/natchez/package.scala @@ -4,43 +4,65 @@ import _root_.natchez._ import cats._ import cats.syntax.all._ import org.typelevel.log4cats.extras.LogLevel +import org.typelevel.log4cats.natchez.TraceLogger._ package object natchez { - /** - * `LogLevel` as an OpenTelemetry `SeverityNumber` - * - * See https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitynumber - * - * @return LogLevel as an OpenTelemetry SeverityNumber, converted to the TraceValue ADT - */ - private val logLevelToSeverityNumber: LogLevel => TraceValue = { - case LogLevel.Trace => 1 - case LogLevel.Debug => 5 - case LogLevel.Info => 9 - case LogLevel.Warn => 13 - case LogLevel.Error => 17 - } + implicit def traceLoggerFactory[F[_] : Trace : Applicative]: LoggerFactory[F] = new LoggerFactory[F] { + override def getLoggerFromName(name: String): SelfAwareStructuredLogger[F] = + new TraceLogger[F] with SelfAwareStructuredLogger[F] { + // if LoggerFactory didn't require the Loggers it returns + // to be _self aware_ structured loggers, we'd omit these. 🤷 + override def isTraceEnabled: F[Boolean] = true.pure[F] + override def isDebugEnabled: F[Boolean] = true.pure[F] + override def isInfoEnabled: F[Boolean] = true.pure[F] + override def isWarnEnabled: F[Boolean] = true.pure[F] + override def isErrorEnabled: F[Boolean] = true.pure[F] + } - /** - * `LogLevel` as an OpenTelemetry `SeverityText` - * - * See https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitytext - * and https://opentelemetry.io/docs/reference/specification/logs/data-model/#displaying-severity - * - * @return LogLevel as an OpenTelemetry SeverityNumber, converted to the TraceValue ADT - */ - private val logLevelToSeverityText: LogLevel => TraceValue = { - case LogLevel.Trace => "TRACE" - case LogLevel.Debug => "DEBUG" - case LogLevel.Info => "INFO" - case LogLevel.Warn => "WARN" - case LogLevel.Error => "ERROR" + override def fromName(name: String): F[SelfAwareStructuredLogger[F]] = getLoggerFromName(name).pure[F] } - private val mapContextToTraceValue: Map[String, String] => List[(String, TraceValue)] = - _.toList.nested.map(TraceValue.StringValue).value + implicit def traceLogger[F[_] : Trace : Applicative]: StructuredLogger[F] = new TraceLogger[F] +} + +package natchez { + object TraceLogger { + /** + * `LogLevel` as an OpenTelemetry `SeverityNumber` + * + * See https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitynumber + * + * @return LogLevel as an OpenTelemetry SeverityNumber, converted to the TraceValue ADT + */ + private[TraceLogger] val logLevelToSeverityNumber: LogLevel => TraceValue = { + case LogLevel.Trace => 1 + case LogLevel.Debug => 5 + case LogLevel.Info => 9 + case LogLevel.Warn => 13 + case LogLevel.Error => 17 + } + + /** + * `LogLevel` as an OpenTelemetry `SeverityText` + * + * See https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitytext + * and https://opentelemetry.io/docs/reference/specification/logs/data-model/#displaying-severity + * + * @return LogLevel as an OpenTelemetry SeverityNumber, converted to the TraceValue ADT + */ + private[TraceLogger] val logLevelToSeverityText: LogLevel => TraceValue = { + case LogLevel.Trace => "TRACE" + case LogLevel.Debug => "DEBUG" + case LogLevel.Info => "INFO" + case LogLevel.Warn => "WARN" + case LogLevel.Error => "ERROR" + } + + private[TraceLogger] val mapContextToTraceValue: Map[String, String] => List[(String, TraceValue)] = + _.toList.nested.map(TraceValue.StringValue.apply).value + } - implicit def TraceLogger[F[_] : Trace : Applicative]: StructuredLogger[F] = new StructuredLogger[F] { + class TraceLogger[F[_] : Trace : Applicative] extends StructuredLogger[F] { private def log(logLevel: LogLevel, ctx: Map[String, String], maybeThrowable: Option[Throwable],