[RADIATOR] Promethues Metrics Exporter/Conflicts with Forks
Kelsey Cummings
kelsey.cummings at sonic.com
Sat Jul 10 01:00:33 UTC 2021
It sure would be nice if Radiator used IPC::Sharable or other similar
method to have shared stats structures across the forks so none of this
was necessary but here's my workaround. Thankfully it is possible, this
seemed like a better option that trying to do similar tricks with other
stats exporters. (And now I can get back to triggering alerts based on
per-client counters.)
TLDR; close/reactive management server port incrementing per fork, use
standalone http server to combine stats for each fork naively
incrementing from starting port until it encounters an error.
YMMV, but at least we can get aggregate stats via a single instance.
****
FarmSize 10
FarmChildHook file:"/etc/radiator/farmchild.pl"
<ServerHTTP>
Identifier MetricsHack
Port 8000
DefaultPrivilegeLevel 1
PageNotFoundHook file:"/etc/radiator/metrics-handler.pl"
</ServerHTTP>
*****
*****
/etc/radiator/farmchild.pl
sub {
my $server =
Radius::Configurable::find('ServerHTTP','MetricsHack');
my $port = $server->{Port} + $main::farmInstance;
&main::log($main::LOG_INFO, "FarmInstance $main::farmInstance
assigning ServerHTTP port to $port");
$server->{Port} = $port;
$server->activate();
}
*****
*****
/etc/radiator/metrics-handler.pl
sub {
my $uri = $_[0];
if($uri !~ /^\/metrics$/) {
return;
}
my $stats;
foreach ( keys %Radius::StatsLogGeneric::statistic_names) {
my $name = "radiator_$_";
my $value = $main::config->{Statistics}{$_};
$stats .= "$name $value\n";
}
for my $client (@{$main::config->{Client}}) {
my $name = $client->{Name};
for my $stat (keys $client->{Statistics} ) {
next if $stat eq 'Name';
$stats .= "radiatorClient_${stat}{client=\"$name\"} " .
$client->{Statistics}{$stat} . "\n";
}
}
return (200, $stats);
}
*****
*****
#!/usr/bin/perl
use strict;
use LWP::Simple;
use List::Util qw(sum);
use HTTP::Daemon;
use HTTP::Status;
use Sys::Syslog;
my $start_port = 8000;
my $server_port = 7999;
my $server = HTTP::Daemon->new( LocalPort => $server_port, Reuse => 1 )
or die;
while (my $client = $server->accept) {
while ( my $request = $client->get_request) {
if ( $request->method eq 'GET' and $request->uri->path
eq '/metrics' ) {
my $metrics = aggregate_metrics();
$client->send_response(HTTP::Response->new(200,undef,undef,$metrics));
} else {
$client->send_error(RC_FORBIDDEN);
}
}
$client->close;
}
sub aggregate_metrics {
my %counters;
my %gauges;
my $metrics;
my $count = 0;
my $port = $start_port;
while (1) {
$port++;
my $farmstat = get("http://127.0.0.1:$port/metrics");
if ( $farmstat ) {
$count++;
for my $line (split /^/, $farmstat ) {
my ($label,$value) = split(/ /,$line);
if ( $label =~ /responseTime/ ) {
push(@{$gauges{$label}},$value);
next;
}
$counters{$label} += $value;
}
} else {
last;
}
}
for my $label (keys %gauges) {
$metrics .= $label . " " . (
sum(@{$gauges{$label}})/@{$gauges{$label}} ) . "\n";
}
for my $label (keys %counters) {
$metrics .= "$label $counters{$label}\n";
}
$metrics .="radiator_FarmActive $count\n";
eval {
openlog($0,'cons,pid','user');
syslog('info',"aggregated stats from $count farm workers");
closelog();
};
return $metrics;
}
*****
*****
# cat aggreagte-metrics.service
[Unit]
Description=Radiator Prometheus Metrics Aggregator Hack
[Service]
ExecStart=/etc/radiator/aggreagte-metrics.pl
[Install]
WantedBy=multi-user.target
*****
--
kelsey.cummings at sonic.com sonic.net, inc.
System Architect 2260 Apollo Way
707.522.1000 Santa Rosa, CA
More information about the radiator
mailing list