Logger (class)

Categories:Framework

Overview

Summary

The Logger class provides a simple object-oriented approach to logging information, both to the Output panel and to file, including basic templating and substitution of placeholder variables.

Contents

Concept

Overview

Often in applications, you will want to log or report some kind of information, e.g. the intention or perhaps result of an action. Doing this with traces to the Output panel is fine, but in more complex applications, sometimes more structure or consistency is necessary.

The Logger class has various features that make it suitable for such a task:

Template

The Logger constructor as its first argument takes a formatted string template, into which future log messages are formatted. A typical template string might look something like this:

> xjsfl: {message}

This allows you to assign a consistent format to all log messages, and only pass in the message (formatted into the message placeholder variable) instead of the whole string each time you log:

var log = new Logger('> xjsfl: {message}', 'c:/temp/xjsfl log.txt');
log.log('New message logged at {time}');

The above code would output to a file in the temp directory:

> xjsfl: New message logged at 14:34:15

Placeholder variables

Because Logger is based on a simple templating system, placholder variables allow you keep things simple, yet flexible.

As seen above, the main placeholder variable (and the default template, should you not supply one) is {message}:

{message}        The message passed to the log() function, i.e. "Loading classes..."

The following standard placeholder variables are recalculated internally each time you log, and can be used in both the template string, or the logged message:

{timestamp}      The current timestamp, i.e. "Fri, 03 Feb 2012 01:38:16 GMT"
{date}           The current date, i.e. "Fri, 03 Feb 2012"
{time}           The current time, i.e. "01:38:16"
{millitime}      The current time with milliseconds, i.e. "01:38:16:124"
{count}          An incremental count of the number of items logged since instantiation, i.e. "34"

The following placeholder variable can be used in both the template string or the logged message, but can be passed in via the log() method only:

{type}           An optional log type, i.e. "INFO"
	

Finally, you can pass in any custom variables you like, which you supply via the log() method:

{foo}           Must be passed in via log(), i.e. template.log('hello', {foo:'Dave'})	

 

Usage

Template vs message variables

Standard variables in template:

template:   '> xjsfl: "{message}" logged at {time}'
log():      'Hello there'
result:     > xjsfl: "Hello there" logged at 14:34:15'

Standard variables in template and log():

template:   '> xjsfl: "{message}"'
log():      'Hello there logged at {time}'
result:     > xjsfl: "Hello there logged at 14:34:15"
User variables in log():
template:   '> xjsfl: "{message}" logged at {time} by {name}'
log():      'Hello there', {name:'Dave'}
result:     > xjsfl: "Hello there" logged at 14:34:15 by Dave

See the SimpleTemplate class for further infomation on the templating functionality in the Logger class.

Debugging code

The logging class can be very useful when writing a complex application that crashes, or worse, hangs Flash. It's easy to add logging traces at key points in your code, then check the log file to see where the paper trail ends.

Whilst writing and testing the URI class, a test URI was causing Flash to hang. Using the logger class, it was fairly easy to trace the error to the section of code that resolved relative-parent folders:

// debug
	logger.log(' > correct() : doubleslashes');

// replace double-slashes
	path = path.replace(/\/+/g, '/');

// debug
	logger.log(' > correct() : ../');

