PhD*_*PhD 5 scala function-composition finagle
在我们的代码中,我们创建了许多“ finagle管道”,如下所示:
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
Run Code Online (Sandbox Code Playgroud)
我现在希望能够在这样的链中的任何地方 “插入”记录器。记录器只会记录请求进入并收到响应的事实。像这样:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用这种方法,我们必须不断声明多个记录器,以便类型可以正确对齐,然后在“正确的位置”插入。
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
Run Code Online (Sandbox Code Playgroud)
有没有办法可以避免这种情况?是否只有一个记录器可以自动推断Req/Resp类型并在链中“可插入任何地方”?
例如:
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
Run Code Online (Sandbox Code Playgroud)
我想不出一种定义自动记录器的方法。我的第一个想法是按照@Krzysztof的建议依赖于编译器类型推断,但是由于带有参数的记录器而最终导致类型错误,[Nothing, Nothing]因此似乎那里的编译器推断触发得太早了。鉴于此,我不确定在没有每种记录器显式类型的情况下,您的描述方式是否可行。
但是,要获得非常相似的功能,您可以使用在运行之前附加Logger 的方法来扩展Filterand Service类withLogging。到那时,您已经具有足够的类型信息来显式构造记录器,并且它还使您可以传递参数:
implicit class FilterLogging[ReqIn, RepOut, ReqOut, RepIn](filter: Filter[ReqIn, RepOut, ReqOut, RepIn]) {
def withLogging(param: String) : Filter[ReqIn, RepOut, ReqOut, RepIn] = new LoggerFilter[ReqIn, RepOut](param).andThen(filter)
}
implicit class ServiceLogging[Req, Rep](service: Service[Req, Rep]) {
def withLogging(param: String) : Service[Req, Rep] = new LoggerFilter[Req, Rep](param).andThen(service)
}
val pipeline = f1.withLogging("f1") andThen f2 andThen f3.withLogging("f3") andThen service.withLogging("s")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
134 次 |
| 最近记录: |