Flush logs so server output is visible under redirection

Julia block-buffers stderr when it isn't a TTY, so a long-running
server's logs stayed trapped in the buffer until exit whenever output
was redirected to a file/pipe (log file, tee, journald, container log
driver). This made it look like workers never ran, when in fact the
"received file" lines were only being flushed at shutdown.

Install a FlushLogger wrapper as the global logger in run(), flushing
after every message so app logs, Oxygen request logs, and startup lines
all appear in real time regardless of where stderr points.
This commit is contained in:
2026-07-02 12:24:35 -04:00
parent 9a02445edb
commit 6d685cfcbb

View File

@@ -22,6 +22,24 @@ include("server.jl") # registers routes (references CONFIG/QUEUE at call time)
export run 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...) run(; overrides...)
@@ -38,6 +56,10 @@ function run(; overrides...)
# us drain the queue gracefully below. # us drain the queue gracefully below.
Base.exit_on_sigint(false) 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...) cfg = config_from_env(; overrides...)
ensure_dirs(cfg) ensure_dirs(cfg)