From 0d055f9fab35e5acac7c9cc32427bed161070d92 Mon Sep 17 00:00:00 2001 From: Daniel Vigovszky Date: Sun, 9 Apr 2023 13:11:40 +0200 Subject: [PATCH] Log a warning in case of fatal errors (#2084) * Log a warning in case of fatal errors * Format --- zio-http/src/main/scala/zio/http/Server.scala | 13 ++++++++++++- .../http/netty/server/ServerInboundHandler.scala | 10 +++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/zio-http/src/main/scala/zio/http/Server.scala b/zio-http/src/main/scala/zio/http/Server.scala index de050ce3a7..0dc7dd41a5 100644 --- a/zio-http/src/main/scala/zio/http/Server.scala +++ b/zio-http/src/main/scala/zio/http/Server.scala @@ -53,6 +53,7 @@ object Server { responseCompression: Option[ResponseCompressionConfig], requestStreaming: RequestStreaming, maxHeaderSize: Int, + logWarningOnFatalError: Boolean, ) { self => @@ -96,6 +97,12 @@ object Server { */ def keepAlive(enable: Boolean): Config = self.copy(keepAlive = enable) + /** + * Log a warning in case of fatal errors when an error response cannot be + * sent back to the client + */ + def logWarningOnFatalError(enable: Boolean): Config = self.copy(logWarningOnFatalError = enable) + /** * Configure the server to use `maxHeaderSize` value when encode/decode * headers. @@ -148,7 +155,8 @@ object Server { Decompression.config.nested("request-decompression").withDefault(Config.default.requestDecompression) ++ ResponseCompressionConfig.config.nested("response-compression").optional ++ RequestStreaming.config.nested("request-streaming").withDefault(Config.default.requestStreaming) ++ - zio.Config.int("max-header-size").withDefault(Config.default.maxHeaderSize) + zio.Config.int("max-header-size").withDefault(Config.default.maxHeaderSize) ++ + zio.Config.boolean("log-warning-on-fatal-error").withDefault(Config.default.logWarningOnFatalError) }.map { case ( sslConfig, @@ -160,6 +168,7 @@ object Server { responseCompression, requestStreaming, maxHeaderSize, + logWarningOnFatalError, ) => Config( sslConfig = sslConfig, @@ -170,6 +179,7 @@ object Server { responseCompression = responseCompression, requestStreaming = requestStreaming, maxHeaderSize = maxHeaderSize, + logWarningOnFatalError = logWarningOnFatalError, ) } @@ -182,6 +192,7 @@ object Server { responseCompression = None, requestStreaming = RequestStreaming.Disabled(1024 * 100), maxHeaderSize = 8192, + logWarningOnFatalError = true, ) final case class ResponseCompressionConfig( diff --git a/zio-http/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala b/zio-http/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala index d388f89fed..b3e518b416 100644 --- a/zio-http/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala +++ b/zio-http/src/main/scala/zio/http/netty/server/ServerInboundHandler.scala @@ -116,7 +116,15 @@ private[zio] final case class ServerInboundHandler( runtime.run(ctx, () => {}) { // We cannot return the generated response from here, but still calling the handler for its side effect // for example logging. - app.runServerErrorOrNull(Cause.die(t)).unit + app + .runServerErrorOrNull(Cause.die(t)) + .tap { response => + if (config.logWarningOnFatalError) + ZIO.logWarningCause(s"Fatal exception in Netty, cannot send error response $response", Cause.die(t)) + else + ZIO.unit + } + .unit } } super.exceptionCaught(ctx, t)