diff --git a/back/Program.cs b/back/Program.cs new file mode 100644 index 0000000..8dbf2df --- /dev/null +++ b/back/Program.cs @@ -0,0 +1,105 @@ +using MCVIngenieros.Healthchecks; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; +using Scalar.AspNetCore; +using Serilog; + +namespace back; + +public class Program +{ + public static void Main(string[] args) + { + var configFiles = Path.Combine(AppContext.BaseDirectory, "configs"); + if (!Directory.Exists(configFiles)) + { + Directory.CreateDirectory(configFiles); + } + + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"; + + var configurationBuilder = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{environment}.json", optional: false, reloadOnChange: true); + + var configs = Directory.GetFiles(configFiles, "*.json", SearchOption.AllDirectories); + foreach (var config in configs) + { + configurationBuilder.AddJsonFile(config, optional: true, reloadOnChange: true); + } + + var configuration = configurationBuilder.Build(); + + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .MinimumLevel.Verbose() + .Enrich.FromLogContext() + .CreateLogger(); + + try + { + var builder = WebApplication.CreateBuilder(args); + builder.Configuration.AddConfiguration(configuration); + builder.Host.UseSerilog(); + // Add services to the container. + builder.Services.AddHealthChecksSupport().DiscoverHealthChecks(); + builder.Services.AddLogging(); + builder.Logging.AddOpenTelemetry(options => + { + options + .SetResourceBuilder( + ResourceBuilder.CreateDefault() + .AddService(AppDomain.CurrentDomain.FriendlyName)) + .AddConsoleExporter(); + }); + builder.Services.AddOpenTelemetry() + .ConfigureResource(resource => resource.AddService(AppDomain.CurrentDomain.FriendlyName)) + .WithTracing(tracing => tracing + .AddAspNetCoreInstrumentation() + .AddConsoleExporter()) + .WithMetrics(metrics => metrics + .AddAspNetCoreInstrumentation() + .AddConsoleExporter()); + + + + builder.Services.AddControllers(options => + { + options.Filters.Add(new Microsoft.AspNetCore.Mvc.RequireHttpsAttribute()); + }); + // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi + builder.Services.AddOpenApi(); + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.MapOpenApi(); + app.MapScalarApiReference("/api-docs", opt => + { + opt.WithTitle("My API Documentation"); + }); + } + + app.UseHttpsRedirection(); + + app.UseAuthorization(); + + + app.MapControllers(); + + app.Run(); + } + catch (Exception ex) + { + Log.Fatal(ex, "Application start-up failed"); + } + finally + { + Log.CloseAndFlush(); + } + } +} diff --git a/back/Properties/launchSettings.json b/back/Properties/launchSettings.json new file mode 100644 index 0000000..acdfb46 --- /dev/null +++ b/back/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "api-docs", + "applicationUrl": "https://localhost:7157", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/back/appsettings.Development.json b/back/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/back/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/back/appsettings.Production.json b/back/appsettings.Production.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/back/appsettings.Production.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/back/appsettings.Staging.json b/back/appsettings.Staging.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/back/appsettings.Staging.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/back/appsettings.json b/back/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/back/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/back/back.csproj b/back/back.csproj new file mode 100644 index 0000000..bad8936 --- /dev/null +++ b/back/back.csproj @@ -0,0 +1,48 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/back/back.sln b/back/back.sln new file mode 100644 index 0000000..3b14fa6 --- /dev/null +++ b/back/back.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36401.2 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "back", "back.csproj", "{C78E8225-44D3-434B-AC2A-C8F4459BB18C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C78E8225-44D3-434B-AC2A-C8F4459BB18C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C78E8225-44D3-434B-AC2A-C8F4459BB18C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C78E8225-44D3-434B-AC2A-C8F4459BB18C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C78E8225-44D3-434B-AC2A-C8F4459BB18C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D5ABA005-3E91-4220-9B2C-874C0BED7E34} + EndGlobalSection +EndGlobal diff --git a/back/configs/healthchecks.json b/back/configs/healthchecks.json new file mode 100644 index 0000000..54fd253 --- /dev/null +++ b/back/configs/healthchecks.json @@ -0,0 +1,15 @@ +{ + "HealthChecksConfigs": { + "CacheDuration": "00:30:00", + "Timeout": "00:00:05", + "AssembliesToScan": [ + "back" + ] + //"MyCheck": { + // "RetryAttempts": 2, + // "Timeout": "00:05:00", + // "RetryDelay": "00:00:10", + // "Severity": "Info" + //} + } +} \ No newline at end of file diff --git a/back/configs/serilog.json b/back/configs/serilog.json new file mode 100644 index 0000000..d7e7e0b --- /dev/null +++ b/back/configs/serilog.json @@ -0,0 +1,41 @@ +{ + "Serilog": { + "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.OpenTelemetry" ], + "MinimumLevel": { + "Default": "Information" + }, + "WriteTo": [ + { + "Name": "Console" + }, + { + "Name": "File", + "Args": { + "path": "Logs/log-.txt", + "rollingInterval": "Day", + "fileSizeLimitBytes": 5242880, + "rollOnFileSizeLimit": true, + "retainedFileCountLimit": 31, + "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "OpenTelemetry", + "Args": { + "endpoint": "http://localhost:4317", + "protocol": "Grpc", + "resourceAttributes": { + "service.name": "back.mmorales.photo", + "deployment.environment": "development" + } + } + } + ], + "Enrich": [ + "FromLogContext", + "WithThreadId", + "WithProcessId", + "WithEnvironmentName" + ] + } +} diff --git a/Captura de pantalla 2025-08-11 003208.png b/docs/uiux/paleta (1).png similarity index 100% rename from Captura de pantalla 2025-08-11 003208.png rename to docs/uiux/paleta (1).png diff --git a/Captura de pantalla 2025-08-11 003533.png b/docs/uiux/paleta (2).png similarity index 100% rename from Captura de pantalla 2025-08-11 003533.png rename to docs/uiux/paleta (2).png