Quantcast
Channel: Nicholas Blumhardt
Viewing all 102 articles
Browse latest View live

Autofac 2.4 is here – come and “NuGet” it!

$
0
0

The latest release of the Autofac IoC container is now available on the project site and via NuGet.

ASP.NET MVC Integration Changes

The best thing in the new release, and possibly since sliced bread, is the new Autofac ASP.NET MVC integration. Gone are special interfaces on HttpApplication, gone are the Web.config file edits, static properties in the application class and multiple different extension points to configure. It couldn’t get any simpler than this.

Here’s how you create a new Autofac-enabled ASP.NET MVC3 project:

1. Create a new MVC3 web application

2. Install the Autofac.Mvc3 Package

3. Set up the Container and DependencyResolver

protected void Application_Start()
{
    var builder = new ContainerBuilder();
    builder.RegisterControllers(typeof(MvcApplication).Assembly);
    var container = builder.Build();
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

    // Other MVC setup...

That’s it!

That’s all you need to do to enable dependency injection into your controllers. There’s a lot more you can do with Autofac and ASP.NET MVC3 – I highly recommend checking out some of Alex’s recent posts on the subject.

The Autofac ASP.NET MVC integration now targets ASP.NET MVC version 3 exclusively. Don’t worry if you’re unable to move to MVC3 right away, see the “Using Autofac 2.4 with ASP.NET MVC2” below.

Complete NuGet Packages

With Autofac 2.4, the recommended way to add Autofac and its sub-features to your applications is to use the NuGet package manager. You can see some of the available packages in the screen shot at step 2 above. Just search for “Autofac” and you’re away.

In the previous Autofac NuGet package, we included the MEF and WCF integrations by default. To keep clutter away, these are now in their own packages Autofac.Mef and Autofac.Wcf respectively.

Improved Decorator Support

The new and improved decorator support makes it much easier to wire up generic decorators with Autofac, and also provides a nice boost when using decorators in other scenarios.

Removed Older Silverlight Versions from Supported Builds

To keep the maintenance burden of the project as light as practical, it is occasionally necessary to discontinue ‘official’ support for older framework versions. In Autofac 2.4, the Silverlight 3 configuration is no longer available. Users of Silverlight 3 should continue to run the Autofac 2.3 builds (bug fixes will be provided for these whenever necessary.)

Events and Interfaces to Support Tracing

Like all IoC containers, Autofac’s internals can be somewhat opaque to follow at runtime. For the occasions that diagnostics are necessary, Autofac 2.4 supports more events that can be used to trace the operations of the container. As an example, ILifetimeScope now supports LifetimeScopeBeginning, ResolveOperationBeginning and other related extension points.

It is intended that these will be used more by Autofac integration and tooling developers than in general application development.

Other Release Notes

The community has been busy as usual, and you’ll find quite a few other enhancements in this release.

  • .AsImplementedInterfaces() is now supported on non-scanning registrations
  • IDisposable is no longer considered a service by .AsImplementedInterfaces()
  • Additional eager checks for generic type/service compatibility at registration time
  • An additional .WithParameter() overload has been added, accepting predicate and value accessor like ResolvedParameter
  • Extension methods for common predicates on System.Type are now public for use with scanning, e.g. Except(t => t.IsClosedTypeOf(x))
  • MVC ExtensibleActionInvoker does not inject action method parameters by default
  • ILifetimeScope rather than IContainer is now accepted by ServiceHostBase (WCF integration)
  • AutofacInstanceContext has been made public so that current scope can be retrieved when needed (WCF integration)
  • Bug fixes and enhancements in AutofacContrib.Multitenant and AutofacContrib.Attributed
  • Dependencies upgraded e.g. Castle Core and NHibernate
  • Fixed bug #288 – resolve all failing in customised lifetime scopes when one component supports multiple interfaces

Using Autofac 2.4 with ASP.NET MVC2

If you’re still using ASP.NET MVC2 in your application, the simplest course of action is to continue using the Autofac 2.3 release series and the appropriate integration bundled with that, until you’re able to upgrade wholesale to ASP.NET MVC3.

If you would like to use Autofac 2.4 with ASP.NET MVC, there is an updated Autofac.Mvc2 NuGet package now on the feed. If you’re already using the MVC2 NuGet package, update the package and you should be fine. If not, first remove all Autofac*.dll references from your project and then install the Autofac.Mvc2 package using the “Add Library Reference” dialog.

Edit: You need to add assembly binding redirects in order for the MVC2 package to work. The appropriate redirects are specified below (you may need to update them with the current Autofac version number) or you can use the commands bundled with NuGet.

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" />
      <bindingRedirect oldVersion="2.3.2.632" newVersion="2.4.3.700" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="Autofac.Integration.Web" publicKeyToken="17863af14b0044da" />
      <bindingRedirect oldVersion="2.3.2.632" newVersion="2.4.3.700" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

Summing Up

I hope that with this release, Autofac is now easier to get and set up than ever before. It has once again been a team effort – thanks especially to the contributors and everyone who has submitted issue reports or patches.


Autofac 2.4.5 Release

$
0
0

More than a month has passed since the last patch release of Autofac 2.4, and enough has changed in trunk to warrant a new one. You can download Autofac 2.4.5 from the project site, or preferably, update your NuGet packages within Visual Studio.

In this release you’ll find:

  • Several bug fixes and improved exception messages
  • Travis and Alex have been busy making the Multi-tenant contrib package work better with the new ASP.NET MVC3 integration
  • The awkward but very useful IContainerAwareComponent introduced in 2.4 has been deprecated and morphed into a much friendlier and more useful Startable implementation
  • Autofac now consistently throws DependencyResolutionException (or a subclass) whenever fatal errors occur during composition

Please feel free to drop in and share your experiences on the discussion forum. For help with using Autofac, including new features, the preferred medium is Stack Overflow.

Designing a Short Course on IoC: Day 1

$
0
0

Today’s the start of a really exciting week for me!

I’ve been working with Inversion of Control (IoC) Containers and related technologies since picking up Castle Windsor in 2006, actively developed Autofac for much of that time, and helped shape the first release of the Managed Extensibility Framework. In that period IoC has grown and truly blossomed in the .NET world: from its “enterprise Java” roots we’ve collectively created something that plays to the unique strengths of .NET and C#. Rather than being viewed as an esoteric fringe technology, as it was just a few years ago, IoC is firmly in the .NET mainstream and is increasingly being baked into the platform itself.

Along the way there have been many difficult questions posed, and I’ve had to ask and answer my share. It can be easy to go wrong with IoC – remember the “sharp tools” analogy of the ALT.NET movement? – especially when finding the right approach to IoC in a new situation can mean finding several wrong ways first!

Last year at TechEd Australia I presented a breakout session on IoC in .NET. Though the feedback I received was positive, I was left feeling that an hour was too little time to get many of the concepts across in enough depth. So, this year courtesy of Readify I’m going to be presenting a short course on IoC from the ground, up.

The course will be a full day, with dates in May, 2011 set for:

The unifying theme will be ASP.NET MVC, but don’t be discouraged if this is not your primary platform. Much of what we cover will be independent of MVC and even of web programming in general. If you’re unfamiliar with ASP.NET MVC then it might help to brush up on that area if you want to keep up with some of the examples.

In terms of level of technical difficulty, I hope there will be something for everyone. You’ll get the most out of the day if you’re a confident .NET developer with beginner-to-intermediate experience with IoC, or if you’re an experienced user of IoC looking for broader and deeper perspectives on its use.

This week I’m preparing material for the course, and while I have a fair idea of the ground to cover, I’m interested in your ideas. I’ll be posting a progress update each day to keep you informed of where things are heading. I hope in the process I can convince you to come along, and bring your team!

Designing a Short Course on IoC: Day 2

$
0
0

So, yesterday, a lot of thinking. Today it’s time to start fleshing out some of the things we’ll need.

The course is going to be split into four sections, to match the natural division of the day by morning tea, lunch and afternoon tea:

  1. Fundamentals
  2. Effective IoC
  3. Resources and Units of Work
  4. Containers and Tooling

Session 1: Fundamentals

First up, we’ll set the theme of the day with some collaborative development. To introduce the vocabulary and concepts of IoC, we’ll write a simple IoC container in C# and integrate it into an ASP.NET MVC application. There are plenty of interesting design issues along the way that we’ll come back to in our discussion of containers and tooling.

Session 2: Effective IoC

The second session will introduce a ‘real’ IoC container. The focus will be on techniques and features that allow IoC to support large, complex applications in the real world. We’ll touch on all of the typical components of MVC web applications as we migrate from the simple container we built ourselves, but we’ll pay special attention to the integration between IoC and domain models because of the challenges and opportunities they present.

Session 3: Resources and Units of Work

Lifetime, AKA “resource management” can be the toughest aspect of IoC to master. We’ll take an excursion outside of the comfort of the web tier, to develop a thorough understanding of the issues involved and their solutions.

Although it is far from being ready for prime time, Whitebox will be a great way to explore the runtime behaviour of lifetime scenarios, so sometime over the coming week I’ll look at filling remaining gaps there.

Session 4: Containers and Tooling

To round out the day, we’ll use the last session to take a leisurely tour of the sights, sounds and smells of the .NET IoC ecosystem. Choosing an IoC container can be tricky business, especially when the easiest metrics to grasp, for example throughput performance, are often misleading or irrelevant. In addition to looking at some of the popular offerings and their relative strengths, I think this is where a discussion of MEF and its role will fit in nicely.

Session 4 will also give us an opportunity to examine debugging and diagnostics issues.

Today

So, what do you think?

Today’s focus for me will be to take a first cut at building the example application. I’m going to leave the ‘simple container’ design task for the event, so that we can truly do it on the fly! I want the day to be heavy on code and light on slides, so dressing up a slide deck with some guiding material will wait for later in the week.

Choosing what kind of application to build is tricky. I want attendees to be able to take something away, ideally a sample that isn’t too far from production readiness. In that respect, simpler will be better, though it can be hard to get enough breadth out of something like a ‘to-do’ or ‘timesheeting’ application. There’s some high-quality code on the web that might be reused for this purpose (e.g. FunnelWeb) so building something that mimics an existing open source application has advantages.

I’ll update you tomorrow on where things land.

Designing a Short Course on IoC: Day 3

$
0
0

Is it just me, or am I slowing down? Yesterday was a busy day of programming, but there’s still a long way to go before this application is going to cut the mustard as an example for the course.

In the end, I went with the idea of a timesheeting application. Simple material keeps out of the way, and to be honest, there is so little logic or fancy presentation in this app that it could be changed from timesheets to another example in a relatively short space of time if need be.

Up and running, we have:

  • A basic MVC3 app layout
  • IoC set up to create controllers
  • Data access with NHibernate
  • Transaction management integrated with MVC
  • Logging with the venerable log4net
  • A skeleton for ‘pick-me-up’ domain events

It is the last item that I’ll be working on in depth today. ‘Pick-me-up’ domain events integrate domain models with external services in a way that plays better with IoC than the thread-static DomainEvents.Raise() pattern commonly seen elsewhere.

Dispatching events to handlers is also a good example of the ‘generic handler’ pattern that’s very widely used, and registering handlers will provide some further examples for convention-based/scanning registration.

To complete the day I’m aiming to polish up the last details of the basic MVC site (for example, error handling) and bed down an example of processing work in a background process to use in the “Resources and Units of Work” session. That leaves tomorrow and Friday for more detailed work on slides, some code samples for the “Containers” session, and some reworking of the example to fit into the flow of the course.

Designing a Short Course on IoC: Day 4

$
0
0

A brief update today. Yesterday I think I covered everything I need to as far as demo app material goes, but tidying up, styling and (egads!) unit testing will have to wait for a rainy day.

I spent a fair bit of time yesterday looking at how I can use Whitebox to give an x-ray view of the composition process as the application is built. The information it provides is great – often revealing little issues that would otherwise go unnoticed – but the usability leaves me deeply unsatisfied. Still, it is a start, and by chipping away at it things are improving. Just having a simple view of component details is an improvement:

Whitebox component detail view

Today I’m concentrating on the flow of the day. I still have some questions to answer around the introductory session – how theoretical do we want to get? Does it make sense to examine the problems of composition in OO languages, or can we take that as a given for people interested in learning more about IoC? My tendency in the past would have been to go into depth about this, but by starting with “you’re going to use IoC – here’s how to do it” I think the practical side of the Dev Day will be emphasised.

Designing a Short Course on IoC: Day 5

$
0
0

The last of this curious series of journal entries today. As I mentioned previously, today is going to be about finalising the end-to-end flow of topics.

I think the first session – Fundamentals – is finished. I’m really excited and even a little nervous about putting together a new container on the fly! As a way of bedding down the terminology, mechanics and challenges, I think it is going to be great.

The layout for the remainder of the day still needs work, so I’d better get stuck into it! Those who’ve already signed up, I’ll see you soon – if you haven’t put your name down yet for either Brisbane, Sydney or Melbourne, this is probably the last reminder you’ll get from me.

Autofac 2.5 Released

$
0
0

Autofac 2.5 is now available on the project site and via NuGet. The new version includes a range of great contributions.

After incubation as an external project, Windows Phone 7 now joins ranks of officially-supported targets (just install the Autofac package via NuGet and you’re up and running!) For some tips on getting started see Brendan Kowitz’s notes.

The new release is highly-compatible with Autofac 2.4 (best used with the VS2010 compiler when targeting .NET 3.5.)

Included changes are:

  • Issue 329 – types are filtered by compatibilty before invoking key mapping functions when scanning assemblies
  • RegisterAssemblyTypes(...).WithMetadataFrom<T>() simplifies extraction of metadata from attribute properties
  • Module.ThisAssembly simplifies implementation of modules that scan their own assembly
  • Issue 333 – enable RegisterAssemblyTypes(...).PreserveExistingDefaults()
  • Windows Phone 7 and 7.1 support
  • Issue 312 – allow ContainerBuilder.Update() on the ComponentRegistry of any
    ILifetimeScope without affecting the parent scope
  • Issue 327 – allow autowiring of enum properties
  • Issue 319 – support list and dictionary literals in XML configuration
  • Issue 330 – corrections to generic type constraint checking where the constraint type is an interface
  • Issue 331 – fix build warnings and runtime issues using Moq integration
  • Introduced ContainerBuildOptions to control invocation of IStartable.Start() under unit tests
  • Container.Empty is now a property rather than a field (protection from inadvertent updates
  • Removed broken/obsolete examples from source tree (better examples are available elsewhere online)
  • Host configuration features for AutofacHostFactory in WCF integration
  • ComponentRegistry.Register() is now safe for use under multiple threads
  • Issue 227 – breaking change additional options (and enum rather than boolean parameter) for PropertiesAutowired()
  • Additional web abstractions are now registered by the MVC3 AutofacWebTypesModule
  • Issue 311 – fixed potential lifetime issues when injecting into MVC filter attributes
  • Tightened up behavior when correct constructor to use under reflection activator is ambiguous (now throws rather than choosing nondeterministically)
  • Issue 309 – fixed some issues in TypeExtensions.IsClosedTypeOf()
  • Improved exception messages

Many thanks to the Autofac project team and collaborators across the web for making this release happen!


Convention-based part registration available in a new MEF preview!

$
0
0

There are many, many similarities between IoC-for-decoupling (as we know and love in Autofac) and IoC-for-extensibility as is implemented by MEF.

One thing that stuck out in the beginning for the MEF project members with IoC backgrounds, was the verbosity of using [Import] and [Export] attributes to describe parts, instead of the much more terse convention-driven approach used by IoC containers.

Over time, most of us grew to appreciate the role that the attributed programming model played in creating an unambiguous, decentralized configuration mechanism for plug-ins.

What the we also found was that applications using MEF for extensibility would also use it for internal composition, a-la IoC. In the much more controlled context of the host application, the lighter, more direct, convention-driven configuration model is compelling. DRY is one of the most important principles for building maintainable software, so techniques that eliminate repetition are very valuable.

It should be no surprise then, that the latest release of MEF (that I’ve only recently had any involvement in) comes with a nifty little model for defining parts by convention. The syntax should be familiar if you’re used to this kind of API:

var builder = new RegistrationBuilder();
builder.ForTypesDerivedFrom<Controller>()
    .Export()
    .SetCreationPolicy(CreationPolicy.NonShared);

When wired up to a MEF catalog, these simple conventions will read a part like:

public class HomeController :  Controller
{
    public HomeController(/* Dependencies here */) {}
    public ActionResult Index() {}
}

As:

[Export, PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController :  Controller
{
    [ImportingConstructor]
    public HomeController(/* Dependencies here */) {}
    public ActionResult Index() {}
}

RegistrationBuilder has more than a few tricks up its sleeve, and we expect to write a lot more about it on the BCL team blog in the coming weeks. For now, you can read about the new release, or even better, download the preview source and binaries from CodePlex.

Autofac update 2.6.1 published

$
0
0

The eagle-eyed may have already spotted Autofac 2.6.1 lurking in the NuGet feed.

The last release, the venerable 2.5.2, served us very well (maturity is a feature!) and this release adds a little more polish, without any known breaking changes.

  • The ASP.NET MVC integration package gets a bug fix for recursive views, UrlHelper and RequestContext registered by AutofacWebTypesModule, and an explicit method for registering model binders.
  • The WCF integration package gets much improved support for services with InstanceContextMode.Single.
  • A new helper InstancePerOwned<T>() makes it easier to control lifetime when using Owned<T>.
  • Autofac can now be used with .NET Portable Class Libraries (download only on the project site. (The Windows Phone 7 build now uses this configuration too.)
  • Autofac.dll is now clear of any issues found by SecAnnotate.exe.

Extra thanks to Alex and Travis for the majority of these improvements.

Serilog

$
0
0

Serilog

Serilog is a new logging library for .NET that combines the best of “traditional” and “structured” approaches.

Instrumentation vs. analysis: different goals, different requirements

Application logs are rich with analysable data, but forces at play during the early phases of application development encourage trade-offs that limit the practicality of consuming them later on.

In their primary role as instrumentation, log entries must be effortless to write and comfortable to read, thus text-message-based logging formats remain more popular than schematised approaches today.

Event analysis later in the application lifecyle then tends to rely on fitting a more structured event stream to the application, or parsing log messages using regular expressions to recover fields from the event.

Serilog avoids this compromise by rethinking how log messages are processed.

Simple, familiar instrumentation

On the surface, Serilog will be familiar to users of nearly any .NET logging library:

Log.Logger = new LoggerConfiguration()
    .WithFileSink("applog.txt")
    .CreateLogger();

Log.Information("Hello, world!");

This example writes a line like the following to applog.txt.

2013-03-29 20:46:12 [Information] Hello, world!

Most of the bread-and-butter features you’d expect from a logging library are supported or planned.

Message parameters as structured data

The significant difference is in how message parameters are captured. While traditional logging libraries render messages into strings before processing, Serilog defers rendering and captures the parameters separately from the message template:

SerilogLog

The log event, rather than being represented by a textual message, is captured as a MessageTemplate along with two properties, SensorInput and Time.

Later in processing the message can be rendered as text for an output mechanism like a log file. Or, the structured event describing the log message may be stored as-is in a NoSQL database like CouchDB or RavenDB. Writing to a document data store is where the strength of Serilog kicks in.

In this example, the @ in front of the SensorInput property name instructs Serilog to preserve the structure of the object, breaking it down into Lat and Long properties (for some examples showing why this is great see this discussion). The resulting document embeds the structure, rather than a string representation:

Couch

This is the core value proposition of the Serilog – build your application with all the advantages of simple text based logging, then seamlessly enable structured log analysis later on by adding a capable data store.

The project

Is Serilog ready for prime time? It depends on your willingness to tinker. The project is coming togrether, but there are numerous rough edges and nice-to-have features missing. Notably, there’s no XML configuration story out of the box. If you have a chance to kick the tyres I’d love to hear what you think.

Is yet-another-logging-library just a serious case of “not invented here”? I think that the log structure problem is yet to be completely solved, and that it needs to be. If you feel the same way, please get in touch – all help appreciated!

Changes in Serilog 0.2

$
0
0

Serilog

Thanks for all the feedback on Serilog, keep it coming! Version 0.2 is now on NuGet and introduces a couple of noticeable changes.

Phone and tablet support

The core of Serilog is now portable across .NET 4.5, Windows 8 and Windows Phone 8.

Serilog on WP8

The latter two platforms only include one ‘sink’ out of the box, that writes to a System.IO.TextWriter. I’d like to set up sinks for local storage on those platforms, if you’re knowledgeable (or brave!) and interested in helping out.

Revised configuration API

The first version of LoggerConfiguration used flat method chaining to drive the configuration process.

Log.Logger = new LoggerConfiguration()
    .MinimumLevel(LogEventLevel.Debug)
    .WithConsoleSink()
    .CreateLogger();

The number of methods on LoggerConfiguration became unwieldy quickly. On typing ‘.’, a user would be presented with everything including .WithKitchenSink().

0.2 aims at a cleaner IntelliSense experience by grouping options:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .CreateLogger();

In addition to MinimumLevel and WriteTo, you can configure Serilog to Filter log events based on arbitrary rules, Enrich log events with properties calculated at runtime, and Destructure complex parameter types for serialization various ways.

There are advantages and disadvantages to any API, for the moment I’m happy with this direction but open to suggestions (give it a try!) Thanks @droyad, @uglybugger and @turtlator for the motivation and first round of feedback.

Control over ‘destructuring’

The new version survives the serialization of circular object graphs and offers more control over the serialization process. For example, only a selection of properties from HttpRequestMessage might be included in a log event:

Log.Logger = new LoggerConfiguration()
    .Destructure.ByTransforming<HttpRequestMessage>(
        m => new { Uri = m.RequestUri.AbsoluteUri,
                   m.Method,
                   m.Headers })
    ...

Log.Debug("Received {@Message}", httpRequestMessage);

Thanks @sandcastle for putting the momentum behind this.

(Quick note on terminology, Serilog breaks down objects in two phases; destructuring controls the tree created out of regular .NET objects, while serialization is specific to the sink being used, for example converting that tree structure into JSON.)

What’s next?

Use, feedback, documentation, performance profiling and tuning, more sinks.

A console sink with property colouring

$
0
0

The coloured console ‘appender’ is one of my favourites in log4net, so high on the list for inclusion in Serilog.

Smart property highlighting makes the result quite interesting:

ColoredConsoleSinkDemo

You can use it on the full .NET Framework using the out-of-the-box Serilog 0.2.8 package.

Log.Logger = new LoggerConfiguration()
    .WriteTo.ColoredConsole()
    .CreateLogger();

Simple at this stage, but fun! What do you think?

A discussion forum for Serilog

Serilog.Sinks.Log4Net

$
0
0

Would you like to try Serilog, but have existing log4net infrastructure? On the journey to “1.0” Serilog needs your experiences and feedback. The Serilog.Sinks.Log4Net package may provide just what you need to kick the tyres of Serilog without turning your existing code and libraries upside-down.

This package lets you pipe structured log events off to suitable storage, while text representations are merged into log4net to be written to a consolidated flat log file.

Serilog.Sinks.Log4Net

To install the package:

PM> Install-Package Serilog.Sinks.Log4Net

Your existing log4net configuration remains unchanged, e.g. using the XmlConfigurator:

XmlConfigurator.Configure();

In your Serilog configuration, include both your choice of structured event storage (in this example the RavenDB sink), and the log4net sink:

Log.Logger = new LoggerConfiguration()
    .WriteTo.RavenDB(documentStore)
    .WriteTo.Log4Net()
    .CreateLogger();

Events written to a log4net logger will travel through the log4net pipeline only. Events written to Serilog will be emitted to RavenDB with full property structure intact, and to the log4net pipeline as regular text-based messages.

The sink is very simple, preserving log levels (Information, Warning, Error and so on) as well as the source class name if ForContext<TSource>() is used.

A running example can be found in the Serilog GitHub repo.


Stupidly easy log queries with Serilog and RavenDB

$
0
0

Have you ever been frustrated with the tedious process of answering even simple questions using regular expressions over log file data?

In one of the early Serilog demos we wrote an event like:

20:08:43.232 [Information] Processed { Lat: 25, Long: 134.5 } in 34ms

Given this log data, for example,

Which sensor inputs took more than 100ms to process?

Regular expression-based searching is great for matching textual patterns, but not so much fun when richer data types (if you can call numbers “rich”) are involved.

By combining Serilog with RavenDB, a commercial document database for .NET, the answer can be derived as simply as issuing the query:

MessageTemplate: "Processed {@SensorInput}*" AND Properties.Elapsed_Range: [Ix100 TO NULL]

This query’s very specific about a) the event type, and b) the numeric range of the Elapsed property. Both of these aspects are tricky to replicate using traditional text-based logs.

Let’s walk through this scenario step-by-step.

Creating a database in RavenDB

If you’ve just downloaded RavenDB you’ll need to start a server. For quick and dirty experiments, the Start.cmd script in the root of the RavenDB zip file will run a local server bound to HTTP port 8080.

The Raven Studio web UI is the first place to go. I’ve created a database called Logs.

logs-database

There aren’t any documents in there yet; we’ll write those through Serilog’s RavenDB sink.

Configuring the RavenDB Sink

The Serilog.Sinks.RavenDB package has everything you need for getting log data into RavenDB.

PM> Install-Package Serilog.Sinks.RavenDB

In your application startup code (Main(), Application_Start() etc.) create a DocumentStore object describing the location of your logs database.

var documentStore = new DocumentStore
{
    Url = "http://localhost:8080",
    DefaultDatabase = "Logs"
};

Configure Serilog using the WriteTo.RavenDB() method.

Log.Logger = new LoggerConfiguration()
    .WriteTo.ColoredConsole()
    .WriteTo.RavenDB(documentStore)
    .CreateLogger();

That’s it! You’re ready to write some log events.

Writing to the log

If you’ve never used Serilog, there are only a couple of things you need to know up-front.

var sensorInput = new Position { Lat = 25, Long = 134.5 };
var elapsedMs = 34;
Log.Information("Processed {@SensorInput} in {Elapsed} ms", sensorInput, elapsedMs);

First, log methods use named rather than positional arguments in format strings. SensorInput and Elapsed are the property names given to the sensorInput and elapsedMs values, respectively.

Second, to capture the structure of a log event property (instead of just capturing it with ToString()) prepend @ to the property name. This is a safeguard against accidentally serializing large object graphs. An article in the documentation has more detail on writing structured data.

After writing a few events, they can be seen in the Raven Studio interface.

raven-showing-logs

If we peek into one of the log events, the preserved structure of the event data can be seen.

{
  "Timestamp": "2013-06-18T17:49:47.7947070+10:00",
  "MessageTemplate": "Processed {@SensorInput} in {Elapsed:000} ms",
  "Level": "Information",
  "Exception": null,
  "RenderedMessage": "Processed Position { Lat: 24.7, Long: 132.2 } in 037 ms",
  "Properties": {
    "SensorInput": {
      "Lat": 24.7,
      "Long": 132.2,
      "$typeTag": "Position"
    },
    "Elapsed": 37,
    "ThreadId": 9,
    "MachineName": "NBLUMHARDT-RMBP"
  }
}

RavenDB Dynamic Queries

The commonly-used query API on RavenDB is Linq, but the lesser-known Lucene syntax is apparently used as RavenDB’s internal representation.

Documentation is a little sparse but the syntax is quite intuitive after a few attempts. Jumping into the Indexes > Dynamic Query screen, our query finds the events we’re after.

raven-query

(I’ve had to drop the time threshold to 10ms to pick anything up in my data set.)

Concluding thoughts

Among the ‘NoSQL’ data stores I’ve tried so far as back-ends for Serilog, RavenDB seems to be a reasonably good fit for the job. What excites me most about the potential of Serilog is the ability to go ‘beyond grep’ and deal with log data in more useful types like numbers, dates and so-on. Through RavenDB we’ve been able to home in on a specific event type and a numeric range, and hardly broke a sweat.

Lucene itself is also very text-oriented, great for classic log searching scenarios. I’m not sure how much of that is surfaced by RavenDB, definitely something to explore.

Caveats

One thing to watch – the RavenDB sink writes events periodically, in batches on a background thread. In normal circumstances, Serilog will flush the current batch on shut-down of the AppDomain, so events will rarely be lost, if ever. Terminating the app “hard” by stopping the debugger may prevent some events from being written back to the database. Using remote sinks like RavenDB in conjunction with a local log file is recommended, anyway.

Also worth pointing out is that RavenDB is a sophisticated piece of software with specific capabilities and requirements. Dumping in and querying large volumes of log data will require some up-front planning and performance analysis that I haven’t done. If you’re using RavenDB in this way today I’d love to know more about the experience.

Acknowledgements

Thanks to Nick Van Eeckhout for figuring out and contributing the RavenDB sink!

Serilog sink for Glimpse

$
0
0

Glimpse is a plugin for ASP.NET that renders server-side request information directly in the browser, in much the same way as Firebug or Google Chrome Developer Tools show client-side information.

With Glimpse and the Serilog Glimpse Sink installed in an ASP.NET project:

PM> Install-Package Glimpse.AspNet
PM> Install-Package Serilog.Sinks.Glimpse

And configured in Global.asax:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Glimpse()
    .CreateLogger();

Log messages written to Serilog will appear in a new Serilog tab in the Glimpse UI:

Glimpse integration for Serilog

Serilog and Glimpse are a great match – when structured objects are used in Serilog events, Glimpse can render them in a nice expandable tree format.

Thanks to the awesome Robert Wagner for kicking off the Glimpse Sink.

More fresh Serilog updates…

WriteTo.Observers()

This tiny new sink in the core Serilog package supports processing Serilog events using Reactive Extensions for .NET (Rx).

var log = new LoggerConfiguration()
    .WriteTo.Observers(events => events
        .Do(evt => { Console.WriteLine(evt.Timestamp); })
        .Subscribe())
    .CreateLogger();

Rx enables some very interesting event processing scenarios on top of Serilog, which I hope to write more about in the future.

Serilog.Extras.Topshelf

A logging integration for the Topshelf Windows service hosting framework. To get started, first install the package:

PM> Install-Package Serilog.Extras.Topshelf

Before running the Topshelf host factory, set up the logger:

HostLogger.UseLogger(new SerilogHostLoggerConfigurator());

Serilog.Web renamed to Serilog.Extras.Web

The Serilog.Web package, providing some helpers for use with ASP.NET, has been renamed Serilog.Extras.Web – as in the Autofac project, we’re going to use the Extras designation to keep clear what is part of the core Serilog package, and what is provided and supported as a best-effort contribution.

Serilog gets a “diagnostic context”

$
0
0

Serilog 0.9.2 includes a new feature that I’ve been holding off on committing to for some time. Those familiar with the NDC (“Nested Diagnostic Context”) in log4net and similar features elsewhere will recognise the basic idea behind LogContext:

log.Information("No contextual properties");

using (LogContext.PushProperty("A", 1))
{
    log.Information("Carries property A = 1");

    using (LogContext.PushProperty("A", 2))
    using (LogContext.PushProperty("B", 1))
    {
        log.Information("Carries A = 2 and B = 1");
    }

    log.Information("Carries property A = 1, again");
}

An application can push properties onto the context to tag events associated with some unit of work, perhaps identifying a specific transaction, customer, message and so-on. The properties can later be used to find messages of interest.

Serilog is all about easier filtering and correlation of events, so, why hold off on adding this feature until now? The reason is that for flexibility and reliability, Serilog’s logging pipeline is essentially stateless and is completely free of static or ambient state. Making all loggers dependent on a global, shared context stack seemed like the wrong thing to do.

Fortunately, it turned out to be easy to reconcile this feature with Serilog’s goals. To use properties from the context, loggers opt-in via a simple configuration method:

var log = new LoggerConfiguration()
    .Enrich.FromLogContext()
    // ...

This way, only loggers that explicitly take interest in the LogContext are affected by it.

Why is this supported only on the full .NET 4.5 framework?

A useful diagnostic context, in today’s .NET, has to play nicely with async/await. Properties pushed onto the stack need to be preserved when an awaited call completes, as below:

async Task Handle(Message message)
{
    using (LogContext.PushProperty("MessageId", message.Id))
    {
        var items = await LoadDataAsync();
       
        Log.Information("Loaded {ItemCount} items", items.Count);
    }
}

In this example, the thread that executes the Log.Information() call may be different from the one that pushed the MessageId property on the stack, because of the awaited call.

Because the thread that resumes execution after awaiting may be a different one from the one that pushed the property onto the stack, [ThreadStatic] variables aren’t suitable for implementing a diagnostic context anymore. Only .NET 4.5 has an async-aware CallContext.LogicalGetData() suitable for this purpose. Stephen Cleary has written a useful article with more discussion of the topic.

Serilog hits 1.0

$
0
0

Serilog

Yesterday the core Serilog package quietly ticked over to become our “1.0” release. If you’ve never tried Serilog, now’s a great time to get started. To find out what it is all about, visit our documentation.

A huge effort has gone into our “serializing logger” over most of this year – I set out hoping to thank everyone involved personally, but quickly found that writing the list is a project in itself. Instead I’ll have to be content with pointing to the awesome contributions, extensions and integrations and helpful issue reports we’ve clocked up. Thanks also to everyone sharing in the vision of what Serilog can be – the ideas and encouragement have carried it a long way!

The project supports a lot of extensions; storage options like Azure Table Storage, CouchDB, MongoDB, RavenDB; broadcasting via SignalR and visualization with Glimpse. These are all in active development and use, but I’m waiting to collect more feedback on each individual package’s maturity before stamping the 1.0 version number on them.

Now seems like a good time to quickly mention Seq, a side project I have in the works to scratch a big itch for me: finding a simple way to capture, filter, correlate and consume structured events from Serilog. I’m intending a small preview in the next few weeks – if you’re using Serilog and interested in providing early feedback please contact me directly.

Lastly, Brisbaneites: find out more about Serilog this Tuesday, 15th October at the BNE.NET User Group.

Happy logging!

…and then 1.1

$
0
0

Serilog has been ticking along since our 1.0 release six weeks ago. We’ve added a few new faces to our Contributors page since then, including

We’ve had plenty of help keeping the project healthy with smaller pull requests, discussions and issue reports.

The current version on NuGet, now stamped ’1.1′, rolls up a few things that are worth a brief mention here too:

.NET 4.0 support

In case you missed the somewhat understated mention on Twitter, the Serilog package now adds support for .NET 4.0. This includes the logging pipeline and all of the built-in sinks (file, console, …). As of writing, some binary compatibility constraints mean that most of the “Extras” and add-on sinks will need to be modified or recompiled to use on .NET 4.0, so drop a line to the mailing list if there’s anything particular you need help with.

To get going with Serilog on .NET 4 all you need to run is:

PM> Install-Package Serilog

Improved byte[] handling

In Serilog 1.0, byte arrays are treated as scalar values. This is because many data stores have built-in support for simple binary values.

byte[] packet = ReadPacket();
Log.Information("Received {Packet}", packet);

This code would result in the contents of packet being passed through and serialized by any configured sinks that supported it (e.g. any of the JSON-based sinks).

Two problems came out of this:

  1. Big binaries could cause a nasty payload surprise
  2. Serilog’s asynchronous logging pipeline requires that scalar values are immutable, which byte arrays aren’t

1.1 makes a different set of compromises that will be a bit more friendly.

Byte arrays smaller than a kilobyte will continue to be passed through as scalar values, but internally we make a copy at the time of logging to protect from later mutations. There are a few use cases where small chunks of binary data are useful in logs – hopefully less than 1 kb is about the sweet spot for those.

Byte arrays larger than 1 kilobyte are now passed through the pipeline as descriptive strings, including the first 16 bytes in hex and the overall length. A large binary will look like:

"E67867EFA578A000AA78EF4D34AA3412... (4672096 bytes)"

Much more fun than 4 GB of base-64 encoded text in JSON. It is still possible to serialize arbitrarily-large binaries with Serilog using a custom type and destructuring policy. If you’re interested in doing this please mail the discussion list.

As part of this refresh, handling of Nullables and Delegates were also improved.

Diagnostic help

One tiny but crucial improvement, the Serilog package now includes PDBs for the Serilog.dll and Serilog.FullNetFx.dll binaries, increasing our chances of getting meaningful stack traces in error reports.

Along with this the SelfLog class, used for debugging Serilog itself, now flushes its output after writes making use with file streams easier.

That’s it for today, happy (Seri-)logging :)

Viewing all 102 articles
Browse latest View live