Skip to content

Commit

Permalink
Merge pull request #700 from leancodepl/more-tracing
Browse files Browse the repository at this point in the history
Improve tracing across CQRS elements
  • Loading branch information
jakubfijalkowski authored Sep 11, 2024
2 parents 77527f3 + 01fe825 commit a370c5d
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 15 deletions.
11 changes: 6 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
but this project DOES NOT adhere to [Semantic Versioning](http://semver.org/).

## 8.1 (Unreleased)
## 8.1
* `LeanCode.Kratos` has switched from official (and at the time outdated) client package `Ory.Kratos.Client` to our own `LeanCode.Kratos.Client` that is maintained at https://github.com/leancodepl/dotnet-kratos-client and with this the usage has changed:
* Underlying JSON (de)serializer is now STJ instead of JSON.NET
* Values returned from client's API calls are now wrapped in response objects that provide additional info
* Models were rebuilt, adding support for NRT and wrapping optional properties in `Option<T>` (importantly, the latter can change how identity metadata should be read)
* The client comes with its own DI registration extensions, changing how it should be added to DI container
* Underlying JSON (de)serializer is now STJ instead of JSON.NET
* Values returned from client's API calls are now wrapped in response objects that provide additional info
* Models were rebuilt, adding support for NRT and wrapping optional properties in `Option<T>` (importantly, the latter can change how identity metadata should be read)
* The client comes with its own DI registration extensions, changing how it should be added to DI container
* Better tracing across CQRS executions

## 8.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using LeanCode.OpenTelemetry;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection;

namespace LeanCode.CQRS.AspNetCore.Local;
Expand Down Expand Up @@ -41,8 +40,10 @@ CancellationToken cancellationToken
{
var metadata = objectSource.MetadataFor(obj.GetType());

using var activity = LeanCodeActivitySource.ActivitySource.StartActivity("pipeline.action.local");
activity?.AddTag("object", metadata.ObjectType.FullName);
using var activity = LeanCodeActivitySource.StartExecution("Local", metadata.ObjectType.FullName);
activity?.AddTag("object.kind", metadata.ObjectKind.ToString());
activity?.AddTag("object.type", metadata.ObjectType.FullName);
activity?.AddTag("object.handler", metadata.HandlerType.FullName);

await using var scope = serviceProvider.CreateAsyncScope();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using LeanCode.Contracts;
using LeanCode.Contracts.Validation;
using LeanCode.CQRS.Execution;
using LeanCode.OpenTelemetry;
using Microsoft.AspNetCore.Http;
using Serilog;

Expand Down Expand Up @@ -35,6 +36,9 @@ public async Task InvokeAsync(HttpContext httpContext)
}
catch (CommandExecutionInvalidException ex)
{
using var activity = LeanCodeActivitySource.StartMiddleware("ExceptionTranslation");
activity?.SetTag("error.code", ex.ErrorCode);

var result = WrapInCommandResult(ex);
logger.Warning("Command {@Command} is not valid with result {@Result}", cqrsPayload.Payload, result);
var executionResult = ExecutionResult.WithPayload(result, StatusCodes.Status422UnprocessableEntity);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using LeanCode.Contracts.Security;
using LeanCode.CQRS.Execution;
using LeanCode.CQRS.Security;
using LeanCode.OpenTelemetry;
using Microsoft.AspNetCore.Http;
using Serilog;

Expand Down Expand Up @@ -41,12 +42,12 @@ public async Task InvokeAsync(HttpContext context)
foreach (var customAuthorizerDefinition in customAuthorizers)
{
var authorizerType = customAuthorizerDefinition.Authorizer;
var customAuthorizer = context.RequestServices.GetService(authorizerType) as IHttpContextCustomAuthorizer;
using var activity = LeanCodeActivitySource.StartMiddleware("Security", authorizerType.FullName);
activity?.SetTag("authorizer.type", authorizerType.FullName);

if (customAuthorizer is null)
{
throw new CustomAuthorizerNotFoundException(authorizerType);
}
var customAuthorizer =
context.RequestServices.GetService(authorizerType) as IHttpContextCustomAuthorizer
?? throw new CustomAuthorizerNotFoundException(authorizerType);

var authorized = await customAuthorizer.CheckIfAuthorizedAsync(
context,
Expand All @@ -56,6 +57,7 @@ public async Task InvokeAsync(HttpContext context)

if (!authorized)
{
activity?.SetTag("authorizer.authorized", false);
logger.Warning(
"User is not authorized for {@Object}, authorizer {AuthorizerType} did not pass",
payload.Payload,
Expand All @@ -66,6 +68,10 @@ public async Task InvokeAsync(HttpContext context)
metrics.CQRSFailure(CQRSMetrics.AuthorizationFailure);
return;
}
else
{
activity?.SetTag("authorizer.authorized", true);
}
}

await next(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public async Task InvokeAsync(HttpContext httpContext)
{
var cqrsMetadata = httpContext.GetCQRSObjectMetadata();

using var activity = LeanCodeActivitySource.Start(
$"{cqrsMetadata.ObjectKind}Handler {cqrsMetadata.HandlerType.FullName}"
using var activity = LeanCodeActivitySource.StartExecution(
cqrsMetadata.ObjectKind.ToString(),
cqrsMetadata.HandlerType.FullName
);
activity?.AddTag("object.kind", cqrsMetadata.ObjectKind.ToString());
activity?.AddTag("object.type", cqrsMetadata.ObjectType.FullName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using LeanCode.Contracts;
using LeanCode.CQRS.Execution;
using LeanCode.CQRS.Validation;
using LeanCode.OpenTelemetry;
using Microsoft.AspNetCore.Http;

namespace LeanCode.CQRS.AspNetCore.Middleware;
Expand Down Expand Up @@ -32,7 +33,11 @@ public async Task InvokeAsync(HttpContext httpContext, ICommandValidatorResolver

if (validator is not null)
{
using var activity = LeanCodeActivitySource.StartMiddleware("Validation");
activity?.SetTag("validation.validator", validator.GetType().FullName);

var result = await validator.ValidateAsync(httpContext, (ICommand)payload.Payload);
activity?.SetTag("validation.valid", result.IsValid);

if (!result.IsValid)
{
Expand Down
7 changes: 7 additions & 0 deletions src/Infrastructure/LeanCode.OpenTelemetry/ActivitySource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ public static class LeanCodeActivitySource
public static readonly ActivitySource ActivitySource = new("LeanCode.CoreLibrary");

public static Activity? Start(string name) => ActivitySource.StartActivity(name);

public static Activity? StartExecution(string type, string? objectType) => Start($"{type} - {objectType}");

public static Activity? StartMiddleware(string middlewareName) => Start($"middleware - {middlewareName}");

public static Activity? StartMiddleware(string middlewareName, string? objectName) =>
Start($"middleware - {middlewareName} - {objectName}");
}

0 comments on commit a370c5d

Please sign in to comment.