diff --git a/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs b/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs index cea65e4..e04da47 100644 --- a/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs +++ b/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.3.5.0")] -[assembly: AssemblyFileVersion("1.3.5.0")] +[assembly: AssemblyVersion("1.3.6.0")] +[assembly: AssemblyFileVersion("1.3.6.0")] diff --git a/TimberWinR/Inputs/LogsListener.cs b/TimberWinR/Inputs/LogsListener.cs index 30fd791..439f8cc 100644 --- a/TimberWinR/Inputs/LogsListener.cs +++ b/TimberWinR/Inputs/LogsListener.cs @@ -6,7 +6,7 @@ using System.Threading; using System.Threading.Tasks; using System.IO; using Interop.MSUtil; - +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; @@ -26,10 +26,17 @@ namespace TimberWinR.Inputs private int _pollingIntervalInSeconds; private TimberWinR.Parser.Log _arguments; private long _receivedMessages; - + private Dictionary _logFileMaxRecords; + private Dictionary _logFileCreationTimes; + private Dictionary _logFileSizes; + public LogsListener(TimberWinR.Parser.Log arguments, CancellationToken cancelToken, int pollingIntervalInSeconds = 3) : base(cancelToken, "Win32-FileLog") { + _logFileMaxRecords = new Dictionary(); + _logFileCreationTimes = new Dictionary(); + _logFileSizes = new Dictionary(); + _receivedMessages = 0; _arguments = arguments; _pollingIntervalInSeconds = pollingIntervalInSeconds; @@ -38,7 +45,7 @@ namespace TimberWinR.Inputs { string file = srcFile.Trim(); Task.Factory.StartNew(() => FileWatcher(file)); - } + } } public override void Shutdown() @@ -54,24 +61,32 @@ namespace TimberWinR.Inputs new JProperty("messages", _receivedMessages), new JProperty("location", _arguments.Location), new JProperty("codepage", _arguments.CodePage), - new JProperty("splitLongLines", _arguments.SplitLongLines), - new JProperty("recurse", _arguments.Recurse) + new JProperty("splitLongLines", _arguments.SplitLongLines), + new JProperty("recurse", _arguments.Recurse), + new JProperty("files", + new JArray(from f in _logFileMaxRecords.Keys + select new JValue(f))), + new JProperty("fileIndices", + new JArray(from f in _logFileMaxRecords.Values + select new JValue(f))), + new JProperty("fileCreationDates", + new JArray(from f in _logFileCreationTimes.Values + select new JValue(f))) ))); + return json; } private void FileWatcher(string fileToWatch) - { + { var iFmt = new TextLineInputFormat() { iCodepage = _arguments.CodePage, - splitLongLines = _arguments.SplitLongLines, + splitLongLines = _arguments.SplitLongLines, recurse = _arguments.Recurse }; - - Dictionary logFileMaxRecords = new Dictionary(); - Dictionary logFileCreationTimes = new Dictionary(); - + + // Execute the query while (!CancelToken.IsCancellationRequested) { @@ -79,7 +94,7 @@ namespace TimberWinR.Inputs try { Thread.CurrentThread.Priority = ThreadPriority.BelowNormal; - + var qfiles = string.Format("SELECT Distinct [LogFilename] FROM {0}", fileToWatch); var rsfiles = oLogQuery.Execute(qfiles, iFmt); for (; !rsfiles.atEnd(); rsfiles.moveNext()) @@ -87,39 +102,46 @@ namespace TimberWinR.Inputs var record = rsfiles.getRecord(); string logName = record.getValue("LogFilename") as string; FileInfo fi = new FileInfo(logName); - + fi.Refresh(); DateTime creationTime = fi.CreationTimeUtc; - bool logHasRolled = logFileCreationTimes.ContainsKey(logName) && creationTime > logFileCreationTimes[logName]; - - if (!logFileMaxRecords.ContainsKey(logName) || logHasRolled) + bool logHasRolled = (_logFileCreationTimes.ContainsKey(logName) && + creationTime > _logFileCreationTimes[logName]) || + (_logFileSizes.ContainsKey(logName) && fi.Length < _logFileSizes[logName]); + + + if (!_logFileMaxRecords.ContainsKey(logName) || logHasRolled) { - logFileCreationTimes[logName] = creationTime; + _logFileCreationTimes[logName] = creationTime; + _logFileSizes[logName] = fi.Length; var qcount = string.Format("SELECT max(Index) as MaxRecordNumber FROM {0}", logName); var rcount = oLogQuery.Execute(qcount, iFmt); var qr = rcount.getRecord(); var lrn = (Int64)qr.getValueEx("MaxRecordNumber"); if (logHasRolled) + { + LogManager.GetCurrentClassLogger().Info("Log {0} has rolled", logName); lrn = 0; - logFileMaxRecords[logName] = lrn; - } + } + _logFileMaxRecords[logName] = lrn; + } } - foreach (string fileName in logFileMaxRecords.Keys.ToList()) + foreach (string fileName in _logFileMaxRecords.Keys.ToList()) { - var lastRecordNumber = logFileMaxRecords[fileName]; + var lastRecordNumber = _logFileMaxRecords[fileName]; var query = string.Format("SELECT * FROM {0} where Index > {1}", fileName, lastRecordNumber); - + var rs = oLogQuery.Execute(query, iFmt); Dictionary colMap = new Dictionary(); for (int col = 0; col < rs.getColumnCount(); col++) { - string colName = rs.getColumnName(col); + string colName = rs.getColumnName(col); colMap[colName] = col; } // Browse the recordset for (; !rs.atEnd(); rs.moveNext()) - { + { var record = rs.getRecord(); var json = new JObject(); foreach (var field in _arguments.Fields) @@ -128,7 +150,7 @@ namespace TimberWinR.Inputs continue; object v = record.getValue(field.Name); - if (field.DataType == typeof (DateTime)) + if (field.DataType == typeof(DateTime)) { DateTime dt = DateTime.Parse(v.ToString()); json.Add(new JProperty(field.Name, dt)); @@ -144,9 +166,9 @@ namespace TimberWinR.Inputs } var lrn = (Int64)record.getValueEx("Index"); - logFileMaxRecords[fileName] = lrn; + _logFileMaxRecords[fileName] = lrn; } - + // Close the recordset rs.close(); rs = null; @@ -160,12 +182,12 @@ namespace TimberWinR.Inputs { oLogQuery = null; } - - Thread.CurrentThread.Priority = ThreadPriority.Normal; + + Thread.CurrentThread.Priority = ThreadPriority.Normal; System.Threading.Thread.Sleep(_pollingIntervalInSeconds * 1000); } Finished(); - } + } } }