Skip to content

Commit

Permalink
Implement option to output information as OpenMetrics time series
Browse files Browse the repository at this point in the history
This new `-o` option will make needrestart output information in a
format that can be scraped by Prometheus or any other daemon that
ingests OpenMetrics format.

The -l, -w and -k options can be used in combination with -o in order to
choose what information gets exported.

(Closes: #291)
  • Loading branch information
Gabriel Filion committed Jul 30, 2024
1 parent 94795e5 commit ceb980b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
5 changes: 4 additions & 1 deletion man/needrestart.1
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ needrestart checks which daemons need to be restarted after library upgrades.
.SH USAGE
Usage:
.IP
needrestart [\-(v|q)] [\-n] [\-c <cfg>] [\-r <mode>] [\-f <fe>] [\-u <ui>] [\-(b|p)] [\-kl]
needrestart [\-(v|q)] [\-n] [\-c <cfg>] [\-r <mode>] [\-f <fe>] [\-u <ui>] [\-(b|p|o)] [\-kl]
.TP
\fB\-v\fR
be more verbose
Expand Down Expand Up @@ -49,6 +49,9 @@ enable batch mode
\fB\-p\fR
nagios plugin mode: makes output and exit codes nagios compatible
.TP
\fB\-o\fR
OpenMetrics output mode: output information that can be scraped by OpenMetrics-compatible services. Implies batch mode.
.TP
\fB\-f\fR <fe>
override debconf(7) frontend, sets the DEBIAN_FRONTEND environment variable to <fe>
.TP
Expand Down
63 changes: 54 additions & 9 deletions needrestart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ sub HELP_MESSAGE {
print <<USG;
Usage:
needrestart [-vn] [-c <cfg>] [-r <mode>] [-f <fe>] [-u <ui>] [-bkl]
needrestart [-vn] [-c <cfg>] [-r <mode>] [-f <fe>] [-u <ui>] [-(b|p|o)] [-klw]
-v be more verbose
-q be quiet
Expand All @@ -99,6 +99,7 @@ Usage:
a (a)utomatically restart
-b enable batch mode
-p enable nagios plugin mode
-o enable OpenMetrics output mode, implies batch mode, cannot be used simultaneously with -p
-f <fe> override debconf frontend (DEBIAN_FRONTEND, debconf(7))
-t <seconds> tolerate interpreter process start times within this value
-u <ui> use preferred UI package (-u ? shows available packages)
Expand Down Expand Up @@ -183,11 +184,12 @@ our $opt_f;
our $opt_k;
our $opt_l;
our $opt_p;
our $opt_o;
our $opt_q;
our $opt_t;
our $opt_u;
our $opt_w;
unless(getopts('c:vr:nm:bf:klpqt:u:w')) {
unless(getopts('c:vr:nm:bf:klpoqt:u:w')) {
HELP_MESSAGE;
exit 1;
}
Expand Down Expand Up @@ -240,7 +242,8 @@ $opt_r = 'l' if($opt_m eq 'e');
$opt_t = $nrconf{tolerance} unless(defined($opt_t));

$nrconf{defno}++ if($opt_n);
$opt_b++ if($opt_p);
die "Options -p and -o cannot be defined simultaneously\n" if ($opt_p && $opt_o);
$opt_b++ if($opt_p || $opt_o);

needrestart_interp_configure({
perl => {
Expand Down Expand Up @@ -456,7 +459,13 @@ my %nagios = (
uret => 3,
uperf => q(U),
);
print "NEEDRESTART-VER: $NeedRestart::VERSION\n" if($opt_b && !$opt_p);
print "NEEDRESTART-VER: $NeedRestart::VERSION\n" if($opt_b && !$opt_p && !$opt_o);

my %ometric_kernel_values = (
kstatus => q(unknown),
krunning => q(unknown),
kexpected => q(unknown),
);

my %restart;
my %sessions;
Expand Down Expand Up @@ -866,12 +875,12 @@ if(defined($opt_k)) {

if(defined($kresult)) {
if($opt_b) {
unless($opt_p) {
unless($opt_p || $opt_o) {
print "NEEDRESTART-KCUR: $kvars{KVERSION}\n";
print "NEEDRESTART-KEXP: $kvars{EVERSION}\n" if(defined($kvars{EVERSION}));
print "NEEDRESTART-KSTA: $kresult\n";
}
else {
elsif ($opt_p) {
$nagios{kstr} = $kvars{KVERSION};
if($kresult == NRK_VERUPGRADE) {
$nagios{kstr} .= "!=$kvars{EVERSION}";
Expand All @@ -894,6 +903,11 @@ if(defined($opt_k)) {
$nagios{kstr} .= " (!!)";
}
}
elsif ($opt_o) {
$ometric_kernel_values{kstatus} = ($kresult != NRK_NOUPGRADE ? "outdated" : "current");
$ometric_kernel_values{krunning} = $kvars{KVERSION};
$ometric_kernel_values{kexpected} = $kvars{EVERSION};
}
}
else {
if($kresult == NRK_NOUPGRADE) {
Expand Down Expand Up @@ -941,7 +955,7 @@ if(defined($opt_k)) {

if($opt_w) {
if($opt_b) {
unless($opt_p) {
unless($opt_p || $opt_o) {
print "NEEDRESTART-UCSTA: $ucode_result\n";
if($ucode_result != NRM_UNKNOWN) {
print "NEEDRESTART-UCCUR: $ucode_vars{CURRENT}\n";
Expand Down Expand Up @@ -1030,7 +1044,7 @@ if(defined($opt_l) && !$uid) {
local $nrconf{systemctl_combine} = 1 unless($opt_r eq 'l');

if($opt_b) {
print "NEEDRESTART-SVC: $rc\n" unless($opt_p);
print "NEEDRESTART-SVC: $rc\n" unless($opt_p || $opt_o);
next;
}

Expand Down Expand Up @@ -1205,7 +1219,7 @@ if(defined($opt_l) && !$uid) {

foreach my $cont (sort { lc($a) cmp lc($b) } keys %conts) {
if($opt_b) {
print "NEEDRESTART-CONT: $cont\n" unless($opt_p);
print "NEEDRESTART-CONT: $cont\n" unless($opt_p || $opt_o);
next;
}

Expand Down Expand Up @@ -1397,6 +1411,37 @@ if($opt_p) {

exit $ret;
}
if ($opt_o) {
print "# HELP needrestart_build_info information about needrestart's runtime build\n";
print "# TYPE needrestart_build_info info\n";
print "needrestart_build_info{version=$NeedRestart::VERSION,perl_version=$^V} 1\n";

my $ometric_now = time();
print "# HELP needrestart_timestamp when, in unix timestamp, needrestart was last updated\n";
print "# TYPE needrestart_timestamp gauge\n";
print "needrestart_timestamp $ometric_now\n";

if ($opt_k) {
print "# HELP needrestart_kernel_info information about the kernel\n";
print "# TYPE needrestart_kernel_info info\n";
print "needrestart_kernel_info{running=$ometric_kernel_values{krunning},expected=$ometric_kernel_values{kexpected}} $ometric_kernel_values{kstatus}\n";
}
if ($opt_w) {
my $ometric_ucode_current = $ucode_result != NRM_UNKNOWN ? $ucode_vars{CURRENT} : "unknown";
my $ometric_ucode_expected = $ucode_result != NRM_UNKNOWN ? $ucode_vars{AVAIL} : "unknown";
my $ometric_ucode_status = ("unknown", "current", "obsolete")[$ucode_result];
print "# HELP needrestart_ucode_info information about the CPU microcode\n";
print "# TYPE needrestart_ucode_info info\n";
print "needrestart_ucode_info{running=$ometric_ucode_current,expected=$ometric_ucode_expected} $ometric_ucode_status\n";
}
if ($opt_l) {
my $ometric_num_services = scalar %restart;
print "# HELP needrestart_services_count number of services requiring a restart\n";
print "# TYPE needrestart_services_count gauge\n";
print "needrestart_services_count $ometric_num_services\n";
}
exit 0;
}

if ($opt_b and scalar %sessions) {
for my $sess (@sessions_list) {
Expand Down

0 comments on commit ceb980b

Please sign in to comment.