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

Add caller sdk id and version to telemetry server side and client side #4864

Merged
merged 24 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
83bf5c3
Add caller sdk id and version to telemetry server side and client side
neha-bhargava Jul 29, 2024
7d47da0
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Aug 5, 2024
a9f6234
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Aug 7, 2024
36a5709
Address comments
neha-bhargava Aug 7, 2024
92d495a
Address comments
neha-bhargava Aug 7, 2024
6f4fa3c
Add constraints and use WithClientName and WithClientVersion APIs
neha-bhargava Aug 12, 2024
89a52c8
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Aug 12, 2024
fe3f4e1
Update tests to expect null for client name and client version
neha-bhargava Aug 12, 2024
2581480
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Aug 13, 2024
def4dce
Update tests for telemetry
neha-bhargava Aug 13, 2024
b30ce09
Add tests
neha-bhargava Aug 14, 2024
f13b88d
Update src/client/Microsoft.Identity.Client/Platforms/Features/OpenTe…
neha-bhargava Aug 17, 2024
747b5e2
Update src/client/Microsoft.Identity.Client/Platforms/Features/OpenTe…
neha-bhargava Aug 17, 2024
476d338
Update src/client/Microsoft.Identity.Client/AppConfig/ApplicationConf…
neha-bhargava Aug 17, 2024
b0ebbff
Update src/client/Microsoft.Identity.Client/AppConfig/ApplicationConf…
neha-bhargava Aug 17, 2024
7366a19
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Sep 10, 2024
1e27ca2
Add caller sdk id and version tags to failed metrics as well
neha-bhargava Sep 11, 2024
331a6d2
Merge branch 'nebharg/ztaSupportSdkInfo' of https://github.com/AzureA…
neha-bhargava Sep 11, 2024
bd002f6
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Sep 11, 2024
b980895
Update src/client/Microsoft.Identity.Client/AppConfig/BaseAbstractApp…
neha-bhargava Sep 12, 2024
c1e38c2
Update src/client/Microsoft.Identity.Client/AppConfig/BaseAbstractApp…
neha-bhargava Sep 12, 2024
c93c8ce
Address comments
neha-bhargava Sep 12, 2024
7c8fc52
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Sep 12, 2024
ea52b17
Merge branch 'main' into nebharg/ztaSupportSdkInfo
neha-bhargava Sep 13, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,6 @@ protected T WithScopes(IEnumerable<string> scopes)
return this as T;
}

/// <summary>
/// Sets Extra Query Parameters for the query string in the HTTP authentication request.
/// </summary>
/// <param name="extraQueryParameters">This parameter will be appended as is to the query string in the HTTP authentication request to the authority
/// as a string of segments of the form <c>key=value</c> separated by an ampersand character.
/// The parameter can be null.</param>
/// <returns>The builder to chain the .With methods.</returns>
public T WithExtraQueryParameters(Dictionary<string, string> extraQueryParameters)
{
CommonParameters.ExtraQueryParameters = extraQueryParameters ??
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
return this as T;
}

/// <summary>
/// Sets claims in the query. Use when the AAD admin has enabled conditional access. Acquiring the token normally will result in a
/// <see cref="MsalUiRequiredException"/> with the <see cref="MsalServiceException.Claims"/> property set. Retry the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,20 @@ public T WithCorrelationId(Guid correlationId)
return (T)this;
}

/// <summary>
/// Sets Extra Query Parameters for the query string in the HTTP authentication request.
/// </summary>
/// <param name="extraQueryParameters">This parameter will be appended as is to the query string in the HTTP authentication request to the authority
/// as a string of segments of the form <c>key=value</c> separated by an ampersand character.
/// The parameter can be null.</param>
/// <returns>The builder to chain the .With methods.</returns>
public T WithExtraQueryParameters(Dictionary<string, string> extraQueryParameters)
{
CommonParameters.ExtraQueryParameters = extraQueryParameters ??
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
return this as T;
}

/// <summary>
/// Validates the parameters of the AcquireToken operation.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,28 +256,6 @@ public T WithTenantId(string tenantId)
return this as T;
}

/// <summary>
/// Sets the name of the calling application for telemetry purposes.
/// </summary>
/// <param name="clientName">The name of the application for telemetry purposes.</param>
/// <returns></returns>
public T WithClientName(string clientName)
{
Config.ClientName = GetValueIfNotEmpty(Config.ClientName, clientName);
return this as T;
}

