Mojo-Netdata
view release on metacpan or search on metacpan
lib/Mojo/Netdata/Collector/HTTP.pm view on Meta::CPAN
package Mojo::Netdata::Collector::HTTP;
use Mojo::Base 'Mojo::Netdata::Collector', -signatures;
use Mojo::UserAgent;
use Mojo::Netdata::Util qw(logf safe_id);
use Time::HiRes qw(time);
require Mojo::Netdata;
our $VERSION = '0.04';
has concurrency => 4;
has jobs => sub ($self) { +[] };
has type => 'HTTP';
has ua => sub { Mojo::UserAgent->new(insecure => 0, connect_timeout => 5, request_timeout => 5) };
has update_every => 30;
sub register ($self, $config, $netdata) {
$config->{update_every} ? $self->update_every($config->{update_every})
: $netdata->update_every >= 10 ? $self->update_every($netdata->update_every)
: $self->update_every(30);
$self->ua->insecure($config->{insecure}) if defined $config->{insecure};
$self->ua->connect_timeout($config->{connect_timeout}) if defined $config->{connect_timeout};
$self->ua->request_timeout($config->{request_timeout}) if defined $config->{request_timeout};
$self->ua->proxy->detect if $config->{proxy} // 1;
$self->ua->transactor->name($config->{user_agent} || "Mojo-Netdata/$VERSION (Perl)");
$self->concurrency($config->{concurrency} || 4);
$self->jobs([]);
my @jobs = ref $config->{jobs} eq 'HASH' ? %{$config->{jobs}} : @{$config->{jobs}};
while (my $url = shift @jobs) {
my $job = $self->_make_job($url => ref $jobs[0] eq 'HASH' ? shift @jobs : {}, $config);
push @{$self->jobs}, $job if $job;
}
return @{$self->jobs} ? $self : undef;
}
sub update_p ($self) {
my ($ua, @p) = ($self->ua);
return Mojo::Promise->map(
{concurrency => $self->concurrency},
sub {
my ($job, $t0) = ($_, time);
my $tx = $ua->build_tx(@{$job->[0]});
return $ua->start_p($tx)->then(sub ($tx) {
$job->[1]->($tx, $t0);
})->catch(sub ($err) {
$job->[1]->($tx, $t0, {message => $err});
});
},
@{$self->jobs}
);
}
sub _make_job ($self, $url, $params, $defaults) {
$url = Mojo::URL->new($url);
return undef unless my $host = $url->host;
my $headers = Mojo::Headers->new->from_hash($defaults->{headers} || {});
$headers->header($_ => $params->{headers}{$_}) for keys %{$params->{headers} || {}};
($headers->header(Host => $url->host), $url->host($params->{via})) if $params->{via};
my $dimension = $params->{dimension} || $headers->host || $url->host;
my $family = $params->{family} || $defaults->{family} || $headers->host || $url->host;
my $log_level = $defaults->{log_level} || 'debug';
my $code_chart = $self->chart("${family}_code")->title("HTTP Status code for $family")
->context('httpcheck.code')->family($family)->units('#');
if ($code_chart->dimension($dimension)) {
logf(warnings => 'Family "%s" already has dimension "%s".', $family, $dimension);
return undef;
}
my $time_chart = $self->chart("${family}_time")->title("Response time for $family")
->context('httpcheck.responsetime')->family($family)->units('ms');
$code_chart->dimension($dimension => {});
$time_chart->dimension($dimension => {});
my $update = sub ($tx, $t0, $err = undef) {
$err ||= $tx->error;
my $req = $tx->req;
my $code = $tx->res->code // 0;
my @msg = ($req->method, $req->url, $err || {code => $code}, $req->headers->to_hash(1));
logf(($code >= 200 && $code < 300 ? $log_level : 'warnings'), '%s %s == %s %s', @msg);
$time_chart->dimension($dimension => {value => int(1000 * (time - $t0))});
$code_chart->dimension($dimension => {value => $code});
};
my @data;
push @data, $headers->to_hash(1);
push @data,
exists $params->{json} ? (json => $params->{json})
: exists $params->{form} ? (form => $params->{form})
: exists $params->{body} ? ($params->{body})
( run in 0.709 second using v1.01-cache-2.11-cpan-5735350b133 )