Working on BackgroundService

This commit is contained in:
Janus Knudsen 2025-02-20 17:14:53 +01:00
parent 9f4996bc8f
commit ad4ed12f00
12 changed files with 368 additions and 317 deletions

View file

@ -1,10 +1,14 @@
{
"AllowedHosts": "*",
"ConnectionStrings": {
"ptdb": "Host=localhost;Port=5433;Database=ptdb01;User Id=sathumper;Password=3911;"
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id={usr};Password={pwd};"
},
"TelemetryConfig": {
"ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548",
"ApplicationInsights": {
"ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/",
"UseSeqLoggingTelemetryChannel": true
},
"SeqConfiguration": {
"IngestionEndpoint": "http://localhost:5341",
"ApiKey": null,
"Environment": "MSTEST"
}
}

View file

@ -19,7 +19,6 @@ namespace PlanTempus.Core.Logging
_telemetryClient = telemetryClient;
_messageChannel = messageChannel;
_seqLogger = seqlogger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)

View file

@ -3,237 +3,238 @@ using System.Text;
namespace PlanTempus.Core.Logging
{
public class SeqLogger<T>
{
private readonly SeqHttpClient _httpClient;
private readonly string _environmentName;
private readonly string _machineName;
private readonly SeqConfiguration _configuration;
public class SeqLogger<T>
{
private readonly SeqHttpClient _httpClient;
private readonly string _environmentName;
private readonly string _machineName;
private readonly SeqConfiguration _configuration;
public SeqLogger(SeqHttpClient httpClient, string environmentName, SeqConfiguration configuration)
{
_httpClient = httpClient;
}
public SeqLogger(SeqHttpClient httpClient, SeqConfiguration configuration)
{
_httpClient = httpClient;
_configuration = configuration;
}
public async Task LogAsync(TraceTelemetry trace, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", trace.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", trace.Message },
{ "@l", MapSeverityToLevel(trace.SeverityLevel) },
{ "Environment", _environmentName },
{ "MachineName", _machineName }
};
public async Task LogAsync(TraceTelemetry trace, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", trace.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", trace.Message },
{ "@l", MapSeverityToLevel(trace.SeverityLevel) },
{ "Environment", _environmentName },
{ "MachineName", _machineName }
};
foreach (var prop in trace.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in trace.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in trace.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
foreach (var prop in trace.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
await SendToSeqAsync(seqEvent, cancellationToken);
}
await SendToSeqAsync(seqEvent, cancellationToken);
}
public async Task LogAsync(EventTelemetry evt, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", evt.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", evt.Name },
{ "@l", "Information" },
{ "Environment", _environmentName },
{ "MachineName", _machineName }
};
public async Task LogAsync(EventTelemetry evt, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", evt.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", evt.Name },
{ "@l", "Information" },
{ "Environment", _environmentName },
{ "MachineName", _machineName }
};
foreach (var prop in evt.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in evt.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in evt.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
foreach (var prop in evt.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
foreach (var metric in evt.Metrics)
seqEvent.Add($"metric_{metric.Key}", metric.Value);
foreach (var metric in evt.Metrics)
seqEvent.Add($"metric_{metric.Key}", metric.Value);
await SendToSeqAsync(seqEvent, cancellationToken);
}
await SendToSeqAsync(seqEvent, cancellationToken);
}
public async Task LogAsync(ExceptionTelemetry ex, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", ex.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", ex.Exception.Message },
{ "@l", "Error" },
{ "@x", FormatExceptionForSeq(ex.Exception) },
{ "Environment", _environmentName },
{ "MachineName", _machineName },
{ "ExceptionType", ex.Exception.GetType().Name },
};
public async Task LogAsync(ExceptionTelemetry ex, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", ex.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", ex.Exception.Message },
{ "@l", "Error" },
{ "@x", FormatExceptionForSeq(ex.Exception) },
{ "Environment", _environmentName },
{ "MachineName", _machineName },
{ "ExceptionType", ex.Exception.GetType().Name },
};
foreach (var prop in ex.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in ex.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in ex.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
foreach (var prop in ex.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
await SendToSeqAsync(seqEvent, cancellationToken);
}
await SendToSeqAsync(seqEvent, cancellationToken);
}
public async Task LogAsync(DependencyTelemetry dep, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", dep.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", $"Dependency: {dep.Name}" },
{ "@l", dep.Success??true ? "Information" : "Error" },
{ "Environment", _environmentName },
{ "MachineName", _machineName },
{ "DependencyType", dep.Type },
{ "Target", dep.Target },
{ "Duration", dep.Duration.TotalMilliseconds }
};
public async Task LogAsync(DependencyTelemetry dep, CancellationToken cancellationToken = default)
{
var seqEvent = new Dictionary<string, object>
{
{ "@t", dep.Timestamp.UtcDateTime.ToString("o") },
{ "@mt", $"Dependency: {dep.Name}" },
{ "@l", dep.Success??true ? "Information" : "Error" },
{ "Environment", _environmentName },
{ "MachineName", _machineName },
{ "DependencyType", dep.Type },
{ "Target", dep.Target },
{ "Duration", dep.Duration.TotalMilliseconds }
};
foreach (var prop in dep.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in dep.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in dep.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
foreach (var prop in dep.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
await SendToSeqAsync(seqEvent, cancellationToken);
}
await SendToSeqAsync(seqEvent, cancellationToken);
}
public async Task LogAsync(RequestTelemetry req, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public async Task LogAsync(Microsoft.ApplicationInsights.Extensibility.IOperationHolder<RequestTelemetry> operationHolder, CancellationToken cancellationToken = default)
{
var req = operationHolder.Telemetry;
public async Task LogAsync(RequestTelemetry req, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public async Task LogAsync(Microsoft.ApplicationInsights.Extensibility.IOperationHolder<RequestTelemetry> operationHolder, CancellationToken cancellationToken = default)
{
var req = operationHolder.Telemetry;
//https://docs.datalust.co/v2025.1/docs/posting-raw-events
var seqEvent = new Dictionary<string, object>
{
//https://docs.datalust.co/v2025.1/docs/posting-raw-events
var seqEvent = new Dictionary<string, object>
{
{ "@t", req.Timestamp.UtcDateTime.ToString("o") },
{ "@mt",req.Name },
{ "@l", req.Success??true ? "Information" : "Error" },
{ "@sp", req.Id }, //Span id Unique identifier of a span Yes, if the event is a span
{ "@t", req.Timestamp.UtcDateTime.ToString("o") },
{ "@mt",req.Name },
{ "@l", req.Success??true ? "Information" : "Error" },
{ "@sp", req.Id }, //Span id Unique identifier of a span Yes, if the event is a span
{ "@tr", req.Context.Operation.Id}, //Trace id An identifier that groups all spans and logs that are in the same trace Yes, if the event is a span
{ "@sk","Server" }, //Span kind Describes the relationship of the span to others in the trace: Client, Server, Internal, Producer, or Consumer
{ "@st", req.Timestamp.UtcDateTime.Subtract(req.Duration).ToString("o") }, //Start The start ISO 8601 timestamp of this span Yes, if the event is a span
{ "SourceContext", typeof(T).FullName },
{ "Url", req.Url },
{ "RequestId", req.Id },
{ "ItemTypeFlag", req.ItemTypeFlag.ToString() }
};
{ "Url", req.Url },
{ "RequestId", req.Id },
{ "ItemTypeFlag", req.ItemTypeFlag.ToString() }
};
if (!string.IsNullOrEmpty(req.ResponseCode))
{
if (int.TryParse(req.ResponseCode, out int statusCode))
{
if (Enum.IsDefined(typeof(System.Net.HttpStatusCode), statusCode))
seqEvent["StatusCode"] = $"{statusCode} {(System.Net.HttpStatusCode)statusCode}";
else
seqEvent["StatusCode"] = $"{statusCode} Unknown";
}
}
if (!string.IsNullOrEmpty(req.Context.Operation.ParentId))
seqEvent["@ps"] = req.Context.Operation.ParentId;
if (!string.IsNullOrEmpty(req.ResponseCode))
{
if (int.TryParse(req.ResponseCode, out int statusCode))
{
if (Enum.IsDefined(typeof(System.Net.HttpStatusCode), statusCode))
seqEvent["StatusCode"] = $"{statusCode} {(System.Net.HttpStatusCode)statusCode}";
else
seqEvent["StatusCode"] = $"{statusCode} Unknown";
}
}
if (!string.IsNullOrEmpty(req.Context.Operation.ParentId))
seqEvent["@ps"] = req.Context.Operation.ParentId;
if (req.Properties.TryGetValue("httpMethod", out string method))
{
seqEvent["RequestMethod"] = method;
seqEvent["@mt"] = $"{req.Properties["httpMethod"]} {req.Name}";
req.Properties.Remove("httpMethod");
}
if (req.Properties.TryGetValue("httpMethod", out string method))
{
seqEvent["RequestMethod"] = method;
seqEvent["@mt"] = $"{req.Properties["httpMethod"]} {req.Name}";
req.Properties.Remove("httpMethod");
}
foreach (var prop in req.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in req.Properties)
seqEvent.Add($"prop_{prop.Key}", prop.Value);
foreach (var prop in req.Context.GlobalProperties)
seqEvent.Add($"global_{prop.Key}", prop.Value);
foreach (var prop in req.Context.GlobalProperties)
seqEvent.Add($"{prop.Key}", prop.Value);
await SendToSeqAsync(seqEvent, cancellationToken);
}
private async Task SendToSeqAsync(Dictionary<string, object> seqEvent, CancellationToken cancellationToken)
{
var content = new StringContent(
Newtonsoft.Json.JsonConvert.SerializeObject(seqEvent),
Encoding.UTF8,
"application/vnd.serilog.clef");
await SendToSeqAsync(seqEvent, cancellationToken);
}
private async Task SendToSeqAsync(Dictionary<string, object> seqEvent, CancellationToken cancellationToken)
{
var content = new StringContent(
Newtonsoft.Json.JsonConvert.SerializeObject(seqEvent),
Encoding.UTF8,
"application/vnd.serilog.clef");
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/ingest/clef")
{
Content = content
};
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/ingest/clef")
{
Content = content
};
var result = await _httpClient.SendAsync(requestMessage, cancellationToken);
var result = await _httpClient.SendAsync(requestMessage, cancellationToken);
result.EnsureSuccessStatusCode();
}
result.EnsureSuccessStatusCode();
}
private string MapSeverityToLevel(SeverityLevel? severity)
{
return severity switch
{
SeverityLevel.Verbose => "Verbose",
SeverityLevel.Information => "Information",
SeverityLevel.Warning => "Warning",
SeverityLevel.Error => "Error",
SeverityLevel.Critical => "Fatal",
_ => "Information"
};
}
private string FormatExceptionForSeq(Exception ex)
{
var sb = new StringBuilder();
var exceptionCount = 0;
private static string MapSeverityToLevel(SeverityLevel? severity)
{
return severity switch
{
SeverityLevel.Verbose => "Verbose",
SeverityLevel.Information => "Information",
SeverityLevel.Warning => "Warning",
SeverityLevel.Error => "Error",
SeverityLevel.Critical => "Fatal",
_ => "Information"
};
}
private static string FormatExceptionForSeq(Exception ex)
{
var sb = new StringBuilder();
var exceptionCount = 0;
void FormatSingleException(Exception currentEx, int depth)
{
if (depth > 0) sb.AppendLine("\n--- Inner Exception ---");
void FormatSingleException(Exception currentEx, int depth)
{
if (depth > 0) sb.AppendLine("\n--- Inner Exception ---");
sb.AppendLine($"Exception Type: {currentEx.GetType().FullName}");
sb.AppendLine($"Message: {currentEx.Message}");
sb.AppendLine($"Source: {currentEx.Source}");
sb.AppendLine($"HResult: 0x{currentEx.HResult:X8}");
sb.AppendLine("Stack Trace:");
sb.AppendLine(currentEx.StackTrace?.Trim());
sb.AppendLine($"Exception Type: {currentEx.GetType().FullName}");
sb.AppendLine($"Message: {currentEx.Message}");
sb.AppendLine($"Source: {currentEx.Source}");
sb.AppendLine($"HResult: 0x{currentEx.HResult:X8}");
sb.AppendLine("Stack Trace:");
sb.AppendLine(currentEx.StackTrace?.Trim());
if (currentEx.Data.Count > 0)
{
sb.AppendLine("Additional Data:");
foreach (var key in currentEx.Data.Keys)
{
sb.AppendLine($" {key}: {currentEx.Data[key]}");
}
}
}
if (currentEx.Data.Count > 0)
{
sb.AppendLine("Additional Data:");
foreach (var key in currentEx.Data.Keys)
{
sb.AppendLine($" {key}: {currentEx.Data[key]}");
}
}
}
void RecurseExceptions(Exception currentEx, int depth = 0)
{
if (currentEx is AggregateException aggEx)
{
foreach (var inner in aggEx.InnerExceptions)
{
RecurseExceptions(inner, depth);
depth++;
}
}
else if (currentEx.InnerException != null)
{
RecurseExceptions(currentEx.InnerException, depth + 1);
}
void RecurseExceptions(Exception currentEx, int depth = 0)
{
if (currentEx is AggregateException aggEx)
{
foreach (var inner in aggEx.InnerExceptions)
{
RecurseExceptions(inner, depth);
depth++;
}
}
else if (currentEx.InnerException != null)
{
RecurseExceptions(currentEx.InnerException, depth + 1);
}
FormatSingleException(currentEx, depth);
exceptionCount++;
}
FormatSingleException(currentEx, depth);
exceptionCount++;
}
RecurseExceptions(ex);
sb.Insert(0, $"EXCEPTION CHAIN ({exceptionCount} exceptions):\n");
return sb.ToString();
}
}
RecurseExceptions(ex);
sb.Insert(0, $"EXCEPTION CHAIN ({exceptionCount} exceptions):\n");
return sb.ToString();
}
}
}

