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 )