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 )