使用ETW和语义记录应用程序块的文件锁

时间:2013-09-30 14:04:48

标签: c# .net logging enterprise-library etw

我们创建了一个非常简单的ETW EventSource实现,它由语义记录应用程序块(通过RollingFlatFileLogs)使用。

基本设置如下:

[EventSource(Name = "My Applicaiton")]
public partial class MyEventSource : EventSource
{
    /// <summary>
    /// The log
    /// </summary>
    public static MyEventSource Log = new MyEventSource();

...

然后具有基本关键字,任务和操作码。

文件由以下类似的事件写入:

/// <summary>
    /// Application starting.
    /// </summary>
    [Event(100, Level = EventLevel.Verbose, Keywords = Keywords.Application, Task = Tasks.AppStart, Opcode = Opcodes.Start, Message = "Application Starting")]
    public void ApplicationStarting()
    {
        if (this.IsEnabled(EventLevel.Verbose, Keywords.Application))
        {
            this.WriteEvent(100);
        }
    }

我们使用此方法订阅:

var listener = Microsoft.Practices.EnterpriseLibrary.SemanticLogging.RollingFlatFileLog.CreateListener("C:\\ServiceRegistry\\services.log", 5120, null, Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Sinks.RollFileExistsBehavior.Increment, Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Sinks.RollInterval.None, null, 10, true);

        listener.EnableEvents(MyEventSource.Log, System.Diagnostics.Tracing.EventLevel.LogAlways);


        // Log some things
        MyEventSource.Log.ApplicationStarting();

然而,我们看到的问题是一些开发人员看到锁定停止执行的日志文件。显示了“文件正在使用且无法写入”的消息。

为什么会这样?即使日志记录异步运行,为什么它会结束进程?

我们怎样才能防止将来发生这种情况?有没有办法强化我们的日志记录实现,以便它可以滚动文件,如果有这样的错误?

谢谢!

编辑:我抓住了问题的堆栈跟踪:

 The process cannot access the file 'C:\ServiceRegistry\services.log' because it is               being used by another process.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
    at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)
    at Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Sinks.RollingFlatFileSink..ctor(String fileName, Int32 rollSizeKB, String timestampPattern, RollFileExistsBehavior rollFileExistsBehavior, RollInterval rollInterval, Int32 maxArchivedFiles, Boolean isAsync)
    at Microsoft.Practices.EnterpriseLibrary.SemanticLogging.RollingFlatFileLog.CreateListener(String fileName, Int32 rollSizeKB, String timestampPattern, RollFileExistsBehavior rollFileExistsBehavior, RollInterval rollInterval, IEventTextFormatter formatter, Int32 maxArchivedFiles, Boolean isAsync)

1 个答案:

答案 0 :(得分:0)

我在使用IISExpress进行本地开发时也遇到了同样的问题,我得到的是“进程无法访问文件'C:\ MyPath \ OurProductName.2016-01-05.log',因为它正在被另一个进程使用。“错误信息。如果我在Global.asax文件中的Application_Start中放置一个断点,我注意到它通过Application_Start运行两次。第二次是导致锁定问题的原因。我发现阻止这种情况的唯一方法是寻找我自己的唯一文件名(请参阅下面的代码)或在IISExpress中编码时关闭日志记录。

以下是检查唯一文件名的例程(每次在IISExpress中重新编译或运行应用程序时,您将获得多个文件):

private static string GetUniqueFileName(string directoryName)
{
   string baseFileName = string.Format("OurProductName.{0}",
      DateTime.Now.ToString("yyyy-MM-dd"));
   string currentFileName = Path.Combine(directoryName, 
      string.Format("{0}.log", baseFileName));
   int number = 1;
   while (System.IO.File.Exists(currentFileName))
   {
      currentFileName = Path.Combine(directoryName, 
         string.Format("{0}.{1}.log", baseFileName, number++));
    }

    return currentFileName;
}