Production Ready Macros for SAS Application Developers
https://github.com/sasjs/core
mf_abort.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief abort gracefully according to context
4  @details Do not use directly! See bottom of explanation for details.
5 
6  Configures an abort mechanism according to site specific policies or the
7  particulars of an environment. For instance, can stream custom
8  results back to the client in an STP Web App context, or completely stop
9  in the case of a batch run.
10 
11  For the sharp eyed readers - this is no longer a macro function!! It became
12  a macro procedure during a project and now it's kinda stuck that way until
13  that project is updated (if it's ever updated). In the meantime we created
14  `mp_abort` which is just a wrapper for this one, and so we recomend you use
15  that for forwards compatibility reasons.
16 
17  @param mac= to contain the name of the calling macro
18  @param type= deprecated. Not used.
19  @param msg= message to be returned
20  @param iftrue= supply a condition under which the macro should be executed.
21 
22  @version 9.2
23  @author Allan Bowe
24 **/
25 
26 %macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1)
27 )/*/STORE SOURCE*/;
28 
29  %if not(%eval(%unquote(&iftrue))) %then %return;
30 
31  %put NOTE: /// mf_abort macro executing //;
32  %if %length(&mac)>0 %then %put NOTE- called by &mac;
33  %put NOTE - &msg;
34 
35  /* Stored Process Server web app context */
36  %if %symexist(_metaperson) or "&SYSPROCESSNAME"="Compute Server" %then %do;
37  options obs=max replace nosyntaxcheck mprint;
38  /* extract log err / warn, if exist */
39  %local logloc logline;
40  %global logmsg; /* capture global messages */
41  %if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
42  %else %let logloc=%qsysfunc(getoption(LOG));
43  proc printto log=log;run;
44  %if %length(&logloc)>0 %then %do;
45  %let logline=0;
46  data _null_;
47  infile &logloc lrecl=5000;
48  input; putlog _infile_;
49  i=1;
50  retain logonce 0;
51  if (_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR") and logonce=0 then do;
52  call symputx('logline',_n_);
53  logonce+1;
54  end;
55  run;
56  /* capture log including lines BEFORE the err */
57  %if &logline>0 %then %do;
58  data _null_;
59  infile &logloc lrecl=5000;
60  input;
61  i=1;
62  stoploop=0;
63  if _n_ ge &logline-5 and stoploop=0 then do until (i>12);
64  call symputx('logmsg',catx('\n',symget('logmsg'),_infile_));
65  input;
66  i+1;
67  stoploop=1;
68  end;
69  if stoploop=1 then stop;
70  run;
71  %end;
72  %end;
73 
74  /* send response in SASjs JSON format */
75  data _null_;
76  file _webout mod lrecl=32000;
77  length msg $32767;
78  sasdatetime=datetime();
79  msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
80  /* escape the quotes */
81  msg=tranwrd(msg,'"','\"');
82  /* ditch the CRLFs as chrome complains */
83  msg=compress(msg,,'kw');
84  /* quote without quoting the quotes (which are escaped instead) */
85  msg=cats('"',msg,'"');
86  if symexist('_debug') then debug=symget('_debug');
87  if debug ge 131 then put '>>weboutBEGIN<<';
88  put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
89  put ',"sasjsAbort" : [{';
90  put ' "MSG":' msg ;
91  put ' ,"MAC": "' "&mac" '"}]';
92  put ",""SYSUSERID"" : ""&sysuserid"" ";
93  if symexist('_metauser') then do;
94  _METAUSER=quote(trim(symget('_METAUSER')));
95  put ",""_METAUSER"": " _METAUSER;
96  _METAPERSON=quote(trim(symget('_METAPERSON')));
97  put ',"_METAPERSON": ' _METAPERSON;
98  end;
99  _PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
100  put ',"_PROGRAM" : ' _PROGRAM ;
101  put ",""SYSCC"" : ""&syscc"" ";
102  put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
103  put ",""SYSJOBID"" : ""&sysjobid"" ";
104  put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
105  put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
106  put "}" @;
107  %if &_debug ge 131 %then %do;
108  put '>>weboutEND<<';
109  %end;
110  run;
111  %let syscc=0;
112  %if %symexist(SYS_JES_JOB_URI) %then %do;
113  /* refer web service output to file service in one hit */
114  filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json";
115  %let rc=%sysfunc(fcopy(_web,_webout));
116  %end;
117  %else %do;
118  data _null_;
119  if symexist('sysprocessmode')
120  then if symget("sysprocessmode")="SAS Stored Process Server"
121  then rc=stpsrvset('program error', 0);
122  run;
123  %end;
124  /**
125  * endsas is reliable but kills some deployments.
126  * Abort variants are ungraceful (non zero return code)
127  * This approach lets SAS run silently until the end :-)
128  */
129  %put _all_;
130  filename skip temp;
131  data _null_;
132  file skip;
133  put '%macro skip(); %macro skippy();';
134  run;
135  %inc skip;
136  %end;
137  %else %do;
138  %put _all_;
139  %abort cancel;
140  %end;
141 %mend;