-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEndpointBuilderExtensions.cs
More file actions
57 lines (52 loc) · 2.49 KB
/
EndpointBuilderExtensions.cs
File metadata and controls
57 lines (52 loc) · 2.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
namespace ServiceLevelIndicators;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
/// <summary>
/// Extension methods for adding SLI metadata to Minimal API endpoints.
/// </summary>
public static class EndpointBuilderExtensions
{
/// <summary>
/// Marks a Minimal API endpoint for SLI metric emission and scans handler parameters
/// for <see cref="CustomerResourceIdAttribute"/> and <see cref="MeasureAttribute"/>.
/// </summary>
/// <typeparam name="TBuilder">The endpoint convention builder type.</typeparam>
/// <param name="builder">The endpoint builder.</param>
/// <param name="operation">An optional custom operation name; if omitted, the route template is used.</param>
/// <returns>The <paramref name="builder"/> for chaining.</returns>
public static TBuilder AddServiceLevelIndicator<TBuilder>(this TBuilder builder, string? operation = default)
where TBuilder : notnull, IEndpointConventionBuilder
{
builder.WithMetadata(new ServiceLevelIndicatorAttribute() { Operation = operation });
builder.Finally(AddSliMetadata);
return builder;
}
private static void AddSliMetadata(EndpointBuilder endpoint)
{
// this appears to be the only way to get back to the original method signature
// REF: https://github.com/dotnet/aspnetcore/blob/main/src/Http/Routing/src/RouteEndpointDataSource.cs#L183
if (endpoint.Metadata.OfType<MethodInfo>().FirstOrDefault()?.GetParameters() is not { } parameters)
{
return;
}
for (var i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
var attributes = parameter.GetCustomAttributes(inherit: false);
for (var j = 0; j < attributes.Length; j++)
{
switch (attributes[j])
{
case CustomerResourceIdAttribute:
if (endpoint.Metadata.OfType<CustomerResourceIdMetadata>().Any())
throw new InvalidOperationException("Multiple " + nameof(CustomerResourceIdAttribute) + " defined on endpoint '" + endpoint.DisplayName + "'.");
endpoint.Metadata.Add(new CustomerResourceIdMetadata(parameter.Name!));
break;
case MeasureAttribute measure:
endpoint.Metadata.Add(new MeasureMetadata(parameter.Name!, measure.Name));
break;
}
}
}
}
}