/// <summary> /// Prepares a log instance and adds it to the instance list /// </summary> /// <param name="instance"> /// The log instance to configure /// </param> private static void ConfigureInstance(Instance instance) { String[] props = instance.Properties.ToArray(); // validate the instance configuration, and initialize the logger instance.Validate(); instance.Logger.Initialize(props); // if this instance is buffered, attach the log buffer if (instance.Buffer > 0) { Loggers.Buffer buffer = new Loggers.Buffer(instance.Logger, instance.Buffer); buffer.Initialize(props); instance.Logger = buffer; } // register the instance instances.Add(instance); }
/// <summary> /// Dispatches a log event to a single log instance /// </summary> /// <param name="instance"> /// The log instance to receive the event /// </param> /// <param name="ctx"> /// The event to dispatch /// </param> private static void DispatchEventInstance(Instance instance, EventContext ctx) { if (instance.Filter.Evaluate(ctx)) try { instance.Logger.Log(new[] { new Event(ctx, instance.Properties) }); } catch { } }
/// <summary> /// Removes a log instance /// </summary> /// <param name="instance"> /// The log instance to remove /// </param> public static void UnregisterInstance(Instance instance) { if (initialized) { Boolean removed = false; // remove the instance from the mapping, // and update the active global context using (ConfigWriteLock()) if (removed = instances.Remove(instance)) ConfigureContexts(); // flush the instance's buffer if (removed && instance.Logger is Loggers.Buffer) ((Loggers.Buffer)instance.Logger).Flush(); } }
/// <summary> /// Manually registers a new log instance /// </summary> /// <param name="instance"> /// The log instance to register /// </param> /// <returns> /// A disposable object that can be used /// to unregister the instance /// </returns> public static IDisposable RegisterInstance(Instance instance) { Initialize(); using (ConfigWriteLock()) { // add the new instance, and refresh the // active global property list ConfigureInstance(instance); ConfigureContexts(); return new Disposable(() => UnregisterInstance(instance)); } }
public void TestFiltering() { var log = new Log(this); var queue = new Loggers.Queue(); var instance = new Instance() { Logger = queue, Synchronous = true, Buffer = 0, Properties = new[] { "Event.Type", "TestLog.ClassValue", "Event.EventValue", "Global.Host" } }; // property inclusion instance.Filter = new Filter() { IncludeProps = new[] { new Filter.Property("Event.Type", "Error"), new Filter.Property("Event.Type", "Warning") } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); log.Warn("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); log.Info("test"); Assert.IsFalse(queue.Dequeue().Any()); } // property exclusion instance.Filter = new Filter() { ExcludeProps = new[] { new Filter.Property("Event.Type", "Error"), new Filter.Property("Event.Type", "Warning") } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.IsFalse(queue.Dequeue().Any()); log.Warn("test"); Assert.IsFalse(queue.Dequeue().Any()); log.Info("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); } instance.Filter = new Filter() { ExcludeProps = new[] { new Filter.Property("Event.Type", "Error"), new Filter.Property("Event.Type", "Warning") } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.IsFalse(queue.Dequeue().Any()); log.Warn("test"); Assert.IsFalse(queue.Dequeue().Any()); log.Info("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); } // property inclusion/exclusion instance.Filter = new Filter() { IncludeProps = new[] { new Filter.Property("Event.Type", "Error"), new Filter.Property("Event.Type", "Warning") }, ExcludeProps = new[] { new Filter.Property("Event.Type", "Warning"), } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); log.Warn("test"); Assert.IsFalse(queue.Dequeue().Any()); log.Info("test"); Assert.IsFalse(queue.Dequeue().Any()); } // source inclusion instance.Filter = new Filter() { IncludeProps = new[] { new Filter.Property("Event.Source", GetType().AssemblyQualifiedName), new Filter.Property("Event.Source", typeof(Int32).AssemblyQualifiedName) } }; using (Log.RegisterInstance(instance)) { log.Info("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); new Log(typeof(Int32)).Info("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); new Log(typeof(String)).Info("test"); Assert.IsFalse(queue.Dequeue().Any()); } // source exclusion instance.Filter = new Filter() { ExcludeProps = new[] { new Filter.Property("Event.Source", GetType().AssemblyQualifiedName), new Filter.Property("Event.Source", typeof(Int32).AssemblyQualifiedName) } }; using (Log.RegisterInstance(instance)) { log.Info("test"); Assert.IsFalse(queue.Dequeue().Any()); new Log(typeof(Int32)).Info("test"); Assert.IsFalse(queue.Dequeue().Any()); new Log(typeof(String)).Info("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); } // source inclusion/exclusion instance.Filter = new Filter() { IncludeProps = new[] { new Filter.Property("Event.Source", GetType().AssemblyQualifiedName), new Filter.Property("Event.Source", typeof(Int32).AssemblyQualifiedName) }, ExcludeProps = new[] { new Filter.Property("Event.Source", typeof(Int32).AssemblyQualifiedName) } }; using (Log.RegisterInstance(instance)) { log.Info("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); new Log(typeof(Int32)).Info("test"); Assert.IsFalse(queue.Dequeue().Any()); new Log(typeof(String)).Info("test"); Assert.IsFalse(queue.Dequeue().Any()); } // non-event property filter instance.Filter = new Filter() { IncludeProps = new[] { new Filter.Property("Event.Message", "test"), } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); log.Error("invalid"); Assert.IsFalse(queue.Dequeue().Any()); } instance.Filter = new Filter() { ExcludeProps = new[] { new Filter.Property("Event.Message", "test"), } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.IsFalse(queue.Dequeue().Any()); log.Error("invalid"); Assert.AreEqual(queue.Dequeue().Count(), 1); } // non-event global property filter instance.Filter = new Filter() { IncludeProps = new[] { new Filter.Property("Global.Host", Environment.MachineName), } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.AreEqual(queue.Dequeue().Count(), 1); } instance.Filter = new Filter() { ExcludeProps = new[] { new Filter.Property("Global.Host", Environment.MachineName), } }; using (Log.RegisterInstance(instance)) { log.Error("test"); Assert.IsFalse(queue.Dequeue().Any()); } }
public void TestConfiguration() { var log = new Log(this); var queue = new Loggers.Queue(); Event evt = null; // invalid global context AssertException(() => Log.RegisterContext("Global", new Dictionary<String, Func<Object>>() { { "Host", () => "test" } } )); // invalid instance registration AssertException(() => Log.RegisterInstance(null)); AssertException(() => Log.RegisterInstance(new Instance())); AssertException(() => Log.RegisterInstance( new Instance() { Buffer = -1, Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = null, Properties = new[] { "Event.Type" }, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = null, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new String[0], } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { (String)null }, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "" }, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { " " }, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "invalid" }, } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, Filter = new Filter() { IncludeProps = new[] { new Filter.Property(null, "test") }, } } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, Filter = new Filter() { IncludeProps = new[] { new Filter.Property("", "test") }, } } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, Filter = new Filter() { IncludeProps = new[] { new Filter.Property(" ", "test") }, } } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, Filter = new Filter() { ExcludeProps = new[] { new Filter.Property(null, "test") }, } } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, Filter = new Filter() { ExcludeProps = new[] { new Filter.Property("", "test") }, } } )); AssertException(() => Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Properties = new[] { "Event.Type" }, Filter = new Filter() { ExcludeProps = new[] { new Filter.Property(" ", "test") }, } } )); // default instance registration var instance = new Instance() { Logger = queue, Synchronous = true, Buffer = 0, Properties = new[] { "Event.Type" } }; Log.RegisterInstance(instance); log.Trace("trace"); evt = queue.Dequeue().Single(); Assert.AreEqual(evt["Event.Type"], EventType.Trace); Log.UnregisterInstance(instance); log.Trace("trace"); Assert.IsFalse(queue.Dequeue().Any()); // disposable instance registration using ( Log.RegisterInstance( new Instance() { Logger = queue, Synchronous = true, Buffer = 0, Properties = new[] { "Event.Type" } } ) ) { log.Info("info"); evt = queue.Dequeue().Single(); Assert.AreEqual(evt["Event.Type"], EventType.Info); } log.Info("info"); Assert.IsFalse(queue.Dequeue().Any()); // log source type Assert.AreEqual(log.SourceType, GetType()); }
public void TestConcurrency() { // concurrent events with no log Parallel.For(0, ParallelIterations, i => { var log = new Log(this); log.InfoEx( new TestContext() { Field = "TestContextField", Property = "TestContextProperty" }, "TestMessage", null ); } ); // configure the log Loggers.Queue queue; using ( Log.RegisterInstance( new Instance() { Logger = queue = new Loggers.Queue(), Synchronous = true, Buffer = 0, Properties = new[] { "Event.Type", "Event.Source", "Event.Timestamp", "Event.Time", "Event.Message", "Event.Exception", "TestLog.Property", "TestContext.Field", "Global.Host" } } ) ) using ( Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Synchronous = true, Buffer = 0, Properties = new[] { "Event.Type" } } ) ) { this.Property = "LogTestProperty"; // concurrent events through private logs { var logs = new Log[ParallelIterations]; for (Int32 i = 0; i < logs.Length; i++) logs[i] = new Log(this); Parallel.For(0, ParallelIterations, i => { logs[i].ErrorEx( new TestContext() { Field = "TestContextField", Property = "TestContextProperty" }, new Exception("TestMessage") ); } ); var events = queue.Dequeue().ToList(); Assert.AreEqual(events.Count, ParallelIterations); foreach (var evt in events) { Assert.AreEqual(evt["Event.Type"], EventType.Error); Assert.AreEqual(evt["Event.Source"], GetType()); Assert.AreNotEqual(evt["Event.Timestamp"], 0); Assert.IsNotNull(evt["Event.Time"]); Assert.AreEqual(evt["Event.Message"], "TestMessage"); Assert.AreEqual(((Exception)evt["Event.Exception"]).Message, "TestMessage"); Assert.AreEqual(evt["TestLog.Property"], "LogTestProperty"); Assert.AreEqual(evt["TestContext.Field"], "TestContextField"); Assert.AreEqual(evt["Global.Host"], Environment.MachineName); } } // concurrent events through a shared log { var log = new Log(this); Parallel.For(0, ParallelIterations, i => { log.ErrorEx( new TestContext() { Field = "TestContextField", Property = "TestContextProperty" }, new Exception("TestMessage") ); } ); var events = queue.Dequeue().ToList(); Assert.AreEqual(events.Count, ParallelIterations); foreach (var evt in events) { Assert.AreEqual(evt["Event.Type"], EventType.Error); Assert.AreEqual(evt["Event.Source"], GetType()); Assert.AreNotEqual(evt["Event.Timestamp"], 0); Assert.IsNotNull(evt["Event.Time"]); Assert.AreEqual(evt["Event.Message"], "TestMessage"); Assert.AreEqual(((Exception)evt["Event.Exception"]).Message, "TestMessage"); Assert.AreEqual(evt["TestLog.Property"], "LogTestProperty"); Assert.AreEqual(evt["TestContext.Field"], "TestContextField"); Assert.AreEqual(evt["Global.Host"], Environment.MachineName); } } } // concurrent events with configuration changes { var log = new Log(this); var queues = new Loggers.Queue[ParallelIterations]; var instances = new Instance[ParallelIterations]; for (Int32 i = 0; i < ParallelIterations; i++) instances[i] = new Instance() { Logger = queues[i] = new Loggers.Queue(), Buffer = 0, Synchronous = true, Properties = new[] { "Event.Type" } }; Parallel.For(0, ParallelIterations, i => { using ( Log.RegisterInstance( new Instance() { Logger = new Loggers.Null(), Buffer = i % 10, Synchronous = true, Properties = new[] { "Event.Type" } } ) ) log.Info("info"); using (Log.RegisterInstance(instances[i])) log.Info("info"); Assert.IsTrue(queues[i].Dequeue().Count() >= 1); } ); } // async event causal ordering using ( Log.RegisterInstance( new Instance() { Logger = queue = new Loggers.Queue(), Buffer = 0, Synchronous = false, Properties = new[] { "Event.Timestamp", "Event.Time", "Event.Index" } } ) ) { var log = new Log(this); for (Int32 i = 0; i < ParallelIterations; i++) log.InfoEx(new { Index = i }); Thread.Sleep(100); var events = queue.Dequeue().ToList(); Assert.AreEqual(events.Count, ParallelIterations); for (Int32 i = 0; i < ParallelIterations; i++) { if (i > 0) { Assert.IsTrue((Int64)events[i]["Event.Timestamp"] >= (Int64)events[i - 1]["Event.Timestamp"]); Assert.IsTrue((DateTime)events[i]["Event.Time"] >= (DateTime)events[i - 1]["Event.Time"]); } Assert.AreEqual(events[i]["Event.Index"], i); } } Log.Flush(); }