Files
mapo-core/MP.SPEC/Program.cs
T
2026-02-25 09:59:03 +01:00

319 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Blazored.LocalStorage;
using Blazored.SessionStorage;
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using MP.AppAuth.Services;
using MP.Data.Services;
using MP.SPEC.Components;
using MP.SPEC.Data;
using MP.SPEC.Services;
using NLog;
using NLog.Targets;
using NLog.Targets.OpenTelemetryProtocol;
using NLog.Web;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using StackExchange.Redis;
var builder = WebApplication.CreateBuilder(args);
/*--------------------
* Note migrazione startup.cs --> program.cs:
*
* - https://stackoverflow.com/questions/69722872/asp-net-core-6-how-to-access-ConfMan-during-startup
* - https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60?view=aspnetcore-5.0&tabs=visual-studio#where-do-i-put-state-that-was-stored-as-fields-in-my-program-or-startup-class
*
* */
ConfigurationManager configuration = builder.Configuration;
var logger = LogManager.Setup()
.LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();
logger.Info("Program.cs: startup");
// REDIS setup
logger.Info("Setup REDIS");
string connStringRedis = configuration.GetConnectionString("Redis") ?? "localhost:6379";
//string connStringRedis = ConfMan.GetConnectionString("RedisAdmin");
string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":"));
// avvio oggetto shared x redis...
var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis);
// ====================================================================
// Setup Tracing e Telemetria...
// ====================================================================
// 1. Leggiamo la configurazione
var otelEnabled = builder.Configuration.GetValue<bool>("Otel:EnableTracing", false);
var otelEndpoint = builder.Configuration["Otel:Endpoint"];
var otelDsn = builder.Configuration["Otel:Dsn"];
if (otelEnabled)
{
// ====================================================================
// SETUP OPENTELEMETRY BASE (Genera gli oggetti Activity)
// Questo gira per i Livelli 1, 2 e 3.
// ====================================================================
var appVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "1.0.0";
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProviderBuilder =>
{
tracerProviderBuilder
.SetResourceBuilder(OpenTelemetry.Resources.ResourceBuilder.CreateDefault()
.AddService(serviceName: "MAPO.SPEC", serviceVersion: appVersion))
.AddSource("MP.DATA.Tracer")
.AddAspNetCoreInstrumentation(options => { options.Filter = ctx => !ctx.Request.Path.StartsWithSegments("/health"); })
.AddSqlClientInstrumentation(options => { options.RecordException = true; })
.AddRedisInstrumentation(redisMultiplexer);
// ====================================================================
// ESPORTAZIONE DI RETE (Solo Livelli 1 e 2)
// ====================================================================
if (!string.IsNullOrWhiteSpace(otelEndpoint))
{
tracerProviderBuilder.AddOtlpExporter(options =>
{
options.Endpoint = new Uri(otelEndpoint);
if (!string.IsNullOrWhiteSpace(otelDsn))
{
options.Headers = $"uptrace-dsn={otelDsn}";
}
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
});
}
// Se otelEndpoint è vuoto (Livello 3), le tracce nascono e muoiono in RAM.
});
// ====================================================================
// ESPORTAZIONE NLOG REALTIME (Solo Livelli 1 e 2)
// ====================================================================
if (!string.IsNullOrWhiteSpace(otelEndpoint))
{
var otlpTarget = new OtlpTarget
{
Name = "UptraceRealtime",
Endpoint = otelEndpoint,
ServiceName = "MP.DATA.Tracer"
};
if (!string.IsNullOrWhiteSpace(otelDsn))
{
otlpTarget.Headers = $"uptrace-dsn={otelDsn}";
}
var config = LogManager.Configuration ?? new NLog.Config.LoggingConfiguration();
config.AddTarget(otlpTarget);
config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, otlpTarget);
LogManager.Configuration = config;
LogManager.ReconfigExistingLoggers();
logger.Info($"🚀 NLog & OTel attivi e in invio verso: {otelEndpoint}");
}
else
{
logger.Info("️ OTel attivo (Local mode). Esportazione di rete disabilitata.");
}
}
else
{
// ====================================================================
// LIVELLO 4: TUTTO SPENTO
// ====================================================================
logger.Info("⏸️ Telemetria e Tracing completamente disabilitati.");
}
//// Check develop e conseguente Uptrace setup
//// CONTROLLO GLOBALE: Tutto questo gira SOLO in Development
//if (builder.Environment.IsDevelopment())
//{
// var uptraceEndpoint = builder.Configuration["UptraceDev:Endpoint"];
// var uptraceDsn = builder.Configuration["UptraceDev:Dsn"];
// // Se le variabili di configurazione esistono nel json locale, attiviamo la magia
// if (!string.IsNullOrEmpty(uptraceEndpoint) && !string.IsNullOrEmpty(uptraceDsn))
// {
// // ====================================================================
// // 1. SETUP NLOG (Per i log in tempo reale)
// // ====================================================================
// var otlpTarget = new OtlpTarget
// {
// Name = "UptraceRealtime",
// Endpoint = uptraceEndpoint,
// ServiceName = "MP.DATA.Tracer",
// Headers = $"uptrace-dsn={uptraceDsn}"
// };
// var config = LogManager.Configuration ?? new NLog.Config.LoggingConfiguration();
// config.AddTarget(otlpTarget);
// config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, otlpTarget);
// LogManager.Configuration = config;
// LogManager.ReconfigExistingLoggers();
// Console.WriteLine("🚀 NLog OTLP Target attivato per Uptrace in Development!");
// // ====================================================================
// // 2. SETUP OPENTELEMETRY (Per gli Span, HTTP, DB e Redis in tempo reale)
// // ====================================================================
// var appVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "1.0.0";
// builder.Services.AddOpenTelemetry()
// .WithTracing(tracerProviderBuilder =>
// {
// tracerProviderBuilder
// // Definiamo il nome e versione del servizio CORRENTE su Uptrace
// .SetResourceBuilder(ResourceBuilder.CreateDefault()
// .AddService(serviceName: "MAPO.SPEC", serviceVersion: appVersion))
// // Diciamo a OTel di ascoltare gli Span manuali generati
// .AddSource("MP.DATA.Tracer")
// // Strumentazione Automatica
// .AddAspNetCoreInstrumentation(options =>
// {
// options.Filter = (httpContext) => !httpContext.Request.Path.StartsWithSegments("/health");
// })
// .AddSqlClientInstrumentation(options =>
// {
// options.RecordException = true;
// })
// // Assicurati che redisMultiplexer sia inizializzato PRIMA di questo blocco
// .AddRedisInstrumentation(redisMultiplexer)
// // Esporta i dati verso Uptrace
// .AddOtlpExporter(options =>
// {
// options.Endpoint = new Uri(uptraceEndpoint);
// options.Headers = $"uptrace-dsn={uptraceDsn}";
// options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
// });
// // Scommenta per testare in console
// // .AddConsoleExporter();
// });
// Console.WriteLine("🚀 OpenTelemetry Tracing attivato per Uptrace in Development!");
// }
// else
// {
// Console.WriteLine("⚠️ Variabili UptraceDev mancanti nel json. Telemetria realtime disabilitata.");
// }
//}
// Add services to the container.
logger.Info("Setup Auth");
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
// redis replliminare
builder.Services.AddSingleton<IConnectionMultiplexer>(redisMultiplexer);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<MpDataService>();
builder.Services.AddSingleton<ListSelectDataSrv>();
builder.Services.AddSingleton<IOApiService>();
builder.Services.AddSingleton<AppAuthService>();
builder.Services.AddScoped<MsgServiceSpec>();
builder.Services.AddSingleton<SharedMemService>();
builder.Services.AddSingleton<TabDataService>();
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddBlazoredSessionStorage();
builder.Services.AddHttpClient();
logger.Info("Aggiunti services");
var app = builder.Build();
logger.Info("Build App");
// aggiunt base URL x routing corretto
app.UsePathBase(configuration.GetValue<string>("SpecialConf:AppUrl"));
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// gestione static files: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-8.0
string BasePathOdlReturn = configuration.GetValue<string>("ServerConf:BasePathOdlReturn") ?? configuration.GetValue<string>("OptConf:BasePathOdlReturn") ?? "";
if (!string.IsNullOrEmpty(BasePathOdlReturn))
{
// preparo mappings opzionali se presenti in conf...
var provider = new FileExtensionContentTypeProvider();
// vedere https://code-maze.com/dotnet-appsettings-json-content-to-dictionary/
var mimeSection = configuration.GetSection("ServerConf:MimeMappings");
if (mimeSection != null)
{
var mimeDict = mimeSection
.AsEnumerable()
.Where(x => !string.IsNullOrWhiteSpace(x.Value))
.ToDictionary(x => x.Key.Replace("ServerConf:MimeMappings:", ""), x => x.Value);
// se ne ho trovati
if (mimeDict != null && mimeDict.Count > 0)
{
// li aggiungo! vedere
// https://thechrisgreen.com/2022/05/add-a-mime-type-to-an-asp-net-core-net-6-app/
// https://harrybellamy.com/posts/getting-mime-types-from-file-extensions-in-net-core/
foreach (var item in mimeDict)
{
// Add new mappings
provider.Mappings[item.Key] = item.Value;
}
}
}
// verifico esista folder
if (Directory.Exists(BasePathOdlReturn))
{
// gestione cartella x file ritornati x ODL
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = provider,
FileProvider = new PhysicalFileProvider(BasePathOdlReturn),
RequestPath = "/RET_DATA",
});
}
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
//app.MapBlazorHub();
//app.MapFallbackToPage("/_Host");
logger.Info("Run App");
app.Run();