c++ - 如何强制执行唯一的错误消息
问题描述
我一直在尝试找到一种方法来在我们的应用程序中强制执行唯一的错误消息。也就是说,我想确切地知道是哪一行代码产生了错误,所以当用户联系支持时,我们可以从记录的消息中知道错误的来源。
我发现这个问题给了我一种机制(使用 guid 来强制唯一性),但还有一个问题: 如何防止复制/粘贴重复?- 具体来说,开发人员复制日志行本身:
Log(<guid>, errorMessage);
在这种情况下,guid 将被复制,并且不再用于识别产生错误的唯一行。
我有一个实际可行的想法是编写一个由我们的构建服务器运行的工具,该工具将解析错误消息 guid 的代码,保留一个列表,并在副本上失败构建。我想知道是否有更清洁的解决方案。
我考虑过的其他事情:
使用某种错误消息的中央列表有各种想法,但我还没有找到解决复制/粘贴问题的想法。
还有一些计划需要以某种方式保留手动列表。我不想追求这样的事情,因为它会造成列表和生产代码之间存在差异的可能性。
我也看到了使用堆栈跟踪的建议,但出于安全和性能原因,我有点犹豫。
解决方案
我不知道这是否真的是您要查找的内容,但您可以在日志消息中包含文件、方法、行号(和其他内容),而无需稍后在源代码中搜索的唯一编号如果你利用System.Diagnostics.StackTrace
类。这样,即使存在复制/粘贴违规,您仍然可以确切地知道调用的Log
来源。
这是一个简化的示例,它返回堆栈跟踪项的文件名、方法签名和行号。请注意,此代码查找调用“Log”方法的堆栈跟踪项并返回下一个。很快就会更清楚:
using System.Diagnostics; // Needed for the StackTrace class
private static string GetStackTraceInfo()
{
var stackTrace = new StackTrace(true).GetFrames();
// Find the item just after the call to teh 'Log' method:
var item = stackTrace?
.SkipWhile(st => !st.GetMethod().Name.Equals("Log"))
.Skip(1)
.FirstOrDefault();
return item == null
? string.Empty
: string.Format("{0} => {1}, line #{2}", Path.GetFileName(item.GetFileName()),
item.GetMethod(), item.GetFileLineNumber());
}
这Log
是强制添加到日志中的堆栈跟踪信息的方法(这是我们在上面的代码中搜索的方法名称):
private static void Log(int id, string message)
{
Console.WriteLine($"Error #{id}: {message} ({GetStackTraceInfo()})");
}
以及一个示例用法:
private static void Main()
{
DoSomething();
DoSomethingElse();
GetKeyFromUser("\nDone! Press any key to exit...");
}
private static void DoSomething()
{
Log(1000, "I copied/pasted this error message from somewhere!");
}
private static void DoSomethingElse()
{
Log(1000, "I copied/pasted this error message from somewhere!");
}
输出