Skip to content

Get information out of your code at runtime to send it to log files, perf counters, consoles, services, sensors. Maximum flexibility and maintainability, minimum code.

License

Notifications You must be signed in to change notification settings

jzabroski/Its.Log

 
 

Repository files navigation

Its.Log

Build Status NuGet Status

Code instrumentation

Its.Log helps you instrument your code. It doesn't know anything about logging libraries, performance counters, or tracing, but it can be used to send a lot of information to all of them easily.

Log any object:

Log.Write(() => ren);

...or several at once:

Log.Write(() => new { ren, stimpy } );
          // writes this to the log:
          // { Information: CallingType = Characters | CallingMethod = Dinner | Subject = { ren = { FirstName = Ren, LastName = Hoek, Species = chihuahua, Weight = 1 } | stimpy = { FirstName = Stimpy, LastName = [null], Species = cat, Weight = 5 } } | TimeStamp = 2014-12-18 16:11:00Z }

Send the output anywhere. Here's how you send it to the console:

Log.EntryPosted += (sender, e) => Console.WriteLine(e.LogEntry.ToString());

Log boundaries:

using (Log.Enter(() => new { ren, stimpy } ))
       // writes: { Start: CallingType = Characters | CallingMethod = Dinner | Subject = { ren = { FirstName = Ren, LastName = Hoek, Species = chihuahua, Weight = 1 } | stimpy = { FirstName = Stimpy, LastName = [null], Species = cat, Weight = 5 } } | TimeStamp = 2014-12-18 16:11:00Z }
{
     ren.Starve();
     stimpy.Feed();  

} // writes:
  // { Stop: CallingType = Characters | CallingMethod = Dinner | ElapsedMilliseconds = 1402 | Subject = { ren = { FirstName = Ren, LastName = Hoek, Species = chihuahua, Weight = .5 } | stimpy = { FirstName = Stimpy, LastName = [null], Species = cat, Weight = 9 } } | TimeStamp = 2014-12-18 16:11:02Z }

Confirm checkpoints along the way:

using (var activity = Log.Enter(() => new { ren, stimpy } ))
{
    stimpy.Feed();  
    activity.Confirm(() => "Stimpy fed");

    ren.Starve();
    activity.Confirm(() => "Ren starved");

    throw new Exception("I want real food!"); 
    
    activity.Confirm(() => "Done!");
} // writes:
  // { Stop: CallingType = Characters | CallingMethod = Dinner | ElapsedMilliseconds = 1402 | Subject = { ren = { FirstName = Ren, LastName = Hoek, Species = chihuahua, Weight = .5 } | stimpy = { FirstName = Stimpy, LastName = [null], Species = cat, Weight = 9 } } | TimeStamp = 2014-12-18 16:11:02Z | Params = { { Confirmed = "Stimpy fed", "Ren starved"} } }

Format anything with the ToLogString extension method:

Console.WriteLine(episodes.ToLogString());
// if episodes is null, it writes: [null]
// otherwise it writes using ToString: { SampleApp.Episode,  SampleApp.Episode,  SampleApp.Episode, (...12 more) }

Tell it to be more informative:

Formatter<Episode>.RegisterForAllProperties();
Console.WriteLine(episodes.ToLogString());  
// now writes: { { Id = 4234, Title = Space Madness, Characters = { SampleApp.Character, SampleApp.Character } } }, (...12 more) }

Customize the output:

Formatter<Episode>.RegisterForAllMembers(e => string.Format("Episode #{0}, Title: {1}", e.Number, e.Title));

Use The Reactive Extensions to query the log event stream...

var errors = Log.Events().Where(e => e.Subject is Exception);

...or buffer and aggregate them...

var countOf404s = logEvents
                    .Where(e => e.SubjectIs<HttpException>())
                    .Where(e => e.GetSubject<HttpException>().GetHttpCode() == 404)
                    .Buffer(TimeSpan.FromSeconds(1))
                    .Select(es => es.Count());

Objects, not strings

Its.Log works best when you pass objects rather than strings.

This works:

  Log.Write(() => "An error occurred: " + anException.ToString());

But this is better:

  Log.Write(() => anException);

Knowing the type lets you decide at a policy level how to route them, format them, or react to them. It also helps keep your log output more consistent and your logging code more terse.

Log levels - Info, Error, Warning, Verbose

While log levels can be specified, Its.Log also sets them by convention based on the type of the object you pass. For example, if the subject of a log entry is an exception:

  Log.Write(() => anException);

then the output log level will default to Error:

  { Error: CallingType = Demo | CallingMethod = Formatting3_Exception_formatting_is_very_descriptive_by_default | ExceptionId = 75743ddd-824f-4c1b-954c-09b249d00e90 | Subject = { ReflectionTypeLoadException: Types = { Demo } | LoaderExceptions = { { DataException: Message = oops! | Data = { [why?, because] } | InnerException = [null] | TargetSite = [null] | StackTrace = [null] | HelpLink = [null] | Source = [null] | HResult = -2146232032 } } | Message = Exception of type 'System.Reflection.ReflectionTypeLoadException' was thrown. | Data = {  } | InnerException = [null] | TargetSite = Void Formatting3_Exception_formatting_is_very_descriptive_by_default() | StackTrace =    at Its.Log.Instrumentation.UnitTests.Demo.Formatting3_Exception_formatting_is_very_descriptive_by_default() in c:\dev\github\Its.Log\Its.Log.UnitTests\Demo.cs:line 93 | HelpLink = [null] | Source = Its.Log.UnitTests | HResult = -2146232830 } | TimeStamp = 2014-12-18 16:23:28Z | Params = {  } }

JSON

Outputting logs as JSON rather than Its.Log's default format is simple. Here's an example using NewtonSoft.Json:

  var serializer = new JsonSerializer
                        {
                           TypeNameHandling = TypeNameHandling.All,
                           ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                        };
                      
                        Formatter<LogEntry>.Register((entry, writer) =>
                        {
                          serializer.Serialize(writer, entry);
                          writer.WriteLine();
                        });

About

Get information out of your code at runtime to send it to log files, perf counters, consoles, services, sensors. Maximum flexibility and maintainability, minimum code.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 83.3%
  • JavaScript 14.4%
  • CSS 1.1%
  • Other 1.2%