/// <summary>
/// Sets the version of the calling application for telemetry purposes.
/// </summary>
/// <param name="clientVersion">The version of the calling application for telemetry purposes.</param>
/// <returns></returns>
public T WithClientVersion(string clientVersion)
{
Config.ClientVersion = GetValueIfNotEmpty(Config.ClientVersion, clientVersion);
return this as T;
}

/// <summary>
/// Sets application options, which can, for instance have been read from configuration files.
/// See https://aka.ms/msal-net-application-configuration.
Expand Down Expand Up @@ -643,10 +621,5 @@ public T WithB2CAuthority(string authorityUri)
}

#endregion

private static string GetValueIfNotEmpty(string original, string value)
{
return string.IsNullOrWhiteSpace(value) ? original : value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,21 @@ public ApplicationConfiguration(MsalClientType applicationType)
break;
}
}

public const string DefaultClientName = "UnknownClient";
public const string DefaultClientVersion = "0.0.0.0";

// For telemetry, the ClientName of the application.
private string _clientName = DefaultClientName;
private string _clientName;
public string ClientName
{
get => _clientName;
internal set { _clientName = string.IsNullOrWhiteSpace(value) ? DefaultClientName : value; }
internal set { _clientName = string.IsNullOrWhiteSpace(value) ? "" : value; }
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
}

// For telemetry, the ClientVersion of the application.
private string _clientVersion = DefaultClientVersion;
private string _clientVersion;
public string ClientVersion
{
get => _clientVersion;
internal set { _clientVersion = string.IsNullOrWhiteSpace(value) ? DefaultClientVersion : value; }
internal set { _clientVersion = string.IsNullOrWhiteSpace(value) ? "" : value; }
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
}

public Func<object> ParentActivityOrWindowFunc { get; internal set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,28 @@ public T WithExperimentalFeatures(bool enableExperimentalFeatures = true)
return (T)this;
}

/// <summary>
/// Sets the name of the calling SDK API Id for telemetry purposes.
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
/// <param name="clientName">The name of the SDK API Id for telemetry purposes.</param>
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
/// <returns></returns>
public T WithClientName(string clientName)
{
Config.ClientName = GetValueIfNotEmpty(Config.ClientName, clientName);
return this as T;
}

/// <summary>
/// Sets the version of the calling SDK for telemetry purposes.
/// </summary>
/// <param name="clientVersion">The version of the calling SDK for telemetry purposes.</param>
/// <returns></returns>
public T WithClientVersion(string clientVersion)
{
Config.ClientVersion = GetValueIfNotEmpty(Config.ClientVersion, clientVersion);
return this as T;
}

internal virtual ApplicationConfiguration BuildConfiguration()
{
ResolveAuthority();
Expand Down Expand Up @@ -295,5 +317,10 @@ internal void ValidateUseOfExperimentalFeature([System.Runtime.CompilerServices.
MsalErrorMessage.ExperimentalFeature(memberName));
}
}

