derroman
derroman

Reputation: 309

How could I get a new line in custom ColdFusion log files?

I've build a ColdFusion custom tag to log error messages and other strings, whenever I need this while developing.

My custom tag is written in cfscript. I try to log everything I can get. Therefore I would like to log a new line whenever I append a new string to "logMessage".

I've tried to include a variable

crlf = chr(10) & chr(13);

but this doesn't work. I think writeLog (and corresponding cflog) are not supposed to add new lines?

That's the reason I've tried to use a workaround (using writeLog() whenever a pipe appears), but that produces a lot of overhead, because there is such a lot of meta data evertytime I run writeLog().

Here's my script. The first lines evaluate given attributes(like "logType" and cfcatch object) and append the values, if defined, to "logMessage".

Please take a look down to the last lines containing the for loop.

<cfscript>
logMessageDelimiter="*******************************************************";
logMessage = "";
fileName = application.standard_log_path & application.server_name & "_standardLog";
logType = "information";
crlf = chr(10) & chr(13);

if(isDefined("attributes")){    //any attribute is given

    if(isDefined("attributes.text")){ //a custom text is given
        logMessage &= "LogMessage: " & attributes.text & " |" ;
    }

    if(isDefined("attributes.file")){   //output filename
        fileName = application.standard_log_path & application.server_name & "_" & attributes.file;
    }

    if(isDefined("attributes.logType")){ //a loglevel type
        switch(attributes.logType){
            case "i":
                logType = "information";
                break;
            case "w":
                logType = "warning";
                break;
            case "e":
                logType = "error";
                break;
            case "f":
                logType = "fatal";
                break;
            default:
                logType = "information";
        }
    }

    if(isDefined("attributes.catch")){ //catch object is defined
        logMessage &= "CFCATCH defined: " & " | ";

        if(isDefined("attributes.catch.detail"))
                logMessage &= "detail: "  & attributes.catch.detail & " | ";
        if(isDefined("attributes.catch.ErrorCode"))
                logMessage &= "ErrorCode: "  & attributes.catch.ErrorCode & " | ";
        if(isDefined("attributes.catch.ErrNumber"))
                logMessage &= "ErrNumber: "  & attributes.catch.ErrNumber & " | ";
        if(isDefined("attributes.catch.ExtendedInfo"))
                logMessage &= "QueryError: "  & attributes.catch.ExtendedInfo & " | ";
        if(isDefined("attributes.catch.message"))
                logMessage &= "message: "  & attributes.catch.message & " | ";
        if(isDefined("attributes.catch.RootCause"))
                logMessage &= "RootCause: "  & attributes.catch.RootCause & " | ";
        if(isDefined("attributes.catch.TagContext"))
        {
            for(i=1; i LTE ArrayLen(attributes.catch.TagContext); i=i+1)
            {
                logMessage &= "TagContext["& i &"] Column: " & attributes.catch.TagContext[i]["Column"] & " | ";
                logMessage &= "TagContext["& i &"] ID: " & attributes.catch.TagContext[i]["ID"] & " | ";
                logMessage &= "TagContext["& i &"] Line: " & attributes.catch.TagContext[i]["Line"] & " | ";
                logMessage &= "TagContext["& i &"] RawTrace: " & attributes.catch.TagContext[i]["Raw_Trace"] & " | ";
                logMessage &= "TagContext["& i &"] Template: " & attributes.catch.TagContext[i]["Template"] & " | ";
                logMessage &= "TagContext["& i &"] Type: " & attributes.catch.TagContext[i]["Type"] & " | ";
            }
        }

        if(isDefined("attributes.catch.Type"))
                logMessage &= "Type: "  & attributes.catch.Type & " | ";        
        if(isDefined("attributes.catch.NativeErrorCode"))
                logMessage &= "NativeErrorCode: "  & attributes.catch.NativeErrorCode & " | ";
        if(isDefined("attributes.catch.SQLState"))
                logMessage &= "SQLState: "  & attributes.catch.SQLState & " | ";
        if(isDefined("attributes.catch.SQL"))
                logMessage &= "SQL: "  & attributes.catch.SQL & " | ";
        if(isDefined("attributes.catch.QueryError"))
                logMessage &= "QueryError: "  & attributes.catch.QueryError & " | ";        
        if(isDefined("attributes.catch.Where"))
                logMessage &= "Where: "  & attributes.catch.Where & " | ";
        if(isDefined("attributes.catch.ErrNumber"))
                logMessage &= "ErrNumber: "  & attributes.catch.ErrNumber & " | ";          
        if(isDefined("attributes.catch.MissingFileName"))
                logMessage &= "MissingFileName: "  & attributes.catch.MissingFileName & " | ";
        if(isDefined("attributes.catch.MissingFileName"))
                logMessage &= "MissingFileName: "  & attributes.catch.MissingFileName & " | ";
        if(isDefined("attributes.catch.LockName"))
                logMessage &= "LockName: "  & attributes.catch.LockName & " | ";
        if(isDefined("attributes.catch.LockOperation"))
                logMessage &= "LockOperation: "  & attributes.catch.LockOperation & " | ";
        if(isDefined("attributes.catch.ExtendedInfo"))
                logMessage &= "ExtendedInfo: "  & attributes.catch.ExtendedInfo & " | ";
    }
}
splittedText = listToArray(logMessage,'|');
for(i=1; i LTE ArrayLen(splittedText); i=i+1)
{
    //I really need a better solution than this loop... 
    writeLog(splittedText[i],logType,true,fileName);
}
writeLog(logMessageDelimiter,logType,true,fileName);

