Blog Post

Couchbase .NET SDK 2.0 Development Series: Logging

Jeff Morris of Couchbase Published

*Note: source can be found here.

While perhaps one of the more drab features of an SDK, logging and instrumentation is probably one of the most valuable in terms of finding and isolating issues and ensuring that your application is running as expected. In this post, I’ll discuss how the new Couchbase SDK 2.0 handles logging, which frameworks it supports and how to get up and running with logging using the new client.

We All Have Something in Common…

We’ll when we all support Apache Common.Logging we do! Jokes aside, the new client supports a variety of logging implementations via this common interface, so your options for a logging provider include:

As long as the logging implementation you chose supports the Common.Logging interface, you’re good to go!

Getting Starting

The client ships with the dependencies for Common.Logging already defined and are either included in the zip files containing the binaries or managed by Nuget packaging.  To enable logging to the default System.Console, you simply add the following configuration to your App.Config or Web.Config:

<configuration>
  <configSections>
    <sectionGroup name="common">
      <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
    </sectionGroup>
  </configSections>

  <common>
    <logging>
      <factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
        <arg key="level" value="DEBUG" />
        <arg key="showLogName" value="true" />
        <arg key="showDataTime" value="true" />
        <arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" />
      </factoryAdapter>
    </logging>
  </common>
</configuration>

In the snippet above, we first defined a new configuration section to hold the Logging.Common configuration. Then we added the configuration element and defined a factory adapter for the System.Console and a little formatting. That’s it! If you run the application you will see that the all the logging information is directed to stdout.

Logging to stdout is useful for Unit Test projects and the like, but our not suited for production deployments. In this case, you are better off using a factory appender like log4net or NLog and writing the results to a file or perhaps a database (hmm, what about back into Couchbase as an Operational Data Store?).

Using the Log4Net Adapter

So, that shows you how to use the default ConsoleOutLoggerFactoryAdapter to write to stdout, but what about using another logging framework like Log4Net? Well, that’s pretty easy to do assuming you have referenced the dependency to Log4Net in your project:

<configuration>
  <configSections>
    <sectionGroup name="common">
      <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
    </sectionGroup>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

  <common>
    <logging>
      <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net">
        <arg key="configType" value="INLINE" />
      </factoryAdapter>
    </logging>
  </common>
 
  <log4net>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
    <param name="File" value="C:\temp\log.txt" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
    </layout>
    </appender>
    <root>
      <level value="INFO" />
      <appender-ref ref="FileAppender" />
    </root>
  </log4net>
</configuration>

Here we are creating the usual Common.Logging section and configuration element and then specifying the Log4NetLoggerFactoryAdapter. We are also specifying a log4net section and configuration element for a file appender and adding the path to the file to write to. This is more like a configuration that you would use in a production environment. Note that you must have references to the following Nuget packages in your packages.config file:

<packages>
  <package id="Common.Logging" version="2.0.0" targetFramework="net45" />
  <package id="Common.Logging.Log4Net" version="2.0.1" targetFramework="net45" />
  <package id="log4net" version="1.2.10" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.1" targetFramework="net45" />
</packages>

In most cases you’re would be using Nuget to manage this file, but using this file allows you to “short cut” the Nuget package manager dialog.

A Quick Note about Log Levels

The client uses the following standard log levels:

  • Trace
  • Debug
  • Error
  • Fatal
  • Warn
  • Info

In general, Debug is used throughout to trace the general execution of an operation. Info is used to trace the configuration management (cluster topology changes, etc) portion of the client and all caught (and possibly re-thrown) exceptions are logged as Error.