diff --git a/src/FileServer.jl b/src/FileServer.jl index 49010c5..cad5d86 100644 --- a/src/FileServer.jl +++ b/src/FileServer.jl @@ -22,6 +22,24 @@ include("server.jl") # registers routes (references CONFIG/QUEUE at call time) export run +# When stderr is a live terminal Julia flushes each write, but when it's +# redirected to a file or pipe (a log file, `tee`, journald, a container log +# driver) Julia block-buffers it — so a long-running server's logs sit unseen in +# the buffer until it fills or the process exits, making it look like nothing is +# happening. This wrapper delegates to a normal logger and flushes after every +# message so output appears immediately wherever stderr is pointed. +struct FlushLogger{L<:AbstractLogger} <: AbstractLogger + inner::L +end +Logging.min_enabled_level(f::FlushLogger) = Logging.min_enabled_level(f.inner) +Logging.shouldlog(f::FlushLogger, args...) = Logging.shouldlog(f.inner, args...) +Logging.catch_exceptions(f::FlushLogger) = Logging.catch_exceptions(f.inner) +function Logging.handle_message(f::FlushLogger, args...; kwargs...) + Logging.handle_message(f.inner, args...; kwargs...) + flush(f.inner.stream) + return nothing +end + """ run(; overrides...) @@ -38,6 +56,10 @@ function run(; overrides...) # us drain the queue gracefully below. Base.exit_on_sigint(false) + # Flush every log message so output is visible in real time even when stderr + # is redirected to a file/pipe (see FlushLogger). Set before anything logs. + global_logger(FlushLogger(ConsoleLogger(stderr))) + cfg = config_from_env(; overrides...) ensure_dirs(cfg)