File Coverage

blib/lib/HPC/Runner/Command/stats.pm
Criterion Covered Total %
statement 33 88 37.5
branch 0 30 0.0
condition 0 21 0.0
subroutine 11 16 68.7
pod n/a
total 44 155 28.3


line stmt bran cond sub pod time code
1             package HPC::Runner::Command::stats;
2              
3 1     1   1173 use MooseX::App::Command;
  1         2  
  1         10  
4 1     1   10874 use Moose::Util qw/apply_all_roles/;
  1         3  
  1         7  
5             extends 'HPC::Runner::Command';
6              
7 1     1   236 use MooseX::Types::Path::Tiny qw/File Path Paths AbsPath AbsFile/;
  1         2  
  1         11  
8             with 'HPC::Runner::Command::Logger::JSON';
9             with 'HPC::Runner::Command::stats::Logger::JSON::Summary';
10             with 'HPC::Runner::Command::stats::Logger::JSON::Long';
11             with 'HPC::Runner::Command::Logger::Loggers';
12              
13 1     1   3118 use JSON;
  1         3  
  1         8  
14 1     1   118 use File::Find::Rule;
  1         2  
  1         11  
15 1     1   60 use File::stat;
  1         2  
  1         7  
16 1     1   52 use File::Spec;
  1         2  
  1         22  
17 1     1   5 use File::Slurp;
  1         2  
  1         48  
18 1     1   5 use Path::Tiny;
  1         2  
  1         39  
19 1     1   5 use File::Basename;
  1         2  
  1         46  
20 1     1   6 use Capture::Tiny ':all';
  1         2  
  1         951  
