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-http.git


The following commit(s) were added to refs/heads/main by this push:
     new f4dbeeae6 Use lazy log templates instead of string interpolation 
(#1292)
f4dbeeae6 is described below

commit f4dbeeae6848502c4ac5015ab662a38fd1cfeaea
Author: PJ Fanning <[email protected]>
AuthorDate: Fri Sep 11 09:51:29 2026 +0100

    Use lazy log templates instead of string interpolation (#1292)
    
    Motivation:
    Several main-source log calls built their message with `s"..."`
    interpolation, so the message was rendered even when the level was
    disabled. A few of them also carried redundant `if (log.isXxxEnabled)`
    guards, and one built an interpolated string that already contained
    `{}` placeholders.
    
    Modification:
    Convert eager `s"..."` log messages to `LoggingAdapter` `{}` templates
    with the values passed as arguments, so the message is only rendered
    when the level is enabled. Drop the now-redundant `isDebugEnabled` /
    `isErrorEnabled` guards in FrameOutHandler, Http2Blueprint and
    NewHostConnectionPool. Remove the unnecessary `s` prefix from the
    HttpsProxyGraphStage message, which had no interpolation at all, and
    pass the slot message of NewHostConnectionPool as a template argument
    rather than splicing it into the template. Rendered messages are
    unchanged.
    
    Result:
    No message string is built for a disabled log level, and a slot error
    message containing `{}` can no longer be mistaken for a placeholder.
    
    Tests:
    - sbt "http-core/compile" "http/compile" - success
    - sbt "++3.3.8" "http-core/compile" "http/compile" - success
    - sbt "http-core/testOnly 
org.apache.pekko.http.impl.engine.server.HttpServerSpec 
org.apache.pekko.http.impl.engine.ws.MessageSpec" - 139 passed
    - sbt "http2-tests/testOnly 
org.apache.pekko.http.impl.engine.http2.Http2ServerSpec 
org.apache.pekko.http.impl.engine.http2.Http2ClientSpec" - 174 passed
    - sbt "http-tests/testOnly 
org.apache.pekko.http.scaladsl.unmarshalling.sse.EventStreamParserOversizedSpec"
 - 18 passed
    - sbt "http-core/scalafmt" "http/scalafmt" - no changes
    
    References:
    None - logging cleanup
---
 .../http/impl/engine/client/HttpsProxyGraphStage.scala      |  2 +-
 .../impl/engine/client/pool/NewHostConnectionPool.scala     |  5 ++---
 .../pekko/http/impl/engine/http2/Http2Blueprint.scala       |  8 +++++---
 .../apache/pekko/http/impl/engine/http2/Http2Demux.scala    |  3 ++-
 .../pekko/http/impl/engine/http2/Http2StreamHandling.scala  |  2 +-
 .../impl/engine/rendering/HttpResponseRendererFactory.scala |  4 +++-
 .../pekko/http/impl/engine/server/HttpServerBluePrint.scala |  8 +++++---
 .../pekko/http/impl/engine/server/ServerTerminator.scala    |  4 ++--
 .../apache/pekko/http/impl/engine/ws/FrameOutHandler.scala  | 13 +++++++------
 .../main/scala/org/apache/pekko/http/scaladsl/Http.scala    |  4 ++--
 .../scaladsl/unmarshalling/sse/ServerSentEventParser.scala  | 10 +++++-----
 11 files changed, 35 insertions(+), 28 deletions(-)

diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/HttpsProxyGraphStage.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/HttpsProxyGraphStage.scala
index 45f5c2f17..2c4a040cf 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/HttpsProxyGraphStage.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/HttpsProxyGraphStage.scala
@@ -178,7 +178,7 @@ private final class HttpsProxyGraphStage(
             state match {
               case Starting =>
                 log.debug(
-                  s"TCP connection to HTTP(S) proxy connection established. 
Sending CONNECT {}:{} to HTTP(S) proxy",
+                  "TCP connection to HTTP(S) proxy connection established. 
Sending CONNECT {}:{} to HTTP(S) proxy",
                   targetHostName, targetPort)
                 push(bytesOut, connectMsg)
                 state = Connecting
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/pool/NewHostConnectionPool.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/pool/NewHostConnectionPool.scala
index d125bb244..eda9dff81 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/pool/NewHostConnectionPool.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/client/pool/NewHostConnectionPool.scala
@@ -161,7 +161,7 @@ private[client] object NewHostConnectionPool {
           }
           if (_connectionEmbargo != oldValue) {
             log.debug(
-              s"Connection attempt failed. Backing off new connection attempts 
for at least ${_connectionEmbargo}.")
+              "Connection attempt failed. Backing off new connection attempts 
for at least {}.", _connectionEmbargo)
             slots.foreach(_.onNewConnectionEmbargo(_connectionEmbargo))
           }
         }
@@ -398,8 +398,7 @@ private[client] object NewHostConnectionPool {
           override def prefixString: String = s"[$slotId 
(${state.productPrefix})]"
 
           def error(cause: Throwable, msg: String): Unit =
-            if (log.isErrorEnabled)
-              log.error(cause, s"[{} ({})] $msg", slotId, state.productPrefix)
+            log.error(cause, "[{} ({})] {}", slotId, state.productPrefix, msg)
 
           def settings: ConnectionPoolSettings = _settings
 
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Blueprint.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Blueprint.scala
index 0907bcf6a..33794e00c 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Blueprint.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Blueprint.scala
@@ -193,8 +193,9 @@ private[http] object Http2Blueprint {
       StreamUtils.encodeErrorAndComplete {
         case ex: Http2Compliance.Http2ProtocolException =>
           // protocol errors are most likely provoked by peer, so we don't log 
them noisily
-          if (log.isDebugEnabled) log.debug(
-            s"HTTP2 connection failed with error [${ex.getMessage}]. Sending 
${ex.errorCode} and closing connection.")
+          log.debug(
+            "HTTP2 connection failed with error [{}]. Sending {} and closing 
connection.",
+            ex.getMessage, ex.errorCode)
           FrameRenderer.render(GoAwayFrame(0, ex.errorCode))
         case ex: StreamTcpException       => throw ex // TCP connection is 
probably broken: just forward exception
         case ex: HttpIdleTimeoutException =>
@@ -202,7 +203,8 @@ private[http] object Http2Blueprint {
           throw ex
         case NonFatal(ex) =>
           log.error(
-            s"HTTP2 connection failed with error [${ex.getMessage}]. Sending 
INTERNAL_ERROR and closing connection.")
+            "HTTP2 connection failed with error [{}]. Sending INTERNAL_ERROR 
and closing connection.",
+            ex.getMessage)
           FrameRenderer.render(GoAwayFrame(0, 
Http2Protocol.ErrorCode.INTERNAL_ERROR))
       },
       Flow[ByteString])
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Demux.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Demux.scala
index 9e63961c9..56c0369e7 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Demux.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2Demux.scala
@@ -266,7 +266,8 @@ private[http2] abstract class Http2Demux(http2Settings: 
Http2CommonSettings,
         // check if we are already terminating, otherwise start termination
         if (!terminating) {
           log.debug(
-            s"Termination of this connection was triggered. Sending GOAWAY and 
waiting for open requests to complete for $CompletionTimeout.")
+            "Termination of this connection was triggered. Sending GOAWAY and 
waiting for open requests to complete for {}.",
+            CompletionTimeout)
           terminating = true
           pushGOAWAY(ErrorCode.NO_ERROR, "Voluntary connection close.")
           lastIdBeforeTermination = lastStreamId()
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala
index cd8b89b33..2b304342e 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala
@@ -916,7 +916,7 @@ private[http2] trait Http2StreamHandling extends 
GraphStageLogic with LogHelper
       }
     }
     override def onUpstreamFailure(ex: Throwable): Unit = {
-      log.error(ex, s"Substream $streamId failed with $ex")
+      log.error(ex, "Substream {} failed with {}", streamId, ex)
       multiplexer.pushControlFrame(RstStreamFrame(streamId, 
Http2Protocol.ErrorCode.INTERNAL_ERROR))
       handleOutgoingFailed(streamId, ex)
       cleanupStream()
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/rendering/HttpResponseRendererFactory.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/rendering/HttpResponseRendererFactory.scala
index bf9a8dd0a..3e6d6bec2 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/rendering/HttpResponseRendererFactory.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/rendering/HttpResponseRendererFactory.scala
@@ -76,7 +76,9 @@ private[http] class HttpResponseRendererFactory(
               catch {
                 case NonFatal(e) =>
                   log.error(e,
-                    s"Rendering of response failed because response entity 
stream materialization failed with '${e.getMessage}'. Sending out 500 response 
instead.")
+                    "Rendering of response failed because response entity 
stream materialization failed with '{}'. " +
+                    "Sending out 500 response instead.",
+                    e.getMessage)
                   push(out,
                     render(ResponseRenderingContext(HttpResponse(500,
                       entity = 
StatusCodes.InternalServerError.defaultMessage))).asInstanceOf[Strict].bytes)
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
index 2948ceaed..4c20f5bd1 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
@@ -519,7 +519,8 @@ private[http] object HttpServerBluePrint {
                   fut.onComplete {
                     case Failure(ex) =>
                       log.error(ex,
-                        s"Response stream for [${requestStart.debugString}] 
failed with '${ex.getMessage}'. Aborting connection.")
+                        "Response stream for [{}] failed with '{}'. Aborting 
connection.",
+                        requestStart.debugString, ex.getMessage)
                     case _ => // ignore
                   }(ExecutionContext.parasitic)
                   newEntity
@@ -528,9 +529,10 @@ private[http] object HttpServerBluePrint {
               val isEarlyResponse = messageEndPending && openRequests.isEmpty
               if (isEarlyResponse && response.status.isSuccess)
                 log.warning(
-                  s"Sending an 2xx 'early' response before end of request for 
${requestStart.uri} received... " +
+                  "Sending an 2xx 'early' response before end of request for 
{} received... " +
                   "Note that the connection will be closed after this 
response. Also, many clients will not read early responses! " +
-                  "Consider only issuing this response after the request data 
has been completely read!")
+                  "Consider only issuing this response after the request data 
has been completely read!",
+                  requestStart.uri)
               val forceClose = (requestStart.expect100Continue && 
oneHundredContinueResponsePending) ||
                 (isClosed(requestParsingIn) && openRequests.isEmpty) ||
                 isEarlyResponse
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/ServerTerminator.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/ServerTerminator.scala
index 8db52775e..343918234 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/ServerTerminator.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/ServerTerminator.scala
@@ -139,8 +139,8 @@ private[http] final class MasterServerTerminator(log: 
LoggingAdapter) extends Se
 
       case Terminating(existingDeadline) =>
         log.warning(
-          s"Issued terminate($timeout) while termination is in progress 
already (with deadline: time left: ${PrettyDuration.format(
-              existingDeadline.timeLeft)}")
+          "Issued terminate({}) while termination is in progress already (with 
deadline: time left: {}",
+          timeout, PrettyDuration.format(existingDeadline.timeLeft))
         termination.future
     }
   }
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/ws/FrameOutHandler.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/ws/FrameOutHandler.scala
index 3645afbea..9f58be0f1 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/ws/FrameOutHandler.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/ws/FrameOutHandler.scala
@@ -74,7 +74,7 @@ private[http] class FrameOutHandler(serverSide: Boolean, 
_closeTimeout: FiniteDu
             setHandler(in, new WaitingForPeerCloseFrame())
             push(out, FrameEvent.closeFrame(Protocol.CloseCodes.Regular))
           case UserHandlerErredOut(e) =>
-            log.error(e, s"Websocket handler failed with ${e.getMessage}")
+            log.error(e, "Websocket handler failed with {}", e.getMessage)
             setHandler(in, new WaitingForPeerCloseFrame())
             push(out, 
FrameEvent.closeFrame(Protocol.CloseCodes.UnexpectedCondition, "internal 
error"))
           case Tick => pull(in) // ignore
@@ -94,7 +94,7 @@ private[http] class FrameOutHandler(serverSide: Boolean, 
_closeTimeout: FiniteDu
         grab(in) match {
           case UserHandlerCompleted   => sendOutLastFrame()
           case UserHandlerErredOut(e) =>
-            log.error(e, s"Websocket handler failed while waiting for handler 
completion with ${e.getMessage}")
+            log.error(e, "Websocket handler failed while waiting for handler 
completion with {}", e.getMessage)
             sendOutLastFrame()
           case start: FrameStart => push(out, start)
           case _                 => pull(in) // ignore
@@ -122,8 +122,8 @@ private[http] class FrameOutHandler(serverSide: Boolean, 
_closeTimeout: FiniteDu
         grab(in) match {
           case Tick =>
             if (deadline.isOverdue()) {
-              if (log.isDebugEnabled) log.debug(
-                s"Peer did not acknowledge CLOSE frame after ${_closeTimeout}, 
closing underlying connection now.")
+              log.debug(
+                "Peer did not acknowledge CLOSE frame after {}, closing 
underlying connection now.", _closeTimeout)
               completeStage()
             } else pull(in)
           case PeerClosed(code, reason) =>
@@ -145,8 +145,9 @@ private[http] class FrameOutHandler(serverSide: Boolean, 
_closeTimeout: FiniteDu
         grab(in) match {
           case Tick =>
             if (deadline.isOverdue()) {
-              if (log.isDebugEnabled) log.debug(
-                s"Peer did not close TCP connection after sendind CLOSE frame 
after ${_closeTimeout}, closing underlying connection now.")
+              log.debug(
+                "Peer did not close TCP connection after sendind CLOSE frame 
after {}, closing underlying connection now.",
+                _closeTimeout)
               completeStage()
             } else pull(in)
           case _ => pull(in) // ignore
diff --git a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/Http.scala 
b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/Http.scala
index b79573dc7..e4ef686fb 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/Http.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/Http.scala
@@ -182,7 +182,7 @@ class HttpExt @InternalStableApi /* constructor signature 
is hardcoded in Teleme
       log: LoggingAdapter): Source[Http.IncomingConnection, 
Future[ServerBinding]] = {
     if (settings.enableHttp2)
       log.warning(
-        s"Binding with a connection source not supported with HTTP/2. Falling 
back to HTTP/1.1 for port [$port]")
+        "Binding with a connection source not supported with HTTP/2. Falling 
back to HTTP/1.1 for port [{}]", port)
 
     val fullLayer: ServerLayerBidiFlow = fuseServerBidiFlow(settings, 
connectionContext, log)
 
@@ -223,7 +223,7 @@ class HttpExt @InternalStableApi /* constructor signature 
is hardcoded in Teleme
       log: LoggingAdapter)(implicit fm: Materializer): Future[ServerBinding] = 
{
     if (settings.enableHttp2)
       log.warning(
-        s"Binding with a connection source not supported with HTTP/2. Falling 
back to HTTP/1.1 for port [$port].")
+        "Binding with a connection source not supported with HTTP/2. Falling 
back to HTTP/1.1 for port [{}].", port)
 
     val fullLayer: Flow[ByteString, ByteString, (Future[Done], 
ServerTerminator)] =
       fuseServerFlow(fuseServerBidiFlow(settings, connectionContext, log), 
handler)
diff --git 
a/http/src/main/scala/org/apache/pekko/http/scaladsl/unmarshalling/sse/ServerSentEventParser.scala
 
b/http/src/main/scala/org/apache/pekko/http/scaladsl/unmarshalling/sse/ServerSentEventParser.scala
index 5bce6ee91..c14257744 100644
--- 
a/http/src/main/scala/org/apache/pekko/http/scaladsl/unmarshalling/sse/ServerSentEventParser.scala
+++ 
b/http/src/main/scala/org/apache/pekko/http/scaladsl/unmarshalling/sse/ServerSentEventParser.scala
@@ -144,8 +144,8 @@ private final class ServerSentEventParser(
               builder.appendData(line)
               val event = builder.build()
               log.warning(
-                s"Oversized SSE Event ${event.id.fold("") { id => s"at ID: $id 
" }}" +
-                s"with size: ${builder.size} exceeds max-event-size: 
$maxEventSize.")
+                "Oversized SSE Event {}with size: {} exceeds max-event-size: 
{}.",
+                event.id.fold("") { id => s"at ID: $id " }, builder.size, 
maxEventSize)
               pull(in)
             case OversizedSseStrategy.Truncate =>
               // Because truncating some field types can categorically change 
the meaning of the event or stream
@@ -153,9 +153,9 @@ private final class ServerSentEventParser(
               // as dropping the entire line which would exceed the message 
size length. So throw away `line`.
               val event = builder.build()
               log.info(
-                s"Oversized SSE Event ${event.id.fold("") { id => s"at ID: $id 
" }}" +
-                s"with size: ${builder.size + line.length} exceeds 
max-event-size: $maxEventSize." +
-                s" Truncating event to last completed line at event size: 
${builder.size}.")
+                "Oversized SSE Event {}with size: {} exceeds max-event-size: 
{}." +
+                " Truncating event to last completed line at event size: {}.",
+                event.id.fold("") { id => s"at ID: $id " }, builder.size + 
line.length, maxEventSize, builder.size)
               push(out, event)
             case OversizedSseStrategy.DeadLetter =>
               builder.appendData(line)


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

Reply via email to