Can <LogBox> be added to an <environment> tag?
Does it just add to the default <LogBox> settings or completely
replace them? i.e., do I need the entire <LogBox> block from
coldbox.xml or can I just specify the parts I want changed?
I'm thinking it would be nice to add development-only <Category> tags
with DEBUG level enabled...
The environment control interceptor can read elements in the environments xml, however, it means that you will be overriding the entire config.
The programmatic approach is more leaning, since well, you are not in XML, but I believe you are not using this approach. But in the programmatic approach you can add, remove, edit, etc on a per environment basis.
P.S: Logging ROCKS!!! 
Luis F. Majano
President
Ortus Solutions, Corp
ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com
By the way, you can create an interceptor or a handler at app start that can reconfigure logbox programmatically also. You have access to LogBox in all your handlers, interceptors, etc. Then you can request the config: logBox.getConfig() and then add categories, appenders, etc.
Just ideas
Luis F. Majano
President
Ortus Solutions, Corp
ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com
Thanx. That pointed me in the right direction. I added code to my
environment control interceptor (since we select environments based on
the inet host name rather than the default domain name). If the
environment name contains 'development' (we have a separate env for
every developer so everyone can customize their settings for
debugging), then we tell LogBox to use FATAL..DEBUG on all <Category>s
otherwise FATAL..INFO.
That allows us to liberally add debug() messages visible in dev that
are suppressed on all other tiers.
I also extended ConsoleAppender as DebugConsoleAppender that only
calls super.logMessage() if logEvent.getSeverity() == logLevels.DEBUG
(much as our FatalEmailAppender only triggers on logLevels.FATAL).
Now we have debug messages appearing only in dev and going to console
and a rolling file. Info, warn and error go to the rolling file and a
DB table. Fatal goes to the rolling file, the DB table and via email.
In addition ColdBox uses a different rolling file (root logger vs
category loggers for our model tree and our webroot tree).
Still not "fun" but effective and powerful.
WOW!! That is some setup Sean!! I likey!!
By the way, I got inspired last night and finished appender affinity. So now you can have a last granular line of defense at the appender level. By default they allow all levels as they expect the loggers to handle it. However, you can now declare them with levels:
//DSL
logBox = {
// Define Appenders
appenders = {
coldboxTracer = {
class=“coldbox.system.logging.appenders.ColdboxTracerAppender”,
layout=“coldbox.testing.cases.logging.MockLayout”,
levelMax = “WARN”
}
}
}
Or via the XML
I will commit these cahnges and some other fixes tonight. Also, you can get the latest SVN logging package and drop it on your current coldbox install without affecting the rest of the core, since LogBox is a modular piece.
Luis F. Majano
President
Ortus Solutions, Corp
ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com
WOW!! That is some setup Sean!! I likey!!
I figured I should share what I have:
<LogBox>
<!-- Don't use ColdBox Tracer in production
<Appender name="coldboxTracer"
class="coldbox.system.logging.appenders.ColdboxTracerAppender" />
-->
<Appender name="debug" class="ws.model.logging.DebugConsoleAppender" />
<Appender name="dbLog" class="ws.model.logging.DBLogAppender" />
<Appender name="email" class="ws.model.logging.FatalEmailAppender">
<Property name="subject">WorldSingles</Property>
<Property name="from">${OwnerEmail}</Property>
<Property name="to">${DevelopmentEmail}</Property>
</Appender>
<Appender name="sysFileLog"
class="coldbox.system.logging.appenders.AsyncRollingFileAppender">
<Property name="filePath">/ws/logfiles</Property>
<Property name="fileName">system</Property>
</Appender>
<Appender name="wsFileLog"
class="coldbox.system.logging.appenders.AsyncRollingFileAppender"
layout="ws.model.logging.FileLayout">
<Property name="filePath">/ws/logfiles</Property>
<Property name="fileName">application</Property>
</Appender>
<!-- Root Logger Definition -->
<Root levelMin="FATAL" levelMax="INFO" appenders="email,sysFileLog" />
<!-- Application-specific Categories -->
<Category name="ws" levelMin="FATAL" levelMax="DEBUG"
appenders="debug,dbLog,email,wsFileLog" />
<Category name="handlers" levelMin="FATAL" levelMax="DEBUG"
appenders="debug,dbLog,email,wsFileLog" />
</LogBox>
I think I've explained the appenders. The FileLayout simply pulls out
some specific keys we use in the struct version of extraInfo so the
log message is formatted a little more cleanly. It might be nice to
have a way to format just the extraInfo portion so you don't have to
duplicate the entire formatting for a given appender.
By the way, I got inspired last night and finished appender affinity. So
now you can have a last granular line of defense at the appender level.
Cool. Thanx. That will allow me to remove the DebugConsoleAppender and
FatalEmailAppender I think and use the regular ones with levels
specified instead. I'll open a ticket in our system to remind me.
Sean,
Can you elaborate on how you reconfigured LogBox in your interceptor?
I'm trying to implement similar enviroment config for LogBox using the
following code::
coldbox.xml:
<Interceptors>
<!-- USE ENVIRONMENT CONTROL -->
<Interceptor class="interceptors.EnvironmentControl">
<Property name='configFile'>config/environments.xml.cfm</Property>
</Interceptor>
<!-- USE AUTOWIRING -->
<Interceptor class="coldbox.system.interceptors.Autowire" />
<!-- USE SES -->
<Interceptor class="coldbox.system.interceptors.SES" />
<!-- Configure LogBox with environment settings -->
<Interceptor class="interceptors.LogBoxInterceptor" />
</Interceptors>
interceptors.LogBoxInterceptor.cfc:
<cfcomponent extends="coldbox.system.Interceptor" output="false">
<cffunction name="afterAspectsLoad" access="public"
returntype="void">
<cfargument name="event" required="true" />
<cfargument name="interceptData" required="true" />
<cfscript>
config = logBox.getConfig();
config.appender(name="console",class="coldbox.system.logging.appenders.ConsoleAppender");
config.category(name="model.services",appenders="console");
</cfscript>
</cffunction>
</cfcomponent>
This was just a test to see if I could add a new appender and category
after app start, but it's failing with the following message:
Error Type: Autowire.AutowireException : [N/A]
Error Messages: Error autowiring handlers.Main. Element console is
undefined in a CFML structure referenced as part of an expression.
Thanks,
Eric
Sure. In my environment control interceptor I have this code:
if ( find( 'development', environment ) == 0 ) {
var cats = logBox.getConfig().getAllCategories();
var cat = 0;
for ( cat in cats ) {
if ( cats[ cat ].levelMax > logBox.logLevels.INFO ) {
logger.debug( 'Non-Development: reset levelMax for ' & cats[
cat ].name );
cats[ cat ].levelMax = logBox.logLevels.INFO;
}
}
}
So for any environment that has development in the name, it leaves the
levels set to FATAL..DEBUG but for non-development, it resets all
categories to stop at INFO.