我正在探索将基于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 "},
};
}
}
}
答案 0 :(得分:1)
如果现有文件被锁定,FileLogTraceListener将写入一个全新的文件。因此,您可以获取日志文件的集合,这可能是您想要的,也可能不是。
数据库对并发访问更具弹性,但您可能会遇到死锁,尤其是在有事务发生时(每个人都试图写入同一个表)
答案 1 :(得分:0)
为避免创建多个跟踪文件,您可以在刷新后释放侦听器以释放跟踪文件。