Logger

Package: MachII.logging.loggers.MachIILog
Inherits from: logging.loggers.AbstractLogger
A logger for Mach-II.

<!--- License: Copyright 2008 GreatBizTools, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Copyright: GreatBizTools, LLC Author: Peter J. Farrell (peter@mach-ii.com) $Id: Logger.cfc 1130 2008-10-31 00:20:20Z peterfarrell $ Created version: 1.6.0 Updated version: 1.6.0 Notes: <property name="Logging" type="MachII.logging.LoggingProperty"> <parameters> <parameter name="MachIILog"> <struct> <key name="type" value="MachII.logging.loggers.MachIILog.Logger" /> <!-- Optional and defaults to true --> <key name="loggingEnabled" value="true|false" /> <!-- Optional and defaults to 'fatal' --> <key name="loggingLevel" value="all|trace|debug|info|warn|error|fatal|off" /> <!-- Optional and defaults to the default display template if not defined --> <key name="displayOutputTemplateFile" value="/path/to/customOutputTemplate.cfm" /> <!-- Optional and defaults to 'false' Shows output only if CF's debug mode is enabled --> <key name="debugModeOnly" value="false" /> <!-- Optional and defaults to 'suppressDebug' Name of event arg that suppresses debug output (useful when a request returns xml, json or images) --> <key name="suppressDebugArg" value="suppressDebug" /> <!-- Optional --> <key name="filter" value="list,of,filter,criteria" /> - OR - <key name="filter"> <array> <element value="array" /> <element value="of" /> <element value="filter" /> <element value="criteria" /> </array> </key> </struct> </parameter> </parameters> </property> Uses the generic channel filter (MachII.logging.filters.GenericChannelFilter)for filtering. See that file header for configuration of filter criteria. --->

Method Summary
private array arrayConcat(array array1, array array2)

Concats two arrays together.

public void configure()

Configures the logger.

public struct getConfigurationData()

Gets the configuration data for this logger including adapter and filter.

public boolean getDebugModeOnly()

Gets if the output is shown only if CF's debug mode is enabled.

public string getDisplayOutputTemplateFile()

Gets the output template location which is used for display output.

private string getMachIIVersion(string version)

Gets a nice version number istead of just numbers.

public string getSuppressDebugArg()

Gets the event-arg the suppresses debug output if it is present.

public void onRequestEnd()

Displays output for this logger.

public void postRedirect(struct data)

Post-redirect logic for this logger.

public void preRedirect(struct data)

Pre-redirect logic for this logger.

private struct processCfdump(any dataToDump)

Processes a cfdump and returns a struct with data and head elements. Also, cleans up invalid HTML syntax so debugging output will not mess up HTML validators.

private void setDebugModeOnly(boolean debugModeOnly)

Sets if the output is shown only if CF's debug mode is enabled.

private void setDisplayOutputTemplateFile(string displayOutputTemplateFile)

Sets the output template location which is used for display output.

private void setSuppressDebugArg(string suppressDebugArg)

Sets the event-arg the suppresses debug output if it is present.

Methods inherited from logging.loggers.AbstractLogger:   setLoggingLevel , isParameterDefined , getLoggerTypeName , setParameter , setLoggingEnabled , init , isMethodDefined , isPrePostRedirectAvailable , getLogAdapter , getLoggerType , isLoggingEnabled , getParameterNames , isOnRequestEndAvailable , getParameter , setParameters , setLoggerId , getParameters , setLogAdapter , getLoggerId , getLoggingLevel
Method Detail
arrayConcat

private array arrayConcat( array array1, array array2 )

Concats two arrays together.

Parameters:
array array1
array array2

Code:

	<cffunction name="arrayConcat" access="private" returntype="array" output="false"
		hint="Concats two arrays together.">
		<cfargument name="array1" type="array" required="true" />
		<cfargument name="array2" type="array" required="true" />
		
		<cfset var result = arguments.array1 />
		<cfset var i = 0 />
		
		<cfloop from="1" to="#ArrayLen(arguments.array2)#" index="i">
			<cfset ArrayAppend(result, arguments.array2[i]) />
		</cfloop>
		
		<cfreturn result />
	</cffunction> 

