知识库

如何将 Neo4j 日志从基本 UTC 转换为本地时区

随着 Neo4j 3.3.1 的引入,可以通过实现 dbms.logs.timezone 参数来将 $NEO4J_HOME/logs/* 中的日期时间戳表示为 UTC 或 SYSTEM 时区。

然而,在之前的版本中,所有 Neo4j 日志的每一行都会以以下格式的日期/时间字符串开头

<YYYY-MM-DD HH24:MM:SS.MMM+0000>

例如

2016-12-01 15:51:00.222+0000 INFO  [o.n.k.i.DiagnosticsManager] --- INITIALIZED diagnostics START ---

其中上面的 +0000 表示日期/时间是以 UTC 格式表示的。当集群成员位于不同时区时,以 UTC 格式记录日志有助于分析。但是,当集群成员位于同一时区或您正在运行单个实例时,您可能希望以本地时区记录日志。有一项待处理的产品改进请求,旨在使日期/时间字符串可根据时区进行配置。

在缺少此功能的情况下,可以运行以下 Perl 脚本,将任何文件从 UTC 时区转换为运行该 perl 脚本的机器时区。

对于大多数 Unix 实现,要确定时区,如果运行

$ date

这将返回类似于以下内容的输出

Mon Jan 16 14:38:06 EST 2017

指示 EST 时区。

要将日志从 UTC 转换为 EST,请运行

$ ./utc.pl debug.log > debug.EST.log

要安装此脚本,请将以下行从此处复制到您的 linux 服务器上名为 utc.pl 的文件中。

#!/usr/bin/perl -w
use strict;
use Time::Local;  #needed for timegm()

my $file = $ARGV[0] or die "USAGE: $0 <filename>\n";

open(my $data, '<', $file) or die "Could not open '$file' $!\n";

while (my $line = <$data>) {
  # where a line might start as
  # 2017-01-11 23:22:28.372+0000 INFO ... .... ....
  chomp $line;
  # check to make sure the line begins with a YYYY-MM-DD HH
  if ( $line =~ /\d\d\d\d-\d\d-\d\d \d\d/ ) {
          my $newstring = UTC2LocalString($line);
          print "$newstring\n";
  }
  else {
      print "$line\n";
  }
}

sub UTC2LocalString
{
  # below attributed to Marshall at http://www.perlmonks.org/?node_id=873435
  my $t = shift;
  my ($datehour, $rest) = split(/:/,$t,2);
  #   $datehour will represent YYYY-MM-DD HH  (i.e. 2017-01-14 12)
  #   $rest represents the rest of the line after
  #   and this will reassemble and return $datehour (adjusted) + $rest
  my ($year, $month, $day, $hour) =
      $datehour =~ /(\d+)-(\d\d)-(\d\d)\s+(\d\d)/;

  #  proto: $time = timegm($sec,$min,$hour,$mday,$mon,$year);
  my $epoch = timegm (0,0,$hour,$day,$month-1,$year);

  #  proto: ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
  #          localtime(time);
  my ($lyear,$lmonth,$lday,$lhour,$isdst) =
            (localtime($epoch))[5,4,3,2,-1];

  $lyear += 1900;  # year is 1900 based
  $lmonth++;       # month number is zero based
  #print "isdst: $isdst\n"; #debug flag day-light-savings time
  return ( sprintf("%04d-%02d-%02d %02d:%s",
           $lyear,$lmonth,$lday,$lhour,$rest) );
}

通过运行以下命令使脚本可执行

$ chmod +x utc.pl

将脚本运行为

$ ./utc.pl <log file>

<log file> 替换为文件名。

使用 Neo4j 3.3,并且由于 PR 10127,可以通过参数 dbms.logs.timezone 配置时间戳时区。

© . All rights reserved.