mirror of
https://github.com/rsyslog/rsyslog.git
synced 2026-06-19 22:12:56 +02:00
Operators want dynstats to survive restarts for consistent metrics and
smoother observability in containers and rolling deploys.
Before: dynstats buckets were ephemeral; restarts reset counters.
After: optional on-disk persistence restores counters; worker thread is
started on demand and torn down with the owning rsconf.
Impact: New state files under WorkDirectory (or statefile.directory)
when enabled; slight I/O overhead on configured thresholds. Defaults
preserve previous behavior (persistence off).
This adds two thresholds to trigger persistence:
- persistStateInterval (count-based) and persistStateTimeInterval
(time-based), both default 0 (disabled). A new statefile.directory
can override WorkDirectory for dynstats files.
On bucket creation, existing JSON state ("dynstats-state:<bucket>")
is loaded to rehydrate counters. Updates may enqueue async writes to a
lazily-started file-write worker; teardown performs a final sync flush
without holding the bucket lock to avoid I/O-induced deadlocks.
Worker lifecycle is tied to rsconf: init in dynstats_initCnf(),
start on first persistent bucket, stop in dynstats_destroyAllBuckets().
The latter now takes rsconf_t* and is invoked from rsconf destruct,
avoiding prior hangs when loadConf/runConf differed. Per-bucket stats
track flushed bytes/counts/errors; a "file-write-worker" group reports
queue size/enqueues. Docs updated; tests add dynstats-persist(+vg) to
verify restore-after-restart and clean shutdown.
With the help of AI Agents: GitHub Copilot, cubic-dev-ai, ChatGPT codex
Co-authored-by: Rainer Gerhards <rgerhards@adiscon.com>
62 lines
2.2 KiB
Bash
Executable File
62 lines
2.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# This file is part of the rsyslog project, released under ASL 2.0
|
|
|
|
#export RSYSLOG_DEBUG="Debug"
|
|
. ${srcdir:=.}/diag.sh init
|
|
generate_conf
|
|
add_conf '
|
|
global(workDirectory="'${RSYSLOG_DYNNAME}'.spool")
|
|
|
|
ruleset(name="stats") {
|
|
action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log")
|
|
}
|
|
|
|
module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on")
|
|
template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n")
|
|
|
|
dyn_stats(name="msg_stats" resettable="off" persistStateInterval="1" statefile.directory="'${RSYSLOG_DYNNAME}'.spool")
|
|
|
|
set $.msg_prefix = field($msg, 32, 1);
|
|
if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then {
|
|
set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix);
|
|
} else {
|
|
set $.increment_successful = -1;
|
|
}
|
|
action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")
|
|
'
|
|
startup
|
|
wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
|
|
injectmsg_file $srcdir/testsuites/dynstats_input_more_0
|
|
wait_queueempty
|
|
rst_msleep 1100 # wait for stats flush
|
|
echo doing shutdown
|
|
shutdown_when_empty
|
|
echo wait on shutdown
|
|
wait_shutdown
|
|
|
|
custom_content_check 'foo=4' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'corge=1' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'quux=2' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
|
|
# check above counts stats have been persisted.
|
|
ls -l ${RSYSLOG_DYNNAME}.spool
|
|
echo restarting rsyslog
|
|
startup
|
|
echo restarted rsyslog, continuing with test
|
|
injectmsg_file $srcdir/testsuites/dynstats_input_more_2
|
|
wait_queueempty
|
|
wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log
|
|
echo doing shutdown
|
|
shutdown_when_empty
|
|
echo wait on shutdown
|
|
wait_shutdown
|
|
custom_content_check 'foo=5' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'corge=3' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'quux=3' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
custom_content_check 'grault=1' "${RSYSLOG_DYNNAME}.out.stats.log"
|
|
exit_test
|