Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This is a major release and a major rewrite of the entire framework to modern CFML, optimizations and script modes.
We have also improved all appenders for performance and reliability. Especially, the file logging facilities have been drastically improved. The new file based appenders now rely on a queuing mechanism and listener watcher threads that stream content to the file repositories.
LogBox is a standalone enterprise ColdFusion (CFML) logging library designed to give you flexibility, simplicity and power when logging or tracing is needed in your applications. LogBox is also part of the ColdBox Platform suite of services and libraries and allows you to easily build upon it's logging framework in order to meet any logging or reporting needs your applications has. LogBox surpasses ColdFusion's very basic cflog
tag. LogBox allows you to create multiple destinations for your loggings and even configure multiple destinations or change them at runtime.
Almost every application needs logging and/or tracing capabilities and we have developed LogBox to satisfy these needs. Although you should take care not to over-use logging as it can slow down an application, LogBox offers you the capabilities to filter out or cancel logging noise a-la-carte. LogBox was inspired by the original logging capabilities in ColdBox and in the Log4j project.
LogBox is maintained under the Semantic Versioning guidelines as much as possible.Releases will be numbered with the following format:
And constructed with the following guidelines:
Breaking backward compatibility bumps the major (and resets the minor and patch)
New additions without breaking backward compatibility bumps the minor (and resets the patch)
Bug fixes and misc changes bumps the patch
The ColdBox Platform, LogBox is open source and licensed under the Apache 2 License.
Copyright by Ortus Solutions, Corp
ColdBox is a registered trademark by Ortus Solutions, Corp
Info: The ColdBox Websites, Documentation, logo and content have a separate license and they are a separate entity.
The LogBox help and discussion group can be found here: https://groups.google.com/forum/#!forum/coldbox
We all make mistakes from time to time :) So why not let us know about it and help us out. We also love pull requests, so please star us and fork us: https://github.com/coldbox/coldbox-platform
By Email: bugs@coldbox.org
ColdBox is a professional open source software backed by Ortus Solutions, Corp offering services like:
Custom Development
Professional Support & Mentoring
Training
Server Tuning
Security Hardening
Code Reviews
Official Site: http://www.coldbox.org
Source Code: https://github.com/coldbox/coldbox-platform
Bug Tracker: https://ortussolutions.atlassian.net/browse/LOGBOX
Twitter: @coldbox
Facebook: https://www.facebook.com/coldboxplatform
Google+: https://www.google.com/+ColdboxOrg
Vimeo Channel: http://vimeo.com/channels/coldbox
Because of His grace, this project exists. If you don't like this, then don't read it, its not for you.
"Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5
LogBox is a standalone enterprise ColdFusion (CFML) logging library designed to give you flexibility, simplicity and power when logging or tracing is needed in your applications. LogBox is also part of the ColdBox Platform suite of services and libraries and allows you to easily build upon it's logging framework in order to meet any logging or reporting needs your applications has. LogBox surpasses ColdFusion's very basic cflog
tag. LogBox allows you to create multiple destinations for your loggings and even configure multiple destinations or change them at runtime.
Almost every application needs logging and/or tracing capabilities and we have developed LogBox to satisfy these needs. Although you should take care not to over-use logging as it can slow down an application, LogBox offers you the capabilities to filter out or cancel logging noise a-la-carte. LogBox was inspired by the original logging capabilities in ColdBox and in the Log4j project.
LogBox is maintained under the Semantic Versioning guidelines as much as possible.Releases will be numbered with the following format:
And constructed with the following guidelines:
Breaking backward compatibility bumps the major (and resets the minor and patch)
New additions without breaking backward compatibility bumps the minor (and resets the patch)
Bug fixes and misc changes bumps the patch
The ColdBox Platform, LogBox is open source and licensed under the Apache 2 License.
Copyright by Ortus Solutions, Corp
ColdBox is a registered trademark by Ortus Solutions, Corp
Info: The ColdBox Websites, Documentation, logo and content have a separate license and they are a separate entity.
The LogBox help and discussion group can be found here: https://groups.google.com/forum/#!forum/coldbox
We all make mistakes from time to time :) So why not let us know about it and help us out. We also love pull requests, so please star us and fork us: https://github.com/coldbox/coldbox-platform
By Email: bugs@coldbox.org
ColdBox is a professional open source software backed by Ortus Solutions, Corp offering services like:
Custom Development
Professional Support & Mentoring
Training
Server Tuning
Security Hardening
Code Reviews
Official Site: http://www.coldbox.org
Source Code: https://github.com/coldbox/coldbox-platform
Bug Tracker: https://ortussolutions.atlassian.net/browse/LOGBOX
Twitter: @coldbox
Facebook: https://www.facebook.com/coldboxplatform
Google+: https://www.google.com/+ColdboxOrg
Vimeo Channel: http://vimeo.com/channels/coldbox
Because of His grace, this project exists. If you don't like this, then don't read it, its not for you.
"Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5
There are two major improvements we did with LogBox in this release:
1) The file locking operations on file appenders have been streamlined to avoid high i/o operations.
2) The console appender uses an asynchronous streaming technique which makes it extremely efficient and fast.
[LOGBOX-34] - Console appender completely rewritten to support asynchronous streaming
[LOGBOX-33] - Improve file exists usage on file appenders to avoid i/o operations
[LOGBOX-32] - Add test and fix for adding a LogBox category after the fact
LogBox 2.0.0 is a major release, mostly aligned to support our ColdBox 4 release.
You can find the release version information here: https://ortussolutions.atlassian.net/browse/LOGBOX/fixforversion/12302
Bug
[LOGBOX-14] - Truncating of category data to avoid error on insertion on DB Appender
Improvement
[LOGBOX-13] - deprecate logbox xml support
New Feature
[LOGBOX-15] - Ability to asynchronize any logger via new 'async' property
The source code for this book is hosted in GitHub: . You can freely contribute to it and submit pull requests. The contents of this book is copyright by and cannot be altered or reproduced without author's consent. All content is provided "As-Is" and can be freely distributed.
The majority of code examples in this book are done in cfscript
.
The majority of code generation and running of examples are done via CommandBox: The ColdFusion (CFML) CLI, Package Manager, REPL -
All ColdFusion examples designed to run on the open soure Railo Platform or Adobe ColdFusion 9.0.2+
Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc. Railo is a trademark and copyright of Railo Technologies, GmbH.
The information in this book is distributed “as is”, without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity with respect to loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software and resources described in it.
We highly encourage contribution to this book and our open source software. The source code for this book can be found in our where you can submit pull requests.
15% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - . So please donate and purchase the printed version of this book, every book sold can help a child for almost 2 months.
Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education and life skills training in a Christian environment. The home is supported by a child sponsorship program.
We have personally supported Shalom for over 6 years now; it is a place of blessing for many children in El Salvador that either have no families or have been abandoned. This is good earth to seed and plant.
Shalom Children’s Home () is one of the ministries that is dear to our hearts located in El Salvador. During the 12 year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children werecame on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.
Luis Majano is a Computer Engineer with over 15 years of software development and systems architecture experience. He was born in San Salvador, El Salvador in the late 70’s, during a period of economical instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he completed his Bachelors of Science in Computer Engineering at Florida International University. Luis resides in Rancho Cucamonga, California with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!
He is the CEO of Ortus Solutions, a consulting firm specializing in web development, ColdFusion (CFML), Java development and all open source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, MockBox, LogBox and anything “BOX”, and contributes to many open source ColdFusion projects. He is also the Adobe ColdFusion user group manager for the Inland Empire. You can read his blog at www.luismajano.com
Luis has a passion for Jesus, tennis, golf, volleyball and anything electronic. Random Author Facts:
He played volleyball in the Salvadorean National Team at the tender age of 17
The Lord of the Rings and The Hobbit is something he reads every 5 years. (Geek!)
His first ever computer was a Texas Instrument TI-86 that his parents gave him in 1986. After some time digesting his very first BASIC book, he had written his own tic-tac-toe game at the age of 9. (Extra geek!)
He has a geek love for circuits, microcontrollers and overall embedded systems.
He has of late (during old age) become a fan of running and bike riding with his family.
Keep Jesus number one in your life and in your heart. I did and it changed my life from desolation, defeat and failure to an abundant life full of love, thankfulness, joy and overwhelming peace. As this world breathes failure and fear upon any life, Jesus brings power, love and a sound mind to everybody!
“Trust in the LORD with all your heart, and do not lean on your own understanding.” Proverbs 3:5
Jorge is an Industrial and Systems Engineer born in El Salvador. After finishing his Bachelor studies at the Monterrey Institute of Technology and Higher Education ITESM, Mexico, he went back to his home country where he worked as the COO of Industrias Bendek S.A.. In 2012 he left El Salvador and moved to Switzerland in persuit of the love of his life. He married her and today he resides in Basel with his lovely wife Marta and their daughter Sofía.
Jorge started working as project manager and business developer at Ortus Solutions, Corp. in 2013, . At Ortus he fell in love with software development and now enjoys taking part on software development projects and software documentation! He is a fellow Cristian who loves to play the guitar, worship and rejoice in the Lord!
Therefore, if anyone is in Christ, the new creation has come: The old has gone, the new is here! 2 Corinthians 5:17
LogBox can handle the inserting of logging and/or tracing statements in your application with a simple to use API while providing you the ability to manage logging behavior outside of your application code.
You can configure LogBox via a programmatic configuration file (cfc)
LogBox categorizes your logging and/or tracing statements according to user-defined categories that can be configured at runtime or pre-runtime. All of these categorizations can have their own logging level ranges (such as debug or info) and even their own destination points or what we refer to as LogBox Appenders (such as Console).
LogBox Appenders are the destination points you configure for your logging and/or tracing statements. LogBox also offers a basic extensible API so you can build and extend upon the Appender framework according to your unique logging or tracing needs. This gives you complete control and flexibility of how to expand LogBox without reinventing the wheel. Some appenders included in LogBox can log to the following destinations: File, Database, Sockets, Email, ColdFusion logging, System Console, and much more.
LogBox facilitates the creation of your very own customized message formats via Layouts. You can create a Layout component that can be configured in to ANY LogBox appender so it can spit out your very own customized messages.
LogBox can be instantiated as many times as you want and used as many times as you like in a single application. There are no restrictions upon its usage.
LogBox allows for category inheritance according to component and package conventions.
LogBox can be downloaded as a standalone framework or it is included with the latest ColdBox Platform release. The main difference between both versions is the instantiation and usage namespace, the rest is the same.
The best way to install LogBox is using CommandBox CLI and package manager.
ColdFusion 11+
Lucee 4.5+
If you are using LogBox within a ColdBox application context, then LogBox is part of the platform. Just install ColdBox normally. If you are using LogBox standalone, just drop LogBox in your application root or create a mapping called logbox
that points to the installation folder. If you can run the following snippet, then LogBox is installed correctly:
You can leverage CommandBox to install the standalone version of LogBox
Standalone
logbox.system.logging
ColdBox
coldbox.system.logging
Info In this book we will be using the standalone namespace for all examples.
Most applications require logging and tracing capabilities. One can usually use ColdFusion's standard cflog
or cftrace
tags but you can reach a limitation very fast.
What if you needed to log only certain severity levels for a particular CFC or piece of code?
What if you needed that severity to advise you via SMS or Twitter (yes Twitter)?
What if you wanted to turn it off easily or reconfigure your logging levels?
You would have to build all of these advising and logging capabilities yourself. Also, inserting log statements is tedious, time consuming and frequently pollutes your real code. You can understand the pain and complexity required to properly deal with these situations. These reasons (and more) are why the ColdBox team has invested in building LogBox.
LogBox has four main components:
LogBox
Logger
Appenders
Layouts.
These four (4) components work in unison to deliver the logging and tracing of messages and to control how they are logged. You will mostly interact with the Logger component as it will send your statements to the Appenders you have configured. Users can extend LogBox and build their own appenders and layouts.
LogBox is the core framework you need to instantiate in order to work with logging in your application. You have to instantiate it with a LogBoxConfig
object that will hold your logging configurations. After the library is instantiated and configured you can ask from it a named Logger object so you can start logging or tracing messages.
You have two ways to use LogBox:
Standalone Framework
Within a ColdBox application
If you have downloaded LogBox as a standalone framework, then the initial namespace for the core is logbox.system
. This allows you to use logbox as a standalone framework that is integrated into your proprietary application.
The ColdBox Framework already has an instance of LogBox created for you in every application and it is stored in the main application controller: controller.getLogBox()
. The namespace within the ColdBox framework is coldbox.system
.
Our LogBox RefCard will get you up and running in no time
Logbox
An appender is an object that LogBox uses to log statements to a destination repository. All appenders act as destinations that can include: databases, JMS, files, consoles, sockets, etc. The appender has the responsibility of taking the logged message and persisting the message or sending the message to an external service. LogBox comes bundled with the following appenders that can be found in the package coldbox.system.logging.appenders
:
Asynchronous Appenders
You may wish your logs to be asynchronous. You can do so by passing an async
property in your configuration. ( This happens at the logger
level and is available to all appenders out of the box, even ones that you create yourself!
You can configure LogBox to use one or all of these appenders at any point in time. You can even register as many instances of any appender by defining a unique name for each. Here are examples of how one can configure appenders programmatically or via the simple configuration CFC:
Programmatic Approach
Configuration CFC approach
Another feature of a LogBox appender is that you can extend
them or create new ones simply by leveraging the LogBox API. To customize LogBox appenders for your own unique needs you would simply extend the core appender class: coldbox.system.logging.AbstractAppender
and implementing the init()
and logMessage()
methods. Extending LogBox will be reviewed in greater detail over the next few sections.
Appender | Description |
CFAppender | Will deliver messages to the coldfusion logs. |
ConsoleAppender | Will deliver messages to the server's console via system.out |
DBAppender | Will deliver messages to a database table. It can auto create the table for you. |
DummyAppender | An endless void of nothingness |
EmailAppender | Will deliver messages to any email address. |
FileAppender | Will deliver messages a file. |
RollingFileAppender | A file appender that can do file rotation and archiving. |
ScopeAppender | Will deliver messages to any ColdFusion variable scope. |
SocketAppender | Will connect to any server socket and deliver messages. |
TracerAppender | Will deliver messages to the ColdFusion tag cftrace. |
No matter what configuration you decide to use, you will always have to instantiate LogBox with a LogBoxConfig
object: logbox.system.logging.config.LogBoxConfig
. However you have the option of either talking directly to this CFC or creating a more portable configuration. This portable configuration we denote as a simple data CFC that contains the LogBox configuration data using what we call our LogBox DSL (Domain Specific Language).
The cool thing about this LogBox DSL is that it is exactly the same whether you are using LogBox in ColdBox applications or in any other framework or non-framework ColdFusion application. So you can configure LogBox by:
Creating a portable data CFC using the LogBox DSL or
Creating the LogBoxConfig
object and interacting with its methods
The layout component defines the format of the message to store in an appender repository. Be default, each appender already has a pre-defined message format. However, if you do not like the format of the message you can easily change it by creating your own layout component and registering it with the appender. You can do this in the configuration object when you add appenders:
Note: Not all appenders use a layout object (e.g. the
DBAppender
).
So to create your very own layout object, you just need to extend the LogBox abstract layout object: logbox.system.logging.Layout
and implement the format()
method.
We have a convention for our category names where each category name uses dot-notation according to the components path. Using a class-path convention for our category names allows one to pseudo-inherit for logging levels and appenders! The following example should help clarify this concept.
The overall premise is that when you request a logger with a category name LogBox will search for it's configuration. If LogBox does not find a configuration for the category name it will try to locate its closest ancestor for logging levels and appenders. If LogBox cannot find an ancestor the message will be logged using the root logger information. For example, let's say we define some appenders like this:
And some categories like this:
Then, let's say we request the following logger objects and logged some info:
Information All example code snippets are using a
getLogger( "categoryname" )
call instead of our preferred approach ofgetLogger( this )
because we want to showcase which category we are talking about. Please take this into consideration.
Since we requested the category: coldbox.system.plugins.BeanFactory
, LogBox tries to locate it, but it has not been defined, so it takes off the last item in the category name. Now it will search for a category of: coldbox.system.plugins
via pseudo-inheritance. However, now coldbox.system.plugins
has been found and it has been configured to only listen to error
messages. Therefore, the coldbox.system.plugins.BeanFactory
logger can ONLY log error messages according to it's inherited category. So the info()
message will be ignored, and the error()
message will be sent to both the FileAppender and the ConsoleAppender!
The second logger is called coldbox.system.interceptors.SES
, LogBox tries to match a category but fails, so it now searches for a logger called coldbox.system.interceptors
. It still cannot find it so it continues up the package chain and finds the coldbox.system
logger which has been set with a minimum of INFO
level and ONLY the console appender. So the messages that get logged is the logger.info()
and the logger.debug()
message and they will be sent to the console appender.
These examples should give you insight into category inheritance and the power they provide. You can easily turn toggle logging for entire packages with a single category definition. However, this is great only if you follow the dot notation conventions. Below is a sample generic chart sample:
Each logger object has several methods that you can use in order to interact with the logger's appenders. You can add, remove, clear or list the appenders on a specific logger instance. Below are the methods you can use in the logger class to interact with appenders:
So you can easily add/remove/check the appenders on any logger at any time.
In order to create a simple data CFC, just create a CFC with one required method on it called configure where you will define the logging configuration data:
Once you have this shell, you will create a logBox
variable in the variables
scope that must be a structure with the following keys:
To define an appender you must define a struct with a key value which is the internal name of the appender. Each appender name must be unique. You configure each appender with the following keys:
To configure the root logger use the following keys:
To define categories you must define a struct with a key value which is the internal name of the category. Each category name must be unique. You configure each category with the following keys:
As you might notice the name of the keys on all the structures match 100% to the programmatic methods you can also use to configure logBox. So when in doubt, refer back to the argument names.
Once you have defined the configuration data in this object you can now use the same LogBox Config object to either instantiate it for you or you can pass a reference of it by using the init()
method of the LogBoxConfig
object:
CFCConfig
: The object instance that has the logbox configuration data
CFCConfigPath
: The instantiation path of the object that has the logbox configuration data
That's it! Using this DSL approach, your configurations are much more portable now and can even be shared in ANY framework, ColdBox or ColdFusion application. So now let's explore how to bypass this data CFC and use the LogBoxConfig
object directly. It is important to understand these methods as they are called for you when you define your LogBox DSL data.
Name
Description
name
A unique name for the appender to register. Only unique names can be registered per instance.
class
The appender's class to register. We will create, init it and register it for you.
properties
The structure of properties to configure this appender with. (OPTIONAL)
layout
The layout class path to use in this appender for custom message rendering. (OPTIONAL)
levelMin
The numerical or English word of the minimal logging level (OPTIONAL, defaults to 0 [FATAL].)
levelMax
The numerical or English word of the maximum logging level (OPTIONAL, defaults to 4 [DEBUG].)
Method
Return Type
Description
hasAppenders()
Boolean
Checks if the logger has any appenders attached to it
getAppenders()
Struct
Returns the map of registered appenders
getAppender(name)
Appender
Return a named appender if it is registered in the logger
appenderExists(name)
Boolean
Checks if a named appender exists in the logger
addAppender(Appender)
void
Register an appender with the logger at runtime
removeAppender(name)
Boolean
Will un-register an appender from this logger
removeAllAppenders()
void
Will try to un-register all appenders from this logger
Key
Description
appenders
A structure where you will define appenders
root
A structure where you will configure the root logger
categories
A structure where you can define granular categories (OPTIONAL)
DEBUG
An array that will hold all the category names to place under the DEBUG logging level (OPTIONAL)
INFO
An array that will hold all the category names to place under the INFO logging level (OPTIONAL)
WARN
An array that will hold all the category names to place under the WARN logging level (OPTIONAL)
ERROR
An array that will hold all the category names to place under the ERROR logging level (OPTIONAL)
FATAL
An array that will hold all the category names to place under the FATAL logging level (OPTIONAL)
OFF
An array that will hold all the category names to not log at all (OPTIONAL)
Key
Description
class
The class path of the appender
properties
The properties struct for the appender (OPTIONAL)
layout
The layout class path of the layout object to use (OPTIONAL)
levelMin
The numerical or English word of the minimal logging level (OPTIONAL, defaults to 0 [FATAL])
levelMax
The numerical or English word of the maximum logging level (OPTIONAL, defaults to 4 [DEBUG])
Key
Description
levelMin
The numerical or English word of the minimal logging level (OPTIONAL, defaults to 0 [FATAL])
levelMax
The numerical or English word of the maximum logging level (OPTIONAL, defaults to 4 [DEBUG])
appenders
A string list of the appenders to use for logging
Key
Description
levelMin
The numerical or English word of the minimal logging level (OPTIONAL, defaults to 0 [FATAL])
levelMax
The numerical or English word of the maximum logging level (OPTIONAL, defaults to 4 [DEBUG])
appenders
A string list of the appenders to use for logging (OPTIONAL, defaults to *)
Category
Configured Levels
Assigned Levels
Appenders
root
FATAL-DEBUG
FATAL-DEBUG
console,file
coldbox.system
INFO-DEBUG
INFO-DEBUG
console
coldbox.system.plugins
ERROR
ERROR
*
coldbox.system.interceptors.SES
coldbox.system.interceptors.SES
INFO-DEBUG from coldbox.system
console from coldbox.system
coldbox.system.plugins.BeanFactory
NONE
ERROR from coldbox.system.plugins
*
Category
Configured Levels
Assigned Levels
root
FATAL-DEBUG
FATAL-DEBUG
x
NONE
FATAL-DEBUG from root
x.y
INFO
INFO
x.y.z
NONE
INFO from x.y
The methods shown below are used to add categories to specific severity levels only. Each method can receive 1 to * category arguments.
public void debug()
public void info()
public void warn()
public void error()
public void fatal()
public void off()
We recommend using the available can{severity}()
methods to determine if we can log at a specific log level before actually writing the logging method line. This is done as best practice in order to avoid processing of messages that will never be logged anyways. So let's look at a very simple example of what NOT to do:
This will call the logger's debug()
method, execute the lines of code and then the logger determines if it can be logged or not. This is ok, but we all love performance and best practice, so we encourage you to do the following:
This way, the logger determines if it can send debug log messages, and only IF IT CAN does it. This is faster and cleaner, but you will type more. Sorry!
Once you have created and configured the LogBox library, you can interact with it in order to get logger objects. The main methods you will use to interact with LogBox are the following, but I recommend you look at the CFC api (http://www.coldbox.org/api) in order to get a listing of all available methods.
The two most important methods are getRootLogger() & getLogger()
, which you will use to get the root or named logger objects.
Caution: When you ask for a named category logger and LogBox cannot find its definition, it will create a logger that will inherit its logging levels and appenders from the root logger.
Once you retrieve a logger object from LogBox, you are ready to start sending messages. We already covered how to dynamically add/remove/list/check appenders from a logger, so let's look at the other methods we have available:
Every logger has access to the following public variables:
As you can probably tell, all logging methods take in a message string an a second argument called extraInfo
. This extraInfo
argument can be anything from a string, a structure, a query or whatever. This way you can send in a complex structure that the appenders will serialize into message form or log into the appropriate channel. Thus, extraInfo
can be very handy when you are building your own custom appenders.
I hope that by now you understand the basics of loggers and how easy it is to use them.
Name
Description
name
A unique name for the category to register. Only unique names can be registered per instance.
levelMin
The default min log level for this category. (OPTIONAL. Defaults to 0 [FATAL].)
levelMax
The max default log level for this category. (OPTIONAL. Defaults to 4 [DEBUG].)
appenders
A list of appender names to configure this category with else it will use all the appenders in the root logger. You can also use * to add all registered apenders. (OPTIONAL)
Name
Description
levelMin
The default minimum log level for the root logger. (OPTIONAL. Defaults to 0 [FATAL].)
levelMax
The default maximum log level for the root logger. (OPTIONAL. Defaults to 4 [DEBUG].)
appenders
A list of appenders to configure the root logger with. Use *
to add all registered appenders
Method
Description
LogBoxConfig getConfig()
Get the config object registered
Logger getLogger(any category)
Get a named logger object using a category string or the object you will log from
Logger getRootLogger()
Get a reference to the root logger
string getVersion()
Get the current version of LogBox
string getCurrentAppenders()
Get a list of currently registered appenders
string getCurrentLoggers()
Get a list of currently instantiated loggers
void configure( LogBoxConfig config )
Dynamically re-configure the LogBox library
Property
Description
this.logLevels
A reference to the logbox.system.logging.LogLevels
class.
Method
Description
boolean canLog(numeric level)
Checks if this logger can log a certain type of severity. There is also a can{severity}()
method for each severity level.
boolean can{severity}()
Checks if this logger can log a certain type of severity.
void setCategory(category)
Set the category name.
Logger getRootLogger()
Get the root logger.
numeric getLevelMin()
Get the minimum severity level.
void setLevelMin(level)
Set the minimum severity level.
numeric getLevelMax()
Get the maximum severity level.
void setLevelMax(level)
Set the maximum severity level.
Method
Description
fatal(string message, [any extraInfo=""])
Log a fatal message.
error(string message, [any extraInfo=""])
Log an error message.
warn(string message, [any extraInfo=""])
Log a warning message.
info(string message, [any extraInfo=""])
Log an information message.
debug(string message, [any extraInfo=""])
Log a debug message.
logMessage(string message, numeric severity, [any extraInfo=""])
Log any kind of message.
This appender logs using Java's System.out.println
function. Logs will appear in the directory specificied in your CF or Lucee Administrator.
Property
The ConsoleAppender takes no additional properties.
The columns needed or created in the table are
id
: UUID
severity
: string
category
: string
logdate
: timestamp
appendername
: string
message
: string
extrainfo
: string
If you are building a column mapper, the map must have the above keys in it that match to your own table columns.
This appender logs directly to the cflog
tag by using a custom file or logging to the application logs.
Property
Type
Required
Default
Description
dsn
string
true
---
The dsn to use for logging
table
string
true
---
The table name to use for logging
columnMap
struct
false
---
A column map for aliasing columns. (Optional)
autocreate
boolean
false
false
if true, then we will create the table. Defaults to false (Optional)
Property | Type | Required | Default | Description |
logType | string(file or application) | false | file | The type of cflog to use: file or application. |
fileName | string | false | Appender's name | The name of the file to log to if using file as the logType. If not set, it will use the appender's name |
As we mentioned before, LogBox ships with over 10 different appenders for your logging and tracing needs. Some of them require configuration properties and some don't. We already discovered that when we configure an appender we can pass in a structure of properties much like how we configure ColdBox Interceptors. Each appender can implement as many properties as they see fit. We will digest all the included LogBox appenders and their configuration properties.
All appenders have an async
boolean property by default inherited from LogBox. This will tell LogBox to log asynchronously in a separate thread. By default all logging is done synchronously
Property
Type
Required
Default
Description
subject
string
true
---
Get's pre-pended with the severity and category field.
from
string
true
---
The from email address
to
string
true
---
The to email(s)
cc
string
false
empty
The cc email(s)
bcc
string
false
empty
The bcc email(s)
mailserver
string
false
empty
The optional mail server
mailusername
string
false
empty
The optional mail username
mailpassword
string
false
empty
The optional mail password
mailport
int
false
25
The optional mail port
useTLS
boolean
false
false
Use the Transport level security setting in the cfmail tag.
useSSL
boolean
false
false
Use SSL or not
When using any of the logging methods like info()
, debug()
, warn()
, etc, they all take two arguments:
The message to log
An extraInfo
argument which can be anything you like.
This extrainfo
argument can be a simple value, a CFC, a complex object and pretty much anything you like. The appenders get this extraInfo
argument and process it into their appropriate destinations by serializing its value. This is done by using the following algorithm:
If it is a simple value, then just use it.
If it is an object then check if the object has a method called $toString()
. If the method exists, then call $toString()
and use its return value.
If it is an object with no $toString()
method, then marshall its representation into XML format.
If it is a complex variable like a struct, query, array, etc, then marshall it into JSON format.
As you can see from the algorithm above, you can use the extraInfo
argument to your benefit to save serialized representations of data to the appenders and then retrieve or re-inflate them later. The $toString()
convention is great because you have complete control on how a CFC will serialize to its string representation. Let's see an example on a simple CFC:
So when this object is sent to a logger's method, it will detect it is an object and the $toString()
function exists and call it for serialization.
Info Please remember to set the
autoExpand
property to FALSE if you will be using an absolute file path location.
Property
Type
Required
Default
Description
filePath
string
true
---
The location of where to store the log file
filename
string
false
Name of the Appender
The name of the file, if not defined, then it will use the name of this appender. Do not append an extension to it. We will append a .log to it
fileEncoding
string
false
utf-8
The file encoding to use, by default we use UTF-8
autoExpand
boolean
false
true
Whether to expand the file path or not. Defaults to true
Property
Type
Required
Default
Description
scope
string
false
request
The scope to persist to, any valid CF scope.
key
string
false
appender's name
The key to use in the scope
limit
numeric
false
0
a limit to the amount of logs to rotate. Defaults to 0, unlimited (optional)
Property
Type
Requierd
Default
Description
host
string
true
The host to connect to
port
string
true
---
The port to connect to
timeout
numeric
false
5
the timeout in seconds. defaults to 5 seconds
persistConnection
boolean
false
true
Whether to persist the connection or create a new one every log time. Defaults to true
Info Please remember to set the
autoExpand
property to FALSE if you will be using an absolute file path location.
Property
Type
Required
Default
Description
filePath
string
true
---
The location of where to store the log file
filename
string
false
Name of the Appender
The name of the file, if not defined, then it will use the name of this appender. Do not append an extension to it. We will append a .log to it
fileEncoding
string
false
utf-8
The file encoding to use, by default we use UTF-8
autoExpand
boolean
false
true
Whether to expand the file path or not. Defaults to true
fileMaxSize
int
false
2000 (2MB)
The max file size for log files. Defaults to 2000 (2 MB)
fileMaxArchives
int
false
2
The max number of archives to keep. Defaults to 2
This appender directs messages via the cftrace
tag. It has no configuration properties.
Every ColdBox application can use LogBox by default since the main engine already uses it. By default ANY ColdBox application will be configured with a LogBox instance with the following appenders:
Also, the app will log on ANY severity by default up to INFO
for the root logger and the ColdBox package. You can customize this default behavior by creating or modifying the LogBox
element in your ColdBox configuration file and follow the same configuration approach as any normal LogBox configuration file.
ColdBox allows for a programmatic approach via the ColdBox.cfc
configuration object. So let's look at how the ColdBox loader looks at your configuration:
Is there a logBox
variable defined in the configuration?
False:
Does a LogBox.cfc
exist in the application's config
folder?
True: Use that CFC by convention to configure LogBox
False: Continue to next point
Configure LogBox with default framework settings (coldbox.system.web.config.LogBox
)
True:
Have you defined a configFile
key?
True: Then use that value to pass into the configuration object so it can load LogBox using that configuration file (CFC)
False: The configuration data is going to be defined inline here so process it
So the configuration DSL is exactly the same as you have seen in before with the only distinction that you can add a configFile
key that can point to an external configuration file (CFC).
Just by building a ColdBox application, you get several key benefits when dealing with LogBox.
First of all, the configuration, creation and instantiation is ALL done for you.
You can configure LogBox on a per-environment criteria as the ColdBox per-environment routines can use the LogBox configuration elements in its definitions.
Every handler and interceptor already has a reference to the LogBox instance as a property called: logBox
. So you have immediate access to it.
Every handler and interceptor already has a configured logger instance as a property called: log
. So you have immediate access to it.
You can configure the logging of ColdBox on a per package level.
You get the power of ColdBox MVC.
The LogBox instance is stored in the ColdBox main controller object (coldbox.system.web.Controller
) and you can retrieve it like so from any handler, or interceptor.
The ColdBox Proxy (coldbox.system.remote.ColdboxProxy
) object also has three utility methods you can use to talk to LogBox from any remote proxy you create:
getLogBox()
: Get a reference to the LogBox instance.
getRootLogger()
: Get a reference to the root logger.
getLogger(category:any)
: Get a named logger instance or reference.
WireBox DI and Injection can talk to LogBox. This way you can easily use our dependency injection DSL for LogBox related objects:
Below you can see the most common usage of this dependency DSL:
Type
Description
logbox
Get a reference to the application's LogBox instance
logbox:root
Get a reference to the root logger
logbox:logger:category
Get a reference to a named logger by its category name
logbox:logger:{this}
Get a reference to a named logger according to the current class path of the injected target
In order to create your own appenders, you will have to create a cfc that extends logbox.system.logging.AbstractAppender
and implement the following methods:
init()
The signature of the init method is the following:
As you can see each appender receives a name
, a structure of properties
, an optional layout
class, and an optional levelMin
and levelMax
severity levels. The properties
and layout
are both optional, but you must call the super.init( argumentCollection = arguments )
method in order to have full ok operation on the appender. You can then do your own constructor as you see fit. Here is an example:
logMessage()
The signature of the logMessage
method is the following:
As you can see it is a very simple method that receives a LogBox logging event object. This object keeps track of the following properties with its appropriate getters and setters:
timestamp
category
message
severity
extraInfo
You can then use this logging event object to log to whatever destination you want. Here is a snippet from our scope appender:
onRegistration()
& onUnregistration()
Finally, both the onRegistration
and onUnregistration
methods have to be void methods with no arguments.
These are great for starting or stopping your appenders if they so need to. Here is a sample from our socket appender:
Method
Description
init()
Your constructor. Make sure to call super.init( argumentCollection=arguments );
logMessage()
The method that is called when a message is received.
onRegistration()
An interceptor that fires when the appender gets created and initialized. It can be used for preparing the appender for operation.
onUnRegistration()
An interceptor that fires when the appender is removed from a logger.
You can programmatically register appenders at runtime by using the registerAppender()
function exposed in the LogBox object. Here is the function API:
Info Please note that registering dynamic appenders at runtime is tricky as some objecs might already have references to some appenders. We recommend registering appenders at configuration load or when the application starts up.
You can easily create a custom layout object by creating a cfc that extends our abstract layout object: logbox.system.logging.Layout
and implementing a format()
method. Below you can see the method signature:
All you need to do is inspect the logging event and create your very own message and then return it back. That's it! You thought there was more?
Every Appender has access to the following public variables:
Every layout has access to the following public variables:
Property
Description
this.logLevels
A reference to the logbox.system.logging.LogLevels
class.
Method
Description
struct getProperties()
Get the entire properties struct.
void setProperties(struct properties)
Override all properties with a new properties struct.
any getProperty(string property)
Get a property.
void setProperty(string property, any value)
Set a property.
boolean propertyExists(string property)
Checks if a property exists.
Method
Description
boolean isInitialized()
Returns true if the appender has been initialized.
string getName()
Get the name of the appender
string getHash()
Get the appender's unique hash id
string severityToString(numeric severity)
Transforms a severity integer to it's human readable form
Method
Description
any getCustomLayout()
Get the custom layout object if defined.
boolean hasCustomLayout()
Checks if the custom layout object is defined in this appender.
Property | Description |
| A reference to the |
| A line separator equal to |
In order for an appender to deal with custom layouts, you must use the layout methods when preparing to log your messages. Below is a simple example from the console appender of how to do this:
As you can see, all you need to do is have an if
statement that checks whether the appender has a custom layout or not and then assign the return of the layout as your message to log.