When using a traditional web server, we have access logs and request logs already defined for us. Most well known web server packages generates these logs so that we can track what is going on in a production environment.

This is a little different with Akka HTTP. Just like with anything else we build with this tool, we start with powerful primitives and we are expected to put together the feature we want by combining those primitives. Akka HTTP won’t on it own generate a log for us.

The logging primitives

To help us get started, Akka provides a series of logging primitives in the class DebuggingDirectives. Some of these log the request, some log the result, and there is one that logs both. Since we are trying to build a log similar to most web server logs, we want to log both.

logRequestResult(("HTTP Request Result", Logging.InfoLevel)){
  //your route handling code here
}

This will put a nice entry into the log that contains all info from both request and response., including cookies, and even the response content. This is close to what we want but it has too much detail. We certainly don’t want our logs to contain the content of all files returned, because we won’t see the forest from the tree. Also noteworthy, we must be cognizant of security: We don’t want to log passwords now do we? Luckily, we can customize.

Customizing the request result logging

We will write a directive that won’t print out the entity content. One of the signatures of logRequestResult allows to easily make this customization:

def logHttp: Directive0 = {
  def logWithoutBody(req: HttpRequest): 
    RouteResult => Option[LogEntry] = {
    case RouteResult.Complete(res) => 
      Some(LogEntry(s"Request $req : Response ${res.status} ${res.headers}", 
        Logging.InfoLevel))
    case RouteResult.Rejected(rej) => 
      Some(LogEntry(s"Request $req : Response $rej", Logging.InfoLevel))
  }
  DebuggingDirectives.logRequestResult(logWithoutBody _)
}

Then we would use this as follows:

logHttp{
   get{
      //other route handling code goes here
   }
}

For me this produced nice concise log messages.

Additional logging

Now if we want to log additional info beyond just requests and replies, the extractRequestContect directive will give us a logging adapter, that we can use.

extractRequestContext { ctx =>
   get {
     //route handling code here
     ctx.log(...)
   }
}

Conclusion

While Akka HTTP does not come with any standard web server logs out of the box, it remains consistent with its design philosophy in that it allows us to quickly construct one from primitives, in a manner of minutes. The logging primitives are in the class DebuggingDirectives and they provide a variety of signatures to tailor our logging to exactly what we want.