mirror of https://github.com/winsw/winsw
Manually applied patch from comment #5 in
http://kenai.com/bugzilla/show_bug.cgi?id=4246pull/4/head
parent
f211481e77
commit
9118145a4b
|
@ -0,0 +1,319 @@
|
|||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace winsw
|
||||
{
|
||||
public interface EventLogger
|
||||
{
|
||||
void LogEvent(string message);
|
||||
void LogEvent(string message, EventLogEntryType type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for handling log.
|
||||
/// </summary>
|
||||
public abstract class LogHandler
|
||||
{
|
||||
private EventLogger eventLogger;
|
||||
private string baseLogFileName;
|
||||
|
||||
public LogHandler(string logDirectory, string baseName)
|
||||
{
|
||||
this.baseLogFileName = Path.Combine(logDirectory, baseName);
|
||||
}
|
||||
|
||||
public abstract void log(Stream outputStream, Stream errorStream);
|
||||
|
||||
public EventLogger EventLogger
|
||||
{
|
||||
set
|
||||
{
|
||||
this.eventLogger = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return this.eventLogger;
|
||||
}
|
||||
}
|
||||
|
||||
public string BaseLogFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.baseLogFileName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method to copy stuff from StreamReader to StreamWriter
|
||||
/// </summary>
|
||||
protected void CopyStream(Stream i, Stream o)
|
||||
{
|
||||
byte[] buf = new byte[1024];
|
||||
while (true)
|
||||
{
|
||||
int sz = i.Read(buf, 0, buf.Length);
|
||||
if (sz == 0) break;
|
||||
o.Write(buf, 0, sz);
|
||||
o.Flush();
|
||||
}
|
||||
i.Close();
|
||||
o.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File replacement.
|
||||
/// </summary>
|
||||
protected void CopyFile(string sourceFileName, string destFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(destFileName);
|
||||
File.Move(sourceFileName, destFileName);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
EventLogger.LogEvent("Failed to copy :" + sourceFileName + " to " + destFileName + " because " + e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SimpleLogAppender : LogHandler
|
||||
{
|
||||
|
||||
private FileMode fileMode;
|
||||
private string outputLogFileName;
|
||||
private string errorLogFileName;
|
||||
|
||||
public SimpleLogAppender(string logDirectory, string baseName, FileMode fileMode)
|
||||
: base(logDirectory, baseName)
|
||||
{
|
||||
this.fileMode = fileMode;
|
||||
this.outputLogFileName = BaseLogFileName + ".out.log";
|
||||
this.errorLogFileName = BaseLogFileName + ".err.log";
|
||||
}
|
||||
|
||||
public string OutputLogFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.outputLogFileName;
|
||||
}
|
||||
}
|
||||
|
||||
public string ErrorLogFileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.errorLogFileName;
|
||||
}
|
||||
}
|
||||
|
||||
public override void log(Stream outputStream, Stream errorStream)
|
||||
{
|
||||
new Thread(delegate() { CopyStream(outputStream, new FileStream(outputLogFileName, fileMode)); }).Start();
|
||||
new Thread(delegate() { CopyStream(errorStream, new FileStream(errorLogFileName, fileMode)); }).Start();
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultLogAppender : SimpleLogAppender
|
||||
{
|
||||
public DefaultLogAppender(string logDirectory, string baseName)
|
||||
: base(logDirectory, baseName, FileMode.Append)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ResetLogAppender : SimpleLogAppender
|
||||
{
|
||||
public ResetLogAppender(string logDirectory, string baseName)
|
||||
: base(logDirectory, baseName, FileMode.Create)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TimeBasedRollingLogAppender : LogHandler
|
||||
{
|
||||
|
||||
private string pattern;
|
||||
private int period;
|
||||
|
||||
public TimeBasedRollingLogAppender(string logDirectory, string baseName, string pattern, int period)
|
||||
: base(logDirectory, baseName)
|
||||
{
|
||||
this.pattern = pattern;
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
public override void log(Stream outputStream, Stream errorStream)
|
||||
{
|
||||
new Thread(delegate() { CopyStreamWithDateRotation(outputStream, ".out.log"); }).Start();
|
||||
new Thread(delegate() { CopyStreamWithDateRotation(errorStream, ".err.log"); }).Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Works like the CopyStream method but does a log rotation based on time.
|
||||
/// </summary>
|
||||
private void CopyStreamWithDateRotation(Stream data, string ext)
|
||||
{
|
||||
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(pattern, period);
|
||||
periodicRollingCalendar.init();
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
FileStream w = new FileStream(BaseLogFileName + "_" + periodicRollingCalendar.format + ext, FileMode.Create);
|
||||
while (true)
|
||||
{
|
||||
int len = data.Read(buf, 0, buf.Length);
|
||||
if (len == 0) break; // EOF
|
||||
|
||||
if (periodicRollingCalendar.shouldRoll)
|
||||
{// rotate at the line boundary
|
||||
int offset = 0;
|
||||
bool rolled = false;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (buf[i] == 0x0A)
|
||||
{// at the line boundary.
|
||||
// time to rotate.
|
||||
w.Write(buf, offset, i + 1);
|
||||
w.Close();
|
||||
offset = i + 1;
|
||||
|
||||
// create a new file.
|
||||
w = new FileStream(BaseLogFileName + "_" + periodicRollingCalendar.format + ext, FileMode.Create);
|
||||
rolled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rolled)
|
||||
{// we didn't roll - most likely as we didnt find a line boundary, so we should log what we read and roll anyway.
|
||||
w.Write(buf, 0, len);
|
||||
w.Close();
|
||||
w = new FileStream(BaseLogFileName + "_" + periodicRollingCalendar.format + ext, FileMode.Create);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{// typical case. write the whole thing into the current file
|
||||
w.Write(buf, 0, len);
|
||||
}
|
||||
|
||||
w.Flush();
|
||||
}
|
||||
data.Close();
|
||||
w.Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SizeBasedRollingLogAppender : LogHandler
|
||||
{
|
||||
public static int BYTES_PER_KB = 1024;
|
||||
public static int BYTES_PER_MB = 1024 * BYTES_PER_KB;
|
||||
public static int DEFAULT_SIZE_THRESHOLD = 10 * BYTES_PER_MB; // rotate every 10MB.
|
||||
public static int DEFAULT_FILES_TO_KEEP = 8;
|
||||
|
||||
private int sizeThreshold;
|
||||
private int filesToKeep;
|
||||
|
||||
public SizeBasedRollingLogAppender(string logDirectory, string baseName, int sizeThreshold, int filesToKeep)
|
||||
: base(logDirectory, baseName)
|
||||
{
|
||||
this.sizeThreshold = sizeThreshold;
|
||||
this.filesToKeep = filesToKeep;
|
||||
}
|
||||
|
||||
public SizeBasedRollingLogAppender(string logDirectory, string baseName)
|
||||
: this(logDirectory, baseName, DEFAULT_SIZE_THRESHOLD, DEFAULT_FILES_TO_KEEP) { }
|
||||
|
||||
public override void log(Stream outputStream, Stream errorStream)
|
||||
{
|
||||
new Thread(delegate() { CopyStreamWithRotation(outputStream, ".out.log"); }).Start();
|
||||
new Thread(delegate() { CopyStreamWithRotation(errorStream, ".err.log"); }).Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Works like the CopyStream method but does a log rotation.
|
||||
/// </summary>
|
||||
private void CopyStreamWithRotation(Stream data, string ext)
|
||||
{
|
||||
byte[] buf = new byte[1024];
|
||||
FileStream w = new FileStream(BaseLogFileName + ext, FileMode.Append);
|
||||
long sz = new FileInfo(BaseLogFileName + ext).Length;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int len = data.Read(buf, 0, buf.Length);
|
||||
if (len == 0) break; // EOF
|
||||
if (sz + len < sizeThreshold)
|
||||
{// typical case. write the whole thing into the current file
|
||||
w.Write(buf, 0, len);
|
||||
sz += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rotate at the line boundary
|
||||
int s = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (buf[i] != 0x0A) continue;
|
||||
if (sz + i < sizeThreshold) continue;
|
||||
|
||||
// at the line boundary and exceeded the rotation unit.
|
||||
// time to rotate.
|
||||
w.Write(buf, s, i + 1);
|
||||
w.Close();
|
||||
s = i + 1;
|
||||
|
||||
try
|
||||
{
|
||||
for (int j = filesToKeep; j >= 1; j--)
|
||||
{
|
||||
string dst = BaseLogFileName + "." + (j - 1) + ext;
|
||||
string src = BaseLogFileName + "." + (j - 2) + ext;
|
||||
if (File.Exists(dst))
|
||||
File.Delete(dst);
|
||||
if (File.Exists(src))
|
||||
File.Move(src, dst);
|
||||
}
|
||||
File.Move(BaseLogFileName + ext, BaseLogFileName + ".0" + ext);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
EventLogger.LogEvent("Failed to rotate log: " + e.Message);
|
||||
}
|
||||
|
||||
// even if the log rotation fails, create a new one, or else
|
||||
// we'll infinitely try to rotate.
|
||||
w = new FileStream(BaseLogFileName + ext, FileMode.Create);
|
||||
sz = new FileInfo(BaseLogFileName + ext).Length;
|
||||
}
|
||||
}
|
||||
|
||||
w.Flush();
|
||||
}
|
||||
data.Close();
|
||||
w.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotate log when a service is newly started.
|
||||
/// </summary>
|
||||
public class RollingLogAppender : SimpleLogAppender
|
||||
{
|
||||
public RollingLogAppender(string logDirectory, string baseName)
|
||||
: base(logDirectory, baseName, FileMode.Append)
|
||||
{
|
||||
}
|
||||
|
||||
public override void log(Stream outputStream, Stream errorStream)
|
||||
{
|
||||
CopyFile(OutputLogFileName, OutputLogFileName + ".old");
|
||||
CopyFile(ErrorLogFileName, ErrorLogFileName + ".old");
|
||||
base.log(outputStream, errorStream);
|
||||
}
|
||||
}
|
||||
}
|
118
Main.cs
118
Main.cs
|
@ -37,7 +37,7 @@ namespace winsw
|
|||
SERVICE_PAUSED = 0x00000007,
|
||||
}
|
||||
|
||||
public class WrapperService : ServiceBase
|
||||
public class WrapperService : ServiceBase, EventLogger
|
||||
{
|
||||
[DllImport("ADVAPI32.DLL")]
|
||||
private static extern bool SetServiceStatus(IntPtr hServiceStatus, ref SERVICE_STATUS lpServiceStatus);
|
||||
|
@ -69,89 +69,6 @@ namespace winsw
|
|||
this.systemShuttingdown = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy stuff from StreamReader to StreamWriter
|
||||
/// </summary>
|
||||
private void CopyStream(Stream i, Stream o)
|
||||
{
|
||||
byte[] buf = new byte[1024];
|
||||
while (true)
|
||||
{
|
||||
int sz = i.Read(buf, 0, buf.Length);
|
||||
if (sz == 0) break;
|
||||
o.Write(buf, 0, sz);
|
||||
o.Flush();
|
||||
}
|
||||
i.Close();
|
||||
o.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Works like the CopyStream method but does a log rotation.
|
||||
/// </summary>
|
||||
private void CopyStreamWithRotation(Stream data, string baseName, string ext)
|
||||
{
|
||||
int THRESHOLD = 10 * 1024 * 1024; // rotate every 10MB. should be made configurable.
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
FileStream w = new FileStream(baseName + ext, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
|
||||
long sz = new FileInfo(baseName + ext).Length;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int len = data.Read(buf, 0, buf.Length);
|
||||
if (len == 0) break; // EOF
|
||||
if (sz + len < THRESHOLD)
|
||||
{// typical case. write the whole thing into the current file
|
||||
w.Write(buf, 0, len);
|
||||
sz += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rotate at the line boundary
|
||||
int s = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (buf[i] != 0x0A) continue;
|
||||
if (sz + i < THRESHOLD) continue;
|
||||
|
||||
// at the line boundary and exceeded the rotation unit.
|
||||
// time to rotate.
|
||||
w.Write(buf, s, i + 1);
|
||||
w.Close();
|
||||
s = i + 1;
|
||||
|
||||
try
|
||||
{
|
||||
for (int j = 8; j >= 0; j--)
|
||||
{
|
||||
string dst = baseName + "." + (j + 1) + ext;
|
||||
string src = baseName + "." + (j + 0) + ext;
|
||||
if (File.Exists(dst))
|
||||
File.Delete(dst);
|
||||
if (File.Exists(src))
|
||||
File.Move(src, dst);
|
||||
}
|
||||
File.Move(baseName + ext, baseName + ".0" + ext);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LogEvent("Failed to rotate log: " + e.Message);
|
||||
}
|
||||
|
||||
// even if the log rotation fails, create a new one, or else
|
||||
// we'll infinitely try to rotate.
|
||||
w = new FileStream(baseName + ext, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
sz = new FileInfo(baseName + ext).Length;
|
||||
}
|
||||
}
|
||||
|
||||
w.Flush();
|
||||
}
|
||||
data.Close();
|
||||
w.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the file copy instructions, so that we can replace files that are always in use while
|
||||
/// the service runs.
|
||||
|
@ -235,35 +152,12 @@ namespace winsw
|
|||
Directory.CreateDirectory(logDirectory);
|
||||
}
|
||||
|
||||
string baseName = descriptor.BaseName;
|
||||
string errorLogfilename = Path.Combine(logDirectory, baseName + ".err.log");
|
||||
string outputLogfilename = Path.Combine(logDirectory, baseName + ".out.log");
|
||||
|
||||
if (descriptor.Logmode == "rotate")
|
||||
{
|
||||
string logName = Path.Combine(logDirectory, baseName);
|
||||
StartThread(delegate() { CopyStreamWithRotation(process.StandardOutput.BaseStream, logName, ".out.log"); });
|
||||
StartThread(delegate() { CopyStreamWithRotation(process.StandardError.BaseStream, logName, ".err.log"); });
|
||||
return;
|
||||
}
|
||||
|
||||
FileMode fileMode = FileMode.Append;
|
||||
|
||||
if (descriptor.Logmode == "reset")
|
||||
{
|
||||
fileMode = FileMode.Create;
|
||||
}
|
||||
else if (descriptor.Logmode == "roll")
|
||||
{
|
||||
CopyFile(outputLogfilename, outputLogfilename + ".old");
|
||||
CopyFile(errorLogfilename, errorLogfilename + ".old");
|
||||
}
|
||||
|
||||
StartThread(delegate() { CopyStream(process.StandardOutput.BaseStream, new FileStream(outputLogfilename, fileMode, FileAccess.Write, FileShare.ReadWrite)); });
|
||||
StartThread(delegate() { CopyStream(process.StandardError.BaseStream, new FileStream(errorLogfilename, fileMode, FileAccess.Write, FileShare.ReadWrite)); });
|
||||
LogHandler logAppender = descriptor.LogHandler;
|
||||
logAppender.EventLogger = this;
|
||||
logAppender.log(process.StandardOutput.BaseStream, process.StandardError.BaseStream);
|
||||
}
|
||||
|
||||
private void LogEvent(String message)
|
||||
public void LogEvent(String message)
|
||||
{
|
||||
if (systemShuttingdown)
|
||||
{
|
||||
|
@ -275,7 +169,7 @@ namespace winsw
|
|||
}
|
||||
}
|
||||
|
||||
private void LogEvent(String message, EventLogEntryType type)
|
||||
public void LogEvent(String message, EventLogEntryType type)
|
||||
{
|
||||
if (systemShuttingdown)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace winsw
|
||||
{
|
||||
/**
|
||||
* This is largely borrowed from the logback Rolling Calendar.
|
||||
**/
|
||||
public class PeriodicRollingCalendar
|
||||
{
|
||||
private PeriodicityType _periodicityType;
|
||||
private string _format;
|
||||
private long _period;
|
||||
private DateTime _currentRoll;
|
||||
private DateTime _nextRoll;
|
||||
|
||||
public PeriodicRollingCalendar(string format, long period)
|
||||
{
|
||||
this._format = format;
|
||||
this._period = period;
|
||||
this._currentRoll = DateTime.Now;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
this._periodicityType = determinePeriodicityType();
|
||||
this._nextRoll = nextTriggeringTime(this._currentRoll);
|
||||
}
|
||||
|
||||
public enum PeriodicityType
|
||||
{
|
||||
ERRONEOUS, TOP_OF_MILLISECOND, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, TOP_OF_DAY
|
||||
}
|
||||
|
||||
private static PeriodicityType[] VALID_ORDERED_LIST = new PeriodicityType[] {
|
||||
PeriodicityType.TOP_OF_MILLISECOND, PeriodicityType.TOP_OF_SECOND, PeriodicityType.TOP_OF_MINUTE, PeriodicityType.TOP_OF_HOUR, PeriodicityType.TOP_OF_DAY
|
||||
};
|
||||
|
||||
private PeriodicityType determinePeriodicityType()
|
||||
{
|
||||
PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(_format, _period);
|
||||
DateTime epoch = new DateTime(1970, 1, 1);
|
||||
|
||||
foreach (PeriodicityType i in VALID_ORDERED_LIST)
|
||||
{
|
||||
string r0 = epoch.ToString(_format);
|
||||
periodicRollingCalendar.periodicityType = i;
|
||||
|
||||
DateTime next = periodicRollingCalendar.nextTriggeringTime(epoch);
|
||||
string r1 = next.ToString(_format);
|
||||
|
||||
if (r0 != null && r1 != null && !r0.Equals(r1))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return PeriodicityType.ERRONEOUS;
|
||||
}
|
||||
|
||||
private DateTime nextTriggeringTime(DateTime input)
|
||||
{
|
||||
DateTime output;
|
||||
switch (_periodicityType)
|
||||
{
|
||||
case PeriodicityType.TOP_OF_MILLISECOND:
|
||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond);
|
||||
output = output.AddMilliseconds(_period);
|
||||
return output;
|
||||
case PeriodicityType.TOP_OF_SECOND:
|
||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second);
|
||||
output = output.AddSeconds(_period);
|
||||
return output;
|
||||
case PeriodicityType.TOP_OF_MINUTE:
|
||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0);
|
||||
output = output.AddMinutes(_period);
|
||||
return output;
|
||||
case PeriodicityType.TOP_OF_HOUR:
|
||||
output = new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0);
|
||||
output = output.AddHours(_period);
|
||||
return output;
|
||||
case PeriodicityType.TOP_OF_DAY:
|
||||
output = new DateTime(input.Year, input.Month, input.Day);
|
||||
output = output.AddDays(_period);
|
||||
return output;
|
||||
default:
|
||||
throw new Exception("invalid periodicity type: " + _periodicityType);
|
||||
}
|
||||
}
|
||||
|
||||
public PeriodicityType periodicityType
|
||||
{
|
||||
set
|
||||
{
|
||||
this._periodicityType = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean shouldRoll
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
if (now > this._nextRoll)
|
||||
{
|
||||
this._currentRoll = now;
|
||||
this._nextRoll = nextTriggeringTime(now);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public string format
|
||||
{
|
||||
get
|
||||
{
|
||||
return this._currentRoll.ToString(this._format);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -76,6 +76,20 @@ namespace winsw
|
|||
return Environment.ExpandEnvironmentVariables(n.InnerText);
|
||||
}
|
||||
|
||||
private int SingleIntElement(XmlNode parent, string tagName, int defaultValue)
|
||||
{
|
||||
var e = parent.SelectSingleNode(tagName);
|
||||
|
||||
if (e == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int.Parse(e.InnerText);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Path to the executable.
|
||||
/// </summary>
|
||||
|
@ -215,25 +229,54 @@ namespace winsw
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Logmode to 'reset', 'rotate' once or 'append' [default] the out.log and err.log files.
|
||||
/// </summary>
|
||||
public string Logmode
|
||||
public LogHandler LogHandler
|
||||
{
|
||||
get
|
||||
{
|
||||
XmlNode logmodeNode = dom.SelectSingleNode("//logmode");
|
||||
|
||||
if (logmodeNode == null)
|
||||
{
|
||||
return "append";
|
||||
string mode;
|
||||
|
||||
// first, backward compatibility with older configuration
|
||||
XmlElement e = (XmlElement)dom.SelectSingleNode("//logmode");
|
||||
if (e!=null) {
|
||||
mode = e.InnerText;
|
||||
} else {
|
||||
// this is more modern way, to support nested elements as configuration
|
||||
e = (XmlElement)dom.SelectSingleNode("//log");
|
||||
mode = e.GetAttribute("mode");
|
||||
}
|
||||
else
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
return logmodeNode.InnerText;
|
||||
case "rotate":
|
||||
return new SizeBasedRollingLogAppender(LogDirectory, BaseName);
|
||||
|
||||
case "reset":
|
||||
return new ResetLogAppender(LogDirectory, BaseName);
|
||||
|
||||
case "roll":
|
||||
return new RollingLogAppender(LogDirectory, BaseName);
|
||||
|
||||
case "roll-by-time":
|
||||
XmlNode patternNode = e.SelectSingleNode("pattern");
|
||||
if (patternNode == null)
|
||||
{
|
||||
throw new InvalidDataException("Time Based rolling policy is specified but no pattern can be found in configuration XML.");
|
||||
}
|
||||
string pattern = patternNode.InnerText;
|
||||
int period = SingleIntElement(e,"period",1);
|
||||
return new TimeBasedRollingLogAppender(LogDirectory, BaseName, pattern, period);
|
||||
|
||||
case "roll-by-size":
|
||||
int sizeThreshold = SingleIntElement(e,"sizeThreshold",10*1024) * SizeBasedRollingLogAppender.BYTES_PER_KB;
|
||||
int keepFiles = SingleIntElement(e,"keepFiles",SizeBasedRollingLogAppender.DEFAULT_FILES_TO_KEEP);
|
||||
return new SizeBasedRollingLogAppender(LogDirectory, BaseName, sizeThreshold, keepFiles);
|
||||
|
||||
case "append":
|
||||
default:
|
||||
return new DefaultLogAppender(LogDirectory, BaseName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -299,16 +342,7 @@ namespace winsw
|
|||
{
|
||||
get
|
||||
{
|
||||
XmlNode waithintNode = dom.SelectSingleNode("//waithint");
|
||||
|
||||
if (waithintNode == null)
|
||||
{
|
||||
return 15000;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int.Parse(waithintNode.InnerText);
|
||||
}
|
||||
return SingleIntElement(dom, "waithint", 15000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,16 +356,7 @@ namespace winsw
|
|||
{
|
||||
get
|
||||
{
|
||||
XmlNode sleeptimeNode = dom.SelectSingleNode("//sleeptime");
|
||||
|
||||
if (sleeptimeNode == null)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int.Parse(sleeptimeNode.InnerText);
|
||||
}
|
||||
return SingleIntElement(dom, "sleeptime", 15000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,9 +48,11 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Download.cs" />
|
||||
<Compile Include="DynamicProxy.cs" />
|
||||
<Compile Include="LogAppenders.cs" />
|
||||
<Compile Include="Main.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PeriodicRollingCalendar.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceDescriptor.cs" />
|
||||
<Compile Include="Wmi.cs" />
|
||||
|
@ -58,6 +60,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="manifest.xml" />
|
||||
<Content Include="pom.xml" />
|
||||
<Content Include="winsw.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
|
Loading…
Reference in New Issue