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

pjfanning 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 b765c5b19c perf: use slf4j placeholders instead of string 
interpolation in logging (#3537)
b765c5b19c is described below

commit b765c5b19cff15a7f05674771d1d3d3304c527fe
Author: PJ Fanning <[email protected]>
AuthorDate: Fri Sep 11 22:04:09 2026 +0100

    perf: use slf4j placeholders instead of string interpolation in logging 
(#3537)
    
    Motivation:
    Several slf4j log calls in main sources built their message with Scala
    string interpolation, so the message was formatted eagerly even when the
    level was disabled. A few others carried an `s` prefix on a literal that
    had no interpolation at all, which is misleading next to the `{}`
    placeholders in the same string.
    
    Modification:
    - Replaced interpolated log messages with slf4j `{}` placeholders and
      lazily formatted arguments in persistence-typed `BehaviorSetup` (both
      the event-sourced and durable-state variants),
      `EventSourcedBehaviorImpl`, and the testkit `LogCapturing` /
      `LogCapturingExtension` rules.
    - Dropped the redundant `s` prefix from log literals that contain no
      interpolation in `Running` and `RequestingRecoveryPermit` (both
      variants).
    - `BehaviorSetup.onSignal` now passes the signal as a placeholder
      argument and keeps the throwable as the trailing slf4j argument, so
      the stack trace is still logged without rendering the exception into
      the message eagerly.
    
    Result:
    Log message rendering is deferred to the logging backend and only
    happens when the level is enabled. Rendered output is unchanged apart
    from `onSignal`, where the exception `toString` is no longer duplicated
    in the message text; it remains available via the logged throwable.
    
    Tests:
    - sbt "actor-testkit-typed/compile" "persistence-typed/compile" - pass
    - scalafmt on changed files - pass
    - No behavior change beyond log formatting; covered by existing
      EventSourcedBehaviorLoggingSpec assertions on "Handled command"
    
    References:
    None - internal logging cleanup
---
 .../org/apache/pekko/actor/testkit/typed/javadsl/LogCapturing.scala | 6 ++++--
 .../pekko/actor/testkit/typed/javadsl/LogCapturingExtension.scala   | 5 ++---
 .../apache/pekko/actor/testkit/typed/scaladsl/LogCapturing.scala    | 4 ++--
 .../org/apache/pekko/persistence/typed/internal/BehaviorSetup.scala | 4 ++--
 .../pekko/persistence/typed/internal/EventSourcedBehaviorImpl.scala | 2 +-
 .../pekko/persistence/typed/internal/RequestingRecoveryPermit.scala | 2 +-
 .../scala/org/apache/pekko/persistence/typed/internal/Running.scala | 4 ++--
 .../pekko/persistence/typed/state/internal/BehaviorSetup.scala      | 4 ++--
 .../persistence/typed/state/internal/RequestingRecoveryPermit.scala | 2 +-
 .../org/apache/pekko/persistence/typed/state/internal/Running.scala | 2 +-
 10 files changed, 18 insertions(+), 17 deletions(-)

diff --git 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturing.scala
 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturing.scala
index 79e4558de7..96f9dc4301 100644
--- 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturing.scala
+++ 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturing.scala
@@ -56,10 +56,12 @@ final class LogCapturing extends TestRule {
     new Statement {
       override def evaluate(): Unit = {
         try {
-          myLogger.info(s"Logging started for test 
[${description.getClassName}: ${description.getMethodName}]")
+          myLogger.info("Logging started for test [{}: {}]", 
description.getClassName, description.getMethodName)
           base.evaluate()
           myLogger.info(
-            s"Logging finished for test [${description.getClassName}: 
${description.getMethodName}] that was successful")
+            "Logging finished for test [{}: {}] that was successful",
+            description.getClassName,
+            description.getMethodName)
         } catch {
           case NonFatal(e) =>
             println(
diff --git 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturingExtension.scala
 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturingExtension.scala
index e90379dd8f..cb86a75502 100644
--- 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturingExtension.scala
+++ 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/javadsl/LogCapturingExtension.scala
@@ -39,10 +39,9 @@ final class LogCapturingExtension extends 
InvocationInterceptor {
     val testMethodName = invocationContext.getExecutable.getName
 
     try {
-      myLogger.info(s"Logging started for test [${testClassName}: 
${testMethodName}]")
+      myLogger.info("Logging started for test [{}: {}]", testClassName, 
testMethodName)
       invocation.proceed
-      myLogger.info(
-        s"Logging finished for test [${testClassName}: ${testMethodName}] that 
was successful")
+      myLogger.info("Logging finished for test [{}: {}] that was successful", 
testClassName, testMethodName)
     } catch {
       case NonFatal(e) =>
         println(
diff --git 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/LogCapturing.scala
 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/LogCapturing.scala
index e8940973ed..b68787c9ac 100644
--- 
a/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/LogCapturing.scala
+++ 
b/actor-testkit-typed/src/main/scala/org/apache/pekko/actor/testkit/typed/scaladsl/LogCapturing.scala
@@ -77,9 +77,9 @@ trait LogCapturing extends BeforeAndAfterAll { self: 
TestSuite =>
   def clearCapturedLogs(): Unit = capturingAppender.clear()
 
   abstract override def withFixture(test: NoArgTest): Outcome = {
-    myLogger.info(s"Logging started for test [${self.getClass.getName}: 
${test.name}]")
+    myLogger.info("Logging started for test [{}: {}]", self.getClass.getName, 
test.name)
     val res = test()
-    myLogger.info(s"Logging finished for test [${self.getClass.getName}: 
${test.name}] that [$res]")
+    myLogger.info("Logging finished for test [{}: {}] that [{}]", 
self.getClass.getName, test.name, res)
 
     if (!(res.isSucceeded || res.isPending)) {
       println(
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/BehaviorSetup.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/BehaviorSetup.scala
index 53564c2607..d687b431c4 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/BehaviorSetup.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/BehaviorSetup.scala
@@ -175,11 +175,11 @@ private[pekko] final class BehaviorSetup[C, E, S](
     } catch {
       case NonFatal(ex) =>
         if (catchAndLog) {
-          internalLogger.error(s"Error while processing signal [$signal]: 
$ex", ex)
+          internalLogger.error("Error while processing signal [{}]", signal, 
ex)
           true
         } else {
           if (internalLogger.isDebugEnabled)
-            internalLogger.debug(s"Error while processing signal [$signal]: 
$ex", ex)
+            internalLogger.debug("Error while processing signal [{}]", signal, 
ex)
           throw ex
         }
     }
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/EventSourcedBehaviorImpl.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/EventSourcedBehaviorImpl.scala
index 494ee17d4a..7204e93b16 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/EventSourcedBehaviorImpl.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/EventSourcedBehaviorImpl.scala
@@ -162,7 +162,7 @@ private[pekko] final case class 
EventSourcedBehaviorImpl[Command, Event, State](
         internalLogger().debug("Save snapshot successful, snapshot metadata 
[{}].", meta)
       case (_, SnapshotFailed(meta, failure)) =>
         internalLogger()
-          .error(s"Save snapshot failed, snapshot metadata [$meta] due to: 
${failure.getMessage}", failure)
+          .error("Save snapshot failed, snapshot metadata [{}] due to: {}", 
meta, failure.getMessage, failure)
       case (_, DeleteSnapshotsCompleted(DeletionTarget.Individual(meta))) =>
         internalLogger().debug("Persistent snapshot [{}] deleted 
successfully.", meta)
       case (_, DeleteSnapshotsCompleted(DeletionTarget.Criteria(criteria))) =>
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/RequestingRecoveryPermit.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/RequestingRecoveryPermit.scala
index 4f00e28cfe..c19fa365b2 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/RequestingRecoveryPermit.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/RequestingRecoveryPermit.scala
@@ -82,7 +82,7 @@ private[pekko] class RequestingRecoveryPermit[C, E, 
S](override val setup: Behav
   def onRequestingRecoveryPermit(@nowarn("msg=never used") context: 
ActorContext[?]): Unit = ()
 
   private def becomeReplaying(receivedPoisonPill: Boolean): 
Behavior[InternalProtocol] = {
-    setup.internalLogger.debug(s"Initializing snapshot recovery: {}", 
setup.recovery)
+    setup.internalLogger.debug("Initializing snapshot recovery: {}", 
setup.recovery)
 
     setup.holdingRecoveryPermit = true
     ReplayingSnapshot(setup, receivedPoisonPill)
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala
index 0b8f4bd342..74b6b4bb49 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/internal/Running.scala
@@ -667,7 +667,7 @@ private[pekko] object Running {
         sideEffects: immutable.Seq[SideEffect[S]] = Nil): 
(Behavior[InternalProtocol], Boolean) = {
       if (setup.internalLogger.isDebugEnabled && 
!effect.isInstanceOf[CompositeEffect[?, ?]])
         setup.internalLogger.debugN(
-          s"Handled command [{}], resulting effect: [{}], side effects: [{}]",
+          "Handled command [{}], resulting effect: [{}], side effects: [{}]",
           msg.getClass.getName,
           effect,
           sideEffects.size)
@@ -919,7 +919,7 @@ private[pekko] object Running {
     def onSaveSnapshotResponse(response: SnapshotProtocol.Response): Unit = {
       val signal = response match {
         case SaveSnapshotSuccess(meta) =>
-          setup.internalLogger.debug(s"Persistent snapshot [{}] saved 
successfully", meta)
+          setup.internalLogger.debug("Persistent snapshot [{}] saved 
successfully", meta)
           if (snapshotReason == SnapshotWithRetention) {
             // deletion of old events and snapshots are triggered by the 
SaveSnapshotSuccess
             setup.retention match {
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/BehaviorSetup.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/BehaviorSetup.scala
index 332bc62e25..c03f9ffe43 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/BehaviorSetup.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/BehaviorSetup.scala
@@ -108,11 +108,11 @@ private[pekko] final class BehaviorSetup[C, S](
     } catch {
       case NonFatal(ex) =>
         if (catchAndLog) {
-          internalLogger.error(s"Error while processing signal [$signal]: 
$ex", ex)
+          internalLogger.error("Error while processing signal [{}]", signal, 
ex)
           true
         } else {
           if (internalLogger.isDebugEnabled)
-            internalLogger.debug(s"Error while processing signal [$signal]: 
$ex", ex)
+            internalLogger.debug("Error while processing signal [{}]", signal, 
ex)
           throw ex
         }
     }
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/RequestingRecoveryPermit.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/RequestingRecoveryPermit.scala
index 3bae69c202..9ec9748c2a 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/RequestingRecoveryPermit.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/RequestingRecoveryPermit.scala
@@ -81,7 +81,7 @@ private[pekko] class RequestingRecoveryPermit[C, S](override 
val setup: Behavior
   def onRequestingRecoveryPermit(@nowarn("msg=never used") context: 
ActorContext[?]): Unit = ()
 
   private def becomeRecovering(receivedPoisonPill: Boolean): 
Behavior[InternalProtocol] = {
-    setup.internalLogger.debug(s"Initializing recovery")
+    setup.internalLogger.debug("Initializing recovery")
 
     setup.holdingRecoveryPermit = true
     Recovering(setup, receivedPoisonPill)
diff --git 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/Running.scala
 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/Running.scala
index 1371ce3515..b4986b7cc2 100644
--- 
a/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/Running.scala
+++ 
b/persistence-typed/src/main/scala/org/apache/pekko/persistence/typed/state/internal/Running.scala
@@ -230,7 +230,7 @@ private[pekko] object Running {
         sideEffects: immutable.Seq[SideEffect[S]] = Nil): 
(Behavior[InternalProtocol], Boolean) = {
       if (setup.internalLogger.isDebugEnabled && 
!effect.isInstanceOf[CompositeEffect[?]])
         setup.internalLogger.debugN(
-          s"Handled command [{}], resulting effect: [{}], side effects: [{}]",
+          "Handled command [{}], resulting effect: [{}], side effects: [{}]",
           msg.getClass.getName,
           effect,
           sideEffects.size)


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

Reply via email to