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 infrastructure 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 v3.0.0.

    • NLog.Extensions.Logging 1.6.2

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

    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 async Task Main(string[] args)
    {
       ILoggerFactory loggerFactory = new LoggerFactory();
    
        loggerFactory.AddNLog(new NLogProviderOptions
        {
            CaptureMessageTemplates = true,
            CaptureMessageProperties = true
        });
    
         LogManager.LoadConfiguration("nlog.config");
    
        var options = new ClusterOptions()
        {
            Logging = loggerFactory,
            UserName = "Administrator",
            Password = "password",
            ConnectionString = "http://localhost"
        };
    
       var cluster = await Cluster.ConnectAsync(options);
       var bucket = await cluster.BucketAsync("beer-sample");
       var collection = bucket.DefaultCollection();
    
       await collection.UpsertAsync<string>("beer-sample-101", "logging example 101");
    
       var returnVal = await collection.GetAsync("beer-sample-101");
    
    
        Console.WriteLine(returnVal.ContentAs<string>());
    
        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 3.0.0 and NLog.Web.AspNetCore 4.9.1.

      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.AspNetCore;
      using Microsoft.AspNetCore.Hosting;
      using Microsoft.Extensions.Hosting;
      using NLog.Web;
      using Microsoft.Extensions.Logging;
      using System;
      
      namespace LoggingWebExample
      {
          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(log =>
                      {
                          log.ClearProviders();
                         log.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
                      })
                      .UseNLog()  // NLog: setup NLog for Dependency injection
                      .Build();
          }
      }
    4. In startup.cs update the ConfigureServices method to look like the following:

      public void ConfigureServices(IServiceCollection services)
      {
      
          // Get logger factory to pass it along to the couchbase cluster.
      
          ILoggerFactory loggerFactory = services.BuildServiceProvider()
              .GetService<ILoggerFactory>();
      
          var options = new ClusterOptions()
          {
              Logging = loggerFactory,
              UserName = "Administrator",
              Password = "password",
              ConnectionString = "http://localhost"
          };
      
          // Bootstrap Cluster Object.
          var cluster = Cluster.ConnectAsync(options)
                          .GetAwaiter()
                          .GetResult();
      
          services.AddSingleton(typeof(ICluster), cluster);
      
      
          services.AddControllers().AddNewtonsoftJson(options => options.UseMemberCasing());
          services.AddMvc().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
      
          //Swagger related
          services.AddSwaggerGen(c =>
          {
              c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Sample API", Version = "v1" });
          });
      }

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