Skip to content

Instantly share code, notes, and snippets.

@FelixSFD
Last active October 27, 2021 11:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FelixSFD/84cf9f447a83d36c8251c3bd6de8f5c4 to your computer and use it in GitHub Desktop.
Save FelixSFD/84cf9f447a83d36c8251c3bd6de8f5c4 to your computer and use it in GitHub Desktop.
startup-classes
using log4net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Oracle.ManagedDataAccess.Client;
using Prometheus;
using Sera.Common.AutoMapper;
using Sera.Common.Core.Context;
using Sera.Common.Grpc.Interceptors;
using Sera.Common.Helper;
using Sera.Common.Logging;
using System;
using System.Collections.Generic;
namespace Sera.Common
{
/// <summary>
/// Basisklasse für die Startup-Klasse eines Microservices. Enthält nützliche Methoden, die mehrfach verwendet werden.
/// </summary>
public abstract class MicroserviceStartupBase
{
private static readonly ILog _logger = LogManager.GetLogger(nameof(MicroserviceStartupBase));
/// <summary>
/// Beinhaltet die Konfiguration aus der appsettings.{Environment}.json
/// </summary>
public static IConfiguration Configuration { get; private set; }
/// <summary>
/// Sekunden, um die das Beenden des Services maximal verzögert werden kann.
/// </summary>
protected abstract int ShutdownTimeout { get; }
/// <summary>
/// Konstruktor, welche die Configuration festlegt
/// </summary>
/// <param name="env">Beinhaltet die Informationen für die Applikationsumgebung</param>
public MicroserviceStartupBase(IWebHostEnvironment env)
{
// Fügt die RequestGuid zum logischen Thread des Logging hinzu
GlobalContext.Properties["RequestGuid"] = Guid.Empty;
Log4NetConfigurator.Setup();
_logger.InfoFormat("Starting Microservice {0} ...", System.Reflection.Assembly.GetEntryAssembly().GetName().Name);
_logger.Debug("Env: " + env.EnvironmentName);
_logger.Info("Version: " + System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString());
_logger.InfoFormat("CPU count: {0}", Environment.ProcessorCount);
Configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables()
.Build();
constructorConfiguration();
}
/// <summary>
/// Konstruktor, welche die Configuration festlegt
/// </summary>
/// <param name="configuration">Konfiguration aus den appsettings.json</param>
public MicroserviceStartupBase(IConfiguration configuration)
{
Configuration = configuration;
constructorConfiguration();
}
/// <summary>
/// Initialisieren der ConfigurationOptions und des Loggers
/// </summary>
private void constructorConfiguration()
{
//Config mit AppSettings verknüpfen
AppSettings.SetConfiguration(Configuration);
}
/// This method gets called by the runtime. Use this method to add services to the container.
public virtual void ConfigureServices(IServiceCollection services)
{
//Configure Oracle-Client
_logger.Debug("Configure Oracle-Client...");
OracleConfiguration.SqlNetAuthenticationServices = "(none)";
_logger.DebugFormat("OracleConfiguration.SqlNetAuthenticationServices: {0}", OracleConfiguration.SqlNetAuthenticationServices);
//AutoMapper
ConfigureAutoMapper(services);
//Service für Health-Checks
services.AddHealthChecks();
//SeraContext (z.B. GUID und Mandant)
services.AddScoped<ISeraContext, SeraContext>();
services.UseSeraGrpcConfiguration()
.AddGrpcInterceptor<SeraContextInterceptor>()
.AddGrpcInterceptor<GrpcClientMetricsInterceptor>()
.Register();
services.Configure<HostOptions>(option =>
{
_logger.DebugFormat("Set ShutdownTimeout to {0} seconds", ShutdownTimeout);
option.ShutdownTimeout = TimeSpan.FromSeconds(ShutdownTimeout);
});
}
/// <summary>
/// Diese Methode wird zur Laufzeit aufgerufen und konfiguriert die HTTP Request Pipeline.
/// Hier werden die einzelnen Middlewares und deren Reihenfolge angegeben
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
try
{
int? http1Port = EnvironmentExtensions.GetEnvironmentVariable<int>("Http1Port");
if (http1Port != null)
{
app.UseMetricServer(url: "/metrics", port: http1Port.Value);
}
else
{
app.UseMetricServer(url: "/metrics", port: 5200);
}
app.UseGrpcMetrics();
string environment, endpointUrl = null;
environment = EnvironmentExtensions.GetEnvironmentVariable<string>("ASPNETCORE_ENVIRONMENT");
if (environment == null)
{
environment = "null";
}
endpointUrl = EnvironmentExtensions.GetEnvironmentVariable<string>("PUSHGATEWAY_URL");
if (endpointUrl == null)
{
throw new ArgumentNullException("No PushGateway was found in the environment.");
}
var pusher = new MetricPusher(new MetricPusherOptions
{
Endpoint = endpointUrl,
Job = AppDomain.CurrentDomain.FriendlyName + "." + Environment.MachineName,
IntervalMilliseconds = 15000,
AdditionalLabels = new List<Tuple<string, string>>() { new Tuple<string, string>("Environment", environment) }
});
pusher.Start();
}
catch (Exception e)
{
_logger.Error(e);
}
app.UseEndpoints(UseEndpoints(app, env));
}
/// <summary>
/// Gibt eine Action zurück, die die Endpunkte des Microservices konfiguriert
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
/// <returns></returns>
protected virtual Action<IEndpointRouteBuilder> UseEndpoints(IApplicationBuilder app, IWebHostEnvironment env)
{
return UseEndpointsAction;
}
/// <summary>
/// Konfiguriert die Endpunkte des Microservices
/// </summary>
/// <param name="endpoints"></param>
protected abstract void UseEndpointsAction(IEndpointRouteBuilder endpoints);
/// <summary>
/// Konfiguriert den AutoMapper.
/// In der <see cref="MicroserviceStartupBase"/> wird bereits das <see cref="CommonProfile"/> hinzugefügt. Weitere können konfiguriert werden, indem diese Methode überschrieben wird.
/// </summary>
/// <param name="services">Service Collection</param>
protected virtual void ConfigureAutoMapper(IServiceCollection services)
{
_logger.Debug("Configure AutoMapper...");
//removed AutoMapper-config for this sample
}
}
}
using log4net;
using Microsoft.Extensions.DependencyInjection;
using Sera.Common.AutoMapper;
using Sera.Common.Core.Context;
using Sera.Common.Tests.SeraContext;
namespace Sera.Common.Tests
{
public class Startup : TestStartupBase
{
/// <inheritdoc/>
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
//Auto-Mapper konfigurieren
services.AddAutoMapper(cfg =>
{
cfg.AddProfile(new CommonProfile());
});
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Builder;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Sera.Common.AutoMapper;
using Sera.Common.Logging;
namespace Sera.Common.Tests
{
/// <summary>
/// Basisklasse für die Statrup-Klasse in Testprojekten
/// </summary>
public class TestStartupBase : MicroserviceStartupBase
{
/// <inheritdoc/>
protected override int ShutdownTimeout => 15;
/// <summary>
/// Konstruktor, welche die Configuration festlegt
/// </summary>
public TestStartupBase() : base(GetTestConfiguration())
{
}
/// <summary>
/// Lädt die Konfiguration für die Tests aus den AppSettings
/// </summary>
/// <returns></returns>
private static IConfiguration GetTestConfiguration()
{
return new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.Development.json", optional: true)
.AddEnvironmentVariables()
.Build();
}
/// <inheritdoc/>
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//wird in Tests normalerweise nicht verwendet
}
/// <inheritdoc/>
public override void ConfigureServices(IServiceCollection services)
{
ServiceProvider serviceProvider = services.BuildServiceProvider();
IFeatureCollection featureCollection = serviceProvider.GetService<IFeatureCollection>();
ApplicationBuilderFactory appBuilderFactory = new ApplicationBuilderFactory(serviceProvider);
services.AddSingleton(appBuilderFactory.CreateBuilder(featureCollection));
// Configure the Mapper for dependency Injection
//removed the AutoMapper-stuff for this sample
}
/// <inheritdoc/>
protected override void UseEndpointsAction(IEndpointRouteBuilder endpoints)
{
// wird in Tests normalerweise nicht verwendet
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment