# DBalert.def: Analyzes alert.log # $Id: DBalert.def,v 1.8 2008/02/25 17:32:54 mschenke Exp $ # ARCS: $Header: /home/cvs/repository/RDA_4/src/scripting/lib/modules/DBalert.def,v 1.8 2008/02/25 17:32:54 mschenke Exp $ # # Change History # 20080225 MSC Change the copyright notice. =head1 NAME DBalert - Analyzes alert.log =head1 DESCRIPTION This module analyzes the alert.log file and produces an analysis summary. =cut # Make the module persistent and share macros keep $KEEP_BLOCK,@SHARE_MACROS var @SHARE_MACROS = ('analyze_alert_pre11G') # Macro for reading the alert.log pre 11G macro analyze_alert_pre11G {var ($fil) = @arg var %sta = ('fil',$fil) var (@cmd,@err,@swt,@trc,%err) = () debug ' Inside DBalert module, analyzing the alert.log data (can take time)' if createBuffer('ALS','R',$fil) {# Define parsing macros macro parse_cmd {var (\%sta,\@cmd,$lin) = @arg var @cmd = (@cmd,concat($sta{'cur'},'|',$lin)) return -1 } macro parse_cnt {var (\%sta,$key) = @arg incr $sta{$key} return -1 } macro parse_err {var (\%sta,\@err,\%err,$lin) = @arg if !$sta{'err'} {var $sta{'err'} = true var @err = (@err,$sta{'cur'}) } var @err = (@err,$lin) if match($lin,'^((ORA|PLS)-\d+)') {var ($err) = (last) incr $err{$err} } return -1 } macro parse_str {var (\%sta,\@err,\@trc) = @arg incr $sta{'str'} # Add the event in the error summary if !$sta{'err'} {var $sta{'err'} = true var @err = (@err,$sta{'cur'}) } var @err = (@err,'Instance was restarted') # Add the event in the trace summary if !$sta{'trc'} {var $sta{'trc'} = true var @trc = (@trc,$sta{'cur'}) } var @trc = (@trc,'Instance was restarted') return -1 } macro parse_swt {var (\%sta,\@swt,$lin) = @arg incr $sta{'swt'} var @swt = (@swt,$sta{'cur'}) return -1 } macro parse_trc {var (\%sta,\@trc,$lin) = @arg if !$sta{'trc'} {var $sta{'trc'} = true var @trc = (@trc,$sta{'cur'}) } var @trc = (@trc,$lin) return -1 } macro parse_tsp {var (\%sta,$lin) = @arg var $sta{'beg'} = nvl($sta{'beg'},$lin) var $sta{'cur'} = $lin var $sta{'end'} = $lin var $sta{'err'} = false var $sta{'trc'} = false return -1 } # Parse the alert.log call parseVar($lin) call parsePattern('TOP',\ '^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)',\ parse_tsp(\%sta,$lin),\ 'Starting ORACLE instance',\ parse_str(\%sta,\@err,\@trc),\ '^Thread .* advanced to log sequence',\ parse_swt(\%sta,\@swt,$lin),\ '^Checkpoint not complete',\ parse_cnt(\%sta,'chk'),\ '^Thread .* cannot allocate new log',\ parse_cnt(\%sta,'non'),\ '^ALTER SYSTEM',\ parse_cmd(\%sta,\@cmd,$lin),\ '^(ORA-|PLS-|SVR4 Error:|Additional information:|Linux Error:|\ IBM AIX RISC System\/6000 Error:|O\/S-Error:|OSD-)',\ parse_err(\%sta,\@err,\%err,$lin),\ '^(Errors in file|Details in trace file)',\ parse_trc(\%sta,\@trc,$lin)) call parse('ALS') var $sta{'lin'} = inputLine('ALS') # Report the analysis call write_alert_summary(\%sta,\%err,\@cmd,\@err,\@swt,\@trc) } } # Macro for writing the alert.log summary macro write_alert_summary {var (\%sta,\%err,\@cmd,\@err,\@swt,\@trc) = @arg import $TOP,$TOC # Define a macro to report events, while merging duplicates macro write_nodup {# Define a macro to report an event macro write_event {var ($beg,$end,$cnt,$evt) = @arg if $cnt {incr $cnt write '|',replace($beg,'\s',' ',true),' |',\ replace($end,'\s',' ',true),' | ',$cnt,'|',$evt,' |' } else write '|',replace($beg,'\s',' ',true),' |||',$evt,' |' } # Merge duplicates var ($cnt,$old,$new) = (0) loop $lin (@arg,'Mon') {if match($lin,'^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)') # Compare event list {if compare('eq',$new,$old) {incr $cnt var ($end,$new) = ($lst) } else {if $old call write_event($beg,$end,$cnt,$old) var ($old,$beg,$cnt,$new) = ($new,$lst,0) } var $lst = $lin } else # Add to the new list until a time stamp is found var $new = join('%BR%',$new,$lin) } # Treat the remaining occurrences if $old call write_event($beg,$end,$cnt,$old) } # Define a macro to report the last 10 shortest redo log switches macro write_redo {var ($prv,@tbl) = @arg var ($cnt,$max,$nul,@tb_nul,%tb_dur,%tb_rec) = (10) import $TOP # Get the begin time var (undef,$mon,$day,$hur,$min,$sec,$yer) = split('\s+|:',$prv) var $beg = mktime($sec,$min,$hur,$day,$mon,$yer) loop $cur (@tbl) {# Determine the redo log switch time interval var (undef,$mon,$day,$hur,$min,$sec,$yer) = split('\s+|:',$cur) var $end = mktime($sec,$min,$hur,$day,$mon,$yer) var $dur = difftime($end,$beg) # Treat the switch if $dur {# Keep the 10 shortest ones var $rec = concat('|',$cur,' |',$prv,' | ',$dur,'|') if $cnt {decr $cnt var $key = gmtime('%Y%m%d%H%M%S',$end) var $tb_dur{$key} = $dur var $tb_rec{$key} = $rec var $max = max($dur,$max) } elsif expr('<=',$dur,$max) {var ($del,$lst) = keys(%tb_dur,'ND') delete $tb_dur{$del},$tb_rec{$del} var $key = gmtime('%Y%m%d%H%M%S',$end) var $tb_dur{$key} = $dur var $tb_rec{$key} = $rec var $max = max($dur,$tb_dur{$lst}) } # Keep the switch time var $prv = $cur var $beg = $end } else {# Store time stamps of null duration if !compare('eq',$nul,$cur) var ($nul,@tb_nul) = ($cur,@tb_nul,$cur) } } # Report the shortest durations loop $tim (keys(%tb_dur,'NA')) write $tb_rec{$tim} # Report null durations if $nul {if hasOutput(true) write $TOP write '---+ Times for Redo Log Switches of 0 Seconds' write '%COL5%',join('%BR%',@tb_nul),'%ENDCOL%' } } debug ' Inside DBalert module, reporting alert.log analysis results' write '---+!! Alert.log Analysis' write '---## For ',$sta{'fil'} write $TOC write '---+ Processing Totals' write '|*Total alert.log records(lines) read*| ',nvl($sta{'lin'},0),'|' write '|*Start time*|',$sta{'beg'},' |' write '|*End time*|',$sta{'end'},' |' write '|*Total instance startups encountered*| ',nvl($sta{'str'},0),'|' write '|*Total log switches found*| ',nvl($sta{'swt'},0),'|' write '|*Total ``Checkpoint not complete`` messages found*| ',\ nvl($sta{'chk'},0),'|' write '|*Total ``Cannot allocate new log`` messages found*| ',\ nvl($sta{'non'},0),'|' write $TOP if @swt {prefix {write '---+ 10 Shortest Redo Log Switch Times' write '|*Event Time Stamp*|* Previous Event Time Stamp*| \ *Duration(seconds)*|' } call write_redo(@swt) if hasOutput(true) write $TOP } prefix {write '---+ Alter System Commands' write '|*Time Stamp*|*Command*|' } loop $lin (@cmd) write '|',$lin,'|' if hasOutput(true) write $TOP prefix {write '---+ Counts by Error' write '|*Error*| *Count*|*Error*| *Count*|*Error*| *Count*|' } var @tbl = keys(%err) while scalar(@tbl) {var ($key1,$key2,$key3,@tbl) = @tbl write '|',$key1,' | ',\ $err{$key1},'|',\ $key2,' | ',\ $err{$key2},'|',\ $key3,' | ',\ $err{$key3},'|' } if hasOutput(true) write $TOP prefix {write '---+ Error Summary' write '|*First Occurrence*|*Last Occurrence*|*Count*|*Event*|' } call write_nodup(@err) if hasOutput(true) write $TOP prefix {write '---+ Trace Summary' write '|*First Occurrence*|*Last Occurrence*|*Count*|*Event*|' } call write_nodup(@trc) if hasOutput(true) write $TOP } =begin credits =over 10 =item RDA 4.8: Jeff Gregory, Anatoli Karol, Michel Villette. =back =end credits =head1 COPYRIGHT NOTICE Copyright (c) 2002-2008, Oracle. All rights reserved. =head1 TRADEMARK NOTICE Oracle, JD Edwards, PeopleSoft, and Siebel are registered trademarks of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. =cut