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": { "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": { "ApplicationInsights": {
"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", "ConnectionString": "InstrumentationKey=6d2e76ee-5343-4691-a5e3-81add43cb584;IngestionEndpoint=https://northeurope-0.in.applicationinsights.azure.com/",
"UseSeqLoggingTelemetryChannel": true "UseSeqLoggingTelemetryChannel": true
},
"SeqConfiguration": {
"IngestionEndpoint": "http://localhost:5341",
"ApiKey": null,
"Environment": "MSTEST"
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,6 @@
using Autofac; using Autofac;
using Insight.Database; using Insight.Database;
using Microsoft.Extensions.Hosting;
using PlanTempus.Database.ConfigurationManagementSystem; using PlanTempus.Database.ConfigurationManagementSystem;
using PlanTempus.Database.Core.DCL; using PlanTempus.Database.Core.DCL;
using PlanTempus.Database.Core.DDL; using PlanTempus.Database.Core.DDL;
@ -189,5 +190,35 @@ namespace PlanTempus.SetupInfrastructure
Console.ForegroundColor = ConsoleColor.White; 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 namespace PlanTempus.SetupInfrastructure
{ {
public class Startup public class Startup
{ {
public virtual IConfigurationRoot Configuration() public virtual IConfigurationRoot Configuration()
{ {
var configuration = new ConfigurationBuilder() var configuration = new ConfigurationBuilder()
.AddJsonFile("appconfiguration.json") .AddJsonFile("appconfiguration.json")
.Build(); .Build();
return configuration; return configuration;
} }
public IContainer ConfigureContainer(ConnectionStringTemplateParameters ctp) public IContainer ConfigureContainer(ConnectionStringTemplateParameters ctp)
{ {
var builder = new ContainerBuilder(); var builder = new ContainerBuilder();
var configuration = Configuration(); var configuration = Configuration();
builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule
{ {
ConnectionString = configuration.GetConnectionString("DefaultConnection").Replace("{usr}", ctp.user).Replace("{pwd}", ctp.pwd) ConnectionString = configuration.GetConnectionString("DefaultConnection").Replace("{usr}", ctp.user).Replace("{pwd}", ctp.pwd)
}); });
builder.RegisterModule(new TelemetryModule builder.RegisterModule(new TelemetryModule
{ {
TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject<TelemetryConfig>() TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject<TelemetryConfig>()
}); });
builder.RegisterAssemblyTypes(typeof(IDbConfigure<>).Assembly) builder.RegisterModule(new SeqLoggingModule
.AsClosedTypesOf(typeof(IDbConfigure<>)) {
.AsSelf(); 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": { "ConnectionStrings": {
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id={usr};Password={pwd};" "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id={usr};Password={pwd};"
}, },
"ApplicationInsights": { "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 config = new SeqConfiguration("http://localhost:5341", null, "MSTEST");
var httpClient = new SeqHttpClient(config); 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); _service = new SeqBackgroundService(telemetryClient, _messageChannel, logger);
_cts = new CancellationTokenSource(); _cts = new CancellationTokenSource();

View file

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

View file

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