Make it possible to suppress "java.io.IOException: Connection remotely closed for <UUID>"
Describe your motivation
From time to time we get this error:
ERROR 1 --- [sphere-Shared-1] c.v.f.s.c.PushAtmosphereHandler : Exception in push connection
java.io.IOException: Connection remotely closed for ad5663e1-9061-4e0a-9363-63427b513089
at org.atmosphere.websocket.WebSocket.write(WebSocket.java:237) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.websocket.WebSocket.write(WebSocket.java:227) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.websocket.WebSocket.write(WebSocket.java:48) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.cpr.AtmosphereResponseImpl$Stream.write(AtmosphereResponseImpl.java:955) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.handler.AbstractReflectorAtmosphereHandler.onStateChange(AbstractReflectorAtmosphereHandler.java:154) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at com.vaadin.flow.server.communication.PushAtmosphereHandler.onStateChange(PushAtmosphereHandler.java:54) ~[flow-server-24.8.0.jar:24.8.0]
at org.atmosphere.cpr.DefaultBroadcaster.invokeOnStateChange(DefaultBroadcaster.java:1036) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.cpr.DefaultBroadcaster.prepareInvokeOnStateChange(DefaultBroadcaster.java:1056) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.cpr.DefaultBroadcaster.executeAsyncWrite(DefaultBroadcaster.java:870) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at org.atmosphere.cpr.DefaultBroadcaster$2.run(DefaultBroadcaster.java:477) ~[atmosphere-runtime-3.0.5.slf4jvaadin1.jar:3.0.5.slf4jvaadin1]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
It happens especially often when we run integration tests.
The underlying problem here is that the client dies and the push connection then detects this ("Connection remotely closed").
Describe the solution you'd like
We don't care what clients are doing. If a client/connection dies this should definitely not be logged to ERROR. I think DEBUG would be appropriate
Describe alternatives you've considered
Overwriting your non-replaceable PushAtmosphereHandler/AtmosphereResourceListener with our own implementation that suppresses the error
Additional context
The problem has been around for a long time: https://github.com/vaadin/flow/issues/11026
My workaround for years in my application.yml logging configuration:
# Disable 'ERROR: Exception in push connection - Connection remotely closed for ***' when the user closes the browser, presses F5 or auto-logout
com.vaadin.flow.server.communication.PushAtmosphereHandler: OFF
My workaround for years in my application.yml logging configuration:
# Disable 'ERROR: Exception in push connection - Connection remotely closed for ***' when the user closes the browser, presses F5 or auto-logout com.vaadin.flow.server.communication.PushAtmosphereHandler: OFF
Thank you for your input, however we likely can't use this: If a REAL error happens it will NOT be shown and we will never notice it.
Would the linked PR solve this? The Connection remotely closed is very similar to Broken pipe that is logged on debug level elsewhere already
@Artur- Thank you for the PR. I think it's definitely a step into the correct direction!
However this might be localized (AFAIK in German Broken pipe is e.g. translated to Verbindung wurde softwaregesteuert abgebrochen), which means it might have a different name on non-english systems.
So I think providing some kind of handler that the developer could customize would be an even better solution :)
Translated exception messages... oh my
Isn't it typically getLocalizedMessage() that returns the translated message though and getMessage() returns the untranslated one?
Isn't it typically
getLocalizedMessage()that returns the translated message though andgetMessage()returns the untranslated one?
I can remember that I have seen translated messages like these in the past in the logs of apps, so just wanted to hint that here. Anyway... Having a customization option on the dev side would definitely not be harmful and may also help in other situations. So I see no downsides in implementing it (maybe in a separate PR if this requires bigger changes to the code-base).
java.lang.Throwable.getLocalizedMessage() is implemented as return getMessage(); and the method is not overridden in any JDK class.
Intuitively it feels like log filtering should be a feature of the logging framework. Isn't there such a thing?
Intuitively it feels like log filtering should be a feature of the logging framework. Isn't there such a thing?
Yes most logging frameworks have that however I don't think it's the best solution:
- Devs have to configure it manually
- It's likely more efficient to not log the messages in the first place
Devs have to configure it manually
Having a customization option on the dev side would definitely not be harmful and may also help in other situations
Please make up your mind 😄
Devs have to configure it manually
I was referring here to the logging settings like log4j2.xml in the context "if this whole issue can be resolved with the logging framework and would therefore likely not require a PR".
In this case everyone would have to configure their log4j2.xml to suppress exceptions with Connection remotely closed for or something similar if this is somehow different between OS/localization.
Having a customization option on the dev side would definitely not be harmful and may also help in other situations
Having a default behavior that doesn't annoy dev's != Also having the option to customize the behavior or logging of PushAtmosphereHandler#onThrowable
Maybe it's also simpler to just stick to my original proposal of logging everything to DEBUG or maybe call super.onThrowable and let it be logged to TRACE - which is the default behavior of AtmosphereResourceEventListenerAdapter.
Why? Because Pushhandler's handleConnectionLost is called anyway afterwards and also does some conditional logging if something is broken like https://github.com/vaadin/flow/blob/37da9f213c40c004036673d67dafabc6841e1700/flow-server/src/main/java/com/vaadin/flow/server/communication/PushHandler.java#L499-L501
Here is a quick example how I would roughly solve the hole situation: https://github.com/vaadin/flow/compare/main...AB-xdev:flow:21782-demo?expand=1
This ticket/PR has been released with Vaadin 24.7.13.
This ticket/PR has been released with Vaadin 24.9.0-beta1.
@caalador Can this change also be back-ported into Vaadin 23 for Vaadin prime customers?
This ticket/PR has been released with Vaadin 23.6.3.
This ticket/PR has been released with Vaadin 25.0.0-alpha8.
This ticket/PR has been released with Vaadin 24.8.8.