This is an automated email from the ASF dual-hosted git repository.

He-Pin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git


The following commit(s) were added to refs/heads/main by this push:
     new 4d821bbce9 fix: include sourceThread in typed actor MDC (#3239) (#3357)
4d821bbce9 is described below

commit 4d821bbce953c55deefa3344399f5b13632c8b2d
Author: He-Pin(kerr) <[email protected]>
AuthorDate: Fri Jul 17 11:10:57 2026 +0800

    fix: include sourceThread in typed actor MDC (#3239) (#3357)
    
    Motivation:
    The MDC setup for typed actors (ActorMdc.setMdc) populated pekkoSource,
    sourceActorSystem, pekkoAddress and pekkoTags, but not sourceThread. Classic
    actors set sourceThread via Slf4jLogger, and the typed logging documentation
    already lists sourceThread as an available MDC attribute, so typed actor log
    entries could not be correlated with the dispatching thread.
    
    Modification:
    Add a sourceThread MDC entry in ActorMdc.setMdc, set to the current thread 
name.
    Typed actors log synchronously on the dispatcher thread that runs the 
actor, so
    the current thread is the source thread on which the user's log statements
    execute. Updated the existing MDC whitelist assertion in ActorLoggingSpec to
    allow the new key and added a regression test asserting sourceThread is 
present.
    
    Result:
    Typed actor log entries now include sourceThread, consistent with classic 
actors
    and the existing documentation.
    
    Tests:
    - sbt "actor-typed-tests/testOnly 
org.apache.pekko.actor.typed.scaladsl.ActorLoggingSpec" -> 20 passed
    - Verified the new test fails before the fix (no sourceThread in typed MDC)
    
    References:
    Fixes #3239
---
 .../pekko/actor/typed/scaladsl/ActorLoggingSpec.scala  | 18 +++++++++++++++++-
 .../apache/pekko/actor/typed/internal/ActorMdc.scala   |  6 ++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git 
a/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/scaladsl/ActorLoggingSpec.scala
 
b/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/scaladsl/ActorLoggingSpec.scala
index b8c7d9792d..7437e6464e 100644
--- 
a/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/scaladsl/ActorLoggingSpec.scala
+++ 
b/actor-typed-tests/src/test/scala/org/apache/pekko/actor/typed/scaladsl/ActorLoggingSpec.scala
@@ -362,7 +362,8 @@ class ActorLoggingSpec extends ScalaTestWithActorTestKit("""
         // not counting for example "pekkoSource", but it shouldn't have any 
other entries
         .withCustom(logEvent =>
           logEvent.mdc.keysIterator.forall(entry =>
-            entry.startsWith("pekko") || entry == "sourceActorSystem" || entry 
== "static") &&
+            entry.startsWith("pekko") || entry == "sourceActorSystem" || entry 
== ActorMdc.SourceThreadKey ||
+            entry == "static") &&
           logEvent.mdc("static") == "1")
         .expect {
           spawn(behaviors)
@@ -383,6 +384,21 @@ class ActorLoggingSpec extends 
ScalaTestWithActorTestKit("""
         }
     }
 
+    // Regression test for https://github.com/apache/pekko/issues/3239: typed 
actor MDC must include
+    // the "sourceThread" attribute (the dispatching thread), consistent with 
classic actors.
+    "include the sourceThread attribute in the MDC" in {
+      val behavior = Behaviors.setup[String] { context =>
+        context.log.info("with-source-thread")
+        Behaviors.empty
+      }
+      LoggingTestKit
+        .info("with-source-thread")
+        .withCustom(event => 
event.mdc.get(ActorMdc.SourceThreadKey).contains(event.threadName))
+        .expect {
+          spawn(behavior)
+        }
+    }
+
     "use the outermost initial mdc" in {
       // when we declare it, we expect the outermost to win
       val behavior =
diff --git 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/ActorMdc.scala
 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/ActorMdc.scala
index 0b9b68cff8..20e7d2977b 100644
--- 
a/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/ActorMdc.scala
+++ 
b/actor-typed/src/main/scala/org/apache/pekko/actor/typed/internal/ActorMdc.scala
@@ -25,6 +25,9 @@ import org.slf4j.MDC
   val PekkoSourceKey = "pekkoSource"
   val PekkoTagsKey = "pekkoTags"
   val PekkoAddressKey = "pekkoAddress"
+  // Mirrors the classic Slf4jLogger MDC attribute 
(Slf4jLogger.mdcThreadAttributeName) so that
+  // typed and classic actor log entries can both be correlated with the 
dispatching thread.
+  val SourceThreadKey = "sourceThread"
 
   def setMdc(context: ActorContextImpl.LoggingContext): Unit = {
     // avoid access to MDC ThreadLocal if not needed, see details in 
LoggingContext
@@ -32,6 +35,9 @@ import org.slf4j.MDC
     MDC.put(PekkoSourceKey, context.pekkoSource)
     MDC.put(SourceActorSystemKey, context.sourceActorSystem)
     MDC.put(PekkoAddressKey, context.pekkoAddress)
+    // Typed actors log synchronously on the dispatcher thread that runs the 
actor, so the current
+    // thread is the source thread the user's log statements execute on.
+    MDC.put(SourceThreadKey, Thread.currentThread().getName)
     // empty string for no tags, a single tag or a comma separated list of tags
     if (context.tagsString.nonEmpty)
       MDC.put(PekkoTagsKey, context.tagsString)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to