在 mrskew 中,我可以从 tim 计算人类可读的时间戳吗?

问题描述

我正在使用 mrskewMethod-R 来分析 Oracle sql 跟踪文件

我想列出所有类似于calls.rc输出数据库调用
但我会打印一个人类可读的日期格式,而不是 $tim 的值。

原始数据(最少混淆):

*** 2020-11-26 10:06:01.867
*** SESSION ID:(1391.49878) 2020-11-26 10:06:01.867
*** CLIENT ID:() 2020-11-26 10:06:01.867
*** SERVICE NAME:(SYS$USERS) 2020-11-26 10:06:01.867
*** MODULE NAME:(JDBC Thin Client) 2020-11-26 10:06:01.867
*** CLIENT DRIVER:(jdbcthin : 12.2.0.1.0) 2020-11-26 10:06:01.867
*** ACTION NAME:() 2020-11-26 10:06:01.867
...
WAIT #0: nam='sql*Net message from client' ela= 491 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=12568091328841
=====================
PARSING IN CURSOR #18446744071522016088 len=71 dep=0 uid=88 oct=7 lid=88 tim=12568091329190 hv=2304270232 ad='61e4d11e0' sqlid='5kpbj024phrws'
/*Begin.Work*/
SELECT ...
END OF STMT
PARSE #18446744071522016088:c=147,e=148,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=957996380,tim=12568091329190
...
EXEC #18446744071522016088:c=683,e=11406,cr=2,cu=11,r=1,tim=12568091341788
CLOSE #18446744071522016088:c=27,e=27,type=1,tim=12568091343665
XCTEND rlbk=0,rd_only=0,tim=12568091343769

当前输出(为了可读性而压缩):

          END-TIM       LINE       sql_ID CALL-NAME STATEMENT-TEXT
-----------------------------------------------------------------------------
  12568091.341788         36 5kpbj024phrws EXEC     /*Begin.Work*/ SELECT ...
  12568091.343769         42               XCTEND    

预期输出(请不要批评我不正确的亚秒计算):

                  END-TIME LINE        sql_ID CALL-NAME STATEMENT-TEXT  
-----------------------------------------------------------------------
2020-11-26 10:06:01.341788   36 5kpbj024phrws EXEC     /*Begin.Work*/ SELECT ...
2020-11-26 10:06:01.343769   42               XCTEND      

我假设我可以使用 POSIX:strftime 正确格式化时间戳,但我需要一种方法来从跟踪文件开头的时间戳生成纪元时间戳

*** 2020-11-26 10:06:01.867

然后是每个 $tim 相对于跟踪文件开头的偏移量。
我希望 methodr 工具集可以提供这个。我应该更容易解释,何时(以人类可读的形式)哪个活动开始。

解决方法

从字符串日期生成纪元秒数非常简单。 Time::Local 有功能可以做到这一点。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Time::Local 'timelocal_posix';

my $date = '2020-11-26 10:06:01.867';

# Split the date apart
my ($yr,$mon,$day,$hr,$min,$sec,$micro) = split /[- :.]/,$date;

# Note necessary adjustments to month and year
say timelocal_posix($sec,$mon - 1,$yr - 1900);
,

在@DaveCross 和@CaryMillsap 评论的帮助下,我的处理现在是:

  1. 从跟踪文件创建一个类似于

    的中间文件
    *** 2020-11-26 10:06:01.867
    
          END-TIM       LINE       SQL_ID CALL-NAME STATEMENT-TEXT
    -----------------------------------------------------------------------------
    XCTEND tim=12568091341788 e=2 dep=0          36 5kpbj024phrws EXEC     /*Begin.Work*/ SELECT ..
    XCTEND tim=12568091343769 e=1 dep=0          42               XCTEND    
    

    在calls.rc中使用

    sprintf("XCTEND tim=%-20d e=%-5d dep=0 %10d %10d %10d  %13s %-40.40s %-.46s",$tim*1000000,$line,($e+$ela)*1000000,$parse_id,$exec_id,$sqlid,"· "x$dep.$name.(scalar(@bind)?"(".join(",",@bind).")":""),"· "x$dep.$sql)
    
  2. 修改结果以使其位于顶部

    *** 2020-11-26 10:06:01.867
    
  3. mrwhen

    处理这个文件
  4. 删除不需要的部分

     sed -E 's/XCTEND t.{37}//'  
    

更详细地记录在here中。