我有一个通用的Windows / WindowsPhone 8.1应用程序,我使用LoggingSession在我的应用程序运行时记录消息。
当发生未处理的异常时,我记录异常然后等待对LoggingSession.SaveToFileAsync的调用以将日志转储到文件中。下次我的应用程序启动时,我上传日志文件并在我的最后收到它。
我看到的问题是,有时我的日志文件以.etl.tmp结尾(通常文件大小为50 - 100 Kb),当我尝试打开它们时(使用跟踪器或Windows事件查看器)我没有看到任何日志。其他时候我打开通常大约200Kb的.etl.tmp文件,我看到一些日志条目。而有时候日志文件(通常在20Kb以下)正确地以.etl扩展名(没有.tmp)结束,并且所有记录的消息都在那里。
1)为什么LoggingSession.SaveToFileAsync有时会生成扩展名为.etl.tmp的文件?
2)有关如何解决此问题的任何建议?我需要捕获所有日志(甚至是未处理的异常),然后再将它们保存到文件中,以便我在应用程序的unhadnled异常事件处理程序中调用LoggingSession.SaveToFileAsync。我还需要我的日志记录解决方案才能提高性能,而不是太慢地减慢我的应用程序。
由于
这里是精简的示例代码:
public sealed partial class App : Application
{
.
.
.
public static ETWLogger Logger;
public App()
{
InitializeComponent();
Logger = new ETWLogger();
Suspending += OnSuspending;
UnhandledException += OnUnhandledExceptionAsync;
}
private async void OnUnhandledExceptionAsync(object sender, UnhandledExceptionEventArgs args)
{
await Logger.SaveToFileAsync();
}
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// Check to see if there are files in the Log folder. If so
// then upload them and then delete all files in the Log folder.
}
.
.
.
}
public class ETWLogger
{
private LoggingSession _session;
private LoggingChannel _channel;
private StorageFolder _logFolder;
.
.
.
public ETWLogger()
{
.
.
.
_session = new LoggingSession("DefaultSession");
_channel = new LoggingChannel("DefaultChannel");
_session.AddLoggingChannel(_channel);
_logFolder = StorageHelper.CreateSubFolder(ApplicationData.Current.LocalFolder, "LogFiles", CreationCollisionOption.OpenIfExists);
.
.
.
}
public async Task SaveToFileAsync()
{
if (_session == null) return;
var fileName = DateTime.Now.ToString("yyyyMMdd-HHmmssTzz", CultureInfo.InvariantCulture) + ".etl";
await _session.SaveToFileAsync(_logUploadFolder, fileName);
}
.
.
.
}
答案 0 :(得分:3)
我非常清楚这里发生了什么。您描述了Microsoft使用的常用技术,它可以防止文件损坏和数据丢失。它不是创建您要求的foo.etl文件,而是 first 创建具有不同名称的文件。喜欢foo.etl.tmp。只有在成功写入文件时,或者换句话说,异步方法实际完成时,它才会将文件从foo.etl.tmp重命名为foo.etl。
你现在有了一个很好的保证,你总是得到一个完整的写好"好"文件。没有腐败。如果您有一个具有相同名称的先前文件,那么它不会被损坏的半写文件替换。没有数据丢失。
当发生未处理的异常时,我记录异常,然后等待呼叫
"未处理的例外"是问题。只有当异常不足以阻止异步/等待管道继续工作时,才能完全写入您的日志文件。换句话说,你只能得到温和的"异常信息。坏的产生了半写的foo.etl.tmp文件,应用程序在完成之前就已经完成了。
如果您想了解“坏”"那么您无法在此使用await
。那些。 SaveToFileAsync()调用必须同步完成。