// Licensed to Timothy Schenk under the GNU AGPL Version 3 License. using System.Net; using System.Reflection; using System.Text.Json; using Continuity.AuthServer; using Continuity.AuthServer.DB; using Continuity.AuthServer.PacketHandlers; using Continuity.AuthServer.Services; using MassTransit; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Npgsql; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; using RaiNote.PacketMediator; using Wonderking.Game.Mapping; using Wonderking.Packets; var builder = Host.CreateApplicationBuilder(); #if DEBUG builder.Environment.EnvironmentName = "Development"; #endif builder.Services.AddMetrics(); builder.Configuration.AddJsonFile("settings.json", true, true) .AddJsonFile($"settings.{builder.Environment.EnvironmentName}.json", true) .AddEnvironmentVariables().Build(); builder.Services.AddLogging(); var loggerFactory = LoggerFactory.Create(loggingBuilder => { loggingBuilder.AddFile("logs/Continuity.AuthServer-{Date}.log", LogLevel.Trace); loggingBuilder.AddFile("logs/Continuity.AuthServer-{Date}.json.log", LogLevel.Trace, isJson: true); loggingBuilder.AddConsole(); loggingBuilder.AddOpenTelemetry(); }); var configuration = builder.Configuration; builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; }); builder.Services.AddOpenTelemetry() .WithMetrics(metrics => { metrics.AddRuntimeInstrumentation().AddProcessInstrumentation().AddMeter("Microsoft.AspNetCore.Hosting", nameof(Continuity.AuthServer)) .ConfigureResource(resourceBuilder => resourceBuilder.AddService("Continuity", serviceNamespace: "Wonderking", serviceVersion: "0.0.1")); }) .WithTracing(tracing => { if (builder.Environment.IsDevelopment()) { tracing.SetSampler(); } tracing.AddEntityFrameworkCoreInstrumentation(options => options.SetDbStatementForText = true).AddNpgsql(); }); builder.Services.AddMetrics(); builder.Services.Configure(logging => logging.AddOtlpExporter()); builder.Services.ConfigureOpenTelemetryMeterProvider(meter => meter.AddOtlpExporter()); builder.Services.ConfigureOpenTelemetryTracerProvider(tracer => tracer.AddOtlpExporter()); builder.Services.AddHealthChecks() .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); builder.Services.AddDbContextPool(o => { o.UseNpgsql( $"Host={configuration["DB:Host"]};Username={configuration["DB:Username"]};Password={configuration["DB:Password"]};Database={configuration["DB:Database"]};Port={configuration["DB:Port"]}") .EnableSensitiveDataLogging().UseLoggerFactory(loggerFactory); }); builder.Services.AddSingleton( JsonSerializer.Deserialize( File.ReadAllText("config/character-stats.mapping.json")) ?? throw new InvalidOperationException()); builder.Services.AddSingleton(loggerFactory); builder.Services.AddSingleton(provider => new PacketDistributorService( provider.GetRequiredService(), new List { Assembly.GetAssembly(typeof(OperationCode)) }.AsReadOnly(), new List { Assembly.GetAssembly(typeof(LoginHandler)) }.AsReadOnly() )); builder.Services.AddSingleton(); builder.Services.AddHostedService(provider => new WonderkingAuthServer(IPAddress.Any, 10001, provider.GetService>() ?? throw new InvalidOperationException(), provider.GetService() ?? throw new InvalidOperationException())); builder.Services.AddHostedService(provider => provider.GetService() ?? throw new InvalidOperationException()); builder.Services.AddHostedService(provider => provider.GetService>() ?? throw new InvalidOperationException()); builder.Services.AddMassTransit(x => { x.UsingInMemory((context, configurator) => configurator.ConfigureEndpoints(context)); x.AddMediator(cfg => cfg.AddConsumers(Assembly.GetExecutingAssembly())); }); using var host = builder.Build(); await using (var scope = host.Services.CreateAsyncScope()) { var db = scope.ServiceProvider.GetRequiredService(); await db.Database.MigrateAsync(); } await host.RunAsync();