Summary - Logging
Combine ILogger, levels and providers to write a logging sample.
Recap: logging
This group covered logging basics: the ILogger<T> interface, four levels (LogDebug, LogInformation, LogWarning, LogError), LoggerMessage.Define for high performance, structured logging with named placeholders, and Console/Debug providers.
Good logging has three properties: selective (not writing everything), structured (queryable fields), and fit for purpose (Console for live watching, Debug for development, files for production archive). Now we apply these in combined examples.
Exercise Structured logging with UserService
Define an ILogger<T> interface with void LogInformation(string message, params object[] args). ConsoleLogger<T> replaces each {...} placeholder in order with the next argument, then calls Console.WriteLine("[INF] " + message). UserService takes an ILogger<UserService> in its constructor; its Greet(string user) method calls _logger.LogInformation("Merhaba {User}", user). In Main, create a ConsoleLogger<UserService> and call Greet("Ayşe").
Show example solution
Define interface ILogger<T> { void LogInformation(string message, params object[] args); }. Write class ConsoleLogger<T> : ILogger<T> { public void LogInformation(string message, params object[] args) { int i = 0; while (i < args.Length) { int s = message.IndexOf('{'); if (s < 0) break; int e = message.IndexOf('}', s); if (e < 0) break; message = message.Substring(0, s) + args[i] + message.Substring(e + 1); i++; } Console.WriteLine("[INF] " + message); } }. Write class UserService { private readonly ILogger<UserService> _logger; public UserService(ILogger<UserService> l) => _logger = l; public void Greet(string user) => _logger.LogInformation("Merhaba {User}", user); }. In Main: var svc = new UserService(new ConsoleLogger<UserService>()); svc.Greet("Ayşe");
Example solution:
using System;
public interface ILogger<T>
{
void LogInformation(string message, params object[] args);
}
public class ConsoleLogger<T> : ILogger<T>
{
public void LogInformation(string message, params object[] args)
{
int i = 0;
while (i < args.Length)
{
int s = message.IndexOf('{');
if (s < 0) break;
int e = message.IndexOf('}', s);
if (e < 0) break;
message = message.Substring(0, s) + args[i] + message.Substring(e + 1);
i++;
}
Console.WriteLine("[INF] " + message);
}
}
class UserService
{
private readonly ILogger<UserService> _logger;
public UserService(ILogger<UserService> logger) => _logger = logger;
public void Greet(string user) =>
_logger.LogInformation("Merhaba {User}", user);
}
class Program
{
static void Main()
{
var service = new UserService(new ConsoleLogger<UserService>());
service.Greet("Ayşe");
}
}
Exercise Compiled logging with LoggerMessage
Define a non-generic ILogger interface (void LogInformation(string message)) and an ILogger<T> : ILogger interface. ConsoleLogger<T> implements ILogger<T> and calls Console.WriteLine("[INF] " + message). In a static LoggerMessage class, DefineInformation(string message) returns Action<ILogger, string>; the delegate replaces the {Arg} placeholder with the second argument. In Main, create a ConsoleLogger<Program>, get the delegate via DefineInformation("Merhaba {Arg}"), and call greet(logger, "Ayşe").
Show example solution
Define interface ILogger { void LogInformation(string message); } and interface ILogger<T> : ILogger { }. Write class ConsoleLogger<T> : ILogger<T> { public void LogInformation(string message) => Console.WriteLine("[INF] " + message); }. Write static class LoggerMessage { public static Action<ILogger, string> DefineInformation(string message) => (logger, arg) => logger.LogInformation(message.Replace("{Arg}", arg)); }. In Main: var logger = new ConsoleLogger<Program>(); var greet = LoggerMessage.DefineInformation("Merhaba {Arg}"); greet(logger, "Ayşe");
Example solution:
using System;
public interface ILogger
{
void LogInformation(string message);
}
public interface ILogger<T> : ILogger { }
public class ConsoleLogger<T> : ILogger<T>
{
public void LogInformation(string message) =>
Console.WriteLine("[INF] " + message);
}
public static class LoggerMessage
{
public static Action<ILogger, string> DefineInformation(string message) =>
(logger, arg) => logger.LogInformation(message.Replace("{Arg}", arg));
}
class Program
{
static void Main()
{
var logger = new ConsoleLogger<Program>();
var greet = LoggerMessage.DefineInformation("Merhaba {Arg}");
greet(logger, "Ayşe");
}
}
Test yourself
-
Match logging concepts
- ILogger<T>
- Logging interface
- LogError
- Error level
- {User}
- Named placeholder
- ConsoleLogger<T>
- Console provider
-
Which level logs error conditions?
- LogDebug
- LogInformation
- LogError
- LogTrace
Show answer
LogError — Correct. LogError logs error conditions.