Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*=============================================================================
- Program Name: LOGCHECK.SAS
- Purpose: To automatically scan SAS log files in a specified directory
- for ERRORs, WARNINGs and NOTEs which are against good
- programming practice. The user can specify the directory
- that the files are stored in and how many files the
- macro will search through.
- Macro variables: DIR [Required]: Windows NT directory path where the
- LOG files are stored
- [usually surounded by a %STR()].
- This pathname can be gained from NT explorer
- using the right-click and using "Properties".
- SCOPE [Default=A]: How many LOG files are to be scanned.
- Values: A = All files, S = Single file,
- I = Include files of this type,
- E = Exclude files of this type
- FILENAME [Optional]: File or start of filename to be scanned.
- If SCOPE=A then this option is ignored.
- If SCOPE=I then all file names beginning
- with this are scanned.
- If SCOPE=E then all file names except
- those beginning with this are scanned.
- If SCOPE=S then this file name is scanned.
- UMESSAGE [Optional]: Comma-delimted list of non-standard
- user-defined LOG messages surrounded
- by a %STR.
- YNZEROOBS [Default=Y]: Switch to check whether data sets have zero observations.
- Values: Y = Check for Zero observations.
- N = Do not check for Zero observations
- DTFROM [Optional]: Date of LOG file creation (on or after).
- LOG files created before this date will not be scanned.
- Date must be of the form: DDMMMYYYY.
- Programmer: Lawrence Heaton-Wright
- OS/SAS Vnum: Windows NT / 8.2
- Date: 28-Aug-2003
- Notes: This program can be run from interactive or batch SAS.
- This macro references several sub-macros:
- SCANLOG, MAXTITLE, FINDINGS
- SCANLOG: Scans LOG file. Creates data set which is
- appended to a FINDINGS data set.
- MAXTITLE: Checks for pre-existing titles -
- finds maximum number of existing title
- FINDINGS: Reports LOG scan findings
- Report options of NOBYLINE, LS=132, PS=50, NONUMBER, DATE
- always set in this macro. The values of the original options
- are reset after running the macro,
- Example: %LogCheck (Dir=%STR(Q:\ABC Pharma\prot 001\BioStatistics\Programs\Tables));
- This will check ALL LOG files in this directory.
- %LogCheck (Dir=%STR(Q:\ABC Pharma\prot 001\BioStatistics\Programs\Tables), Scope=S, FileName=t01);
- This will check the T01.LOG file in this directory.
- %LogCheck (Dir=%STR(Q:\ABC Pharma\prot 001\BioStatistics\Programs\Tables), Scope=I, FileName=demog);
- This will check all LOG files beginning with DEMOG
- (ie. DEMOG_TABLE.LOG, DEMOG_BASELINE.LOG) in this directory.
- %LogCheck (Dir=%STR(Q:\ABC Pharma\prot 001\BioStatistics\Programs\Tables), Scope=E, FileName=compare);
- This will check all LOG files other than those beginning with COMPARE
- %LogCheck (Dir=%STR(Q:\ABC Pharma\prot 001\BioStatistics\Programs\Tables), UMessage=%STR(PGM NOTE:, PROBLEM:));
- This will check ALL LOG files in this directory searching
- the LOG files for the additional messages "PGM NOTE:" and "PROBLEM:".
- %LogCheck (Dir=%STR(Q:\ABC Pharma\prot 001\BioStatistics\Programs\Tables), dtFrom=25APR2008);
- This will check ALL LOG files in this directory created on or after 25APR2008.
- --------------------------------------------------------------------------------
- Modifications:
- Programmer/Date: Reason:
- ---------------- -------
- LHW / 18-JAN-2005 Improved summary section of report. Produce a list of files
- with and without issues and user ID and date submitted.
- LHW / 07-NOV-2005 Add code to check for existing WORK data sets. At completion
- of macro delete any WORK data sets created by the macro but
- not-pre-existing WORK data sets.
- LHW / 09-NOV-2005 Added HEADING3 to report. Prints directory scanned on a separate
- row in the header information.
- Create PRNFILE1/PRNFILE2 = Heading information for FILENAME
- broken into 2 parts {amount of characters 1->132, 133->end}.
- LHW / 05-JAN-2006 Added YNZEROOBS macro variable. This is a Y/N variable which
- activates the search for zero observations in a data set.
- LHW / 16-APR-2007 Version 1.0:
- Updated SCOPE=E option to use a similar functionality to
- the Inclusion of files option.
- Added _VERSION & _VERDATE to show version number and date.
- LHW / 06-JUL-2007 Version 1.1:
- Added BQUOTE around SYSPBUFF macro variable to mask commas
- inside the UMESSAGE input variable. Otherwise an error is
- generated stated that there are the wrong amount of elements
- for the INDEX macro function.
- LHW / 29-APR-2008 Version 2.0:
- Added DTFROM macro variable. This variable is an additional
- switch to enable users to only scan LOG files created on
- or after a specified date.
- LHW / 30-APR-2008 Version 2.1:
- When creating SCANLOG=1 restrict data set to those files
- which are SCANLOG=1 as this will ensure that the data set
- _LOGFILES will contain only those LOG files to be scanned.
- This will also allow interrogation based on the number
- of observations.
- Added Date LOG files craeted to REPORT headings.
- Added VALIDVARNAME to list of options checked.
- Set OPTIONS VALIDVARNAME=UPCASE as default for duration of macro.
- ==============================================================================*/
- %MACRO LogCheck (Dir=, Scope=A, FileName=, UMessage=, ynZeroObs=Y, dtFrom=, _Version=%STR(2.1), _VerDate=29APR2008) / PARMBUFF;
- OPTIONS NOSOURCE;
- *-------------------------------------------------------------------------------*;
- * Upper-case zero observations switch flag variable. *;
- *-------------------------------------------------------------------------------*;
- %LET ynZeroObs=%UPCASE(&ynZeroObs.);
- PROC SQL;
- *-------------------------------------------------------------------------------*;
- * Find WORK data sets already existing prior to invocation of LOGCHECK macro. *;
- *-------------------------------------------------------------------------------*;
- CREATE TABLE _pre_exist AS
- SELECT DISTINCT memname FROM SASHELP.vstable WHERE UPCASE(libname) EQ "WORK";
- *-------------------------------------------------------------------------------*;
- * Retrieve OPTIONS settings for PS, LS, DATE, NUMBER & BYLINE. These options *;
- * are set by the LOGCHECK macro. At the end of the macro these will be reset to *;
- * the intial values. *;
- *-------------------------------------------------------------------------------*;
- CREATE TABLE _initial_options AS
- SELECT DISTINCT optname, setting FROM SASHELP.voption
- WHERE optname IN ('LINESIZE' 'PAGESIZE' 'BYLINE' 'DATE' 'NUMBER' 'VALIDVARNAME');
- QUIT;
- DATA _NULL_;
- SET _initial_options;
- CALL SYMPUT(optname,COMPRESS(setting));
- RUN;
- OPTIONS VALIDVARNAME=UPCASE;
- *-------------------------------------------------------------------------------*;
- * Check UMESSGAE macro variable. If non-missing then there are non-standard *;
- * user-defined LOG messages to check for. Create macro variables with a prefix *;
- * of MESSAGE for the number of non-standard user-dfiened LOG messages. *;
- *-------------------------------------------------------------------------------*;
- %IF &UMessage NE %THEN %DO;
- DATA _NULL_;
- UMessage=SYMGET("UMessage");
- len_with_comma=LENGTH(UMessage);
- len_without_comma=LENGTH(COMPRESS(UMessage,','));
- UserM=len_with_comma-len_without_comma+1;
- CALL SYMPUT('UserM',COMPRESS(PUT(UserM,BEST.)));
- RUN;
- %LET MaxUMLen=1;
- %DO um_i=1 %TO &UserM.;
- %LET Message&um_i=%SCAN(&UMessage.,&um_i.,',');
- %IF %LENGTH(&&Message&um_i.) GT &MaxUMLen. %THEN %LET MaxUMLen=%LENGTH(&&Message&um_i.);
- %PUT User message &um_i. = &&Message&um_i. Maximum length of comment=&MaxUMLen.;
- %END;
- %END;
- %*** Macro variable used to indicate that the macro should continue when =N ***;
- %LET CloseDown=N; %LET Scope=%UPCASE(&Scope); %LET FileName=%UPCASE(&FileName);
- %*------------------------------------------------------------------------------*;
- %* Check that user have not change version number or version date. *;
- %* Added BQUOTE to mask commas inside UMESSAGE (if UMESSAGE specified). *;
- %*------------------------------------------------------------------------------*;
- %PUT SysPBuff=&SysPBuff.;
- %IF %INDEX(%BQUOTE(%UPCASE(&SysPBuff.)),_VERSION) GT 0
- OR %INDEX(%BQUOTE(%UPCASE(&SysPBuff.)),_VERDATE) GT 0 %THEN %DO;
- %PUT ERROR: Version or Version Date Changed by User;
- %PUT Terminating &SysMacroName.;
- %PUT;
- %LET CloseDown=Y;
- %END;
- LIBNAME _test_ "&Dir";
- %*** Use the SYSLIBRC macro variable to determine if the LIBREF has been assigned ***;
- %*** If SYSLIBRC=0 then this indicates that the LIBNAME statement was successful ***;
- %*** For any other value shut down the macro. Also check for null values of DIR ***;
- %IF &CloseDown=N %THEN %DO;
- %*------------------------------------------------------------------------------*;
- %* Macro information. *;
- %*------------------------------------------------------------------------------*;
- %PUT &SysMacroName. Version &_Version., Version Date &_VerDate.;
- %PUT;
- %PUT NOTE: STARTING &SysMacroName. PARAMETER CHECKS;
- %PUT;
- %IF &SysLibRC. NE 0 %THEN %DO;
- %LET CloseDown=Y;
- %PUT ;
- %PUT ERROR: Specified directory does not exist. Check spelling.;
- %PUT ERROR: Macro terminating due to &Dir not existing;
- %PUT ;
- %END;
- %END;
- %*** Continue with the macro ***;
- %IF &CloseDown=N %THEN %DO;
- %PUT ;
- %PUT NOTE: Specified directory exists. Macro continuing.;
- %PUT NOTE: Checking &Dir LOG files.;
- %PUT ;
- %*** Check that SCOPE requested is a valid values [A/I/E/S]. ***;
- %IF NOT (&Scope=A OR &Scope=I OR &Scope=E OR &Scope=S) %THEN %DO;
- %PUT ;
- %PUT ERROR: SCOPE has not been specified as All/Include/Exclude/Single LOG file check.;
- %PUT ERROR: Macro terminating. SCOPE=&Scope.. Choices are A/I/E/S. ;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %END;
- %*** Continue with the macro ***;
- %IF &CloseDown=N %THEN %DO;
- %PUT ;
- %PUT NOTE: Macro continuing.;
- %PUT NOTE: Checking &Dir SCOPE=&Scope LOG files.;
- %PUT ;
- %*** Check that if SCOPE is Include/Exclude/Single then a filename has been specified. ***;
- %IF (&Scope=I OR &Scope=I OR &Scope=S) AND &FileName= %THEN %DO;
- %PUT ;
- %PUT ERROR: No filename specified even though an Include/Exclude or Single LOG file check has been requested.;
- %PUT ERROR: Macro terminating. SCOPE=&Scope FILENAME=&FileName.. FileName MUST be entered.;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %END;
- %*** Continue with the macro ***;
- %IF &CloseDown=N %THEN %DO;
- %PUT ;
- %PUT NOTE: Macro continuing.;
- %PUT NOTE: Checking Zero Observations switch flag has correct input value;
- %PUT ;
- %*** Check that if YNZEROOBS has a value of Y or N. ***;
- %IF NOT (&ynZeroObs. EQ Y OR &ynZeroObs. EQ N) %THEN %DO;
- %PUT ;
- %PUT ERROR: Zero observations switch flag has incorrect values.;
- %PUT ERROR: Macro terminating. YNZEROOBS=&ynZeroObs.. ynZeroObs MUST have values of Y or N.;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %END;
- %*** Continue with the macro ***;
- %*** Checking that DTFROM is a valid date ***;
- %IF &dtFrom NE %THEN %DO;
- %PUT ;
- %PUT NOTE: Macro continuing.;
- %PUT NOTE: Checking Date of LOG files is a valid date value;
- %PUT ;
- %*** Check that DTFROM is of the form DDMMYYYY. ***;
- %LET dtWrong=N;
- DATA _NULL_;
- _dt=INPUT(SYMGET('dtFrom'),??DATE9.);
- IF _dt EQ . THEN CALL SYMPUT('dtWrong','Y');
- RUN;
- %IF &dtWrong. EQ Y %THEN %DO;
- %PUT ;
- %PUT ERROR: Cutoff Date not of DDMMYYYY format.;
- %PUT ERROR: Macro terminating. DTFROM=&dtFrom.. dtFrom MUST be the form DDMMMYYYY.;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %END;
- %*** Continue with the macro ***;
- %IF &CloseDown=N %THEN %DO;
- %PUT ;
- %PUT NOTE: Macro continuing.;
- %PUT NOTE: Checking &Dir SCOPE=&Scope FILENAME=&FileName LOG files.;
- %PUT ;
- DATA _NULL_;
- folder=SYMGET("dir");
- %*** Use DIR to create a DOS command to return all of the LOG files in a directory. ***;
- %IF &dtFrom. NE %THEN %DO;
- dir_cmd="'dir " || '"' || TRIM(LEFT(folder)) || '\*.LOG"' || "/od'";
- %END;
- %ELSE %DO;
- dir_cmd="'dir " || '"' || TRIM(LEFT(folder)) || '\*.LOG"' || "/b'";
- %END;
- CALL SYMPUT ('dir_cmd',dir_cmd);
- RUN;
- FILENAME dir PIPE &Dir_Cmd.;
- %IF &dtFrom. NE %THEN %DO;
- DATA _LogFiles (DROP=_LogFile _crDate _dtFrom);
- ATTRIB
- _crDate LABEL="File Creation Date" FORMAT=DATE9.
- _dtFrom LABEL="Cutoff Date for LOG file scan" FORMAT=DATE9.
- LogFile LABEL="SAS LOG file" LENGTH=$100.
- ;
- INFILE dir TRUNCOVER;
- INPUT _LogFile $CHAR256. @;
- IF INDEXC(SUBSTR(_LogFile,1,1),'1234567890') EQ 0 THEN DELETE;
- _crDate=INPUT(SCAN(_LogFile,1,' '),DDMMYY10.);
- LogFile=SCAN(_LogFile,4,' ');
- _dtFrom=INPUT(SYMGET('dtFrom'),DATE9.);
- IF _crDate LT _dtFrom THEN DELETE;
- %END;
- %ELSE %DO;
- DATA _LogFiles;
- LENGTH ReadFile $200.;
- INFILE dir TRUNCOVER;
- INPUT LogFile $CHAR256. @;
- %END;
- %*** Use SYMGET functionality to retrieve all input macro variables ***;
- folder=SYMGET("dir"); scope=SYMGET("scope"); FileName=SYMGET("FileName");
- ReadFile=TRIM(folder) || "\" || LogFile;
- LogFile=UPCASE(LogFile);
- %*** Check SCOPE and FILENAME. Set a flag [SCANLOG=1] for the following records: ***;
- %*** If SCOPE=A then SCANLOG=1 for all records. ***;
- %*** If SCOPE=I then SCANLOG=1 for records where LOGFILE begins with FILENAME. ***;
- %*** If SCOPE=E then SCANLOG=1 for records where LOGFILE does not begin with ***;
- %*** FILENAME. ***;
- %*** If SCOPE=S then SCANLOG=1 for the record where LOGFILE=FILENAME. ***;
- ScanLog=0;
- IF scope='A' OR
- (scope='I' AND SUBSTR(LogFile,1,LENGTH(FileName)) EQ FileName) OR
- (scope='E' AND SUBSTR(LogFile,1,LENGTH(FileName)) NE FileName) OR
- (scope='S' AND LogFile EQ COMPRESS(FileName || '.LOG')) THEN ScanLog=1;
- IF ScanLog EQ 1;
- RUN;
- %*** Check LOG files data set for occurrences of SCANLOG. ***;
- %LET dsid=%SYSFUNC(OPEN(WORK._LogFiles));
- %LET N_Files=%SYSFUNC(ATTRN(&dsid.,NOBS));
- %LET rc=%SYSFUNC(CLOSE(&dsid.));
- %*** If SCOPE=I or E then SCANLOG should equal 1 for at least one record. ***;
- %IF (&Scope=I OR &Scope=E) AND %EVAL(&N_Files)=0 %THEN %DO;
- %PUT ;
- %PUT ERROR: Multiple log files requested but no files match FILENAME=&FileName..;
- %PUT ERROR: Macro terminating.;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %*** If SCOPE=S then SCANLOG should equal 1 for only one record. ***;
- %IF &Scope=S AND %EVAL(&N_Files) NE 1 %THEN %DO;
- %PUT ;
- %PUT ERROR: Single log file requested but no file matches FILENAME=&FileName..;
- %PUT ERROR: Macro terminating.;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %*** Check that there are files to be scanned if no LOG files created after DTFROM ***;
- %IF &dtFrom. NE AND %EVAL(&N_Files) EQ 0 %THEN %DO;
- %PUT ;
- %PUT ERROR: No LOG files created after DTFROM = &dtFrom..;
- %PUT ERROR: Macro terminating.;
- %PUT ;
- %LET CloseDown=Y;
- %END;
- %END;
- %*** Continue with the macro ***;
- %IF &CloseDown=N %THEN %DO;
- %*-------------------------------------------------------------------------------*;
- %* Check WORK area for existing _FINDINGS data set. If this exists then delete *;
- %* this data set as we do not require LOG file findings from previous log checks *;
- %* to be reported again. *;
- %* Use EXIST function to check if _FINDINGS exists. Returns non-zero value if *;
- %* operation was successful (i.e. _FINDINGS exists). *;
- %*-------------------------------------------------------------------------------*;
- %IF %SYSFUNC(EXIST(WORK._FINDINGS)) %THEN %DO;
- %PUT NOTE: WORK._FINDINGS already exists. Deleting for new report.;
- %PUT;
- PROC DATASETS LIBRARY=WORK;
- DELETE _findings;
- RUN; QUIT;
- %END;
- %*** For each occurrence of SCANLOG=1, call the SCANLOG macro to search that file ***;
- %*** for ERRORs, WARNINGs, NOTEs. ***;
- %*** Create INVOKEORDER variable = unique record number of LOG file to be scanned ***;
- %*** Use INVOKEORDER from a macro DO loop to create _READFILE - a macro variable ***;
- %*** which is used in the invocation of the SCANLOG macro. ***;
- DATA _LogFiles;
- SET _LogFiles (WHERE=(ScanLog=1));
- InvokeOrder=_N_;
- RUN;
- %DO _i=1 %TO &N_Files.;
- DATA _NULL_;
- SET _LogFiles (WHERE=(InvokeOrder=&_i.));
- CALL SYMPUT ('_ReadFile',TRIM(LEFT(ReadFile)));
- RUN;
- %ScanLog(InFile=%STR(&_ReadFile.));
- %END;
- %*-------------------------------------------------------------------------------*;
- %* Check SASHELP.VTITLE for maximum number of titles. Create TITLE+1 for *;
- %* LOG findings report. *;
- %*-------------------------------------------------------------------------------*;
- %MaxTitle;
- %LET Title=%EVAL(&MaxTitle+1);
- TITLE&Title "LOG FILE CHECK";
- %*-------------------------------------------------------------------------------*;
- %* Print out relevant LOG file problems. *;
- %*-------------------------------------------------------------------------------*;
- PROC FORMAT;
- PICTURE RepLine
- -1=" FILE NAME: " (NOEDIT)
- 0-HIGH="0000099" (PREFIX="LOG LINE:")
- .=" " (NOEDIT);
- RUN;
- %*-------------------------------------------------------------------------------*;
- %* Check _FINDINGS is not missing. If missing then create a dummy data set *;
- %* containing 1 observation which will be used to print out a *;
- %* "No Log File Problems" report. *;
- %* If no observations in _FINDINGS data set set NERROR=0 [Number of LOG files *;
- %* with errors/problems found]. Otherwise set NERROR to the number of LOG files *;
- %* in _FINDINGS. *;
- %*-------------------------------------------------------------------------------*;
- PROC SQL NOPRINT;
- SELECT DISTINCT NObs INTO: NObs FROM SASHELP.vtable
- WHERE libname="WORK" AND memname="_FINDINGS";
- QUIT;
- %IF %EVAL(&NObs.) EQ 0 %THEN %DO;
- %PUT NO RECORDS IN _FINDINGS - CREATE DUMMY DATA SET;
- DATA _findings;
- step=1; LineNo=1; Repline=.; Line=" ";
- FileName="No Problems detected in LOG file(s)";
- RUN;
- %LET NError=0;
- %END;
- %ELSE %DO;
- PROC SQL NOPRINT;
- SELECT DISTINCT N(DISTINCT FileName) INTO: NError FROM _findings;
- QUIT;
- %END;
- %LET MaxLines=%EVAL(36-&Title.);
- PROC SORT DATA=_findings;
- BY FileName Step LineNo;
- RUN;
- %*-------------------------------------------------------------------------------*;
- %* Define SUMMARY page data set. *;
- %* Produce list of LOG files scanned and those with potential issues and those *;
- %* without. Find final page number. Use this to start the detailed report *;
- %* pagination calculations. *;
- %*-------------------------------------------------------------------------------*;
- DATA _summary ;
- SET _FileInfo;
- ATTRIB
- directory LABEL="Directory Scanned" LENGTH=$132.
- ScopeFiles LABEL="Scope of Files Scanned" LENGTH=$132.
- Summary LABEL="Number LOG Files Scanned and Number of Issues" LENGTH=$132.
- Program LABEL="Program LOG File Scanned" LENGTH=$132.
- ;
- directory=SYMGET("dir");
- scope=SYMGET("scope");
- IF scope="A" THEN ScopeFiles="All LOG Files scanned";
- ELSE IF scope="S" THEN ScopeFiles="Scanned File = &Filename..LOG";
- ELSE IF scope="I" THEN ScopeFiles="Files beginning with &Filename. scanned";
- ELSE IF scope="E" THEN ScopeFiles="Files beginning with &Filename. excluded from scanning";
- Summary="Number of LOG files scanned = " || COMPRESS(PUT(&N_Files.,BEST.)) ||
- "; Number of LOG files with potential issues = " ||
- COMPRESS(PUT(&NError.,BEST.)) ||".";
- Program=SCAN(FileName,-1,'\');
- RUN;
- %*-------------------------------------------------------------------------------*;
- %* Calculate pagination for SUMMARY data set. Use MAXLINES macro variable which *;
- %* indicates how many lines are available to the report. *;
- %*-------------------------------------------------------------------------------*;
- PROC SORT DATA=_Summary;
- BY issue FileName;
- RUN;
- DATA _Summary;
- SET _Summary END=eod;
- BY issue FileName;
- RETAIN page 0 LinesLeft &MaxLines.;
- IF _N_ EQ 1 THEN page=1;
- IF FIRST.issue THEN LinesLeft=LinesLeft-6;
- LinesLeft=LinesLeft-1;
- IF LinesLeft LT 1 THEN DO;
- Page+1; LinesLeft=&MaxLines.-6;
- END;
- _Page=page;
- IF eod THEN CALL SYMPUT('SummPage',PUT(page,BEST.));
- RUN;
- %*-------------------------------------------------------------------------------*;
- %* Calculate page numbers. *;
- %*-------------------------------------------------------------------------------*;
- DATA _findings;
- SET _findings END=eof;
- ATTRIB
- Page LABEL="Page number"
- LinesLft LABEL="Lines left per report page"
- ExtraLine LABEL="Extra line needed for LINE - FLOW variable"
- UID_Date LABEL="User ID and Date/Time submitted" LENGTH=$132.
- PrnFile1 LABEL="REPORT Heading: 1st 132 characters of FILENAME" LENGTH=$132.
- PrnFile2 LABEL="REPORT Heading: 2nd 132 characters of FILENAME" LENGTH=$132.
- ;
- RETAIN Page %EVAL(&SummPage.+1) LinesLft &MaxLines.;
- BY FileName Step LineNo;
- DDLogs=INDEX(UPCASE(FileName),"DERIVED DATASETS");
- UID_Date=TRIM(LEFT(UserID)) || " / " || TRIM(LEFT(PUT(SubmitDT,DATETIME20.)));
- ExtraLine=CEIL(LENGTH(Line)/112);
- LinesLft=LinesLft-ExtraLine;
- IF FIRST.Step THEN LinesLft=LinesLft-2;
- IF FIRST.FileName THEN DO;
- LinesLft=LinesLft-2;
- FileNameID+1;
- END;
- IF (DDLogs>0 AND FIRST.FileName AND _N_ NE 1) OR
- (FIRST.FileName AND LinesLft<3) OR LinesLft<1 THEN DO;
- Page+1;
- LinesLft=&MaxLines.;
- END;
- %IF &NError. NE 0 %THEN %DO;
- IF eof THEN CALL SYMPUT ("TotPages",COMPRESS(PUT(page,BEST.)));
- %END;
- %ELSE %DO;
- %LET TotPages=&SummPage.;
- *CALL SYMPUT ("TotPages",'1');
- %END;
- %*-------------------------------------------------------------------------------*;
- %* If length of FILENAME (plus "Filename =") >132 then create PRNFILE2 as *;
- %* remainder of FILENAME from characters 133 to the end. PRNFILE1 is the first *;
- %* 132 characters of FILENAME. *;
- %*-------------------------------------------------------------------------------*;
- PrnFile1=SUBSTR(FileName,1,132-11);
- IF (LENGTH(FileName)+11)>132 THEN PrnFile2=SUBSTR(FileName,132-11+1);
- RUN;
- %*-------------------------------------------------------------------------------*;
- %* Reporting step. *;
- %*-------------------------------------------------------------------------------*;
- OPTIONS NOBYLINE LS=132 PS=48 DATE NONUMBER;
- PROC REPORT DATA=_summary NOWD MISSING SPACING=0 SPLIT="~";
- COLUMN Page directory ScopeFiles Summary issue _Page ("__" Program UserID SubmitDT);
- DEFINE _Page / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE issue / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE directory / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE ScopeFiles / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE Summary / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE Page / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE Program / ORDER ORDER=INTERNAL "File Name" WIDTH=50 FLOW LEFT;
- DEFINE UserID / DISPLAY "User ID" WIDTH=50 FLOW LEFT;
- DEFINE SubmitDT / DISPLAY "Date/time Submitted" WIDTH=32 FLOW LEFT;
- BREAK AFTER Page / PAGE;
- BREAK AFTER issue / SKIP;
- COMPUTE BEFORE Page;
- LINE @1 132*'_';
- LINE @1 ' ';
- ENDCOMP;
- COMPUTE BEFORE _Page;
- LENGTH Heading1-Heading3 $132.;
- Heading2=TRIM(ScopeFiles)
- %IF &dtFrom. NE %THEN %DO;
- || " [ for LOG files created after %UPCASE(&dtFrom.) ]"
- %END;
- || " in Directory:";
- Heading3=TRIM(Directory);
- IF issue EQ . THEN DO;
- Heading1='LOG DIRECTORY SCANNING INFORMATION SUMMARY - NO ISSUES IN LOG FILES';
- END;
- ELSE DO;
- Heading1='LOG DIRECTORY SCANNING INFORMATION SUMMARY - POSSIBLE ISSUES IN LOG FILES';
- END;
- LINE @1 132*'=';
- LINE @1 Heading1 $132.;
- LINE @1 Heading2 $132.;
- LINE @1 Heading3 $132.;
- LINE @1 Summary $132.;
- LINE @1 132*'=';
- LINE @1 ' ';
- ENDCOMP;
- COMPUTE AFTER Page;
- LENGTH PageXofY $132.;
- PageXofY="Page " || COMPRESS(PUT(page,BEST.)) || " of &TotPages.";
- LINE @1 132*'_';
- LINE @1 ' ';
- LINE @1 PageXofY $132.;
- ENDCOMP;
- RUN;
- QUIT;
- %IF &NError. NE 0 %THEN %DO;
- PROC REPORT DATA=_findings LS=132 NOWD MISSING SPACING=0 SPLIT="~";
- COLUMN Page PrnFile1 PrnFile2 UID_Date FileNameID Step LineNo
- ("__" RepLine Line);
- DEFINE Page / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE PrnFile1 / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE PrnFile2 / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE UID_Date / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE FileNameID / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE Step / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE LineNo / ORDER NOPRINT ORDER=INTERNAL;
- DEFINE RepLine / DISPLAY " " FORMAT=RepLine. WIDTH=20 LEFT;
- DEFINE Line / DISPLAY " " WIDTH=112 FLOW;
- BREAK AFTER Page / PAGE;
- COMPUTE BEFORE FileNameID;
- LINE @1 "FileName = " PrnFile1 $132.;
- LINE @1 " " PrnFile2 $132.;
- LINE @1 "User ID/Date Submitted = " UID_Date $132.;
- LINE @1 132*'_';
- LINE @1 ' ';
- ENDCOMP;
- COMPUTE AFTER Step;
- LINE @1 132*'_';
- LINE @1 ' ';
- ENDCOMP;
- COMPUTE AFTER Page;
- LENGTH PageXofY $132.;
- PageXofY="Page " || COMPRESS(PUT(page,BEST.)) || " of &TotPages.";
- LINE @1 PageXofY $132.;
- ENDCOMP;
- RUN;
- QUIT;
- %END;
- %END;
- *-------------------------------------------------------------------------------*;
- * Resetting options and statements from ones modified by LOGCHECK to original *;
- * settings. *;
- *-------------------------------------------------------------------------------*;
- TITLE&Title.; LIBNAME _test_;
- *-------------------------------------------------------------------------------*;
- * Find WORK data sets existing after invocation of LOGCHECK macro. *;
- * Create macro variable _LIST_DELETE as a list of data sets created by *;
- * LOGCHECK/SCANLOG/MAXTITLE invocation which did not exist prior to invocation. *;
- * Use this macro variable in a PROC DATASETS call to delete these data sets. *;
- *-------------------------------------------------------------------------------*;
- DATA _NULL_;
- MERGE
- _pre_exist (IN=in_pre_exist)
- SASHELP.vstable (WHERE=(UPCASE(libname) EQ "WORK") IN=in_post_exist) END=eof
- ;
- LENGTH list_delete $1024.;
- RETAIN list_delete ' ';
- BY memname;
- IF in_post_exist AND NOT in_pre_exist THEN list_delete=TRIM(list_delete) || " " || memname;
- IF eof THEN DO;
- PUT "DELETE THESE DATA SETS: " list_delete;
- CALL SYMPUT ('_list_delete',list_delete);
- END;
- RUN;
- PROC DATASETS LIBRARY=WORK MTYPE=DATA;
- DELETE &_list_delete.;
- RUN; QUIT;
- OPTIONS SOURCE;
- %PUT RESETTING TO INTIAL OPTION SETTINGS;
- %PUT;
- %PUT LS=&LineSize. PS=&PageSize. DATE=&Date. BYLINE=&ByLine. VALIDVARNAME=&ValidVarName.;
- OPTIONS LS=&LineSize. PS=&PageSize. &Date. &ByLine. &Number VALIDVARNAME=&ValidVarName.;
- %MEND LogCheck;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement