SoapUI: Using FileAppender for Logging

In writing SoapUI test scripts, you may come across a situation where you need some additional logging functionality; for example, writing information to a file aside from the default SoapUI log for review after running a script via testrunner.  You could explicitly create and manage your own text file, but you may find it simpler to leverage the existing Logger object (via the log variable) to send logged messages to another file using the FileAppender class.

A FileAppender can forward messages sent to the log to a separate file, using formatting options to label messages with dates, logging levels, etc.  Here's an example setup script demonstrating how to set up a FileAppender to write to a simple text file (you can download a starter project containing all this code here):

import org.apache.log4j.FileAppender
import org.apache.log4j.PatternLayout

//Define the layout to use
def pLayout = new PatternLayout("%d{DATE} : %m%n")
//Create FileAppender in context using layout we just defined
context.customLogger = new FileAppender(pLayout,"C:\\Temp\\CustomLog\\CustomLog.txt", false)
//Add the appender to the existing log
log.addAppender(context.customLogger)

Remember, there's no need to add any additional jars to SoapUI's ext folder in this case; we're using the log4j package that's already part of its libraries.  However, we do need to import the FileAppender and PatternLayout classes at the top of our script.

After the import statements, a new PatternLayout is created for use with the FileAppender:

def pLayout = new PatternLayout("%d{DATE} : %m%n")

The string that's passed into the PatternLayout constructor ("%d{DATE} : %m%n") is used to describe how we'd like information formatted in the log file.  For a detailed list of the special formatting indicators (generally demarcated by the % character), see the javadoc for the log4j PatternLayout class.  In the meantime, here's a table showing some example patterns and how the line log.info("Simple Test Message One") is rendered in a custom log (starting with the pattern used in our script):

PatternOutputNotes
%d{DATE} : %m%n
14 Sep 2015 21:51:21,223 : Simple Test Message One
- %d indicates a date, with {DATE} specifying a log4j pre-canned date format
- %m indicates where the actual message content will be shown
- %n indicates a new line character
%-15d{ABSOLUTE}%p : %m%n
16:25:33,000   INFO : Simple Test Message One
- {ABSOLUTE} is used with %d to specify another log4j pre-canned date format-- this one prints only the time component of the {DATE} default format used in the first example.
- The -15 at the beginning of the date pads the expression, reserving 15 characters for the date and right-padding with spaces if the date is less than 15 characters long.
- %p indicates the priority level of the message (e.g., INFO, DEBUG, etc.).
%26d{ISO8601} : %m%n
   2015-09-19 16:50:08,095 : Simple Test Message One
- {ISO8601} is the last of the log4j pre-canned date formats, printing the date portion with numeric year, month, and day. ISO8601 is also the default format used if none is specified.
- The 26 at the beginning of the date format expression pads the date expression like -15 in the previous example, but the positive value pads the left instead of the right (note the leading spaces in the output).
%d{MM-dd-yyyy HH:mm:ss.SSS} : %.10m%n
09-19-2015 17:31:10.976 : essage One
- In this case we're using a custom format for the date; this one prints the date with numeric month, then day, then year, then prints the time using a decimal point as the divider between seconds and nanoseconds. You can find out more about the date and time pattern characters to use for a custom date format here. According to the log4j javadocs, using a custom format like this could result in a performance hit; they encourage you to use the pre-canned formats instead.
- The .10 before the message specifier is another spacing indicator; this one specifies that if the message is longer than 10 characters, it should be truncated from the front (which is why you only see the last 10 characters in the output).

Once we have our PatternLayout created, we can create our FileAppender, using the PatternLayout as an argument in its constructor.  We put it in context to manage disposing its resources later on in the tear down script:

context.customlogger = new FileAppender(pLayout, "C:\\Temp\\CustomLog\\CustomLog.txt", false)

The first two arguments should be self-explanatory: the first is the layout we want the FileAppender to use and the second is a string giving the path and name of the text file where we want the FileAppender to forward messages-- feel free to change this path as you see fit.  Remember that "\" has a special meaning in string in Java; that's why we have to use the escape sequence "\\" here instead.  The final argument specifies whether we want the messages appended to the text file.  When set to true, any content in the text file generated in previous runs is preserved and information from this run is added to the end of the file.  In this example we're setting the argument to false, so each time we run our suite a new log is created.

The final line in the setup script registers the appender with the default SoapUI log.

log.addAppender(context.customLogger)

Once everything is configured and the appender is registered with the log object, there's nothing special you have to do to send messages to this custom log file-- anything sent to the log within your script is sent to the FileAppender's underlying stream.

As indicated in the table above, the line log.info("Simple Test Message One") in our script results in this output in the custom log file:

14 Sep 2015 21:51:21,223 : Simple Test Message One

Within our tear down script (or whenever we're done with the appender), we have to release the resources being used by the appender, closing the underlying file and the appender itself:

context.customLogger.closeFile()
context.customLogger.close()

I encourage you to play around with the provided starter project to see what can be done with a file appender.  In particular, try making changes to the pattern layout string to see how it controls formatting and affects the custom log's output. 

2 comments:

  1. Found many similar solutions but none worked the way I wanted and none explained the code as good as done here. Especially no one ever mentioned how to cleanly close the opened resources while exiting the test. Finally got my answer here.
    Thanks!

    ReplyDelete

Please be respectful of others (myself included!) when posting comments. Unfortunately, I may not be able to address (or even read) all comments immediately, and I reserve the right to remove comments periodically to keep clutter to a minimum ("clean" posts that aren't disrespectful or off-topic should stay on the site for at least 30 days to give others a chance to read them). If you're looking for a solution to a particular issue, you're free to post your question here, but you may have better luck posting your question on the main forum belonging to your tool's home site (links to these are available on the navigation bar on the right).