/// <summary> /// Samples of how logging can be used. You can tweak what makes it out into the log file by changing the logging level /// in appsettings.json /// They are essentially "Debug", "Info", "Warning", "Error", "Fatal" /// </summary> private static void SampleLogging() { LoggingContexts(); LoggingTags(); LoggingExceptionsAndObjects(); // Why don't XML Doc comments work here? Anyway. // This method shows how logging context works and is scoped. Scope COULD be method names but are probably better used in a wider way. // Up to you, but this is how they work. void LoggingContexts() { Logger.Info("This is outside any context"); using (Logger.Context("Context 1")) { Logger.Debug("Inside the first context"); using (Logger.Context("Context 2")) { Logger.Debug("Inside the second context"); LoggingContextsAlsoWorkInsideMethods(); } Logger.Debug("Outside the second context but inside the first context"); } Logger.Error("And now we're back outside any contexts"); void LoggingContextsAlsoWorkInsideMethods() { Logger.Warning("So, inside second context from inside a method"); Logger.LogMethodName = true; Logger.Debug("We're now logging the method name"); var areUsingContext = Logger.UseContext; Logger.UseContext = false; Logger.Debug("We're now logging the method name, but without the context"); Logger.LogMethodName = false; Logger.UseContext = areUsingContext; Logger.Debug("Now we're not logging the method name"); } } // Log tags are a way to get finer grained logging that can be switched on or off in addition to the typical logging levels. // I've always tended to activate log tags at startup, based on config file settings, but they could be switched dynamically // once you have a way to communicate what tags should be active! void LoggingTags() { Logger.LogActiveLogTags(); // All contained logging will be tagged, including any scoped methods using (Logger.ScopedLogTag(LogTags.Defined)) { Logger.Warning( "It's worth knowing that only Info & Debug can get tagged & thus switched off. Anything more serious shouldn't be switchable!"); Logger.Debug("A debug message with the tag Defined"); Logger.Info("An info message with the tag Defined"); Logger.Debug("The previous two used the scoped tag but for this one I'll use a different tag", LogTags.AreCurrently); ButWhatAboutLoggingFromSubroutines(); } using (Logger.ScopedLogTag()) { Logger.Debug("This one will use a tag of SampleLogging, NOT LoggingTags"); ButWhatAboutLoggingFromSubroutines(); } var madeUpOnTheFly = new LogTag("MadeUpOnTheFly"); Logger.ActivateLogTag(madeUpOnTheFly); Logger.Info("Adding a new log tag", madeUpOnTheFly); Logger.DeactivateLogTag(madeUpOnTheFly); Logger.Info("This one won't appear!", madeUpOnTheFly); void ButWhatAboutLoggingFromSubroutines() { Logger.Info("If they don't specify a tag, they will take on whatever tag scope is active"); Logger.Debug("Unless of course they use their own override", LogTags.NoTags); } } // Here I show you how to log an exception and objects in general void LoggingExceptionsAndObjects() { try { try { Logger.Info("You'll get a JSON representation of the Logging Configuration"); Logger.Info(Initialise.LoggingConfiguration); Logger.Info($"Here's the Logging Configuration - {Logger.JsonIt(Initialise.LoggingConfiguration)}"); throw new AmbiguousImplementationException("Now let's log an exception!"); } catch (Exception excep) { Logger.Error(excep); try { Logger.Info("It'll even handle nested exceptions"); throw new BadImageFormatException("The outer exception message", excep); } catch (Exception e) { Logger.Error(e); throw; } } } catch (Exception e) { Logger.Info( "Previously logged exceptions log less verbosely when logged again in a cascading catch"); Logger.Error(e); } } }