View file

@ -4,25 +4,29 @@ using PlanTempus.Core.Telemetry;
namespace PlanTempus.Core.ModuleRegistry
{
public class SeqLoggingModule : Module
{
protected override void Load(ContainerBuilder builder)
{
public class SeqLoggingModule : Module
{
public required SeqConfiguration SeqConfiguration { get; set; }
builder.RegisterType<MessageChannel>()
.As<IMessageChannel<Microsoft.ApplicationInsights.Channel.ITelemetry>>()
.SingleInstance();
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<SeqBackgroundService>()
.As<Microsoft.Extensions.Hosting.IHostedService>()
.SingleInstance();
builder.RegisterType<MessageChannel>()
.As<IMessageChannel<Microsoft.ApplicationInsights.Channel.ITelemetry>>()
.SingleInstance();
builder.RegisterType<SeqHttpClient>()
.As<SeqHttpClient>()
.SingleInstance();
builder.RegisterType<SeqBackgroundService>()
.As<Microsoft.Extensions.Hosting.IHostedService>()
.SingleInstance();
builder.RegisterGeneric(typeof(SeqLogger<>));
builder.RegisterInstance(SeqConfiguration);
}
}
builder.RegisterType<SeqHttpClient>()
.As<SeqHttpClient>()
.SingleInstance();
}
}
}

