bldsystemtools/commonbldutils/EventLogReader.pl
branchRCL_3
changeset 5 d90029decf65
parent 4 a9d4531388d0
child 6 5e522efbae7b
equal deleted inserted replaced
4:a9d4531388d0 5:d90029decf65
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 #!perl -w
       
    17 # This script reads data from specified Windows Event Logs and writes the information to a file
       
    18 # Output is ScanLog-compatible. First this script establishes a time range by reading the specified Build Log.
       
    19 # For info. on Win32::EventLog, see "Win32 Perl Programming" Page 171 et seq.
       
    20 use FindBin;
       
    21 use Sys::Hostname;
       
    22 use Win32;
       
    23 use Win32::EventLog;
       
    24 use Getopt::Long;
       
    25 use strict;
       
    26 # For Date calculations
       
    27 {
       
    28 no warnings;
       
    29 use lib "$FindBin::Bin/../buildsystemtools/lib"; # For running in source
       
    30 }
       
    31 use Date::Manip;
       
    32 
       
    33 # Set TimeZone because Date:Manip needs it set and then tell it to IGNORE the TimeZone
       
    34 &Date_Init("TZ=GMT","ConvTZ=IGNORE");
       
    35 
       
    36 # Check if HiRes Timer is available
       
    37 my $gHiResTimer = 0; #Flag - TRUE if HiRes Timer module available
       
    38 if (eval "require Time::HiRes;") {
       
    39   $gHiResTimer = 1;
       
    40 } else {
       
    41   print "Cannot load HiResTimer Module\n";
       
    42 }
       
    43 
       
    44 # Capture the name of this script for Help display etc.
       
    45 $0 =~ m/([^\\]+?)$/;
       
    46 my $gThisFile = $1;
       
    47 # Process command line
       
    48 
       
    49 my ($gComputer, $gBuildLogstart, $gBuildLogend, $gOutLogFile, @gEventSourcesUser) = ProcessCommandLine();
       
    50 $gComputer = (defined $gComputer)? uc $gComputer: hostname();
       
    51 
       
    52 # Open logfile, if specified
       
    53 my $gOutLogHandle = \*OUTLOGFILE;
       
    54 if (defined $gOutLogFile)
       
    55 {
       
    56     open ($gOutLogHandle, ">$gOutLogFile") or die "Failed to open $gOutLogFile";
       
    57     my $iTime = gmtime(time);
       
    58     PrintStageStart(0,"Windows Event Log Extracts",$gThisFile);
       
    59     print "Logfile: $gOutLogFile  Opened: $iTime\n";
       
    60     print $gOutLogHandle "Output file: $gOutLogFile  Opened: $iTime\n";
       
    61 }
       
    62 else
       
    63 {
       
    64     $gOutLogHandle = \*STDOUT;
       
    65     PrintStageStart(0,"Windows Event Log Extracts",$gThisFile);     # Start logging Generic Info. as pseudo Build Stage
       
    66     print "Logging to STDOUT\n";
       
    67 }
       
    68 print $gOutLogHandle "Data extracted from Windows Event Logs for Computer: $gComputer\n";
       
    69 
       
    70 # Establish time range. Get build start  time from specified Build Log file.
       
    71 unless (defined $gBuildLogstart)
       
    72 {
       
    73     my $iMsg = "No Build Log specified";
       
    74     print $gOutLogHandle "ERROR: $iMsg\n";
       
    75     PrintStageEnd(0);     # Stop logging Generic Info.
       
    76     Usage("$iMsg");
       
    77 }
       
    78 
       
    79 unless (defined $gBuildLogend)
       
    80 {
       
    81     my $iMsg = "No Build Log specified";
       
    82     print $gOutLogHandle "ERROR: $iMsg\n";
       
    83     PrintStageEnd(0);     # Stop logging Generic Info.
       
    84     Usage("$iMsg");
       
    85 }
       
    86 
       
    87 
       
    88 my ($gStartSecs, $gStopSecs) = GetTimeRange($gBuildLogstart, $gBuildLogend);
       
    89 
       
    90 unless (defined $gStartSecs)
       
    91 {
       
    92     my $iMsg = "Invalid Build Log: $gBuildLogstart";
       
    93     print $gOutLogHandle "ERROR: $iMsg\n";
       
    94     PrintStageEnd(0);          # Stop logging Generic Info.
       
    95     Usage("$iMsg");
       
    96 }
       
    97 
       
    98 # Establish time range. Get build  end time from specified Build Log file.
       
    99 # Determine which Event Logs are to be read. Default is "All three". Specifying one only is really a debug convenience.
       
   100 my @gEventSourcesDefault = ('Application','Security','System');
       
   101 my @gEventSources;
       
   102 if (@gEventSourcesUser)  # Event Log(s) specified by user.
       
   103 {
       
   104     foreach my $iSrcU (@gEventSourcesUser)
       
   105     {
       
   106         my $iOKFlag = 0;
       
   107         foreach my $iSrcD (@gEventSourcesDefault)
       
   108         {
       
   109             if (lc $iSrcU eq lc $iSrcD)
       
   110             {
       
   111                 push (@gEventSources, $iSrcD);
       
   112                 $iOKFlag = 1;
       
   113                 last;
       
   114             }
       
   115         }
       
   116         unless ($iOKFlag)
       
   117         {
       
   118             my $iMsg = "Invalid Event Log Filename: $iSrcU";
       
   119             print $gOutLogHandle "ERROR: $iMsg\n";
       
   120             PrintStageEnd(0);     # Stop logging Generic Info.
       
   121             Usage("$iMsg");
       
   122         }
       
   123     }   # End foreach my $iSrcU (@gEventSourcesUser)
       
   124 
       
   125 }
       
   126 else    # Default to "All logs"
       
   127 {
       
   128     @gEventSources = @gEventSourcesDefault;
       
   129 }
       
   130 
       
   131 PrintStageEnd(0);     # Stop logging Generic Info.
       
   132 
       
   133 # Finally read the required Event Log(s)
       
   134 $Win32::EventLog::GetMessageText = 1;   # Ensure that we get the message content from each Event Log entry.
       
   135 for (my $iIndx = 0; $iIndx < @gEventSources; )
       
   136 {
       
   137     my $iEventSource=$gEventSources[$iIndx];
       
   138     ++$iIndx;
       
   139     print "Reading Event Log: $iEventSource\n";
       
   140     ReadEventLog ($iIndx,$iEventSource);
       
   141 }
       
   142 
       
   143 close OUTLOGFILE;
       
   144 exit (0);
       
   145 
       
   146 # ReadEventLog
       
   147 #
       
   148 # Read from one Event Log and output to supplied logfile handle.
       
   149 #
       
   150 # Input: Stage Number, Event Log Name
       
   151 #
       
   152 # Output: ScanLog-compatible data to log file
       
   153 #
       
   154 sub ReadEventLog
       
   155 {
       
   156     my $iStage = shift;         # Stage number.
       
   157     my $iEventSource = shift;   # Name of Event Log file.
       
   158     # First argument to "new Win32::EventLog()" may be "Application", "Security" or "System";
       
   159     my $iTotalEvents;
       
   160     my $iSeparator = "------------------------------------------------------------\n";
       
   161     PrintStageStart($iStage,"Windows $iEventSource Event Log Extracts",$gThisFile);
       
   162 
       
   163     my $iEventObject = new Win32::EventLog($iEventSource, $gComputer);
       
   164 
       
   165     unless ($iEventObject)
       
   166     {
       
   167         print $gOutLogHandle  "ERROR: Failed to open Event Log: $iEventSource\n";
       
   168         PrintStageEnd($iStage);
       
   169         return;
       
   170     }
       
   171 
       
   172     unless ($iEventObject->GetNumber($iTotalEvents))
       
   173     {
       
   174         print $gOutLogHandle  "ERROR: Cannot read Event Log: $iEventSource\n";
       
   175         PrintStageEnd($iStage);
       
   176         return;
       
   177     }
       
   178 
       
   179     unless ($iTotalEvents)    # Check number of events in log.
       
   180     {
       
   181         print $gOutLogHandle "No event recorded in $iEventSource Log.\n";
       
   182     }
       
   183     else
       
   184     {
       
   185         # Reading Flags: EVENTLOG_FORWARDS_READ, EVENTLOG_BACKWARDS_READ, EVENTLOG_SEQUENTIAL_READ, EVENTLOG_SEEK_READ
       
   186         my $iFlag = EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
       
   187         my $iRecNum = 0;     # Ignored unless $iFlag == EVENTLOG_SEEK_READ
       
   188         my $iStopFlag = 0;
       
   189         my $count = 0;
       
   190         while (!$iStopFlag)
       
   191         {
       
   192             my %iHash;
       
   193             unless ($iEventObject->Read($iFlag, $iRecNum, \%iHash))
       
   194             {
       
   195                 $iStopFlag = 1;
       
   196             }
       
   197             else    # Successful "read"
       
   198             {
       
   199             my $iEventTime = $iHash{TimeGenerated};
       
   200             if ($iEventTime > $gStopSecs)
       
   201                 { next; }
       
   202             if ($iEventTime < $gStartSecs)
       
   203                 { last; }
       
   204             ++$count;
       
   205             print $gOutLogHandle $iSeparator;
       
   206             # Supported Event Types: EVENTLOG_ERROR_TYPE, EVENTLOG_WARNING_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_AUDIT_SUCCESS, EVENTLOG_AUDIT_FAILURE
       
   207             my $iTxt;
       
   208             if ($iHash{EventType} == EVENTLOG_ERROR_TYPE)
       
   209                 {$iTxt = 'Error'; }
       
   210             elsif ($iHash{EventType} == EVENTLOG_WARNING_TYPE)
       
   211                 {$iTxt = 'Warning'; }
       
   212             elsif ($iHash{EventType} == EVENTLOG_INFORMATION_TYPE)
       
   213                 {$iTxt = 'Information'; }
       
   214             elsif ($iHash{EventType} == EVENTLOG_AUDIT_SUCCESS)
       
   215                 {$iTxt = 'Audit Success'; }
       
   216             elsif ($iHash{EventType} == EVENTLOG_AUDIT_FAILURE)
       
   217                 {$iTxt = 'Audit Failure'; }
       
   218             else
       
   219                 {$iTxt = "*unknown* [$iHash{EventType}]"; }
       
   220             print $gOutLogHandle "EventType: $iTxt  Source: $iHash{Source}  RecNum: $iHash{RecordNumber}\n";
       
   221             my $iTimeStr = gmtime($iHash{TimeGenerated});
       
   222             print $gOutLogHandle "TimeGen:   $iHash{TimeGenerated} ($iTimeStr)\n";
       
   223             print $gOutLogHandle "Computer:  $iHash{Computer}\n";
       
   224             print $gOutLogHandle "User:      $iHash{User}\n";
       
   225             print $gOutLogHandle "EventID:   $iHash{EventID}\n";
       
   226             print $gOutLogHandle "Category:  $iHash{Category}\n";
       
   227             $iTxt = (defined $iHash{Message})? $iHash{Message}: '*none*';
       
   228             print $gOutLogHandle "Message:   $iTxt\n";
       
   229             $iTxt = ($iHash{Strings})? $iHash{Strings}: '*none*';
       
   230             print $gOutLogHandle "Strings:   $iTxt\n";
       
   231             }
       
   232         }   # End while (!$iStopFlag)
       
   233         print $gOutLogHandle $iSeparator;
       
   234         print $gOutLogHandle "Events in specified time range = $count    Events in file = $iTotalEvents\n";
       
   235     }   # End unless ($iTotalEvents)
       
   236     PrintStageEnd($iStage);
       
   237 }
       
   238 
       
   239 # PrintStageStart
       
   240 #
       
   241 # Print to log file the ScanLog-Compatible lines to start a stage
       
   242 #
       
   243 # Input: Stage, Component Name [,Command Name]
       
   244 #
       
   245 # Output: Start time etc.
       
   246 #
       
   247 sub PrintStageStart
       
   248 {
       
   249     my $iStage = shift;         # Stage number.
       
   250     my $iComponent = shift;     # e.g. Name of Event Log file.
       
   251     my $iCommand = shift;
       
   252     my $iTime = gmtime(time);
       
   253     print $gOutLogHandle "===-------------------------------------------------\n";
       
   254     print $gOutLogHandle "=== Stage=$iStage\n";
       
   255     print $gOutLogHandle "===-------------------------------------------------\n";
       
   256     print $gOutLogHandle "=== Stage=$iStage started $iTime\n";
       
   257     print $gOutLogHandle "=== Stage=$iStage == $iComponent\n";
       
   258     if (defined $iCommand)
       
   259     {
       
   260         print $gOutLogHandle "-- $iCommand\n";
       
   261     }
       
   262     print $gOutLogHandle "++ Started at $iTime\n";
       
   263 
       
   264     if ($gHiResTimer)
       
   265     {
       
   266         print $gOutLogHandle "+++ HiRes Start ".Time::HiRes::time()."\n";
       
   267     }
       
   268 }
       
   269 
       
   270 # PrintStageEnd
       
   271 #
       
   272 # Print to log file the ScanLog-Compatible lines to end a stage
       
   273 #
       
   274 # Input: Stage
       
   275 #
       
   276 # Output: End time etc.
       
   277 #
       
   278 sub PrintStageEnd
       
   279 {
       
   280     my $iStage = shift;         # Stage number.
       
   281     if ($gHiResTimer)
       
   282     {
       
   283         print $gOutLogHandle "+++ HiRes End ".Time::HiRes::time()."\n";
       
   284     }
       
   285     my $iTime = gmtime(time);
       
   286     print $gOutLogHandle "++ Finished at $iTime\n";
       
   287     print $gOutLogHandle "=== Stage=$iStage finished $iTime\n";
       
   288 }
       
   289 
       
   290 #sub GetTimeRange
       
   291 #
       
   292 # Establish start and end times for overall build
       
   293 # Typical start line: === Stage=1 started Mon Oct  4 15:55:31 2004
       
   294 # Typical end line:   === Stage=115 finished Tue Oct  5 01:47:37 2004
       
   295 #
       
   296 # Input: Name of Build Log File to read
       
   297 #
       
   298 # Output: Summary timing info to log file
       
   299 #
       
   300 # Return: Start/End times in seconds
       
   301 #
       
   302 sub GetTimeRange
       
   303 {
       
   304 
       
   305     my ($iBuildLogstart,$iBuildLogend) = @_;
       
   306 
       
   307     my ($iStartTime, $iStopTime);
       
   308     
       
   309 # $iStartTime Time read from $iBuildLogstart
       
   310     unless (open (INLOGFILE, "<$iBuildLogstart"))
       
   311     {
       
   312         print $gOutLogHandle "Failed to open input file: $iBuildLogstart\n";
       
   313         return undef, undef;
       
   314     }
       
   315     while(my $iLine = <INLOGFILE>)
       
   316     {
       
   317         chomp $iLine;
       
   318         unless (defined $iStartTime)
       
   319         {
       
   320             if ($iLine =~ m/^===\s+Stage=\S*\s+started\s+(.+)/)
       
   321                 { $iStartTime = $1; last; }
       
   322         }
       
   323     }
       
   324     close INLOGFILE;
       
   325 
       
   326 # $iStopTime Time read from $iBuildLogend
       
   327 
       
   328     unless (open (OUTFILE, "<$iBuildLogend"))
       
   329     {
       
   330         print $gOutLogHandle "Failed to open input file: $iBuildLogend\n";
       
   331         return undef, undef;
       
   332     }
       
   333     while(my $iLine = <OUTFILE>)
       
   334     {
       
   335         chomp $iLine;
       
   336         if (($iLine =~ m/^===\s(.*\s)?finished\s+(.+)/))
       
   337             { $iStopTime = $2; }
       
   338     }
       
   339     close OUTFILE;
       
   340 
       
   341     my $iDate = ParseDateString($iStartTime);
       
   342     my $iStartSecs = UnixDate($iDate,"%s");
       
   343 
       
   344     print $gOutLogHandle "Time range taken for Build start time from Build Log: $iBuildLogstart\n";
       
   345     print $gOutLogHandle "Earliest Event: $iStartTime\n\n";
       
   346 
       
   347     $iDate = ParseDateString($iStopTime);
       
   348     my $iStopSecs = UnixDate($iDate,"%s");
       
   349 
       
   350     print $gOutLogHandle "Time range taken for Build end time from Build Log: $iBuildLogend\n";
       
   351     print $gOutLogHandle "Latest Event: $iStopTime\n\n";
       
   352 
       
   353     my $iSecs = $iStopSecs - $iStartSecs;
       
   354     my $iMins = int ($iSecs/60);
       
   355     $iSecs %= 60;
       
   356     my $iHours = int($iMins/60);
       
   357     $iMins %= 60;
       
   358     printf $gOutLogHandle "--Time Range between the build START and FINISH:<< %d:%02d:%02d>>\n\n",$iHours,$iMins,$iSecs;
       
   359 
       
   360     return $iStartSecs, $iStopSecs;
       
   361 }
       
   362 
       
   363 
       
   364 # ProcessCommandLine
       
   365 #
       
   366 # Process Commandline. On error, call Usage()
       
   367 #
       
   368 # Input: None
       
   369 #
       
   370 # Return: Parameters as strings.
       
   371 #
       
   372 sub ProcessCommandLine
       
   373 {
       
   374 
       
   375   my ($iHelp, $iComputer, $iBuildLogstart, $iBuildLogend , $iOutFile, @iEventSources);
       
   376   GetOptions('h' => \$iHelp, 'c=s' => \$iComputer, 'l=s' => \$iBuildLogstart,'k=s'=> \$iBuildLogend, 'o=s' => \$iOutFile, 's=s' => \@iEventSources);
       
   377 
       
   378   if ($iHelp)
       
   379   {
       
   380     Usage();
       
   381   }
       
   382   else
       
   383   {
       
   384     return ($iComputer, $iBuildLogstart, $iBuildLogend,$iOutFile, @iEventSources);
       
   385   }
       
   386 }
       
   387 
       
   388 
       
   389 # Usage: Display Help and exits script.
       
   390 #
       
   391 # Input: Error message, if any
       
   392 #
       
   393 # Output: Usage information.
       
   394 #
       
   395 # Return: Never returns. Exits with non-zero errorlevel
       
   396 #
       
   397 sub Usage
       
   398 {
       
   399     if (@_)
       
   400     {
       
   401         print "\nERROR: @_\n";
       
   402     }
       
   403 
       
   404     print <<USAGE_EOF;
       
   405 
       
   406     $gThisFile:
       
   407       Reads the Windows Event Logs for the specified computer.
       
   408       The time range is established by reading the specified Build Log.
       
   409       ScanLog-compatible output is written to specified logfile.
       
   410 
       
   411     Usage: $gThisFile parameters [options]
       
   412 
       
   413     Parameters:
       
   414       -l  Build start Log file
       
   415       -k  Build End Log file
       
   416 
       
   417     Options:
       
   418       -h  Help
       
   419       -c  Computer name (defaults to local PC)
       
   420       -o  Logfile for output (defaults to STDOUT)
       
   421       -s  Event Log Source (defaults to "All")
       
   422           (Supported logs: "Application", "Security" or "System")
       
   423 
       
   424 
       
   425 USAGE_EOF
       
   426 
       
   427     exit 1;
       
   428 }
       
   429 
       
   430 __END__