Skip to content

Commit

Permalink
Westinm/downstreamapi-logging (#2206)
Browse files Browse the repository at this point in the history
  • Loading branch information
westin-m authored Apr 18, 2023
1 parent 47f1066 commit d87870c
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,23 @@ internal partial class DownstreamApi : IDownstreamApi
where TOutput : class
{
DownstreamApiOptions effectiveOptions = MergeOptions(serviceName, downstreamApiOptionsOverride, HttpMethod.Get);
HttpResponseMessage response = await CallApiInternalAsync(serviceName, effectiveOptions, false, null, user, cancellationToken).ConfigureAwait(false);

return await DeserializeOutput<TOutput>(response, effectiveOptions).ConfigureAwait(false);

try
{
HttpResponseMessage response = await CallApiInternalAsync(serviceName, effectiveOptions, false, null, user, cancellationToken).ConfigureAwait(false);
return await DeserializeOutput<TOutput>(response, effectiveOptions).ConfigureAwait(false);
}
catch(Exception ex) when (
ex is InvalidOperationException
|| ex is HttpRequestException)
{
Logger.HttpRequestError(
_logger,
serviceName!,
effectiveOptions.BaseUrl!,
effectiveOptions.RelativePath!, ex);
throw;
}
}

/// <inheritdoc/>
Expand Down
57 changes: 57 additions & 0 deletions src/Microsoft.Identity.Web.DownstreamApi/DownstreamApi.Logger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Microsoft.Extensions.Logging;

namespace Microsoft.Identity.Web
{
/// <summary>
/// LoggerMessage class for DownstreamApi.
/// </summary>
internal partial class DownstreamApi
{
internal static class Logger
{
private static readonly Action<ILogger, string, string, string, Exception?> s_httpRequestError =
LoggerMessage.Define<string, string, string>(
LogLevel.Debug,
DownstreamApiLoggingEventId.HttpRequestError,
"[MsIdWeb] An error occurred during HTTP Request. " +
"ServiceName: {serviceName}, " +
"BaseUrl: {BaseUrl}, " +
"RelativePath: {RelativePath} ");

private static readonly Action<ILogger, Exception?> s_unauthenticatedApiCall =
LoggerMessage.Define(
LogLevel.Information,
DownstreamApiLoggingEventId.UnauthenticatedApiCall,
"[MsIdWeb] An unauthenticated call was made to the Api with null Scopes");


/// <summary>
/// Logger for handling options exceptions in DownstreamApi.
/// </summary>
/// <param name="logger">ILogger.</param>
/// <param name="ServiceName">Name of API receiving request.</param>
/// <param name="BaseUrl">Base url from appsettings.</param>
/// <param name="RelativePath">Relative path from appsettings.</param>
/// <param name="ex">Exception.</param>
public static void HttpRequestError(
ILogger logger,
string ServiceName,
string BaseUrl,
string RelativePath,
Exception? ex) => s_httpRequestError(logger, ServiceName, BaseUrl, RelativePath, ex);

/// <summary>
/// Logger for unauthenticated internal API call in DownstreamApi.
/// </summary>
/// <param name="logger">Logger.</param>
/// <param name="ex">Exception.</param>
public static void UnauthenticatedApiCall(
ILogger logger,
Exception? ex) => s_unauthenticatedApiCall(logger, ex);
}
}
}
12 changes: 10 additions & 2 deletions src/Microsoft.Identity.Web.DownstreamApi/DownstreamApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Abstractions;

Expand All @@ -21,23 +22,26 @@ internal partial class DownstreamApi : IDownstreamApi
private readonly IAuthorizationHeaderProvider _authorizationHeaderProvider;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IOptionsMonitor<DownstreamApiOptions> _namedDownstreamApiOptions;
private const string ScopesNotConfiguredInConfigurationOrViaDelegate = "IDW10107: Scopes need to be passed-in either by configuration or by the delegate overriding it. ";
private const string Authorization = "Authorization";
protected readonly ILogger<DownstreamApi> _logger;

/// <summary>
/// Constructor.
/// </summary>
/// <param name="authorizationHeaderProvider">Authorization header provider.</param>
/// <param name="namedDownstreamApiOptions">Named options provider.</param>
/// <param name="httpClientFactory">HTTP client factory.</param>
/// <param name="logger">Logger.</param>
public DownstreamApi(
IAuthorizationHeaderProvider authorizationHeaderProvider,
IOptionsMonitor<DownstreamApiOptions> namedDownstreamApiOptions,
IHttpClientFactory httpClientFactory)
IHttpClientFactory httpClientFactory,
ILogger<DownstreamApi> logger)
{
_authorizationHeaderProvider = authorizationHeaderProvider;
_namedDownstreamApiOptions = namedDownstreamApiOptions;
_httpClientFactory = httpClientFactory;
_logger = logger;
}

/// <inheritdoc/>
Expand Down Expand Up @@ -306,6 +310,10 @@ await _authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(
cancellationToken).ConfigureAwait(false);
httpRequestMessage.Headers.Add(Authorization, authorizationHeader);
}
else
{
Logger.UnauthenticatedApiCall(_logger, null);
}
// Opportunity to change the request message
effectiveOptions.CustomizeHttpRequestMessage?.Invoke(httpRequestMessage);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.Identity.Abstractions;

namespace Microsoft.Identity.Web
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.Extensions.Logging;

namespace Microsoft.Identity.Web
{
internal static class DownstreamApiLoggingEventId
{
#pragma warning disable IDE1006 // Naming styles
// DownstreamApi EventIds 100+
public static readonly EventId HttpRequestError = new(100, "HttpRequestError");
public static readonly EventId UnauthenticatedApiCall = new(101, "UnauthenticatedApiCall");
#pragma warning restore IDE1006 // Naming styles
}
}

0 comments on commit d87870c

Please sign in to comment.