Implementing custom logging

Instructions in this topic can be used for integrating logging aspect into custom implementations as well as for temporarily adding logging statements for issue analysis.

Log file

The default log file is the log file for the servlet. Writing to this file can be done like this:

  • System language:

    $success=rtecall( "log", $L.rc, "My message" )
  • SM JavaScript & colon:

    var rc;
    var success = system.functions.rtecall( "log", rc, "My message" );

    SM JavaScript also implements the print( "My message" ); function to write to the message log in the current session. This information appears in the message view of the client. These messages are printed into the servlet log as well, when the servlet was started with parameter msglog:1.

Sometimes you may want to write information into a log file separated from the servlet log file. This can be done using the writeFile() function:

writeFile( "c:\\SM\\logs\\mylog.log", "a", "My message");

Note In a JavaScript string, the backslash is used as an escape character, and therefore the backslash character has to appear twice.

Converting variables to a string to print to a log file

You can convert variables into a string for logging:

  • System language:

    $s=str( '1 00:00:00' )
  • SM JavaScript & colon:

    // converting a JavaScript value into string
    
        var s=1.toString();  
    
        // JavaScript implictly uses toString() method to convert a value to string             
    
        print(1);
    
        // converting a value by System Language function into string   
    
        var s=system.functions.str(1); 

For compound data types, JavaScript function toString() returns frequently just the string representation of the data type, which is not really helpful. You can use the following statements to convert complex objects into a string:

  • Converting SCFile object to XML string:

    var f = new SCFile( "dbdict" );
    var rc = f.doSelect('name="pmstatus"');
    
        // like system language str() function - does not include fieldnames
    var s1 = f.getText();
    
        // output as XML document - this includes tags with fieldnames
    var s2 = f.getXML();
  • Converting a JS object to JSON string:

    var s = lib.JSON.json().stringify( ["a", 1, { field1: "abc", field2: 2 } ] );

Writing a custom logging function in SM JavaScript

When designing a logging function, you may want to implement a log level: some messages should only be logged when debugging, but not during normal operations.

A typical log function design is as follows

var loglevel = "INFO";
   function logDebug( s )
   {
      if (loglevel == "DEBUG") print( s );
   }

This design of the function call has an issue:

logDebug( "Record: "+record );

At the time of the call, the object "record" is converted into a string. However, when the global variables "loglevel" is not "DEBUG", the message is not printed at all. Therefore, depending on the size of "record", and the frequency of this call (that is, in a loop), this may cause significant memory consumption and execution time.

Therefore, consider the following design:

var loglevel = "INFO";
   function logDebug( )
   {
     if (loglevel == "DEBUG") print( Array.prototype.join.call(arguments) );
   }

   logDebug( "Record: ", record);

Now, the reference to object "record" is handed to the logDebug() function and the conversion to a string takes only place if the variable "loglevel" is equal to "DEBUG".

Out-of-Box loggers for JavaScript

There are two out-of-box loggers.

  • ScriptLibrary log4js:

    The ScriptLibrary "log4js" supports logging in Log4J style to a message log.

    // Create a logger object set to log level "INFO"
    var myLogger=new lib.log4js.Log(lib.log4js.Log.INFO);
    myLogger.info("an info");

    For more information, see The log4js script.

  • RTE-supported logger

    Using the getLog() global JavaScript function, the Service Manager RTE provides logger support.

    // Get a logger for name "MyLog"
    var mylog = getLog("MyLog");
    // Set the log level
    mylog.setLevel('trace');
    // Log a message for log level "trace"
    mylog.trace('trace message');

    For more information, see JavaScript global method: getLog.

    Tip There is GUI-support for this kind of loggers (using ScriptLibrary "jlog"): On the search form for ScriptLibrary, you select the "JavaScript Logger" option and you get to a dialog where you can set the log level for loggers by name.