BookmarkSubscribeRSS Feed
DavidRice
Fluorite | Level 6

I'm working on a macro function to append a record to a SAS data set every time a specific function is called, and I need to include information on the context from which it was called.  Is there a way to programmatically access the 'breadcrumb' trail that appears in the log when mprintnest or mlogicnest options are enabled?

 

With the 'mlogicnest' option enabled in the log excerpt below, it's clear that I've called the 'send_message' macro function which in turn calls the 'test_macro' macro function.  Using 'put _all_;' from that inner function shows me (among many others) macro variables available in the 'send_message' scope, and the automatic macro variable 'sysmacroname' shows that the current macro function is named 'test_macro'.

 

Is there another place to look for the whole breadcrumb trail? or do I have to construct it as I traverse the nested macro function tree?

 

Thank you!
David

 

86 %send_message(
MLOGIC(SEND_MESSAGE): Beginning execution.
87 message_dest = WORK.message_log,
88 message_type = exception,
89 message_user = david
90 )
MLOGIC(SEND_MESSAGE): Parameter MESSAGE_DEST has value WORK.message_log
MLOGIC(SEND_MESSAGE): Parameter MESSAGE_TYPE has value exception
MLOGIC(SEND_MESSAGE): Parameter MESSAGE_USER has value david
MLOGIC(SEND_MESSAGE): Parameter MESSAGE_SRC has value unknown
MLOGIC(SEND_MESSAGE): Parameter MESSAGE_TEXT has value
MPRINT(SEND_MESSAGE): data WORK.new_message;
MPRINT(SEND_MESSAGE): format message_timestamp_utc E8601LX.;
MPRINT(SEND_MESSAGE): length message_type $32 message_src $128 message_user $32 message_text $256 message_exception_detail $1024;
MPRINT(SEND_MESSAGE): message_timestamp_utc = tzones2u(datetime());
MPRINT(SEND_MESSAGE): message_type = symget('message_type');
MPRINT(SEND_MESSAGE): message_src=symget('message_src');
MPRINT(SEND_MESSAGE): message_user = symget('message_user');
MPRINT(SEND_MESSAGE): message_text = symget('message_text');
...
MLOGIC(SEND_MESSAGE.TEST_MACRO): Beginning execution.
MLOGIC(SEND_MESSAGE.TEST_MACRO): This macro was compiled from the autocall file
.../macros/test_macro.sas
...
MLOGIC(SEND_MESSAGE.TEST_MACRO): %PUT _all_
SEND_MESSAGE MESSAGE_DEST WORK.message_log SEND_MESSAGE MESSAGE_SRC unknown SEND_MESSAGE MESSAGE_TEXT SEND_MESSAGE MESSAGE_TYPE exception
SEND_MESSAGE MESSAGE_USER david
...
AUTOMATIC SYSMACRONAME TEST_MACRO
...
MLOGIC(SEND_MESSAGE.TEST_MACRO): Ending execution.
MLOGIC(SEND_MESSAGE): Ending execution.

 

3 REPLIES 3
agannon
Obsidian | Level 7

I don't know that this is exactly what you are looking for, but hopefully it is a good start.

 

There are two things you can use to pull back the current macro being executed. First is the %sysmexecdepth SAS macro which will pull back a whole number representing the current "depth" of the macro being executed. Second is the %sysmexecname SAS macro which will pull back the name of the macro at a given depth. 

 

/* ------ 
 * Define test macro 1
 * ------ */
%macro mac_level_1;
	%put NOTE: This is macro 1;
	%put System Defined Level: %sysmexecdepth;
	%put System Defined Macro: %sysmexecname(%sysmexecdepth);
	
	%mac_level_2;
%mend mac_level_1;

/* ------
 * Define test macro 2
 * ------ */
%macro mac_level_2;
	%put NOTE: This is macro 2;
	%put System Defined Level: %sysmexecdepth;
	%put System Defined Macro: %sysmexecname(%sysmexecdepth);

%mend mac_level_2;

/* ------
 * Call test macro 1 (which will call test macro 2) 
 * ------ */
%mac_level_1;

The %sysmexecname macro requires a numeric input, which will output the name of the macro at that level. Below is the log from executing the above code:

43         %mac_level_1;
NOTE: This is macro 1
System Defined Level:1
System Defined Macro:MAC_LEVEL_1
NOTE: This is macro 2
System Defined Level:2
System Defined Macro:MAC_LEVEL_2
44         

You should be able to use these system macros, in a loop, to output something along the lines of MAC_LEVEL1.MAC_LEVEL_2  with a loop like:

%do i = 1 %to %sysmexecdepth;
    %sysmexecname(&i);
%end;

Documentation for SAS macros: 

https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=n19g3xotkajctbn1tujf4pce6n3d.htm&docse...

https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=n19g1rkeq1al87n1djihhoec4oxp.htm&docse...

DavidRice
Fluorite | Level 6

Thank you for the very helpful information.  I've reviewed the macro functions that you referenced, and it does look like they'll provide the macro nesting lineage.  I started to implement them but ran into some issues where I was missing some of the nest levels, but I'll work on it a little more and update this reply as I know more.

 

Thanks again!
David

Tom
Super User Tom
Super User

If you want something that looks like what the MPRINT() log entries have you could use a macro like this:

%macro running_macros;
%local depth sep;
%do depth=1 %to %sysmexecdepth-1;&sep.%str()%sysmexecname(&depth)%let sep=.;%end;
%mend running_macros;

The -1 is to exclude the RUNNING_MACROS from the list.  The %str() is deal with the bug in how SAS parses strings generated by %SYSMEXECNAME() that causes the parse to "eat" any leading spaces.

Example:

460   %macro running_macros;
461   %local depth sep;
462   %do depth=1 %to %sysmexecdepth-1;&sep.%str()%sysmexecname(&depth)%let sep=.;%end;
463   %mend running_macros;
464
465   %macro test1;
466     %put &sysmacroname called by %running_macros;
467   %mend;
468   %macro test2;
469     %test1;
470   %mend;
471
472   %put %running_macros;

473   %test1;
TEST1 called by TEST1
474   %test2;
TEST1 called by TEST2.TEST1

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 476 views
  • 2 likes
  • 3 in conversation