/******************************************************************************************** Input parameters: indir = input directory where the .log files are located fnames= names of the .log files to be checked (default: all .log files in the directory (blank)) example: fnames=rlab.log recg.log rae.log, or: fnames=r*.log, (all .log files beginning with r) outfile= output report file name (default=chklogs.lst) Leave blank if do not want this file. outdir= output directory for the output report file. ******************************************************************************************************/ %macro chklogs(indir=, fnames=, outfile=chklogs.lst, outdir=); options nosource nosource2 nonotes ps=55 ls=158; %* Determine the operating system specific directory command; %if %index(&indir,/)>0 %then %do; %let sep=/; %let dir=%str(ls -x1); %let del=rm; %let platf=UNIX; %end; %else %if %index(&indir,\)>0 %then %do; options noxwait; %let sep=\; %let dir=%str(dir/b); %let del=del; %let platf=WINDOWS; %end; %* Test if the indir= and outdir= exist and give warnings if not; %if %sysfunc(fileexist(&indir))=0 %then %do; %do i=1 %to 3; %put *** Error: Directory &indir does not exist ***; %end; %put; %goto eom; %end; %if %sysfunc(fileexist(&outdir))=0 %then %do; %do i=1 %to 3; %put *** Error: Directory &outdir does not exist ***; %end; %put; %goto eom; %end; %* Break up fnames, if it is not empty; %let nfn=0; %if %length(&fnames)>0 %then %do; %let count=1; %let fn&count=%scan(&fnames,&count,%str( )); %do %while(%length(&&fn&count)>0); %let count=%eval(&count+1); %let fn&count=%scan(&fnames,&count,%str( )); %end; %let nfn=%eval(&count-1); %end; %* Read log file names from the input directory and create a temporary file; %if &nfn=0 %then %do; x "&dir &indir&sep.*.log > &outdir&sep.dir.tmp"; %if &platf=UNIX %then %do; x "&dir &indir&sep.*.LOG >> &outdir&sep.dir.tmp"; %end; %end; %else %do; x "&dir &indir&sep&fn1 > &outdir&sep.dir.tmp"; %if &nfn>1 %then %do i=2 %to &nfn; x "&dir &indir&sep&&fn&i >> &outdir&sep.dir.tmp"; %end; %end; %* Get the current log file name to be deleted from the list; %let sysin = %sysfunc(getoption(sysin)); %if %quote(&sysin) ne %then %do; data _null_; log=reverse(scan(reverse("&sysin"),1,"&sep")); call symput('log',trim(scan(log,1,'.'))); run; %end; %else %let log = ; %* Get log file names and number of files; filename all_logs "&outdir&sep.dir.tmp"; data _null_; length text $200; infile all_logs lrecl=200 pad missover; input text 1-200; if index(text,"&sep") then text=reverse(scan(reverse(text),1,"&sep")); if upcase(text)=upcase("&log..LOG") then delete; retain i 0; i=i+1; call symput('text'||trim(left(put(i,8.))),trim(left(text))); call symput('ntext',trim(left(put(i,8.)))); run; %* Read each .log file from input directory and write out report if there are problems; %let j=0; %let k=0; %if &ntext>0 %then %do x=1 %to &ntext; filename logs "&indir&sep&&text&x"; data reprt(keep=filena num chek skey); length line $200 filena $22 chek $56 skey $88; infile logs lrecl=200 pad missover end=last; input line 1-200; filena="&&text&x"; retain err warn warn2 warn3 warn4 nots nots2 systint systwar 0 j &j k &k; if index(substr(line,1,5),'ERROR')>0 and index(substr(line,6,16),':')>0 then err+1; if index(substr(line,1,38),'WARNING: The data set')>0 or index(substr(line,1,38),'WARNING: Data set')>0 then warn+1; if index(line,'WARNING: Apparent symbolic reference')>0 and index(line,'not resolved')>0 then warn2+1; if index(line,'unbalanced quotation marks')>0 then warn3+1; if index(line,'WARNING: The variable')>0 or index(line,'WARNING: Multiple lengths')>0 then warn4+1; if index(line,'NOTE: MERGE statement has more than one data set')>0 then nots+1; if index(line,'NOTE: Variable')>0 and index(line,'is uninitialized')>0 then nots2+1; if index(substr(line,1,32),'SYSTEM INTERRUPTION:')>0 then systint+1; if index(substr(line,1,32),'SYSTEM WARNING:')>0 then systwar+1; if last then do; if (err+warn+warn2+warn3+warn4+nots+nots2+systint+systwar)>0 then do; j=j+1; if err>0 then do; num=1; chek=put(err,8.)||" Errors"; skey='ERROR (At first column of line. See bottom of file for pages)'; output; end; if warn>0 then do; num=2; chek=put(warn,8.)||" Warnings on incomplete data sets"; skey='WARNING: The data set (or) WARNING: Data set'; output; end; if warn2>0 then do; num=3; chek=put(warn2,8.)||" Warnings on unresolved symbolic references"; skey='WARNING: Apparent symbolic reference'; output; end; if warn3>0 then do; num=4; chek=put(warn3,8.)||" Warnings on unbalanced quotation marks"; skey='unbalanced quotation marks'; output; end; if warn4>0 then do; num=4.5; chek=put(warn4,8.)||" Warnings on variables"; skey='WARNING: The variable'; output; end; if nots>0 then do; num=5; chek=put(nots,8.)||' Notes on BY variable repeats in data merge'; skey='NOTE: MERGE statement has more than one data set with repeats of BY'; output; end; if nots2>0 then do; num=6; chek=put(nots2,8.)||' Notes on uninitialized variables'; skey='is uninitialized'; output; end; if systint>0 then do; num=7; chek=put(systint,8.)||" Arrow System Interruptions"; skey="SYSTEM INTERRUPTION:"; output; end; if systwar>0 then do; num=8; chek=put(systwar,8.)||" Arrow System Warnings"; skey="SYSTEM WARNING:"; output; end; end; else do; k=k+1; end; call symput('j',trim(left(put(j,8.)))); call symput('k',trim(left(put(k,8.)))); call symput('nerr',trim(left(err))); call symput('nwarn',trim(left(warn))); call symput('nwarn2',trim(left(warn2))); call symput('nwarn3',trim(left(warn3))); call symput('nwarn4',trim(left(warn4))); call symput('nnots',trim(left(nots))); call symput('nnots2',trim(left(nots2))); call symput('nsystint',trim(left(systint))); call symput('nsystwar',trim(left(systwar))); end; run; %if &x=1 %then %do; %str(data report; set reprt; run;); %put %str(LOG CHECKING REPORT); %put %str(DIRECTORY: %upcase(&indir)); %put %str(=============================================================================); %end; %if &x>1 %then %do; data report; set report reprt; run; %end; %* Display results in the log; %put %str(&&text&x); %if &nerr+&nwarn+&nwarn2+&nwarn3+&nwarn4+&nnots+&nnots2+&nsystint+&nsystwar=0 %then %do; %put %str( ---> 0 Errors, Critical Warnings and Notes and Arrow System Interruptions and Warnings.); %put; %end; %else %do; %if &nerr>0 %then %put %str( ---> &nerr Errors.); %if &nwarn>0 %then %put %str( ---> &nwarn Warnings on incomplete data sets.); %if &nwarn2>0 %then %put %str( ---> &nwarn2 Warnings on unresolved symbolic references.); %if &nwarn3>0 %then %put %str( ---> &nwarn3 Warnings on unbalanced quotation marks.); %if &nwarn4>0 %then %put %str( ---> &nwarn4 Warnings on variables.); %if &nnots>0 %then %put %str( ---> &nnots Notes on BY variable repeats in data merge.); %if &nnots2>0 %then %put %str( ---> &nnots2 Notes on uninitialized variables.); %if &nsystint>0 %then %put %str( ---> &nsystint Arrow System Interruptions.); %if &nsystwar>0 %then %put %str( ---> &nsystwar Arrow System Warnings.); %put; %end; %end; %* Delete temporary file dir.tmp; x "&del &outdir&sep.dir.tmp"; %* Write out report if any .log file has problems; %if &j^=0 and %length(&outfile)>0 %then %do; proc sort data=report out=report; by filena num; run; data report; set report; by filena num; run; data _null_; file "&outdir&sep.chklgs.lst" print notitles n=ps header=pagetop linesleft=ll; set report end=last; by filena num; if _n_>1 and ll<7 then put _page_; if first.filena then put @1 filena @; put @22 chek @73 skey ; if last.filena then put; if last then do; do while(ll>6); put; end; end; if ll<7 then do; put #50 / @1 158*'-' / "NOTE 1: THIS PROGRAM CHECKS ALL OR SPECIFIED " @; put "LOG FILES IN A DIRECTORY AND REPORTS ERRORS, WARNINGS ON INCOMPLETE " @; put "DATASETS, UNRESOLVED SYMBOLIC REFERENCES AND"; put @10 "UNBALANCED QUOTES, NOTES ON REPEAT BY VARIABLE DATASET MERGES AND " @; put "UNINITIALIZED VARIABLES, AND ARROW SYSTEM INTERRUPTION AND WARNING MESSAGES."; put @1 "NOTE 2: &ntext LOG " @; put %if &ntext=1 %then "FILE HAS "; %else %if &ntext>1 %then "FILES HAVE ";@; put "BEEN PROCESSED IN THE DIRECTORY. " @; put %if &k=1 %then "&k IS CLEAN. "; %else %if &k>1 %then "&k ARE CLEAN. ";@; put %if &j=1 %then "&j HAS PROBLEMS."/; %else %if &j>1 %then "&j HAVE PROBLEMS."/; put @1 'NOTE 3: USE THE SEARCH KEY WORDS TO FIND THE PROBLEMS IN THE SPECIFIED LOG FILE.'; end; return; pagetop: put _page_; pagenum+1; call symput('pno',trim(left(put(pagenum,8.)))); put @1 'PAGE ' pagenum / @138 'PROGRAM USED: CHKLOGS'//// @1 "DIRECTORY: %upcase(&indir)"// @1 "LOG FILE CHECKING REPORT (ONLY LOGS WITH PROBLEMS WILL BE REPORTED HERE)"; put @1 158*'-'; put @1 'LOG FILE NAME' @22 'CHECK POINTS' @73 'SEARCH KEY WORDS'/ @1 18*'-' @22 48*'-' @73 72*'-'; return; run; %* Add total number of pages, program name and run time to report; data _null_; length line2 $200; infile "&outdir&sep.chklgs.lst" lrecl=200 missover pad; file %if %length(&outfile)>0 %then "&outdir&sep&outfile"; %else "&outdir&sep.chklogs.lst";; input line2 1-200; if _n_=1 and input(substr(line2,1),bits8.)=12 then line2=substr(line2,2,158); if index(scan(line2,1),'PAGE')>0 then do; line2=trim(left(line2))||" OF &pno"; if _n_=1 then put @1 line2 @144 "&sysdate9" +1 "&systime"; else put @1 line2 @145 "&sysdate9" +1 "&systime"; delete; end; put _infile_; run; %* Delete temporary file chklgs.lst; x "&del &outdir&sep.chklgs.lst"; %end; %eom: %mend chklogs; *** Sample calls *****; %chklogs(indir = C:\user\sas, fnames = ad*.log, outfile = cklogs.lst, outdir = c:\user\sas);