Logging with the Azure SDK for .NET

The Azure SDK for .NET's client libraries include the ability to log client library operations. This logging allows you to monitor I/O requests and responses that client libraries are making to Azure services. Typically, the logs are used to debug or diagnose communication issues. This article describes the following approaches to enable logging with the Azure SDK for .NET:

Important

This article applies to client libraries that use the most recent versions of the Azure SDK for .NET. To see if a library is supported, refer to the list of Azure SDK latest releases. If your app is using an older version of the Azure SDK client libraries, refer to specific instructions in the applicable service documentation.

Log information

The SDK logs each HTTP request and response, sanitizing parameter query and header values to remove personal data.

HTTP request log entry:

  • Unique ID
  • HTTP method
  • URI
  • Outgoing request headers

HTTP response log entry:

  • Duration of I/O operation (time elapsed)
  • Request ID
  • HTTP status code
  • HTTP reason phrase
  • Response headers
  • Error information, when applicable

For HTTP request and response content:

Event logs are output usually at one of these three levels:

  • Informational for request and response events
  • Warning for errors
  • Verbose for detailed messages and content logging

Enable logging with built-in methods

The Azure SDK for .NET's client libraries log events to Event Tracing for Windows (ETW) via the System.Diagnostics.Tracing.EventSource class, which is typical for .NET. Event sources allow you to use structured logging in your app with minimal performance overhead. To gain access to the event logs, you need to register event listeners.

The SDK includes the Azure.Core.Diagnostics.AzureEventSourceListener class, which contains two static methods that simplify comprehensive logging for your .NET app: CreateConsoleLogger and CreateTraceLogger. Each of these methods accepts an optional parameter that specifies a log level. If the parameter isn't provided, the default log level of Informational is used.

Log to the console window

A core tenet of the Azure SDK for .NET client libraries is to simplify the ability to view comprehensive logs in real time. The CreateConsoleLogger method allows you to send logs to the console window with a single line of code:

using AzureEventSourceListener listener = 
    AzureEventSourceListener.CreateConsoleLogger();

Log to diagnostic traces

If you implement trace listeners, you can use the CreateTraceLogger method to log to the standard .NET event tracing mechanism (System.Diagnostics.Tracing). For more information on event tracing in .NET, see Trace Listeners.

This example specifies a log level of verbose:

using AzureEventSourceListener listener = 
    AzureEventSourceListener.CreateTraceLogger(EventLevel.Verbose);

Configure custom logging

As mentioned above, you need to register event listeners to receive log messages from the Azure SDK for .NET. If you don't want to implement comprehensive logging using one of the simplified methods above, you can construct an instance of the AzureEventSourceListener class. Pass that instance a callback method that you write. This method will receive log messages that you can process however you need to. In addition, when you construct the instance, you can specify the log levels to include.

The following example creates an event listener that logs to the console with a custom message. The logs are filtered to those events emitted from the Azure Core client library with a level of verbose. The Azure Core library uses an event source name of Azure-Core.

using Azure.Core.Diagnostics;

// code omitted for brevity

using var listener = new AzureEventSourceListener((e, message) =>
    {
        // Only log messages from "Azure-Core" event source
        if (e.EventSource.Name == "Azure-Core")
        {
            Console.WriteLine($"{DateTime.Now} {message}");
        }
    },
    level: EventLevel.Verbose);

Map to ASP.NET Core logging

When the AddAzureClients or the AddAzureClientsCore extension method is called, the AzureEventSourceLogForwarder service is registered. The AzureEventSourceLogForwarder service enables you to use the standard ASP.NET Core logging configuration for logging.

The following table depicts how the Azure SDK for .NET EventLevel maps to the ASP.NET Core LogLevel.

Azure SDK EventLevel ASP.NET Core LogLevel
Critical Critical
Error Error
Informational Information
Warning Warning
Verbose Debug
LogAlways Information

Logging with client registration

Consider the following AddAzureClients call in the Program.cs file of an ASP.NET Core project. The AddAzureClients method registers the Azure Service Bus client and sets the default token credential to be used for all clients.

using Azure.Identity;
using Microsoft.Extensions.Azure;

// code omitted for brevity

builder.Services.AddAzureClients(azureBuilder =>
{
    azureBuilder.AddServiceBusClient(
        builder.Configuration.GetConnectionString("ServiceBus"));
    azureBuilder.UseCredential(new DefaultAzureCredential());
});

In the ASP.NET Core project's appsettings.json file, the default log level for the Azure Service Bus client library can be changed. For example, toggle it to Debug by setting the Logging:LogLevel:Azure.Messaging.ServiceBus key as follows:

{
  "ConnectionStrings": {
    "ServiceBus": "<connection_string>"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Azure.Messaging.ServiceBus": "Debug"
    }
  },
  "AllowedHosts": "*"
}

Since the Logging:LogLevel:Azure.Messaging.ServiceBus key is set to Debug, Service Bus client events up to EventLevel.Verbose will be logged.

Logging without client registration

While this approach is far less common, your app may not need to explicitly register clients for Azure SDK libraries. In that scenario, a call to AddAzureClientsCore will suffice. Take this approach when your app uses ASP.NET extension libraries that depend on other Azure SDK libraries. Common examples of such ASP.NET extension libraries include:

Consider the following Program.cs example, which uses the two aforementioned ASP.NET Core Data Protection extension libraries:

using Azure.Identity;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Azure;

// code omitted for brevity

builder.services.AddAzureClientsCore();

builder.services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(storageConnString, blobContainerName, "keys.xml")
    .ProtectKeysWithAzureKeyVault(new Uri(uri), new DefaultAzureCredential());

In the ASP.NET Core project's appsettings.json file, the default log level for the Azure Core client library can be changed. For example, toggle it to Debug by setting the Logging:LogLevel:Azure.Messaging.ServiceBus key as follows:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Azure.Core": "Debug"
    }
  },
  "AllowedHosts": "*"
}

Since the Logging:LogLevel:Azure.Core key is set to Debug, Azure Core library events up to EventLevel.Verbose will be logged.

For more information, see Logging in .NET Core and ASP.NET Core.

Log HTTP request and response bodies

When troubleshooting unexpected behavior with a client library, it's helpful to inspect the following items:

  • The HTTP request body sent to the underlying Azure service's REST API.
  • The HTTP response body received from the Azure service's REST API.

By default, logging of the aforementioned content is disabled. To enable logging of the HTTP request and response bodies, complete the following steps:

  1. Set the client options object's IsLoggingContentEnabled property to true. For example:

    var options = new SecretClientOptions
    {
        Diagnostics = 
        {
            IsLoggingContentEnabled = true,
        }
    };
    
  2. Use your preferred logging approach with an event/log level of verbose/debug or higher. Find your approach in the following table for specific instructions.

    Approach Instructions
    Enable logging with built-in methods Pass EventLevel.Verbose or EventLevel.LogAlways to AzureEventSourceListener.CreateConsoleLogger or AzureEventSourceListener.CreateTraceLogger
    Configure custom logging Set the AzureEventSourceListener class' level constructor parameter to EventLevel.Verbose or EventLevel.LogAlways
    Map to ASP.NET Core logging Add "Azure.Core": "Debug" to appsettings.json

Next steps