Create a Custom Logger: Part 1 - Mach-II/Mach-II-Framework GitHub Wiki

Part One: Introduction and Conception Overview

How-To originally by Peter J. Farrell (peter@…)

Table of Contents

  1. Objective and Overview
  2. Logging Terms
  3. A Log Message - Start to Finish
  4. Bundled Loggers, Log Adapters and Filters
  5. Building a Logger
  6. Continue Reading How-To: Create a Custom Logger

This How-To is a working document and has not been completed.

Objective and Overview

The object of this how-to document is to help Mach-II developers learn how to the leverage the Mach-II logging package so they can create loggers that perform functionality that is not provided by the bundled loggers in the framework. The Mach-II logging package is a completely independent subsystem from the Mach-II MVC framework. This allows developers to leverage the logging package in projects where Mach-II MVC might not be used.

Creating a custom logger is an easy process. Essentially, the loggers that are bundled with the core framework download are "custom" loggers. The only difference is that they exist is all downloads of the framework, whereas any custom loggers are the maintained by you and are separate from the core files. A logger consists of two CFCs that make up a logger packager - a "logger" CFC and a "log adapter". A logger packager may also leverage a "channel filter" which is optional and may or may not be used depending on the logger you are designing. It's ok that you don't know what these three different CFCs do right now since we'll dig into this soon.

If you are unfamiliar with Mach-II logging, we highly suggest that you read the Introduction to Logging before you continue with this wiki entry as this entry builds on the vocabulary and concepts introduced in that wiki entry.

Logging Terms

Before we can get knee deep into the Mach-II logging package, lets take a brief detour into some of the terms you'll be seeing in the rest of document.

Message

A message is a bit of information that indicates something has happened or occurred. There are six logging levels trace, debug, info, warn, error and exception that indicate the severity of the message. The trace level is the least severe and is used for most trivial of message while the exception level is most severe and is used for the most serious situations.

Log

A log is a CFC that has methods you can call to log a message at one of the six different logging levels. Other helper methods are available such as isTraceEnabled() (with other methods for the remaining levels) that allows you decided whether or not to log a message at a particular level. This is especially helpful if additional and process intensive logic is required before logging a message.

Channel

A log CFC is given a name that indicates the channel in which to "broadcast" any log messages that it receives. Think of a logging channel in a similar manner to watching a TV. While you might be interested in watching all the available channels, you might watching only have interest in 2 or 3 channels. The channel name is assigned to the log CFC when it is instantiated. For Mach-II extended components such as listeners, the channel name is set for you which is one of the reasons why people forget that the logging system also has channels. Setting the channel name during the init() of the log CFC allows you to just log a message without having to pass the correct channel name each time a message is logged.

Logger

A logger is a group of CFCs that accept log messages, filter messages based on its broadcasted channel / log level and ultimately does something with those log message. A logger might for example output all log messages out to the console, display it at the bottom of the HTML output in a browser or pass the message over TCP/IP to another system. There is limitless possibilities to what loggers can be designed and implemented. Also, there can be one or more loggers configured at one time.

Log Adapter

A log adapter is an intermediate point for log messages and is one of the CFC that comprises the group of CFCs mentioned above in the logger section. The log adapter is used to filter log messages that it is interested in by criteria such as channel name and log level. Most people setup their logging to be interested in logged messages that only exceed a certain log level while ignoring messages at a level that are not important at the time (i.e. serious debugging). The adapter uses logic to decide whether or not to accept the logged message and pass it on for further processing.

A Log Message - Start to Finish

In order to understand the Mach-II logging package, it is best to understand how a log message is processed by the system from the point it is logged to the final end point.

  1. In a fictitious NewsService, a message is logged such getLog().debug("Paris Hilton got another driving violation - #Now()#."). Each log is broadcasted on a channel name. It is best practice to set the channel name as dot path to the CFC (e.g. myApp.model.news.NewsService).
  2. The log CFC broadcasts the message, the channel name and the logging level to all log adapters currently registered.
  3. Each registered log adapter decided what to do with the log message. This is based on criteria which is user configurable such as channel name(s), logging level or other criteria. The adapter then processes the message in the manner the adapter was designed. The simplest log adapter simply appends the message to an array in a CF scope.
  4. A logger retrieves log messages. In our example, it gets the messages from a CF scope and then displays them at the end of the request at the bottom of the output in the CFML page.

Bundled Loggers, Log Adapters and Filters

As explained above, we will create a logger and log adapter for our custom logging package. Instead of building a custom channel filter we will utilize the GenericChannelFilter that is bundled with the core framework download.

Not unlike other Mach-II developer extended components, loggers will extend (inheritance) the MachII.logging.loggers.AbstractLogger and log adapters will extend MachII.logging.adapter.AbstractLogAdapter. This is no different then developing Mach-II listeners which extend MachII.framework.Listener.

Bundled Loggers

There are a few bundled loggers that come with the Mach-II logging package. These are:

  • MachIILogger - Logs messages and outputs them to bottom of the screen on each request
  • EmailLogger - Logs messages and emails them to specified list of email addresses
  • CFLogger - Logs messages using <cflog> to a logging file

All loggers specify a logging adapter which "listens" for logging messages. For example, the !MachIILogger uses to the scope log adapter to log messages to the request scope so the logger can render the messages at the end of the request. The EmailLogger also uses the scope log adapter. The !CFLogger uses the CFLog log adapter since it is logging messages to a very specific implementation.

Bundled Log Adapters

There are two bundled log adapters that come with the Mach-II logging package. These are:

  • CFLogAdapter - Logs messages via the CFML engine's <cflog> infrastructure
  • ScopeAdapter - Logs messages to a specified scope for use later

All log adapters are the end point for all messages. The logger uses the log adapter to pick up messages and perform additional processing such as displaying at the bottom of your request.

Bundled Filters

There is one bundled log filter that comes with the Mach-II logging package.

  • GenericChannelFilter - This determines of the channel name for the passed log message matches any of the channel names that logger is interested in.

There is limitless possibilities on what criteria is used for filtering. A filter is not required when building a custom logger, however using building a custom filter or using the GenericChannelFilter will greatly increase the flexibility of the logger especially when using the logging for debugging (e.g. watching specific channels to debug a difficult problem).

Building a Logger

Building a logger requires you to extend specific Mach-II components which is not unlike creating a listener, plugin or filter. Extending these components gives you an API to implement so the logging package an utilize your logger and utility methods that will provide functionality and aid the development of your logger.

Continue Reading How-To: Create a Custom Logger

⚠️ **GitHub.com Fallback** ⚠️