diff --git a/TimberWinR.ServiceHost/Program.cs b/TimberWinR.ServiceHost/Program.cs index bc5e8de..afadb46 100644 --- a/TimberWinR.ServiceHost/Program.cs +++ b/TimberWinR.ServiceHost/Program.cs @@ -13,6 +13,7 @@ using TimberWinR.Inputs; using Topshelf; using Topshelf.HostConfigurators; +using Topshelf.Logging; using Topshelf.ServiceConfigurators; namespace TimberWinR.ServiceHost @@ -34,7 +35,8 @@ namespace TimberWinR.ServiceHost serviceConfigurator.WhenStopped(myService => myService.Stop()); }); - hostConfigurator.AddCommandLineDefinition("configFile", c => arguments.ConfigFile = c); + hostConfigurator.AddCommandLineDefinition("configFile", c => arguments.ConfigFile = c); + hostConfigurator.AddCommandLineDefinition("logLevel", c => arguments.LogLevel = c); hostConfigurator.ApplyCommandLine(); hostConfigurator.RunAsLocalSystem(); @@ -50,10 +52,14 @@ namespace TimberWinR.ServiceHost internal class Arguments { public string ConfigFile { get; set; } + public string LogLevel { get; set; } + public string LogfileDir { get; set; } public Arguments() { - ConfigFile = string.Empty; + ConfigFile = "default.json"; + LogLevel = "Info"; + LogfileDir = @"C:\logs"; } } @@ -93,7 +99,7 @@ namespace TimberWinR.ServiceHost /// private void RunService() { - _manager = new TimberWinR.Manager(_args.ConfigFile, _cancellationToken); + _manager = new TimberWinR.Manager(_args.ConfigFile, _args.LogLevel, _args.LogfileDir, _cancellationToken); } } } diff --git a/TimberWinR.ServiceHost/config.json b/TimberWinR.ServiceHost/config.json index e154a46..0e62426 100644 --- a/TimberWinR.ServiceHost/config.json +++ b/TimberWinR.ServiceHost/config.json @@ -13,17 +13,6 @@ "_comment": "Output from NLog", "port": 5140 } - ], - "Logs": [ - { - "location": "C:\\Logs1\\*.log" - } - ], - "IISW3CLogs": [ - { - "_comment": "Default site", - "location": "c:\\inetpub\\logs\\LogFiles\\W3SVC1\\*" - } ] }, "Outputs": { diff --git a/TimberWinR/Configuration.cs b/TimberWinR/Configuration.cs index cb4c5c3..15dec00 100644 --- a/TimberWinR/Configuration.cs +++ b/TimberWinR/Configuration.cs @@ -91,17 +91,18 @@ namespace TimberWinR if (x.TimberWinR.Inputs != null) { - c._events = x.TimberWinR.Inputs.WindowsEvents.ToList(); - c._iisw3clogs = x.TimberWinR.Inputs.IISW3CLogs.ToList(); - c._logs = x.TimberWinR.Inputs.Logs.ToList(); - - c._tcps = x.TimberWinR.Inputs.Tcps.ToList(); + if (x.TimberWinR.Inputs.WindowsEvents != null) + c._events = x.TimberWinR.Inputs.WindowsEvents.ToList(); + if (x.TimberWinR.Inputs.IISW3CLogs != null) + c._iisw3clogs = x.TimberWinR.Inputs.IISW3CLogs.ToList(); + if (x.TimberWinR.Inputs.Logs != null) + c._logs = x.TimberWinR.Inputs.Logs.ToList(); + if (x.TimberWinR.Inputs.Tcps != null) + c._tcps = x.TimberWinR.Inputs.Tcps.ToList(); } - if (x.TimberWinR.Outputs != null) - { - c._redisOutputs = x.TimberWinR.Outputs.Redis.ToList(); - } + if (x.TimberWinR.Outputs != null) + c._redisOutputs = x.TimberWinR.Outputs.Redis.ToList(); if (x.TimberWinR.Filters != null) c._filters = x.TimberWinR.AllFilters.ToList(); diff --git a/TimberWinR/Inputs/InputBase.cs b/TimberWinR/Inputs/InputBase.cs index a5dfea6..d2ea723 100644 --- a/TimberWinR/Inputs/InputBase.cs +++ b/TimberWinR/Inputs/InputBase.cs @@ -11,166 +11,7 @@ namespace TimberWinR.Inputs public abstract class InputBase { public const string TagName = "Inputs"; - - internal List parseFields(XElement parent, Dictionary allPossibleFields) - { - IEnumerable xml_fields = - from el in parent.Elements("Fields").Elements("Field") - select el; - - List fields = new List(); - - foreach (XElement f in xml_fields) - { - // Parse field name. - string name; - string attributeName = "name"; - try - { - name = f.Attribute(attributeName).Value; - } - catch (NullReferenceException) - { - throw new TimberWinR.ConfigurationErrors.MissingRequiredAttributeException(f, attributeName); - } - - // Ensure field name is valid. - if (allPossibleFields.ContainsKey(name)) - { - fields.Add(new FieldDefinition(name, allPossibleFields[name])); - } - else - { - throw new TimberWinR.ConfigurationErrors.InvalidAttributeValueException(f.Attribute("name")); - } - } - - // If no fields are provided, default to all fields. - if (fields.Count == 0) - { - foreach (KeyValuePair entry in allPossibleFields) - { - fields.Add(new FieldDefinition(entry.Key, entry.Value)); - } - } - - return fields; - } - - protected static string ParseRequiredStringAttribute(XElement e, string attributeName) - { - XAttribute a = e.Attribute(attributeName); - if (a != null) - return a.Value; - else - throw new TimberWinR.ConfigurationErrors.MissingRequiredAttributeException(e, attributeName); - } - - protected static string ParseStringAttribute(XElement e, string attributeName, string defaultValue = "") - { - string retValue = defaultValue; - XAttribute a = e.Attribute(attributeName); - if (a != null) - retValue = a.Value; - return retValue; - } - - protected static string ParseDateAttribute(XElement e, string attributeName, string defaultValue = "") - { - string retValue = defaultValue; - XAttribute a = e.Attribute(attributeName); - if (a != null) - { - DateTime dt; - if (DateTime.TryParseExact(a.Value, - "yyyy-MM-dd hh:mm:ss", - CultureInfo.InvariantCulture, - DateTimeStyles.None, - out dt)) - { - retValue = a.Value; - } - else - { - throw new TimberWinR.ConfigurationErrors.InvalidAttributeDateValueException(a); - } - } - - return retValue; - } - - protected static bool ParseRequiredBoolAttribute(XElement e, string attributeName) - { - XAttribute a = e.Attribute(attributeName); - if (a == null) - throw new TimberWinR.ConfigurationErrors.InvalidAttributeValueException(e.Attribute(attributeName)); - - switch (a.Value) - { - case "ON": - case "true": - return true; - - case "OFF": - case "false": - return false; - - default: - throw new TimberWinR.ConfigurationErrors.InvalidAttributeValueException(e.Attribute(attributeName)); - } - } - - protected static string ParseEnumAttribute(XElement e, string attributeName, IEnumerable values, string defaultValue) - { - XAttribute a = e.Attribute(attributeName); - - if (a != null) - { - string v = a.Value; - if (values.Contains(v)) - return v; - else - throw new TimberWinR.ConfigurationErrors.InvalidAttributeValueException(e.Attribute(attributeName)); - } - return defaultValue; - } - - protected static int ParseIntAttribute(XElement e, string attributeName, int defaultValue) - { - XAttribute a = e.Attribute(attributeName); - if (a != null) - { - int valInt; - if (int.TryParse(a.Value, out valInt)) - return valInt; - else - throw new TimberWinR.ConfigurationErrors.InvalidAttributeIntegerValueException(a); - } - return defaultValue; - } - protected static bool ParseBoolAttribute(XElement e, string attributeName, bool defaultValue) - { - bool retValue = defaultValue; - XAttribute a = e.Attribute(attributeName); - - if (a != null) - { - switch (a.Value) - { - case "ON": - case "true": - retValue = true; - break; - - case "OFF": - case "false": - retValue = false; - break; - } - } - return retValue; - } - + public override string ToString() { StringBuilder sb = new StringBuilder(); diff --git a/TimberWinR/Inputs/InputListener.cs b/TimberWinR/Inputs/InputListener.cs index 39fa6d1..7eef3db 100644 --- a/TimberWinR/Inputs/InputListener.cs +++ b/TimberWinR/Inputs/InputListener.cs @@ -65,7 +65,7 @@ namespace TimberWinR.Inputs } } - private void AddDefaultFields(JObject json) + protected virtual void AddDefaultFields(JObject json) { if (json["type"] == null) json.Add(new JProperty("type", _typeName)); @@ -76,8 +76,13 @@ namespace TimberWinR.Inputs if (json["@version"] == null) json.Add(new JProperty("@version", 1)); + DateTime utc = DateTime.UtcNow; + if (json["@timestamp"] == null) - json.Add(new JProperty("@timestamp", DateTime.UtcNow.ToString("o"))); + json.Add(new JProperty("@timestamp", utc.ToString("o"))); + + if (json["UtcTimestamp"] == null) + json.Add(new JProperty("UtcTimestamp", utc.ToString("o"))); } protected void ProcessJson(JObject json) diff --git a/TimberWinR/Inputs/WindowsEvtInputListener.cs b/TimberWinR/Inputs/WindowsEvtInputListener.cs index 29f5e2f..4e0c9df 100644 --- a/TimberWinR/Inputs/WindowsEvtInputListener.cs +++ b/TimberWinR/Inputs/WindowsEvtInputListener.cs @@ -27,7 +27,7 @@ namespace TimberWinR.Inputs public WindowsEvtInputListener(TimberWinR.Parser.WindowsEvent arguments, CancellationToken cancelToken, int pollingIntervalInSeconds = 1) : base(cancelToken, "Win32-Eventlog") - { + { _arguments = arguments; _pollingIntervalInSeconds = pollingIntervalInSeconds; var task = new Task(EventWatcher, cancelToken); @@ -36,15 +36,15 @@ namespace TimberWinR.Inputs public override void Shutdown() { - base.Shutdown(); - + base.Shutdown(); } private void EventWatcher() { var oLogQuery = new LogQuery(); - + LogManager.GetCurrentClassLogger().Info("WindowsEvent Input Listener Ready"); + // Instantiate the Event Log Input Format object var iFmt = new EventLogInputFormat() { @@ -69,7 +69,7 @@ namespace TimberWinR.Inputs { try { - var rs = oLogQuery.Execute(query, iFmt); + var rs = oLogQuery.Execute(query, iFmt); // Browse the recordset for (; !rs.atEnd(); rs.moveNext()) { diff --git a/TimberWinR/Manager.cs b/TimberWinR/Manager.cs index 3e16e0d..b42d03e 100644 --- a/TimberWinR/Manager.cs +++ b/TimberWinR/Manager.cs @@ -24,11 +24,13 @@ namespace TimberWinR public List Listeners { get; set; } public void Shutdown() { + LogManager.GetCurrentClassLogger().Info("Shutting Down"); + foreach (InputListener listener in Listeners) listener.Shutdown(); } - public Manager(string jsonConfigFile, CancellationToken cancelToken) + public Manager(string jsonConfigFile, string logLevel, string logfileDir, CancellationToken cancelToken) { Outputs = new List(); Listeners = new List(); @@ -38,19 +40,30 @@ namespace TimberWinR // Create our default targets var coloredConsoleTarget = new ColoredConsoleTarget(); - Target fileTarget = CreateDefaultFileTarget("c:\\logs"); + Target fileTarget = CreateDefaultFileTarget(logfileDir); loggingConfiguration.AddTarget("Console", coloredConsoleTarget); loggingConfiguration.AddTarget("DailyFile", fileTarget); + // The LogLevel.Trace means has to be at least Trace to show up on console loggingConfiguration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, coloredConsoleTarget)); - loggingConfiguration.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, fileTarget)); + // LogLevel.Debug means has to be at least Debug to show up in logfile + loggingConfiguration.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget)); LogManager.Configuration = loggingConfiguration; - LogManager.EnableLogging(); - - LogManager.GetCurrentClassLogger().Info("Initialized"); + LogManager.EnableLogging(); + + LogManager.GlobalThreshold = LogLevel.FromString(logLevel); + + FileInfo fi = new FileInfo(jsonConfigFile); + + LogManager.GetCurrentClassLogger().Info("Initialized, Reading Config: {0}", fi.FullName); + LogManager.GetCurrentClassLogger().Info("Log Directory {0}", logfileDir); + LogManager.GetCurrentClassLogger().Info("Logging Level: {0}", LogManager.GlobalThreshold); + if (!fi.Exists) + throw new FileNotFoundException("Missing config file", jsonConfigFile); + // Read the Configuration file Config = Configuration.FromFile(jsonConfigFile); diff --git a/TimberWinR/Outputs/Redis.cs b/TimberWinR/Outputs/Redis.cs index d6934df..fee0276 100644 --- a/TimberWinR/Outputs/Redis.cs +++ b/TimberWinR/Outputs/Redis.cs @@ -92,7 +92,7 @@ namespace TimberWinR.Outputs ApplyFilters(jsonMessage); var message = jsonMessage.ToString(); - LogManager.GetCurrentClassLogger().Trace(message); + LogManager.GetCurrentClassLogger().Debug(message); lock (_locker) { @@ -136,7 +136,7 @@ namespace TimberWinR.Outputs { client.StartPipe(); LogManager.GetCurrentClassLogger() - .Info("Sending {0} Messages to {1}", messages.Length, client.Host); + .Debug("Sending {0} Messages to {1}", messages.Length, client.Host); foreach (string jsonMessage in messages) { diff --git a/TimberWinR/TimberWinR.csproj b/TimberWinR/TimberWinR.csproj index fe34a2d..120f191 100644 --- a/TimberWinR/TimberWinR.csproj +++ b/TimberWinR/TimberWinR.csproj @@ -108,6 +108,7 @@ +