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.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.nuget
Its.Log.UnitTests
Its.Log.js.UnitTests
Its.Log.js
Its.Log
Recipes.Tests
Recipes
.gitattributes
.gitignore
Its.Log.sln
NuGet.Config
ProductInfo.cs
README.md
appveyor.yml
license.txt

README.md

Its.Log

Join the chat at https://gitter.im/jonsequitur/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();
                        });
You can’t perform that action at this time.