How to make akka-http logRequest log to a specific

2019-08-01 05:56发布

问题:

I have a Main non-actor class where routes are defined.

I would like to log the incoming requests to those routes into a specific log file but they are being logged into the "root" log file.

val logger = LoggerFactory.getLogger("access_log")l
logger.info("log to access log") //<--- is logged in access log file

val routes =
      path("ping" ) {
          logRequest("logging ping", Logging.InfoLevel) { <-- logged to root log
            complete("pong")
          }
        }
      }

The documentation states that "To change the logger, wrap this directive by withLog.", but I don't know how to change my logger into a LoggingAdapter that withLog is called with.

My logback.xml has a logger entry

 <logger name="access_log" level="INFO">
        <appender-ref ref="ACCESSLOG" />
    </logger>

Can anyone help?

Edit 2: following @Ramon J Romero y Vigil's update to his answer I realise I can simply (given a correctly configured logback.xml) do:

val accessLog = Logging(system.eventStream, "access_log")

val routes =
  path("ping" ) {
    withLog(accessLog) {
      logRequest("ping", Logging.InfoLevel) {
        complete("pong")
      }
    }
  }

Edit:

Based on @Ramon J Romero y Vigil's answer I was able to get the requests logged to my access_log by doing the following:

val loggingAdapter : LoggingAdapter = new LoggingAdapter {
      override def isDebugEnabled : Boolean = logger.isDebugEnabled
      override def isErrorEnabled : Boolean = logger.isErrorEnabled
      override def isInfoEnabled : Boolean = logger.isInfoEnabled
      override def isWarningEnabled : Boolean = logger.isWarnEnabled

      override def notifyDebug(message: String): Unit = logger.debug(message)

      override protected def notifyError(message: String): Unit =  logger.error(message)

      override protected def notifyError(cause: Throwable, message: String): Unit = logger.error(message, cause)

      override protected def notifyWarning(message: String): Unit = logger.warn(message)

      override protected def notifyInfo(message: String): Unit = logger.info(message)
    }

    val routes =
      path("ping" ) {
        withLog(loggingAdapter) {
          logRequest("**ping**", Logging.InfoLevel) {
            complete("pong")
          }
        }
      } 

回答1:

If you have to use LoggerFactory

It appears as if you are using slf4j directly instead of using akka's logging mechanisms, but you want akka to use the slf4j Logger instead of its own LoggingAdapter. This type of mixing & matching of log systems isn't advised, it is easier to stick with one or the other.

If this mixing is necessary then you can just create a LoggingAdapter manually by using the Logger that you've already created and overriding all of the abstract fields in LoggingAdapter:

val logger = LoggerFactory.getLogger("access_log")

val loggingAdapter : LoggingAdapter = new LoggingAdapter {
  override def isDebugEnabled : Boolean = logger.isDebugEnabled
  override def isErrorEnabled : Boolean = logger.isErrorEnabled
  ...
}

The adapter can now be used by adding the withLog directive.

Using Akka Logging Directly

It is much easier to utilize akka's logging functionality directly.

This still allows you to interact with the slf4j api. By using the slf4j API you can specify which logback appender you want to use, including file appenders in which the output file is specified in configuration settings.