多个TraceSource实例写入单个FileLogTraceListener

时间:2014-03-25 15:41:24

标签: c# .net multithreading logging system.diagnostics

我正在探索将基于TraceSource的日志记录添加到我的ASP.NET应用程序中。我需要有能力为不同的代码组件选择性地控制SourceLevels,因此需要多个源。所有TraceSource实例都将写入单个FileLogTraceListener派生的侦听器。

此策略是否可以在多线程环境中创建性能/并发访问问题? 从MSDN描述中,TraceSource和FileLogTraceListener似乎都是线程安全的。有没有人有经验表明不是吗?

在这种情况下,首先在app.config / web.config中通过<sharedListers>添加侦听器,而不是像我在下面的代码中那样以编程方式添加侦听器吗?

我使用了这个完美运行的测试代码 - 写出了预期的日志条目数。在生产中部署此策略之前,我只想获得一些指导。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.VisualBasic.Logging;

namespace SourcesListeners
{
    class Program
    {
        [STAThread]
        static void Main()
        {
            const string baseFileName = @"test-log";
            var threads = 10*Environment.ProcessorCount;
            const int iterationsPerThread = 4000;

            var listener = new DailyRollingFileListener(@".\", baseFileName);
            {
                Parallel.For(0, threads, i =>
                {
                    var source = new TraceSource(string.Format("source-{0}", i), SourceLevels.All);
                    source.Listeners.Clear();
                    source.Listeners.Add(listener);
                    source.TraceEvent(TraceEventType.Information, 0, "Created");

                    for (var k = 0; k < iterationsPerThread; ++k)
                    {
                        source.TraceEvent(TraceEventType.Information, 0, "thread: {0}, iteration: {1}", i, k);
                    }
                });
            }
        }

        class DailyRollingFileListener : FileLogTraceListener
        {
            public DailyRollingFileListener(
                string customLocation, string baseFileName,
                bool autoFlush = true)
            {
                CustomLocation = customLocation;
                BaseFileName = baseFileName;
                AutoFlush = autoFlush;
                LogFileCreationSchedule = LogFileCreationScheduleOption.Daily;
                Append = false;
                MaxFileSize = 40*1024*1024;
            }

            public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
            {
                var entry = string.Format("{0:yyyy-MM-dd hh:mm:ss.fff}Z {1,4} {2,-5} {3} {4}",
                    eventCache.DateTime,
                    eventCache.ThreadId,
                    GetSeverity(eventType),
                    source,
                    message);
                base.WriteLine(entry);
            }

            public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
            {
                var message = args != null ? string.Format(format, args) : format;
                if (eventCache != null)
                {
                    TraceEvent(eventCache, source ?? string.Empty, eventType, id, message);
                }
                else
                {
                    base.WriteLine(string.Format("{0} {1} {2}", GetSeverity(eventType), source ?? string.Empty, message));
                }
            }

            private static string GetSeverity(TraceEventType eventType)
            {
                string value;
                return SeverityLevel.TryGetValue(eventType, out value) ? value : eventType.ToString().ToUpper();
            }

            private static readonly Dictionary<TraceEventType, string> SeverityLevel =
                new Dictionary<TraceEventType, string>
            {
                {TraceEventType.Critical, "FATAL"},
                {TraceEventType.Error, "ERROR"},
                {TraceEventType.Warning, "WARN "},
                {TraceEventType.Information, ""},
                {TraceEventType.Verbose, "DEBUG"},
                {TraceEventType.Start, "ENTRY"},
                {TraceEventType.Stop, "EXIT "},
            };
        }
    }
}

2 个答案:

答案 0 :(得分:1)

如果现有文件被锁定,FileLogTraceListener将写入一个全新的文件。因此,您可以获取日志文件的集合,这可能是您想要的,也可能不是。

数据库对并发访问更具弹性,但您可能会遇到死锁,尤其是在有事务发生时(每个人都试图写入同一个表)

答案 1 :(得分:0)

为避免创建多个跟踪文件,您可以在刷新后释放侦听器以释放跟踪文件。