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  @cond
25 **/
26 
27 %macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1)
28 )/*/STORE SOURCE*/;
29 
30  %if not(%eval(%unquote(&iftrue))) %then %return;
31 
32  %put NOTE: /// mf_abort macro executing //;
33  %if %length(&mac)>0 %then %put NOTE- called by &mac;
34  %put NOTE - &msg;
35 
36  /* Stored Process Server web app context */
37  %if %symexist(_metaperson) or "&SYSPROCESSNAME"="Compute Server" %then %do;
38  options obs=max replace nosyntaxcheck mprint;
39  /* extract log err / warn, if exist */
40  %local logloc logline;
41  %global logmsg; /* capture global messages */
42  %if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
43  %else %let logloc=%qsysfunc(getoption(LOG));
44  proc printto log=log;run;
45  %if %length(&logloc)>0 %then %do;
46  %let logline=0;
47  data _null_;
48  infile &logloc lrecl=5000;
49  input; putlog _infile_;
50  i=1;
51  retain logonce 0;
52  if (_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR") and logonce=0 then do;
53  call symputx('logline',_n_);
54  logonce+1;
55  end;
56  run;
57  /* capture log including lines BEFORE the err */
58  %if &logline>0 %then %do;
59  data _null_;
60  infile &logloc lrecl=5000;
61  input;
62  i=1;
63  stoploop=0;
64  if _n_ ge &logline-5 and stoploop=0 then do until (i>12);
65  call symputx('logmsg',catx('\n',symget('logmsg'),_infile_));
66  input;
67  i+1;
68  stoploop=1;
69  end;
70  if stoploop=1 then stop;
71  run;
72  %end;
73  %end;
74 
75  /* send response in SASjs JSON format */
76  data _null_;
77  file _webout mod lrecl=32000;
78  length msg $32767;
79  sasdatetime=datetime();
80  msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
81  /* escape the quotes */
82  msg=tranwrd(msg,'"','\"');
83  /* ditch the CRLFs as chrome complains */
84  msg=compress(msg,,'kw');
85  /* quote without quoting the quotes (which are escaped instead) */
86  msg=cats('"',msg,'"');
87  if symexist('_debug') then debug=symget('_debug');
88  if debug ge 131 then put '>>weboutBEGIN<<';
89  put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
90  put ',"sasjsAbort" : [{';
91  put ' "MSG":' msg ;
92  put ' ,"MAC": "' "&mac" '"}]';
93  put ",""SYSUSERID"" : ""&sysuserid"" ";
94  if symexist('_metauser') then do;
95  _METAUSER=quote(trim(symget('_METAUSER')));
96  put ",""_METAUSER"": " _METAUSER;
97  _METAPERSON=quote(trim(symget('_METAPERSON')));
98  put ',"_METAPERSON": ' _METAPERSON;
99  end;
100  _PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
101  put ',"_PROGRAM" : ' _PROGRAM ;
102  put ",""SYSCC"" : ""&syscc"" ";
103  put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
104  put ",""SYSJOBID"" : ""&sysjobid"" ";
105  put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
106  put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
107  put "}" @;
108  %if &_debug ge 131 %then %do;
109  put '>>weboutEND<<';
110  %end;
111  run;
112  %let syscc=0;
113  %if %symexist(SYS_JES_JOB_URI) %then %do;
114  /* refer web service output to file service in one hit */
115  filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json";
116  %let rc=%sysfunc(fcopy(_web,_webout));
117  %end;
118  %else %do;
119  data _null_;
120  if symexist('sysprocessmode')
121  then if symget("sysprocessmode")="SAS Stored Process Server"
122  then rc=stpsrvset('program error', 0);
123  run;
124  %end;
125  /**
126  * endsas is reliable but kills some deployments.
127  * Abort variants are ungraceful (non zero return code)
128  * This approach lets SAS run silently until the end :-)
129  */
130  %put _all_;
131  filename skip temp;
132  data _null_;
133  file skip;
134  put '%macro skip(); %macro skippy();';
135  run;
136  %inc skip;
137  %end;
138  %else %do;
139  %put _all_;
140  %abort cancel;
141  %end;
142 %mend;
143 
144 /** @endcond */