mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Merge pull request #2029 from DuendeSoftware/beh/token-count-diagnostic-entry
Token Issue Count Diagnostic Entry
This commit is contained in:
commit
6b3ef3a18d
6 changed files with 434 additions and 2 deletions
|
|
@ -218,6 +218,7 @@ public static class IdentityServerBuilderExtensionsCore
|
|||
builder.Services.AddSingleton<IDiagnosticEntry, RegisteredImplementationsDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<IDiagnosticEntry, IdentityServerOptionsDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<IDiagnosticEntry, DataProtectionDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<IDiagnosticEntry, TokenIssueCountDiagnosticEntry>();
|
||||
builder.Services.AddSingleton<DiagnosticSummary>();
|
||||
builder.Services.AddHostedService<DiagnosticHostedService>();
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,12 @@ internal abstract class AuthorizeEndpointBase : IEndpointHandler
|
|||
Telemetry.Metrics.TokenIssued(
|
||||
response.Request.ClientId,
|
||||
response.Request.GrantType,
|
||||
response.Request.AuthorizeRequestType);
|
||||
response.Request.AuthorizeRequestType,
|
||||
response.AccessToken.IsPresent(),
|
||||
response.AccessToken.IsPresent() ? response.Request.AccessTokenType : null,
|
||||
false,
|
||||
ProofType.None,
|
||||
response.IdentityToken.IsPresent());
|
||||
return _events.RaiseAsync(new TokenIssuedSuccessEvent(response));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,10 @@ internal class TokenEndpoint : IEndpointHandler
|
|||
var response = await _responseGenerator.ProcessAsync(requestResult);
|
||||
|
||||
await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult));
|
||||
Telemetry.Metrics.TokenIssued(clientResult.Client.ClientId, requestResult.ValidatedRequest.GrantType, null);
|
||||
|
||||
Telemetry.Metrics.TokenIssued(clientResult.Client.ClientId, requestResult.ValidatedRequest.GrantType, null,
|
||||
response.AccessToken.IsPresent(), response.AccessTokenType.IsPresent() ? requestResult.ValidatedRequest.AccessTokenType : null, response.RefreshToken.IsPresent(),
|
||||
requestResult.ValidatedRequest.ProofType, response.IdentityToken.IsPresent());
|
||||
LogTokens(response, requestResult);
|
||||
|
||||
// return result
|
||||
|
|
|
|||
|
|
@ -0,0 +1,186 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
#nullable enable
|
||||
using System.Diagnostics.Metrics;
|
||||
using System.Text.Json;
|
||||
using Duende.IdentityServer.Models;
|
||||
|
||||
namespace Duende.IdentityServer.Licensing.V2.Diagnostics.DiagnosticEntries;
|
||||
|
||||
internal class TokenIssueCountDiagnosticEntry : IDiagnosticEntry
|
||||
{
|
||||
private long _jwtTokenIssued;
|
||||
private long _referenceTokenIssued;
|
||||
private long _refreshTokenIssued;
|
||||
private long _jwtPoPDPoPTokenIssued;
|
||||
private long _referencePoPDPoPTokenIssued;
|
||||
private long _jwtPoPmTLSTokenIssued;
|
||||
private long _referencePoPmTLSTokenIssued;
|
||||
private long _idTokenIssued;
|
||||
|
||||
private long _implicitGrantTypeFlows;
|
||||
private long _hybridGrantTypeFlows;
|
||||
private long _authorizationCodeGrantTypeFlows;
|
||||
private long _clientCredentialsGrantTypeFlows;
|
||||
private long _resourceOwnerPasswordGrantTypeFlows;
|
||||
private long _deviceFlowGrantTypeFlows;
|
||||
private long _otherGrantTypeFlows;
|
||||
|
||||
private readonly MeterListener _meterListener;
|
||||
|
||||
public TokenIssueCountDiagnosticEntry()
|
||||
{
|
||||
_meterListener = new MeterListener();
|
||||
|
||||
_meterListener.InstrumentPublished += (instrument, listener) =>
|
||||
{
|
||||
if (instrument.Name == Telemetry.Metrics.Counters.TokenIssued)
|
||||
{
|
||||
listener.EnableMeasurementEvents(instrument);
|
||||
}
|
||||
};
|
||||
|
||||
_meterListener.SetMeasurementEventCallback<long>(HandleLongMeasurementRecorded);
|
||||
|
||||
_meterListener.Start();
|
||||
}
|
||||
|
||||
public Task WriteAsync(Utf8JsonWriter writer)
|
||||
{
|
||||
writer.WritePropertyName("TokenIssueCounts");
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WriteNumber("Jwt", _jwtTokenIssued);
|
||||
writer.WriteNumber("Reference", _referenceTokenIssued);
|
||||
writer.WriteNumber("JwtPoPDPoP", _jwtPoPDPoPTokenIssued);
|
||||
writer.WriteNumber("ReferencePoPDPoP", _referencePoPDPoPTokenIssued);
|
||||
writer.WriteNumber("JwtPoPmTLS", _jwtPoPmTLSTokenIssued);
|
||||
writer.WriteNumber("ReferencePoPmTLS", _referencePoPmTLSTokenIssued);
|
||||
writer.WriteNumber("Refresh", _refreshTokenIssued);
|
||||
writer.WriteNumber("Id", _idTokenIssued);
|
||||
writer.WriteNumber(GrantType.Implicit, _implicitGrantTypeFlows);
|
||||
writer.WriteNumber(GrantType.Hybrid, _hybridGrantTypeFlows);
|
||||
writer.WriteNumber(GrantType.AuthorizationCode, _authorizationCodeGrantTypeFlows);
|
||||
writer.WriteNumber(GrantType.ClientCredentials, _clientCredentialsGrantTypeFlows);
|
||||
writer.WriteNumber(GrantType.ResourceOwnerPassword, _resourceOwnerPasswordGrantTypeFlows);
|
||||
writer.WriteNumber(GrantType.DeviceFlow, _deviceFlowGrantTypeFlows);
|
||||
writer.WriteNumber("Other", _otherGrantTypeFlows);
|
||||
|
||||
writer.WriteEndObject();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void HandleLongMeasurementRecorded(Instrument instrument, long value, ReadOnlySpan<KeyValuePair<string, object?>> tags, object? state)
|
||||
{
|
||||
if (instrument.Name != Telemetry.Metrics.Counters.TokenIssued)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var accessTokenIssued = false;
|
||||
var accessTokenType = AccessTokenType.Jwt;
|
||||
var refreshTokenIssued = false;
|
||||
var proofType = ProofType.None;
|
||||
var identityTokenIssued = false;
|
||||
var grantType = string.Empty;
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
switch (tag.Key)
|
||||
{
|
||||
case Telemetry.Metrics.Tags.AccessTokenType:
|
||||
if (!Enum.TryParse(tag.Value?.ToString(), out accessTokenType))
|
||||
{
|
||||
accessTokenType = AccessTokenType.Jwt;
|
||||
}
|
||||
break;
|
||||
case Telemetry.Metrics.Tags.RefreshTokenIssued:
|
||||
bool.TryParse(tag.Value?.ToString(), out refreshTokenIssued);
|
||||
break;
|
||||
case Telemetry.Metrics.Tags.ProofType:
|
||||
if (!Enum.TryParse(tag.Value?.ToString(), out proofType))
|
||||
{
|
||||
proofType = ProofType.None;
|
||||
}
|
||||
break;
|
||||
case Telemetry.Metrics.Tags.AccessTokenIssued:
|
||||
bool.TryParse(tag.Value?.ToString(), out accessTokenIssued);
|
||||
break;
|
||||
case Telemetry.Metrics.Tags.IdTokenIssued:
|
||||
bool.TryParse(tag.Value?.ToString(), out identityTokenIssued);
|
||||
break;
|
||||
case Telemetry.Metrics.Tags.GrantType:
|
||||
grantType = tag.Value?.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (accessTokenIssued)
|
||||
{
|
||||
switch (proofType)
|
||||
{
|
||||
case ProofType.None when accessTokenType == AccessTokenType.Jwt:
|
||||
Interlocked.Increment(ref _jwtTokenIssued);
|
||||
break;
|
||||
case ProofType.None when accessTokenType == AccessTokenType.Reference:
|
||||
Interlocked.Increment(ref _referenceTokenIssued);
|
||||
break;
|
||||
case ProofType.DPoP when accessTokenType == AccessTokenType.Jwt:
|
||||
Interlocked.Increment(ref _jwtPoPDPoPTokenIssued);
|
||||
break;
|
||||
case ProofType.DPoP when accessTokenType == AccessTokenType.Reference:
|
||||
Interlocked.Increment(ref _referencePoPDPoPTokenIssued);
|
||||
break;
|
||||
case ProofType.ClientCertificate when accessTokenType == AccessTokenType.Jwt:
|
||||
Interlocked.Increment(ref _jwtPoPmTLSTokenIssued);
|
||||
break;
|
||||
case ProofType.ClientCertificate when accessTokenType == AccessTokenType.Reference:
|
||||
Interlocked.Increment(ref _referencePoPmTLSTokenIssued);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshTokenIssued)
|
||||
{
|
||||
Interlocked.Increment(ref _refreshTokenIssued);
|
||||
}
|
||||
|
||||
if (identityTokenIssued)
|
||||
{
|
||||
Interlocked.Increment(ref _idTokenIssued);
|
||||
}
|
||||
|
||||
var tokenWasIssued = accessTokenIssued || refreshTokenIssued || identityTokenIssued;
|
||||
if (!tokenWasIssued || string.IsNullOrEmpty(grantType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (grantType)
|
||||
{
|
||||
case GrantType.Implicit:
|
||||
Interlocked.Increment(ref _implicitGrantTypeFlows);
|
||||
break;
|
||||
case GrantType.Hybrid:
|
||||
Interlocked.Increment(ref _hybridGrantTypeFlows);
|
||||
break;
|
||||
case GrantType.AuthorizationCode:
|
||||
Interlocked.Increment(ref _authorizationCodeGrantTypeFlows);
|
||||
break;
|
||||
case GrantType.ClientCredentials:
|
||||
Interlocked.Increment(ref _clientCredentialsGrantTypeFlows);
|
||||
break;
|
||||
case GrantType.ResourceOwnerPassword:
|
||||
Interlocked.Increment(ref _resourceOwnerPasswordGrantTypeFlows);
|
||||
break;
|
||||
case GrantType.DeviceFlow:
|
||||
Interlocked.Increment(ref _deviceFlowGrantTypeFlows);
|
||||
break;
|
||||
default:
|
||||
Interlocked.Increment(ref _otherGrantTypeFlows);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
|
||||
using System.Diagnostics.Metrics;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Validation;
|
||||
|
||||
namespace Duende.IdentityServer;
|
||||
|
|
@ -65,6 +66,11 @@ public static class Telemetry
|
|||
public const string Scheme = "scheme";
|
||||
public const string Result = "result";
|
||||
public const string Type = "type";
|
||||
public const string AccessTokenIssued = "access_token_issued";
|
||||
public const string AccessTokenType = "access_token_type";
|
||||
public const string RefreshTokenIssued = "refresh_token_issued";
|
||||
public const string ProofType = "proof_type";
|
||||
public const string IdTokenIssued = "id_token_issued";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -436,12 +442,14 @@ public static class Telemetry
|
|||
public static readonly Counter<long> TokenIssuedCounter =
|
||||
Meter.CreateCounter<long>(Counters.TokenIssued);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to increase <see cref="TokenIssuedCounter"/>
|
||||
/// </summary>
|
||||
/// <param name="clientId">Client Id</param>
|
||||
/// <param name="grantType">Grant Type</param>
|
||||
/// <param name="requestType">Type of authorization request</param>
|
||||
[Obsolete("This overload will be removed in a future version. Use the overload with accessTokenIssued, accessTokenType, refreshTokenIssued, proofType, and idTokenIssued parameters instead.")]
|
||||
public static void TokenIssued(string clientId, string grantType, AuthorizeRequestType? requestType)
|
||||
{
|
||||
Success(clientId);
|
||||
|
|
@ -451,6 +459,32 @@ public static class Telemetry
|
|||
new(Tags.AuthorizeRequestType, requestType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to increase <see cref="TokenIssuedCounter"/>
|
||||
/// </summary>
|
||||
/// <param name="clientId">Client Id</param>
|
||||
/// <param name="grantType">Grant Type</param>
|
||||
/// <param name="requestType">Type of authorization request</param>
|
||||
/// <param name="accessTokenIssued">Whether an access token was issued</param>
|
||||
/// <param name="accessTokenType">The type of access token issued (Null if no access token was issued, otherwise JWT or Reference)</param>
|
||||
/// <param name="refreshTokenIssued">Whether a refresh token was issued</param>
|
||||
/// <param name="proofType">The proof type used (None, ClientCertificate, or DPoP)</param>
|
||||
/// <param name="idTokenIssued">Whether an id token was issued</param>
|
||||
public static void TokenIssued(string clientId, string grantType, AuthorizeRequestType? requestType,
|
||||
bool accessTokenIssued, AccessTokenType? accessTokenType, bool refreshTokenIssued, ProofType proofType, bool idTokenIssued)
|
||||
{
|
||||
Success(clientId);
|
||||
TokenIssuedCounter.Add(1,
|
||||
new(Tags.Client, clientId),
|
||||
new(Tags.GrantType, grantType),
|
||||
new(Tags.AuthorizeRequestType, requestType),
|
||||
new(Tags.AccessTokenIssued, accessTokenIssued),
|
||||
new(Tags.AccessTokenType, accessTokenType),
|
||||
new(Tags.RefreshTokenIssued, refreshTokenIssued),
|
||||
new(Tags.ProofType, proofType),
|
||||
new(Tags.IdTokenIssued, idTokenIssued));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to increase <see cref="TokenIssuedCounter"/> on errors
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using Duende.IdentityServer.Licensing.V2.Diagnostics.DiagnosticEntries;
|
||||
using Duende.IdentityServer.Models;
|
||||
|
||||
namespace IdentityServer.UnitTests.Licensing.V2.DiagnosticEntries;
|
||||
|
||||
public class TokenIssueCountDiagnosticEntryTests
|
||||
{
|
||||
private readonly TokenIssueCountDiagnosticEntry _subject = new();
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_JwtAccessToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("Jwt").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_JwtReferenceToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Reference, false, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("Reference").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_JwtDPoPToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.DPoP, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("JwtPoPDPoP").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_ReferenceDPoPToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Reference, false, ProofType.DPoP, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("ReferencePoPDPoP").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_JwtMTlsToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.ClientCertificate, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("JwtPoPmTLS").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_ReferenceMTlsToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Reference, false, ProofType.ClientCertificate, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("ReferencePoPmTLS").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_RefreshToken()
|
||||
{
|
||||
IssueToken("refresh_token", false, AccessTokenType.Jwt, true, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("Refresh").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Count_IdToken()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, false, AccessTokenType.Jwt, false, ProofType.None, true);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
result.RootElement.GetProperty("TokenIssueCounts").GetProperty("Id").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Handle_Multiple_Token_Types()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, true, ProofType.None, false);
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.DPoP, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
tokenIssueCounts.GetProperty("Jwt").GetInt64().ShouldBe(1);
|
||||
tokenIssueCounts.GetProperty("JwtPoPDPoP").GetInt64().ShouldBe(1);
|
||||
tokenIssueCounts.GetProperty("Refresh").GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Handle_No_Token_Issued()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, false, null, false, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
tokenIssueCounts.GetProperty("Jwt").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("Reference").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("JwtPoPDPoP").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("JwtPoPmTLS").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("ReferencePoPDPoP").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("ReferencePoPmTLS").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("Refresh").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("Id").GetInt64().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Handle_Initial_Grant_Type_Count()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
tokenIssueCounts.GetProperty(GrantType.AuthorizationCode).GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Handle_Multiple_Grant_Type_Counts()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
IssueToken(GrantType.ClientCredentials, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
tokenIssueCounts.GetProperty(GrantType.AuthorizationCode).GetInt64().ShouldBe(1);
|
||||
tokenIssueCounts.GetProperty(GrantType.ClientCredentials).GetInt64().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Handle_Multiple_Grant_Type_Counts_With_Grant_Type()
|
||||
{
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
IssueToken(GrantType.AuthorizationCode, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
tokenIssueCounts.GetProperty(GrantType.AuthorizationCode).GetInt64().ShouldBe(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Handle_Grant_Type_Counts_For_All_Grant_Types()
|
||||
{
|
||||
var grantTypes = typeof(GrantType).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
|
||||
.Where(field => field.IsLiteral && !field.IsInitOnly)
|
||||
.Select(field => field.GetValue(null)?.ToString())
|
||||
.Where(value => value != null);
|
||||
foreach (var grantType in grantTypes)
|
||||
{
|
||||
IssueToken(grantType, true, AccessTokenType.Jwt, false, ProofType.None, false);
|
||||
}
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
foreach (var grantType in grantTypes)
|
||||
{
|
||||
tokenIssueCounts.GetProperty(grantType).GetInt64().ShouldBe(1);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Should_Ignore_Non_TokenIssued_Instruments()
|
||||
{
|
||||
Duende.IdentityServer.Telemetry.Metrics.TokenIssuedFailure("ClientId", "GrantType", null, "error");
|
||||
|
||||
var result = await DiagnosticEntryTestHelper.WriteEntryToJson(_subject);
|
||||
|
||||
var tokenIssueCounts = result.RootElement.GetProperty("TokenIssueCounts");
|
||||
tokenIssueCounts.GetProperty("Jwt").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("Reference").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("JwtPoPDPoP").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("JwtPoPmTLS").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("ReferencePoPDPoP").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("ReferencePoPmTLS").GetInt64().ShouldBe(0);
|
||||
tokenIssueCounts.GetProperty("Refresh").GetInt64().ShouldBe(0);
|
||||
}
|
||||
|
||||
private void IssueToken(string grantType, bool accessTokenIssued, AccessTokenType? accessTokenType, bool refreshTokenIssued,
|
||||
ProofType proofType, bool idTokenIssued) =>
|
||||
Duende.IdentityServer.Telemetry.Metrics.TokenIssued("ClientId", grantType, null, accessTokenIssued, accessTokenType, refreshTokenIssued, proofType, idTokenIssued);
|
||||
}
|
||||
Loading…
Reference in a new issue