-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAsyncFileAppender.cs
More file actions
131 lines (119 loc) · 4.29 KB
/
AsyncFileAppender.cs
File metadata and controls
131 lines (119 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using log4net;
using log4net.Appender;
using log4net.Core;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/// <summary>
/// <logger name="position">
/// <level value="DEBUG" />
/// <appender-ref ref="TESTLogger" />
/// </logger>
/// <appender name="TESTLogger" type="namespace.AsyncFileAppender">
/// <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
/// <file value="Log\position.txt"/>
/// <appendToFile value="true"/>
/// <rollingStyle value="Date"/>
/// <datePattern value="yyyyMMdd"/>
/// <maxSizeRollBackups value="10"/>
/// <layout type="log4net.Layout.PatternLayout">
/// <conversionPattern value="%d{MM.dd.yyyy HH:mm:ss.fff} [%-5level] %logger // %message%newline"/>
/// </layout>
/// <filter type="log4net.Filter.LevelRangeFilter">
/// <levelMin value="ALL"/>
/// <acceptOnMatch value="true"/>
/// </filter>
/// <filter type="log4net.Filter.DenyAllFilter"/>
/// </appender>
/// </summary>
public class AsyncFileAppender : RollingFileAppender
{
const int RUNNING = 1;
const int NOT_RUNNING = 0;
static int runningState = 0;
static readonly object syncLock = new object();
static ConcurrentBag<AsyncFileAppender> afAppenders = new ConcurrentBag<AsyncFileAppender>();
//static System.Collections.Queue logQueue = System.Collections.Queue.Synchronized(new System.Collections.Queue(1000, 1));
static System.Threading.AutoResetEvent mAutoResetEvent = new System.Threading.AutoResetEvent(true);
static int waitTime = 5 * 1000;
object lockObject = new object();
List<LoggingEvent> loggingEvents = new List<LoggingEvent>();
/// <summary>
/// Thread wait time (ms)
/// </summary>
public int WaitTime
{
get { return waitTime; }
set
{
if (value > 0)
{
waitTime = value;
}
}
}
public AsyncFileAppender()
: base()
{
if (runningState == NOT_RUNNING) { processQueue(); }
afAppenders.Add(this);
}
protected override void Append(log4net.Core.LoggingEvent loggingEvent)
{
if (runningState == NOT_RUNNING) { return; }
lock (this.lockObject)
{
this.loggingEvents.Add(loggingEvent);//.DoAppend(tuple.Item2);
}
}
static void processQueue()
{
//if (running == 1) { return; } System.Threading.Interlocked.Exchange(ref running, 1); // prevent double
if (System.Threading.Interlocked.Exchange(ref runningState, RUNNING) == RUNNING) { return; } // prevent double
new System.Threading.Thread(() =>
{
try
{
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Lowest;
System.Threading.Thread.Sleep(300); // wait for first run delay
while (runningState == RUNNING)
{
writeLogs();
mAutoResetEvent.WaitOne(waitTime);
}
}
catch (System.Threading.ThreadInterruptedException ex)
{
}
catch (System.Threading.ThreadAbortException ex)
{
}
}).Start();
}
static void writeLogs()
{
foreach (var appKV in afAppenders)
{
if (appKV.loggingEvents.Count > 0)
{
lock (appKV.lockObject)
{
appKV.AddToBaseAppender(appKV.loggingEvents.ToArray());
appKV.loggingEvents.Clear();
}
}
}
}
void AddToBaseAppender(LoggingEvent[] e)
{
base.Append(e);
}
protected override void OnClose()
{
mAutoResetEvent.Set();
runningState = 0;// false;
base.OnClose();
}
}