configure

public void configure( )

Configures the logger.

Parameters:

Code:

	<cffunction name="configure" access="public" returntype="void" output="false"
		hint="Configures the logger.">
		
		<cfset var filter = CreateObject("component", "MachII.logging.filters.GenericChannelFilter").init(getParameter("filter", "")) />
		<cfset var adapter = CreateObject("component", "MachII.logging.adapters.ScopeAdapter").init(getParameters()) />
		
		
		<cfset adapter.setFilter(filter) />
		
		
		<cfset adapter.configure() />
		<cfset setLogAdapter(adapter) />
		
		
		<cfif isParameterDefined("displayOutputTemplateFile")>
			<cfset setDisplayOutputTemplateFile(getParameter("displayOutputTemplateFile")) />
		</cfif>
		
		<cfif isParameterDefined("debugModeOnly")>
			<cfif NOT IsBoolean(getParameter("debugModeOnly"))>
				<cfthrow type="MachII.logging.loggers.MachIILog.Logger"
					message="The value of 'debugModeOnly' must be boolean."
					detail="Current value '#getParameter('debugModeOnly')#'" />
			<cfelse>
				<cfset setDebugModeOnly(getParameter("debugModeOnly")) />
			</cfif>
		</cfif>
		
		<cfif isParameterDefined("suppressDebugArg")>
			<cfset setSuppressDebugArg(getParameter("suppressDebugArg")) />
		</cfif>
	</cffunction> 

getConfigurationData

public struct getConfigurationData( )

Gets the configuration data for this logger including adapter and filter.

Parameters:

Code:

	<cffunction name="getConfigurationData" access="public" returntype="struct" output="false"
		hint="Gets the configuration data for this logger including adapter and filter.">
		
		<cfset var data = StructNew() />
		
		<cfset data["Debug Mode Only"] = getDebugModeOnly() />
		<cfset data["Supress Debug Arg"] = getSuppressDebugArg() />
		<cfset data["Display Output Template"] = getDisplayOutputTemplateFile() />
		<cfset data["Logging Enabled"] = YesNoFormat(isLoggingEnabled()) />
		
		<cfreturn data />
	</cffunction> 

getDebugModeOnly

public boolean getDebugModeOnly( )

Gets if the output is shown only if CF's debug mode is enabled.

Parameters:

Code:

	<cffunction name="getDebugModeOnly" access="public" returntype="boolean" output="false"
		hint="Gets if the output is shown only if CF's debug mode is enabled.">
		<cfreturn variables.instance.debugModeOnly />
	</cffunction> 

getDisplayOutputTemplateFile

public string getDisplayOutputTemplateFile( )

Gets the output template location which is used for display output.

Parameters:

Code:

	<cffunction name="getDisplayOutputTemplateFile" access="public" returntype="string" output="false"
		hint="Gets the output template location which is used for display output.">
		<cfreturn variables.instance.displayOutputTemplateFile />
	</cffunction> 

getMachIIVersion

private string getMachIIVersion( string version )

Gets a nice version number istead of just numbers.

Parameters:
string version

Code:

	<cffunction name="getMachIIVersion" access="private" returntype="string" output="false"
		hint="Gets a nice version number istead of just numbers.">
		<cfargument name="version" type="string" required="true" />

		<cfset var release = "" />
		
		<cfswitch expression="#ListLast(arguments.version, ".")#">
			<cfcase value="0">
				<cfset release = "BER - Unknown build" />
			</cfcase>
			<cfcase value="1">
				<cfset release = "Alpha" />
			</cfcase>
			<cfcase value="2">
				<cfset release = "Beta" />
			</cfcase>
			<cfcase value="3">
				<cfset release = "RC1" />
			</cfcase>
			<cfcase value="4">
				<cfset release = "RC2" />
			</cfcase>
			<cfcase value="5">
				<cfset release = "RC3" />
			</cfcase>
			<cfcase value="6">
				<cfset release = "RC4" />
			</cfcase>
			<cfcase value="7">
				<cfset release = "RC5" />
			</cfcase>
			<cfcase value="8">
				<cfset release = "Production Stable" />
			</cfcase>
			<cfcase value="9">
				<cfset release = "Production-Only Stable (duck-typed)" />
			</cfcase>
			<cfdefaultcase>
				<cfset release = "BER - Build " & ListLast(arguments.version, ".") />
			</cfdefaultcase>
		</cfswitch>
		
		<cfreturn Left(arguments.version, Len(arguments.version) - Len(ListLast(arguments.version, ".")) - 1) & " " & release />
	</cffunction> 

