File Coverage

blib/lib/Plack/App/ServiceStatus.pm
Criterion Covered Total %
statement 60 75 80.0
branch 8 16 50.0
condition n/a
subroutine 14 16 87.5
pod 1 2 50.0
total 83 109 76.1


line stmt bran cond sub pod time code
1             package Plack::App::ServiceStatus;
2              
3             # ABSTRACT: Check and report status of various services needed by your app
4              
5             our $VERSION = '0.909'; # VERSION
6              
7 1     1   70464 use 5.018;
  1         12  
8 1     1   5 use strict;
  1         1  
  1         20  
9 1     1   4 use warnings;
  1         2  
  1         25  
10              
11 1     1   4 use base 'Class::Accessor::Fast';
  1         1  
  1         558  
12             __PACKAGE__->mk_accessors(qw(app version checks show_hostname buildinfo));
13              
14 1     1   3681 use Try::Tiny;
  1         2149  
  1         59  
15 1     1   464 use Plack::Response;
  1         11941  
  1         30  
16 1     1   460 use JSON::MaybeXS;
  1         8391  
  1         61  
17 1     1   454 use Sys::Hostname qw(hostname);
  1         1038  
  1         64  
18 1     1   587 use Module::Runtime qw(use_module);
  1         1704  
  1         11  
19 1     1   527 use Log::Any qw($log);
  1         8790  
  1         5  
20 1     1   3122 use Path::Tiny;
  1         13190  
  1         768  
21              
22             my $startup = time();
23              
24             sub new {
25 3     3 1 9337 my ( $class, %args ) = @_;
26              
27 3         9 my %attr = map { $_ => delete $args{$_}} qw(app version show_hostname buildinfo);
  12         32  
28 3         8 $attr{checks} = [];
29              
30 3         14 while ( my ( $key, $value ) = each %args ) {
31 0         0 my $module;
32 0 0       0 if ( $key =~ /^\+/ ) {
33 0         0 $module = $key;
34 0         0 $module =~ s/^\+//;
35             }
36             else {
37 0         0 $module = 'Plack::App::ServiceStatus::' . $key;
38             }
39             try {
40 0     0   0 use_module($module);
41             push(
42             $attr{checks}->@*,
43 0         0 { class => $module,
44             name => $key,
45             args => $value
46             }
47             );
48             }
49             catch {
50 0     0   0 $log->errorf( "%s: cannot init %s: %s", __PACKAGE__, $module,
51             $_ );
52 0         0 };
53             }
54              
55 3         26 return bless \%attr, $class;
56             }
57              
58             sub to_app {
59 3     3 0 6 my $self = shift;
60              
61 3 50       79 my $hostname = $self->show_hostname ? hostname() : '';
62              
63 3         28 my $buildinfo;
64 3 50       54 if ($self->buildinfo) {
65 3 100       63 if (-f $self->buildinfo) {
66 2         49 $buildinfo = eval { decode_json(path($self->buildinfo)->slurp_utf8) };
  2         83  
67 2 100       1790 if ($@) {
68 1         6 $buildinfo = { status=>'error', message=>$@ };
69             }
70             }
71             else {
72 1         75 $buildinfo = { status=>'error', message=>'cannot read buildinfo from '.$self->buildinfo };
73             }
74             }
75              
76             my $app = sub {
77 3     3   14 my $env = shift;
78              
79 3         73 my $json = {
80             app => $self->app,
81             started_at => $startup,
82             uptime => time() - $startup,
83             };
84 3         130 $json->{version} = $self->version;
85 3 50       32 $json->{hostname} = $hostname if $hostname;
86 3 50       9 $json->{buildinfo} = $buildinfo if $buildinfo;
87              
88 3         55 my @results = (
89             { name => $self->app,
90             status => 'ok',
91             }
92             );
93              
94 3         24 foreach my $check ( @{ $self->checks } ) {
  3         53  
95             my ( $status, $message ) = try {
96 0         0 return $check->{class}->check( $check->{args} );
97             }
98             catch {
99 0         0 return 'nok', "$_";
100 0         0 };
101             my $result = {
102             name => $check->{name},
103 0         0 status => $status,
104             };
105 0 0       0 $result->{message} = $message if ($message);
106              
107 0         0 push( @results, $result );
108             }
109 3         34 $json->{checks} = \@results;
110              
111 3         66 return Plack::Response->new( 200,
112             [ 'Content-Type', 'application/json' ],
113             encode_json($json) )->finalize;
114 3         39 };
115 3         11 return $app;
116             }
117              
118             1;
119              
120             __END__