View file

@ -6,6 +6,10 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Database\PlanTempus.Database.csproj" />
</ItemGroup>

View file

@ -1,5 +1,6 @@
using Autofac;
using Insight.Database;
using Microsoft.Extensions.Hosting;
using PlanTempus.Database.ConfigurationManagementSystem;
using PlanTempus.Database.Core.DCL;
using PlanTempus.Database.Core.DDL;
@ -189,5 +190,35 @@ namespace PlanTempus.SetupInfrastructure
Console.ForegroundColor = ConsoleColor.White;
}
}
async Task Run(string[] args)
{
try
{
var host = Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new Autofac.Extensions.DependencyInjection.AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>((hostContext, builder) =>
{
var startup = new Startup();
var connectionStringParams = new Startup.ConnectionStringTemplateParameters("your_user", "your_password");
startup.ConfigureContainer(connectionStringParams);
})
.ConfigureServices((hostContext, services) =>
{
// Konfigurer andre services her (hvis nødvendigt)
})
.Build();
await host.StartAsync();
Console.WriteLine("Host has started.");
await host.WaitForShutdownAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Host failed to start: {ex}");
}
}
}
}

View file

@ -6,41 +6,47 @@ using PlanTempus.Database.Core;
namespace PlanTempus.SetupInfrastructure
{
public class Startup
{
public virtual IConfigurationRoot Configuration()
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appconfiguration.json")
.Build();
public class Startup
{
public virtual IConfigurationRoot Configuration()
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appconfiguration.json")
.Build();
return configuration;
}
return configuration;
}
public IContainer ConfigureContainer(ConnectionStringTemplateParameters ctp)
{
var builder = new ContainerBuilder();
var configuration = Configuration();
public IContainer ConfigureContainer(ConnectionStringTemplateParameters ctp)
{
var builder = new ContainerBuilder();
var configuration = Configuration();
builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule
{
ConnectionString = configuration.GetConnectionString("DefaultConnection").Replace("{usr}", ctp.user).Replace("{pwd}", ctp.pwd)
});
builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule
{
ConnectionString = configuration.GetConnectionString("DefaultConnection").Replace("{usr}", ctp.user).Replace("{pwd}", ctp.pwd)
});
builder.RegisterModule(new TelemetryModule
{
TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject<TelemetryConfig>()
});
builder.RegisterModule(new TelemetryModule
{
TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject<TelemetryConfig>()
});
builder.RegisterAssemblyTypes(typeof(IDbConfigure<>).Assembly)
.AsClosedTypesOf(typeof(IDbConfigure<>))
.AsSelf();
builder.RegisterModule(new SeqLoggingModule
{
SeqConfiguration = configuration.GetSection("SeqConfiguration").ToObject<Core.Logging.SeqConfiguration>()
});
return builder.Build();
}
builder.RegisterAssemblyTypes(typeof(IDbConfigure<>).Assembly)
.AsClosedTypesOf(typeof(IDbConfigure<>))
.AsSelf();
public record ConnectionStringTemplateParameters(string user, string pwd);
}
return builder.Build();
}
public record ConnectionStringTemplateParameters(string user, string pwd);
}
}

