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, see the list of Azure SDK latest releases. If your app is using an older version of an Azure SDK client library, 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
HTTP request and response content:
Content stream as text or bytes depending on the
Content-Type
header.Note
Content logging is disabled by default. To enable it, see Log HTTP request and response bodies. This capability applies only to libraries using HTTP to communicate with an Azure service. Libraries based on alternative protocols, such as AMQP, don't support content logging. Unsupported examples include libraries for Azure services such as Event Hubs, Service Bus, and Web PubSub.
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;
using System.Diagnostics.Tracing;
// 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
The AzureEventSourceLogForwarder service enables you to use the standard ASP.NET Core logging configuration for logging. The service forwards log messages from Azure SDK event sources to ILoggerFactory.
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
Using the Azure Service Bus library as an example, complete the following steps:
Install the Microsoft.Extensions.Azure NuGet package:
dotnet add package Microsoft.Extensions.Azure
In Program.cs, register the Azure SDK library's client via a call to the AddAzureClients extension method:
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 preceding sample, the
AddAzureClients
method:- Registers the following objects with the dependency injection (DI) container:
- Log forwarder service
- Azure Service Bus client
- Sets the default token credential to be used for all registered clients.
- Registers the following objects with the dependency injection (DI) container:
In appsettings.json, change the Service Bus library's default log level. For example, toggle it to
Debug
by setting theLogging: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 toDebug
, Service Bus client events up toEventLevel.Verbose
will be logged.
Logging without client registration
There are scenarios in which registering an Azure SDK library's client with the DI container is either impossible or unnecessary:
- The Azure SDK library doesn't include an
IServiceCollection
extension method to register a client in the DI container. - Your app uses Azure extension libraries that depend on other Azure SDK libraries. Examples of such Azure extension libraries include:
In these scenarios, complete the following steps:
Install the Microsoft.Extensions.Azure NuGet package:
dotnet add package Microsoft.Extensions.Azure
In Program.cs, register the log forwarder service as a singleton in the DI container:
using Azure.Identity; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Azure; using Microsoft.Extensions.DependencyInjection.Extensions; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); builder.Services.TryAddSingleton<AzureEventSourceLogForwarder>(); builder.Services.AddDataProtection() .PersistKeysToAzureBlobStorage("<connection_string>", "<container_name>", "keys.xml") .ProtectKeysWithAzureKeyVault(new Uri("<uri>"), new DefaultAzureCredential());
Fetch the log forwarder service from the DI container and invoke its Start method. For example, using constructor injection in an ASP.NET Core Razor Pages page model class:
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Azure; public class IndexModel : PageModel { public IndexModel(AzureEventSourceLogForwarder logForwarder) => logForwarder.Start();
In appsettings.json, change the Azure Core library's default log level. For example, toggle it to
Debug
by setting theLogging:LogLevel:Azure.Core
key as follows:{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning", "Azure.Core": "Debug" } }, "AllowedHosts": "*" }
Since the
Logging:LogLevel:Azure.Core
key is set toDebug
, Azure Core library events up toEventLevel.Verbose
will be logged.
For more information, see Logging in .NET Core and ASP.NET Core.
Logging using Azure.Monitor.OpenTelemetry.AspNetCore
The Azure Monitor OpenTelemetry distro, starting with version 1.2.0
, supports capturing logs coming from Azure client libraries. You can control logging using any of the configuration options discussed in Logging in .NET Core and ASP.NET Core.
Using the Azure Service Bus library as an example, complete the following steps:
Install the Azure.Monitor.OpenTelemetry.AspNetCore NuGet package:
dotnet add package Azure.Monitor.OpenTelemetry.AspNetCore
Create or register the library's client. The distro supports both cases.
await using var client = new ServiceBusClient("<connection_string>");
In appsettings.json, change the Service Bus library's default log level. For example, toggle it to
Debug
by setting theLogging: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 toDebug
, Service Bus client events up toEventLevel.Verbose
will be logged.
Log HTTP request and response bodies
Note
This capability applies only to libraries using HTTP to communicate with an Azure service. Libraries based on alternative protocols, such as AMQP, don't support content logging. Unsupported examples include libraries for Azure services such as Event Hubs, Service Bus, and Web PubSub.
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:
Set the client options object's IsLoggingContentEnabled property to
true
, and pass the options object to the client's constructor. For example, to log HTTP requests and responses for the Azure Key Vault Secrets library:var clientOptions = new SecretClientOptions { Diagnostics = { IsLoggingContentEnabled = true, } }; var client = new SecretClient( new Uri("https://<keyvaultname>.vault.azure.net/"), new DefaultAzureCredential(), clientOptions);
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
orEventLevel.LogAlways
toAzureEventSourceListener.CreateConsoleLogger
orAzureEventSourceListener.CreateTraceLogger
Configure custom logging Set the AzureEventSourceListener
class'level
constructor parameter toEventLevel.Verbose
orEventLevel.LogAlways
Map to ASP.NET Core logging Add "Azure.Core": "Debug"
to appsettings.json
Next steps
- Enable diagnostics logging for apps in Azure App Service
- Review Azure security logging and auditing options
- Learn how to work with Azure platform logs
- Read more about .NET logging and tracing