softwaremill / ox

Safe direct style concurrency and resiliency for Scala on the JVM

Home Page:https://ox.softwaremill.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add `log` (based on slf4j) operator

geminicaprograms opened this issue · comments

To consider: implement as logAsView using mapAsView

Some questions/discussion starters:

  1. How to manage slf4j dependency?

    1. make ox.core depend on slf4j
    2. add slf4j as "provided" dependency of ox.core (then users would need to add slf4j themselves in order to use .log operators
    3. create logging abstraction in ox.core and create a new module - ox.slf4j-logger, that would provide an implementation. Similar to org.apache.pekko.event.LoggingAdapter
    4. other?
  2. Handling logging level

    1. fixed default
    2. optional level with configurable default (via system property or something)
    3. other?
  3. Api proposal

  enum LogLevel:
    case Trace, Debug, Info, Warn, Error

  def log(name: String, level: LogLevel = LogLevel.Info, formatter: T => String = _.toString)(using Ox, StageCapacity): Source[T] =
    val logger = org.slf4j.LoggerFactory.getLogger(name)
    map(t => { logF(logger, level)(formatter(t)); t })

  def logAsView(name: String, level: LogLevel = LogLevel.Info, formatter: T => String = _.toString)(using Ox, StageCapacity): Source[T] =
    val logger = org.slf4j.LoggerFactory.getLogger(name)
    mapAsView(t => { logF(logger, level)(formatter(t)); t })

  private def logF(logger: org.slf4j.Logger, level: LogLevel): String => Unit =
    level match
      case LogLevel.Trace => logger.trace
      case LogLevel.Debug => logger.debug
      case LogLevel.Info  => logger.info
      case LogLevel.Warn  => logger.warn
      case LogLevel.Error => logger.error

To be honest I don't like neither of the options in 1., maybe since we already have .mapAsView, the simplest solution would be to add .tapAsView and document how this can be used for logging?