scala logging playframework enumerator iteratee

scala - Reproducir/Registrar/Imprimir cuerpo de respuesta/Ejecutar sobre enumerador/tamponar el cuerpo



logging playframework (3)

Como me parece, si result.body &> Enumeratee.map sesión en result.body &> Enumeratee.map (como se sugiere en https://stackoverflow.com/a/27630208/1781549 ) y el cuerpo del resultado se presenta en más de un fragmento, entonces cada fragmento se registrará de forma independiente. Probablemente no quieras esto.

Lo implementaría así:

val ret = block(request).flatMap { result => val consume = Iteratee.consume[Array[Byte]]() val bodyF = Iteratee.flatten(result.body(consume)).run bodyF.map { bodyBytes: Array[Byte] => // // Log the body // result.copy(body = Enumerator(bodyBytes)) } }

Pero tenga cuidado: la idea general de esto es consumir todos los datos del Enumerador result.body antes de iniciar sesión (y devolver el nuevo Enumerator). Por lo tanto, si la respuesta es grande o confía en la transmisión, probablemente también sea lo que no desea.

Estoy buscando una forma de imprimir el cuerpo de respuesta en Play framework, tengo un código como este:

object AccessLoggingAction extends ActionBuilder[Request] { def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = { Logger.info(s"""Request: id=${request.id} method=${request.method} uri=${request.uri} remote-address=${request.remoteAddress} body=${request.body} """) val ret = block(request) /* ret.map {result => Logger.info(s"""Response: id=${request.id} body=${result.body} """) } */ //TODO: find out how to print result.body (be careful not to consume the enumerator) ret } }

Actualmente, el código comentado no funciona como yo quería, es decir, se imprimiría:

Response: id=1 body=play.api.libs.iteratee.Enumerator$$anon$18@39e6c1a2

Entonces, necesito encontrar una manera de obtener una Cadena de Enumerador [Matriz [Byte]]. Traté de entender el concepto de Enumerator leyendo esto: http://mandubian.com/2012/08/27/understanding-play2-iteratees-for-normal-humans/

Entonces ... si lo entiendo correctamente:

  1. No debería secar el enumerador en el proceso de convertirlo a String. De lo contrario, el cliente no recibiría nada.

  2. Supongamos que descubro cómo implementar el mecanismo de T / filtro. Pero entonces ... ¿no vencería el propósito del marco Play como un marco de transmisión sin bloqueo (porque estaría construyendo la matriz completa de bytes en la memoria, antes de llamar a String y finalmente registrarla)?

Entonces, ¿cuál es la forma correcta de registrar la respuesta?

Gracias de antemano, Raka


Este código funciona:

object AccessLoggingAction extends ActionBuilder[Request] { def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = { val start = System.currentTimeMillis Logger.info(s"""Request: id=${request.id} method=${request.method} uri=${request.uri} remote-address=${request.remoteAddress} body=${request.body} """) val resultFut = block(request) resultFut.map {result => val time = System.currentTimeMillis - start Result(result.header, result.body &> Enumeratee.map(arrOfBytes => { val body = new String(arrOfBytes.map(_.toChar)) Logger.info(s"""Response: id=${request.id} method=${request.method} uri=${request.uri} delay=${time}ms status=${result.header.status} body=${body}""") arrOfBytes }), result.connection) } } }

En parte aprendí esto desde aquí (sobre cómo sacar el conjunto de bytes del enumerador): Scala Play 2.1: Acceder a los cuerpos de solicitud y respuesta en un filtro .

Estoy usando Play 2.3.7 mientras que el enlace que di usa 2.1 (y todavía usa PlainResult, que ya no existe en 2.3).


Utilicé la respuesta anterior como punto de partida, pero noté que solo registrará las respuestas si hay un cuerpo presente. Lo hemos adaptado a esto:

var responseBody = None:Option[String] val captureBody = Enumeratee.map[Array[Byte]](arrOfBytes => { val body = new String(arrOfBytes.map(_.toChar)) responseBody = Some(body) arrOfBytes }) val withLogging = (result.body &> captureBody).onDoneEnumerating({ logger.debug(.. create message here ..) }) result.copy(body=withLogging)