Skip to content

Commit e671fc2

Browse files
committed
refactor(journald-usage): also print SystemMaxUse and SystemKeepFree
1 parent 220c8e7 commit e671fc2

File tree

4 files changed

+64
-23
lines changed

4 files changed

+64
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Icinga Director:
4343

4444
Monitoring Plugins:
4545

46+
* journald-usage: also print SystemMaxUse and SystemKeepFree
4647
* pip-updates: modernize code
4748
* rocketchat-stats: improve output and docs a little bit
4849
* statuspal: 'performance' degredation is now a WARN, not UNKNOWN

check-plugins/journald-usage/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ options:
6666
Output:
6767

6868
```text
69-
3.0GiB used [WARNING] (sum of all archived and active journal files). Remove the oldest archived journal files by using `journalctl --vacuum-size=`, `--vacuum-time=` and/or `--vacuum-files=`.
69+
3.0GiB used [WARNING] (sum of all archived and active journal files; SystemMaxUse=595M SystemKeepFree=1388M).
70+
Configure `SystemMaxUse` and `SystemKeepFree` in `/etc/systemd/journald.conf/`, or remove the oldest archived
71+
journal files by using `journalctl --vacuum-size=`, `--vacuum-time=` and/or `--vacuum-files=`.
7072
```
7173

7274

check-plugins/journald-usage/journald-usage

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@ import lib.base # pylint: disable=C0413
1919
import lib.human # pylint: disable=C0413
2020
import lib.shell # pylint: disable=C0413
2121
import lib.lftest # pylint: disable=C0413
22-
from lib.globals import (STATE_OK, STATE_UNKNOWN, # pylint: disable=C0413
23-
STATE_WARN)
22+
import lib.txt # pylint: disable=C0413
23+
from lib.globals import (STATE_OK, STATE_UNKNOWN)
2424

2525
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
26-
__version__ = '2025021501'
26+
__version__ = '2025071701'
2727

2828
DESCRIPTION = """Checks the current disk usage of all journal files of the systemd journal
2929
(in fact the sum of the disk usage of all archived and active journal files)."""
3030

3131
DEFAULT_WARN = 6 # GiB; journald: "capped to 4G" per default
32+
SYSTEMD_DEFAULT_MAX_USE = '4G'
33+
SYSTEMD_DEFAULT_KEEP_FREE = '1M'
3234

3335

3436
def parse_args():
@@ -39,7 +41,7 @@ def parse_args():
3941
parser.add_argument(
4042
'-V', '--version',
4143
action='version',
42-
version='%(prog)s: v{} by {}'.format(__version__, __author__)
44+
version=f'%(prog)s: v{__version__} by {__author__}'
4345
)
4446

