Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSAL logging levels now correlate with the AzureEventSourceListener configured log level #44631

Merged
merged 5 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/identity/Azure.Identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Bugs Fixed

### Other Changes
- The logging level passed to MSAL now correlates to the log level configured on your configured `AzureEventSourceListener`. Previously, the log level was always set to `Microsoft.Identity.Client.LogLevel.Info`.

## 1.12.0 (2024-06-17)

Expand Down
56 changes: 55 additions & 1 deletion sdk/identity/Azure.Identity/src/AzureIdentityEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
using System.Text;
using Azure.Core;
using Azure.Core.Diagnostics;
using Microsoft.IdentityModel.Abstractions;

namespace Azure.Identity
{
[EventSource(Name = EventSourceName)]
internal sealed class AzureIdentityEventSource : AzureEventSource
internal sealed class AzureIdentityEventSource : AzureEventSource, IIdentityLogger
ahsonkhan marked this conversation as resolved.
Show resolved Hide resolved
{
private const string EventSourceName = "Azure-Identity";

Expand All @@ -26,6 +27,8 @@ internal sealed class AzureIdentityEventSource : AzureEventSource
private const int MsalLogInfoEvent = 8;
private const int MsalLogWarningEvent = 9;
private const int MsalLogErrorEvent = 10;
private const int MsalLogCriticalEvent = 23;
private const int MsalLogAlwaysEvent = 24;
private const int InteractiveAuthenticationThreadPoolExecutionEvent = 11;
private const int InteractiveAuthenticationInlineExecutionEvent = 12;
private const int DefaultAzureCredentialCredentialSelectedEvent = 13;
Expand All @@ -50,6 +53,45 @@ private AzureIdentityEventSource() : base(EventSourceName) { }

public static AzureIdentityEventSource Singleton { get; } = new AzureIdentityEventSource();

public bool IsEnabled(EventLogLevel eventLogLevel)
{
return eventLogLevel switch
{
EventLogLevel.Critical => IsEnabled(EventLevel.Critical, EventKeywords.All),
EventLogLevel.Error => IsEnabled(EventLevel.Error, EventKeywords.All),
EventLogLevel.Warning => IsEnabled(EventLevel.Warning, EventKeywords.All),
EventLogLevel.Informational => IsEnabled(EventLevel.Informational, EventKeywords.All),
EventLogLevel.Verbose => IsEnabled(EventLevel.Verbose, EventKeywords.All),
EventLogLevel.LogAlways => IsEnabled(EventLevel.LogAlways, EventKeywords.All),
_ => false,
};
}

public void Log(LogEntry entry)
{
switch (entry.EventLogLevel)
{
case EventLogLevel.Critical when IsEnabled(EventLevel.Critical, EventKeywords.All):
LogMsalCritical(entry.Message);
break;
case EventLogLevel.Error when IsEnabled(EventLevel.Error, EventKeywords.All):
LogMsalError(entry.Message);
break;
case EventLogLevel.Warning when IsEnabled(EventLevel.Warning, EventKeywords.All):
LogMsalWarning(entry.Message);
break;
case EventLogLevel.Informational when IsEnabled(EventLevel.Informational, EventKeywords.All):
LogMsalInformational(entry.Message);
break;
case EventLogLevel.Verbose when IsEnabled(EventLevel.Verbose, EventKeywords.All):
LogMsalVerbose(entry.Message);
break;
case EventLogLevel.LogAlways when IsEnabled(EventLevel.LogAlways, EventKeywords.All):
LogMsalAlways(entry.Message);
break;
}
}

[NonEvent]
public void GetToken(string method, TokenRequestContext context)
{
Expand Down Expand Up @@ -197,6 +239,12 @@ public void LogMsal(Microsoft.Identity.Client.LogLevel level, string message)
}
}

[Event(MsalLogCriticalEvent, Level = EventLevel.Critical, Message = "{0}")]
public void LogMsalCritical(string message)
{
WriteEvent(MsalLogCriticalEvent, message);
}

[Event(MsalLogErrorEvent, Level = EventLevel.Error, Message = "{0}")]
public void LogMsalError(string message)
{
Expand All @@ -221,6 +269,12 @@ public void LogMsalVerbose(string message)
WriteEvent(MsalLogVerboseEvent, message);
}

[Event(MsalLogAlwaysEvent, Level = EventLevel.LogAlways, Message = "{0}")]
public void LogMsalAlways(string message)
{
WriteEvent(MsalLogAlwaysEvent, message);
}

[NonEvent]
private static string FormatStringArray(string[] array)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ protected virtual async ValueTask<IConfidentialClientApplication> CreateClientCo

ConfidentialClientApplicationBuilder confClientBuilder = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithHttpClientFactory(new HttpPipelineClientFactory(Pipeline.HttpPipeline))
.WithLogging(LogMsal, enablePiiLogging: IsSupportLoggingEnabled);
.WithLogging(AzureIdentityEventSource.Singleton, enablePiiLogging: IsSupportLoggingEnabled);

// Special case for using appTokenProviderCallback, authority validation and instance metadata discovery should be disabled since we're not calling the STS
// The authority matches the one configured in the CredentialOptions.
Expand Down
2 changes: 1 addition & 1 deletion sdk/identity/Azure.Identity/src/MsalPublicClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected virtual ValueTask<IPublicClientApplication> CreateClientCoreAsync(bool
.Create(ClientId)
.WithAuthority(authorityUri)
.WithHttpClientFactory(new HttpPipelineClientFactory(Pipeline.HttpPipeline))
.WithLogging(LogMsal, enablePiiLogging: IsSupportLoggingEnabled);
.WithLogging(AzureIdentityEventSource.Singleton, enablePiiLogging: IsSupportLoggingEnabled);

if (!string.IsNullOrEmpty(RedirectUrl))
{
Expand Down
49 changes: 49 additions & 0 deletions sdk/identity/Azure.Identity/tests/CredentialTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,55 @@ public async Task RespectsIsSupportLoggingEnabled([Values(true, false)] bool isS
Assert.True(_listener.EventData.Any(d => d.Payload.Any(p => p.ToString().StartsWith($"{expectedPrefix} MSAL"))));
}

[Test]
[TestCase(EventLevel.Informational)]
ahsonkhan marked this conversation as resolved.
Show resolved Hide resolved
[TestCase(EventLevel.Verbose)]
public async Task ListenerEventLevelControlsMsalLogLevel(EventLevel eventLevel)
{
using var _listener = new TestEventListener();
_listener.EnableEvents(AzureIdentityEventSource.Singleton, eventLevel);

var token = Guid.NewGuid().ToString();
TransportConfig transportConfig = new()
{
TokenFactory = req => token
};
var factory = MockTokenTransportFactory(transportConfig);
var mockTransport = new MockTransport(factory);

var config = new CommonCredentialTestConfig()
{
TransportConfig = transportConfig,
Transport = mockTransport,
TenantId = TenantId,
IsUnsafeSupportLoggingEnabled = true
};
var credential = GetTokenCredential(config);
if (!CredentialTestHelpers.IsMsalCredential(credential))
{
Assert.Ignore($"{credential.GetType().Name} is not an MSAL credential.");
}
transportConfig.IsPubClient = CredentialTestHelpers.IsCredentialTypePubClient(credential);
AccessToken actualToken = await credential.GetTokenAsync(new TokenRequestContext(MockScopes.Default, null), default);

Assert.AreEqual(token, actualToken.Token);

Assert.True(_listener.EventData.Any(d => d.Level == EventLevel.Informational && d.EventName == "LogMsalInformational"));

switch (eventLevel)
{
case EventLevel.Informational:
Assert.False(_listener.EventData.Any(d => d.Level == EventLevel.Verbose && d.EventName == "LogMsalVerbose"));
christothes marked this conversation as resolved.
Show resolved Hide resolved
break;
case EventLevel.Verbose:
Assert.True(_listener.EventData.Any(d => d.Level == EventLevel.Verbose && d.EventName == "LogMsalVerbose"));
break;
default:
Assert.Fail("Unexpected event level");
break;
}
}

[Test]
[NonParallelizable]
public async Task DisableInstanceMetadataDiscovery([Values(true, false)] bool disable)
Expand Down