CommunityToolkit / CommunityToolkit/Graph-Controls

[Feature] Improve logging in providers

Open
#179 0 comments 0 reactions 0 assignees View on GitHub
Area: Providers enhancement :sparkles: In-PR :rocket:
Dominant language
C#
Stars
156
Forks
38
PR merge metrics
No merged PRs in 30d

Description

## Describe the problem this feature would solve

When the authentication providers work, they are a delight. But when they don't work, they are rather difficult to troubleshoot.

## Describe the solution

We need better logging to expose some insights into what the provider is doing, and what exceptions or failures are occurring. However, I feel like this is a great opportunity to handle logging in a more generic way across the whole toolkit.

I see a few moving parts:

- `ILogger` interface - defines the basic functions of a logger. At a minimum, log a string message.
- `DebugLogger` implementation - extends `ILogger` and uses `System.Diagnostics.Debug.WriteLine` to log messages. This is the default.
- `LogManager` singleton - maintains active `ILogger` implementation used across the packages.

### 1. The logger interface and implementation

I'd like to see the `ILogger` interface put in the `CommunityToolkit.Diagnostics` package ([link](https://github.com/CommunityToolkit/dotnet/tree/main/CommunityToolkit.Diagnostics)). This enables us to offer the simple `DebugLogger` based on `System.Diagnostics.Debug.WriteLine`

```csharp
// Defines a basic logger
public interface ILogger
{
// Turn logging on or off
bool IsEnabled { get; set; }

// Log a string message, if enabled
void Log(string message);
}

// Default logger implementation
public class DebugLogger : ILogger
{
// Turned off by default.
public bool IsEnabled { get; set; } = false;

public void Log(string message)
{
if (IsEnabled)
{
System.Diagnostics.Debug.WriteLine(message);
}
}
}

// Manages the global logger instance
public class LogManager
{
public static LogManager Instance { get; } = new LogManager();

public ILogger Logger { get; set; } = new DebugLogger();
}
```

### 2. Consuming the logger

Developers with a custom logger can extend `ILogger` OR use a shim class instead to connect it to the `LogManager`:

```csharp
// Set somewhere in app startup code
LogManager.Instance.Logger.IsEnabled = true;

// OR

// An example custom logger shim, if you don't want the default DebugLogger:
public class CustomLogger : ILogger
{
public bool IsEnabled { get; set; } = true;

public void Log(string message)
{
// Call your custom logger here
}
}

// Set somewhere in app startup code
LogManager.Instance.Logger = new CustomLogger();
```

### 3. Applying the logger to WindowsProvider

Pretty straight forward, ensure that every try/catch block sends any exceptions to the logger. Also look for opportunities to log other common events that could help with troubleshooting.

### 4. Applying the logger to MsalProvider

First ensure that every try/catch block sends any exceptions to the logger. But also, the `MsalProvider` leverages the `PublicClientApplication` object from MSAL for .NET which has a mechanism for passing in a method to handle the log output. This is enabled by using the `WithLogging` method on the client builder. This can be connected with the `LogManager` like so:

`clientBuilder.WithLogging((level, message, containsPii) => LogManager.Instance.Logger.Log(message));`

## Additional context & Screenshots

Here is an example of a developers having issues with troubleshooting in the auth providers:
https://github.com/MicrosoftDocs/WindowsCommunityToolkitDocs/issues/593

## Open questions

1. Should the auth providers handle logging internally (local to the auth packages)?
1. OR is a logging system the right thing to do?
1. Where should the core classes to support logging go? In the *Diagnostics* or *Common* packages?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.