pve-manager/PVE/ExtMetric.pm
Thomas Lamprecht e35f1d37d7 Ext. Metrics: module global variable does not help with memory leak
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2019-11-18 19:15:13 +01:00

106 lines
2.5 KiB
Perl

package PVE::ExtMetric;
use strict;
use warnings;
use PVE::Status::Plugin;
use PVE::Status::Graphite;
use PVE::Status::InfluxDB;
PVE::Status::Graphite->register();
PVE::Status::InfluxDB->register();
PVE::Status::Plugin->init();
sub foreach_plug($&) {
my ($status_cfg, $code) = @_;
for my $id (sort keys %{$status_cfg->{ids}}) {
my $plugin_config = $status_cfg->{ids}->{$id};
next if $plugin_config->{disable};
my $plugin = PVE::Status::Plugin->lookup($plugin_config->{type});
$code->($plugin, $id, $plugin_config);
}
}
sub update_all($$@) {
my ($transactions, $subsystem, @params) = @_;
my $method = "update_${subsystem}_status";
my (undef, $fn, $line, $subr) = caller(1);
for my $txn (@$transactions) {
my $plugin = PVE::Status::Plugin->lookup($txn->{cfg}->{type});
$plugin->$method($txn, @params);
if (length($txn->{data}) > 48000) {
# UDP stack cannot handle messages > 65k, if we've alot of data we
# do smaller batch sends then, but keep the connection alive
transaction_flush($txn, 1);
}
}
}
# must return a transaction hash with the format:
# {
# cfg => $plugin_config,
# connection => ..., # the connected socket
# data => '', # payload, will be sent at the trannsaction flush
# }
sub transactions_start {
my ($cfg) = @_;
my $transactions = [];
foreach_plug($cfg, sub {
my ($plugin, $id, $plugin_config) = @_;
my $connection = $plugin->_connect($plugin_config);
push @$transactions, {
connection => $connection,
cfg => $plugin_config,
id => $id,
data => '',
};
});
return $transactions;
}
sub transaction_flush {
my ($txn, $keepconnected) = @_;
if (!$txn->{connection}) {
return if !$txn->{data}; # OK, if data was already sent/flushed
die "cannot flush metric data, no connection available!\n";
}
return if !defined($txn->{data}) || $txn->{data} eq '';
my $plugin = PVE::Status::Plugin->lookup($txn->{cfg}->{type});
my $data = delete $txn->{data};
eval { $plugin->send($txn->{connection}, $data) };
my $senderr = $@;
if (!$keepconnected) {
$plugin->_disconnect($txn->{connection});
$txn->{connection} = undef;
# avoid log spam, already got a send error; disconnect would fail too
warn "disconnect failed: $@" if $@ && !$senderr;
}
die "metrics send error '$txn->{id}': $senderr" if $senderr;
};
sub transactions_finish {
my ($transactions) = @_;
for my $txn (@$transactions) {
eval { transaction_flush($txn) };
warn "$@" if $@;
}
}
1;