Logging complex objects
You are viewing the English version of this page because it has not yet been fully translated. Interested in helping out? See Contributing.
In the Getting Started with OpenTelemetry .NET Logs - Console guide, we learned how to log primitive data types. This guide will show you how to log complex objects.
Complex object logging in .NET
Complex object logging was introduced in .NET 8.0 through the LogPropertiesAttribute
. This attribute and the corresponding code generation logic are provided by an extension package called Microsoft.Extensions.Telemetry.Abstractions
.
Prerequisites
- Complete the Getting Started with Console tutorial.
Implementation steps
1. Install the required package
Install the Microsoft.Extensions.Telemetry.Abstractions
package:
dotnet add package Microsoft.Extensions.Telemetry.Abstractions
2. Define a complex data type
Create a struct to represent your complex object:
public struct FoodRecallNotice { public string? BrandName { get; set; } public string? ProductDescription { get; set; } public string? ProductType { get; set; } public string? RecallReasonDescription { get; set; } public string? CompanyName { get; set; } }
3. Create a logger extension method with LogPropertiesAttribute
Define an extension method for your logger that uses the Define an extension method to ILogger
that uses the
using Microsoft.Extensions.Logging; internal static partial class LoggerExtensions { [LoggerMessage(LogLevel.Critical)] public static partial void FoodRecallNotice( this ILogger logger, [LogProperties(OmitReferenceName = true)] in FoodRecallNotice foodRecallNotice); }
The [LogProperties(OmitReferenceName = true)]
attribute instructs the source generator to:
- Include all properties of the
FoodRecallNotice
as individual log attributes - Omit the reference name (the parameter name) from the attribute keys
4. Log the complex object
Create an instance of your complex object and log it:
// Create a complex object var foodRecallNotice = new FoodRecallNotice { BrandName = "Contoso", ProductDescription = "Salads", ProductType = "Food & Beverages", RecallReasonDescription = "due to a possible health risk from Listeria monocytogenes", CompanyName = "Contoso Fresh Vegetables, Inc.", }; // Log the complex object logger.FoodRecallNotice(foodRecallNotice);
5. Run the application
Run the application, for example using dotnet run
, and you should see the log output on the console:
LogRecord.Timestamp: 2024-01-12T19:01:16.0604084Z LogRecord.CategoryName: Program LogRecord.Severity: Fatal LogRecord.SeverityText: Critical LogRecord.FormattedMessage: LogRecord.Body: LogRecord.Attributes (Key:Value): CompanyName: Contoso Fresh Vegetables, Inc. RecallReasonDescription: due to a possible health risk from Listeria monocytogenes ProductType: Food & Beverages ProductDescription: Salads BrandName: Contoso LogRecord.EventId: 252550133 LogRecord.EventName: FoodRecallNotice
Notice that each property of the FoodRecallNotice
object appears as a separate attribute in the log record.
LogPropertiesAttribute options
The LogPropertiesAttribute
provides several options to control how properties are included in logs:
OmitReferenceName: When set to
true
, the parameter name is omitted from attribute keys. In the example above, attribute keys are just the property names (for example, “BrandName”) rather than “foodRecallNotice.BrandName”.IncludeProperties: Used to specify which properties should be included. If not specified, all properties are included.
ExcludeProperties: Used to specify which properties should be excluded from logging.
IncludeSensitive: When set to
true
, properties marked with[Sensitive]
attribute are included in logs. The default isfalse
.
Complete example
Here’s a complete example that puts everything together:
using System; using Microsoft.Extensions.Logging; using OpenTelemetry; using OpenTelemetry.Logs; // Complex object definition public struct FoodRecallNotice { public string? BrandName { get; set; } public string? ProductDescription { get; set; } public string? ProductType { get; set; } public string? RecallReasonDescription { get; set; } public string? CompanyName { get; set; } } // Logger extension method internal static partial class LoggerExtensions { [LoggerMessage(LogLevel.Critical)] public static partial void FoodRecallNotice( this ILogger logger, [LogProperties(OmitReferenceName = true)] in FoodRecallNotice foodRecallNotice); } // Main program class Program { static void Main(string[] args) { // Create a logger factory with OpenTelemetry using var loggerFactory = LoggerFactory.Create(builder => { builder.AddOpenTelemetry(options => { options.AddConsoleExporter(); }); }); // Get a logger instance var logger = loggerFactory.CreateLogger<Program>(); // Create a complex object var foodRecallNotice = new FoodRecallNotice { BrandName = "Contoso", ProductDescription = "Salads", ProductType = "Food & Beverages", RecallReasonDescription = "due to a possible health risk from Listeria monocytogenes", CompanyName = "Contoso Fresh Vegetables, Inc.", }; // Log the complex object logger.FoodRecallNotice(foodRecallNotice); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } }
Learn more
- Microsoft.Extensions.Logging.LogPropertiesAttribute
- Microsoft.Extensions.Telemetry.Abstractions
- Log Correlation in OpenTelemetry .NET
- OpenTelemetry Logs Data Model
フィードバック
このページは役に立ちましたか?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!