| 63 | | <cffunction name="tracer" access="Public" hint="Log a trace message to the debugger panel" output="false" returntype="void"> |
| 64 | | <!--- ************************************************************* ---> |
| 65 | | <cfargument name="message" type="string" required="Yes" hint="Message to Send" > |
| 66 | | <cfargument name="ExtraInfo" required="No" default="" type="any" hint="Extra Information to dump on the trace"> |
| 67 | | <!--- ************************************************************* ---> |
| 68 | | <cfscript> |
| 69 | | var tracerEntry = StructNew(); |
| 70 | | var event = controller.getRequestService().getContext(); |
| 71 | | var oSessionStorage = getPlugin("sessionstorage"); |
| 72 | | var tracerStack = ""; |
| 73 | | |
| 74 | | /* Verify if the tracer stack exists, else create */ |
| 75 | | if ( not oSessionStorage.Exists("fw_tracerStack") ){ |
| 76 | | oSessionStorage.setVar("fw_tracerStack", ArrayNew(1) ); |
| 77 | | } |
| 78 | | |
| 79 | | /* Local Reference */ |
| 80 | | tracerStack = oSessionStorage.getVar("fw_tracerStack"); |
| 81 | | |
| 82 | | /* Insert Message & Info to entry */ |
| 83 | | StructInsert(tracerEntry,"message", arguments.message); |
| 84 | | |
| 85 | | /* Extra Info Operations */ |
| 86 | | if ( not isSimpleValue(arguments.ExtraInfo) ) |
| 87 | | StructInsert(tracerEntry,"ExtraInfo", duplicate(arguments.ExtraInfo)); |
| 88 | | else |
| 89 | | StructInsert(tracerEntry,"ExtraInfo", arguments.ExtraInfo); |
| 90 | | |
| 91 | | /* Append Entry to Array */ |
| 92 | | ArrayAppend(tracerStack,tracerEntry); |
| 93 | | |
| 94 | | /* Store in Flash Session Variable */ |
| 95 | | oSessionStorage.setVar("fw_tracerStack", tracerStack ); |
| 96 | | </cfscript> |
| 97 | | </cffunction> |
| 98 | | |
| 99 | | <!--- ************************************************************* ---> |
| 100 | | |
| 105 | | <!--- Initialize variables ---> |
| 106 | | <cfset var Exception = arguments.ExceptionBean> |
| 107 | | <cfset var BugReport = ""> |
| 108 | | <cfset var logSubject = ""> |
| 109 | | <cfset var errorText = ""> |
| 110 | | <cfset var arrayTagContext = ""> |
| 111 | | <cfset var myStringBuffer = ""> |
| 112 | | |
| 113 | | <cftry> |
| 114 | | <cfif getSetting("EnableColdfusionLogging") or getSetting("EnableColdboxLogging")> |
| 115 | | <!--- Log Entry in the Logs ---> |
| 116 | | <cfif isStruct(Exception.getExceptionStruct())> |
| 117 | | <cfset myStringBuffer = getPlugin("StringBuffer").setup(BufferLength=500)> |
| 118 | | <cfif Exception.getType() neq ""> |
| 119 | | <cfset myStringBuffer.append( "CFErrorType=" & Exception.getType() & chr(13) )> |
| 120 | | </cfif> |
| 121 | | <cfif Exception.getDetail() neq ""> |
| 122 | | <cfset myStringBuffer.append("CFDetails=" & Exception.getDetail() & chr(13) )> |
| 123 | | </cfif> |
| 124 | | <cfif Exception.getMessage() neq ""> |
| 125 | | <cfset myStringBuffer.append("CFMessage=" & Exception.getMessage() & chr(13) )> |
| 126 | | </cfif> |
| 127 | | <cfif Exception.getStackTrace() neq ""> |
| 128 | | <cfset myStringBuffer.append("CFStackTrace=" & Exception.getStackTrace() & chr(13) )> |
| 129 | | </cfif> |
| 130 | | <cfif Exception.getTagContextAsString() neq ""> |
| 131 | | <cfset myStringBuffer.append("CFTagContext=" & Exception.getTagContextAsString() & chr(13) )> |
| 132 | | </cfif> |
| 133 | | </cfif> |
| 134 | | <!--- Log the Entry ---> |
| 135 | | <cfset logEntry("error","Custom Error Message: #Exception.getExtraMessage()#",myStringBuffer.getString() )> |
| 136 | | </cfif> |
| 137 | | <cfcatch type="any"><!---Silent Failure---></cfcatch> |
| 138 | | </cftry> |
| 139 | | |
| 140 | | <!--- Check if Bug Reports are Enabled, then send Email Bug Report ---> |
| 141 | | <cfif getSetting("EnableBugReports") and getSetting("BugEmails") neq ""> |
| 142 | | <cftry> |
| 143 | | <!--- Save the Bug Report ---> |
| 144 | | <cfset BugReport = controller.getService("exception").renderEmailBugReport(arguments.ExceptionBean)> |
| 145 | | <!--- Setup The Subject ---> |
| 146 | | <cfset logSubject = "#getSetting("Codename",1)# Bug Report: #getSetting("Environment")# - #getSetting("appname")#"> |
| 147 | | <!--- Check for Custom Mail Settings or use CFMX Administrator Settings ---> |
| 148 | | <cfif getSetting("MailServer") neq ""> |
| 149 | | <!--- Mail New Bug ---> |
| 150 | | <cfmail to="#getSetting("BugEmails")#" |
| 151 | | from="#getSetting("OwnerEmail")#" |
| 152 | | subject="#logSubject#" |
| 153 | | type="html" |
| 154 | | server="#getSetting("MailServer")#" |
| 155 | | username="#getSetting("MailUsername")#" |
| 156 | | password="#getSetting("MailPassword")#">#BugReport#</cfmail> |
| 157 | | <cfelse> |
| 158 | | <!--- Mail New Bug ---> |
| 159 | | <cfmail to="#getSetting("BugEmails")#" |
| 160 | | from="#getSetting("OwnerEmail")#" |
| 161 | | subject="#logSubject#" |
| 162 | | type="html" |
| 163 | | username="#getSetting("MailUsername")#" |
| 164 | | password="#getSetting("MailPassword")#">#BugReport#</cfmail> |
| 165 | | </cfif> |
| 166 | | <cfcatch type="any"><!---Silent Failure---></cfcatch> |
| 167 | | </cftry> |
| | 50 | <cfif getThread().currentThread().getThreadGroup().getName() eq "cfthread"> |
| | 51 | <cfscript> |
| | 52 | super.logErrorWithBean(argumentCollection=arguments); |
| | 53 | </cfscript> |
| | 54 | <cfelse> |
| | 55 | <cfthread name="coldbox.plugins.MTlogger.logErrorWithBean-#createUUID()#"> |
| | 56 | <cfscript> |
| | 57 | super.logErrorWithBean(argumentCollection=arguments); |
| | 58 | </cfscript> |
| | 59 | </cfthread> |
| 190 | | <!--- Check for Severity via RE ---> |
| 191 | | <cfif not reFindNoCase("^(#getValidSeverities()#)$",arguments.Severity)> |
| 192 | | <cfthrow type="Framework.plugins.logger.InvalidSeverityException" message="The severity you entered: #arguments.severity# is an invalid severity. Valid severities are #getValidSeverities()#."> |
| 193 | | </cfif> |
| 194 | | |
| 195 | | <!--- Check for Coldfusion Logging ---> |
| 196 | | <cfif getSetting("EnableColdfusionLogging")> |
| 197 | | <!--- Coldfusion Log Entry ---> |
| 198 | | <cflog type="#trim(lcase(arguments.severity))#" |
| 199 | | text="#arguments.message# & #chr(13)# & ExtraInfo: #arguments.ExtraInfo#" |
| 200 | | file="#getLogFileName()#"> |
| 201 | | </cfif> |
| 202 | | |
| 203 | | <!--- Check For Coldbox Logging ---> |
| 204 | | <cfif getSetting("EnableColdboxLogging")> |
| 205 | | <!--- Check for Log File ---> |
| 206 | | <cfif not FileExists(getlogFullPath())> |
| 207 | | <!--- File has been deleted, reinit the log location ---> |
| 208 | | <cfset initLogLocation(false)> |
| 209 | | <!--- Log the occurrence recursively---> |
| 210 | | <cfset logEntry("warning","Log Location had to be reinitialized. The file: #getLogFullPath()# was not found when trying to do a log.")> |
| 211 | | </cfif> |
| 212 | | |
| 213 | | <!--- Check Rotation ---> |
| 214 | | <cfset checkRotation()> |
| 215 | | |
| 216 | | <cflock type="exclusive" name="#getLockName()#" timeout="120"> |
| 217 | | <cftry> |
| 218 | | <cffile action="append" |
| 219 | | addnewline="true" |
| 220 | | file="#getlogFullPath()#" |
| 221 | | output="#formatLogEntry(arguments.severity,arguments.message,arguments.extraInfo)#" |
| 222 | | charset="#getSetting("LogFileEncoding",1)#"> |
| 223 | | <cfcatch type="any"> |
| 224 | | <cfthrow type="Framework.plugins.logger.WritingEntryException" message="An error occurred writing an entry to the log file." detail="#cfcatch.Detail#<br>#cfcatch.message#"> |
| 225 | | </cfcatch> |
| 226 | | </cftry> |
| 227 | | </cflock> |
| | 71 | <!--- if we're inside a cfthread, run syncronously ---> |
| | 72 | <cfif getThread().currentThread().getThreadGroup().getName() eq "cfthread"> |
| | 73 | <cfscript> |
| | 74 | super.logEntry(argumentCollection=arguments); |
| | 75 | </cfscript> |
| | 76 | <cfelse> |
| | 77 | <cfthread name="coldbox.plugins.MTlogger.logEntry-#createUUID()#"> |
| | 78 | <cfscript> |
| | 79 | super.logEntry(argumentCollection=arguments); |
| | 80 | </cfscript> |
| | 81 | </cfthread> |
| 233 | | <cffunction name="initLogLocation" access="public" hint="Initialize the ColdBox log location." output="false" returntype="void"> |
| 234 | | <!--- ************************************************************* ---> |
| 235 | | <cfargument name="firstRunFlag" default="true" type="boolean" required="false" hint="This is true when ran from the configloader, to run the setupLogLocationVariables() method."> |
| 236 | | <!--- ************************************************************* ---> |
| 237 | | <cfset var FileWriter = ""> |
| 238 | | <cfset var InitString = ""> |
| 239 | | <cfset var oFileUtilities = ""> |
| 240 | | |
| 241 | | <cflock name="#getlockName()#" type="exclusive" timeout="120"> |
| 242 | | <!--- Determine First Run ---> |
| 243 | | <cfif arguments.firstRunFlag> |
| 244 | | <!--- Setup Log Location Variables ---> |
| 245 | | <cfset setupLogLocationVariables()> |
| 246 | | </cfif> |
| 247 | | <!--- Create Log File if It does not exist and initialize it. ---> |
| 248 | | <cfif not fileExists(getLogFullPath())> |
| 249 | | <cfset oFileUtilities = getPlugin("Utilities")> |
| 250 | | <cftry> |
| 251 | | <!--- Create Log File ---> |
| 252 | | <cfset oFileUtilities.createFile(getLogFullPath())> |
| 253 | | <!--- Check if we can write to the file ---> |
| 254 | | <cfif not oFileUtilities.FileCanWrite(getLogFullPath())> |
| 255 | | <cfthrow type="Framework.plugins.logger.LogFileNotWritableException" message="The log file: #getLogFullPath()# is not a writable file. Please check your operating system's permissions."> |
| 256 | | </cfif> |
| 257 | | <cfcatch type="any"> |
| 258 | | <cfthrow type="Framework.plugins.logger.CreatingLogFileException" message="An error occurred creating the log file at #getLogFullPath()#." detail="#cfcatch.Detail#<br>#cfcatch.message#"> |
| 259 | | </cfcatch> |
| 260 | | </cftry> |
| 261 | | |
| 262 | | <cftry> |
| 263 | | <!--- |
| 264 | | Log Format |
| 265 | | "[severity]" "[ThreadID]" "[Date]" "[Time]" "[Application]" "[Message]" |
| 266 | | ---> |
| 267 | | <cfset InitString = '"Severity","ThreadID","Date","Time","Application","Message"' & chr(13) & chr(10) & formatLogEntry("information","The log file has been initialized successfully by ColdBox.","Log file: #getLogFullPath()#; Encoding: #getSetting("LogFileEncoding",1)#")> |
| 268 | | |
| 269 | | <cffile action="append" |
| 270 | | addnewline="true" |
| 271 | | file="#getlogFullPath()#" |
| 272 | | output="#InitString#" |
| 273 | | charset="#getSetting("LogFileEncoding",1)#"> |
| 274 | | |
| 275 | | <cfcatch type="any"> |
| 276 | | <cfthrow type="Framework.plugins.logger.WritingFirstEntryException" message="An error occurred writing the first entry to the log file." detail="#cfcatch.Detail#<br>#cfcatch.message#"> |
| 277 | | </cfcatch> |
| 278 | | </cftry> |
| 279 | | |
| 280 | | </cfif> |
| 281 | | </cflock> |
| 282 | | </cffunction> |
| | 87 | <!------------------------------------------- PRIVATE -------------------------------------------> |
| 311 | | <!--- ************************************************************* ---> |
| 312 | | |
| 313 | | <cffunction name="getLogFileName" access="public" hint="Get the logfilename" output="false" returntype="string"> |
| 314 | | <cfreturn instance.logfilename > |
| 315 | | </cffunction> |
| 316 | | |
| 317 | | <!--- ************************************************************* ---> |
| 318 | | |
| 319 | | <cffunction name="setlogFullPath" access="public" hint="Set the logFullPath" output="false" returntype="void"> |
| 320 | | <!--- ************************************************************* ---> |
| 321 | | <cfargument name="logFullPath" type="string" required="yes" hint="The logFullPath to set"> |
| 322 | | <!--- ************************************************************* ---> |
| 323 | | <cfset instance.logFullPath = arguments.logFullPath> |
| 324 | | </cffunction> |
| 325 | | |
| 326 | | <!--- ************************************************************* ---> |
| 327 | | |
| 328 | | <cffunction name="getlogFullPath" access="public" hint="Get the logFullPath" output="false" returntype="string"> |
| 329 | | <cfreturn instance.logFullPath > |
| 330 | | </cffunction> |
| 331 | | |
| 332 | | <!--- ************************************************************* ---> |
| 333 | | |
| 334 | | <cffunction name="getvalidSeverities" access="public" hint="Get the validSeverities" output="false" returntype="string"> |
| 335 | | <cfreturn instance.validSeverities > |
| 336 | | </cffunction> |
| 337 | | |
| 338 | | <!--- ************************************************************* ---> |
| 339 | | |
| 340 | | <cffunction name="getlockName" access="public" output="false" returntype="string" hint="Get lockName"> |
| 341 | | <cfreturn instance.lockName/> |
| 342 | | </cffunction> |
| 343 | | |
| 344 | | <!--- ************************************************************* ---> |
| 345 | | |
| 346 | | <!------------------------------------------- PRIVATE -------------------------------------------> |
| 347 | | |
| 348 | | <!--- ************************************************************* ---> |
| 349 | | |
| 350 | | <cffunction name="formatLogEntry" access="private" hint="Format a log request into the specified entry format." output="false" returntype="string"> |
| 351 | | <!--- ************************************************************* ---> |
| 352 | | <cfargument name="Severity" type="string" required="yes" hint="error|warning|info"> |
| 353 | | <cfargument name="Message" type="string" required="yes" hint="The message to log."> |
| 354 | | <cfargument name="ExtraInfo" type="string" required="no" default="" hint="Extra information to append."> |
| 355 | | <!--- ************************************************************* ---> |
| 356 | | <cfscript> |
| 357 | | var LogEntry = ""; |
| 358 | | //Manipulate entries |
| 359 | | arguments.severity = trim(lcase(arguments.severity)); |
| 360 | | arguments.message = trim(arguments.message) & trim(arguments.extrainfo); |
| 361 | | arguments.message = replace(arguments.message,'"','""',"all"); |
| 362 | | arguments.message = replace(arguments.message,"#chr(13)##chr(10)#",' ',"all"); |
| 363 | | arguments.message = replace(arguments.message,chr(13),' ',"all"); |
| 364 | | LogEntry = '"#arguments.Severity#","logger-plugin","#dateformat(now(),"MM/DD/YYYY")#","#timeformat(now(),"HH:MM:SS")#",,"#arguments.message#"'; |
| 365 | | //return formatted entry |
| 366 | | return logEntry; |
| 367 | | </cfscript> |
| 368 | | </cffunction> |
| 369 | | |
| 370 | | <!--- ************************************************************* ---> |
| 371 | | |
| 372 | | <cffunction name="setupLogLocationVariables" access="private" hint="Setup the log location variables." output="false" returntype="void"> |
| 373 | | <!--- The Default Full log directory path ---> |
| 374 | | <cfset var DefaultLogDirectory = getSetting("ApplicationPath",1) & getSetting("OSFileSeparator",1) & getSetting("DefaultLogDirectory",1)> |
| 375 | | <!--- The absolute test Path ---> |
| 376 | | <cfset var absTestPath = getPlugin("Utilities").getAbsolutePath(getSetting("ColdboxLogsLocation"))> |
| 377 | | <!--- The local relative test path ---> |
| 378 | | <cfset var TestPath = getSetting("ApplicationPath",1) & getSetting("OSFileSeparator",1) & getSetting("ColdboxLogsLocation")> |
| 379 | | <!--- Test EstablishedLogLocationpath ---> |
| 380 | | <cfset var EstablishedLogLocationpath = ""> |
| 381 | | |
| 382 | | <!--- Test for no setting defined, but logging enabled. ---> |
| 383 | | <cfif getSetting("ColdboxLogsLocation") eq ""> |
| 384 | | <cfset createDefaultLogDirectory()> |
| 385 | | <cfset EstablishedLogLocationpath = DefaultLogDirectory> |
| 386 | | <!--- Test for local relative test path ---> |
| 387 | | <cfelseif directoryExists( TestPath )> |
| 388 | | <cfset EstablishedLogLocationpath = TestPath> |
| 389 | | <!--- Test for the absolute test path ---> |
| 390 | | <cfelseif not directoryExists(absTestPath)> |
| 391 | | <cfdirectory action="create" directory="#absTestPath#"> |
| 392 | | <cfset EstablishedLogLocationpath = absTestPath> |
| 393 | | </cfif> |
| 394 | | |
| 395 | | <!--- Finalize the path ---> |
| 396 | | <cfset EstablishedLogLocationpath = EstablishedLogLocationpath & getSetting("OSFileSeparator",1) & getLogFileName() & ".log"> |
| 397 | | |
| 398 | | <!--- Then set the complete log path and save. ---> |
| 399 | | <cfset setSetting("ExpandedColdboxLogsLocation", EstablishedLogLocationpath)> |
| 400 | | <cfset setlogFullPath(EstablishedLogLocationpath)> |
| 401 | | </cffunction> |
| 402 | | |
| 403 | | <!--- ************************************************************* ---> |
| 404 | | |
| 405 | | <cffunction name="createDefaultLogDirectory" access="private" hint="Creates the default log directory." output="false" returntype="void"> |
| 406 | | <cfset var DefaultLogDirectory = getSetting("ApplicationPath",1) & getSetting("OSFileSeparator",1) & getSetting("DefaultLogDirectory",1)> |
| 407 | | <!--- Check if the directory already exists ---> |
| 408 | | <cfif not directoryExists(DefaultLogDirectory)> |
| 409 | | <cfdirectory action="create" directory="#DefaultLogDirectory#"> |
| 410 | | </cfif> |
| 411 | | </cffunction> |
| 412 | | |
| 413 | | <!--- ************************************************************* ---> |
| 414 | | |
| 415 | | <cffunction name="checkRotation" access="private" hint="Checks the log file size. If greater than framework's settings, then zip and rotate." output="false" returntype="void"> |
| 416 | | <cfset var zipFileName = ""> |
| 417 | | <cfset var qArchivedLogs = ""> |
| 418 | | <cfset var ArchiveToDelete = ""> |
| 419 | | |
| 420 | | <!--- Verify FileSize ---> |
| 421 | | <cfif getPlugin("Utilities").FileSize(getlogFullPath()) gt (getSetting("LogFileMaxSize",1) * 1024)> |
| 422 | | <cftry> |
| 423 | | |
| 424 | | <!--- How Many Log Files Do we Have ---> |
| 425 | | <cfdirectory action="list" |
| 426 | | filter="#getLogFileName()#*.zip" |
| 427 | | name="qArchivedLogs" |
| 428 | | directory="#getDirectoryFromPath(getlogFullPath())#" |
| 429 | | sort="DATELASTMODIFIED" > |
| 430 | | |
| 431 | | <!--- Zip Log File ---> |
| 432 | | <cflock name="#getlockName()#" type="exclusive" timeout="120"> |
| 433 | | <!--- Should I remove log Files ---> |
| 434 | | <cfif qArchivedLogs.recordcount gte getSetting("LogFileMaxArchives",1)> |
| 435 | | <cfset ArchiveToDelete = qArchivedLogs.directory[1] & getSetting("OSFileSeparator",1) & qArchivedLogs.name[1] > |
| 436 | | <!--- Remove the oldest one ---> |
| 437 | | <cffile action="delete" file="#ArchiveToDelete#"> |
| 438 | | </cfif> |
| 439 | | <!--- Set the name of the archive ---> |
| 440 | | <cfset zipFileName = getDirectoryFromPath(getlogFullPath()) & getLogFileName() & "." & createUUID() & ".zip"> |
| 441 | | <!--- Zip it ---> |
| 442 | | <cfset getPlugin("zip").AddFiles(zipFileName,getlogFullPath(),"","",false,9,false )> |
| 443 | | </cflock> |
| 444 | | |
| 445 | | <!--- Clean & reinit Log File ---> |
| 446 | | <cfset removeLogFile(true)> |
| 447 | | |
| 448 | | <!--- Trap Any errors ---> |
| 449 | | <cfcatch type="any"> |
| 450 | | <cfset logEntry("error","Could not zip and rotate log files.","#cfcatch.Detail# #cfcatch.Message#")> |
| 451 | | </cfcatch> |
| 452 | | </cftry> |
| 453 | | </cfif> |
| 454 | | </cffunction> |
| 455 | | |
| 456 | | <!--- ************************************************************* ---> |
| 457 | | |