When logging with ILogger, it is common to use C# string interpolation ($"") to include variable values in a message. However, for better log performance, readability, and easier analysis in the future, it is recommended to use “Message Templates.” This article explains how to write structured logs by embedding variables in the {Placeholder} format.
Table of Contents
- Implementation Sample: Payment Processing Logs
- Execution Result
- Explanation: Why Should You Avoid String Interpolation ($)?
Implementation Sample: Payment Processing Logs
In this example, we log a transaction ID and an amount for a payment system. Notice that we pass the variables as arguments instead of combining them into a string.
1. PaymentWorker.cs (Logging Class)
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace PaymentApp
{
public class PaymentWorker : BackgroundService
{
private readonly ILogger<PaymentWorker> _logger;
public PaymentWorker(ILogger<PaymentWorker> logger)
{
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
// Variables to log
var transactionId = "TX-998877";
decimal amount = 5000m;
// [Recommended Way]
// Place a {Name} placeholder in the message and pass variables as subsequent arguments
_logger.LogInformation("Starting payment process. Transaction ID: {TransactionId}, Amount: {Amount} JPY", transactionId, amount);
// [Not Recommended Way] (String Interpolation)
// _logger.LogInformation($"Starting payment process. Transaction ID: {transactionId}, Amount: {amount} JPY");
return Task.CompletedTask;
}
}
}
2. appsettings.json (Log Level Settings)
Configure the settings to display logs at the Information level or higher for the PaymentApp namespace.
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"System": "Warning",
"Microsoft": "Warning",
"PaymentApp": "Information"
}
}
}
Execution Result
info: PaymentApp.PaymentWorker[0]
Starting payment process. Transaction ID: TX-998877, Amount: 5000 JPY
Explanation: Why Should You Avoid String Interpolation ($)?
1. Support for Structured Logging
When you use the template syntax "{Key}", value, the data is sent to logging platforms (such as Application Insights, Elasticsearch, or Seq) as “properties” (key-value pairs) rather than just a simple sentence. This allows you to perform queries like “find all logs where Amount is greater than 10,000.” If you use string interpolation ($"{var}"), the message becomes a single string, and you lose this benefit.
2. Performance Improvement
String interpolation ($"") executes the string concatenation immediately, regardless of the log level. In contrast, with template syntax, if the log level is disabled (for example, a Trace log when the setting is Warning), the string formatting process is skipped entirely. This helps reduce unnecessary CPU usage.
3. Syntax Rules
- Name your placeholders like
{Name}. While you can use numbers like{0}, using names makes it much easier to search for data later. - The order of arguments must match the order in which the placeholders appear in the message.
