Using Behaviors.withMdc thread safety

akka-typed

(Kafkapre) #1

I am trying akka typed with MDC logging. It works fine, but I am not sure about thread safety of logiging. See code below. What happens with logger when eg log.info() is called. I understand that it is not ensured that callId is propagated into final log, but is it thread safe? How to handle logging in futures? Use log.withMdc().info() ? Thanks.

object LoggingTestActor {

  trait Command
  case class Process1(payload: String, callId: Int, replyTo: ActorRef[Done]) extends Command
  case class Process2(payload: String, replyTo: ActorRef[Done]) extends Command

  private val mdcFactory: Command => Map[String, Any] = {
    case Process1(_, callId, _) => Map("idCall" -> callId)
    case _: Process2 => Map.empty[String, Any]
  }

  def behavior(): Behavior[Command] = {
    Behaviors.setup[Command] { ctx =>
      Behaviors.withMdc(mdcFactory) {
        new Running(ctx)
      }
    }
  }

  class Running(ctx: ActorContext[Command]) extends AbstractBehavior[Command] {

    private val log = ctx.log
    private implicit val ec: ExecutionContextExecutor = ctx.executionContext

    override def onMessage(cmd: Command): Behavior[Command] = {

      cmd match {

        case Process1(payload, callId, replyTo) =>
          log.info(s"test1: $payload")
          val f = Future {
            log.info("from future 1")
            Thread.sleep(10)
            log.info("from future 2")
            42
          }
          f.onComplete {
            case Success(_) =>
              log.info("from onComplete")
            case Failure(e) => e.printStackTrace()
          }
          replyTo ! Done

        case Process2(payload, replyTo) =>
          log.info(s"test2: $payload")
          replyTo ! Done

      }
      this
    }
  }

}