Skip to content

Commit

Permalink
Optional URL logging
Browse files Browse the repository at this point in the history
  • Loading branch information
lynxpluto authored and ihostage committed Jun 14, 2023
1 parent afa75ff commit d23482a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 27 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ It allows you to enable request/response (including the body) logging. It can be
```hocon
configured-ahc-ws-client.logging.enabled = true
```
Also, you can exclude some URLs by specifying a list of matching regexps.
```hocon
configured-ahc-ws-client.logging.skip-urls = ["(foo|bar)\\.acme\\.com/some/path"]
```
Enjoy!

### ServiceCall running on coroutines (Java ✗ / Scala ✗ / Kotlin ✓)
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
configured-ahc-ws-client {
logging {
# Enables or completely disables logging.
enabled = false
# List of regexp patterns of URLs to be excluded from logging.
skip-urls = []
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package org.taymyr.lagom.ws

import java.util.UUID
import java.util.UUID.randomUUID

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import play.api.libs.ws.StandaloneWSResponse
Expand All @@ -11,31 +8,37 @@ import play.api.libs.ws.WSRequestFilter
import play.api.libs.ws.ahc.CurlFormat
import play.api.libs.ws.ahc.StandaloneAhcWSRequest

import java.util.UUID
import java.util.UUID.randomUUID
import scala.concurrent.ExecutionContext

class AhcRequestResponseLogger(logger: Logger)(implicit ec: ExecutionContext) extends WSRequestFilter with CurlFormat {
class AhcRequestResponseLogger(loggingSettings: LoggingSettings, logger: Logger)(implicit ec: ExecutionContext)
extends WSRequestFilter
with CurlFormat {

override def apply(executor: WSRequestExecutor): WSRequestExecutor = {
WSRequestExecutor { request =>
val eventualResponse = executor(request)
val correlationId = randomUUID()
val url = logRequest(request.asInstanceOf[StandaloneAhcWSRequest], correlationId)
override def apply(executor: WSRequestExecutor): WSRequestExecutor = WSRequestExecutor { request =>
val eventualResponse = executor(request)
val correlationId = randomUUID()
val r = request.asInstanceOf[StandaloneAhcWSRequest]
val url = r.buildRequest().getUrl
if (loggingSettings.skipUrls.exists { _.findFirstIn(url).nonEmpty }) {
eventualResponse
} else {
logRequest(r, url, correlationId)
eventualResponse.map { response =>
logResponse(response, url, correlationId)
response
}
}
}

private def logRequest(request: StandaloneAhcWSRequest, correlationId: UUID): String = {
val url = request.buildRequest().getUrl
val sb = new StringBuilder(s"Request to $url")
private def logRequest(request: StandaloneAhcWSRequest, url: String, correlationId: UUID): Unit = {
val sb = new StringBuilder(s"Request to $url")
sb.append("\n")
.append(s"Request correlation ID: $correlationId")
.append("\n")
.append(toCurl(request))
logger.info(sb.toString())
url
}

private def logResponse(response: StandaloneWSResponse, url: String, correlationId: UUID): Unit = {
Expand Down Expand Up @@ -84,11 +87,9 @@ object AhcRequestResponseLogger {

private val logger = LoggerFactory.getLogger("org.taymyr.lagom.ws.AhcRequestResponseLogger")

def apply()(implicit ec: ExecutionContext): AhcRequestResponseLogger = {
new AhcRequestResponseLogger(logger)
}
def apply(loggingSettings: LoggingSettings)(implicit ec: ExecutionContext): AhcRequestResponseLogger =
new AhcRequestResponseLogger(loggingSettings, logger)

def apply(logger: Logger)(implicit ec: ExecutionContext): AhcRequestResponseLogger = {
new AhcRequestResponseLogger(logger)
}
def apply(loggingSettings: LoggingSettings, logger: Logger)(implicit ec: ExecutionContext): AhcRequestResponseLogger =
new AhcRequestResponseLogger(loggingSettings, logger)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ import play.api.libs.ws.WSRequest
import play.api.libs.ws.ahc.AhcWSClient
import play.api.libs.ws.ahc.StandaloneAhcWSClient

import scala.collection.JavaConverters._
import scala.concurrent.ExecutionContext
import scala.util.matching.Regex

/**
* Extension of AhcWSClient with logging.
* Extension of [[AhcWSClient]] with logging.
*/
class ConfiguredAhcWSClient(underlyingClient: StandaloneAhcWSClient, config: Config)(
implicit executionContext: ExecutionContext
) extends AhcWSClient(underlyingClient = underlyingClient) {

private val isLogging = config.getBoolean("configured-ahc-ws-client.logging.enabled")
private val loggingSettings = LoggingSettings(config.getConfig("configured-ahc-ws-client.logging"))

override def url(url: String): WSRequest = {
val wSRequest = super.url(url)
if (isLogging) {
wSRequest.withRequestFilter(AhcRequestResponseLogger())
override def url(url: String): WSRequest =
if (loggingSettings.enabled) {
super.url(url).withRequestFilter(AhcRequestResponseLogger(loggingSettings))
} else {
wSRequest
super.url(url)
}
}
}

object ConfiguredAhcWSClient {
Expand All @@ -32,3 +32,20 @@ object ConfiguredAhcWSClient {
): ConfiguredAhcWSClient =
new ConfiguredAhcWSClient(underlyingClient, config)
}

case class LoggingSettings(enabled: Boolean, skipUrls: Seq[Regex])

object LoggingSettings {

def apply(config: Config): LoggingSettings = LoggingSettings(
config.getBoolean("enabled"),
config
.getStringList("skip-urls")
.asScala
.toSeq
.filter { s =>
s != null && s.nonEmpty
}
.map { _.r }
)
}

0 comments on commit d23482a

Please sign in to comment.