如何在自定义 ColdFusion 日志文件中获得新行?

Posted

技术标签:

【中文标题】如何在自定义 ColdFusion 日志文件中获得新行?【英文标题】:How could I get a new line in custom ColdFusion log files? 【发布时间】:2013-01-26 15:13:12 【问题描述】:

我已经构建了一个 ColdFusion 自定义标签来记录错误消息和其他字符串,只要我在开发过程中需要它。

我的自定义标签是用 cfscript 编写的。我试着记录我能得到的一切。因此,每当我将新字符串附加到“logMessage”时,我都想记录一个新行。

我试图包含一个变量

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

但这不起作用。我认为 writeLog(和相应的 cflog)不应该添加新行?

这就是我尝试使用解决方法的原因(每当出现管道时使用 writeLog()),但这会产生大量开销,因为每次运行 writeLog() 时都会产生大量元数据。

这是我的脚本。第一行评估给定属性(如“logType”和 cfcatch 对象)并将值(如果已定义)附加到“logMessage”。

请查看包含 for 循环的最后几行。

<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);

我像这样使用我的自定义标签:

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

在日志中我会得到以下输出(截断):

"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","*******************************************************"

那你会吗?有没有办法获得一个新行,而无需一遍又一遍地执行 writeLog()。

我希望看到这样的结果:

"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 "
    ...
    "*******************************************************"

我可以使用方法写入文件,但我认为这也不是最好的方法,不是吗?另外:我无法从我的应用程序中写入 ColdFusion 的标准日志文件夹(例如 /path/to/coldfusion/instancename/logs/myLogFolder)?!

有什么方法可以让我的日志文件有一些结构吗?你有什么想法吗?

【问题讨论】:

仅供参考,CRLF 是 Chr(13) &amp; Chr(10); 而不是相反 为什么觉得cflog和writelog不加新行? 我很确定 CFlog 和 WriteLog 会转义或忽略换行符。这通常是您想要的,因为每个条目只有一行。由于您已经通过单个标签汇集日志记录,您可能希望使用 File API 以您想要的格式直接写入文件 如果您真的想要对输出进行这种级别的控制,也许可以使用 cffile action="write" 或 fileWriteLine 来构建您自己的日志记录 CFC? 我认为文件 API 是一种可能性,但我只是想找到一种方法来分别使用 cflog 和 writeLog()。不过还是谢谢。 【参考方案1】:

没有。我刚刚验证了 CF 用空格替换了 CRLF 字符。就是这样。我猜它这样做是为了让日志解析器可以告诉我 CRLF 表示日志条目的结束,而不必担心它是日志消息的一部分。这有点懒惰的CF,IMO。有趣的是,Railo 没有这样做。

您可以做的最好的事情是粘贴一些其他 ASCII 字符(我刚刚测试了 chr(30) - RECORD SEPARATOR),然后编写一个日志查看器,将其与 CRLF 交换出来。这不是一个很好的建议,但如果它对你很重要,它是一个选项。

【讨论】:

我为此提出了一个错误:bugbase.adobe.com/index.cfm?event=bug&id=3498448 感谢您确认我的假设并感谢您提出错误。我会留意的。

以上是关于如何在自定义 ColdFusion 日志文件中获得新行?的主要内容,如果未能解决你的问题,请参考以下文章

Coldfusion的createObject()函数如何搜索组件?

如何使用Coldfusion fileExist检查Amazon S3上是否存在文件?

MobileFirst 客户端日志记录以在自定义位置写入日志

包含文件中的 ColdFusion 用户定义函数不可用

如何在自定义 ListView 中获取 EditText 的所有值

Google Cloud Platform Vertex AI 日志未显示在自定义作业中