Обрабатывать лог-файл для идентификации остановленных данных - PullRequest
1 голос
/ 04 мая 2019

У меня запущено несколько процессов, которые создают данные с разной скоростью. Я хотел бы использовать Perl для идентификации тех экспериментов, которые не создавали данные более 1 часа, чтобы завершить их раньше. Файл журнала выглядит примерно так (генерируется каждые 15 минут, сокращается для удобства чтения):

# Dataset,Timestamp,dataset size
exp-201905040115a,1556932502,0
exp-201905040115b,1556932502,0
exp-201905040115a,1556934301,213906
exp-201905040115b,1556934301,25487
exp-201905040115a,1556936102,399950
exp-201905040115b,1556936102,210548
exp-201905040115a,1556937002,399950
exp-201905040115b,1556937002,487250
exp-201905040115a,1556937902,399950
exp-201905040115b,1556937902,487250
exp-201905040115a,1556938802,399950
exp-201905040115b,1556938802,502145
exp-201905040115a,1556939701,399950
exp-201905040115b,1556939701,502145
exp-201905040115a,1556940601,399950
exp-201905040115b,1556940601,502145
exp-201905040115a,1556941502,399950
exp-201905040115b,1556941502,502145
exp-201905040115a,1556942401,399950
exp-201905040115b,1556942401,502145

Первый размер набора данных обычно равен 0, но иногда небольшое число (<100). </p>

Я уже научился читать данные из файла журнала и проверять их построчно (или, возможно, превратить эту строку в массив для извлечения записей столбцов).

#!/usr/bin/perl

use warnings;
use strict;

my @datasets = ( 'exp-201905040115a', 'exp-201905040115b' );

foreach my $dataset (@datasets) {
        open my $logfile, '<', 'data.log' or die "Cannot open: $!";
        while (my $line = <$logfile>) {
                chomp $line;
                my ( $log_dataset, $log_timestamp, $log_datasize ) = split /,/, $line ;

                if ( $dataset eq $log_dataset ) {
                        print "Matched: " , $dataset, "\t" ;
                        printf('%10d', $log_datasize) ;
                        print " at " , $log_timestamp , "\n" ;
                }
        }
        close $logfile;
}

  1. Я немного озадачен тем, как поступить с той частью, которая сообщает мне, произошло ли какое-либо изменение в третьем столбце за последние 3600 секунд. Я думаю, мне нужно сравнить значения из разных строк друг с другом, но здесь так много для сравнения?

  2. Кроме того, есть ли более эффективный способ, чем просмотр всего файла журнала несколько раз (по одному разу для каждого набора данных)?

Может кто-нибудь дать мне предложение? Спасибо!

1 Ответ

1 голос
/ 04 мая 2019

Входные данные CSV и несколько наборов данных для группировки заставляют меня думать о базах данных.И действительно ...

#!/bin/sh
logfile="$1"
sqlite3 -batch -noheader -csv <<EOF
CREATE TABLE logs(dataset TEXT, ts INTEGER, size INTEGER
                , PRIMARY KEY(dataset, size, ts)) WITHOUT ROWID;
.import "$logfile" logs
SELECT dataset
FROM logs AS l
GROUP BY dataset, size
HAVING max(ts) - min(ts) >= 3600
   AND max(ts) = (SELECT max(ts) FROM logs AS l2 WHERE l.dataset = l2.dataset
                                                   AND l.size = l2.size)
ORDER BY dataset;
EOF

распечатает exp-201905040115a при работе с вашими примерами данных.

Но вы хотите Perl.Существует удобный драйвер для DBI, который работает с CSV-файлами, но поддерживаемый им диалект SQL не включает HAVING, плюс он довольно медленный.Итак, план б.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;

my %datasets;

# Read the log file into a hash table of lists of (time,size) pairs.
while (<>) {
  chomp;
  my ($ds, $time, $size) = split /,/;
  push @{$datasets{$ds}}, [ $time => $size ];
}

# For each dataset listed in the file:
DATASET:
while (my ($ds, $data) = each %datasets) {
  # Sort list in reverse order of time
  @$data = sort { $b->[0] <=> $a->[0] } @$data;
  # Get the most recent entry
  my ($time, $size) = @{shift @$data};
  # And compare it against the rest until...
  for my $rec (@$data) {
    # ... different size
    next DATASET if $size != $rec->[1];
    # ... Same size, entry more than an hour old
    if ($time - $rec->[0] >= 3600) {
      say $ds;
      next DATASET;
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...