How many a times at work have you gone thru the logs looking for ERROR, WARNINGS, NOTES etc for more information about the generated problem?…I’ve been doing a lot like that lately for developing / debugging / lines of code for more information…I just wished I had a piece of code that would search and report me the location / line number and few more information about….luckily I found this macro in a SAS SUGI paper…here’s the link….www2.sas.com/proceedings/sugi25/25/po/25p219.pdf
Then I had to customize it a little more to make the macro browse thru a folder of log files with a common runtime so that I can get all the errors into one report file…
Here’s an example and the full code below….
I intentionally induced couple of errors highlighted in RED font locations in these datasteps below….
%let LogLoc=C:\SASDATA;
%let cyle_runtime=10OCT2010102001;
proc printto log = “&LogLoc.\example1_&cyle_runtime..log” ; run ;
DATA example1;
INPUT ID $ 1 SBP 2 – 4 DBP 5 – 7 GENDER $ 8 AGE 9 – 10 WT 11 – 13 ;
DATALINES ;
1120 80M15115
2130 70F25180
3140100M89170
4120 80F30150
5125 80F20110
;
RUN ;
PROC MENS ;
RUN ;
proc printto ; run ;
proc printto log = “&LogLoc.\example2_&cyle_runtime..log” ; run ;
DATA CDS2;
INPUT @ 1 CATEGORY $9. @ 10 NUMBER 3. ;
DATALINES ;
JAZZ 252
POP 49
CLASSICAL 59
RAP 21
GOSPEL 44
JAZZ 21
;
run ;
ODS RTF ;
PROC FREQ DATA = CDS ORDER =FREQ; WEIGHT NUMBER;
TITLE3 ‘READ IN SUMMARIZED DATA’ ;
TABLES CATEGORY;
RUN ;
proc printto ; run ;
This code produces 2 log files at C:\SASDATA\ with timestamp on them…
Now running my SAS Macro %ReportErrorWarnings with the right parameters would result in a Error file at the same location…
%ReportErrorsWarnings (s earchstr,searchloc,searchfiles,outfile,lines2display);
The macro from the SUGI paper was good…it created an arrow against the error / filename and linenumber…I customized the macro to browse thru a folder / location of logs etc… I agree it isn’t pretty but it works for me….This error file gives me the exact location (for eg line 20 in example 1 file and 2 lines above and below….). The number of lines to display above and below is again customizable though as the last parameter…
Similarly one can search for “ERROR:”,”WARNING:”, “NOTE:”,”not resolved”, “uninitialized”, “invalid data”, “_ERROR_=1”, “missing values”, “lock held by” etc…any other usual errors that you might want to track .
%ReportErrorsWarnings (s earchstr,searchloc,searchfiles,outfile,lines2display);
Here’s the full code …with the repeatition of the above code again…for context…
You can get it from here as well…
http://snipplr.com/view/42133/sas-macros-to-search-and-report-errors-and-warnings-from-your-sas-logs/
or
http://www.docstoc.com/docs/57181769/SAS-Macros-to-Search-and-Report-Errors-and-Warnings-from-your-SAS-Logs
%macro recsinds(table,macvar);
/*———————————————————————-
this macro can be used to get the count of observations in a dataset
into a macrovariable that you give.
usage: %recsinds(sashelp.class,macvar);
&macvar is the observation count of your dataset
———————————————————————-*/
%global &macvar;
%local handle rc;
%let handle = %sysfunc (open(&table)); /* open the table */
%if &handle %then
%do ;
/* get the observation count into the macvar macro variable */
%let &macvar = %sysfunc (attrn(&handle, nlobs));
%let rc = %sysfunc (close(&handle)); /* close the dataset */
%end ;
/* write the record count to the log */
%put recsinds &table: &&&macvar. &macvar=&&&macvar.;
%mend recsinds;
%macro SearchErrorsWarnings(strg,loc,dsx,mm= 1 );
* mm=# of lines to display before and after target lines. mm=0,1,2 …etc.;
filename dd “&loc.\&dsx.” ;
%global nnn; *nnn=# of records in dsx;
data aa (keep= filen arrow linum xx);
infile dd length=ln end=last;
length llprted pthru 8 arrow $ 3 xx $ 120 filen $ 400 ;
retain llprted pthru 0 ;
*LLPRTed:line # of Last Line Printed; * PThru: to be line # of the last of: * the 2mm+1 lines to be displayed;
length %do jj= 1 %to &mm; x&jj %end ; XT $ 120 ;
retain filen XT ‘ ‘ %do jj= 1 %to &mm; x&jj %end ;;;
filen= “&dsx.” ;
* These store the mm lines that are; * to be printed prior to a Find; * Next save these mm lines;
%do jj= %eval (&mm- 1 ) %to 1 %by – 1 ;
x %eval (&jj+ 1 )=x&jj;;
%end ;
x1=XT;
input XT $varying120. ln;
XT=upcase(XT);
if index (XT, “THE SAS SYSTEM” )> 0 then delete;
if index (XT,upcase( “&strg” ))> 0 then
do;
filen= “========================================” ;linum= . ; arrow= ‘=====’ ; xx= ‘========================================================================================’ ;
output;
filen= “&dsx.” ; arrow= ” ;
* Found one!; * Insert a blank line between finds; * provided the scopes of two finds ; * do not overlap;
if (_n_ > pthru + &mm + 1 ) & pthru > 0
then
do;
filen= “========================================” ;linum= . ; arrow= ‘=====’ ; xx= ‘========================================================================================’ ;
output;
filen= “&dsx.” ; arrow= ” ;
end;
*Output mm lines preceding the find;
%do jj=&mm %to 1 %by – 1 ;
if &jj<_n_ – pthru then
do;
xx=x&jj;
linum=_n_ – &jj;
output;
end;
%end ;
linum=_n_;
xx=XT;
if &mm > 0 then arrow= “–>” ;
llprted=_n_;
output; * Output the Found line;
* Compute pthru, the line # of the ; * last line of the scope so that the; * next mm lines can be printed;
pthru=_n_+&mm;
arrow= ‘ ‘ ;
end;
else
do;
if _n_<=pthru then
do;
linum=_n_;
xx=XT;
output;
* Outputting the next mm lines;
end;
end;
if last then call symput( ‘nnn’ ,left(put(_n_, 5. )));
run;
proc append base=allout data=aa; run;
%mend SearchErrorsWarnings;
%macro ReportErrorsWarnings(searchstr,searchloc,searchfiles,outfile,lines2display);
proc sql;
drop table allout;
drop table aa;
drop table new;
quit;
%let dircmd0= %nrbquote ( %str (dir /b /s %”) %str (&searchloc.\&searchfiles.) %str (%”));
FILENAME rootloc pipe “&dircmd0” ;
/*data _null_; run;*/
data new;
length file $ 1000 ;
infile rootloc;
input file;
cnt=count(file, “\” );
file=translate(file, ‘ ‘ , ‘\’ );
file=scan(file,cnt+ 1 , ‘ ‘ );
call symput(compress( ‘filen’ ||_N_),file);
run;
%recsinds (new,nobs);
%if &nobs gt 0 %then %do ;
%do k= 1 %to &nobs;
%SearchErrorsWarnings (& searchstr. ,& searchloc. ,&&filen& k. ,mm=& lines2display. );
%end ;
data allout;
retain filen linum arrow xx;
set allout;
run;
data _null_;
file “&outfile.” lrecl= 32767 ;
set allout;
if _n_ = 1 then
do;
put “FILENAME” ’09’x “LINE #” ’09’x “ARROW” ’09’x “MESSAGE” ;
put “*****************************************************************************************************” ;
end;
put filen ’09’x linum ’09’x arrow ’09’x xx ’09’x ;
run;
%end ;
%else
%do ;
%put ==================;
%put NO LOGS TO PROCESS;
%put ==================;
%end ;
%mend ReportErrorsWarnings;
%let LogLoc=C:\SASDATA;
%let cyle_runtime=10OCT2010102001;
proc printto log = “&LogLoc.\example1_&cyle_runtime..log” ; run ;
DATA example1;
INPUT ID $ 1 SBP 2 – 4 DBP 5 – 7 GENDER $ 8 AGE 9 – 10 WT 11 – 13 ;
DATALINES ;
1120 80M15115
2130 70F25180
3140100M89170
4120 80F30150
5125 80F20110
;
RUN ;
PROC MENS ;
RUN ;
proc printto ; run ;
proc printto log = “&LogLoc.\example2_&cyle_runtime..log” ; run ;
DATA CDS2;
INPUT @ 1 CATEGORY $9. @ 10 NUMBER 3. ;
DATALINES ;
JAZZ 252
POP 49
CLASSICAL 59
RAP 21
GOSPEL 44
JAZZ 21
;
run ;
ODS RTF ;
PROC FREQ DATA =CDS ORDER =FREQ; WEIGHT NUMBER;
TITLE3 ‘READ IN SUMMARIZED DATA’ ;
TABLES CATEGORY;
RUN ;
proc printto ; run ;
%ReportErrorsWarnings (ERROR:,& LogLoc. ,*_& cyle_runtime..l og,& LogLoc. \error_& cyle_runtime..t xt, 2 );