All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.odin.config.package.scala Maven / Gradle / Ivy

package io.odin

import java.time.LocalDateTime

import cats.Monad
import cats.effect.kernel.Clock
import cats.syntax.all._
import io.odin.internal.StringContextLength
import io.odin.loggers.DefaultLogger

import scala.annotation.tailrec

package object config extends FileNamePatternSyntax {

  /**
    * Route logs to specific logger based on the fully qualified package name.
    * Beware of O(n) complexity due to the partial matching done during the logging
    */
  def enclosureRouting[F[_]: Clock: Monad](router: (String, Logger[F])*): DefaultBuilder[F] = {
    new DefaultBuilder[F](new EnclosureRouting(_, router.toList))
  }

  /**
    * Route logs to specific logger based on `Class[_]` instance. Beware of O(n) complexity due to the partial matching
    * done during the logging
    */
  def classRouting[F[_]: Clock: Monad](
      router: (Class[_], Logger[F])*
  ): DefaultBuilder[F] =
    new DefaultBuilder[F](
      new EnclosureRouting(
        _,
        router.toList.map {
          case (cls, logger) =>
            cls.getName -> logger
        }
      )
    )

  /**
    * Route logs based on their level
    *
    * Complexity should be roughly constant
    */
  def levelRouting[F[_]: Clock: Monad](router: Map[Level, Logger[F]]): DefaultBuilder[F] =
    new DefaultBuilder[F]({ (default: Logger[F]) =>
      new DefaultLogger[F](Level.Trace) {
        def submit(msg: LoggerMessage): F[Unit] = router.getOrElse(msg.level, default).log(msg)

        override def submit(msgs: List[LoggerMessage]): F[Unit] = {
          msgs.groupBy(_.level).toList.traverse_ {
            case (level, msgs) =>
              router.getOrElse(level, default).log(msgs)
          }
        }

        def withMinimalLevel(level: Level): Logger[F] =
          levelRouting(router.map {
            case (level, logger) =>
              level -> logger.withMinimalLevel(level)
          }).withDefault(default.withMinimalLevel(level))
      }
    })

  implicit class FileNamePatternInterpolator(private val sc: StringContext) extends AnyVal {

    def file(ps: FileNamePattern*): LocalDateTime => String = {
      StringContextLength.checkLength(sc, ps)
      dt => {
        @tailrec
        def rec(args: List[FileNamePattern], parts: List[String], acc: StringBuilder): String = {
          args match {
            case Nil          => acc.append(parts.head).toString()
            case head :: tail => rec(tail, parts.tail, acc.append(parts.head).append(head.extract(dt)))
          }
        }
        rec(ps.toList, sc.parts.toList, new StringBuilder())
      }
    }

  }

  implicit def str2fileNamePattern(str: String): FileNamePattern = {
    Value(str)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy