Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Logging and profiling

Samuel Debruyn edited this page Dec 24, 2015 · 6 revisions

To analyze performance and problems with Cirqus, you can use resp. profiling and logging.

Logging

You can obtain a decent amount of information using Cirqus' logging facilities. Built-in loggers can log to the Console or to Debug (output window) and you can also set up MongoDB, Serilog or NLog for logging. The first two require you to define the minimum logging level of actions that have to be logged. It's quite easy, however, to create your own logger.

Configuration

The logger is configured in the command processor and is used globally throughout the application.

var processor = CommandProcessor.With().....Logging(conf =>
{
    conf.UseConsole(Logger.Level.Info);
}).Create();

Logging levels

Debug

Debug logging is used for fairly detailed and verbose logging, like e.g. logging what's going on inside loops, etc. You will often turn OFF debug logging in production.

Info

Info logging is used for useful information, not too verbose, and is meant to be turned on also for production environments.

Warn

Warn logging is used to notify you of things that could potentially be an error, like e.g. an exception while trying to load events to dispatch to views, etc. It will be used in cases where the system can recover if the error is transient in nature.

Error

Error logging is used in rare cases where some really unexpected condition has happened, like e.g. a background timer fired and wanted to trim an in-mem cache but then an exception occurred (which will most likely be some kind of logic error).

Custom logger

To create your own logger, create a class that implements Logger and another class that implements CirqusLoggerFactory.

This is the factory for the DebugLogger:

public class DebugLoggerFactory: CirqusLoggerFactory
{
    readonly Logger.Level _minLevel;

    public DebugLoggerFactory(Logger.Level minLevel = Logger.Level.Debug)
    {
        _minLevel = minLevel;
    }

    public override Logger GetLogger(Type ownerType)
    {
        return new DebugLogger(ownerType, _minLevel);
    }
}

As you can see, there isn't much to it. The Logger itself are just a few methods per log level.

To configure the custom logger in the command processor, use the Use method.

var processor = CommandProcessor.With()....Logging(conf =>
    {
        conf.Use(new MyCustomLoggerFactory(Logger.Level.Info))
    }).Create();

Profiling

Commands

Profiling lets you analyze how fast Cirqus is able to hydrate an aggregate root. (So how long it takes to replay all events for an aggregate root on an empty/new aggregate root object.)

You can configure a profiler with the Options configuration in the Command Processor.

var processor = CommandProcessor.With()....Options(opt =>
{
    opt.AddProfiler(new MyProfiler());
})).Create();

The MyProfiler class in the code above should be an implementation of the IProfiler interface. It contains a few methods with types, timespans and identifiers so you can easily log how long some actions took.

Currently, you can record data about the following operations:

  • Hydrating an aggregate root
  • Saving a batch events
  • Checking if an aggregate root with a given ID exists
  • Dispatching an event
  • Retrieving the next global sequence number

Event dispatchers

Besides profiling the working of aggregate roots and commands, you can also profile the dispatching of events in an Event dispatcher.

he interface to implement is IViewManagerProfiler. This interface contains a single method with a view manager, an event and a timespan that lets you record how long it took to process an event in a view manager.

To configure the profiler, use the fluent configuration API on the event dispatcher.

CommandProcessor.With()
    .(...)
    .EventDispatcher(e => {
        e.UseViewManagerEventDispatcher(views).WithProfiler(new MyProfiler());
    })
    .Create();

The method above is only available on the built-in event dispatchers.

Default profiler

Cirqus comes with a default profiler for event dispatchers. It keeps track of all the time spent and the operations per event and per view manager. You can retrieve the statistics by calling .GetStats() on that profiler. You need to register the profiler yourself like in the example above. It's called StandardViewManagerProfiler.