Command Logging

Command Logging

Top  Previous  Next


Command logging allows an application to create a detailed audit log of every command executed, including those from within Procs, paragraphs, menus, etc. The QM command processor passes the command and its origin to an optional user supplied logging subroutine, leaving the application designer free to determine what information is actually logged.


The logging is performed by a QMBasic class module globally catalogued as !CLOG. This has a public subroutine named LOG that two arguments; the command and its origin.


The origin is one of the following:


UserA command entered by the user at the command prompt, including commands executed from the command stack.


S nameExecution of a VOC sentence.


PA name@nThe command from line n of a VOC paragraph. For an IF command, the conditioned command is separately logged if the condition is true.


PQ name@nThe command from line n of the named Proc.


M name@nThe command from option n of the named VOC menu.


Exec name@nAn EXECUTE on line n of a QMBasic program.


Chain cmdA command executed using CHAIN.


CliA command executed by a QMClient session.


AutoExecution of an automatic script (MASTER.LOGIN, LOGIN, ON.LOGTO, ON.EXIT, ON.ABORT).


CmdA command executed from the operating system shell by supplying it as a command line argument to the QM executable.


Where a command includes an inline prompt construct, the command is logged a second time after expansion of the inline prompt.



Logging may be enabled in two mutually exclusive manners. If the CMDLOG configuration parameter is not null, it specifies the pathname of the directory in which logging data is to be recorded. Logging is enabled across all processes and merged into a single log file per day in the specified directory using a name formed from the date in yymmdd format with a .log suffix.


If the CMDLOG configuration parameter is null, logging may be enabled in individual processes by use of the COMMAND.LOGGING ON command. In this mode, the logged data is written to a file named clog.nnn.log in the QM temporary directory where nnn is the QM user number.



The default command logger shown below is catalogued as part of QM and is also issued in source form in the BP file of the QMSYS account. Users may adapt this to meet their own needs.


class clog

$catalogue !clog


$include keys.h


  private log.f,, log.dir


  public subroutine create.object = 0

     log.dir = config('CMDLOG')



  public subroutine log(cmd, origin)

     tm = epoch()


     if not(fileinfo(log.f, FL$OPEN)) then

        if log.dir = '' then    ;* Single process logging

           log.path = system(SYS$TEMP) : @ds : 'clog.' : : '.log'

        end else

           dt = mvdate(tm)

           if # dt then  ;* New date - switch log files

              closeseq log.f      ;* No effect if file was not open

     = dt



           log.path = log.dir : @ds : oconv(, 'D2YMD["",""]') : '.log'


        openseq log.path shared to log.f else return



     * Construct and write log data


     log.rec = tm

     log.rec<-1> =

     log.rec<-1> = @logname

     log.rec<-1> = origin

     log.rec<-1> = cmd

     writeseq change(log.rec, @fm, char(9)) to log.f else null






This example logger constructs a dynamic array that it then converts to be tab delimited. The logged data is the epoch value (allowing consistent logging across time zones), the QM user number, user name, command origin and the command itself.