Don Stanley Sysware Consulting Group Box 634 Wellington NEW ZEALAND
We needed to write an interface between SAS Software and Tivoli for a Sysware Consulting Group client. Tivoli is a tool that our client uses for (among other things) displaying application errors on an operators console. Our interface required to pass messages from a SAS job to Tivoli to display on the operators console. This paper does not discuss Tivoli operation or functionality.
The interface consists of a macro that can be called from any SAS job. At the heart of the macro are the call to Tivoli and defining the error message that is to be displayed. The macro is called %tivoli. Laurie Fleming from Sysware Consulting Group wrote that macro.
We decided that the easiest way to handle SAS --> Tivoli messaging from a batch environment was to have each application create its own table of error messages. Each message has a number, and it is that number that we pass to %tivoli. Upon receiving the number, %tivoli obtains the actual message.
We also can pass through to Tivoli the following fields:
|Source||This determines the Tivoli source system that the application calling Tivoli belongs to|
|Severity||This Tivoli attribute determines the colours and escalation action that Tivoli uses. Valid values defined in Tivoli include HARMLESS WARNING CRITICAL FATAL MINOR UNKNOWN|
|Progname||This is freeflow text describing the program name that called the Tivoli macro.|
|Action||Freeflow text that gives the people reading the message an idea of what to do about the message|
|Errornum||The errornum of the error being reported|
|Freeform||Freeform error message text|
We also extract from UNIX the host name that the failing job is running under and populate that into the Tivoli Hostname field.
At first glance it appears that &action and &freeform are the same thing. In fact we have set the interface up so that it sends an error message (picked up from a table), as well as these two fields. The logic is that the table message is a static message such as "ERROR: Business Key Check Failed". Then the &freeflow field expands on that message by being non-static. It can be populated according to what is happening at the time of the error. An example to go with the above message could be "Field Case Manager User Id Is Blank At Line 44 Of Batch 1031". The line number and the batch number are provided at run time. The &action field for this could read "Critical Error -- Stop Further Interface Runs And Raise High Priority Problem For SAS Support -- Do Not Bleep".
The table driven messages are provided by Proc Format. An example set of messages is
proc format ;
9979 = 'Critical Problem -- FTP Link Is Down'
9980 = 'Secondary Server Parameter File Does Not Exist'
9981 = 'Secondary Update Server Must Not Be Same As Primary Update Server'
9982 = 'Secondary Update Of batch Id In SAS Tables Failed -- Check SASLOG'
9983 = 'File INTERFCE.LOADED Not Available'
9984 = 'Attempt To Read Extract Failed -- No LEGCOUNT variable created -- Check SASLOG'
9985 = 'Attempt To Obtain batch_id Failed -- Check SASLOG'
9986 = 'The Extract Header Indicates Zero Records -- No Processing Will Occur'
9987 = 'Missing Business Key'
9988 = 'No Header Record Found'
9989 = 'Bad Filename Passed -- Not Interface -- Not Reconcile'
9990 = 'File Rename To Pending File Generated Bad Filename'
9991 = 'Sybload Failed'
9992 = 'Logon From UNIX To Mainframe Failed'
9993 = 'Non Existent Filename Passed To Interface'
9994 = 'Inconsistency Between Control File And Input File Header'
9995 = 'Control File Record Count Does Not Match Number Of Records'
9996 = 'Invalid Update Indicator or Record Type or Transaction Type'
9997 = 'Processing Wrong File -- Control Header Does Not Match File Header'
9998 = 'Control File Has No Pending Data'
9999 = 'The File Has Already Been Processed'
8888 = 'At Least 1 Database Loaded But Needed To Have Duplicate Keys Removed'
0 = 'Successful Run Of DTINTFC'
The following code is the Tivoli macro as written to run under SAS 6.12 using UNIX Solaris Operating System.
%macro tivoli(source=DTINTFC, severity=, progname=, action=, errornum=, freeform=)
/ des='Pass return codes to Tivoli';
Macro name tivoli.sas
Author Laurie Fleming
SYSWARE CONSULTING GROUP
Date-written 1 July 1997
Remarks Passes an error value to Tivoli, for
displaying (and subsequent action) on
the Tivoli console.
Formats tivoli (in library)
Issue %genfmt(format=tivoli) to get
Method Parse the parameters
%sysexec postemsg Execute the Tivoli posting procedure
as an external Unix command.
Laurie Fleming First written.
1 July 1997.
Don Stanley Added Support for Tivoli Hostname
1 August 1997. extracts using uname command
Define a global error value, and populate it.
%let __error = 1;
Parse parameters, checking up on defaults.
%if &source = %then
%let source = DTINTFC; (1)
%if &progname = %then %do;
%put ERROR: Programme name (progname) cannot be missing.;
%if &errornum = %then %do;
%put ERROR: Error number (errornum) cannot be missing.;
%if %eval(%sysfunc(verify(&errornum, 0123456789)) ne 0) %then %do;
%put ERROR: Error number (errornum) must be numeric.;
%if &severity =
%then %let severity = WARNING;
%let severity = %upcase(&severity);
%if not(&severity = FATAL or &severity = CRITICAL or &severity = MINOR
or &severity = WARNING or &severity = HARMLESS or &severity = UNKNOWN) %then %do;
%put ERROR: Invalid severity parameter: &severity..;
%put %str( Valid values are FATAL, CRITICAL, MINOR, WARNING, HARMLESS )
Since the free-form message can contain characters that macro can attempt to
interpret, quote the value to stop that.
%let freeform = %quote(&freeform);
%let action = %quote(&action);
This finds the hostname that the job is running under, and returns it to use in
%let fileref= hostname ;
%let rc = %sysfunc(filename(fileref,%str(uname -n),pipe)) ;
%let fileid = %sysfunc(fopen(hostname,S)) ;
%let rc = %sysfunc(fread(&fileid)) ;
%let rc = %sysfunc(fget(&fileid,hostname)) ;
%let rc = %sysfunc(fclose(&fileid)) ;
%let rc = %sysfunc(filename(fileref,' ')) ;
Issue the Tivoli posting procedure, passing through the appropriate parameters. If
freeform is blank, don't try to pass it through, because postemsg doesn't like it.
%sysexec postemsg -S tivoli1 (2)
-m "%qsysfunc(trim(%qsysfunc(putn(&errornum, tivoli.))))"
%if &freeform ne %then %do;
%if &action ne %then %do;
%let __error = 0;
There are various ways to call the macro. Note that the macro makes no attempt to stop the job, and even permits non error messages. Different jobs may have different requirements of the Tivoli macro.
In the %tivoli listing the numbered figures indicate code you will need to change to run the macro at your site. The –S parameter is the name of the Tivoli server, the uname code should run in any UNIX environment but will need changing for other environments, and the default source name can be obtained from your Tivoli administrator.
In the jobs that I use %tivoli in, the standard I have adopted is that error numbers between 9000 and 9999 will issue fatal messages to Tivoli. Numbers between 1 and 8999 are warning messages. 0 is a successful job post. I have written a second small macro, %call_tiv that calls the %tivoli macro and takes appropriate action.
%macro call_tiv(errornum,text,etype) / des='Interface With Tivoli' ;
PARAMETER -- errornum: the error number to be reported
-- text : the freeform text to be displayed
-- etype : the Tivoli errortype (WARNING HARMLESS FATAL CRITICAL etc)
GLOBAL IN -- none
GLOBAL OUT -- NONE
INTERNAL -- NONE
%put IN TIVOLI ERROR HANDLER ;
%put ERRORNUM &errornum ;
%put TEXT &text ;
%put ERRORTYPE &etype ;
Tivoli Error handling Routine.
This passes the appropriate message number across to Tivoli, as well as some
additional text. It calls the Tivoli error handler that Laurie Fleming wrote.
call the SAS macro that interfaces to Tivoli
quit the job
%if &errornum ge 9000 %then %do ;
%put ABENDING WITH RETURN CODE &errornum ;
%mend call_tiv ;
An example of how to call the %call_tiv macro follows::
get the filename from UNIX environment variable
%let ftpfile = %sysfunc(sysget(FILENAME)) ;
%put FTP FILE NAME &ftpfile ;
validate its existence
%if %sysfunc(fileexist(&ftpfile)) eq 0 %then %do ;
%call_tiv(9993,The Filename &ftpfile Was Passed To Interface Job At &sysdate
&systime But Does Not Exist,FATAL)