Added serilog
This commit is contained in:
parent
3dc21bc54d
commit
7b34b55197
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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": "*"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue