2

I'm trying to monitor the progression of a long SAS script. At the beginning, I used something like:

DATA work.dataset1;
    SYSECHO "Currently working on: work.dataset1";
    /* DO STUFF*/
END;

PROC SORT DATA=work.dataset1 OUT = work.work.dataset2;
    SYSECHO "Currently working on: work.dataset2";
    /* DO STUFF*/
END;
  .....
DATA work.datasetn;
    SYSECHO "Currently working on: work.datasetn";
    /* DO STUFF*/
END;

However, this very hard to maintain and very verbose. Hence I tried to create a macro that would automatically get the step name or the step data set (or any information letting me know which step is currently running) and pass it to SYSECHO:

%macro nstep;
SYSECHO "Finished Processing &SYSLAST";
%mend;


DATA work.dataset1;
    %nstep;
    /* DO STUFF*/
END;

However, this actually prints the last impacted data set, not the current one. Hence the behaviour is particularly problematic with the first step executed, the first use of %nstep displays the name of the data set from the previous execution.

I'm searching for a way to find the current data / proc statement name, or any distinctive human readable information.

Théophile Pace
  • 826
  • 5
  • 14

1 Answers1

3

There is no explicit introspection or callback mechanism in SAS for supervisory level source code processing, step statement gathering time (pre-compile) or at step compile time.

However, you can implement and utilize (adopt) a name specifying framework that performs the desired actions.

Concept:

  • Create a macro, E, which accepts name to be reported.
  • Message about name using SYSECHO via DOSUBL
  • Emit name as source code
  • Use %E(<name>) (in the context of actual source code) when ever you want to send a name message back to IOM client

Framework in code:

%* part of autoexec, autocall, or specified macro library;
%macro E(name);
  &name
  %local rc;
  %let rc = %sysfunc(DOSUBL(%nrstr(
    %put NOTE: SYSECHOing &name;  /* The put NOTE: can be removed if you want */
    SYSECHO "Working on &name";
  )));
%mend;


DATA %E(work.dataset1);
    /* DO STUFF*/
RUN;

PROC SORT DATA=work.dataset1 OUT = %E(work.dataset2);
    /* DO STUFF*/
RUN;
… 
DATA %E(work.dataset27);
    /* DO STUFF*/
END;

Not automatic, but not as verbose.

Richard
  • 25,390
  • 3
  • 25
  • 38
  • 1
    Tried to use your macro, and it works if `&name` put before `%local`:`%macro E(name); &name %local rc;` – Llex Jan 29 '20 at 14:05
  • Hi thanks for the solution! It does need the fix from @AlexeySigida to work correctly though. Please update the answer, I'll accept it as it fixes the problem> TBH, I can't believe you need something so far-fetched to achieve a reasonably standard log. – Théophile Pace Jan 29 '20 at 14:26
  • 1
    Answer fixed per comment. Side info `DOSUBL` returns 0 or not 0 -- the `%let` 'eats' the return value so it does not get emitted into the source code stream by the macro processor. – Richard Jan 29 '20 at 14:36
  • @ThéophilePace just wait until you want to do some error handling then. =/ – Robert Penridge Jan 29 '20 at 16:30