getSuppressDebugArg

public string getSuppressDebugArg( )

Gets the event-arg the suppresses debug output if it is present.

Parameters:

Code:

	<cffunction name="getSuppressDebugArg" access="public" returntype="string" output="false"
		hint="Gets the event-arg the suppresses debug output if it is present.">
		<cfreturn variables.instance.suppressDebugArg />
	</cffunction> 

onRequestEnd

public void onRequestEnd( )

Displays output for this logger.

Parameters:

Code:

	<cffunction name="onRequestEnd" access="public" returntype="void"
		hint="Displays output for this logger.">
		
		
		
		<cfset var data = ArrayNew(1) />
		<cfset var local = StructNew() />
		<cfset var out = getPageContext().getOut() />
		<cfset var buffer = "" />
		<cfset var count = 0 />
		<cfset var output = "" />
		
		
		<cfif getLogAdapter().getLoggingEnabled()
			AND getLogAdapter().isLoggingDataDefined()
			AND ((getDebugModeOnly() AND IsDebugMode()) OR NOT getDebugModeOnly())
			AND NOT arguments.event.isArgDefined(getSuppressDebugArg())>

			<cfset data = getLogAdapter().getLoggingData().data />
			
			<cfsavecontent variable="output">
				<cfinclude template="#getDisplayOutputTemplateFile()#" />
			</cfsavecontent>
			
			
			<cftry>
				<cfset buffer = out.getBuffer().toString() />
				<cfcatch type="any">
					
				</cfcatch>
			</cftry>

			
			<cfif StructKeyExists(local, "headElement")>
				<cfhtmlhead text="#local.headElement#" />
			</cfif>
				
			
			<cfset count = FindNoCase("</body>", buffer) />
			<cfif count>
				<cfset output = Insert(output, buffer, count - 1) />
				<cfset out.clearBuffer() />
			</cfif>
			
			<cfoutput>#output#</cfoutput>
		</cfif>
	</cffunction> 

postRedirect

public void postRedirect( struct data )

Post-redirect logic for this logger.

Parameters:
struct data

Code:

	<cffunction name="postRedirect" access="public" returntype="void" output="false"
		hint="Post-redirect logic for this logger.">
		<cfargument name="data" type="struct" required="true"
			hint="Redirect persist data struct." />

		<cfset var loggingData = StructNew() />
		
		<cfif getLogAdapter().getLoggingEnabled() AND getLogAdapter().isLoggingDataDefined()>
			<cftry>
				<cfset loggingData = getLogAdapter().getLoggingData() />
				<cfset loggingData.data = arrayConcat(arguments.data[getLoggerId()].data, loggingData.data) />
				<cfcatch type="any">
					
				</cfcatch>
			</cftry>
		</cfif>
	</cffunction> 

preRedirect

public void preRedirect( struct data )

Pre-redirect logic for this logger.

Parameters:
struct data

Code:

	<cffunction name="preRedirect" access="public" returntype="void" output="false"
		hint="Pre-redirect logic for this logger.">
		<cfargument name="data" type="struct" required="true"
			hint="Redirect persist data struct." />
		
		<cfif getLogAdapter().getLoggingEnabled() AND getLogAdapter().isLoggingDataDefined()>
			<cfset arguments.data[getLoggerId()] = getLogAdapter().getLoggingData() />
		</cfif>
	</cffunction> 

