protected override void ProcessLogQueue(ConcurrentQueue<LogEvent> logQueue, LogEventDispatcher dispatcher) { // Open a buffered stream writer to the console standard out LogEvent logEvent; using (var writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput()))) { // Pull all of the log events from the queue and write them to the buffered writer while (logQueue.IsEmpty == false) { if (logQueue.TryDequeue(out logEvent)) { try { writer.Write(Layout.FormatLogEvent(logEvent)); } catch (Exception e) { try { writer.Flush(); } finally { if (dispatcher != null) dispatcher.HandleException(e, logEvent); else throw e; } } } } writer.Flush(); } }
/// <summary> /// Initializes the target as normal, except with a layout built-into the target /// </summary> /// <param name="targetConfig">The target config to build this target from</param> /// <param name="dispatcher">The dispatcher this target is attached to</param> /// <param name="synchronous">An override to the synchronous setting in the target config</param> public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { // Initialize the base target as normal // Add logic for initializing the layout as well base.Initialize(targetConfig, dispatcher, synchronous); if (targetConfig != null) { lock (_configLock) { // Check to see if the target configuration passed in is already a layout target configuration and initialize // depending on this LayoutConfig layoutConfig = null; if (typeof(LayoutTargetConfig).IsAssignableFrom(targetConfig.GetType())) { layoutConfig = ((LayoutTargetConfig)targetConfig).LayoutConfig; } else { var layoutConfigToken = targetConfig.Config[LayoutTokenName]; layoutConfig = new LayoutConfig(layoutConfigToken); } Layout = LayoutFactory.BuildLayout(layoutConfig); } } else { Name = DefaultTargetName; Layout = new StandardLayout(); } }
public void TestTagListWildcard() { var config = new LoggingConfig(); config.LoadConfig(); var dispatcher = new LogEventDispatcher(config); var tagKeeper = dispatcher.TagKeeper; Assert.IsTrue(tagKeeper.CheckMatch("helloworld", "hello*")); }
// Initialize our configuration public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { // We need to inherit the configuration of the parent targets base.Initialize(targetConfig, dispatcher, synchronous); // Cast or parse our configuration into a ColorConsoleTargetConfig if (targetConfig != null) ColorConfig = targetConfig is ColorConsoleTargetConfig ? (ColorConsoleTargetConfig)targetConfig : new ColorConsoleTargetConfig(targetConfig.Config); }
public void TestTagList() { var config = new LoggingConfig(); config.LoadConfig(); var dispatcher = new LogEventDispatcher(config); var tagList = new List<string> { "fatal", "error", "warn", "info", "debug", "trace" }; var tagKeeper = dispatcher.TagKeeper; for (int lp = 0; lp < tagList.Count - 1; lp++) for (int lp2 = lp + 1; lp2 < tagList.Count; lp2++) Assert.IsTrue(tagKeeper.CheckMatch(tagList[lp], tagList[lp2]), String.Format("Checking {0} = {1}", tagList[lp2], tagList[lp])); }
public void TestSimpleIncludeRule() { var config = new LoggingConfig(); config.LoadConfig(@"Configs\SimpleIncludeRuleTest.json"); var dispatcher = new LogEventDispatcher(config); var ruleKeeper = dispatcher.RuleKeeper; var infoTargets = ruleKeeper.GetTargetsForTags(new List<string> { "info" }); Assert.IsNotNull(infoTargets); Assert.IsTrue(infoTargets.Count == 1); Assert.IsTrue(infoTargets.Contains("console")); var traceTargets = ruleKeeper.GetTargetsForTags(new List<string> { "trace" }); Assert.IsNotNull(traceTargets); Assert.IsTrue(traceTargets.Count == 0); }
public void TestStrictIncludeRule() { var config = new LoggingConfig(); config.LoadConfig(@"Configs\StrictIncludeRuleTest.json"); var dispatcher = new LogEventDispatcher(config); var ruleKeeper = dispatcher.RuleKeeper; var strictTargets = ruleKeeper.GetTargetsForTags(new List<string> { this.GetType().FullName, "info" }); Assert.IsNotNull(strictTargets); Assert.IsTrue(strictTargets.Count == 1); Assert.IsTrue(strictTargets.Contains("console")); var incompleteTargets = ruleKeeper.GetTargetsForTags(new List<string> { "info" }); Assert.IsNotNull(incompleteTargets); Assert.IsTrue(incompleteTargets.Count == 0); }
/// <summary> /// Initializes this text file target /// </summary> /// <param name="targetConfig">The configuration for this target</param> /// <param name="dispatcher">The dispatcher this target belongs to</param> /// <param name="synchronous">An override to the synchronous flag in the target config</param> public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { // Initialize the target using the base base.Initialize(targetConfig, dispatcher, synchronous); // Make sure we have an initialized text file target if (targetConfig != null) Config = targetConfig is TextFileTargetConfig ? (TextFileTargetConfig)targetConfig : new TextFileTargetConfig(targetConfig.Config); // Setup a bit. Make sure that the directory exists where we are going to write the log file. // Start a worker task for rolling the log file and cleaning the old files EnsurePathExists(Config.FileName); Task.Factory.StartNew(() => { // Run this task until the target is told to shutdown // Watch for the internal stopwatch running, which indicates that data has been written to log // Wait for the minimum idle time since the last write, or the maximum wait time to roll/cleanup the files Stopwatch maxWaitStopwatch = new Stopwatch(); while (!DoShutdown) { if (_sw.IsRunning) { if (maxWaitStopwatch.IsRunning == false) maxWaitStopwatch.Start(); if (_sw.ElapsedMilliseconds > RollIdleWait || maxWaitStopwatch.ElapsedMilliseconds > MaxRollWait) { lock (_fileLock) { RollFile(); CleanupOldFiles(); _sw.Stop(); maxWaitStopwatch.Stop(); } } } Thread.Yield(); Thread.Sleep(RollIdleWait); } }); }
/// <summary> /// Initializes the target with the given targe tconfig, dispatcher and synchronous flag /// </summary> /// <param name="targetConfig">The configuration to build this target with</param> /// <param name="dispatcher">The dispatcher that this target is attached to</param> /// <param name="synchronous">The synchronous flag, used to overwrite the synchronous behavior in the configuration</param> public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { // Default to synchronous base.Initialize(targetConfig, dispatcher, synchronous.HasValue ? synchronous : true); // Parse out the target configuration if (targetConfig != null) { ConsoleTargetConfig consoleConfig = typeof(ConsoleTargetConfig).IsAssignableFrom(targetConfig.GetType()) ? (ConsoleTargetConfig)targetConfig : new ConsoleTargetConfig(targetConfig.Config); ColorRules = consoleConfig.ColorRules; // The rules may have changed, reset the cache RuleCache.Clear(); } }
/// <summary> /// Initializes this target for writing to the windows event log. /// </summary> /// <param name="targetConfig">The target config to build this target from</param> /// <param name="dispatcher">The dispatcher this target is attached to</param> /// <param name="synchronous">An override to the synchronous setting in the target config</param> public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { base.Initialize(targetConfig, dispatcher, synchronous); // Parse out the target configuration Config = targetConfig != null && typeof(WindowsEventLogTargetConfig).IsAssignableFrom(targetConfig.GetType()) ? (WindowsEventLogTargetConfig)targetConfig : new WindowsEventLogTargetConfig(targetConfig.Config); // Make sure that the windows event log is ready for us try { if (!EventLog.SourceExists(Config.Source)) EventLog.CreateEventSource(Config.Source, Config.Log); } catch (Exception cause) { Debug.WriteLine("Failure ensuring log source exists, try running first as an administrator to create the source. Error: " + cause.GetType().FullName + ": " + cause.Message); } }
public void TestMultipleRule() { var config = new LoggingConfig(); config.LoadConfig(@"Configs\MultipleRuleTest.json"); var dispatcher = new LogEventDispatcher(config); var ruleKeeper = dispatcher.RuleKeeper; var cond1Targets = ruleKeeper.GetTargetsForTags(new List<string> { "cond1" }); Assert.IsNotNull(cond1Targets); Assert.IsTrue(cond1Targets.Count == 2); Assert.IsTrue(cond1Targets.Contains("target1")); Assert.IsTrue(cond1Targets.Contains("target2")); var cond2Targets = ruleKeeper.GetTargetsForTags(new List<string> { "cond2" }); Assert.IsNotNull(cond2Targets); Assert.IsTrue(cond2Targets.Count == 1); Assert.IsTrue(cond2Targets.Contains("target2")); var cond3Targets = ruleKeeper.GetTargetsForTags(new List<string> { "cond3" }); Assert.IsNotNull(cond3Targets); Assert.IsTrue(cond3Targets.Count == 1); Assert.IsTrue(cond3Targets.Contains("target1")); }
/// <summary> /// Starts this trace listener extender. Starts a trace listener that will /// route trace messages through the framework as log events /// </summary> /// <param name="dispatcher">The dispatcher that has been initialized for the framework. This TraceListenerExtender doesn't use the dispatcher.</param> public override void Startup(LogEventDispatcher dispatcher) { _traceListener = new InternalTraceListener(this); Trace.Listeners.Add(_traceListener); }
/// <summary> /// Initializes the logging framework using a provided ILoggingConfigBuilder /// </summary> /// <param name="configBuilder">The config builder to use to initialize the logging framework</param> /// <param name="dispatcher">An alternate dispatcher to use for the logging framework</param> /// <param name="exceptionHandler">An exception handler to use for debugging purposes</param> /// <param name="force">Whether or not to force the re-configuration if the framework has alredy been intiaizlied</param> public static void Initialize(ILoggingConfigBuilder configBuilder, LogEventDispatcher dispatcher = null, Action<Exception, string> exceptionHandler = null, bool force = true) { LoggingConfig config = null; // Try to load the config from the given builder try { config = configBuilder.Build(); } catch (Exception cause) { // Report the exception string message = String.Format(FailedConfigBuilderMessage, configBuilder == null ? NullString : configBuilder.GetType().FullName, cause); if (exceptionHandler != null) { exceptionHandler(cause, message); } else { Trace.WriteLine(message, TraceConfigCategory); } } Initialize(config, dispatcher, exceptionHandler, force); }
/// <summary> /// Builds the standard base logger, attached to the given dispatcher, with the given default tags /// </summary> /// <param name="dispatcher">The dispatcher attached to this logger</param> /// <param name="defaultTags">The default tags assigned to this logger</param> public LoggerBase(LogEventDispatcher dispatcher, ICollection<string> defaultTags) { Dispatcher = dispatcher; DefaultTags = defaultTags; }
/// <summary> /// Initializes/Configures this email target /// </summary> /// <param name="targetConfig">The target config to use to configure this email target</param> /// <param name="dispatcher">The dispatcher this target is associated to</param> /// <param name="synchronous">An optional override to the synchronous flag in the target config</param> public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { // Wire up all the default goodies base.Initialize(targetConfig, dispatcher, synchronous); lock (_configLock) { // Reset our "Default" settings to "zero" FromAddress = null; ReplyTo.Clear(); To.Clear(); CC.Clear(); BCC.Clear(); if (targetConfig != null) { // Check target config type here then get it into a SmtpTargetConfig if (typeof(EmailTargetConfig).IsAssignableFrom(targetConfig.GetType())) { Config = (EmailTargetConfig)targetConfig; } else { Config = new EmailTargetConfig(targetConfig.Config); } // Build out the subject layout SubjectLayout = LayoutFactory.BuildLayout(Config.SubjectLayout); // Make sure body layout is setup correctly // If the body file is specified, load a StandardLayout with the contents of the file as the format // Otherwise, use the layout factory to build our layout if (String.IsNullOrEmpty(Config.BodyFile)) { BodyLayout = LayoutFactory.BuildLayout(Config.BodyLayout); } else { try { string fileContent = File.ReadAllText(Config.BodyFile); BodyLayout = new StandardLayout(fileContent); } catch (Exception cause) { Trace.WriteLine(String.Format(FailedToLoadBodyFileMessage, Config.BodyFile, cause)); BodyLayout = new StandardLayout(); } } // Parse out the addresses FromAddress = new MailAddress(Config.FromAddress); // Parse the other email address lists AddAddresses(ReplyTo, Config.ReplyTo); AddAddresses(To, Config.To); AddAddresses(CC, Config.CC); AddAddresses(BCC, Config.BCC); } } }
// Asynchronous logging protected override void ProcessLogQueue(ConcurrentQueue<LogEvent> logQueue, LogEventDispatcher dispatcher) { base.ProcessLogQueue(logQueue, dispatcher); }
/// <summary> /// Builds the standard base logger, attached to the given dispatcher /// </summary> /// <param name="dispatcher">The dispatcher attached to this logger</param> public LoggerBase(LogEventDispatcher dispatcher) { Dispatcher = dispatcher; DefaultTags = new List<string>(); }
/// <summary> /// Initializes the logging framework using a provided LoggingConfig /// </summary> /// <param name="config">The LoggingConfig to use to initialize the logging framework</param> /// <param name="dispatcher">An alternate dispatcher to use for the logging framework</param> /// <param name="exceptionHandler">An exception handler to use for debugging purposes</param> /// <param name="force">Whether or not to force the re-configuration if the framework has alredy been intiaizlied</param> public static void Initialize(LoggingConfig config = null, LogEventDispatcher dispatcher = null, Action<Exception, string> exceptionHandler = null, bool force = true) { lock (_factoryLock) { var instance = Instance.Value; // We only want to configure if we haven't yet, or if it is marked to override (force) the initialization if (force || !instance.Initialized) { // Shutdown existing config if it exists if (instance.Initialized) instance.LoggingConfig.Shutdown(); // Wire up the exception handler instance.ExceptionHandler = exceptionHandler; // Setup the logging config instance.InitializeConfig(config); // Load and initialize the extenders, allowing them to update the config // before we start instance.InitializeExtenders(); // Setup the dispatcher instance.InitializeDispatcher(dispatcher); // Start the extenders instance.StartExtenders(instance.LogEventDispatcher); // Mark us as initialized instance.Initialized = true; } } }
// Initialize the target public override void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { base.Initialize(targetConfig, dispatcher, synchronous); }
// Initialize the extenders private void StartExtenders(LogEventDispatcher dispatcher) { foreach (var extender in Extenders) { try { extender.Startup(dispatcher); } catch (Exception cause) { // Handle the failure HandleException(cause); } } }
/// <summary> /// Constructs the basic logger, with the given dispatcher and default tags /// </summary> /// <param name="dispatcher">The dispatcher to uswe for this logger</param> /// <param name="defaultTags">The default tags to assign to the logger</param> public DefaultLogger(LogEventDispatcher dispatcher, ICollection<string> defaultTags) : base(dispatcher, defaultTags) { }
/// <summary> /// An internal function for initializing the dispatcher /// </summary> /// <param name="dispatcher">An alternate dispatcher to use. If none(null) provided, will use the default dispatcher</param> private void InitializeDispatcher(LogEventDispatcher dispatcher = null) { // If we've been provided an alternate dispatcher, we laready have one // and we aren't already using the new alternate if (dispatcher != null && LogEventDispatcher != null && LogEventDispatcher != dispatcher) { try { // Shut down our current dispatcher LogEventDispatcher.Shutdown(); } catch (Exception e) { // We failed to shutdown the existing dispatcher, log the error and continue Trace.WriteLine(String.Format(ShutdownDispatcherFailureMessage, e), TraceConfigCategory); } } // If we've been provided with an alternate dispatcher if (dispatcher != null) { // Wire it up LogEventDispatcher = dispatcher; LogEventDispatcher.NotifyNewConfig(LoggingConfig); LoggingConfig.RegisterObserver(LogEventDispatcher); } else { // If we don't yet have a dispatcher if (LogEventDispatcher == null) { // Wire up a new default one LogEventDispatcher = new LogEventDispatcher(LoggingConfig, ExceptionHandler); LoggingConfig.RegisterObserver(LogEventDispatcher); } else { // Notify of new config if we already have a dispatcher LogEventDispatcher.NotifyNewConfig(LoggingConfig); } } }
/// <summary> /// Initializes the target using the provided information /// </summary> /// <param name="targetConfig">The configuration to use for this target</param> /// <param name="dispatcher">The dispatcher this target belongs to</param> /// <param name="synchronous">An override of the synchronous flag in the target config</param> public virtual void Initialize(TargetConfig targetConfig, LogEventDispatcher dispatcher = null, bool? synchronous = null) { // Wire up our pieces BaseTargetConfig = targetConfig; Dispatcher = dispatcher; // use the passed configuration if we have it, otherwise, use default values if (targetConfig != null) { Name = targetConfig.Name; Synchronous = synchronous.HasValue ? synchronous.Value : targetConfig.Synchronous.HasValue ? targetConfig.Synchronous.Value : DefaultSynchronousSetting; } else { Name = DefaultName; Synchronous = synchronous.HasValue ? synchronous.Value : DefaultSynchronousSetting; } // Wire up the worker thread (will start a thread if synchronous is false, will stop it otherwise) ConfigureWorkerThread(Synchronous); }
protected override void ProcessLogQueue(ConcurrentQueue<LogEvent> logQueue, LogEventDispatcher dispatcher) { LogEvent logEvent; lock (_fileLock) using (var fileStream = new StreamWriter(new BufferedStream(File.Open(Config.FileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)))) while (logQueue.IsEmpty == false && !QuickRollCheck()) { if (logQueue.TryDequeue(out logEvent)) { try { fileStream.Write(Layout.FormatLogEvent(logEvent)); _lastWrite = GetDateTime(); } catch (Exception e) { if (dispatcher != null) dispatcher.HandleException(e, logEvent); else throw e; } } } if (QuickRollCheck()) RollFile(); _sw.Restart(); }
/// <summary> /// Processes the log queue of events. This is used for asynchronous logging. The worker thread calls this function /// to handle queued log events. The dispatcher is provided for access to the other parts of the framework that /// may be needed for logging purposes, for example, the tag keeper. /// /// Override this function to provide advanced asynchronous logging logic. By default, this function simply calls /// <see cref="Log" />. Additional performance gains can be had, especially when using an external resource such /// as a file, database or service, by opening the handle/connection once and using it for each of the log events, /// as opposed to opening and closing the handle/connection for each log event. Special consideration should be /// taken for "playing nice", if you expect that processing the log events in this queue may be expensive in terms /// of CPU and cycles, consider processing a limited number of log events from the queue before breaking, releasing /// the control back to the system more courteously. /// /// TODO: Consider removing the connection of the dispatcher in favor of the TagKeeper, reducing the coupling needed /// and complexity. /// </summary> /// <param name="logQueue">The queue of log events to log</param> /// <param name="dispatcher">The dispatcher that owns this target</param> protected virtual void ProcessLogQueue(ConcurrentQueue<LogEvent> logQueue, LogEventDispatcher dispatcher) { // Iterate over the queue, removing and logging each log event LogEvent logEvent; while (logQueue.IsEmpty == false) { if (logQueue.TryDequeue(out logEvent)) { try { Log(logEvent); } catch (Exception e) { if (dispatcher != null) dispatcher.HandleException(e, logEvent); else throw e; } } } }
/// <summary> /// Initializes the logging framework using a file /// </summary> /// <param name="configFile">The path to the JSON configuration file to use</param> /// <param name="dispatcher">An alternate dispatcher to use for the logging framework</param> /// <param name="exceptionHandler">An exception handler to use for debugging purposes</param> /// <param name="force">Whether or not to force the re-configuration if the framework has alredy been intiaizlied</param> public static void Initialize(string configFile, LogEventDispatcher dispatcher = null, Action<Exception, string> exceptionHandler = null, bool force = true) { LoggingConfig config = null; // Try to load the config from the given file try { config = new LoggingConfig(configFile); } catch (Exception cause) { // Report the exception if (exceptionHandler != null) { exceptionHandler(cause, ConfigurationFailedUsingDefaultsMessage); } else { Trace.WriteLine(cause, TraceConfigCategory); } } Initialize(config, dispatcher, exceptionHandler, force); }
/// <summary> /// Constructs the basic logger, with the given dispatcher attached /// </summary> /// <param name="dispatcher">The dispatcher to use for this logger</param> public DefaultLogger(LogEventDispatcher dispatcher) : base(dispatcher) { }
/// <summary> /// Builds a basic target base, with the associated dispatcher /// </summary> /// <param name="dispatcher">The dispatcher that owns this target</param> public TargetBase(LogEventDispatcher dispatcher) { InitializeInstance(dispatcher); }
/// <summary> /// Instructs the extender to startup, providing the initialized dispatcher /// </summary> /// <param name="dispatcher">The dispatcher to associate with this extender</param> public abstract void Startup(LogEventDispatcher dispatcher);
/// <summary> /// Initializes this instance to the provided dispatcher /// </summary> /// <param name="dispatcher">The dispatcher that owns this target</param> private void InitializeInstance(LogEventDispatcher dispatcher) { Dispatcher = dispatcher; LogQueue = new ConcurrentQueue<LogEvent>(); DoShutdownThread = false; IsThreadShutdown = false; }