In our code we create many "finagle pipelines" like so:
val f1 = new Filter[A,B,C,D](...)
val f2 = new SimpleFilter[C,D](...)
val f3 = new Filter[C,D,E,F](...)
val s = new Service[E,F](...)
val pipeline: Service[A,B] = f1 andThen f2 andThen f3 andThen s
I would now like the ability to "insert" loggers anywhere in such a chain. The logger would only log the fact that a request came in and a response was received. Something like this:
class LoggerFilter[Req, Resp](customLog: String) extends SimpleFilter[Req, Resp] with LazyLogging{
override def apply(request: Req, service: Service[Req, Resp]): Future[Resp] = {
logger.info(s"$customLog => Request: ${request.getClass.getName} -> ${service.toString}")
service(request).map{resp =>
logger.info(s"$customLog => Response: ${resp.getClass.getName} -> ${request.getClass.getName}")
resp
}
}
}
With this approach we have to keep declaring multiple loggers so that the types can align correctly and then we insert at the "right location".
val logger1 = new LoggerFilter[A,B]("A->B Logger")
val logger2 = new LoggerFilter[C,D]("C->D Logger")
val logger3 = new LoggerFilter[E,F]("E->F Logger")
val pipeline = logger1 andThen f1 andThen f2 andThen logger2 andThen f3 andThen logger3 andThen s
Is there a way this can be avoided? Is it possible to just have a single logger that can infer the Req/Resp
types automagically and be "insertable anywhere" in the chain?
E.g.:
val logger = getTypeAgnosticLogger // What's the implementation?
val pipeline = logger andThen f1 andThen f2 andThen logger andThen f3 andThen logger andThen s
// Is this possible - params for logger to print?
val pipeline = logger("f1") andThen f1 andThen f2 andThen logger("f3") andThen f3 andThen logger("s") andThen s