// resolve ../
	while(path.indexOf('../') > -1)
	{
		logger.log(' > correct() 1: ' + path);
		path = path.replace(/(^|\/)[^\/]+\/\.\.\//, "/");
		logger.log(' > correct() 2: ' + path);
	}

// debug
	logger.log(' > correct() : ./');

In the buggy version of the file, the RegEx that was supposed to be fully-resolving the ../ tokens was leaving one in, and so the while-loop never completed. The error log thus-contained many message of the same kind!

The output of the final log can be seen here: file-debugging-log.txt

API

Logger(template, uriOrPath, append)

Logger constructor

Parameters:

  • template String An optional input pattern
  • uriOrPath String An optional URI or path to which to save a log file
  • uriOrPath URI An optional URI instance to which to save a log file
  • append Boolean An optional Boolean to append (rather than clear) any existing file, defaults to false

An Output panel logger (with no file logging) is created by supplying only an input pattern to the constructor.

var logger = new Logger('{timestamp} - {message}';
logger.log('Something happened');
Sun, 05 Feb 2012 00:41:47 GMT - Something happened	

A file logger (with no output panel traces) is created by supplying both an input pattern, and a file path or URI:

var uri    = '{user}temp/logs/user.txt';
var logger = new Logger('{timestamp} - {message}', uri);
logger.log('Something happened');

Note that a file logger does not by default trace to the output panel. To trace to the output panel you need to pass a Boolean true in the log() call:

logger.log('This message was written to both the file and the output panel...', true);

It is also possible for multiple loggers to write to the same file:

var path = 'c:/temp/log.txt';
var logger1 = new Logger('> log1: {message}', path);
var logger2 = new Logger('> log2: {message}', path);

logger1.log('This is from log 1')
logger2.log('And this is from log 2')
logger1.log('And this is from log 1 again')

logger1.open();
> log1: This is from log 1
> log2: And this is from log 2
> log1: And this is from log 1 again 

Properties

template

The SimpleTemplate the Logger uses to create the log

  • Type: SimpleTemplate
  • Access: Read/write

file

The File object that contains the log data

  • Type: File
  • Access: Read/write

count

An incremental count that can be used within the Template as {count}

  • Type: Number
  • Access: Read/write

Logging methods

log(message, $type, $params, $trace)

Log a message (note that the order of $ arguments may be swapped)

Parameters:

  • message String The message to log
  • $type String An optional log type String that will be rendered into the {type} placeholders
  • $params Object An optional Object of name:value pairs that will be rendered into the user's custom placeholders
  • $trace Boolean An optional Boolean to additionally trace the result to the Output panel (File logging only)

Returns:

  •   Logger The current instance

The log() method is the workhorse of the Logger class, and allows you to pass in a message, message type, and custom parameters should you wish. At its most basic level, you would simply log a message.

The following example logs a message to a file:

var logger = new Logger('{time} - {message}', '{user}temp/logs/user.txt');
logger.log('Something happened');
12:02:34 - Something happened

The following example logs a message to a file, along with a message type:

var logger = new Logger('{time} - {type} - {message}', '{user}temp/logs/user.txt');
logger.log('Something happened', 'INFO');
12:02:34 - INFO - Something happened

Note that you can also trigger callbacks by registering a certain log type using addtrigger().

The following example logs a message to a file, along with some custom variables:

var logger = new Logger('{time} - {a} {b} {c}', '{user}temp/logs/user.txt');
logger.log('Something happened', {a:1, b:2, c:3});
12:02:34 - 1 2 3

addTrigger(type, callback)

Add a callback function that should fire when a log with a certain type is logged

Parameters:

  • type String The message type to register a callback for
  • callback Function The function to call when a log of that type is called

Returns:

  •   Logger The current instance

The log() method of the logger class allows you to pass in an additional string you may use to assign types to your log messages, such as "info", "warn", "error", etc. addTrigger() allows you to bind callbacks to these types, so if a message of a certain type is received, you can run some custom code, such as running a batch file that might send an email, or calling a panel that might connect to a server.

The following example demonstrates how to fire a custom action when a message of type "error" is logged:

/**
 * Callback function to handle log trigger
 * @param	{Logger}	logger	The logger instance
 * @param	{String}	message	The log message
 * @param	{Object}	data	The data passed to the log
 */
function onError(logger, message, data)
{
	alert('There is an error: ' + data.message);
	logger.open();
}

// set up the logger
var logger = new Logger('[{type}]\t{message}', '{user}temp/logs/new log.txt');
logger.addTrigger('error', onError)

// start logging
logger
	.log('Everything is fine...', 'info') // nothing will fire here, as "info" types are not registered
	.log('Oh dear!', 'error');
		
[info]  Everything is fine...
[error] Oh dear!

File-related methods

write(message, trace)

Writes directly to the log file, if there is one

Parameters:

  • message String The message to log
  • trace Boolean An optional Boolean to additionally trace the result to the Output panel

Returns:

  •   Logger The current instance

Usually, you will use the log() method to write to the log file or output panel, but there may be times when you wish to write directly to the log file or output panel.

The following example logs two messages with a divider between them:

var logger = new Logger('{time} - {message}');
logger
    .log('This is a message...')
    .write('\n------------------------------------------------------------\n')
    .log('...and this is another message');
12:32:51 - This is a message...

------------------------------------------------------------

12:32:51 - ...and this is another message

clear()

Clears the log file

Returns:

  •   Logger The current instance

The following example creates and clears an existing log file, then writes a new message to it:

var logger = new Logger(null, 'user/temp/logs/user.txt');
logger
	.log('You will never read this...')
	.clear()
	.log('...but you will read this!')
	.open();
...but you will read this!

open()

Opens the log file in a text editor, if there is one

Returns:

  •   Logger The current instance

The following example creates a log file, logs a message then opens the log in the user's default text editor:

var logger = new Logger();
logger
	.log('You should now be reading this')
	.open();		

reveal()

Reveals the log file in the Explorer / Finder, if there is one

Returns:

  •   Logger The current instance

The following example creates a log file, logs a message then reveals the log file in the user's Explorer / Finder:

var logger = new Logger(null, 'user/temp/logs/user.txt');
logger
	.log('Hello there')
	.reveal();

remove()

Revoves the log file on disk, if there is one

Returns:

  •   Logger The current instance

The following example creates a log file, logs a message then deletes the log from the user's hard drive:

var logger = new Logger(null, 'user/temp/logs/user.txt');
logger
	.log('You will never read this!')
	.remove();

File-related accessors

contents

Get the contents of the log file Directly set the contents of the log file

  • Type: String
  • Access: Read and write

Sometimes you will just want to manipulate the contents of the log file manually.

The following example creates a log file, then both reads and wrotes directly to the contents property:

var logger = new Logger('', 'user/temp/logs/user.txt');
logger.log('This is some content');

trace(logger.contents)
logger.contents += 'This is some more content'
trace(logger.contents)
This is some content

This is some content
This is some more content

Utility methods

toString()

Returns a String representation of the instance

Returns:

  •   String Description

The following example traces the string represnetation of the logger instance:

var logger = new Logger('', '../temp/logs/user.txt');
trace(logger);
[object Logger template="{message}" path="E:/Projects/xJSFL/user/temp/logs/user.txt"]	

Comments are closed.