当异常消息包含不可打印字符时,TraceSource.TraceEvent()无法记录日志

本文关键字:TraceEvent TraceSource 记录日志 消息 异常 包含不 字符 打印 | 更新日期: 2023-09-27 18:10:04

我有一个对TraceSource.TraceEvent()的调用,有时不写入Azure诊断日志。

public class WorkerRole : RoleEntryPoint
{
    private TraceSource trace = new TraceSource(
        "ImportService", SourceLevels.Information);
    public override void Run()
    {
        ...
        try
        {
            ...
        }
        catch (Exception ex)
        {
            bool hasMsg = !string.IsNullOrEmpty(ex.Message);
            trace.TraceEvent(TraceEventType.Error, 0,
                "ex has message: " + hasMsg.ToString());   // this gets logged
            trace.TraceEvent(TraceEventType.Error, 0,
                "Inner exception message: " + ex.Message); // this does not
        }
    }
}

在某些情况下,由于无法读取Exception消息,我无法判断是哪种情况,第二个调用在WADLogsTable中找不到。是否有某些字符是TraceSourceDiagnosticMonitor不允许的?

为了进一步缩小范围,所讨论的异常实际上是异常的InnerException:"XML文档中有一个错误(72,-499)"。导致异常的XML包含无效的字符实体,例如。可能是异常消息包含这些字符实体中的一些,TraceSource未能记录它们吗?

编辑:我终于能够在我的开发环境中再现这一点,所以我能够在调试器中检查异常。不记录日志的异常是XmlException:

"为无效字符,十六进制值为0x11。第72行,位置-499。

在引号之间是不可打印的字符——它在调试器中显示为黑色三角形。所以,这让我相信我的怀疑是正确的——日志机制的某些部分不喜欢不可打印的字符。那么,是哪一块呢?或者,更重要的是,因为看起来我需要在跟踪时开始对所有字符串进行消毒,我应该寻找哪些字符来删除?

是否有一些内置的函数将清理字符串,删除不可打印的字符?

当异常消息包含不可打印字符时,TraceSource.TraceEvent()无法记录日志

有意思。看起来您需要对异常字符串进行HTML编码。这会将引号转换为例如",将ASCII非打印字符转换为或类似的字符。

:

    trace.TraceEvent(TraceEventType.Error, 0,
        "ex has message: " + HttpUtility.HtmlEncode(hasMsg.ToString()));   
    trace.TraceEvent(TraceEventType.Error, 0,
        "Inner exception message: " + HttpUtility.HtmlEncode(ex.Message)); 

应该可以正常工作。

令人沮丧的是,HttpUtility在System中。Web,您需要添加对System.Web.dll的引用以使其运行

另一个问题的答案帮助我找到了解决方案。为了方便起见,我添加了两个扩展方法:

public static string RemoveControlChars(this string s)
{
    return Regex.Replace(s, @"(?!['r'n])'p{Cc}", "");
}
public static void TraceEvent(this TraceSource trace, 
    TraceEventType eventType, MyEvtEnum eventId, string message)
{
    trace.TraceEvent(eventType, (int)eventId, message.RemoveControlChars());
}

我喜欢每次调用TraceEvent时不必将MyEvtEnum转换为int的额外好处,它增加了自然的过载,所以这感觉像是双赢。

我不得不做这件事,这让我很烦恼。诊断系统的主要用途之一是记录异常。这样的诊断系统应该能够处理异常消息中可能包含的任何字符串。我也失去了换行符,这是令人沮丧的。编辑:丢失换行符是RemoveControlChars()的副作用。我没有意识到'r'n是作为"控制字符"包含的。我已经更新了我的正则表达式,不替换'r'n字符。

我不喜欢接受我自己的答案,所以如果你有一个替代的解决方案或对我的改进,请把它贴出来,如果它更好,我会接受的。