Skip to content

Commit d82afae

Browse files
committed
wip: wire up telemetry throughout the application
1 parent cc09580 commit d82afae

File tree

5 files changed

+81
-43
lines changed

5 files changed

+81
-43
lines changed

src/Whaally.Domain/Abstractions/IEvaluationAgent.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public async Task<IResult<IEventEnvelope[]>> Invoke(params ICommandEnvelope[] co
7575

7676
if (eventResult.IsFailed)
7777
return Result.Fail<IEventEnvelope[]>(eventResult.Errors);
78-
78+
7979
foreach (var envelope in commandResult.Value)
8080
await Continue(envelope);
8181

@@ -86,11 +86,11 @@ public async Task<IResult<IEventEnvelope[]>> Invoke(
8686
IServiceEnvelope serviceEnvelope)
8787
{
8888
var serviceResult = await Evaluate(serviceEnvelope);
89-
89+
9090
if (serviceResult.IsFailed)
9191
return new Result<IEventEnvelope[]>()
9292
.WithReasons(serviceResult.Reasons);
93-
93+
9494
return await Invoke(serviceResult.Value);
9595
}
9696
}
Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.ObjectModel;
12
using Microsoft.Extensions.DependencyInjection;
23
using Whaally.Domain.Abstractions;
34

@@ -6,20 +7,32 @@ namespace Whaally.Domain;
67
public class DefaultContextFactory(IServiceProvider services) : IContextFactory
78
{
89
public ISagaContext CreateSagaContext(IEventMetadata metadata)
9-
=> new SagaContext(services, metadata);
10+
=> new SagaContext(services, metadata)
11+
{
12+
Attributes = new ReadOnlyDictionary<string, object>(metadata.Attributes),
13+
AggregateId = metadata.AggregateId,
14+
ParentContext = metadata.ParentContext
15+
};
1016

1117
public IServiceHandlerContext CreateServiceHandlerContext(IServiceMetadata metadata)
1218
=> new ServiceHandlerContext(
1319
services,
14-
services.GetRequiredService<IEvaluationAgent>());
20+
services.GetRequiredService<IEvaluationAgent>())
21+
{
22+
Attributes = new ReadOnlyDictionary<string, object>(metadata.Attributes),
23+
ParentContext = metadata.ParentContext
24+
};
1525

1626
public ICommandHandlerContext<TAggregate> CreateCommandHandlerContext<TAggregate>(
1727
TAggregate aggregate,
1828
ICommandMetadata metadata)
1929
where TAggregate : class, IAggregate =>
2030
new CommandHandlerContext<TAggregate>(services, metadata.AggregateId)
2131
{
22-
Aggregate = aggregate
32+
Aggregate = aggregate,
33+
Attributes = new ReadOnlyDictionary<string, object>(metadata.Attributes),
34+
AggregateId = metadata.AggregateId,
35+
ParentContext = metadata.ParentContext
2336
};
2437

2538
public IEventHandlerContext<TAggregate> CreateEventHandlerContext<TAggregate>(
@@ -28,6 +41,9 @@ public IEventHandlerContext<TAggregate> CreateEventHandlerContext<TAggregate>(
2841
where TAggregate : class, IAggregate =>
2942
new EventHandlerContext<TAggregate>(metadata.AggregateId)
3043
{
31-
Aggregate = aggregate
44+
Aggregate = aggregate,
45+
Attributes = new ReadOnlyDictionary<string, object>(metadata.Attributes),
46+
AggregateId = metadata.AggregateId,
47+
ParentContext = metadata.ParentContext
3248
};
3349
}

src/Whaally.Domain/DefaultEvaluationAgent.cs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ public class DefaultEvaluationAgent : IEvaluationAgent
99
{
1010
private readonly IServiceProvider _services;
1111
private readonly DomainContext _domainContext;
12-
private readonly IAggregateHandlerFactory _handlerFactory;
1312
private readonly IContextFactory _contextFactory;
13+
private readonly IAggregateHandlerFactory _handlerFactory;
14+
1415
private readonly Activity? _activity;
1516

1617
public DefaultEvaluationAgent(IServiceProvider services)
1718
{
1819
_services = services;
1920
_domainContext = _services.GetRequiredService<DomainContext>();
20-
_handlerFactory = _services.GetRequiredService<IAggregateHandlerFactory>();
2121
_contextFactory = _services.GetRequiredService<IContextFactory>();
22+
_handlerFactory = _services.GetRequiredService<IAggregateHandlerFactory>();
2223

2324
_activity = DomainContext.ActivitySource.StartActivity(
2425
ActivityKind.Internal,
@@ -36,7 +37,9 @@ public async Task<IResult<ICommandEnvelope[]>> Evaluate(IServiceEnvelope service
3637
{
3738
if (serviceEnvelope.Messages.Count() != 1)
3839
throw new ArgumentException($"Expected {nameof(serviceEnvelope)} to contain one message");
39-
40+
41+
serviceEnvelope.Metadata.ParentContext = _activity?.Context;
42+
4043
var serviceContext = _contextFactory.CreateServiceHandlerContext(serviceEnvelope.Metadata);
4144

4245
var result = await _domainContext
@@ -45,13 +48,9 @@ public async Task<IResult<ICommandEnvelope[]>> Evaluate(IServiceEnvelope service
4548
serviceContext,
4649
serviceEnvelope.Messages.Single());
4750

48-
if (result.IsFailed)
49-
return Result.Fail<ICommandEnvelope[]>(result.Errors);
50-
51-
return Result
52-
.Ok(Array.Empty<ICommandEnvelope>())
53-
.WithReasons(result.Reasons)
54-
.WithValue(serviceContext.Commands.ToArray());
51+
return new Result<ICommandEnvelope[]>()
52+
.WithValue(serviceContext.Commands.ToArray())
53+
.WithReasons(result.Reasons);
5554
}
5655

5756
/// <summary>
@@ -68,23 +67,20 @@ public async Task<IResult<IEventEnvelope[]>> Evaluate(params ICommandEnvelope[]
6867
{
6968
if (!envelope.Messages.Any()) continue;
7069

70+
envelope.Metadata.ParentContext = _activity?.Context;
71+
7172
var handler = _handlerFactory.Instantiate(
7273
GetCommonAggregateType(envelope),
7374
envelope.Metadata.AggregateId);
7475

7576
results.Add(await handler.Evaluate(envelope));
7677
}
77-
78-
var result = Result
79-
.Ok(Array.Empty<IEventEnvelope>())
80-
.WithReasons(results.SelectMany(q => q.Reasons));
81-
82-
if (result.IsSuccess)
83-
result.WithValue(results
78+
79+
return new Result<IEventEnvelope[]>()
80+
.WithValue(results
8481
.Select(q => q.Value)
85-
.ToArray());
86-
87-
return result;
82+
.ToArray())
83+
.WithReasons(results.SelectMany(q => q.Reasons));
8884
}
8985

9086
/// <summary>
@@ -100,6 +96,8 @@ public async Task<IResultBase> Apply(params IEventEnvelope[] eventEnvelopes)
10096
foreach (var envelope in eventEnvelopes)
10197
{
10298
if (!envelope.Messages.Any()) continue;
99+
100+
envelope.Metadata.ParentContext = _activity?.Context;
103101

104102
var handler = _handlerFactory.Instantiate(
105103
GetCommonAggregateType(envelope),
@@ -108,10 +106,8 @@ public async Task<IResultBase> Apply(params IEventEnvelope[] eventEnvelopes)
108106
results.Add(await handler.Apply(envelope));
109107
}
110108

111-
var result = new Result()
109+
return new Result()
112110
.WithReasons(results.SelectMany(q => q.Reasons));
113-
114-
return result;
115111
}
116112

117113
/// <summary>
@@ -121,6 +117,8 @@ public async Task<IResultBase> Apply(params IEventEnvelope[] eventEnvelopes)
121117
/// <returns></returns>
122118
public Task<IResultBase> Continue(IEventEnvelope eventEnvelope)
123119
{
120+
eventEnvelope.Metadata.ParentContext = _activity?.Context;
121+
124122
foreach (var @event in eventEnvelope.Messages)
125123
{
126124
foreach (var saga in _domainContext.GetSaga(@event.GetType()))
@@ -142,6 +140,8 @@ public async Task<IResultBase> Invoke(ISaga saga, IEventEnvelope eventEnvelope)
142140
{
143141
if (eventEnvelope.Messages.Count() != 1)
144142
throw new ArgumentException($"Expected {nameof(eventEnvelope)} to contain one message");
143+
144+
eventEnvelope.Metadata.ParentContext = _activity?.Context;
145145

146146
return await saga.Evaluate(
147147
_contextFactory.CreateSagaContext(eventEnvelope.Metadata),

src/Whaally.Domain/DomainContext.cs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,26 @@ namespace Whaally.Domain;
1212
* - Do not inject dependencies to this class (IAggregateHandlerFactory & IEvaluationAgent) as concrete instances.
1313
* Doing so causes an infinite loop as this class is often injected as dependency to those.
1414
*/
15-
public class DomainContext(IServiceProvider services)
15+
public class DomainContext
1616
{
1717
internal static ActivitySource ActivitySource = new("Whaally.Domain");
1818

19+
private readonly IServiceProvider _services;
20+
private readonly Activity? _activity;
21+
22+
public DomainContext(IServiceProvider services)
23+
{
24+
_services = services;
25+
26+
_activity = ActivitySource.StartActivity(
27+
ActivityKind.Internal,
28+
name: nameof(DomainContext),
29+
tags: new Dictionary<string, object?>
30+
{
31+
32+
});
33+
}
34+
1935
#region handler metadata
2036
/// <summary>
2137
/// Metadata about the command handlers registered with this domain instance.
@@ -102,12 +118,12 @@ public IEnumerable<Type> SnapshotFactoryTypes
102118
init => SnapshotFactories = value.Select(SnapshotFactoryMeta.From).ToList().AsReadOnly();
103119
}
104120
#endregion
105-
106-
private IEvaluationAgent _evaluationAgent => services.GetRequiredService<IEvaluationAgent>();
107-
121+
122+
private IEvaluationAgent _evaluationAgent => _services.GetRequiredService<IEvaluationAgent>();
123+
108124
private IAggregateHandler GetAggregate(Type type, string id)
109125
{
110-
var aggregateHandlerFactory = services.GetRequiredService<IAggregateHandlerFactory>();
126+
var aggregateHandlerFactory = _services.GetRequiredService<IAggregateHandlerFactory>();
111127

112128
if (type.IsAssignableTo(typeof(IAggregate)))
113129
{
@@ -151,7 +167,8 @@ public virtual Task<IResult<IEventEnvelope[]>> Evaluate<TCommand>(
151167
new CommandMetadata
152168
{
153169
AggregateId = aggregateId,
154-
CreatedAt = DateTimeOffset.UtcNow
170+
CreatedAt = DateTimeOffset.UtcNow,
171+
ParentContext = _activity?.Context
155172
},
156173
command);
157174
}
@@ -164,7 +181,8 @@ public virtual Task<IResult<IEventEnvelope[]>> Evaluate(
164181
new CommandEnvelope(
165182
new CommandMetadata
166183
{
167-
AggregateId = aggregateId
184+
AggregateId = aggregateId,
185+
ParentContext = _activity?.Context
168186
},
169187
commands));
170188
}
@@ -192,7 +210,8 @@ public virtual Task<IResult<IEventEnvelope[]>> Trigger(
192210
new CommandMetadata
193211
{
194212
AggregateId = aggregateId,
195-
CreatedAt = DateTimeOffset.UtcNow
213+
CreatedAt = DateTimeOffset.UtcNow,
214+
ParentContext = _activity?.Context
196215
},
197216
commands));
198217
}
@@ -207,30 +226,31 @@ public virtual Task<IResult<IEventEnvelope[]>> Trigger(
207226
new ServiceEnvelope(
208227
metadata ?? new ServiceMetadata
209228
{
210-
CreatedAt = DateTimeOffset.UtcNow
229+
CreatedAt = DateTimeOffset.UtcNow,
230+
ParentContext = _activity?.Context
211231
}, service));
212232
}
213233

214234
public IServiceHandler GetServiceHandler(Type serviceType) =>
215-
(IServiceHandler)services.GetRequiredService(
235+
(IServiceHandler)_services.GetRequiredService(
216236
ServiceHandlers
217237
.Single(q => q.ServiceType == serviceType)
218238
.HandlerType);
219239

220240
public IEnumerable<ISaga> GetSaga(Type eventType) =>
221241
Sagas.Where(q => q.EventType == eventType)
222-
.Select(q => (ISaga)services.GetRequiredService(q.HandlerType));
242+
.Select(q => (ISaga)_services.GetRequiredService(q.HandlerType));
223243

224244
public IEventHandler GetEventHandler(Type eventType) =>
225-
(IEventHandler)services.GetRequiredService(
245+
(IEventHandler)_services.GetRequiredService(
226246
EventHandlers
227247
.Single(q => q.EventType == eventType)
228248
.HandlerType);
229249

230250
// TODO: See if we can also require the aggregate type as argument to validate that we're executing the correct handlers
231251
// Same goes for the event handlers though.
232252
public ICommandHandler GetCommandHandler(Type commandType) =>
233-
(ICommandHandler)services.GetRequiredService(
253+
(ICommandHandler)_services.GetRequiredService(
234254
CommandHandlers
235255
.Single(q => q.CommandType == commandType)
236256
.HandlerType);

src/Whaally.Domain/Service/ServiceHandlerContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public class ServiceHandlerContext : IServiceHandlerContext
1111
private readonly IServiceProvider _services;
1212
private readonly IEvaluationAgent _evaluationAgent;
1313

14+
// ToDo: Add an activity here to track service evaluation
15+
1416
public ServiceHandlerContext(
1517
IServiceProvider services,
1618
IEvaluationAgent evaluationAgent)

0 commit comments

Comments
 (0)