我打电话给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中找不到第二个调用。是TraceSource
还是DiagnosticMonitor
?
为了进一步缩小范围,有问题的异常实际上是异常的InnerException
:“XML文档中存在错误(72,-499)”。导致异常的XML包含无效的字符实体,例如
。可能是Exception消息包含一些这些字符实体而且TraceSource
无法记录它们吗?
编辑:我能够在我的开发环境中最终重现这一点,因此我能够在调试器中检查异常。不记录的异常是XmlException
:
'',十六进制值0x11,是无效字符。第72行,位置-499。
在引号之间是不可打印的字符 - 它在调试器中显示为黑色三角形。所以,这让我相信我的怀疑是正确的 - 某些记录机制不喜欢不可打印的字符。那么,哪一块?或者,更重要的是,因为看起来我需要在跟踪时开始清理所有字符串,我应该找哪些字符删除?
是否有一些内置函数可以清理字符串,删除不可打印的字符?
答案 0 :(得分:1)
有趣。看起来您需要对异常字符串进行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的引用才能实现此目的。
答案 1 :(得分:1)
The answer to another question帮助我找到了解决方案。为方便起见,我添加了几个扩展方法:
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());
}
我喜欢每次拨打MyEvtEnum
时不必将int
投射到TraceEvent
的额外好处,并且它会增加自然超载,所以这感觉就像双赢。
让我感到困扰的是我必须这样做。诊断系统的主要用途之一是记录异常。这样的诊断系统应该能够处理异常消息可能包含的任何字符串。 我也失去了换行符,这令人沮丧。 编辑:失去换行符是RemoveControlChars()
的副作用。我没有意识到\r
和\n
被包含为“控制字符”。我已将正则表达式更新为不替换\r
和\n
字符。
我不喜欢接受我自己的答案,所以如果你有替代解决方案或我的改进,请发布它,如果它更好,我会接受它。