I use my custom tag like this:

<cftry>
  ...some buggy code
<cfcatch>
  <customTagName text="Hey, you've got an error!" file="myLogFile" type="e" catch="#cfcatch#">
</cfcatch>
</cftry>

in the logs I'll get the following output (truncated):

"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS","LogMessage: Hey, you've got an error!"
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS","CFCATCH defined:  "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," detail:  "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," ErrorCode:  "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," ErrNumber: 0 "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," QueryError:  "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," message: Errormessage from CF telling me my errors "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," TagContext[1] Column: 0 "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," TagContext[1] ID: CF_CFPAGE "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," TagContext[1] Line: 183 "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," TagContext[1] RawTrace:       at cffileecfm1278323672._factor2(/the/path/to/my/file.cfm:183) "
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," TagContext[1] Template: /the/path/to/my/file.cfm"
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS"," TagContext[1] Type: CFML "
...
"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS","*******************************************************"

So would you do? Is there a way to get a new line, without executing writeLog() over and over again.

I would like to see a result like this:

"Information","ajp-bio-8013-exec-37118","02/11/13","14:26:09","SYS_MYSYS","LogMessage: Hey, you've got an error!"
    "CFCATCH defined:  "
    " detail:  "
    " ErrorCode:  "
    " ErrNumber: 0 "
    " QueryError:  "
    " message: Errormessage from CF telling me my errors "
    " TagContext[1] Column: 0 "
    " TagContext[1] ID: CF_CFPAGE "
    " TagContext[1] Line: 183 "
    " TagContext[1] RawTrace:       at cffileecfm1278323672._factor2(/the/path/to/my/file.cfm:183) "
    " TagContext[1] Template: /the/path/to/my/file.cfm"
    " TagContext[1] Type: CFML "
    ...
    "*******************************************************"

I could use methods to write into a file, but I think that's not the best way either, isn't it? In addition: I can't write to standard log folder (e.g. /path/to/coldfusion/instancename/logs/myLogFolder) of ColdFusion from within my application?!

Is there any way to get some structure to my log files? Do you have an idea?

Upvotes: 2

Views: 1281

Answers (1)

Adam Cameron
Adam Cameron

Reputation: 29870

No. I just verified that CF replaces CRLF characters with spaces. And that's that. I am guessing it does this so that the log parser can ass-u-me that a CRLF denotes the end of a log entry, without having to worry about it being part of the log message. This is a bit lazy of CF, IMO. Railo does not do this, interestingly.

The best you can do is to stick some other ASCII character (I just tested chr(30) - RECORD SEPARATOR) instead, and write a log viewer which swaps that out with a CRLF. This is not a very good suggestion, but if it's important to you, it's an option.

Upvotes: 3

Related Questions