C# by Myles

Logging in C#

Logging in C# is a critical practice for monitoring application behavior, diagnosing issues, and gaining operational insights. Whether building desktop applications, APIs, or cloud-native services, effective logging allows developers and operators to understand how the system behaves in real time and after the fact.

csharp
logging
diagnostics
structuredlogging
bestpractices
...see more

In structured logging within C#, it's common to log endpoint URLs that consist of a base address and a path. To ensure safe and consistent logging, developers should use a centralized utility method to combine these values without risking exceptions or malformed URLs. This Snipp outlines two recommended approaches for implementing this functionality in a logging-safe way.

...see more

When production issues happen, logs should clearly show what started, what happened in between, and how it ended. A simple and consistent pattern using _logger with Application Insights can make troubleshooting much easier.

Here is a practical example for an operation like retrieving role assignments.

Start – Log inputs clearly

Log the action and key parameters at the beginning:

const string action = "Retrieve role assignments for scope";
var stopwatch = Stopwatch.StartNew();

_logger.LogInformation("Start {Action}. Scope={Scope}, RoleId={RoleId}",
    action, scope, roleId);

This creates structured properties (Action, Scope, RoleId) that are searchable in Application Insights.

Flow – Log important checkpoints

Log meaningful steps inside the method:

_logger.LogInformation("Flow {Action} – calling external service. Scope={Scope}",
    action, scope);

Only log major steps. Avoid too many details.

End – Log result summary and duration

When successful:

stopwatch.Stop();

_logger.LogInformation("End {Action}. Count={Count}, ElapsedMs={ElapsedMs}",
    action, result.Count, stopwatch.ElapsedMilliseconds);

Include result summaries (like counts) and execution time. This helps detect performance issues.

Fail – Log exception with full context

On failure:

catch (Exception ex)
{
    stopwatch.Stop();

    _logger.LogError("Fail {Action}. Scope={Scope}, RoleId={RoleId}, ElapsedMs={ElapsedMs}, Exception={Exception}",
        action, scope, roleId, stopwatch.ElapsedMilliseconds, ex);

    throw;
}

Always pass the exception to LogError. Application Insights will capture the stack trace automatically.

Why This Works

  • Messages are easy to read
  • Properties are structured and searchable
  • Start, Flow, End, and Fail follow the same pattern
  • Operations teams can trace full execution paths

With this consistent approach, logs become a reliable story of what your system did — and why.

Comments