【问题标题】:Merging log files with different formats合并不同格式的日志文件
【发布时间】:2016-03-06 09:47:26
【问题描述】:

我想要合并两个具有不同日期/时间格式的日志文件。

第一个文件是标准的 Apache access_log 文件,如下所示:

127.0.0.1 - - [29/Feb/2016:16:57:52 -0600] "GET /application/wcs/api/version?nodeRef=workspace://SpacesStore/ecd62cfa-fd19-4d6b-b45d- 14f0e5b92cf0 HTTP/1.1" 200 567
127.0.0.1 - - [29/Feb/2016:16:57:52 -0600] “GET /application/wcs/api/node/workspace/SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0/workflow-instances HTTP/ 1.1" 200 40
127.0.0.1 - - [29/Feb/2016:16:57:52 -0600] “GET /application/wcs/cisco/appId?userId=abcdefg&requestType=get HTTP/1.1”200 45
173.37.239.93 - abcdefg [29/Feb/2016:16:57:52 -0600] “GET /share/page/site/nextgen-edcs/document-details?nodeRef=workspace://SpacesStore/ecd62cfa-fd19-4d6b -b45d-14f0e5b92cf0 HTTP/1.1" 200 124492
173.37.239.93 - abcdefg [29/Feb/2016:16:57:53 -0600] "GET /share/service/messages_69bcdfdb058bb873ff49cc2a10c958b7.js?locale=en_US HTTP/1.1" 200 81698
173.37.239.93 - abcdefg [29/Feb/2016:16:57:53 -0600] “GET /share/res/yui/history/history_543b42a00a378f4d4b6e70c81d915b0a.js HTTP/1.1”200 5781

。 . .其中 'abcdedfg' = 用户 ID。

第二个日志文件的格式如下:

2016-02-12 08:16:03,630 WARN [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] 集群处于非活动状态,但为缓存 HazelcastSimpleCache[cacheName= 调用了 put(k,v) cache.readersSharedCache]
2016-02-12 08:16:03,630 WARN [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] 集群处于非活动状态,但为缓存 HazelcastSimpleCache [cacheName=cache.readersSharedCache] 调用了 get(key),键=AclEntity[ID=1893033,版本=55,aclId=16cf5bc3-27d0-4d50-a93d-3bee1ddd​​112e,isLatest=true,aclVersion=1,inherits=true,inheritsFrom=1889292,type=1,inheritedAcl=1893034,isVersioned=假,需要版本=假,aclChangeSet=1451473]
2016-02-12 08:16:03,630 WARN [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] 集群处于非活动状态,但调用了 put(k,v) 缓存 HazelcastSimpleCache[cacheName=cache.readersSharedCache ]

我的目标是:

  1. 将第一个日志文件中的日期/时间格式转换为第二个日志文件的日期/时间格式
  2. 从第一个日志文件中删除 IP 地址,但保留用户 ID。
  3. 将两个日志文件合并在一起
  4. 按日期/时间排序。

这是我目前所拥有的——

$LOGFILE1 = "catalina.out";
$LOGFILE2 = "access_log";

open(LOGFILE1) or die("Could not open log file.");
foreach $line (<LOGFILE1>) {
    chomp($line);
    if ($line =~ /^2016.+$/) {
         print $line . "\n";
    }
}

open(LOGFILE2) or die("Could not open log file.");
foreach $line (<LOGFILE2>) {
chomp($line);
if ($line =~ /\d{2}\/\S{3}\/\d{4}:\d{2}:\d{2}:\d{2} -\d{3}/) {
print $line . "\n";
}

    # format of file 1
    # DD/MMM/YYYY:HH:MM:SS -NNNN
    # 29/Feb/2016:20:03:07 -600
    # format of file 2
    # YYYY-MM-DD HH:MM:SS,NNN
    # 2016-02-12 08:16:03,631
}

所以我基本上只对带有日期/时间信息的行感兴趣,所以上面的代码丢弃了其他行。

我被困的地方是:
1) 如何将文件 1 中的日期/时间格式转换为文件 2 的数据/时间格式?
2) 我对 IP 地址不感兴趣,但我确实想保留用户 ID。由于文件 1 不像文件 2 那样以日期/时间信息开头,因此在转换后,将两者合并后如何按日期排序?

任何帮助将不胜感激!

【问题讨论】:

  • 我们帮助那些自助的人。你有什么尝试,请表现出一些努力。
  • @anunsh - 添加了我到目前为止的代码。
  • 可以使用DateTime::Format::Strptime 完成。您将需要 2 个函数 parse_datetime and format_datetime 函数。
  • 也可以通过 Time::Piece 使用 Time::Piece->strptime(STRING, FORMAT)strftime 函数来完成。 Time::Piece 在 5.010 版本中成为 perl 核心的一部分。

标签: perl


【解决方案1】:

这是使用Time::Piece 的解决方案。我使用 Inline::Files 来模拟这两个文件。你需要打开你的日志文件,比如

my $logfile1 = "catalina.out";
my $logfile2 = "access_log";


open my $log1_fh, '<', $logfile1 or die $1;
open my $log2_fh, '<', $logfile2 or die $1;

程序看起来像这样,它给了我我认为你想要的结果。

#!/usr/bin/perl
use strict;
use warnings;
use Inline::Files;
use Time::Piece;

my %data;

while (<FILE2>) {
    # get date_time
    my ($dt) = /^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d),/ or next;
    push @{ $data{$dt} }, $_;
}

my $format = '%d/%b/%Y:%H:%M:%S';

