Beekeeper
view release on metacpan or search on metacpan
examples/dashboard/lib/Beekeeper/Service/Dashboard/Worker.pm view on Meta::CPAN
package
Beekeeper::Service::Dashboard::Worker; # hide from PAUSE
use strict;
use warnings;
our $VERSION = '0.10';
use Beekeeper::Worker ':log';
use base 'Beekeeper::Worker';
use Beekeeper::Worker::Extension::RemoteSession;
use Beekeeper::Service::Supervisor;
use Beekeeper::Service::LogTail;
use Beekeeper::Config;
use AnyEvent;
use JSON::XS;
use Scalar::Util 'weaken';
use Digest::SHA 'sha256_hex';
use Fcntl qw(:DEFAULT :flock);
use Time::HiRes;
use constant AVERAGE => 0;
use constant MAXIMUM => 1;
use constant TOTAL => 2;
use constant COUNT => 3;
use constant TSTAMP => 0;
use constant STATS => 1;
sub authorize_request {
my ($self, $req) = @_;
# Explicitly authorize the login method
return BKPR_REQUEST_AUTHORIZED if $req->{method} eq 'bkpr.dashboard.login';
# Require an user logged in for any other request
return unless $self->get_authentication_data;
return BKPR_REQUEST_AUTHORIZED;
}
sub on_startup {
my ($self) = @_;
my $config = Beekeeper::Config->read_config_file( 'dashboard.config.json' );
$self->{config} = $config || {};
unless ($config) {
log_warn "Couldn't read config file 'dashboard.config.json'";
}
unless ($config && $config->{users} && %{$config->{users}}) {
log_warn "No users defined into config file 'dashboard.config.json'";
}
$self->accept_remote_calls(
'bkpr.dashboard.login' => 'login',
'bkpr.dashboard.services' => 'service_stats',
'bkpr.dashboard.logs' => 'log_tail',
);
$self->_init_collector;
log_info "Ready";
}
sub on_shutdown {
my ($self) = @_;
$self->_save_state;
log_info "Stopped";
}
sub stop_working {
my ($self) = @_;
examples/dashboard/lib/Beekeeper/Service/Dashboard/Worker.pm view on Meta::CPAN
my $stats = $self->{"services_$resol"} or die "Invalid resolution";
my $idx = @$stats - $count;
$idx = 0 if $idx < 0;
if ($after) {
my $min = $idx;
my $new_data;
for (my $i = @$stats - 1; $i >= 0; $i--) {
last if $stats->[$i]->[TSTAMP] <= $after;
last if $i < $min;
$new_data = $i;
}
return [] unless $new_data;
$idx = $new_data;
}
unless ($class) {
return [ @$stats[$idx..(@$stats - 1)] ];
}
my @svc_stats;
foreach my $st (@$stats[$idx..(@$stats - 1)]) {
next unless exists $st->[STATS]->{$class};
push @svc_stats, [ $st->[TSTAMP], $st->[STATS]->{$class} ];
}
return \@svc_stats;
}
sub log_tail {
my ($self, $params, $req) = @_;
my %filters;
foreach my $filter (qw'service count level after host pool message') {
next unless $params->{$filter};
$filters{$filter} = $params->{$filter};
}
$req->async_response;
$req->deflate_response;
Beekeeper::Service::LogTail->tail_async(
%filters,
on_success => sub {
my ($resp) = @_;
$req->send_response( $resp->result );
},
on_error => sub {
my ($resp) = @_;
$req->send_response( $resp );
},
);
}
sub _init_collector {
my ($self) = @_;
weaken($self);
$self->_load_state;
$self->{services_1s} ||= [];
$self->{services_5s} ||= [];
$self->{services_2m} ||= [];
$self->{services_15m} ||= [];
$self->{services_1h} ||= [];
my $now = Time::HiRes::time;
my $msec = $now - int($now);
my $offs_1s = $msec;
my $offs_5s = $now % 5 + $msec;
my $offs_1m = $now % 60 + $msec;
$self->{collect_tmr} = AnyEvent->timer(
after => 1 - $offs_1s,
interval => 1,
cb => sub {
Beekeeper::Service::Supervisor->get_services_status_async(
on_success => sub {
my ($resp) = @_;
$self->_collect_stats( $resp->result );
},
on_error => sub {
my ($error) = @_;
log_warn $error->message;
},
);
},
);
$self->{consolidate_5s_tmr} = AnyEvent->timer(
after => 5 - $offs_5s,
interval => 5,
cb => sub {
# 1 hour in 5 sec resolution
$self->_consolidate(
from => $self->{services_1s},
into => $self->{services_5s},
period => 5,
keep => 60 * 60/5, # 720
);
},
);
$self->{consolidate_1m_tmr} = AnyEvent->timer(
after => 60 - $offs_1m,
interval => 60,
cb => sub {
# 1 day in 2 min resolution
$self->_consolidate(
from => $self->{services_5s},
into => $self->{services_2m},
period => 2 * 60,
keep => 24 * 60/2, # 720
);
( run in 2.015 seconds using v1.01-cache-2.11-cpan-98e64b0badf )