Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- %macro ut_sas8lchk(logfile=_default_,logref=_default_,outfile=_default_,
- debug=_default_);
- /*soh*****************************************************************
- DESCRIPTION : The ut_sas8lchk is a platform independent
- macro that scans the SAS log for
- occurrences of certain text
- messages (e.g. ERROR, WARNING, etc. It
- then produces a report (detail and
- summary) of the findings.
- SOFTWARE/VERSION# : SAS V8
- INPUT : SAS log file to be scanned is automatic
- on MVS(i.e. no need to specify the
- filename) and user supplied on W2K.
- OUTPUT MS Windows -
- Output report written to PRINT destination.
- ------------------------------------------------------------------------
- Parameters:
- Name Type Default Description and Valid Values
- -------- -------- -------- ------------------------------------------
- LOGFILE optional Full name of a file that contains a
- SAS log
- LOGREF optional Fileref previously defined by a FILENAME
- statement that points to a file
- containing a SAS log
- OUTFILE optional The name of file to write the report to.
- If this is not specified then the report
- will be written to the print file.
- OUTPUT to PDS members is not supported
- DEBUG required 0 %ut_logical value specifying whether debug
- mode is on or off
- ------------------------------------------------------------------------
- Usage Notes:
- If neither LOGFILE nor LOGREF are specified then the contents of
- the log window in display manager is scanned by this macro.
- ------------------------------------------------------------------------
- Assumptions:
- In MS Windows, a SAS configuration setting can cause problem with
- the use of the DM command that this macro uses. This applies when
- running SAS in display manager mode when your program uses the ODS
- statment. To resolve the problem, start SAS display manager, click
- on "Tools ... Options ... Preferences". When the resulting dialog
- box appears, click on "Results". At the bottom of this dialog box
- select "Preferred web browser" in the "View results using:" section.
- If "Internal browser" is selected then SAS will not be able to
- evaluate the contents of the log window when you call this macro
- ----------------------------------------------------------------------
- Typical Macro Call(s) and Description:
- MSWindows - %ut_sas8lchk(logfile=h:\myprogram.log)
- fileref mylog 'h:\myprogram.log';
- MSWindows - %ut_sas8lchk(logref=mylog)
- MSWindows - %ut_sas8lchk in display manager
- -----------------------------------------------------------------------
- BROAD-USE MODULE HISTORY
- Ver# Author Description
- ---- --------------- ----------------------------------------------
- 22 Strings to search for:
- 1 ARGUMENT TO FUNCTION
- 2 DIVISION BY ZERO DETECTED
- 3 ENDSAS
- 4 ERROR
- 5 FORMAT WAS TOO SMALL FOR THE NUMBER TO BE PRINTED
- 6 INVALID NUMERIC DATA
- 7 LOST CARD
- 8 MATHEMATICAL OPERATIONS COULD NOT BE PERFORMED
- 9 MISSING VALUES WERE GENERATED
- 10 MORE THAN ONE DATA SET WITH REPEATS OF BY VALUES
- 11 NOT FOUND
- 12 NOT PREVIOUSLY
- 13 NOTE: FORMATTED VALUES OF
- 14 ONE OR MORE LINES WERE TRUNCATED
- 15 SAS WENT TO A NEW LINE
- 16 SHIFTED BY THE "BEST" FORMAT
- 17 UERROR
- 18 UNINITIALIZED
- 19 UWARNING
- 20 VALUES HAVE BEEN CONVERTED TO
- 21 WARNING
- 22 _ERROR_=1
- Reports UWARNING separately from WARNING
- Reports ERROR and WARNING only when they are
- upper case in the log file and they are the
- first word in the line
- Added parameter OUTFILE to allow user to
- redirect the report to any file.
- Improved header lines:
- Reports number of message strings found in
- addition to the number of lines, in case
- more than one string is found in one line
- Displays physical path of scanned log file
- Displays userid of windows user (previously
- displayed only for MVS
- Sort list of strings found by descending count
- Changed the way options are restored, using
- one macro variable instead of 10
- Added message when both LOGREF and LOGFILE
- have been specified in the call to the macro
- Clarified message when neither LOGREF nor
- LOGFILE were specified in the macro call
- Changed macro names to make it more clear
- altlog1 = altlog1_ddname_path
- altlog2 = log_file_path
- Limited the number of log lines with bad
- strings that are reported to 1000 when
- running in display manager
- Added Found flag to summary to make it easier
- to see the non-zero counts of bad messages
- Added message when no bad messages found stating
- no searched messages found
- Changed format of warning to conform to
- ut_errmsg
- Enhanced header comment
- Added UNOTE when both LOGFILE and LOGREF are
- specified in call to the ut_sas8lchk
- Clears title and footnote lines in output and
- restores them at the end of the macro.
- Thus, the report will not have pre-existing
- titles and footnotes but the titles and
- footnotes will be the same after the macro
- call as they were before the macro call.
- Set option nodate
- Verifies that log file can be read. If not,
- then a message is displayed indicating the
- log file was not checked.
- **eoh******************************************************************/
- %if %bquote(%upcase(&logfile)) = %upcase(_default_) %then
- %let logfile =;
- %if %bquote(%upcase(&logref)) = %upcase(_default_) %then
- %let logref =;
- %if %bquote(%upcase(&outfile)) = %upcase(_default_) %then
- %let outfile =;
- %if %bquote(%upcase(&debug)) = %upcase(_default_) %then
- %let debug = 0;
- %if %sysfunc(indexw(%str(Y T YES TRUE ON OUI JA),%upcase(&debug)))
- %then %let debug = 1;
- %else %if %sysfunc(indexw(%str(N F NO FALSE OFF NON NEIN),
- %upcase(&debug))) %then %let debug = 0;
- %if &debug ^= 1 & &debug ^= 0 %then %do;
- %put UNOTE(ut_sas8lchk):
- INVALID LOGICAL VALUE OF DEBUG = %nrbquote(&debug);
- %let debug = 0;
- %end;
- %local options checklog lookfors mvs_sas8lchk_entry altlog1_ddname_path
- log_file_path rc i numtitles numfootnotes fid rc;
- %*---------------------------------------------------------------------;
- %* ;
- %* Save original values of changed options. ;
- %* ;
- %*---------------------------------------------------------------------;
- %let options = %sysfunc(getoption(formdlim));
- %if %bquote(&options) ^= %then %let options = formdlim="&options";
- %let options = &options
- %sysfunc(getoption(center))
- %sysfunc(getoption(caps))
- %sysfunc(getoption(sgen))
- %sysfunc(getoption(pageno,keyword))
- %sysfunc(getoption(date))
- %sysfunc(getoption(notes))
- %sysfunc(getoption(mprint))
- %sysfunc(getoption(source))
- %sysfunc(getoption(source2))
- %sysfunc(getoption(mlogic))
- ;
- %if ^ &debug %then %do;
- options nomprint nosource nosource2 nomlogic nonotes;
- %end;
- options FORMDLIM='-' nocenter nosgen pageno=1 nodate;
- *======================================================================;
- * Save pre-existing titles and foonotes for later restoration;
- * and clear all title and footnote lines;
- *======================================================================;
- proc sql;
- create table _cltitles as select * from dictionary.titles;
- quit;
- %let numtitles = 0;
- %let numfootnotes = 0;
- data _null_;
- if eof then do;
- call symput('numtitles',trim(left(put(title_num,2.0))));
- call symput('numfootnotes',trim(left(put(footnote_num,2.0))));
- end;
- set _cltitles end=eof;
- if type = 'T' then do;
- title_num + 1;
- call symput('title' || trim(left(put(title_num,2.0))),
- 'title' || trim(left(put(number,2.0))) || ' ' || trim(text));
- end;
- else if type = 'F' then do;
- footnote_num + 1;
- call symput('footnote' || trim(left(put(footnote_num,2.0))),
- 'footnote' || trim(left(put(number,2.0))) || ' ' || trim(text));
- end;
- run;
- %if &numtitles > 0 %then %do;
- title;
- %end;
- %if &numfootnotes > 0 %then %do;
- footnote;
- %end;
- %*---------------------------------------------------------------------;
- %* Verify LOGFILE and LOGREF parameters;
- %*---------------------------------------------------------------------;
- %if %bquote(&logfile) ^= %then %do;
- %if ^ %sysfunc(fileexist(&logfile)) %then %do;
- %put UWARNING(ut_sas8lchk): specified log file does not exist
- &logfile;
- %goto endmac;
- %end;
- %end;
- %if %bquote(&logref) ^= %then %do;
- %let rc = %sysfunc(fileref(&logref));
- %if &debug %then
- %put UNOTE(ut_sas8lchk): logref fileref (&logref) exist rc=&rc;
- %if &rc < 0 %then %do;
- %put UWARNING(ut_sas8lchk): specified log fileref exists but the
- file it points to does not exist - &logref;
- %goto endmac;
- %end;
- %if &rc > 0 %then %do;
- %put UWARNING(ut_sas8lchk): specified log fileref does not exist
- &logref;
- %goto endmac;
- %end;
- %end;
- %if %bquote(&logfile) ^= & %bquote(&logref) ^= %then %do;
- %put UNOTE(ut_sas8lchk): LOGFILE and LOGREF parameters have both
- been specified - at most one should be specified;
- %end;
- *----------------------------------------------------------------------;
- * ;
- * Determine Operating system and assign appropriate ;
- * output destination. ;
- %* ;
- %* MVS will write LOG scan report to fileref CHECKLOG ;
- %* to be viewed in IOF. ;
- %* W2K will write report to PRINT fileref. ;
- *----------------------------------------------------------------------;
- %if &sysscp = OS %then %do;
- *--------------------------------------------------------------------;
- * ;
- * In MVS, determine if user invoked SAS via the standard SAS8 clist ;
- * or by using the SAS8LCHK clist. The SAS8LCHK clist ;
- * allocates an eyecatcher file with fileref/ddname ;
- * altlog1. A non-blank value for this PATHNAME ;
- * indicates entry via SAS8LCHK clist, which enables ;
- * the automatic SAS log checking and exit. Use of the ;
- * UT_SAS8LCHK macro is therefore possible in normal SAS8 ;
- * entry. ;
- * ;
- *--------------------------------------------------------------------;
- option caps;
- %let altlog1_ddname_path = %sysfunc(pathname(altlog1));
- *--------------------------------------------------------------------;
- * ;
- * If macro variable altlog1_ddname_path is blank, then the user ;
- * is using the std SAS8 clist. Otherwise, the user ;
- * is using the SAS8LCHK clist. If they are using the ;
- * SAS8 clist, then allow use of the SAS8LCHK macro ;
- * just like W2K by using the macro variables ;
- * LOGREF or LOGFILE passed by the user. ;
- * ;
- *--------------------------------------------------------------------;
- %if %bquote(&altlog1_ddname_path) = %then %do; /* Entry via SAS8 */
- %if %bquote(&logfile) ne %then %do; /* Use user logfile */
- filename altlog1 "&logfile" disp=shr;
- %end;
- %let mvs_sas8lchk_entry = 0;
- %let checklog = print; /* Output to PRINT */
- %end;
- %else %do; /* Entry via SAS8LCHK */
- %let mvs_sas8lchk_entry = 1;
- %let checklog = checklog;
- %end;
- %end;
- %else %if &sysscp = WIN %then %do;
- %if %bquote(&logfile) ^= %then %do;
- filename altlog1 "&logfile";
- %end;
- %let checklog = print;
- %let mvs_sas8lchk_entry = 0;
- %end;
- %else %do;
- %put UNOTE(ut_sas8lchk): operating system not recognised = &sysscp;
- %goto endmac;
- %end;
- %*---------------------------------------------------------------------;
- %* ;
- %* If LOGREF and LOGFILE are both absent, then write log window to ;
- %* a temporary file for input to the macro. This action is ;
- %* only necessary if the user is NOT using the SAS8LCHK clist ;
- %* (or batch) on MVS. ;
- %* ;
- %*---------------------------------------------------------------------;
- %if %bquote(&logref) = & %bquote(&logfile) = & ^ &mvs_sas8lchk_entry
- %then %do;
- %if &sysprocessname = %str(DMS Process) %then %do;
- filename _lclchk temp;
- dm log 'file _lclchk replace';
- %let logref = _lclchk;
- %if &debug %then %do;
- filename _lclchk list;
- data _null_;
- infile _lclchk;
- input;
- put 'UNOTE(ut_sas8lchk): debug ' _infile_;
- run;
- %end;
- %end;
- %else %do;
- %put UNOTE(ut_sas8lchk): neither LOGFILE nor LOGREF parameters
- have been specified - one must be specified when not executing
- in display manager;
- %goto endmac;
- %end;
- %end;
- %if %bquote(&logref) ^= %then
- %let log_file_path = %sysfunc(pathname(&logref));
- %else %if %bquote(&logfile) ^= %then %let log_file_path = &logfile;
- %*=====================================================================;
- %* Verify that the log file can be opened in read mode;
- %*=====================================================================;
- %if &logref ^= %then %do; /* Use user logref if supplied */
- %let fid = %sysfunc(fopen(&logref,i));
- %end;
- %else %do; /* else use logfile file */
- %let fid = %sysfunc(fopen(altlog1,i));
- %end;
- %if &debug %then %put fid = &fid;
- %if &fid > 0 %then %do;
- %let rc = %sysfunc(fclose(&fid));
- %if &debug %then %put close rc=&rc;
- %end;
- %else %do;
- data _null_;
- %if %bquote(&outfile) = %then %do;
- file &checklog;
- %end;
- %else %do;
- file "&outfile";
- %end;
- date = today();
- time = time();
- put "SAS LOG FILE SCANNED &log_file_path";
- %if &sysscp = OS %then %do;
- put @3 "Jobname: &sysjobid";
- %end;
- put @3 "User : &sysuserid";
- put @3 "Date(of SCAN) : " date date9.;
- put @3 "Time(of SCAN) : " time time8.0;
- put @3 "Operating System(of SCAN): &sysscp &sysscpl";
- put @3 "SAS Version(of SCAN) : &sysver";
- put //// @ 20 'Unable to open log file. Log check not performed.';
- stop;
- run;
- %goto endmac;
- %end;
- *----------------------------------------------------------------------;
- * ;
- * Create a data set containing things to look for in the log. ;
- * ;
- * Each text string will be assigned to a macro variable ;
- * (lookfor1, lookfor2, lookfor3, etc). ;
- * ;
- *----------------------------------------------------------------------;
- data _clsrchfor;
- length lookfor $ 80. count 8;
- count = 0;
- lookfor='er' || 'ror'; output;
- lookfor='war' || 'ning'; output;
- lookfor='unin' || 'itialized'; output;
- lookfor='mis' || 'sing values were generated'; output;
- lookfor='uer' || 'ror'; output;
- lookfor='more th' || 'an one data set with repeats of BY values';
- output;
- lookfor='arg' || 'ument to function'; output;
- lookfor='valu' || 'es have been converted to'; output;
- lookfor='mathema' || 'tical operations could not be performed';
- output;
- lookfor = 'lost ' || 'card'; output;
- lookfor = 'not' || ' found'; output;
- lookfor = 'not' || ' previously'; output;
- lookfor = '_error_' || '=1'; output;
- lookfor = 'end' || 'sas'; output;
- lookfor = 'uwar' || 'ning'; output;
- lookfor = 'division by' || ' zero detected'; output;
- lookfor = 'sas went' || ' to a new line'; output;
- lookfor = 'in' || 'valid numeric data'; output;
- lookfor = 'On' || 'e or more lines were truncated'; output;
- lookfor = 'format was too' ||' small for the number to be printed';
- output;
- lookfor = 'shifted' || ' by the ""best"" format'; output;
- lookfor = 'note: formatted values of'; output;
- stop;
- run;
- %let lookfors = 0;
- data _clsrchfor;
- set _clsrchfor end=last;
- if lookfor ^= ' ';
- lookfor = upcase(lookfor);
- looknum + 1;
- call symput('lookfor' || trim(left(put(looknum,8.0))),
- trim(left(lookfor)));
- if last then call symput('lookfors',trim(left(put(looknum,8.0))));
- lookfor = tranwrd(lookfor,'""BEST""','"BEST"');
- drop looknum;
- run;
- %if &debug %then %do;
- %put lookfors=&lookfors;
- %do i = 1 %to &lookfors;
- %put lookfor&i=&&lookfor&i;
- %end;
- %put;
- %end;
- data _cllines (keep=logrec logrecline)
- _clmsg (keep=msg_found logrecline);
- length msg msg_found $80.;
- date = today();
- time = time();
- %if &logref ^= %then %do; /* Use user logref if supplied */
- infile &logref end=last missover length=lv;
- %end;
- %else %do; /* else use logfile file */
- infile altlog1 end=last missover length=lv;
- %end;
- input @1 logrec $varying132. lv;
- %if &debug %then %do;
- file log;
- if _n_ = 1 then put 'UNOTE(ut_sas8lchk): starting debug list of log file:'/;
- put _infile_;
- if last then put 'UNOTE(ut_sas8lchk): ending debug list of log file:'/;
- %end;
- %if %bquote(&outfile) = %then %do;
- file &checklog;
- %end;
- %else %do;
- file "&outfile";
- %end;
- if _n_ = 1 then do;
- put "SAS LOG FILE SCANNED &log_file_path";
- %if &sysscp = OS %then %do;
- put @3 "Jobname: &sysjobid";
- %end;
- put @3 "User : &sysuserid";
- put @3 "Date(of SCAN) : " date date9.;
- put @3 "Time(of SCAN) : " time time8.0;
- put @3 "Operating System(of SCAN): &sysscp &sysscpl";
- put @3 "SAS Version(of SCAN) : &sysver";
- put ;
- end;
- logrecline = _n_;
- badrec = 0;
- *--------------------------------------------------------------------;
- * Scan for er-ror and wa-rning in column 1 only ;
- * Scan for other messages anywhere in the log line ;
- *--------------------------------------------------------------------;
- %do i = 1 %to &lookfors;
- *------------------------------------------------------------------;
- %bquote(* Message &i;)
- *------------------------------------------------------------------;
- msg = "%substr(&&lookfor&i,1,2)" || "%substr(&&lookfor&i,3)";
- found_at = index(upcase(logrec),trim(msg));
- msg_found = ' ';
- if found_at in (1 2) and ((msg = 'ER' || 'ROR' | msg = 'WAR' || 'NING')
- & upcase(left(logrec)) ^=: 'UER' ||'ROR' &
- upcase(left(logrec)) ^=: 'UWA' || 'RNING')
- then do;
- if index(logrec,trim(msg)) in (1 2) then do;
- msgs_found + 1;
- msg_found = msg;
- if ^ badrec then do;
- recs_found + 1;
- badrec = 1;
- output _cllines;
- end;
- end;
- end;
- else if found_at ge 1 and
- (msg ^= 'ER' || 'ROR' and MSG ^= 'WAR' || 'NING') then do;
- msgs_found + 1;
- msg_found = msg;
- if ^ badrec then do;
- recs_found + 1;
- badrec = 1;
- output _cllines;
- end;
- end;
- if msg_found ^= ' ' then output _clmsg;
- %end;
- if last then do;
- put 'Total log file lines read ' _n_;
- if . < recs_found < 1 & . < msgs_found < 1 then
- put 'No searched messages found.';
- else put 'Number of lines containing at least one searched message '
- recs_found / 'Number of searched messages found '
- msgs_found // ;
- end;
- run;
- proc freq data=_clmsg;
- tables msg_found / noprint out=_clmsg_found(keep=msg_found count);
- run;
- proc sort data = _clsrchfor;
- by lookfor;
- run;
- %if &debug %then %do;
- proc print data = _clmsg width=minimum;
- title '(ut_sas8lchk) debug: _clmsg data set';
- run;
- proc print data = _clmsg_found width=minimum;
- title '(ut_sas8lchk) debug: _clmsg_found data set';
- run;
- proc print data = _clsrchfor width=minimum;
- title '(ut_sas8lchk) debug: _clsrchfor data set';
- run;
- title;
- %end;
- data _clmsg_found;
- merge _clsrchfor (rename=(lookfor=msg_found)) _clmsg_found;
- by msg_found;
- run;
- proc sort data = _clmsg_found;
- by descending count msg_found;
- run;
- proc printto print=
- %if %bquote(&outfile) = %then %do;
- &checklog
- %end;
- %else %do;
- "&outfile"
- %end;
- ;
- run;
- proc print noobs data=_clmsg_found label;
- label msg_found='Searched Message'
- count = 'Frequency';
- run;
- data _null_;
- file print;
- if eof & _n_ = 1 then
- put //// @20 'N o s e a r c h e d m e s s a g e s f o u n d !';
- set _cllines end=eof;
- %if &sysprocessname = %str(DMS Process) %then %do;
- if _n_ <= 1000 then put @2 'Record=' logrecline '-->' / logrec /;
- else do;
- put // @20 'Further records will not be printed';
- stop;
- end;
- %end;
- %else %do;
- put @2 'Record=' logrecline '-->' / logrec /;
- %end;
- run;
- proc printto;
- run;
- *----------------------------------------------------------------------;
- * Check for OS before clearing a fileref. You cannot clear a ;
- * fileref that was assigned via JCL (you will get a warning). ;
- * Only do the FILENAME CLEAR in MVS if it is a non-temp dataset. ;
- * A temporary dataset (i.e. JCL defined) will begin with SYS. ;
- *----------------------------------------------------------------------;
- %if &sysscp = OS %then %do;
- %if %substr(%str(&altlog1_ddname_path ),1,3) ^= SYS %then %do;
- %if %sysfunc(fileref(altlog1)) <= 0 %then %do;
- filename altlog1 clear;
- %end;
- %end;
- %end;
- %else %if &sysscp = WIN %then %do;
- %if %sysfunc(fileref(altlog1)) <= 0 %then %do;
- filename altlog1 clear;
- %end;
- %end;
- %endmac:
- *----------------------------------------------------------------------;
- * Return options to their original value. ;
- *----------------------------------------------------------------------;
- proc datasets lib = work nolist;
- delete _cl:;
- run; quit;
- %if &sysscp = OS & &sysenv = FORE & &mvs_sas8lchk_entry = 1 %then %do;
- *--------------------------------------------------------------------;
- * ;
- * If OS is MVS and environment is foreground, ;
- * and we are in the SAS8LCHK clist, then ENDSAS. ;
- * ;
- *--------------------------------------------------------------------;
- endsas;
- %end;
- %if &numtitles > 0 %then %do i = 1 %to &numtitles;
- &&title&i;
- %end;
- %if &numfootnotes > 0 %then %do i = 1 %to &numfootnotes;
- &&footnote&i;
- %end;
- options &options;
- %mend;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement