Site hosted by Build your free website today!

Don Stanley
Sysware Consulting Group
Box 634

Contact Don Stanley

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 ;
   value tivoli
   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       
       Author                     Laurie Fleming
       Date-written               1 July 1997
       Stored                     /sasautos/
       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
                                  the source.

       Method                     Parse the parameters
       %sysexec postemsg          Execute the Tivoli posting procedure
                                  as an external Unix command.

       Modification History
       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.

%global __error;
%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.;
    %goto EndMac;
%if &errornum = %then %do;
    %put ERROR: Error number (errornum) cannot be missing.;
    %goto EndMac;
%if %eval(%sysfunc(verify(&errornum, 0123456789)) ne 0) %then %do;
    %put ERROR: Error number (errornum) must be numeric.;
    %goto EndMac;
%if &severity =
    %then %let severity = WARNING;
    %else %do;
          %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 )
                   %str(and UNKNOWN.);
              %goto EndMac;
       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.))))"
                  -r &severity
%if &freeform ne %then %do;
%if &action ne %then %do;
                  &source &source;
%let __error = 0;
%mend tivoli;
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' ;

 macro variables
  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 


%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 ;
      endsas ;
    %end ;

%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)
 %end ;