Logging
ILogger<T> structured logging integrates Console, Debug, EventSource, and third-party sinks (Serilog, Application Insights).
Introduction
ILogger<T> structured logging integrates Console, Debug, EventSource, and third-party sinks (Serilog, Application Insights). Log levels Trace→Critical filter noise; structured placeholders enable queryable logs.
Never log passwords or PAN. Correlation IDs trace requests across microservices. Interviewers ask log levels and difference from metrics/tracing.
The story
When a bank transfer fails at 2 AM, on-call engineers search centralized logs by account IDs — not by parsing free-text messages. Structured logging with scopes attaches FromAccount and ToAccount to every log line in the transfer operation, and message templates like {Amount} make amounts queryable in Seq or Application Insights.
Understanding the topic
Key concepts
- ILogger LogInformation LogWarning LogError.
- Structured: LogInformation('Order {OrderId} placed', id).
- LogLevel hierarchy filters minimum level.
- Category named after T in ILogger
. - Scopes push properties for nested operations.
- OpenTelemetry bridges logs, metrics, traces.
flowchart LRApp --> ILoggerILogger --> Providers[Console / File / Seq]Providers --> Aggregation[Centralized Logs]
Step-by-step explanation
- Register logging in WebApplication.CreateBuilder.
- Inject ILogger
constructor. - Configuration appsettings Logging:LogLevel.
- Serilog replaces default via UseSerilog.
- BeginScope adds correlationId for request.
- Exception overload logs stack and inner.
Practical code example
Structured logging with scopes in ASP.NET Core service:
namespace TechLearningPro.Logging;public sealed class TransferService(ILogger<TransferService> logger, IBankRepository repo){public async Task<bool> TransferAsync(Guid from, Guid to, decimal amount, CancellationToken ct){using (logger.BeginScope(new Dictionary<string, object>{["FromAccount"] = from,["ToAccount"] = to})){logger.LogInformation("Transfer started for amount {Amount}", amount);try{await repo.TransferAsync(from, to, amount, ct);logger.LogInformation("Transfer completed");return true;}catch (Exception ex){logger.LogError(ex, "Transfer failed for amount {Amount}", amount);throw;}}}}
Line-by-line code explanation
TransferService(ILogger<TransferService> logger, IBankRepository repo)injects a typed logger category.logger.BeginScope(new Dictionary<string, object> { ... })pushes scope properties for nested log lines.["FromAccount"] = fromattaches structured context visible in log aggregation tools.using (...)disposes the scope when the transfer block exits — even on exceptions.logger.LogInformation("Transfer started for amount {Amount}", amount)uses a template — not string interpolation.await repo.TransferAsync(from, to, amount, ct)performs the actual database transfer.logger.LogInformation("Transfer completed")records success within the same scope.catch (Exception ex) logger.LogError(ex, "Transfer failed...")logs the exception object with stack trace.throw;rethrows after logging so callers and middleware can still handle the failure.
Key takeaway: Message templates use {Name} placeholders — not string interpolation — for structured querying in Seq/Application Insights.
Real-world use
Where you'll use this in production
- Production incident debugging with correlation ID.
- Audit trails complementing security logs.
- Performance slow query logging in EF.
- Centralized ELK/Splunk aggregation.
Best practices
- Use structured logging templates.
- Correct level — Error for failures, Information for business events.
- Redact PII and secrets.
- Include correlation ID middleware early.
- Sample verbose logs in high-traffic paths.
Common mistakes
- String interpolation destroys structured properties.
- Logging inside tight loops at Information.
- Swallowing exceptions without LogError.
- Logging full credit card numbers.
Advanced interview questions
Q1BeginnerILogger log levels order?
Q2BeginnerWhy structured logging?
Q3IntermediateLogger category purpose?
Q4IntermediateLogs vs metrics vs traces?
Q5AdvancedDesign logging for PCI-compliant payment service.
Summary
ILogger provides structured categorized logging. Use message templates and appropriate levels. Scopes and correlation IDs aid distributed tracing. Never log secrets or excessive PII. Next: unit testing with xUnit.