21              
22             command_short_description 'Query submissions by project, or jobname';
23             command_long_description 'Query submissions by project, or jobname. ' . 'This
24             searches through the tars created during execution.'
25             . ' If you have a large number
26             of submissions you may want to specify a project, '
27             . 'or supply the desired submission with --data_tar.';
28              
29             option 'most_recent' => (
30             is => 'rw',
31             isa => 'Bool',
32             required => 0,
33             default => 1,
34             documentation => q(Show only the most recent submission.),
35             trigger => sub {
36             my $self = shift;
37             $self->all(1) if !$self->most_recent;
38             }
39             );
40              
41             option 'all' => (
42             is => 'rw',
43             isa => 'Bool',
44             required => 0,
45             default => 0,
46             documentation => 'Show all submissions.',
47             trigger => sub {
48             my $self = shift;
49             $self->most_recent(1) if !$self->all;
50             },
51             cmd_aliases => ['a'],
52             );
53              
54             option '+project' => ( documentation => 'Query by project.', );
55              
56             option 'jobname' => (
57             is => 'rw',
58             isa => 'Str',
59             documentation => 'Query by jobname',
60             required => 0,
61             predicate => 'has_jobname',
62             );
63              
64             option 'summary' => (
65             is => 'rw',
66             isa => 'Bool',
67             documentation =>
68             'Summary view of your jobs - Number of running, completed, failed, successful.',
69             required => 0,
70             default => 1,
71             );
72              
73             option 'long' => (
74             is => 'rw',
75             isa => 'Bool',
76             documentation =>
77             'Long view. More detailed report - Task tags, exit codes, duration, etc.',
78             required => 0,
79             default => 0,
80             trigger => sub {
81             my $self = shift;
82             $self->summary(0) if $self->long;
83             },
84             cmd_aliases => ['l'],
85             );
86              
87             option 'json' => (
88             is => 'rw',
89             isa => 'Bool',
90             default => 0,
91             documentation => 'Output data in json instead of a table. '
92             . 'This option suppresses logging output.',
93             cmd_aliases => ['j'],
94             );
95              
96             has 'task_data' => (
97             is => 'rw',
98             isa => 'HashRef',
99             default => sub { {} },
100             clearer => 'clear_task_data',
101             );
102              
103             parameter 'stats_type' => (
104             is => 'rw',
105             isa => 'Str',
106             default => 'JSON',
107             documentation => 'hpcrunner.pl stats JSON/Sqlite/Elasticsearch .',
108             );
109              
110             sub BUILD {
111 0     0     my $self = shift;
112              
113 0 0 0       if ( $self->json && $self->summary ) {
    0 0        
    0 0        
    0 0        
114 0           apply_all_roles( $self,
115             'HPC::Runner::Command::stats::Logger::'
116             . $self->stats_type
117             . '::Summary::JSONOutput' );
118             }
119             elsif ( !$self->json && $self->summary ) {
120 0           apply_all_roles( $self,
121             'HPC::Runner::Command::stats::Logger::'
122             . $self->stats_type
123             . '::Summary::TableOutput' );
124             }
125             elsif ( $self->json && $self->long ) {
126 0           apply_all_roles( $self,
127             'HPC::Runner::Command::stats::Logger::'
128             . $self->stats_type
129             . '::Long::JSONOutput' );
130             }
131             elsif ( !$self->json && $self->long ) {
132 0           apply_all_roles( $self,
133             'HPC::Runner::Command::stats::Logger::'
134             . $self->stats_type
135             . '::Long::TableOutput' );
136             }
137             }
138              
139             sub execute {
140 0     0     my $self = shift;
141              
142 0           $self->iter_submissions;
143             }
144              
145             sub iter_submissions {
146 0     0     my $self = shift;
147              
148 0           my $results = $self->get_submissions();
149              
150 0           foreach my $result ( @{$results} ) {
  0            
151 0           $self->data_dir($result);
152 0           my $submission_file =
153             File::Spec->catdir( $self->data_dir, 'submission.json' );
154 0 0         if ( -e $submission_file ) {
155 0           my $submission_json = read_file($submission_file);
156 0           my $submission = decode_json($submission_json);
157 0           my $jobref = $submission->{jobs};
158              
159 0 0         $self->iter_jobs_summary( $submission, $jobref )
160             if $self->summary;
161 0 0         $self->iter_jobs_long( $submission, $jobref ) if $self->long;
162             }
163             else {
164 0           $self->screen_log->info( 'Data Tar '
165             . $self->data_dir
166             . ' does not contain any submission info!' );
167             }
168             }
169              
170             }
171              
172             sub get_submissions {
173 0     0     my $self = shift;
174              
175             ## Skip over this searching nonsense
176 0           my $results;
177 0 0 0       if ( $self->has_data_dir && $self->data_dir->exists ) {
    0 0        
178 0           my $file = $self->data_dir;
179 0           $results = ["$file"];
180             }
181             elsif ( $self->has_data_dir && !$self->data_dir->exists ) {
182 0           $self->screen_log->fatal(
183             'You have supplied a data tar that does not exist.');
184 0           $self->screen_log->fatal(
185             'Data Tar ' . $self->data_dir . ' does not exist' );
186 0           exit 1;
187             }
188             else {
189 0           $results = $self->search_submission;
190             }
191              
192 0           return $results;
193             }
194              
195             sub search_submission {
196 0     0     my $self = shift;
197              
198 0           my $data_path = "";
199 0           my $data_dir = File::Spec->catdir( $self->cache_dir, '.hpcrunner-data' );
200 0 0         if ( $self->project ) {
201 0           $data_path = File::Spec->catdir( $data_dir, $self->project );
202             }
203             else {
204 0           $data_path = $data_dir;
205             }
206              
207 0 0 0       if ( !path($data_path)->exists && path($data_path)->is_dir ) {
208 0           $self->screen_log->info( 'There is no data logged. '
209             . 'Please ensure you either in the project directory, '
210             . 'or that you have supplied --data_dir to the correct location.'
211             );
212             }
213              
214 0           $self->screen_log->info( 'Searching for submissions in ' . $data_dir );
215              
216             ##TODO In the case of a lot of submissions - get the most recent directory
217 0           my @files = File::Find::Rule->directory()->maxdepth(2)->name(qr/.*UID.*/)
218             ->in($data_path);
219 0 0         if ( !$self->json ) {
220 0           $self->screen_log->info( 'Found ' . scalar @files . ' submissions.' );
221 0 0         $self->screen_log->info('Reporting on the most recent.')
222             if $self->most_recent;
223 0 0         $self->screen_log->info('Reporting on all submissions.') if $self->all;
224             }
225              
226 0           my %stats = ();
227 0           map { my $st = stat($_); $stats{ $st->[9] } = $_ } @files;
  0            
  0            
228              
229 0           my @sorted_files = ();
230 0           foreach ( sort { $b <=> $a } keys(%stats) ) {
  0            
231 0           push( @sorted_files, $stats{$_} );
232 0 0         last if $self->most_recent;
233             }
234              
235 0           return \@sorted_files;
236             }
237              
238             __PACKAGE__->meta()->make_immutable();
239              
240             1;