while (<FILE1>) {
    /\[(\S+)/;
    my $t = Time::Piece->strptime($1, $format)
        or die "Cannot parse $1. $!";

    my $dt = $t->strftime('%Y-%m-%d %H:%M:%S');

    s/^\S+ (?:- )+//;
    s/(?<=\[)[^\]]+/$dt/;
    push @{ $data{$dt} }, $_;
}

for my $dt (sort keys %data) {
    my $aref = $data{$dt};
    print for @$aref;   
}


__FILE1__
127.0.0.1 - - [29/Feb/2016:16:57:52 -0600] "GET /application/wcs/api/version?nodeRef=workspace://SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0 HTTP/1.1" 200 567
127.0.0.1 - - [29/Feb/2016:16:57:52 -0600] "GET /application/wcs/api/node/workspace/SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0/workflow-instances HTTP/1.1" 200 40
127.0.0.1 - - [29/Feb/2016:16:57:52 -0600] "GET /application/wcs/cisco/appId?userId=abcdefg&requestType=get HTTP/1.1" 200 45
173.37.239.93 - abcdefg [29/Feb/2016:16:57:52 -0600] "GET /share/page/site/nextgen-edcs/document-details?nodeRef=workspace://SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0 HTTP/1.1" 200 124492
173.37.239.93 - abcdefg [29/Feb/2016:16:57:53 -0600] "GET /share/service/messages_69bcdfdb058bb873ff49cc2a10c958b7.js?locale=en_US HTTP/1.1" 200 81698
173.37.239.93 - abcdefg [29/Feb/2016:16:57:53 -0600] "GET /share/res/yui/history/history_543b42a00a378f4d4b6e70c81d915b0a.js HTTP/1.1" 200 5781
__FILE2__
2016-02-12 08:16:03,630  WARN  [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] Cluster is inactive but put(k,v) was called for cache HazelcastSimpleCache[cacheName=cache.readersSharedCache]
2016-02-12 08:16:03,630  WARN  [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] Cluster is inactive but get(key) was called for cache HazelcastSimpleCache[cacheName=cache.readersSharedCache], key=AclEntity[ ID=1893033, version=55, aclId=16cf5bc3-27d0-4d50-a93d-3bee1ddd112e, isLatest=true, aclVersion=1, inherits=true, inheritsFrom=1889292, type=1, inheritedAcl=1893034, isVersioned=false, requiresVersion=false, aclChangeSet=1451473]
2016-02-12 08:16:03,630  WARN  [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] Cluster is inactive but put(k,v) was called for cache HazelcastSimpleCache[cacheName=cache.readersSharedCache]

我使用哈希 %data 来存储这些行。关键是转换后的日期,所以稍后在程序中,您可以按排序顺序打印它们。

这个程序的输出是:

2016-02-12 08:16:03,630  WARN  [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] Cluster is inactive but put(k,v) was called for cache HazelcastSimpleCache[cacheName=cache.readersSharedCache]
2016-02-12 08:16:03,630  WARN  [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] Cluster is inactive but get(key) was called for cache HazelcastSimpleCache[cacheName=cache.readersSharedCache], key=AclEntity[ ID=1893033, version=55, aclId=16cf5bc3-27d0-4d50-a93d-3bee1ddd112e, isLatest=true, aclVersion=1, inherits=true, inheritsFrom=1889292, type=1, inheritedAcl=1893034, isVersioned=false, requiresVersion=false, aclChangeSet=1451473]
2016-02-12 08:16:03,630  WARN  [cluster.cache.HazelcastSimpleCache] [http-bio-8443-exec-212] Cluster is inactive but put(k,v) was called for cache HazelcastSimpleCache[cacheName=cache.readersSharedCache]
[2016-02-29 16:57:52] "GET /application/wcs/api/version?nodeRef=workspace://SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0 HTTP/1.1" 200 567
[2016-02-29 16:57:52] "GET /application/wcs/api/node/workspace/SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0/workflow-instances HTTP/1.1" 200 40
[2016-02-29 16:57:52] "GET /application/wcs/cisco/appId?userId=abcdefg&requestType=get HTTP/1.1" 200 45
abcdefg [2016-02-29 16:57:52] "GET /share/page/site/nextgen-edcs/document-details?nodeRef=workspace://SpacesStore/ecd62cfa-fd19-4d6b-b45d-14f0e5b92cf0 HTTP/1.1" 200 124492
abcdefg [2016-02-29 16:57:53] "GET /share/service/messages_69bcdfdb058bb873ff49cc2a10c958b7.js?locale=en_US HTTP/1.1" 200 81698
abcdefg [2016-02-29 16:57:53] "GET /share/res/yui/history/history_543b42a00a378f4d4b6e70c81d915b0a.js HTTP/1.1" 200 5781

【讨论】:

    【解决方案2】:

    虽然我不会为您编写脚本,但一般脚本应如下所示:

    use strict;
    use warnings;
    use DateTime::Format::Strptime;
    
    sub firstFileLine {
        # parse line as needed, and return a hash reference with 2 keys:
        #   1. `line`: the contents of the line, possibly edited 
        #   2. `ts`: the UTC unix timestamp, via the DateTime::Format::Strptime module
    }
    
    sub secondFileLine {
        # similar to `firstFileLine`, return a hash reference
    }
    
    my @firstLines = map { firstFileLine($_) } <FILE1>;
    my @secondLines = map { secondFileLine($_) } <FILE2>;
    
    my @sorted = map { $_->{line} } sort {$a->{ts} <=> $b->{ts}} (@firstLines, @secondLines);
    

    阅读DateTime::Format::Strptimemapsort 上的文档。您很幸运,Perl 是目前记录最好的语言之一,充分利用这一事实!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 2011-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多