Advertisement
Guest User

Untitled

a guest
Jul 3rd, 2017
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
SAS 17.11 KB | None | 0 0
  1. /*=============================================================================
  2. Program Name:         SCANLOG.SAS
  3. Purpose:              To automatically scan specified LOG file for
  4.                       ERROR/WARNING/NOTE information
  5. DataSets Used:        {None}
  6. DataSets Created:     FINDINGS
  7. Macro variables:      INFILE [Default from LOGCHECK macro]:  
  8.                              Actual LOG file to scan for ERROR/WARNING/NOTE
  9. Programmer:           Lawrence Heaton-Wright
  10. OS/SAS Vnum:          Windows NT / 8.2
  11. Date:                 29-Aug-2003
  12. Notes:                This macro can be run from interactive or batch SAS.
  13.                       This macro is called from LOGCHECK.
  14. Example:              
  15. --------------------------------------------------------------------------------
  16.  Modifications:
  17.  Programmer/Date:     Reason:
  18.  ----------------     -------
  19.  LHW / 29-JAN-2004    Exclude warnings about license expiry.
  20.  LHW / 14-JAN-2005    Added FILEINFO data set step. This will be used to create
  21.                       a summary of files scanned and which ones have issues in
  22.                       them [LOGCHECK macro].
  23.  LHW / 19-MAY-2005    Added "Compression was disabled" to exclude from WARNING
  24.                       messages regarding compression.
  25.  LHW / 24-AUG-2005    Adapt ERESINFO section to accomodate the standardised
  26.                       global directory structure LOG information.
  27.  LHW / 26-SEP-2005    To ensure that SCANLOG can still be used even on non-standard
  28.                       log files ensure that if log stype is non-standard
  29.                       (i.e. not QTHV or globalisation standard) then set this to
  30.                       THV as version 0.2 of SCANLOG worked like this for non-standard files.
  31.  LHW / 09-NOV-2005    Changed length of FILENAME from 132 characters to 200 to
  32.                       accomodate very long file names.
  33.                       Retain TYPE variable for correct scanning of ERES information.
  34. CP   / 07-NOV-2006    keep only notes needed for QSTR  
  35. ==============================================================================*/
  36.  
  37. %MACRO ScanLog (InFile=);
  38.     FILENAME LogFile "&InFile";
  39. %*-------------------------------------------------------------------------------*;
  40. %* Read in specified SAS log file - no check in place for confirming existence   *;
  41. %* of file [add later]. Flag lines from LOG which indicate a new page in the SAS *;
  42. %* log and therefore contain a page-throw character. These records to be deleted.*;
  43. %*-------------------------------------------------------------------------------*;
  44.     DATA _Log;
  45.         INFILE LogFile LRECL=200 TRUNCOVER;
  46.         INPUT @1 line $CHAR200.;
  47.         ATTRIB
  48.             ObsNo   LABEL="SAS data set observation number"
  49.         ;
  50.         RETAIN DeleteLine 0;
  51.         ObsNo=_n_;
  52.         IF INDEXW(Line,"The SAS System")>0 AND INDEXW(Line,"NOTE:")=0 THEN DO;
  53.             DeleteLine=ObsNo;
  54.             DelFlag=1;
  55.         END;
  56.         IF ObsNo=DeleteLine+1 THEN DO;
  57.             DelFlag=1;
  58.             DeleteLine=0;
  59.         END;
  60.     RUN;
  61. %*-------------------------------------------------------------------------------*;
  62. %* The format OBSNO is used to convert the number of observations [i.e. number   *;
  63. %* of lines in the log file] to the nearest 100, 1000, etc. This will be used to *;
  64. %* create LINENO for those log file records which are not part of the program    *;
  65. %* code, i.e. NOTEs, WARNINGs, etc.                                              *;
  66. %* Add indicator flags for standard user-defined LOG warning messages            *;
  67. * (i.e. DATA ISSUE:, STL ISSUE: DM ISSUE:).                                      *;
  68. %*-------------------------------------------------------------------------------*;
  69.     PROC FORMAT;
  70.         VALUE obsno
  71.              1-99="100"
  72.           100-999="1000"
  73.         1000-9999="10000"
  74.       10000-99999="100000"
  75.     100000-999999="1000000"
  76.             OTHER=_ERROR_;
  77.     RUN;
  78.  
  79.     DATA _Log (DROP=WarnTemp ErrorTemp type);
  80.         SET _Log (WHERE=(DelFlag NE 1)) NOBS=nobs;
  81.         ATTRIB
  82.             type        LABEL="Log message type [THV or GBL - Global]"
  83.             LineNo      LABEL="Program line number from LOG file"
  84.             Note        LABEL="LOG line gives NOTE message"
  85.             Warning     LABEL="LOG line gives WARNING message"
  86.             Error       LABEL="LOG line gives ERROR message"
  87.             DataIssue   LABEL="LOG line gives DATA ISSUE message"
  88.             STLIssue    LABEL="LOG line gives STL ISSUE message"
  89.             DMIssue     LABEL="LOG line gives DM ISSUE message"
  90.         ;
  91.         number_obs=nobs;
  92.         RETAIN LineNo ProcDataSets EresInfo Type 0;
  93. %*** Based on the number of observations in the LOGFILE dataset, i.e. number of records in log file ***;
  94. %*** Create an order variable for those log records without a line number ***;
  95.         denom=INPUT(PUT(nobs,obsno.),BEST.);;
  96.         _LineNo=SCAN(line,1," ");
  97.         SecondWord=SCAN(line,2," ");
  98. %*** Standard user-defined LOG messages are always 2 words ending in "ISSUE:" ***;
  99.         IF SecondWord="ISSUE:" THEN
  100.             _LineNo=TRIM(LEFT(_LineNo)) || " " || TRIM(LEFT(SecondWord));
  101.  
  102.         IF COMPRESS(Line)="-----Directory-----" THEN ProcDataSets=1;
  103.         IF Line="NOTE: PROCEDURE DATASETS used:" THEN ProcDataSets=0;
  104.         IF line IN ("USER INFORMATION:","*  USER & SYSTEM INFORMATION :") THEN EresInfo=1;
  105.         IF line EQ "USER INFORMATION:" THEN type='THV';
  106.         ELSE IF line EQ "*  USER & SYSTEM INFORMATION :" THEN type='GBL';
  107.         IF EresInfo=1 AND SUBSTR(line,1,10) IN ("----------","*---------") THEN EresInfo=0;
  108.         NonNum=0;
  109.         IF INDEXC(_LineNo,'1234567890') THEN DO x=1 TO 255 UNTIL (NonNum=1);
  110.             IF NOT (x=32 OR 48<=x<=57)AND INDEXC(_LineNo,BYTE(x))>0 THEN NonNum=1;
  111.         END;
  112.         IF SecondWord=:"+" THEN NonNum=1;
  113.         IF INDEXC(_LineNo,'1234567890') AND NonNum=0 AND ProcDataSets=0 AND SecondWord NE "at" THEN
  114.             LineNo=INPUT(_LineNo,BEST.);
  115.         ELSE LineNo=LineNo+(1/denom);
  116. %*** Create indicator flags for NOTEs, WARNINGs & ERRORs + standard user-defined messages ***;
  117.         ARRAY SearchVal[8] $11. _TEMPORARY_
  118.             ("NOTE:" "WARNING:" "ERROR:" "WARNING" "ERROR" "DATA ISSUE:" "STL ISSUE:" "DM ISSUE:");
  119.         ARRAY LogVar[*] Note Warning Error WarnTemp ErrorTemp DataIssue STLIssue DMIssue;
  120.         DO i=1 TO DIM(LogVar);
  121.             IF _LineNo=SearchVal[i] THEN LogVar[i]=1;
  122.         END;
  123.         IF WarnTemp=1 THEN Warning=1;
  124.         IF ErrorTemp=1 THEN Error=1;
  125.  
  126. %*** Checking for non-standard user-defined messages ***;
  127.         %IF &UMessage NE %THEN %DO;
  128.             ARRAY SearchUser[&UserM.] $%EVAL(&MaxUMLen.) _TEMPORARY_ (
  129.                 %DO um_i=1 %TO &UserM.;
  130.                     "&&Message&um_i."
  131.                 %END;
  132.                 );
  133.             ARRAY LogUser[&UserM.];
  134. %*** Check each of the non-standard user-defined messages against the start of LINE ***;
  135.             DO i=1 TO DIM(SearchUser);
  136.                 IF Line=:SearchUser[i] THEN LogUser[i]=1;
  137.             END;
  138.         %END;
  139.  
  140. %*** Translate CR [Carriage return]/FF [Form Feed] characters to spaces ***;
  141.         line=TRANWRD(line,BYTE(13)," ");
  142.         line=TRANWRD(line,BYTE(10)," ");
  143.  
  144. %*** Non-standard log files use THV standard ERES info scanning ***;
  145.         IF type EQ ' ' THEN type='THV';
  146.         IF type NE ' ' THEN CALL SYMPUT ('LogType',type);
  147.     RUN;
  148.     %PUT Log file type=&LogType.;
  149. %*-------------------------------------------------------------------------------*;
  150. %* Create STEP - an indicator variable with an new integer for each "step" of    *;
  151. %* the log file. Ensure that comment blocks (/* -> */) are included all as one   *;
  152. %* step.                                                                         *;
  153. %*-------------------------------------------------------------------------------*;
  154.     DATA _Step_Log (KEEP=line ObsNo LineNo Step Comment Note Warning Error
  155.                         DataIssue STLIssue DMIssue
  156.                         %IF &UMessage NE %THEN %DO um_i=1 %TO &UserM.;
  157.                             LogUser&um_i.
  158.                         %END;
  159.                         FileName)
  160.          _EresInfo (KEEP=line FileName);
  161.         SET _Log;
  162.         LENGTH Filename $200.;
  163.         RETAIN comment step 0;
  164.         FileName="&InFile";
  165.         IF SecondWord=:"/*" THEN comment=1;
  166.         IF INDEX(line,"*/")>0 THEN comment=2;
  167.         IF comment=2 AND INDEX(line,"*/")=0 THEN comment=0;
  168.         IF (UPCASE(SecondWord) IN ("PROC" "DATA" "OPTIONS") AND note NE 1 AND comment EQ 0) OR
  169.             UPCASE(SecondWord)=:"TITLE" THEN step=step+1;
  170.         OUTPUT _Step_Log;
  171.         IF EresInfo=1 THEN OUTPUT _EresInfo;
  172.     RUN;
  173.     PROC SORT DATA=_Step_Log;
  174.         BY Step LineNo;
  175.     RUN;
  176. %*-------------------------------------------------------------------------------*;
  177. %* Scan through ERES information to find who ran the file and when. Merge this   *;
  178. %* information onto _REPORT prior to checking for LOG problems.                  *;
  179. %* Dependent on LOG file information type [LOGTYPE] create ERESDATA data set     *;
  180. %* based on this type of information. LOGTYPE=THV indicates the QTHV LOG         *;
  181. %* information standard, LOGTYPE=GBL indicates the Global Harmonised Structure   *;
  182. %* Log information standard.                                                     *;
  183. %*-------------------------------------------------------------------------------*;
  184.     %IF &LogType EQ THV %THEN %DO;
  185.         DATA _EresData (KEEP=FileName UserID SubmitDT);
  186.             SET _EresInfo END=eof;
  187.             ATTRIB
  188.                 UserID  LABEL="User ID who submitted file" LENGTH=$50.
  189.                 _Date   LABEL="Date file submitted [character]" LENGTH=$50.
  190.                 _Hour   LABEL="Hour file submitted [character]" LENGTH=$2.
  191.                 _Minute LABEL="Minute file submitted [character]" LENGTH=$2. LENGTH=$2.
  192.                 SubmitDT    LABEL="Date/Time file submitted" FORMAT=DATETIME20.
  193.             ;
  194.             RETAIN UserID ' ' SubmitDT 0;
  195.             Line=COMPBL(Line);
  196.             IF Line=:"User ID" THEN UserID=SCAN(Line,2,":");
  197.             IF Line=:"Date" THEN DO;
  198.                 _Date=SCAN(Line,2,":");
  199.                 _Hour=SCAN(COMPRESS(Line),3,":");
  200.                 _Minute=SCAN(COMPRESS(Line),4,":");
  201.                 SubmitDT=DHMS(INPUT(SCAN(COMPRESS(_Date),2,','),DATE9.),INPUT(_Hour,BEST.),INPUT(_Minute,BEST.),0);
  202.             END;
  203.             IF eof;
  204.         RUN;
  205.     %END;
  206.     %ELSE %DO;
  207.         DATA _EresData (KEEP=FileName UserID SubmitDT);
  208.             SET _EresInfo END=eof;
  209.             ATTRIB
  210.                 _QID        LABEL="Quintiles User ID" LENGTH=$7.
  211.                 _UserName   LABEL="User Name" LENGTH=$40.
  212.                 UserID      LABEL="User ID who submitted file" LENGTH=$50.
  213.                 _FullDate   LABEL="Full Date file submitted [character]" LENGTH=$50.
  214.                 _Day        LABEL="Day file submitted [character]" LENGTH=$2.
  215.                 _Month      LABEL="Month file submitted [character]" LENGTH=$10.
  216.                 _Year       LABEL="Year file submitted [character]" LENGTH=$4.
  217.                 _Time       LABEL="Time file submitted" FORMAT=TIME8.
  218.                 _Date       LABEL="Date file submitted" FORMAT=DATE9.
  219.                 SubmitDT    LABEL="Date/Time file submitted" FORMAT=DATETIME20.
  220.             ;
  221.             RETAIN _QID _UserName ' ' _Time _Date 0;
  222.             Line=COMPBL(Line); Line=TRANWRD(Line,': ',':');
  223.             IF Line=:"* User ID" THEN _QID=SCAN(Line,2,":");
  224.             IF Line=:"* User Name" THEN _UserName=SCAN(Line,2,":");
  225.             IF Line=:"* Date" THEN DO;
  226.                 _FullDate=SCAN(Line,2,":");
  227.                 _Day=COMPRESS(TRANWRD(SCAN(_FullDate,3,' '),',',' '));
  228.                 _Month=SUBSTR(SCAN(_FullDate,2,' '),1,3);
  229.                 _Year=SCAN(_FullDate,4,' ');
  230.                 _Date=INPUT(COMPRESS(_Day || _Month || _Year),DATE9.);
  231.             END;
  232.             IF Line=:"* Time :" THEN _Time=INPUT(SUBSTR(SCAN(Line,3," "),2),TIME8.);
  233.             IF eof THEN DO;
  234.                 SubmitDT=DHMS(_Date,HOUR(_Time),MINUTE(_Time),SECOND(_Time));
  235.                 UserID=_QID || " (" || TRIM(LEFT(_UserName)) || ")";
  236.                 OUTPUT;
  237.             END;
  238.         RUN;
  239.     %END;
  240. %*-------------------------------------------------------------------------------*;
  241. %* Check the NOTE contents for "errors" - NOTE information that could be         *;
  242. %* potential issues, i.e. Unitialized variables, etc.                            *;
  243. %*-------------------------------------------------------------------------------*;
  244.     DATA _Step_Log;
  245.         SET _Step_Log;
  246.         RETAIN Note_N Warning_N Error_N DataIssue_N STLIssue_N DMIssue_N 0;
  247.         ATTRIB
  248.             Note_N      LABEL="NOTE Identifier within STEP"
  249.             Warning_N   LABEL="WARNING Identifier within STEP"
  250.             Error_N     LABEL="ERROR Identifier within STEP"
  251.             DataIssue_N LABEL="DATA ISSUE Identifier within STEP"
  252.             STLIssue_N  LABEL="STL ISSUE Identifier within STEP"
  253.             DMIssue_N   LABEL="DM ISSUE Identifier within STEP"
  254.             Problem     LABEL="Flag to highlight what message to print in LOG report"
  255.         ;
  256.         BY Step LineNo;
  257.         ARRAY LogVar[*] Note Warning Error DataIssue STLIssue DMIssue;
  258.         ARRAY LogVarNum[*] Note_N Warning_N Error_N DataIssue_N STLIssue_N DMIssue_N;
  259.         DO i=1 TO DIM(LogVar);
  260.             IF FIRST.Step THEN LogVarNum[i]=0;
  261.             IF LogVar[i]=1 THEN LogVarNum[i]=LogVarNum[i]+1;
  262.         END;
  263. %*** Checking NOTES: ***;
  264.         IF Note THEN DO;
  265.             IF /*INDEX(Line,"created, with 0 rows")>0 OR INDEX(Line,"has 0 observations")>0 OR*/
  266.                 INDEX(Line,"uninitialized")>0 OR INDEX(Line,"Invalid")>0 OR INDEX(Line,"invalid")>0 OR
  267.                 INDEX(Line,"Division by zero")>0 /*OR INDEX(Line,"Missing values were generated")>0*/ OR
  268.              /*   INDEX(Line,"Numeric values have been converted to character values")>0 OR
  269.                 INDEX(Line,"Character values have been converted to numeric values")>0 OR */
  270.                 INDEX(Line,"MERGE statement has more than one data set with repeats of BY values")>0 OR
  271.               /*  INDEX(Line,"At least one W.D format was too small for the number to be printed")>0 OR
  272.                 INDEX(Line,"Character format specified for the result of a numeric expression")>0 OR
  273.                */ INDEX(Line,"Mathematical operations could not be performed at the following places")>0 OR
  274.              /*   INDEX(Line,"ERROR DETECTED IN ANNOTATE=")>0 OR INDEX(Line,"PROBLEM IN OBSERVATION")>0 OR
  275.                 INDEX(Line,"Reduction in size of titles")>0 OR INDEX(Line,"outside the axis range")>0 OR
  276.                */ INDEX(Line,"The SAS System stopped processing this step because of insufficient disk space")>0 OR
  277.                 INDEX(Line,"not found or could not be loaded")>0
  278.                  THEN Problem=1;
  279.         END;
  280.         IF Warning OR Error THEN Problem=1;
  281.         IF DataIssue OR STLIssue OR DMIssue THEN Problem=1;
  282.         IF Warning AND
  283.             (INDEX(Line,"is associated will expire within")>0 OR
  284.              INDEX(Line,"Compression was disabled")>0 OR
  285.              INDEX(Line,"product with which")>0 OR
  286.              INDEX(Line,"Your system is scheduled to expire on")>0) THEN Problem=0;
  287.  
  288.         %IF &UMessage NE %THEN %DO um_i=1 %TO &UserM.;
  289.             ARRAY LogUser[&UserM.];
  290.             DO i=1 TO DIM(LogUser) UNTIL (Problem=1);
  291.                 IF LogUser[i]=1 THEN Problem=1;
  292.             END;
  293.         %END;
  294.     RUN;
  295. %*-------------------------------------------------------------------------------*;
  296. %* Select steps with PROBLEM=1 - need to investigate. Potential problem.         *;
  297. %*-------------------------------------------------------------------------------*;
  298.     PROC SQL NOPRINT;
  299.         CREATE TABLE _Step_Log AS
  300.             SELECT s.*, UserID, SubmitDT
  301.             FROM _Step_Log s LEFT JOIN _EresData e
  302.             ON s.FileName EQ e.FileName;
  303.         CREATE TABLE _Report AS
  304.             SELECT *, INT(LineNo) AS RepLine FROM _Step_Log
  305.             WHERE problem=1 ORDER BY Step, LineNo;
  306.         CREATE TABLE _FileInfo_file AS
  307.             SELECT DISTINCT s.filename, UserID, SubmitDT, Issue
  308.             FROM _Step_Log s LEFT JOIN
  309.                 (SELECT DISTINCT filename, 1 AS issue FROM _Step_Log WHERE problem EQ 1) p
  310.             ON s.filename EQ P.filename ORDER BY s.filename;
  311.     QUIT;
  312. %*-------------------------------------------------------------------------------*;
  313. %* Append all _REPORT data sets to FINDINGS: This is the final report.           *;
  314. %*-------------------------------------------------------------------------------*;
  315.     PROC APPEND BASE=_findings FORCE DATA=_Report;
  316.     RUN;
  317.     PROC APPEND BASE=_FileInfo FORCE DATA=_FileInfo_file;
  318.     RUN;
  319. %*-------------------------------------------------------------------------------*;
  320. %* Remove data sets [_LOG/_STEP_LOG/_REPORT] from WORK area at end of SCANLOG.   *;
  321. %*-------------------------------------------------------------------------------*;
  322.     PROC DATASETS LIBRARY=WORK MTYPE=DATA;
  323.         DELETE _log _step_log _report _eres: _FileInfo_file;
  324.     RUN; QUIT;
  325. %MEND ScanLog;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement