Logging with ILogger
Level: Beginner to Intermediate
Logging helps you understand what your application did before, during, and after a request. It becomes essential when debugging APIs, production issues, authentication failures, and database problems.
- Logging purpose: Understand what app did before/after crash, monitor production issues, debug slow endpoints
ILogger<T>injection:private readonly ILogger<StudentController> _logger;in constructor- Log methods:
_logger.LogInformation(),.LogWarning(),.LogError(),.LogDebug(),.LogCritical() - Log levels: Debug (detailed, dev only) < Information (important events) < Warning (potential issues) < Error (operation failed) < Critical (app broken)
- When to log: User login/logout, API request received, database queries (expensive), exceptions caught, state changes
- School Management logging: "User logged in as teacher", "Student 101 marked present", "Database connection failed"
- Structured logging:
_logger.LogInformation("Student {StudentId} created", student.Id)(not string concatenation) - Exception logging:
_logger.LogError(ex, "Failed to create student")(includes stack trace) - Logging in services: Business logic logs what it's doing (StudentService logs CRUD operations)
- Configuration in appsettings.json: Log levels per namespace (e.g., Microsoft logs Warning, but School.Api logs Information)
- Log output destinations: Console (development), File (production via Serilog), Application Insights (Azure monitoring)
- Common mistakes: Logging sensitive data (passwords, SSN), logging every line (performance hit), no structured logging (hard to search logs)
- Debugging with logs: Find pattern before crash, identify slow operations, track user actions
Why Logging Matters
When an app runs on your machine, you can use breakpoints.
When an app runs on a server, you need logs.
Logs answer questions like:
- Which request failed?
- Which student id was used?
- Was validation passed?
- Did the database call fail?
- Did the user have permission?
- How often is this error happening?
ILogger Basics
ASP.NET Core provides logging through ILogger<T>.
ILogger<StudentsController> means the log is tagged with the controller name.
Log Levels
Log levels show how serious a message is.
| Level | Meaning | Example |
|---|---|---|
Trace | Very detailed internal flow | Deep diagnostics |
Debug | Developer debugging details | SQL query decision |
Information | Normal successful events | Attendance marked |
Warning | Something unusual but handled | Student record not found |
Error | Operation failed | Database save failed |
Critical | App-level serious failure | Payment service unavailable |
When to Use Each Level
Use Information for normal important events:
_logger.LogInformation("Student {StudentId} profile viewed", id);
Use Warning when something is not ideal but app continues:
_logger.LogWarning("Student {StudentId} was not found", id);
Use Error when an operation fails:
_logger.LogError("Failed to save attendance for student {StudentId}", id);
Use Critical for severe failures:
_logger.LogCritical("Database is unavailable during exam result publishing");
Structured Logging
Prefer this:
_logger.LogInformation(
"Attendance marked for student {StudentId} on {AttendanceDate}",
studentId,
attendanceDate);
Avoid this:
_logger.LogInformation("Attendance marked for student " + studentId);
Structured logging keeps values separate, so log tools can search and filter by StudentId.
Logging in a Service
Controllers are not the only place for logs.
public class AttendanceService : IAttendanceService
{
private readonly ILogger<AttendanceService> _logger;
public AttendanceService(ILogger<AttendanceService> logger)
{
_logger = logger;
}
public void MarkAttendance(int studentId, DateTime date)
{
_logger.LogInformation(
"Marking attendance for student {StudentId} on {Date}",
studentId,
date);
// Save attendance here
}
}
Business services should log meaningful business events and failures.
Logging Exceptions
When logging an exception, pass the exception object as the first argument after the log level method.
try
{
_attendanceService.MarkAttendance(studentId, DateTime.Today);
}
catch (Exception ex)
{
_logger.LogError(
ex,
"Failed to mark attendance for student {StudentId}",
studentId);
return StatusCode(500, "Unable to mark attendance.");
}
This preserves stack trace details.
Configuring Log Levels
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"School.Api": "Debug"
}
}
}
Meaning:
| Key | Meaning |
|---|---|
Default | Default level for the app |
Microsoft.AspNetCore | Framework logs |
School.Api | Your application namespace |
In Development, you may use more detail:
{
"Logging": {
"LogLevel": {
"Default": "Debug"
}
}
}
In Production, avoid too much noise:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
What Not to Log
Never log sensitive information.
Do not log:
- passwords
- full connection strings
- credit card details
- OTP values
- authentication tokens
- private student data unless required and protected
Safer:
_logger.LogInformation("Login failed for user id {UserId}", userId);
Risky:
_logger.LogInformation("Login failed for password {Password}", password);
School App Logging Examples
| Scenario | Suggested Level |
|---|---|
| Student profile opened | Information |
| Attendance already marked | Warning |
| Invalid admission form | Warning |
| Database save failed | Error |
| Payment gateway unavailable | Error or Critical |
| Application cannot start | Critical |
Common Mistakes
| Mistake | Better Approach |
|---|---|
Using Console.WriteLine everywhere | Use ILogger |
| Building log text with string concatenation | Use structured logging |
| Logging passwords or tokens | Never log secrets |
| Logging every small step in production | Use appropriate log levels |
| Catching exceptions and hiding them silently | Log useful context |
Practice Task
Add logging to a student API:
- Log when a student search starts.
- Log a warning when the student is not found.
- Log information when a student is returned.
- Log an exception if the service fails.
- Configure Development logging as
Debug.
Quick Recap
| Question | Answer |
|---|---|
| Main logging type? | ILogger<T> |
| Best style? | Structured logging |
| Normal events use? | LogInformation |
| Recoverable unusual events use? | LogWarning |
| Exceptions use? | LogError(ex, "...") |
Q: How do you implement logging in ASP.NET Core?
Good Answer: "ASP.NET Core provides built-in logging through ILogger<T>, which is injected by dependency injection. Logs are written using levels such as Debug, Information, Warning, Error, and Critical. Structured logging should be used with placeholders, for example LogInformation(\"Student {StudentId} loaded\", id), because it makes logs searchable. Log levels can be configured in appsettings.json and adjusted per environment. Sensitive data should never be logged."
Use ChatGPT, Claude, or Copilot to go deeper on ASP.NET Core Logging. Try these prompts:
"Explain ILogger in ASP.NET Core with a controller example.""What is structured logging and why is it better?""When should I use Warning vs Error?""What should never be written into application logs?"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.