diff --git a/packages/backend/Controllers/AuthenticationController.cs b/packages/backend/Controllers/AuthenticationController.cs index ee40f0d..9e12a8a 100644 --- a/packages/backend/Controllers/AuthenticationController.cs +++ b/packages/backend/Controllers/AuthenticationController.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; -using Serilog; using System.Security.Claims; using YaleAccess.Models; @@ -14,15 +13,8 @@ namespace YaleAccess.Controllers [Route("api/[controller]")] [EnableCors] [Authorize] - public class AuthenticationController : ControllerBase + public class AuthenticationController(IOptions authenticationOptions, ILogger logger) : ControllerBase { - private readonly Models.Options.AuthenticationOptions _authenticationOptions; - - public AuthenticationController(IOptions authenticationOptions) - { - _authenticationOptions = authenticationOptions.Value; - } - [HttpPost("login")] [AllowAnonymous] public async Task Login([FromBody] string password) @@ -30,7 +22,7 @@ namespace YaleAccess.Controllers try { // Check if the password is correct - if (password != _authenticationOptions.Password) + if (password != authenticationOptions.Value.Password) { return Unauthorized(new ApiResponse("Incorrect password.")); } @@ -50,7 +42,7 @@ namespace YaleAccess.Controllers } catch(Exception ex) { - Log.Logger.Error(ex, "An error occurred logging in."); + logger.LogError(ex, "An error occurred logging in."); return BadRequest(new ApiResponse("An error occurred logging in.")); } } @@ -68,7 +60,7 @@ namespace YaleAccess.Controllers } catch (Exception ex) { - Log.Logger.Error(ex, "An error occured logging out."); + logger.LogError(ex, "An error occured logging out."); return BadRequest(new ApiResponse("An error occured logging out.")); } } diff --git a/packages/backend/Controllers/HealthController.cs b/packages/backend/Controllers/HealthController.cs index 1158afa..c8fe97a 100644 --- a/packages/backend/Controllers/HealthController.cs +++ b/packages/backend/Controllers/HealthController.cs @@ -1,7 +1,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; -using Serilog; namespace YaleAccess.Controllers { @@ -9,13 +8,13 @@ namespace YaleAccess.Controllers [Route("api/[controller]")] [EnableCors] [Authorize] - public class HealthController : ControllerBase + public class HealthController(ILogger logger) : ControllerBase { [HttpGet] [AllowAnonymous] public IActionResult Health() { - Log.Logger.Information("Hit the health endpoint."); + logger.LogInformation("Hit the health endpoint."); return Ok("Service is healthy"); } } diff --git a/packages/backend/Controllers/PeopleController.cs b/packages/backend/Controllers/PeopleController.cs index e90b0ca..300000d 100644 --- a/packages/backend/Controllers/PeopleController.cs +++ b/packages/backend/Controllers/PeopleController.cs @@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Serilog; using YaleAccess.Data; using YaleAccess.Models; @@ -12,27 +11,20 @@ namespace YaleAccess.Controllers [Route("api/[controller]")] [EnableCors] [Authorize] - public class PeopleController : ControllerBase + public class PeopleController(ILogger logger, YaleContext context) : ControllerBase { - private readonly YaleContext _context; - - public PeopleController(YaleContext context) - { - _context = context; - } - [HttpGet] public async Task GetPeople() { try { // Return all people - List people = await _context.People.ToListAsync(); + List people = await context.People.ToListAsync(); return Ok(new ApiResponse(people)); } catch (Exception ex) { - Log.Logger.Error(ex, "An error occured retriving the people."); + logger.LogError(ex, "An error occured retriving the people."); return BadRequest(new ApiResponse("An error occured retriving the people.")); } } @@ -46,15 +38,15 @@ namespace YaleAccess.Controllers Person newPerson = new() { Name = person.Name, PhoneNumber = person.PhoneNumber }; // Add the person - await _context.AddAsync(newPerson); - await _context.SaveChangesAsync(); + await context.AddAsync(newPerson); + await context.SaveChangesAsync(); // Return the newly created person return Ok(new ApiResponse(newPerson)); } catch (Exception ex) { - Log.Logger.Error(ex, "An error occured creating the person."); + logger.LogError(ex, "An error occured creating the person."); return BadRequest(new ApiResponse("An error occured creating the person.")); } } @@ -65,18 +57,18 @@ namespace YaleAccess.Controllers try { // Ensure the person exists - Person person = await _context.People.FindAsync(id) ?? throw new Exception("Person not found."); + Person person = await context.People.FindAsync(id) ?? throw new Exception("Person not found."); // Remove the person - _context.Remove(person); - await _context.SaveChangesAsync(); + context.Remove(person); + await context.SaveChangesAsync(); // Return the newly removed person return Ok(new ApiResponse(person)); } catch (Exception ex) { - Log.Logger.Error(ex, "An error occured deletiong the person."); + logger.LogError(ex, "An error occured deletiong the person."); return BadRequest(new ApiResponse("An error occured deletiong the person.")); } } diff --git a/packages/backend/Controllers/YaleController.cs b/packages/backend/Controllers/YaleController.cs index 90c17fa..3172612 100644 --- a/packages/backend/Controllers/YaleController.cs +++ b/packages/backend/Controllers/YaleController.cs @@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; -using Serilog; using YaleAccess.Models; using YaleAccess.Models.Options; using YaleAccess.Services; @@ -14,33 +13,27 @@ namespace YaleAccess.Controllers [Route("api/[controller]")] [EnableCors] [Authorize] - public class YaleController : ControllerBase + public class YaleController( + ILogger logger, + IYaleAccessor yaleAccessor, + IOptions codeOptions, + SMSService smsService + ) : ControllerBase { - private readonly IYaleAccessor _yaleAccessor; - private readonly CodesOptions _codeOptions; - private readonly SMSService _smsService; - - public YaleController(IYaleAccessor yaleAccessor, IOptions codeOptions, SMSService smsService) - { - _yaleAccessor = yaleAccessor; - _codeOptions = codeOptions.Value; - _smsService = smsService; - } - [HttpGet("codes")] public async Task GetUserCodes() { try { // Get the home code first - YaleUserCode homeCode = await _yaleAccessor.GetCodeInformationAsync(_codeOptions.Home); + YaleUserCode homeCode = await yaleAccessor.GetCodeInformationAsync(codeOptions.Value.Home); homeCode.IsHome = true; // Get the guest codes List guestCodes = new(); - foreach (int code in Enumerable.Range(_codeOptions.GuestCodeRangeStart, _codeOptions.GuestCodeRangeCount)) + foreach (int code in Enumerable.Range(codeOptions.Value.GuestCodeRangeStart, codeOptions.Value.GuestCodeRangeCount)) { - guestCodes.Add(await _yaleAccessor.GetCodeInformationAsync(code)); + guestCodes.Add(await yaleAccessor.GetCodeInformationAsync(code)); } // Add the home code to the list @@ -51,7 +44,7 @@ namespace YaleAccess.Controllers } catch(Exception ex) { - Log.Logger.Error(ex, "An error occurred retriving the codes."); + logger.LogError(ex, "An error occurred retriving the codes."); return BadRequest(new ApiResponse("An error occurred retriving the codes.")); } } @@ -69,23 +62,23 @@ namespace YaleAccess.Controllers } // Set the new code - bool result = await _yaleAccessor.SetUserCode(id, newCode); + bool result = await yaleAccessor.SetUserCode(id, newCode); // Return the result if (result) { - Log.Logger.Information("Updated code for user {id} to {code}", id, newCode); + logger.LogInformation("Updated code for user {id} to {code}", id, newCode); return Ok(new ApiResponse(true)); } else { - Log.Logger.Information("Failed to update code for user {id} to {code}", id, newCode); + logger.LogInformation("Failed to update code for user {id} to {code}", id, newCode); return BadRequest(new ApiResponse("An error occurred setting the code.")); } } catch (Exception ex) { - Log.Logger.Error(ex, "An error occurred setting the code."); + logger.LogError(ex, "An error occurred setting the code."); return BadRequest(new ApiResponse("An error occurred setting the code.")); } } @@ -96,30 +89,30 @@ namespace YaleAccess.Controllers try { // First validate the user code - string validCode = YaleAccessor.ValidateClearCode(id, _codeOptions.Home); + string validCode = YaleAccessor.ValidateClearCode(id, codeOptions.Value.Home); if (validCode != string.Empty) { return BadRequest(new ApiResponse(validCode)); } // Set the available status - bool result = await _yaleAccessor.SetCodeAsAvailable(id); + bool result = await yaleAccessor.SetCodeAsAvailable(id); // Return the result if (result) { - Log.Logger.Information("Updated code status for user {id} to available", id); + logger.LogInformation("Updated code status for user {id} to available", id); return Ok(new ApiResponse(true)); } else { - Log.Logger.Information("Failed to update code status for user {id} to available", id); + logger.LogInformation("Failed to update code status for user {id} to available", id); return BadRequest(new ApiResponse("An error occurred setting the code status.")); } } catch (Exception ex) { - Log.Logger.Error(ex, "An error occurred setting the code status."); + logger.LogError(ex, "An error occurred setting the code status."); return BadRequest(new ApiResponse("An error occurred setting the code status.")); } } @@ -130,17 +123,17 @@ namespace YaleAccess.Controllers try { // Get the user code - YaleUserCode userCode = await _yaleAccessor.GetCodeInformationAsync(id); + YaleUserCode userCode = await yaleAccessor.GetCodeInformationAsync(id); // Send the code via SMS to the phone number - await _smsService.SendCodeViaSMSAsync(userCode.Code, phoneNumber); + await smsService.SendCodeViaSMSAsync(userCode.Code, phoneNumber); // Return success return Ok(new ApiResponse(true)); } catch (Exception ex) { - Log.Logger.Error(ex, "An error occurred sending the code."); + logger.LogError(ex, "An error occurred sending the code."); return BadRequest(new ApiResponse("An error occurred sending the code.")); } } diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index 00d8581..88229d7 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base WORKDIR /app -EXPOSE 80 +EXPOSE 8080 -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY ["YaleAccess.csproj", "."] RUN dotnet restore "./YaleAccess.csproj" diff --git a/packages/backend/Program.cs b/packages/backend/Program.cs index 7088b29..b69eb38 100644 --- a/packages/backend/Program.cs +++ b/packages/backend/Program.cs @@ -1,8 +1,7 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.HttpOverrides; using Microsoft.EntityFrameworkCore; -using Serilog; -using Serilog.Events; +using OpenTelemetry.Logs; using YaleAccess.Data; using YaleAccess.Models.Options; using YaleAccess.Services; @@ -10,15 +9,25 @@ using YaleAccess.Services.Interfaces; var builder = WebApplication.CreateBuilder(args); -// Create the bootstraper logger -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .Enrich.FromLogContext() - .WriteTo.Console() - .CreateLogger(); - try { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + + if (useOtlpExporter) + { + logging.AddOtlpExporter(); + } + else + { + Console.WriteLine("OTEL_EXPORTER_OTLP_ENDPOINT is not set. Skipping OTLP exporter configuration."); + } + }); + // Add services to the container. builder.Services.AddControllers(); @@ -41,13 +50,6 @@ try // Get a copy of the configuration IConfiguration configuration = builder.Configuration; - string logLocation = configuration["LogLocation"] ?? "Log.txt"; - - // Setup the application logger - Log.Logger = new LoggerConfiguration() - .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Error) - .WriteTo.File(logLocation, rollingInterval: RollingInterval.Day) - .CreateLogger(); // Configure the DI services builder.Services.AddScoped(); @@ -100,9 +102,6 @@ try }; }); - // Setup logging flow - builder.Host.UseSerilog(); - var app = builder.Build(); // Create the database if it doesn't exist @@ -144,11 +143,7 @@ catch (Exception ex) // Ignore host aborted exceptions caused by build checks if (ex is not HostAbortedException) { - Log.Fatal(ex, "Host terminated unexpectedly"); + Console.WriteLine("Host terminated unexpectedly"); throw; } } -finally -{ - Log.CloseAndFlush(); -} \ No newline at end of file diff --git a/packages/backend/Services/SMSService.cs b/packages/backend/Services/SMSService.cs index faaa10d..3998a34 100644 --- a/packages/backend/Services/SMSService.cs +++ b/packages/backend/Services/SMSService.cs @@ -1,35 +1,27 @@ using Microsoft.Extensions.Options; -using Serilog; using Twilio; using Twilio.Rest.Api.V2010.Account; using YaleAccess.Models.Options; namespace YaleAccess.Services { - public class SMSService + public class SMSService(ILogger logger, IOptions twiloOptions) { - private readonly TwiloOptions _twiloOptions; - - public SMSService(IOptions twiloOptions) - { - _twiloOptions = twiloOptions.Value; - } - public async Task SendCodeViaSMSAsync(string code, string phoneNumber) { // Create a Twilio client - TwilioClient.Init(_twiloOptions.AccountSid, _twiloOptions.AuthToken); + TwilioClient.Init(twiloOptions.Value.AccountSid, twiloOptions.Value.AuthToken); // Send the message var message = await MessageResource.CreateAsync( - body: $"{_twiloOptions.Message} {code}", - from: new Twilio.Types.PhoneNumber(_twiloOptions.FromNumber), + body: $"{twiloOptions.Value.Message} {code}", + from: new Twilio.Types.PhoneNumber(twiloOptions.Value.FromNumber), to: new Twilio.Types.PhoneNumber(phoneNumber) ); // Log the message - Log.Logger.Information("SMS sent to {PhoneNumber} with message SID {MessageSid}.", phoneNumber, message.Sid); - Log.Logger.Debug("SMS message: {MessageBody}", message.Body); + logger.LogInformation("SMS sent to {PhoneNumber} with message SID {MessageSid}.", phoneNumber, message.Sid); + logger.LogDebug("SMS message: {MessageBody}", message.Body); } } } diff --git a/packages/backend/Services/YaleAccessor.cs b/packages/backend/Services/YaleAccessor.cs index da9d637..5201900 100644 --- a/packages/backend/Services/YaleAccessor.cs +++ b/packages/backend/Services/YaleAccessor.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; -using Serilog; using YaleAccess.Models; using YaleAccess.Models.Options; using YaleAccess.Services.Interfaces; @@ -38,10 +37,11 @@ namespace YaleAccess.Services #endregion Dispose Logic + private readonly ILogger _logger; private Driver? driver = null; private readonly ZWaveNode lockNode = null!; - public YaleAccessor(IOptions zwave, IOptions device) + public YaleAccessor(IOptions zwave, IOptions device, ILogger logger) { // Retrive options from configuration ZWaveOptions zwaveOptions = zwave.Value; @@ -75,6 +75,8 @@ namespace YaleAccess.Services // Get the lock node from the driver lockNode = driver.Controller.Nodes.Get(devicesOptions.YaleLockNodeId); + + _logger = logger; } public async Task GetCodeInformationAsync(int userCodeId) @@ -101,7 +103,7 @@ namespace YaleAccess.Services // If the result is not successful log the message if (!result.Success) { - Log.Logger.Error("Failed to set user code {@userCodeId} to {@code}. Error message: {message}", userCodeId, code, result.Message); + _logger.LogError("Failed to set user code {@userCodeId} to {@code}. Error message: {message}", userCodeId, code, result.Message); } // Return the result @@ -116,7 +118,7 @@ namespace YaleAccess.Services // If the result is not successful log the message if (!result.Success) { - Log.Logger.Error("Failed to set user code {@userCode} to available status. Error message: {message}", userCode, result.Message); + _logger.LogError("Failed to set user code {@userCode} to available status. Error message: {message}", userCode, result.Message); } // Return the result diff --git a/packages/backend/YaleAccess.csproj b/packages/backend/YaleAccess.csproj index 408dbad..a31870e 100644 --- a/packages/backend/YaleAccess.csproj +++ b/packages/backend/YaleAccess.csproj @@ -1,7 +1,7 @@  - net7.0 + net10.0 enable enable 83aa9238-2d6b-483c-b60d-886f32d17532 @@ -17,23 +17,20 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - + + + + + + +