Added serilog

This commit is contained in:
henry 2025-05-16 21:08:23 -04:00
parent 3dc21bc54d
commit 7b34b55197
9 changed files with 132 additions and 21 deletions

View File

@ -8,6 +8,9 @@
<ItemGroup>
<PackageReference Include="Blazor.Bootstrap" Version="3.3.1" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -2,9 +2,20 @@ using AccessQueuePlayground.Components;
using AccessQueuePlayground.Services;
using AccessQueueService.Data;
using AccessQueueService.Services;
using Serilog;
var builder = WebApplication.CreateBuilder(args);
// Add Serilog configuration for console logging only
builder.Host.UseSerilog((context, services, configuration) =>
{
configuration
.WriteTo.Console()
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext();
});
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();

View File

@ -7,6 +7,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>

View File

@ -1,8 +1,18 @@
using AccessQueueService.Data;
using AccessQueueService.Services;
using Serilog;
var builder = WebApplication.CreateBuilder(args);
// Add Serilog configuration from appsettings and serilog.json
builder.Host.UseSerilog((context, services, configuration) =>
{
configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext();
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

View File

@ -1,15 +1,16 @@

namespace AccessQueueService.Services
namespace AccessQueueService.Services
{
public class AccessCleanupBackgroundService : BackgroundService
{
private readonly IAccessService _accessService;
private readonly IConfiguration _config;
private readonly ILogger<AccessCleanupBackgroundService> _logger;
public AccessCleanupBackgroundService(IAccessService accessService, IConfiguration config)
public AccessCleanupBackgroundService(IAccessService accessService, IConfiguration config, ILogger<AccessCleanupBackgroundService> logger)
{
_accessService = accessService;
_config = config;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
@ -17,7 +18,18 @@ namespace AccessQueueService.Services
var cleanupIntervalMillis = _config.GetValue<int>("AccessQueue:CleanupIntervalSeconds") * 1000;
while (!stoppingToken.IsCancellationRequested)
{
await _accessService.DeleteExpiredTickets();
try
{
var removed = await _accessService.DeleteExpiredTickets();
if (removed > 0)
{
_logger.LogInformation("Background cleanup removed {Count} expired tickets.", removed);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred during background cleanup.");
}
await Task.Delay(cleanupIntervalMillis, stoppingToken);
}
}

View File

@ -1,6 +1,7 @@
using System.Threading.Tasks;
using AccessQueueService.Data;
using AccessQueueService.Models;
using Microsoft.Extensions.Logging;
namespace AccessQueueService.Services
{
@ -8,16 +9,18 @@ namespace AccessQueueService.Services
{
private readonly IConfiguration _configuration;
private readonly IAccessQueueRepo _accessQueueRepo;
private readonly ILogger<AccessService> _logger;
private readonly SemaphoreSlim _queueLock = new(1, 1);
private readonly int EXP_SECONDS;
private readonly int ACT_SECONDS;
private readonly int CAPACITY_LIMIT;
private readonly bool ROLLING_EXPIRATION;
public AccessService(IConfiguration configuration, IAccessQueueRepo accessQueueRepo)
public AccessService(IConfiguration configuration, IAccessQueueRepo accessQueueRepo, ILogger<AccessService> logger)
{
_configuration = configuration;
_accessQueueRepo = accessQueueRepo;
_logger = logger;
EXP_SECONDS = _configuration.GetValue<int>("AccessQueue:ExpirationSeconds");
ACT_SECONDS = _configuration.GetValue<int>("AccessQueue:ActivitySeconds");
CAPACITY_LIMIT = _configuration.GetValue<int>("AccessQueue:CapacityLimit");
@ -47,6 +50,7 @@ namespace AccessQueueService.Services
ExpiresOn = expiresOn,
LastActive = DateTime.UtcNow
});
_logger.LogInformation("User {UserId} already has access. Expires on {ExpiresOn}.", userId, expiresOn);
return new AccessResponse
{
ExpiresOn = expiresOn
@ -62,6 +66,7 @@ namespace AccessQueueService.Services
LastActive = DateTime.UtcNow
};
_accessQueueRepo.UpsertTicket(accessTicket);
_logger.LogInformation("User {UserId} granted access. Expires on {ExpiresOn}.", userId, accessTicket.ExpiresOn);
return new AccessResponse
{
ExpiresOn = accessTicket.ExpiresOn,
@ -80,6 +85,7 @@ namespace AccessQueueService.Services
LastActive = DateTime.UtcNow,
ExpiresOn = DateTime.MaxValue,
});
_logger.LogInformation("User {UserId} added to queue. Requests ahead: {RequestsAhead}.", userId, requestsAhead);
}
return new AccessResponse
{
@ -88,6 +94,11 @@ namespace AccessQueueService.Services
};
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred while processing access request for user {UserId}.", userId);
throw;
}
finally
{
_queueLock.Release();
@ -99,7 +110,17 @@ namespace AccessQueueService.Services
await _queueLock.WaitAsync();
try
{
return _accessQueueRepo.RemoveUser(userId);
var removed = _accessQueueRepo.RemoveUser(userId);
if (removed)
{
_logger.LogInformation("User {UserId} access revoked.", userId);
}
return removed;
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred while revoking access for user {UserId}.", userId);
throw;
}
finally
{
@ -112,7 +133,17 @@ namespace AccessQueueService.Services
await _queueLock.WaitAsync();
try
{
return _accessQueueRepo.DeleteExpiredTickets();
var removed = _accessQueueRepo.DeleteExpiredTickets();
if (removed > 0)
{
_logger.LogInformation("Cleaned up {Count} expired tickets.", removed);
}
return removed;
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception occurred during expired ticket cleanup.");
throw;
}
finally
{

View File

@ -1,16 +1,34 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AccessQueue": {
"CapacityLimit": 100, // Maximum number of active users
"ActivitySeconds": 900, // Time since last access before a user is considered inactive
"ExpirationSeconds": 43200, // 12 hours - Time before a user access is revoked
"RollingExpiration": true, // Whether to extend expiration time on access
"CleanupIntervalSeconds": 60 // Interval for cleaning up expired users
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{ "Name": "File", "Args": { "path": "Logs/log-.txt", "rollingInterval": "Day", "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" } }
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "AccessQueueService"
}
},
"AccessQueue": {
"CapacityLimit": 100,
"ActivitySeconds": 900,
"ExpirationSeconds": 43200,
"RollingExpiration": true,
"CleanupIntervalSeconds": 60
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,20 @@
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{ "Name": "File", "Args": { "path": "Logs/log-.txt", "rollingInterval": "Day", "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" } }
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "AccessQueueService"
}
}
}

View File

@ -3,6 +3,7 @@ namespace AccessQueueServiceTests
using global::AccessQueueService.Data;
using global::AccessQueueService.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@ -31,8 +32,9 @@ namespace AccessQueueServiceTests
.AddInMemoryCollection(inMemorySettings)
.Build();
var accessQueueRepo = new TakeANumberAccessQueueRepo();
_accessService = new AccessService(configuration, accessQueueRepo);
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
var logger = loggerFactory.CreateLogger<AccessService>();
_accessService = new AccessService(configuration, accessQueueRepo, logger);
}
[Fact]