File Coverage

blib/lib/Plack/App/ServiceStatus.pm
Criterion Covered Total %
statement 63 78 80.7
branch 10 16 62.5
condition n/a
subroutine 15 17 88.2
pod 1 2 50.0
total 89 113 78.7


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.911'; # VERSION
6              
7 2     2   138908 use 5.024;
  2         28  
8 2     2   11 use strict;
  2         4  
  2         38  
9 2     2   10 use warnings;
  2         3  
  2         52  
10              
11 2     2   14 use base 'Class::Accessor::Fast';
  2         3  
  2         1042  
12             __PACKAGE__->mk_accessors(qw(app version checks show_hostname buildinfo));
13              
14 2     2   6906 use Try::Tiny;
  2         4297  
  2         130  
15 2     2   985 use Plack::Response;
  2         23744  
  2         65  
16 2     2   1017 use JSON::MaybeXS;
  2         16834  
  2         133  
17 2     2   964 use Sys::Hostname qw(hostname);
  2         2105  
  2         123  
18 2     2   1625 use Module::Runtime qw(use_module);
  2         3616  
  2         22  
19 2     2   1115 use Log::Any qw($log);
  2         17221  
  2         10  
20 2     2   6255 use Path::Tiny;
  2         26042  
  2         144  
21 2     2   1043 use POSIX qw(strftime);
  2         13469  
  2         11  
22              
23             my $startup = time();
24              
25             sub new {
26 4     4 1 10206 my ( $class, %args ) = @_;
27              
28             my %attr =
29 4         12 map { $_ => delete $args{$_} } qw(app version show_hostname buildinfo);
  16         42  
30 4         12 $attr{checks} = [];
31              
32 4         21 while ( my ( $key, $value ) = each %args ) {
33 0         0 my $module;
34 0 0       0 if ( $key =~ /^\+/ ) {
35 0         0 $module = $key;
36 0         0 $module =~ s/^\+//;
37             }
38             else {
39 0         0 $module = 'Plack::App::ServiceStatus::' . $key;
40             }
41             try {
42 0     0   0 use_module($module);
43             push(
44             $attr{checks}->@*,
45             {
46 0         0 class => $module,
47             name => $key,
48             args => $value
49             }
50             );
51             }
52             catch {
53 0     0   0 $log->errorf( "%s: cannot init %s: %s", __PACKAGE__, $module, $_ );
54 0         0 };
55             }
56              
57 4         17 return bless \%attr, $class;
58             }
59              
60             sub to_app {
61 4     4 0 8 my $self = shift;
62              
63 4 50       108 my $hostname = $self->show_hostname ? hostname() : '';
64              
65 4         40 my $buildinfo;
66 4 100       74 if ( $self->buildinfo ) {
67 3 100       64 if ( -f $self->buildinfo ) {
68             $buildinfo =
69 2         55 eval { decode_json( path( $self->buildinfo )->slurp_utf8 ) };
  2         46  
70 2 100       1635 if ($@) {
71 1         4 $buildinfo = { status => 'error', message => $@ };
72             }
73             }
74             else {
75 1         60 $buildinfo = {
76             status => 'error',
77             message => 'cannot read buildinfo from ' . $self->buildinfo
78             };
79             }
80             }
81              
82             my $app = sub {
83 4     4   18 my $env = shift;
84              
85 4         92 my $json = {
86             app => $self->app,
87             started_at_iso8601 => strftime( '%Y-%m-%dT%H:%M:%SZ', gmtime($startup) ),
88             started_at => $startup,
89             uptime => time() - $startup,
90             };
91 4         360 $json->{version} = $self->version;
92 4 50       34 $json->{hostname} = $hostname if $hostname;
93 4 100       11 $json->{buildinfo} = $buildinfo if $buildinfo;
94              
95 4         69 my @results = (
96             {
97             name => $self->app,
98             status => 'ok',
99             }
100             );
101              
102 4         28 foreach my $check ( @{ $self->checks } ) {
  4         73  
103             my ( $status, $message ) = try {
104 0         0 return $check->{class}->check( $check->{args} );
105             }
106             catch {
107 0         0 return 'nok', "$_";
108 0         0 };
109             my $result = {
110             name => $check->{name},
111 0         0 status => $status,
112             };
113 0 0       0 $result->{message} = $message if ($message);
114              
115 0         0 push( @results, $result );
116             }
117 4         32 $json->{checks} = \@results;
118              
119 4         94 return Plack::Response->new( 200,
120             [ 'Content-Type', 'application/json' ],
121             encode_json($json) )->finalize;
122 4         45 };
123 4         15 return $app;
124             }
125              
126             1;
127              
128             __END__