View file

@ -1,9 +1,14 @@
{
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id={usr};Password={pwd};"
},
"ApplicationInsights": {
"ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/"
"ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/",
"UseSeqLoggingTelemetryChannel": true
},
"SeqConfiguration": {
"IngestionEndpoint": "http://localhost:5341",
"ApiKey": null,
"Environment": "MSTEST"
}
}

View file

@ -23,7 +23,7 @@ namespace PlanTempus.Tests.Logging
var config = new SeqConfiguration("http://localhost:5341", null, "MSTEST");
var httpClient = new SeqHttpClient(config);
var logger = new SeqLogger<SeqBackgroundService>(httpClient, Environment.MachineName, config);
var logger = new SeqLogger<SeqBackgroundService>(httpClient, config);
_service = new SeqBackgroundService(telemetryClient, _messageChannel, logger);
_cts = new CancellationTokenSource();

View file

@ -17,7 +17,7 @@ namespace PlanTempus.Tests.Logging
_testId = Guid.NewGuid().ToString();
var config = new SeqConfiguration("http://localhost:5341", null, "MSTEST");
_httpClient = new SeqHttpClient(config);
_logger = new SeqLogger<SeqLoggerTests>(_httpClient, Environment.MachineName, config);
_logger = new SeqLogger<SeqLoggerTests>(_httpClient, config);
}
[TestMethod]

