Statistique Dollar Universe ou Baby Perl

Je n’apprends de nouveau langage que si nécessaire…. ainsi il y a 4 ans j’ai appris le python qui fut un véritable plaisir ou bien le WLangage (avec moins de plaisir….). Hier je devais produire des statistiques d’exécution de batch lancés par l’ordonnanceur Dollar Universe (connu aussi sous le nom $U), un outil obsolète, propriétaire dont la fonction statistique est vraiment minimaliste.

En effet la commande obscure livrée avec $U permet d’avoir sous forme textuelle, l’état de chaque batch avec la date d’exécution, l’heure de début et l’heure de fin. Quid des traitements qui démarrent avant minuit et finissent après… on aurait aimé avoir la date de fin également, mais bon $U est un outils basique et payant, n’en demandons pas trop.

Afin d’agréger le résultats par batch et faire quelques statistiques (max, min, moyenne dans un premier temps), un petit programme Perl semblait tout indiqué. Voilà ce que cela donne après avoir lu 2 livres: Modern Perl et Impatient Perl , du baby perl tout craché! Le couteaux suisse de l’administrateur Unix/Linux ne dément pas sa réputation: il fait le boulot !

Le script suivant prend en entrée le résultat de la commande d’état des batchs de $U et recrache sur la sortie standard un CSV. Alternativement on peut lui passer en argument le fichier issu de $U et le fichier de sortie CSV.

#!/usr/bin/env perl
use warnings;
use DateTime::Format::Strptime;
use Text::CSV;

my %batch_stat = ();

sub get_input{
    my $num_arg =  $#ARGV + 1;
    unless ($num_arg==0) {
    open my  $input_fd , '<', $ARGV[0]
        or die "Impossible d'ouvrir le fichier $ARGV[0]";
    return $input_fd
    } 
    my $input = STDIN;
    return $input;
}

sub get_output {
  my $num_arg =  $#ARGV + 1;
    unless ($num_arg < 2) {
    open my  $output_fd , '>', $ARGV[1]
        or die "Impossible d'ouvrir le fichier $ARGV[1]";
    $output_fd -> autoflush(1);        
    return $output_fd;

    }
    my $output = STDOUT;
    return $output;
}

sub handle_line {
    my ($line) = @_;
    my $date_format = qr/\d{2}\/\d{2}\/\d{4}/;
    my $heure_format = qr/\d{4}/;
    if (  $line =~ /TERMINE\s*(?<date_exec>$date_format)\s(?<heure_debut>$heure_format)\s(?<heure_fin>$heure_format)/) {
    my @splitted = split(/\s+/,substr($line,19, length($line)));
    my $batch =  $splitted[0];
    my $date =  "$+{date_exec}";
    my $heure_debut =  "$+{heure_debut}";
    my $heure_fin =  "$+{heure_fin}";
    #print "$batch $date $heure_debut $heure_fin\n";

    my $analyseur = DateTime::Format::Strptime ->new (pattern => '%d/%m/%Y %H%M');
    my $dt_debut = $analyseur -> parse_datetime ($date .  ' ' .  $heure_debut);
    my $dt_fin = $analyseur -> parse_datetime ($date . ' ' .  $heure_fin);
    # la commande de stat de dollar univers ne précise pas la date de fin
    # mais uniquement l'heure de fin
    if ($dt_fin < $dt_debut){
        my $un_jour = DateTime::Duration -> new (days => 1);
        $dt_fin -> add_duration($un_jour);
    }
    my $duree = $dt_fin - $dt_debut;
    my $duree_minutes = $duree -> in_units('minutes');

    unless(exists($batch_stat{$batch})){
        #my %info = qw (min 0 max 0 moyenne 0 nb 0);
        $batch_stat{$batch}= {
        min => $duree_minutes,
        max => $duree_minutes,
        moyenne => 0,
        nb => 0        
        };
        #print "nouveau stat de batch cree \n";
    }
    my $current_nb = $batch_stat{$batch}{nb};
    $batch_stat{$batch}{nb} = $current_nb + 1;
        $batch_stat{$batch}{'min'} = $duree_minutes if $duree_minutes < $batch_stat{$batch}{'min'};
        $batch_stat{$batch}{'max'} = $duree_minutes if $duree_minutes > $batch_stat{$batch}{'max'};
    $batch_stat{$batch}{'moyenne'} = ( $batch_stat{$batch}{'moyenne'} * $current_nb + $duree_minutes ) / $batch_stat{$batch}{nb};

    }

}

my $real_input = get_input();

while (<$real_input>)
{
    handle_line($_);

}
#print Dumper \%batch_stat;

my $real_output = get_output();

my @entetes = ('batch','nb_exec','temp_min','temp_max','temp_moy');

$csv = Text::CSV -> new();
$csv -> print($real_output, \@entetes);
$real_output -> say();

foreach my $batch_name (keys(%batch_stat)) {
    my @column = ($batch_name,  $batch_stat{$batch_name}{nb}, $batch_stat{$batch_name}{min}, $batch_stat{$batch_name}{max}, $batch_stat{$batch_name}{moyenne} );
    $csv -> print($real_output, \@column);
    $real_output -> say();
}