【问题标题】:Thread name in Akka actor logging regarding PinnedDispatcherAkka actor 记录中有关 PinnedDispatcher 的线程名称
【发布时间】:2020-06-15 19:01:10
【问题描述】:

我正在使用 Akka v2.5.23 编写应用程序。该应用程序涉及以下参与者:

  • 名为 CalculatorRouter 的路由器参与者类
  • 名为 Calculator 的路由演员类

我在创建 Calculator Actor 时配置了 PinnedDispatcher,并将 log.info 放入此 Actor 类的接收方法中。我希望在日志文件中看到包含pinned 的线程名称字段。但是,线程名称字段为default-dispatcher。我在日志文件中搜索,发现与这个log.info 相关的所有线程名称都是default-dispatcher。我的代码有问题吗?

日志文件sn-p:

09:49:25.116 [server-akka.actor.default-dispatcher-14] INFO  handler.Calculator $anonfun$applyOrElse$3 92 - akka://server/user/device/$a/$a Total calc received

以下是sn-ps的代码:

class CalculatorRouter extends Actor with ActorLogging {
    var router = {
        val routees = Vector.fill(5) {
            val r = context.actorOf(Props[Calculator].withDispatcher("calc.my-pinned-dispatcher"))
            context.watch(r)
            ActorRefRoutee(r)
        }
        Router(SmallestMailboxRoutingLogic(), routees)
    }

    def receive = {
        case w:  Calc => router.route(w, sender)
        case Terminated(a) =>
            router.removeRoutee(a)
            val r = context.actorOf(Props[Calculator].withDispatcher("calc.my-pinned-dispatcher"))
            context.watch(r)
            router = router.addRoutee(r)
    }
}

calc.my-pinned-dispatcher 配置如下:

  calc.my-pinned-dispatcher {
    executor="thread-pool-executor"
    type=PinnedDispatcher
  }

类计算器源码如下:

class Calculator extends Actor with ActorLogging {
    val w = new UdanRemoteCalculateTotalBalanceTime

    def receive = {
        case TotalCalc(fn, ocvFilepath, ratedCapacity, battCount) ⇒

                log.info(s"${self.path} Total calc received")
                Try{
                    w.CalculateTotalBalanceTime(1, fn, ocvFilepath, ratedCapacity)
                } match {
                    case Success(t) ⇒
                        val v = t.getIntData
                        sender.!(Calculated(v))(context.parent)
                    case Failure(e) ⇒ log.error(e.getMessage)
                }
    }
}

object Calculator {
    sealed trait Calc
    final case class TotalCalc(filename: String, ocvFilepath: String, ratedCapacity: String, batteryCount: Int) extends Calc
}

logback.xml

<configuration debug="true">
   <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <!-- reset all previous level configurations of all j.u.l. loggers -->
        <resetJUL>true</resetJUL>
    </contextListener>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/var/log/app.log</file>
        <append>true</append>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
          <!-- daily rollover -->
              <fileNamePattern>/var/log/app.%d{yyyy-MM-dd}.log</fileNamePattern>

              <!-- keep 30 days' worth of history capped at 3GB total size -->
              <maxHistory>100</maxHistory>
              <totalSizeCap>30000MB</totalSizeCap>
        </rollingPolicy>

        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M %L - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
        <queueSize>500</queueSize>
        <includeCallerData>true</includeCallerData>
    </appender>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %M %L - %msg%n</pattern>
        </encoder>
    </appender>


    <logger name="application" level="DEBUG"/>
    <root level="INFo">
        <appender-ref ref="ASYNCFILE"/>
    </root>
</configuration>


'20 3 月 4 日更新

感谢@anand-sai。在我将akka.loggers-dispatcher = "calc.my-pinned-dispatcher" 放入conf 文件后,我在日志文件的每一行中都有my-pinned-dispatcher-xx 作为线程名称。我认为线程名称应该指示actor Calculator 的receive 方法正在执行的线程,在这种情况下,类似于'pinned-dispatcher-xx',因为线程是根据我的配置由固定调度程序获得的。现在证明是logger的dispatcher获取的线程。如果是这种情况,如何为参与者的消息处理程序代码记录线程名称?

【问题讨论】:

    标签: scala logging akka


    【解决方案1】:

    我认为解决方案是在您的application.conf 中添加akka.loggers-dispatcher

    calc.my-pinned-dispatcher {
        executor="thread-pool-executor"
        type=PinnedDispatcher
      }
    akka.loggers-dispatcher = "calc.my-pinned-dispatcher"
    

    如果你在akka的default configuration中搜索logger-dispatcher,你会发现值是“akka.actor.default-dispatcher”,我们需要覆盖这个配置,如上所示。

    编辑

    ActorLogging 是异步的。当您使用 ActorLogging 进行日志记录时,它会向日志记录参与者发送一条消息,该参与者默认在默认调度程序上运行。 Logback 记录调用它的线程,这将是 ActorLogging actor 的线程,而不是您的 actor 的线程。为了实现这个目标,有一个所谓的 Mapped Diagnostic Context (MDC) 捕获了akka source(执行日志记录的参与者的路径)source thread(执行日志记录的线程)以及执行日志记录的更多内容。

    documentation

    由于日志记录是异步完成的,因此 在 MDC 中使用属性名称捕获已执行的日志记录 sourceThread.

    执行日志记录的actor的路径可用 在属性名称为 akkaSource 的 MDC 中。

    执行日志记录的参与者系统名称可用 在属性名称为 sourceActorSystem 的 MDC 中,但那是 通常也包含在akkaSource 属性中。

    actor 系统的地址,如果是,则包含主机和端口 系统正在使用集群,可通过akkaAddress获得。

    对于类型化的 Actor,日志事件的时间戳是在日志调用时获取的 是为 Akka 的内部日志记录以及经典演员制作的 日志记录是异步的,这意味着日志条目的时间戳 从调用底层记录器实现时获取, 一开始可能会令人惊讶。如果你想更准确 输出此类记录器的时间戳,使用 MDC 属性 akkaTimestamp。请注意,MDC 密钥对于 a 没有任何值 打字演员。

    如果有帮助请告诉我!!

    【讨论】:

    • 将 akka.loggers-dispatcher = "calc.my-pinned-dispatcher" 放入 conf 文件后,我在日志文件的每一行中都有 my-pinned-dispatcher-xx 作为线程名称。跨度>
    • 感谢您的编辑和参考文档。我已将 sourceThread 放入配置文件中,它按预期工作。日志文件现在将 pinned-dispatcher-xx 作为与 PinnedDispatcher 关联的参与者中的日志调用的线程名称。
    猜你喜欢
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    • 2016-12-14
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多