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]