Collecting Information and Logging in the .NET SDK with Couchbase Server

The logging infrastructure in the .NET SDK depends on which .NET runtime you’re targerting. For applications that are targeting .NET Framework 4.5.2+ the SDK uses the Apache Common Infrastructure Libraries and applications that are targeting .NET Core the SDK uses Microsoft.Extensions.Logging.

Logging in applications targeting .NET Framework 4.5.2+

The Apache Common Infrstucture libraries provides a common interface for logging adapters. The SDK currently uses version 3.4.1 of Common.Logging for versions Couchbase .NET SDK v2.6.0 and greater.

In order to use logging within the SDK, you need to reference the packages for the adapter you want to use. There are adapters available for all the major logging implementations. More information and a list of available adapters is available on the project website here.

The recommended dependencies for Couchbase .NET SDK v2.6.0 greater are:

  • Log4Net v2.07

  • Common.Logging 3.4.1

  • Common.Logging.Core 3.4.1

  • Common.Logging.Log4Net207 v3.4.1

The following steps describe the process for using the Log4Net Adapter with the SDK:

  1. Using the NuGet Package Manager in Visual Studio, include the following package in your project: Common.Logging.Log4Net207 common logging log4net207

  2. In your App.Config or Web.Config, add the following elements between the <configuration> and </configuration> tags so that your configuration looks like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <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.Log4Net207">
            <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="DEBUG" />
            <appender-ref ref="FileAppender" />
        </root>
      </log4net>
    
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
      </startup>
    </configuration>
    This example creates a FileAppender. There’s a wide variety of possible appenders and configuration options you can customize to your liking. For more information regarding customizing your configuration, check out the Log4Net documentation.

Logging in applications targeting .NET Core

As part of the new .NET Core runtime, Microsoft have added a new abstraction interface. This is conceptually very similar to the Common.Logging, however it also has additional support built in for ASP.NET 5 and other Microsoft libraries.

To get logging to work within the .NET SDK, you need will need to add a package for the adapter to connect with. There are a number of logging implementations based on Microsoft.Extensions.Logging that can be viewed here. There are also some basic Microsoft provided adapters such as Debug, Console and EventLog.

Using NLog in a Console Application

The following instructions show you how to get up and running with NLog in a Console Application with the Couchbase .NET SDK.

Dependencies:

  • CouchbaseNetClient v2.6.0 or greater

  • NLog.Extensions.Logging 1.2.0

1. Add the dependencies above using the NuGet Package Manager: logging nuget nlog

2. Copy the following nlog.config file into your project and set "Copy to output directory" to "Copy always" in Visual Studio:

<?xml version="1.0" encoding="utf-8" ?>
    <!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        autoReload="true"
        internalLogFile="c:\temp\console-example-internal.log"
        internalLogLevel="Info" >

        <!-- the targets to write to -->
        <targets>
        <!-- write logs to file -->
        <target xsi:type="File" name="target1" fileName="c:\temp\console-example.log"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
        <target xsi:type="Console" name="target2"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />

        </targets>

        <!-- rules to map from logger name to target -->
        <rules>
        <logger name="*" minlevel="Trace" writeTo="target1,target2" />

        </rules>
    </nlog>
...
</xml>

Add the following code to the class that contains your entrypoint into the application:

static void Main(string[] args)
{
    ILoggerFactory loggerFactory = new LoggerFactory();
    loggerFactory.AddNLog(new NLogProviderOptions
    {
        CaptureMessageTemplates = true,
        CaptureMessageProperties = true
    });
    NLog.LogManager.LoadConfiguration("nlog.config");

    var config = new ClientConfiguration
    {
        LoggerFactory = loggerFactory,
        Servers = new List<Uri>
        {
            new Uri("http://http://localhost:8091")
        }
    };

    var cluster = new Cluster(config);
    cluster.Authenticate("Administrator", "password");

    var bucket = cluster.OpenBucket("memcached");

    var insert = bucket.Insert("mykey", "mydoc");
    Console.WriteLine(insert.Status);

    Console.Read();
}

Using NLog in a Web Application

The following instructions show how to get up and running with the NLog adapter with the SDK in an ASP.NET 5 web application using the newer Visual Studio 2017 format:

  1. Add the following two nuget dependencies: CouchbaseNetClient 2.6.X and NLog.Web.AspNetCore 4.5.4.

    logging nuget nlog web aspnet
  2. Create a nlog.config in the root of your project and set "Copy to output directory" to "Copy always" in Visual Studio. An example config could look like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        autoReload="true"
        internalLogLevel="info"
        internalLogFile="c:\temp\internal-nlog.txt">
    
        <!-- enable asp.net core layout renderers -->
        <extensions>
            <add assembly="NLog.Web.AspNetCore"/>
        </extensions>
    
        <!-- the targets to write to -->
        <targets>
        <!-- write logs to file  -->
        <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
    
        <!-- another file log, only own logs. Uses some ASP.NET core renderers -->
        <target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-own-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
        </targets>
    
        <!-- rules to map from logger name to target -->
        <rules>
        <!--All logs, including from Microsoft-->
        <logger name="*" minlevel="Trace" writeTo="allfile" />
    
        <!--Skip non-critical Microsoft logs and so log only own logs-->
        <logger name="Microsoft.*" maxLevel="Info" final="true" /> <!-- BlackHole without writeTo -->
        <logger name="*" minlevel="Trace" writeTo="ownFile-web" />
        </rules>
    </nlog>
  3. In Program.cs add the following code to the Main() method:

    using Microsoft.Extensions.Logging;
    using NLog.Web;
    
    public class Program
    {
        public static void Main(string[] args)
        {
            // NLog: setup the logger first to catch all errors
            var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
            try
            {
                logger.Debug("init main");
                BuildWebHost(args).Run();
            }
            catch (Exception ex)
            {
                //NLog: catch setup errors
                logger.Error(ex, "Stopped program because of exception");
                throw;
            }
            finally
            {
                // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
                NLog.LogManager.Shutdown();
            }
        }
    
        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .ConfigureLogging(logging =>
                {
                    logging.ClearProviders();
                    logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
                })
                .UseNLog()  // NLog: setup NLog for Dependency injection
                .Build();
    }
  4. In startup.cs update the Startup method to look like the following:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
    
        app.UseStaticFiles();
    
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    
        var config = new ClientConfiguration
        {
            LoggerFactory = loggerFactory,
            Servers = new List<Uri>
            {
                new Uri("http://localhost:8091")
            }
        };
    
        ClusterHelper.Initialize(config, new PasswordAuthenticator("Administrator", "password"));
    }

More details on configuring NLog with Microsoft.Extensions.Logging can be found here.