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.910'; # VERSION
6              
7 2     2   135201 use 5.018;
  2         28  
8 2     2   14 use strict;
  2         3  
  2         40  
9 2     2   10 use warnings;
  2         4  
  2         54  
10              
11 2     2   10 use base 'Class::Accessor::Fast';
  2         4  
  2         1012  
12             __PACKAGE__->mk_accessors(qw(app version checks show_hostname buildinfo));
13              
14 2     2   6441 use Try::Tiny;
  2         4119  
  2         113  
15 2     2   854 use Plack::Response;
  2         22427  
  2         63  
16 2     2   909 use JSON::MaybeXS;
  2         15423  
  2         122  
17 2     2   887 use Sys::Hostname qw(hostname);
  2         1950  
  2         123  
18 2     2   983 use Module::Runtime qw(use_module);
  2         3441  
  2         13  
19 2     2   990 use Log::Any qw($log);
  2         16263  
  2         10  
20 2     2   5792 use Path::Tiny;
  2         24784  
  2         123  
21 2     2   1021 use POSIX qw(strftime);
  2         12719  
  2         11  
22              
23             my $startup = time();
24              
25             sub new {
26 4     4 1 10364 my ( $class, %args ) = @_;
27              
28             my %attr =
29 4         16 map { $_ => delete $args{$_} } qw(app version show_hostname buildinfo);
  16         49  
30 4         14 $attr{checks} = [];
31              
32 4         25 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         19 return bless \%attr, $class;
58             }
59              
60             sub to_app {
61 4     4 0 9 my $self = shift;
62              
63 4 50       109 my $hostname = $self->show_hostname ? hostname() : '';
64              
65 4         51 my $buildinfo;
66 4 100       78 if ( $self->buildinfo ) {
67 3 100       71 if ( -f $self->buildinfo ) {
68             $buildinfo =
69 2         56 eval { decode_json( path( $self->buildinfo )->slurp_utf8 ) };
  2         47  
70 2 100       1886 if ($@) {
71 1         5 $buildinfo = { status => 'error', message => $@ };
72             }
73             }
74             else {
75 1         61 $buildinfo = {
76             status => 'error',
77             message => 'cannot read buildinfo from ' . $self->buildinfo
78             };
79             }
80             }
81              
82             my $app = sub {
83 4     4   17 my $env = shift;
84              
85 4         101 my $json = {
86             app => $self->app,
87             started_at_iso8601 => strftime( '%FT%TZ', gmtime($startup) ),
88             started_at => $startup,
89             uptime => time() - $startup,
90             };
91 4         454 $json->{version} = $self->version;
92 4 50       44 $json->{hostname} = $hostname if $hostname;
93 4 100       13 $json->{buildinfo} = $buildinfo if $buildinfo;
94              
95 4         70 my @results = (
96             {
97             name => $self->app,
98             status => 'ok',
99             }
100             );
101              
102 4         35 foreach my $check ( @{ $self->checks } ) {
  4         72  
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         37 $json->{checks} = \@results;
118              
119 4         110 return Plack::Response->new( 200,
120             [ 'Content-Type', 'application/json' ],
121             encode_json($json) )->finalize;
122 4         67 };
123 4         14 return $app;
124             }
125              
126             1;
127              
128             __END__