processCfdump

private struct processCfdump( any dataToDump )

Processes a cfdump and returns a struct with data and head elements. Also, cleans up invalid HTML syntax so debugging output will not mess up HTML validators.

Parameters:
any dataToDump

Code:

	<cffunction name="processCfdump" access="private" returntype="struct" output="false"
		hint="Processes a cfdump and returns a struct with data and head elements. 
		Also, cleans up invalid HTML syntax so debugging output will not mess up HTML validators.">
		<cfargument name="dataToDump" type="any" required="true" />
		
		<cfset var data = CreateObject("java", "java.lang.StringBuffer") />
		<cfset var results = StructNew() />
		<cfset var reFindResults = "" />
		<cfset var temp = "" />
		
		
		<cfsavecontent variable="temp"><cfdump var="#arguments.dataToDump#" expand="false" /></cfsavecontent>
		<cfset data.init(temp) />
		
		
		<cfset results.data = "" />
		<cfset results.headElement = "" />
		
		
		<cfset reFindResults = REFindNoCase("(<style.*</style>)", data.toString(), 1, true) />
		
		<cfif reFindResults.pos[1] NEQ 0>
			
			<cfset temp = data.substring(reFindResults.pos[1] - 1, reFindResults.len[1] + reFindResults.pos[1] - 1) />

			
			<cfset temp = REReplace(temp, "<style.*?>", '<style type="text/css">', "one") />
			
			<cfset data.delete(reFindResults.pos[1] - 1, reFindResults.len[1] + reFindResults.pos[1] - 1) />
			<cfset results.headElement = results.headElement & temp />
		</cfif>
		
		
		<cfset reFindResults = REFindNoCase("(<script.*</script>)", data.toString(), 1, true) />
		
		<cfif reFindResults.pos[1] NEQ 0>
			<cfset temp = data.substring(reFindResults.pos[1] - 1, reFindResults.len[1] + reFindResults.pos[1] - 1) />
			
			
			<cfset temp = REReplace(temp, "<script.*?>", '<script type="text/javascript">', "one") />
			
			<cfset data.delete(reFindResults.pos[1] - 1, reFindResults.len[1] + reFindResults.pos[1] - 1) />
			<cfset results.headElement = results.headElement & temp />
		</cfif>
		
		
		<cfset results.data = data.toString() />

		<cfreturn results />
	</cffunction> 

setDebugModeOnly

private void setDebugModeOnly( boolean debugModeOnly )

Sets if the output is shown only if CF's debug mode is enabled.

Parameters:
boolean debugModeOnly

Code:

	<cffunction name="setDebugModeOnly" access="private" returntype="void" output="false"
		hint="Sets if the output is shown only if CF's debug mode is enabled.">
		<cfargument name="debugModeOnly" type="boolean" required="true" />
		<cfset variables.instance.debugModeOnly = arguments.debugModeOnly />
	</cffunction> 

setDisplayOutputTemplateFile

private void setDisplayOutputTemplateFile( string displayOutputTemplateFile )

Sets the output template location which is used for display output.

Parameters:
string displayOutputTemplateFile

Code:

	<cffunction name="setDisplayOutputTemplateFile" access="private" returntype="void" output="false"
		hint="Sets the output template location which is used for display output.">
		<cfargument name="displayOutputTemplateFile" type="string" required="true" />
		<cfset variables.instance.displayOutputTemplateFile = arguments.displayOutputTemplateFile />
	</cffunction> 

setSuppressDebugArg

private void setSuppressDebugArg( string suppressDebugArg )

Sets the event-arg the suppresses debug output if it is present.

Parameters:
string suppressDebugArg

Code:

	<cffunction name="setSuppressDebugArg" access="private" returntype="void" output="false"
		hint="Sets the event-arg the suppresses debug output if it is present.">
		<cfargument name="suppressDebugArg" type="string" required="true" />
		<cfset variables.instance.suppressDebugArg = arguments.suppressDebugArg />
	</cffunction>