View file

@ -8,92 +8,84 @@ using PlanTempus.Core.Configurations.JsonConfigProvider;
using PlanTempus.Core.ModuleRegistry;
namespace PlanTempus.Tests
{
/// <summary>
/// Act as base class for tests. Avoids duplication of test setup code
/// </summary>
[TestClass]
public abstract partial class TestFixture
{
private readonly string _configurationFilePath;
/// <summary>
/// Act as base class for tests. Avoids duplication of test setup code
/// </summary>
[TestClass]
public abstract partial class TestFixture
{
private readonly string _configurationFilePath;
protected IContainer Container { get; private set; }
protected ContainerBuilder ContainerBuilder { get; private set; }
protected IContainer Container { get; private set; }
protected ContainerBuilder ContainerBuilder { get; private set; }
public virtual IConfigurationRoot Configuration()
{
var configuration = new ConfigurationBuilder()
.AddJsonFile($"{_configurationFilePath}appconfiguration.dev.json")
.Build();
public virtual IConfigurationRoot Configuration()
{
var configuration = new ConfigurationBuilder()
.AddJsonFile($"{_configurationFilePath}appconfiguration.dev.json")
.Build();
return configuration;
}
return configuration;
}
protected TestFixture() : this(null) { }
public TestFixture(string configurationFilePath)
{
if (configurationFilePath is not null)
_configurationFilePath = configurationFilePath?.TrimEnd('/') + "/";
protected TestFixture() : this(null) { }
public TestFixture(string configurationFilePath)
{
if (configurationFilePath is not null)
_configurationFilePath = configurationFilePath?.TrimEnd('/') + "/";
CreateContainerBuilder();
Container = ContainerBuilder.Build();
}
protected virtual void CreateContainerBuilder()
{
IConfigurationRoot configuration = Configuration();
CreateContainerBuilder();
Container = ContainerBuilder.Build();
}
protected virtual void CreateContainerBuilder()
{
IConfigurationRoot configuration = Configuration();
//var logger = new LoggerConfiguration()
// .MinimumLevel.Verbose()
// .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
// .MinimumLevel.Override("System", Serilog.Events.LogEventLevel.Error)
// .WriteTo.Seq("http://localhost:5341", apiKey: "Gt8hS9ClGNfOCAdswDlW")
// .WriteTo.ApplicationInsights(configuration.Get<string>("ApplicationInsights:ConnectionString"),
// TelemetryConverter.Traces)
// .Enrich.FromLogContext()
// .Enrich.WithMachineName()
// .CreateLogger();
//var logger = new LoggerConfiguration()
// .MinimumLevel.Verbose()
// .MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
// .MinimumLevel.Override("System", Serilog.Events.LogEventLevel.Error)
// .WriteTo.Seq("http://localhost:5341", apiKey: "Gt8hS9ClGNfOCAdswDlW")
// .WriteTo.ApplicationInsights(configuration.Get<string>("ApplicationInsights:ConnectionString"),
// TelemetryConverter.Traces)
// .Enrich.FromLogContext()
// .Enrich.WithMachineName()
// .CreateLogger();
//Log.Logger = logger;
var builder = new ContainerBuilder();
//Log.Logger.Verbose("Is thos work");
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(Logger<>))
.As(typeof(ILogger<>))
.SingleInstance();
//builder.Register(c => new SerilogLoggerFactory(logger))
// .As<ILoggerFactory>()
// .SingleInstance();
builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule
{
ConnectionString = configuration.GetConnectionString("DefaultConnection")
});
builder.RegisterGeneric(typeof(Logger<>))
.As(typeof(ILogger<>))
.SingleInstance();
builder.RegisterModule(new TelemetryModule
{
TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject<TelemetryConfig>()
});
builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule
{
ConnectionString = configuration.GetConnectionString("DefaultConnection")
});
ContainerBuilder = builder;
}
builder.RegisterModule(new TelemetryModule
{
TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject<TelemetryConfig>()
});
[TestCleanup]
public void CleanUp()
{
Trace.Flush();
var telemetryClient = Container.Resolve<TelemetryClient>();
telemetryClient.Flush();
if (Container != null)
{
Container.Dispose();
Container = null;
}
}
ContainerBuilder = builder;
}
[TestCleanup]
public void CleanUp()
{
Trace.Flush();
var telemetryClient = Container.Resolve<TelemetryClient>();
telemetryClient.Flush();
if (Container != null)
{
Container.Dispose();
Container = null;
}
}
}
}
}

View file

@ -5,5 +5,10 @@
"ApplicationInsights": {
"ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/",
"UseSeqLoggingTelemetryChannel": true
},
"SeqConfiguration": {
"IngestionEndpoint": "http://localhost:5341",
"ApiKey": null,
"Environment": "MSTEST"
}
}