Section 4 of 6
Structured Logging
🎯 What You'll Learn
- What is structured logging
- Message templates
- Named parameters
- Benefits of structured logging
- Querying structured logs
What is Structured Logging?
Structured logging stores log data as structured data (key-value pairs) instead of plain text, making logs easier to search and analyze.
String Interpolation vs Message Templates
❌ Bad: String Interpolation
Unstructured (Don't do this)
C#
_logger.LogInformation($"Product {productId} created by {userId}");
Output: "Product 123 created by user456" (plain text)
✅ Good: Message Templates
Structured (Do this)
C#
_logger.LogInformation("Product {ProductId} created by {UserId}", productId, userId);
Output: Structured data with properties ProductId=123,
UserId="user456"
Named Parameters
Use PascalCase names in curly braces for parameters.
Named Parameters
C#
_logger.LogInformation(
"Order {OrderId} placed by {CustomerName} for {TotalAmount:C}",
orderId,
customerName,
totalAmount
);
Format Specifiers
Formatting Values
C#
// Currency
_logger.LogInformation("Price: {Price:C}", 19.99); // $19.99
// Decimal places
_logger.LogInformation("Percentage: {Percent:P2}", 0.1234); // 12.34%
// Date
_logger.LogInformation("Date: {Date:yyyy-MM-dd}", DateTime.Now);
Benefits of Structured Logging
- Searchable: Query by specific properties
- Analyzable: Aggregate and analyze data
- Filterable: Filter by property values
- Machine-readable: Easy to parse programmatically
InvenTrack Example
Structured Logging in Action
C#
public async Task<IActionResult> CreateOrder(Order order)
{
_logger.LogInformation(
"Creating order for customer {CustomerId} with {ItemCount} items, total {TotalAmount:C}",
order.CustomerId,
order.Items.Count,
order.TotalAmount
);
try
{
await _context.Orders.AddAsync(order);
await _context.SaveChangesAsync();
_logger.LogInformation(
"Order {OrderId} created successfully",
order.Id
);
return Ok(order);
}
catch (Exception ex)
{
_logger.LogError(
ex,
"Failed to create order for customer {CustomerId}",
order.CustomerId
);
return BadRequest();
}
}
Key Takeaways
- Structured logging: Key-value pairs, not plain text
- Message templates: Use {PropertyName} placeholders
- Don't use string interpolation: Use parameters instead
- PascalCase: Name parameters in PascalCase
- Format specifiers: {Price:C}, {Percent:P2}, etc.
- Benefits: Searchable, analyzable, filterable