4547
parser.add_argument(
@@ -59,7 +61,8 @@ def parse_args():
5961

6062
parser.add_argument(
6163
'-w', '--warning',
62-
help='Set the WARN threshold in GiB. Default: >= %(default)s',
64+
help='Set the WARN threshold in GiB. '
65+
'Default: >= %(default)s',
6366
dest='WARN',
6467
type=int,
6568
default=DEFAULT_WARN,
@@ -68,6 +71,27 @@ def parse_args():
6871
return parser.parse_args()
6972

7073

74+
def extract_config(output):
75+
"""
76+
Extracts the last occurrences of SystemMaxUse and SystemKeepFree.
77+
Returns a tuple: (SystemMaxUse_value, SystemKeepFree_value).
78+
"""
79+
max_use = None
80+
keep_free = None
81+
for line in reversed(output.splitlines()):
82+
if max_use is None and line.startswith('SystemMaxUse='):
83+
max_use = line.split('=', 1)[1].strip()
84+
if keep_free is None and line.startswith('SystemKeepFree='):
85+
keep_free = line.split('=', 1)[1].strip()
86+
if max_use is not None and keep_free is not None:
87+
break
88+
if max_use is None:
89+
max_use = SYSTEMD_DEFAULT_MAX_USE
90+
if keep_free is None:
91+
keep_free = SYSTEMD_DEFAULT_KEEP_FREE
92+
return max_use, keep_free
93+
94+
7195
def main():
7296
"""The main function. Hier spielt die Musik.
7397
"""
@@ -81,12 +105,20 @@ def main():
81105
# fetch data
82106
if args.TEST is None:
83107
cmd = 'journalctl --disk-usage'
84-
stdout, stderr, retc = lib.base.coe(lib.shell.shell_exec(cmd)) # pylint: disable=W0612
108+
stdout, stderr, _ = lib.base.coe(lib.shell.shell_exec(cmd)) # pylint: disable=W0612
85109
if stderr:
86110
lib.base.cu(stderr)
111+
112+
# get journald's thresholds
113+
cmd = 'systemd-analyze cat-config systemd/journald.conf'
114+
config, stderr, _ = lib.base.coe(lib.shell.shell_exec(cmd)) # pylint: disable=W0612
115+
if stderr:
116+
lib.base.cu(stderr)
117+
max_use, keep_free = extract_config(config)
87118
else:
88119
# do not call the command, put in test data
89-
stdout, stderr, retc = lib.lftest.test(args.TEST)
120+
stdout, stderr, _ = lib.lftest.test(args.TEST)
121+
max_use, keep_free = SYSTEMD_DEFAULT_MAX_USE, SYSTEMD_DEFAULT_KEEP_FREE
90122

91123
# init some vars
92124
msg = ''
@@ -96,22 +128,28 @@ def main():
96128
# Archived and active journals take up %s on disk.\n
97129
# Archived and active journals take up %s in the file system.\n
98130
# Journals take up %s on disk.\n
99-
# currently no need for re module, let's do simple string matching
100-
pos1 = stdout.find(' take up ') + len(' take up ')
101-
pos2 = stdout.find(' ', pos1)
102-
value = stdout[pos1:pos2]
131+
value = lib.txt.extract_str(stdout, ' take up ', ' ', include_fromto=False, be_tolerant=False)
103132
value = lib.human.human2bytes(value)
104133

105134
# build the message
106135
state = lib.base.get_state(value, args.WARN * 1024 * 1024 * 1024, None)
107-
msg += '{} used{} (sum of all archived and active journal files)'.format(
108-
lib.human.bytes2human(value),
109-
lib.base.state2str(state, prefix=' '),
110-
)
136+
msg += f'{lib.human.bytes2human(value)} used{lib.base.state2str(state, prefix=" ")} ' \
137+
'(sum of all archived and active journal files; ' \
138+
f'SystemMaxUse={max_use} SystemKeepFree={keep_free})'
111139
if state != STATE_OK:
112-
msg += '. Remove the oldest archived journal files by using `journalctl --vacuum-size=`, ' \
113-
'`--vacuum-time=` and/or `--vacuum-files=`.'
114-
perfdata += lib.base.get_perfdata('journald-usage', value, 'B', args.WARN * 1024 * 1024 * 1024, None, 0, None)
140+
msg += '. Configure `SystemMaxUse` and `SystemKeepFree` in ' \
141+
'`/etc/systemd/journald.conf/`, ' \
142+
'or remove the oldest archived journal files by using ' \
143+
'`journalctl --vacuum-size=`, `--vacuum-time=` and/or `--vacuum-files=`.'
144+
perfdata += lib.base.get_perfdata(
145+
'journald-usage',
146+
value,
147+
uom='B',
148+
warn=args.WARN * 1024 * 1024 * 1024,
149+
crit=None,
150+
_min=0,
151+
_max=None,
152+
)
115153

116154
# over and out
117155
lib.base.oao(msg, state, perfdata, always_ok=args.ALWAYS_OK)

check-plugins/journald-usage/unit-test/run

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,25 @@ class TestCheck(unittest.TestCase):
3030

3131
def test_if_check_runs_EXAMPLE01(self):
3232
stdout, stderr, retc = lib.base.coe(lib.shell.shell_exec(self.check + ' --test=stdout/EXAMPLE01,,0'))
33-
self.assertIn('7.0GiB used [WARNING] (sum of all archived and active journal files)', stdout)
33+
self.assertIn('7.0GiB used [WARNING] (sum of all archived and active journal files; SystemMaxUse=4G SystemKeepFree=1M)', stdout)
3434
self.assertEqual(stderr, '')
3535
self.assertEqual(retc, STATE_WARN)
3636

3737
def test_if_check_runs_EXAMPLE02(self):
3838
stdout, stderr, retc = lib.base.coe(lib.shell.shell_exec(self.check + ' --test=stdout/EXAMPLE02,,0'))
39-
self.assertIn('3.2KiB used (sum of all archived and active journal files)', stdout)
39+
self.assertIn('3.2KiB used (sum of all archived and active journal files; SystemMaxUse=4G SystemKeepFree=1M)', stdout)
4040
self.assertEqual(stderr, '')
4141
self.assertEqual(retc, STATE_OK)
4242

4343
def test_if_check_runs_EXAMPLE03(self):
4444
stdout, stderr, retc = lib.base.coe(lib.shell.shell_exec(self.check + ' --test=stdout/EXAMPLE03,,0'))
45-
self.assertIn('26.6MiB used (sum of all archived and active journal files)', stdout)
45+
self.assertIn('26.6MiB used (sum of all archived and active journal files; SystemMaxUse=4G SystemKeepFree=1M)', stdout)
4646
self.assertEqual(stderr, '')
4747
self.assertEqual(retc, STATE_OK)
4848

4949
def test_if_check_runs_EXAMPLE04(self):
5050
stdout, stderr, retc = lib.base.coe(lib.shell.shell_exec(self.check + ' --test=stdout/EXAMPLE04,,0'))
51-
self.assertIn('0.0B used (sum of all archived and active journal files)', stdout)
51+
self.assertIn('0.0B used (sum of all archived and active journal files; SystemMaxUse=4G SystemKeepFree=1M)', stdout)
5252
self.assertEqual(stderr, '')
5353
self.assertEqual(retc, STATE_OK)
5454

0 commit comments

Comments
 (0)