假设我有一个基于Futures、基于scala.concurrent的scala应用程序来处理asyn /一致性(到目前为止还没有使用任何参与者)。
在许多地方,我使用log4j将内容记录到日志文件中。由于是I/O,我想我可以通过向LoggingActor发送日志消息来提高性能
就像这样:
def stuffTodo(arg:String)(implicit ex:ExecutionContext) : Future[Result] = {
// important performant work
// ..
logAcrot ! LogMessage("message-1")
// ...
}其中msg:case class LogMessage(msg:String, implicit ex:ExecutionContext)
然后在ActorLog
def receive = {
case LogMessage(msg:String, ex:ExecutionContext) ⇒ {log.info(msg + ex)}
}我看到了其他方法,基本上是包装 scala.concurent.ExecutionContext (用当前线程),使用映射诊断上下文-magic (log4j),并通过将线程id附加到日志消息来进行日志记录。但最终它会阻塞/减缓线程/执行(据我理解),并使应用程序变慢。
在本例中,使用此Actor,日志记录保持独立/异步并同时保持顺序。
走这条路好吗?分享经验故事?赞成/反对/关切?在重负荷试验之前询问..。
发布于 2015-09-10 13:37:02
Akka已经很好地支持日志记录,日志记录在页面伐木- Akka文档上。我不认为在您的系统中创建记录器参与者是必要或可取的,特别是在这种机制已经存在的情况下。
您可能已经使用了异步执行日志记录的LoggingAdaptor类,它通过将其发送到事件总线来实现这一点。您应该能够在参与者或外部使用相同的机制。
测井Mixin
Scala为参与者提供了一个混合器,它为参与者创建了记录器,并允许设置MDC。来自文件:
import Logging.MDC
final case class Req(work: String, visitorId: Int)
class MdcActorMixin extends Actor with akka.actor.DiagnosticActorLogging {
var reqId = 0
override def mdc(currentMessage: Any): MDC = {
reqId += 1
val always = Map("requestId" -> reqId)
val perMessage = currentMessage match {
case r: Req => Map("visitorId" -> r.visitorId)
case _ => Map()
}
always ++ perMessage
}
def receive: Receive = {
case r: Req => {
log.info(s"Starting new request: ${r.work}")
}
}
}在参与者之外登录
在Logging.scala文件中有两个示例用于在参与者之外创建一个LoggingSource:
trait MyType { // as an example
def name: String
}
implicit val myLogSourceType: LogSource[MyType] = new LogSource[MyType] {
def genString(a: MyType) = a.name
}
class MyClass extends MyType {
val log = Logging(eventStream, this) // will use "hallo" as logSource
def name = "hallo"
}第二个变体用于包括参与者系统的地址:
trait MyType { // as an example
def name: String
}
implicit val myLogSourceType: LogSource[MyType] = new LogSource[MyType] {
def genString(a: MyType) = a.name
def genString(a: MyType, s: ActorSystem) = a.name + "," + s
}
class MyClass extends MyType {
val sys = ActorSystem("sys")
val log = Logging(sys, this) // will use "hallo,akka://sys" as logSource
def name = "hallo"
}如果需要,可以在日志适配器上设置MDC。
日志线程和MDC
当日志记录由另一个线程异步执行时,文档还介绍了日志记录线程上的要点。
由于日志记录是异步完成的,因此执行日志记录的线程将在属性名为sourceThread的映射诊断上下文(MDC)中捕获。使用Logback,在模式布局配置中%X{sourceThread}说明符中可以使用线程名。
发布于 2015-09-10 03:58:08
看起来就像在工程上。
如果我要这样做,我将使用logback,并实现自定义异步Appender,因此如果我决定不停止,就不必更改代码。
否则,日志库是不错的选择,我可能会尝试调优它以获得更好的性能,并在实现此特性时依赖其他人的经验。
https://stackoverflow.com/questions/32491795
复制相似问题