internal static string GetValueIfNotEmpty(string original, string value)
{
return string.IsNullOrWhiteSpace(value) ? original : value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal class LoggerHelper

public static string GetClientInfo(string clientName, string clientVersion)
{
if (!string.IsNullOrEmpty(clientName) && !ApplicationConfiguration.DefaultClientName.Equals(clientName))
if (!string.IsNullOrEmpty(clientName))
{
// space is intentional for formatting of the message
if (string.IsNullOrEmpty(clientVersion))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ protected override async Task<AuthenticationResult> ExecuteAsync(CancellationTok
// Use a linked token source, in case the original cancellation token source is disposed before this background task completes.
using var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
return GetAccessTokenAsync(tokenSource.Token, logger);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkVersion);
}
}
catch (MsalServiceException e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ protected override async Task<AuthenticationResult> ExecuteAsync(CancellationTok
// Use a linked token source, in case the original cancellation token source is disposed before this background task completes.
using var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
return GetAccessTokenAsync(tokenSource.Token, logger);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkVersion);
}
}
catch (MsalServiceException e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ protected override async Task<AuthenticationResult> ExecuteAsync(CancellationTok
// Use a linked token source, in case the original cancellation token source is disposed before this background task completes.
using var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
return RefreshRtOrFetchNewAccessTokenAsync(tokenSource.Token);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkVersion);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using Microsoft.Identity.Client.TelemetryCore.TelemetryClient;
using Microsoft.Identity.Client.TelemetryCore.OpenTelemetry;
using Microsoft.Identity.Client.Internal.Broker;
using System.Runtime.ConstrainedExecution;

namespace Microsoft.Identity.Client.Internal.Requests
{
Expand Down Expand Up @@ -91,7 +92,7 @@ public async Task<AuthenticationResult> RunAsync(CancellationToken cancellationT

UpdateTelemetry(measureDurationResult.Milliseconds + measureTelemetryDurationResult.Milliseconds, apiEvent, authenticationResult);
LogMetricsFromAuthResult(authenticationResult, AuthenticationRequestParameters.RequestContext.Logger);
LogSuccessTelemetryToOtel(authenticationResult, apiEvent.ApiId, measureDurationResult.Microseconds);
LogSuccessTelemetryToOtel(authenticationResult, apiEvent, measureDurationResult.Microseconds);

return authenticationResult;
}
Expand All @@ -117,12 +118,14 @@ public async Task<AuthenticationResult> RunAsync(CancellationToken cancellationT
}
}

private void LogSuccessTelemetryToOtel(AuthenticationResult authenticationResult, ApiEvent.ApiIds apiId, long durationInUs)
private void LogSuccessTelemetryToOtel(AuthenticationResult authenticationResult, ApiEvent apiEvent, long durationInUs)
{
// Log metrics
ServiceBundle.PlatformProxy.OtelInstrumentation.LogSuccessMetrics(
ServiceBundle.PlatformProxy.GetProductName(),
apiId,
apiEvent.ApiId,
apiEvent.CallerSdkApiId,
apiEvent.CallerSdkVersion,
GetCacheLevel(authenticationResult),
durationInUs,
authenticationResult.AuthenticationResultMetadata,
Expand Down Expand Up @@ -242,12 +245,42 @@ private ApiEvent InitializeApiEvent(string accountId)
apiEvent.TokenType = AuthenticationRequestParameters.AuthenticationScheme.TelemetryTokenType;
apiEvent.AssertionType = GetAssertionType();

UpdateCallerSdkDetails(apiEvent);

// Give derived classes the ability to add or modify fields in the telemetry as needed.
EnrichTelemetryApiEvent(apiEvent);

return apiEvent;
}

private void UpdateCallerSdkDetails(ApiEvent apiEvent)
{
string callerSdkId;
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
string callerSdkVer;

// Check if ExtraQueryParameters contains caller-sdk-id and caller-sdk-ver
if (AuthenticationRequestParameters.ExtraQueryParameters.TryGetValue("caller-sdk-id", out callerSdkId))
{
AuthenticationRequestParameters.ExtraQueryParameters.Remove("caller-sdk-id");
}
else
{
callerSdkId = AuthenticationRequestParameters.RequestContext.ServiceBundle.Config.ClientName;
}

if (AuthenticationRequestParameters.ExtraQueryParameters.TryGetValue("caller-sdk-ver", out callerSdkVer))
{
AuthenticationRequestParameters.ExtraQueryParameters.Remove("caller-sdk-ver");
}
else
{
callerSdkVer = AuthenticationRequestParameters.RequestContext.ServiceBundle.Config.ClientVersion;
}

apiEvent.CallerSdkApiId = callerSdkId == null ? null : callerSdkId.Substring(0, Math.Min(callerSdkId.Length, 10));
apiEvent.CallerSdkVersion = callerSdkVer == null ? null : callerSdkVer.Substring(0, Math.Min(callerSdkVer.Length, 20));
}

private AssertionType GetAssertionType()
{
if (ServiceBundle.Config.IsManagedIdentity ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ public async Task<AuthenticationResult> ExecuteAsync(CancellationToken cancellat
// Use a linked token source, in case the original cancellation token source is disposed before this background task completes.
using var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
return RefreshRtOrFailAsync(tokenSource.Token);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId);
}, logger, ServiceBundle, AuthenticationRequestParameters.RequestContext.ApiEvent.ApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkApiId,
AuthenticationRequestParameters.RequestContext.ApiEvent.CallerSdkVersion);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ internal static void ProcessFetchInBackground(
Func<Task<AuthenticationResult>> fetchAction,
ILoggerAdapter logger,
IServiceBundle serviceBundle,
ApiEvent.ApiIds apiId)
ApiEvent.ApiIds apiId,
string callerSdkId,
string callerSdkVersion)
{
_ = Task.Run(async () =>
{
Expand All @@ -95,6 +97,8 @@ internal static void ProcessFetchInBackground(
serviceBundle.PlatformProxy.OtelInstrumentation.IncrementSuccessCounter(
serviceBundle.PlatformProxy.GetProductName(),
apiId,
callerSdkId,
callerSdkVersion,
TokenSource.IdentityProvider,
CacheRefreshReason.ProactivelyRefreshed,
Cache.CacheLevel.None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ private void AddClaims()
// no-op if resolvedClaims is null
_oAuth2Client.AddBodyParameter(OAuth2Parameter.Claims, resolvedClaims);
}

private void AddExtraHttpHeaders()
{
if (_requestParams.ExtraHttpHeaders != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public OtelInstrumentation()
public void LogSuccessMetrics(
string platform,
ApiEvent.ApiIds apiId,
string callerSdkId,
string callerSdkVersion,
CacheLevel cacheLevel,
long totalDurationInUs,
AuthenticationResultMetadata authResultMetadata,
Expand All @@ -100,6 +102,8 @@ public void LogSuccessMetrics(
IncrementSuccessCounter(
platform,
apiId,
callerSdkId,
callerSdkVersion,
authResultMetadata.TokenSource,
authResultMetadata.CacheRefreshReason,
cacheLevel,
Expand Down Expand Up @@ -151,6 +155,8 @@ public void LogSuccessMetrics(

public void IncrementSuccessCounter(string platform,
ApiEvent.ApiIds apiId,
string callerSdkId,
string callerSdkVersion,
TokenSource tokenSource,
CacheRefreshReason cacheRefreshReason,
CacheLevel cacheLevel,
Expand All @@ -162,6 +168,8 @@ public void IncrementSuccessCounter(string platform,
new(TelemetryConstants.MsalVersion, MsalIdHelper.GetMsalVersion()),
new(TelemetryConstants.Platform, platform),
new(TelemetryConstants.ApiId, apiId),
new(TelemetryConstants.CallerSdkId, callerSdkId ?? ""),
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
new(TelemetryConstants.CallerSdkVersion, callerSdkVersion ?? ""),
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
new(TelemetryConstants.TokenSource, tokenSource),
new(TelemetryConstants.CacheRefreshReason, cacheRefreshReason),
new(TelemetryConstants.CacheLevel, cacheLevel));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal class HttpTelemetryManager : IHttpTelemetryManager
{
/// <summary>
/// Expected format: 5|api_id,cache_info,region_used,region_autodetection,region_outcome|platform_config
/// platform_config: is_token_cache_serialized,is_legacy_cache_enabled, token_type
/// platform_config: is_token_cache_serialized,is_legacy_cache_enabled, token_type, caller_sdk_id, caller_sdk_version
/// </summary>
public string GetCurrentRequestHeader(ApiEvent eventInProgress)
{
Expand Down Expand Up @@ -51,6 +51,10 @@ public string GetCurrentRequestHeader(ApiEvent eventInProgress)
sb.Append(TelemetryConstants.CommaDelimiter);
// Token type is to indicate 1 - bearer, 2 - pop, 3 - ssh-cert, 4 - external.
sb.Append(eventInProgress.TokenTypeString);
sb.Append(TelemetryConstants.CommaDelimiter);
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
sb.Append(eventInProgress.CallerSdkApiId);
sb.Append(TelemetryConstants.CommaDelimiter);
sb.Append(eventInProgress.CallerSdkVersion);

return sb.ToString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ public string TokenTypeString
public CacheLevel CacheLevel { get; set; }

public string MsalRuntimeTelemetry { get; set; }


public string CallerSdkApiId { get; set; }

public string CallerSdkVersion { get; set; }

public static bool IsLongRunningObo(ApiIds apiId) => apiId == ApiIds.InitiateLongRunningObo || apiId == ApiIds.AcquireTokenInLongRunningObo;

public static bool IsOnBehalfOfRequest(ApiIds apiId) => apiId == ApiIds.AcquireTokenOnBehalfOf || IsLongRunningObo(apiId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ internal interface IOtelInstrumentation
internal void LogSuccessMetrics(
string platform,
ApiEvent.ApiIds apiId,
string callerSdkId,
string callerSdkVersion,
CacheLevel cacheLevel,
long totalDurationInUs,
AuthenticationResultMetadata authResultMetadata,
ILoggerAdapter logger);

internal void IncrementSuccessCounter(string platform,
ApiEvent.ApiIds apiId,
string callerSdkId,
string callerSdkVersion,
TokenSource tokenSource,
CacheRefreshReason cacheRefreshReason,
CacheLevel cacheLevel,
neha-bhargava marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading