Class EarlyLogCapture
UltiTools#onLoad() and the moment the panel's log
stream starts (LogStreamManager#initialize), so they reach the panel too (#487).
Before 6.3.0 the stream's capture was attached inside initialize(), which runs only once
the panel connection is open, so everything the server logged before it -- module loading,
dependency resolution, the framework's own start-up diagnostics -- never reached the panel. This
handler is attached to the java.util.logging root logger in onLoad(); when the
stream starts, drainInto(java.util.logging.Handler, java.lang.Runnable) replays what it kept, oldest first, attaches the live handler,
and detaches itself. LogStreamManager replays into the stream handler's replay path, so
the transmitter delivers the early records in log_batch messages of at most 64 KiB, about
one per second, whatever the live batch settings (as of 6.3.0); a live record can therefore arrive
before the last early messages.
The buffer is bounded three ways, so a server that never connects to the panel cannot grow it:
by record count, by an estimate of the bytes it holds, and by time -- after
RELEASE_AFTER_MS without the stream starting it detaches itself and keeps nothing. A
record past the count or byte bound is not kept and is counted; drainInto(java.util.logging.Handler, java.lang.Runnable) returns the
count. It applies the live stream's default filters as records arrive (level INFO and
above, the configured excluded-loggers), so it never holds a record the stream would not
send; the live handler applies the current configuration again when the records are replayed.
- Since:
- 6.3.0
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static EarlyLogCaptureThe capture attached to the root logger, ornull.private longprivate final LongSupplierprivate final longprivate booleanprivate intprivate static final Object(package private) static final longMost bytes kept, estimated from each record's message, logger name and exception.(package private) static final intMost records kept.private final longprivate final intstatic final longHow long the capture waits for the stream to start before it releases what it holds.private static final intCharged per record carrying an exception, whose stack trace the stream will render. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprivateEarlyLogCapture(Collection<String> excludedLoggers, int maxRecords, long maxBytes, long releaseAfterMs, LongSupplier clock) -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()private static voidstatic intReplays every record the capture kept tolive, oldest first, then runsattachLive(which attaches the live handler to the root logger) and detaches the capture.private static longestimateBytes(LogRecord record) private booleanexpired()voidflush()private booleanisExcluded(String loggerName) voidstatic voidrelease()Detaches the capture and discards what it holds -- when the stream cannot start (thelogscapability is off, or the framework is disabling) or its time is up.static voidReleases the capture if the stream did not start withinRELEASE_AFTER_MS.static voidstart(Collection<String> excludedLoggers) Attaches the capture to the root logger, replacing one already attached, whatever the logs capability says;UltiTools#onLoad()goes throughstartIfLogsEnabled(java.util.Collection<java.lang.String>).(package private) static voidstart(Collection<String> excludedLoggers, int maxRecords, long maxBytes, long releaseAfterMs, LongSupplier clock) static booleanstartIfLogsEnabled(Collection<String> excludedLoggers) Attaches the capture only when the panel receives the log stream: withultipanel.capabilities.logs: falsenothing is collected, as a disabled capability prevents collection rather than collecting and discarding (D-12).takeAll()Methods inherited from class java.util.logging.Handler
getEncoding, getErrorManager, getFilter, getFormatter, getLevel, isLoggable, reportError, setEncoding, setErrorManager, setFilter, setFormatter, setLevel
-
Field Details
-
MAX_RECORDS
static final int MAX_RECORDSMost records kept.- See Also:
-
MAX_BYTES
static final long MAX_BYTESMost bytes kept, estimated from each record's message, logger name and exception.- See Also:
-
RELEASE_AFTER_MS
public static final long RELEASE_AFTER_MSHow long the capture waits for the stream to start before it releases what it holds. -
THROWN_ESTIMATE_BYTES
private static final int THROWN_ESTIMATE_BYTESCharged per record carrying an exception, whose stack trace the stream will render.- See Also:
-
LOCK
-
active
The capture attached to the root logger, ornull. Guarded byLOCK. -
records
-
excludedLoggers
-
maxRecords
private final int maxRecords -
maxBytes
private final long maxBytes -
deadline
private final long deadline -
clock
-
bytes
private long bytes -
dropped
private int dropped -
draining
private boolean draining
-
-
Constructor Details
-
EarlyLogCapture
private EarlyLogCapture(Collection<String> excludedLoggers, int maxRecords, long maxBytes, long releaseAfterMs, LongSupplier clock)
-
-
Method Details
-
start
Attaches the capture to the root logger, replacing one already attached, whatever the logs capability says;UltiTools#onLoad()goes throughstartIfLogsEnabled(java.util.Collection<java.lang.String>).- Parameters:
excludedLoggers- the configuredultipanel.logging.excluded-loggers, applied as records arrive
-
startIfLogsEnabled
Attaches the capture only when the panel receives the log stream: withultipanel.capabilities.logs: falsenothing is collected, as a disabled capability prevents collection rather than collecting and discarding (D-12). Called fromUltiTools#onLoad(), after the plugin instance is set, so the configured value is read.- Parameters:
excludedLoggers- the configuredultipanel.logging.excluded-loggers, applied as records arrive- Returns:
- whether the capture was attached
-
start
static void start(Collection<String> excludedLoggers, int maxRecords, long maxBytes, long releaseAfterMs, LongSupplier clock) -
drainInto
Replays every record the capture kept tolive, oldest first, then runsattachLive(which attaches the live handler to the root logger) and detaches the capture. Records logged while the replay runs are kept and replayed too, before the live handler is attached. When no capture is attached -- a reconnect after the first stream, or a capture already released -- this only runsattachLive.- Parameters:
live- the live stream's handlerattachLive- attachesliveto the root logger- Returns:
- how many records the capture could not keep because a bound was reached
-
release
public static void release()Detaches the capture and discards what it holds -- when the stream cannot start (thelogscapability is off, or the framework is disabling) or its time is up. -
releaseIfExpired
public static void releaseIfExpired()Releases the capture if the stream did not start withinRELEASE_AFTER_MS. Scheduled once fromUltiTools#onEnable()so a quiet server does not wait for its next log line. -
detachActive
private static void detachActive() -
publish
-
expired
private boolean expired() -
isExcluded
-
takeAll
-
estimateBytes
-
flush
public void flush() -
close
public void close()
-