Skip to content

Commit 55f8908

Browse files
Merge pull request #409 from NielsPilgaard/feature/metrics
Feature/metrics
2 parents cc01b4d + 7c3a0a2 commit 55f8908

File tree

17 files changed

+198
-100
lines changed

17 files changed

+198
-100
lines changed

src/shared/Jordnaer.Shared/Extensions/ServiceCollectionExtensions.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ public static IServiceCollection AddDataForsyningenClient(this IServiceCollectio
2626

2727
var pingCircuitBreakerOptions = new HttpCircuitBreakerStrategyOptions
2828
{
29-
FailureRatio = 0.5,
30-
BreakDuration = TimeSpan.FromMinutes(5),
31-
MinimumThroughput = 2,
29+
FailureRatio = 0.25,
30+
BreakDuration = TimeSpan.FromMinutes(1),
3231
ShouldHandle = arguments =>
3332
new ValueTask<bool>(
3433
arguments.Outcome.Exception is not null ||

src/web/Jordnaer/Components/Account/IdentityComponentsEndpointRouteBuilderExtensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.Extensions.Primitives;
1010
using System.Security.Claims;
1111
using System.Text.Json;
12+
using Jordnaer.Features.Metrics;
1213

1314
namespace Jordnaer.Components.Account;
1415

@@ -46,6 +47,9 @@ public static IEndpointConventionBuilder MapAdditionalIdentityEndpoints(this IEn
4647
[FromForm] string returnUrl) =>
4748
{
4849
await signInManager.SignOutAsync();
50+
51+
JordnaerMetrics.LogoutCounter.Add(1);
52+
4953
return TypedResults.LocalRedirect(string.IsNullOrEmpty(returnUrl)
5054
? "~/"
5155
: returnUrl);

src/web/Jordnaer/Components/Account/Pages/ExternalLogin.razor

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@
114114
RedirectManager.RedirectToWithStatus("Account/Login", "Fejl - Det lykkedes ikke at finde dit login. Prøv venligst igen.", HttpContext);
115115
}
116116

117+
JordnaerMetrics.ExternalLoginCounter.Add(1);
118+
117119
var accessToken = _externalLoginInfo.AuthenticationProperties?.GetTokenValue("access_token");
118120
if (accessToken is not null)
119121
{
@@ -146,7 +148,7 @@
146148
private async Task OnValidSubmitAsync()
147149
{
148150
var emailStore = GetEmailStore();
149-
var user = CreateUser();
151+
var user = new ApplicationUser();
150152

151153
await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
152154
await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
@@ -182,24 +184,13 @@
182184
RedirectManager.RedirectTo("Account/RegisterConfirmation", queryParameters: new() { ["email"] = Input.Email });
183185
}
184186

187+
JordnaerMetrics.ExternalLoginCounter.Add(1);
188+
185189
await SignInManager.SignInAsync(user, isPersistent: false, _externalLoginInfo.LoginProvider);
186190
RedirectManager.RedirectTo(FirstLoginReturnUrl);
187191
}
188192
}
189193

190-
private static ApplicationUser CreateUser()
191-
{
192-
try
193-
{
194-
return Activator.CreateInstance<ApplicationUser>();
195-
}
196-
catch
197-
{
198-
throw new InvalidOperationException($"Can't create an instance of '{nameof(ApplicationUser)}'. " +
199-
$"Ensure that '{nameof(ApplicationUser)}' is not an abstract class and has a parameterless constructor");
200-
}
201-
}
202-
203194
private IUserEmailStore<ApplicationUser> GetEmailStore()
204195
{
205196
if (!UserManager.SupportsUserEmail)

src/web/Jordnaer/Components/Account/Pages/Login.razor

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
lockoutOnFailure: true);
8383
if (result.Succeeded)
8484
{
85+
JordnaerMetrics.LoginCounter.Add(1);
86+
8587
Logger.LogInformation("User logged in.");
8688

8789
RedirectManager.RedirectTo(FirstLoginReturnUrl);

src/web/Jordnaer/Consumers/SendEmailConsumer.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Jordnaer.Extensions;
22
using Jordnaer.Features.Email;
3+
using Jordnaer.Features.Metrics;
34
using MassTransit;
45
using Polly;
56
using Polly.CircuitBreaker;
@@ -15,7 +16,8 @@ public class SendEmailConsumer(
1516
ISendGridClient sendGridClient)
1617
: IConsumer<SendEmail>
1718
{
18-
private static readonly ResiliencePipeline<Response> Retry = new ResiliencePipelineBuilder<Response>()
19+
private static readonly ResiliencePipeline<Response> Retry =
20+
new ResiliencePipelineBuilder<Response>()
1921
.AddRetry(new RetryStrategyOptions<Response>
2022
{
2123
ShouldHandle = new PredicateBuilder<Response>()
@@ -91,6 +93,8 @@ public async Task Consume(ConsumeContext<SendEmail> consumeContext)
9193
{
9294
logger.LogInformation("Email sent to {@Recipient}. Subject: {Subject}",
9395
message.To?.Select(x => x.Email), message.Subject);
96+
97+
JordnaerMetrics.EmailsSentCounter.Add(1);
9498
}
9599
}
96100
}
Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,27 @@
11
using Jordnaer.Database;
22
using Jordnaer.Extensions;
33
using Jordnaer.Features.Chat;
4+
using Jordnaer.Features.Metrics;
45
using Jordnaer.Shared;
56
using MassTransit;
67
using Microsoft.AspNetCore.SignalR;
78
using Microsoft.EntityFrameworkCore;
89

910
namespace Jordnaer.Consumers;
1011

11-
public class SendMessageConsumer : IConsumer<SendMessage>
12+
public class SendMessageConsumer(
13+
JordnaerDbContext context,
14+
ILogger<SendMessageConsumer> logger,
15+
IHubContext<ChatHub, IChatHub> chatHub)
16+
: IConsumer<SendMessage>
1217
{
13-
private readonly JordnaerDbContext _context;
14-
private readonly ILogger<SendMessageConsumer> _logger;
15-
private readonly IHubContext<ChatHub, IChatHub> _chatHub;
16-
17-
public SendMessageConsumer(JordnaerDbContext context, ILogger<SendMessageConsumer> logger, IHubContext<ChatHub, IChatHub> chatHub)
18-
{
19-
_context = context;
20-
_logger = logger;
21-
_chatHub = chatHub;
22-
}
23-
2418
public async Task Consume(ConsumeContext<SendMessage> consumeContext)
2519
{
26-
_logger.LogDebug("Consuming SendMessage message. ChatId: {ChatId}", consumeContext.Message.ChatId);
20+
logger.LogDebug("Consuming SendMessage message. ChatId: {ChatId}", consumeContext.Message.ChatId);
2721

2822
var chatMessage = consumeContext.Message;
2923

30-
_context.ChatMessages.Add(
24+
context.ChatMessages.Add(
3125
new ChatMessage
3226
{
3327
ChatId = chatMessage.ChatId,
@@ -38,14 +32,14 @@ public async Task Consume(ConsumeContext<SendMessage> consumeContext)
3832
SentUtc = chatMessage.SentUtc
3933
});
4034

41-
var recipientIds = await _context.UserChats
35+
var recipientIds = await context.UserChats
4236
.Where(userChat => userChat.ChatId == chatMessage.ChatId)
4337
.Select(userChat => userChat.UserProfileId)
4438
.ToListAsync(consumeContext.CancellationToken);
4539

4640
foreach (var recipientId in recipientIds.Where(recipientId => recipientId != chatMessage.SenderId))
4741
{
48-
_context.UnreadMessages.Add(new UnreadMessage
42+
context.UnreadMessages.Add(new UnreadMessage
4943
{
5044
RecipientId = recipientId,
5145
ChatId = chatMessage.ChatId,
@@ -55,20 +49,22 @@ public async Task Consume(ConsumeContext<SendMessage> consumeContext)
5549

5650
try
5751
{
58-
await _context.SaveChangesAsync(consumeContext.CancellationToken);
52+
await context.SaveChangesAsync(consumeContext.CancellationToken);
5953

60-
await _chatHub.Clients.Users(recipientIds).ReceiveChatMessage(chatMessage);
54+
await chatHub.Clients.Users(recipientIds).ReceiveChatMessage(chatMessage);
6155

62-
await _context.Chats
56+
await context.Chats
6357
.Where(chat => chat.Id == chatMessage.ChatId)
6458
.ExecuteUpdateAsync(call =>
6559
call.SetProperty(chat => chat.LastMessageSentUtc, DateTime.UtcNow),
6660
consumeContext.CancellationToken);
6761
}
6862
catch (Exception exception)
6963
{
70-
_logger.LogException(exception);
64+
logger.LogException(exception);
7165
throw;
7266
}
67+
68+
JordnaerMetrics.ChatMessagesSentCounter.Add(1);
7369
}
7470
}

src/web/Jordnaer/Consumers/StartChatConsumer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Jordnaer.Database;
22
using Jordnaer.Features.Chat;
3+
using Jordnaer.Features.Metrics;
34
using Jordnaer.Shared;
45
using MassTransit;
56
using Microsoft.AspNetCore.SignalR;
@@ -76,5 +77,7 @@ public async Task Consume(ConsumeContext<StartChat> consumeContext)
7677
}
7778

7879
await _chatNotificationService.NotifyRecipients(chat);
80+
81+
JordnaerMetrics.ChatStartedSentCounter.Add(1);
7982
}
8083
}

src/web/Jordnaer/Extensions/WebApplicationBuilderExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ public static WebApplicationBuilder AddOpenTelemetry(this WebApplicationBuilder
9191
.AddProcessInstrumentation()
9292
.AddRuntimeInstrumentation()
9393
.AddMeter(InstrumentationOptions.MeterName)
94-
.AddMeter("Polly"))
94+
.AddMeter("Polly")
95+
.AddMeter("Jordnaer"))
9596
.WithTracing(tracing =>
9697
{
9798
if (builder.Environment.IsDevelopment())
@@ -102,7 +103,8 @@ public static WebApplicationBuilder AddOpenTelemetry(this WebApplicationBuilder
102103

103104
tracing.AddAspNetCoreInstrumentation()
104105
.AddHttpClientInstrumentation()
105-
.AddSource(DiagnosticHeaders.DefaultListenerName);
106+
.AddSource(DiagnosticHeaders.DefaultListenerName)
107+
.AddSource("Jordnaer");
106108
});
107109

108110
// Use the Aspire Dashboard in development

src/web/Jordnaer/Features/Ad/SponsorAd.razor

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,9 @@
3535

3636
[Parameter]
3737
public bool Fluid { get; set; } = true;
38+
39+
protected override void OnInitialized()
40+
{
41+
JordnaerMetrics.SponsorAdViewCounter.Add(1, new KeyValuePair<string, object?>("link", Link));
42+
}
3843
}

src/web/Jordnaer/Features/GroupSearch/GroupSearchService.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Jordnaer.Database;
2+
using Jordnaer.Features.Metrics;
23
using Jordnaer.Features.Search;
34
using Jordnaer.Shared;
45
using Microsoft.EntityFrameworkCore;
@@ -15,10 +16,11 @@ public class GroupSearchService(
1516
IZipCodeService zipCodeService)
1617
: IGroupSearchService
1718
{
18-
1919
public async Task<GroupSearchResult> GetGroupsAsync(GroupSearchFilter filter,
2020
CancellationToken cancellationToken = default)
2121
{
22+
JordnaerMetrics.GroupSearchesCounter.Add(1, MakeTagList(filter));
23+
2224
var groups = context.Groups
2325
.AsNoTracking()
2426
.AsQueryable()
@@ -83,4 +85,14 @@ public async Task<GroupSearchResult> GetGroupsAsync(GroupSearchFilter filter,
8385

8486
return (groups, true);
8587
}
88+
89+
private static ReadOnlySpan<KeyValuePair<string, object?>> MakeTagList(GroupSearchFilter filter)
90+
{
91+
return new KeyValuePair<string, object?>[]
92+
{
93+
new(nameof(filter.Location), filter.Location),
94+
new(nameof(filter.Categories), string.Join(',', filter.Categories ?? [])),
95+
new(nameof(filter.WithinRadiusKilometers), filter.WithinRadiusKilometers)
96+
};
97+
}
8698
}

0 commit comments

Comments
 (0)