From 9f4996bc8f62e38ff2735676c790abec4e30547f Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Thu, 20 Feb 2025 00:23:13 +0100 Subject: [PATCH] Enhancing telemetry in Seq and fixes namespaces --- Application/Application.csproj | 21 - .../Common/ComponentsViewLocationExpander.cs | 2 +- .../Navigation/NavigationViewComponent.cs | 4 +- Application/Pages/Index.cshtml | 2 +- Application/Pages/Index.cshtml.cs | 4 +- Application/PlanTempus.Application.csproj | 21 + Application/Program.cs | 2 +- Application/Startup.cs | 11 +- Application/appconfiguration.json | 8 +- Core/Configurations/Common/KeyValueToJson.cs | 2 +- Core/Configurations/ConfigurationBuilder.cs | 6 +- Core/Configurations/IAppConfiguration.cs | 2 +- Core/Configurations/IConfigurationRoot.cs | 2 +- .../JsonConfigProvider/JsonConfigExtension.cs | 5 +- .../SmartConfigProvider/AppConfiguration.cs | 2 +- .../IConfigurationRepository.cs | 2 +- .../PostgresConfigurationRepository.cs | 2 +- .../SmartConfigExtension.cs | 4 +- .../SmartConfigProvider/SmartConfigOptions.cs | 2 +- .../SmartConfigProvider.cs | 6 +- Core/Entities/Users/Class1.cs | 2 +- Core/Entities/Users/PasswordHasher.cs | 2 +- Core/Exceptions/ConfigurationException.cs | 14 +- Core/Logging/SeqBackgroundService.cs | 18 +- Core/Logging/SeqConfiguration.cs | 2 +- Core/Logging/SeqHttpClient.cs | 3 +- Core/Logging/SeqLogger.cs | 417 +++++++++--------- Core/ModuleRegistry/SeqLoggingModule.cs | 6 +- Core/ModuleRegistry/TelemetryModule.cs | 89 ++-- Core/MultiKeyEncryption/MasterKey.cs | 2 +- .../SecureConnectionString.cs | 2 +- Core/{Core.csproj => PlanTempus.Core.csproj} | 3 +- .../Enrichers/EnrichWithMetaTelemetry.cs | 22 + Core/Telemetry/IMessageChannel.cs | 2 +- Core/Telemetry/MessageChannel.cs | 30 +- Core/Telemetry/SeqLoggingTelemetryChannel.cs | 6 +- Database/Common/Validations.cs | 2 +- .../SetupConfiguration.cs | 133 +++--- Database/Core/DCL/SetupApplicationUser.cs | 163 +++---- Database/Core/DCL/SetupDbAdmin.cs | 7 +- Database/Core/DCL/SetupOrganizationUser.cs | 143 +++--- Database/Core/DDL/SetupIdentitySystem.cs | 3 +- Database/Core/IDbConfigure.cs | 10 +- Database/Core/UserService.cs | 6 +- Database/ModuleRegistry/DbPostgreSqlModule.cs | 30 +- Database/NavigationSystem/Setup.cs | 48 +- ...base.csproj => PlanTempus.Database.csproj} | 2 +- Database/RolesPermissionSystem/Setup.cs | 125 +++--- Database/Tenants/InitializeTenantData.cs | 2 +- PlanTempus.sln | 10 +- ... => PlanTempus.SetupInfrastructure.csproj} | 2 +- SetupInfrastructure/Program.cs | 247 ++++++----- SetupInfrastructure/Startup.cs | 65 +-- .../JsonConfigurationProviderTests.cs | 199 ++++----- .../KeyValueJsonHandlingTests.cs | 7 +- .../SmartConfigProviderTests.cs | 11 +- .../appconfiguration.dev.json | 3 +- Tests/Logging/SeqBackgroundServiceTest.cs | 26 +- Tests/Logging/SeqLoggerTests.cs | 236 +++++----- Tests/PasswordHasherTest.cs | 10 +- .../{Tests.csproj => PlanTempus.Tests.csproj} | 4 +- Tests/PostgresTests.cs | 11 +- Tests/SecureConnectionStringTests.cs | 11 +- Tests/TestFixture.cs | 12 +- Tests/appconfiguration.dev.json | 3 +- 65 files changed, 1122 insertions(+), 1139 deletions(-) delete mode 100644 Application/Application.csproj create mode 100644 Application/PlanTempus.Application.csproj rename Core/{Core.csproj => PlanTempus.Core.csproj} (96%) create mode 100644 Core/Telemetry/Enrichers/EnrichWithMetaTelemetry.cs rename Database/{Database.csproj => PlanTempus.Database.csproj} (80%) rename SetupInfrastructure/{SetupInfrastructure.csproj => PlanTempus.SetupInfrastructure.csproj} (83%) rename Tests/{Tests.csproj => PlanTempus.Tests.csproj} (88%) diff --git a/Application/Application.csproj b/Application/Application.csproj deleted file mode 100644 index bfbcf6c..0000000 --- a/Application/Application.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net8.0 - enable - - - - - - - - - - - - - - - - diff --git a/Application/Common/ComponentsViewLocationExpander.cs b/Application/Common/ComponentsViewLocationExpander.cs index 710be8f..d181ae5 100644 --- a/Application/Common/ComponentsViewLocationExpander.cs +++ b/Application/Common/ComponentsViewLocationExpander.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Mvc.Razor; -namespace Application.Common +namespace PlanTempus.Application.Common { public class ComponentsViewLocationExpander : IViewLocationExpander { diff --git a/Application/Components/Navigation/NavigationViewComponent.cs b/Application/Components/Navigation/NavigationViewComponent.cs index f524bed..8ae9973 100644 --- a/Application/Components/Navigation/NavigationViewComponent.cs +++ b/Application/Components/Navigation/NavigationViewComponent.cs @@ -1,14 +1,14 @@ using Microsoft.ApplicationInsights; using Microsoft.AspNetCore.Mvc; -namespace Application.Components.Navigation +namespace PlanTempus.Application.Components.Navigation { public class NavigationViewComponent : ViewComponent { public NavigationViewComponent(TelemetryClient telemetryClient) { - + } public IViewComponentResult Invoke() { diff --git a/Application/Pages/Index.cshtml b/Application/Pages/Index.cshtml index c0fdf0f..ae061fa 100644 --- a/Application/Pages/Index.cshtml +++ b/Application/Pages/Index.cshtml @@ -1,5 +1,5 @@ @page -@model IndexModel +@model PlanTempus.Application.Pages.IndexModel @{ ViewData["Title"] = "Home page"; } diff --git a/Application/Pages/Index.cshtml.cs b/Application/Pages/Index.cshtml.cs index e87cd2d..806a114 100644 --- a/Application/Pages/Index.cshtml.cs +++ b/Application/Pages/Index.cshtml.cs @@ -3,7 +3,7 @@ using Microsoft.ApplicationInsights; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -namespace PlanTempus.Pages +namespace PlanTempus.Application.Pages { public class IndexModel : PageModel { @@ -13,7 +13,7 @@ namespace PlanTempus.Pages { _telemetry = telemetry; - + } diff --git a/Application/PlanTempus.Application.csproj b/Application/PlanTempus.Application.csproj new file mode 100644 index 0000000..17391d4 --- /dev/null +++ b/Application/PlanTempus.Application.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + + + + + + + + + + + + + + + + diff --git a/Application/Program.cs b/Application/Program.cs index 480670b..21d2de7 100644 --- a/Application/Program.cs +++ b/Application/Program.cs @@ -1,5 +1,5 @@ -using Application; using Autofac.Extensions.DependencyInjection; +using PlanTempus.Application; var host = Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) diff --git a/Application/Startup.cs b/Application/Startup.cs index 88fbd14..a501a94 100644 --- a/Application/Startup.cs +++ b/Application/Startup.cs @@ -1,8 +1,9 @@ using Autofac; -using Core.Configurations.JsonConfigProvider; -using Core.Configurations; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.Configurations; +using PlanTempus.Core.ModuleRegistry; -namespace Application +namespace PlanTempus.Application { public class Startup { @@ -39,9 +40,9 @@ namespace Application ConnectionString = ConfigurationRoot.GetConnectionString("ptdb") }); - builder.RegisterModule(new Core.ModuleRegistry.TelemetryModule + builder.RegisterModule(new TelemetryModule { - TelemetryConfig = ConfigurationRoot.GetSection(nameof(Core.ModuleRegistry.TelemetryConfig)).ToObject() + TelemetryConfig = ConfigurationRoot.GetSection(nameof(TelemetryConfig)).ToObject() }); diff --git a/Application/appconfiguration.json b/Application/appconfiguration.json index 3636840..87bf926 100644 --- a/Application/appconfiguration.json +++ b/Application/appconfiguration.json @@ -4,11 +4,7 @@ "ptdb": "Host=localhost;Port=5433;Database=ptdb01;User Id=sathumper;Password=3911;" }, "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" - }, - "Feature": { - "Enabled": true, - "RolloutPercentage": 25, - "AllowedUserGroups": [ "beta" ] + "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", + "UseSeqLoggingTelemetryChannel": true } } \ No newline at end of file diff --git a/Core/Configurations/Common/KeyValueToJson.cs b/Core/Configurations/Common/KeyValueToJson.cs index 073daa7..2f531c7 100644 --- a/Core/Configurations/Common/KeyValueToJson.cs +++ b/Core/Configurations/Common/KeyValueToJson.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Core.Configurations.Common +namespace PlanTempus.Core.Configurations.Common { using Newtonsoft.Json.Linq; diff --git a/Core/Configurations/ConfigurationBuilder.cs b/Core/Configurations/ConfigurationBuilder.cs index 95ab656..83bb998 100644 --- a/Core/Configurations/ConfigurationBuilder.cs +++ b/Core/Configurations/ConfigurationBuilder.cs @@ -1,5 +1,5 @@ using Newtonsoft.Json.Linq; -namespace Core.Configurations +namespace PlanTempus.Core.Configurations { public interface IConfigurationBuilder { @@ -133,7 +133,7 @@ namespace Core.Configurations public interface IConfigurationProvider { void Build(); - Newtonsoft.Json.Linq.JObject Configuration(); + JObject Configuration(); } public class ConfigurationSection : IConfigurationSection @@ -148,6 +148,6 @@ namespace Core.Configurations { string Path { get; } string Key { get; } - Newtonsoft.Json.Linq.JToken Value { get; set; } + JToken Value { get; set; } } } diff --git a/Core/Configurations/IAppConfiguration.cs b/Core/Configurations/IAppConfiguration.cs index ab5826b..1ca246e 100644 --- a/Core/Configurations/IAppConfiguration.cs +++ b/Core/Configurations/IAppConfiguration.cs @@ -1,4 +1,4 @@ -namespace Core.Configurations +namespace PlanTempus.Core.Configurations { /// /// Marker interface for application configurations that should be automatically registered in the DI container. diff --git a/Core/Configurations/IConfigurationRoot.cs b/Core/Configurations/IConfigurationRoot.cs index 0dc36ee..1660f75 100644 --- a/Core/Configurations/IConfigurationRoot.cs +++ b/Core/Configurations/IConfigurationRoot.cs @@ -1,4 +1,4 @@ -namespace Core.Configurations +namespace PlanTempus.Core.Configurations { public interface IConfigurationRoot : IConfiguration { } diff --git a/Core/Configurations/JsonConfigProvider/JsonConfigExtension.cs b/Core/Configurations/JsonConfigProvider/JsonConfigExtension.cs index 0a305d6..4c02292 100644 --- a/Core/Configurations/JsonConfigProvider/JsonConfigExtension.cs +++ b/Core/Configurations/JsonConfigProvider/JsonConfigExtension.cs @@ -1,8 +1,9 @@ -using Core.Exceptions; +using PlanTempus.Core.Exceptions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using PlanTempus.Core.Configurations; -namespace Core.Configurations.JsonConfigProvider +namespace PlanTempus.Core.Configurations.JsonConfigProvider { public static class JsonConfigExtension { diff --git a/Core/Configurations/SmartConfigProvider/AppConfiguration.cs b/Core/Configurations/SmartConfigProvider/AppConfiguration.cs index 1ce705a..df2ba1d 100644 --- a/Core/Configurations/SmartConfigProvider/AppConfiguration.cs +++ b/Core/Configurations/SmartConfigProvider/AppConfiguration.cs @@ -1,4 +1,4 @@ -namespace Core.Configurations.SmartConfigProvider; +namespace PlanTempus.Core.Configurations.SmartConfigProvider; public class AppConfiguration { public long Id { get; set; } diff --git a/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs b/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs index ba040a0..9b3d6d7 100644 --- a/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs +++ b/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs @@ -1,4 +1,4 @@ -namespace Core.Configurations.SmartConfigProvider; +namespace PlanTempus.Core.Configurations.SmartConfigProvider; public interface IConfigurationRepository { string ConnectionString { get; set; } diff --git a/Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs b/Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs index 1535978..d78ef4d 100644 --- a/Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs +++ b/Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs @@ -1,7 +1,7 @@ using System.Data; using Insight.Database; -namespace Core.Configurations.SmartConfigProvider.Repositories; +namespace PlanTempus.Core.Configurations.SmartConfigProvider.Repositories; public class PostgresConfigurationRepository : IConfigurationRepository { private IDbConnection _connection; diff --git a/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs b/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs index 5efb867..1078ae7 100644 --- a/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs +++ b/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs @@ -1,4 +1,6 @@ -namespace Core.Configurations.SmartConfigProvider +using PlanTempus.Core.Configurations; + +namespace PlanTempus.Core.Configurations.SmartConfigProvider { /// /// Extension methods for adding smart configuration providers to IConfigurationBuilder. diff --git a/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs b/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs index a457123..1064ae3 100644 --- a/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs +++ b/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs @@ -1,4 +1,4 @@ -namespace Core.Configurations.SmartConfigProvider +namespace PlanTempus.Core.Configurations.SmartConfigProvider { /// /// Configuration options for setting up smart configuration providers. diff --git a/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs b/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs index 0e74746..7cfe0b9 100644 --- a/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs +++ b/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs @@ -1,9 +1,9 @@ -using Core.Configurations.JsonConfigProvider; -using Core.Exceptions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.Exceptions; -namespace Core.Configurations.SmartConfigProvider +namespace PlanTempus.Core.Configurations.SmartConfigProvider { /// /// Configuration provider that loads configuration from a smart configuration source (e.g. database). diff --git a/Core/Entities/Users/Class1.cs b/Core/Entities/Users/Class1.cs index 3f13ae8..805c028 100644 --- a/Core/Entities/Users/Class1.cs +++ b/Core/Entities/Users/Class1.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Core.Entities.Users +namespace PlanTempus.Core.Entities.Users { public class User { diff --git a/Core/Entities/Users/PasswordHasher.cs b/Core/Entities/Users/PasswordHasher.cs index b6ff815..6d1e8aa 100644 --- a/Core/Entities/Users/PasswordHasher.cs +++ b/Core/Entities/Users/PasswordHasher.cs @@ -1,4 +1,4 @@ -namespace Core.Entities.Users +namespace PlanTempus.Core.Entities.Users { public static class PasswordHasher { diff --git a/Core/Exceptions/ConfigurationException.cs b/Core/Exceptions/ConfigurationException.cs index fa2061d..4021bef 100644 --- a/Core/Exceptions/ConfigurationException.cs +++ b/Core/Exceptions/ConfigurationException.cs @@ -1,9 +1,9 @@ -namespace Core.Exceptions +namespace PlanTempus.Core.Exceptions { - internal class ConfigurationException : Exception - { - public ConfigurationException(string message) : base(message) - { - } - } + internal class ConfigurationException : Exception + { + public ConfigurationException(string message) : base(message) + { + } + } } diff --git a/Core/Logging/SeqBackgroundService.cs b/Core/Logging/SeqBackgroundService.cs index 6d21380..008dc10 100644 --- a/Core/Logging/SeqBackgroundService.cs +++ b/Core/Logging/SeqBackgroundService.cs @@ -1,20 +1,20 @@ -using Core.Telemetry; -using Microsoft.ApplicationInsights; +using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.DataContracts; using Microsoft.Extensions.Hosting; +using PlanTempus.Core.Telemetry; -namespace Core.Logging +namespace PlanTempus.Core.Logging { public class SeqBackgroundService : BackgroundService { private readonly IMessageChannel _messageChannel; private readonly TelemetryClient _telemetryClient; - private readonly SeqLogger _seqLogger; + private readonly SeqLogger _seqLogger; public SeqBackgroundService(TelemetryClient telemetryClient, IMessageChannel messageChannel, - SeqLogger seqlogger) + SeqLogger seqlogger) { _telemetryClient = telemetryClient; _messageChannel = messageChannel; @@ -49,12 +49,12 @@ namespace Core.Logging await _seqLogger.LogAsync(et); break; - case EventTelemetry et: - await _seqLogger.LogAsync(et); - break; + case EventTelemetry et: + await _seqLogger.LogAsync(et); + break; - default: + default: throw new NotSupportedException(telemetry.GetType().Name); } } diff --git a/Core/Logging/SeqConfiguration.cs b/Core/Logging/SeqConfiguration.cs index 7c6afee..884eb56 100644 --- a/Core/Logging/SeqConfiguration.cs +++ b/Core/Logging/SeqConfiguration.cs @@ -1,7 +1,7 @@ using Microsoft.ApplicationInsights.DataContracts; using System.Text; -namespace Core.Logging +namespace PlanTempus.Core.Logging { public record SeqConfiguration(string IngestionEndpoint, string ApiKey, string Environment); } \ No newline at end of file diff --git a/Core/Logging/SeqHttpClient.cs b/Core/Logging/SeqHttpClient.cs index 8eb282c..30c5384 100644 --- a/Core/Logging/SeqHttpClient.cs +++ b/Core/Logging/SeqHttpClient.cs @@ -1,5 +1,4 @@ - -namespace Core.Logging +namespace PlanTempus.Core.Logging { public class SeqHttpClient { diff --git a/Core/Logging/SeqLogger.cs b/Core/Logging/SeqLogger.cs index ec5578a..1677bea 100644 --- a/Core/Logging/SeqLogger.cs +++ b/Core/Logging/SeqLogger.cs @@ -1,248 +1,239 @@ using Microsoft.ApplicationInsights.DataContracts; using System.Text; -namespace Core.Logging +namespace PlanTempus.Core.Logging { - public class SeqLogger - { - private readonly SeqHttpClient _httpClient; - private readonly string _environmentName; - private readonly string _machineName; - private readonly SeqConfiguration _configuration; + public class SeqLogger + { + 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; - _environmentName = configuration.Environment; - _machineName = Environment.MachineName; - } + public SeqLogger(SeqHttpClient httpClient, string environmentName, SeqConfiguration configuration) + { + _httpClient = httpClient; + } - public async Task LogAsync(TraceTelemetry trace, CancellationToken cancellationToken = default) - { - var seqEvent = new Dictionary - { - { "@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 + { + { "@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.Key, prop.Value); - } + foreach (var prop in trace.Properties) + seqEvent.Add($"prop_{prop.Key}", prop.Value); - await SendToSeqAsync(seqEvent, cancellationToken); - } + foreach (var prop in trace.Context.GlobalProperties) + seqEvent.Add($"global_{prop.Key}", prop.Value); - public async Task LogAsync(EventTelemetry evt, CancellationToken cancellationToken = default) - { - var seqEvent = new Dictionary - { - { "@t", evt.Timestamp.UtcDateTime.ToString("o") }, - { "@mt", evt.Name }, - { "@l", "Information" }, - { "Environment", _environmentName }, - { "MachineName", _machineName } - }; + await SendToSeqAsync(seqEvent, cancellationToken); + } - foreach (var prop in evt.Properties) - { - seqEvent.Add(prop.Key, prop.Value); - } + public async Task LogAsync(EventTelemetry evt, CancellationToken cancellationToken = default) + { + var seqEvent = new Dictionary + { + { "@t", evt.Timestamp.UtcDateTime.ToString("o") }, + { "@mt", evt.Name }, + { "@l", "Information" }, + { "Environment", _environmentName }, + { "MachineName", _machineName } + }; - foreach (var metric in evt.Metrics) - { - seqEvent.Add($"metric_{metric.Key}", metric.Value); - } + foreach (var prop in evt.Properties) + seqEvent.Add($"prop_{prop.Key}", prop.Value); - await SendToSeqAsync(seqEvent, cancellationToken); - } + foreach (var prop in evt.Context.GlobalProperties) + seqEvent.Add($"global_{prop.Key}", prop.Value); - public async Task LogAsync(ExceptionTelemetry ex, CancellationToken cancellationToken = default) - { - var seqEvent = new Dictionary - { - { "@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 metric in evt.Metrics) + seqEvent.Add($"metric_{metric.Key}", metric.Value); - foreach (var prop in ex.Properties) - { - seqEvent.Add(prop.Key, prop.Value); - } + await SendToSeqAsync(seqEvent, cancellationToken); + } - await SendToSeqAsync(seqEvent, cancellationToken); - } + public async Task LogAsync(ExceptionTelemetry ex, CancellationToken cancellationToken = default) + { + var seqEvent = new Dictionary + { + { "@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(DependencyTelemetry dep, CancellationToken cancellationToken = default) - { - var seqEvent = new Dictionary - { - { "@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 ex.Properties) + seqEvent.Add($"prop_{prop.Key}", prop.Value); - foreach (var prop in dep.Properties) - { - seqEvent.Add(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(RequestTelemetry req, CancellationToken cancellationToken = default) - { - var seqEvent = new Dictionary - { - { "@t", req.Timestamp.UtcDateTime.ToString("o") }, - { "@mt",$"{req.Properties["httpMethod"]} {req.Name}" }, - { "@l", req.Success??true ? "Information" : "Error" }, - { "Environment", _environmentName }, - { "MachineName", _machineName }, - { "Url", req.Url }, - { "ResponseCode", req.ResponseCode }, - { "Application", "sadasd" }, - { "RequestMethod", req.Properties["httpMethod"] }, - { "RequestId", req.Id }, - { "ItemTypeFlag", req.ItemTypeFlag.ToString() }, - { "@sp", "12"}, - { "@tr", "23344"}, - { "@sk","Server" }, - { "@st", req.Timestamp.UtcDateTime.Subtract(req.Duration).ToString("o") } - }; - req.Properties.Remove("httpMethod"); + public async Task LogAsync(DependencyTelemetry dep, CancellationToken cancellationToken = default) + { + var seqEvent = new Dictionary + { + { "@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 } + }; - //we should add a property with name { "Application", "<...>" } other the Seq Span is not looking ok - foreach (var prop in req.Properties) - { - seqEvent.Add(prop.Key, prop.Value); - } + foreach (var prop in dep.Properties) + seqEvent.Add($"prop_{prop.Key}", prop.Value); - await SendToSeqAsync(seqEvent, cancellationToken); - } - public async Task LogAsync(Microsoft.ApplicationInsights.Extensibility.IOperationHolder operationHolder, CancellationToken cancellationToken = default) - { - var req = operationHolder.Telemetry; - - var seqEvent = new Dictionary - { + foreach (var prop in dep.Context.GlobalProperties) + seqEvent.Add($"global_{prop.Key}", prop.Value); - { "@t", req.Timestamp.UtcDateTime.ToString("o") }, - { "@mt",$"{req.Properties["httpMethod"]} {req.Name}" }, - { "@l", req.Success??true ? "Information" : "Error" }, - { "Environment", _environmentName }, - { "MachineName", _machineName }, - { "Url", req.Url }, - { "ResponseCode", req.ResponseCode }, - { "Application", "sadasd" }, - { "RequestMethod", req.Properties["httpMethod"] }, - { "RequestId", req.Id }, - { "ItemTypeFlag", req.ItemTypeFlag.ToString() }, - { "@sp", "12"}, - { "@tr", "23344"}, - { "@sk","Server" }, - { "@st", req.Timestamp.UtcDateTime.Subtract(req.Duration).ToString("o") } - }; - req.Properties.Remove("httpMethod"); + await SendToSeqAsync(seqEvent, cancellationToken); + } - //we should add a property with name { "Application", "<...>" } other the Seq Span is not looking ok - foreach (var prop in req.Properties) - { - seqEvent.Add(prop.Key, prop.Value); - } + public async Task LogAsync(RequestTelemetry req, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + public async Task LogAsync(Microsoft.ApplicationInsights.Extensibility.IOperationHolder operationHolder, CancellationToken cancellationToken = default) + { + var req = operationHolder.Telemetry; - await SendToSeqAsync(seqEvent, cancellationToken); - } - private async Task SendToSeqAsync(Dictionary seqEvent, CancellationToken cancellationToken) - { - var content = new StringContent( - Newtonsoft.Json.JsonConvert.SerializeObject(seqEvent), - Encoding.UTF8, - "application/vnd.serilog.clef"); + //https://docs.datalust.co/v2025.1/docs/posting-raw-events + var seqEvent = new Dictionary + { - var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/ingest/clef") - { - Content = content - }; + { "@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() } + }; - var result = await _httpClient.SendAsync(requestMessage, cancellationToken); - result.EnsureSuccessStatusCode(); - } + 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; - 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; + if (req.Properties.TryGetValue("httpMethod", out string method)) + { + seqEvent["RequestMethod"] = method; + seqEvent["@mt"] = $"{req.Properties["httpMethod"]} {req.Name}"; + req.Properties.Remove("httpMethod"); + } - void FormatSingleException(Exception currentEx, int depth) - { - if (depth > 0) sb.AppendLine("\n--- Inner Exception ---"); + foreach (var prop in req.Properties) + seqEvent.Add($"prop_{prop.Key}", prop.Value); - 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()); + foreach (var prop in req.Context.GlobalProperties) + seqEvent.Add($"global_{prop.Key}", prop.Value); - if (currentEx.Data.Count > 0) - { - sb.AppendLine("Additional Data:"); - foreach (var key in currentEx.Data.Keys) - { - sb.AppendLine($" {key}: {currentEx.Data[key]}"); - } - } - } + await SendToSeqAsync(seqEvent, cancellationToken); + } + private async Task SendToSeqAsync(Dictionary seqEvent, CancellationToken cancellationToken) + { + var content = new StringContent( + Newtonsoft.Json.JsonConvert.SerializeObject(seqEvent), + Encoding.UTF8, + "application/vnd.serilog.clef"); - 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); - } + var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/ingest/clef") + { + Content = content + }; - FormatSingleException(currentEx, depth); - exceptionCount++; - } + var result = await _httpClient.SendAsync(requestMessage, cancellationToken); - RecurseExceptions(ex); - sb.Insert(0, $"EXCEPTION CHAIN ({exceptionCount} exceptions):\n"); - return sb.ToString(); - } - } + 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; + + 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()); + + 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); + } + + FormatSingleException(currentEx, depth); + exceptionCount++; + } + + RecurseExceptions(ex); + sb.Insert(0, $"EXCEPTION CHAIN ({exceptionCount} exceptions):\n"); + return sb.ToString(); + } + } } diff --git a/Core/ModuleRegistry/SeqLoggingModule.cs b/Core/ModuleRegistry/SeqLoggingModule.cs index 679467d..94b469a 100644 --- a/Core/ModuleRegistry/SeqLoggingModule.cs +++ b/Core/ModuleRegistry/SeqLoggingModule.cs @@ -1,8 +1,8 @@ using Autofac; -using Core.Logging; -using Core.Telemetry; +using PlanTempus.Core.Logging; +using PlanTempus.Core.Telemetry; -namespace Core.ModuleRegistry +namespace PlanTempus.Core.ModuleRegistry { public class SeqLoggingModule : Module { diff --git a/Core/ModuleRegistry/TelemetryModule.cs b/Core/ModuleRegistry/TelemetryModule.cs index f2d15f8..a4d80f6 100644 --- a/Core/ModuleRegistry/TelemetryModule.cs +++ b/Core/ModuleRegistry/TelemetryModule.cs @@ -1,71 +1,48 @@ using Autofac; -using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.Extensibility; -using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel; -namespace Core.ModuleRegistry +namespace PlanTempus.Core.ModuleRegistry { - public class TelemetryModule : Module - { - public TelemetryConfig TelemetryConfig { get; set; } - protected override void Load(ContainerBuilder builder) - { - if (TelemetryConfig == null) - throw new Exceptions.ConfigurationException("TelemetryConfig is missing"); + public class TelemetryModule : Module + { + public TelemetryConfig TelemetryConfig { get; set; } - //builder.Register(c => - //{ - // var channel = new Telemetry.DualTelemetryChannel("C:\\logs\\telemetry.log"); - // channel.DeveloperMode = true; - // var config = new TelemetryConfiguration - // { - - // ConnectionString = TelemetryConfig.ConnectionString, - // TelemetryChannel = channel - // }; - // return new TelemetryClient(config); - //}).InstancePerLifetimeScope(); - - var telemetryChannel = new InMemoryChannel - { - DeveloperMode = true - }; - - //var configuration = new TelemetryConfiguration - //{ - // ConnectionString = TelemetryConfig.ConnectionString, - // TelemetryChannel = telemetryChannel - //}; - - //telemetryChannel.Initialize(configuration); + protected override void Load(ContainerBuilder builder) + { + if (TelemetryConfig == null) + throw new Exceptions.ConfigurationException("TelemetryConfig is missing"); - var tmc = Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.CreateDefault(); - tmc.ConnectionString = TelemetryConfig.ConnectionString; - tmc.TelemetryChannel.DeveloperMode = true; - var channel = new Telemetry.SeqLoggingTelemetryChannel("C:\\logs\\telemetry.log"); + var configuration = TelemetryConfiguration.CreateDefault(); + configuration.ConnectionString = TelemetryConfig.ConnectionString; + configuration.TelemetryChannel.DeveloperMode = true; - tmc.TelemetryChannel = channel; + if (TelemetryConfig.UseSeqLoggingTelemetryChannel) + configuration.TelemetryChannel = new Telemetry.SeqLoggingTelemetryChannel(); ; - ////var r = new Microsoft.ApplicationInsights.Extensibility.Implementation.TelemetryProcessorChainBuilder(tmc); - ////r.Use(next => new Domain.EventTelemetryEnrichers.EnrichWithMetaTelemetry(next)); - ////r.Build(); + var r = new Microsoft.ApplicationInsights.Extensibility.Implementation.TelemetryProcessorChainBuilder(configuration); + r.Use(next => new Telemetry.Enrichers.EnrichWithMetaTelemetry(next)); + r.Build(); - //builder.RegisterInstance(configuration); - builder.Register(c => new TelemetryClient(tmc)).InstancePerLifetimeScope(); + //builder.RegisterInstance(configuration); - //builder.RegisterType() - // .InstancePerLifetimeScope(); + //builder.RegisterType() + // .InstancePerLifetimeScope(); - //builder.RegisterType() - // .As() - // .InstancePerLifetimeScope(); - } - } + var client = new Microsoft.ApplicationInsights.TelemetryClient(configuration); + client.Context.GlobalProperties["Application"] = GetType().Namespace.Split('.')[0]; + client.Context.GlobalProperties["MachineName"] = Environment.MachineName; + client.Context.GlobalProperties["Version"] = Environment.Version.ToString(); + client.Context.GlobalProperties["ProcessorCount"] = Environment.ProcessorCount.ToString(); - public class TelemetryConfig - { - public string ConnectionString { get; set; } - } + builder.Register(c => client).InstancePerLifetimeScope(); + } + } + + public class TelemetryConfig + { + public string ConnectionString { get; set; } + public bool UseSeqLoggingTelemetryChannel { get; set; } + } } diff --git a/Core/MultiKeyEncryption/MasterKey.cs b/Core/MultiKeyEncryption/MasterKey.cs index d21f3a9..3b16729 100644 --- a/Core/MultiKeyEncryption/MasterKey.cs +++ b/Core/MultiKeyEncryption/MasterKey.cs @@ -1,4 +1,4 @@ -namespace Core.MultiKeyEncryption +namespace PlanTempus.Core.MultiKeyEncryption { internal class MasterKey { diff --git a/Core/MultiKeyEncryption/SecureConnectionString.cs b/Core/MultiKeyEncryption/SecureConnectionString.cs index df4e85e..ef37f90 100644 --- a/Core/MultiKeyEncryption/SecureConnectionString.cs +++ b/Core/MultiKeyEncryption/SecureConnectionString.cs @@ -5,7 +5,7 @@ using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; -namespace Core.MultiKeyEncryption +namespace PlanTempus.Core.MultiKeyEncryption { public class SecureConnectionString { diff --git a/Core/Core.csproj b/Core/PlanTempus.Core.csproj similarity index 96% rename from Core/Core.csproj rename to Core/PlanTempus.Core.csproj index 2cb5851..96a7344 100644 --- a/Core/Core.csproj +++ b/Core/PlanTempus.Core.csproj @@ -1,4 +1,5 @@ - + + net8.0 diff --git a/Core/Telemetry/Enrichers/EnrichWithMetaTelemetry.cs b/Core/Telemetry/Enrichers/EnrichWithMetaTelemetry.cs new file mode 100644 index 0000000..ace831a --- /dev/null +++ b/Core/Telemetry/Enrichers/EnrichWithMetaTelemetry.cs @@ -0,0 +1,22 @@ +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.Extensibility; + +namespace PlanTempus.Core.Telemetry.Enrichers +{ + + public class EnrichWithMetaTelemetry : ITelemetryProcessor + { + private readonly ITelemetryProcessor _next; + + public EnrichWithMetaTelemetry(ITelemetryProcessor next) + { + _next = next; + } + + public void Process(ITelemetry item) + { + //nothing going on here yet :) + _next.Process(item); + } + } +} diff --git a/Core/Telemetry/IMessageChannel.cs b/Core/Telemetry/IMessageChannel.cs index e794f98..6876d61 100644 --- a/Core/Telemetry/IMessageChannel.cs +++ b/Core/Telemetry/IMessageChannel.cs @@ -1,5 +1,5 @@ using System.Threading.Channels; -namespace Core.Telemetry +namespace PlanTempus.Core.Telemetry { public interface IMessageChannel : IDisposable { diff --git a/Core/Telemetry/MessageChannel.cs b/Core/Telemetry/MessageChannel.cs index ae84408..ef94d14 100644 --- a/Core/Telemetry/MessageChannel.cs +++ b/Core/Telemetry/MessageChannel.cs @@ -1,23 +1,23 @@ using Microsoft.ApplicationInsights.Channel; using System.Threading.Channels; -namespace Core.Telemetry +namespace PlanTempus.Core.Telemetry { - public class MessageChannel : IMessageChannel - { - private readonly Channel _channel; + public class MessageChannel : IMessageChannel + { + private readonly Channel _channel; - public MessageChannel() - { - _channel = Channel.CreateUnbounded(); - } + public MessageChannel() + { + _channel = Channel.CreateUnbounded(); + } - public ChannelWriter Writer => _channel.Writer; - public ChannelReader Reader => _channel.Reader; + public ChannelWriter Writer => _channel.Writer; + public ChannelReader Reader => _channel.Reader; - public void Dispose() - { - _channel.Writer.Complete(); - } - } + public void Dispose() + { + _channel.Writer.Complete(); + } + } } diff --git a/Core/Telemetry/SeqLoggingTelemetryChannel.cs b/Core/Telemetry/SeqLoggingTelemetryChannel.cs index cd8575d..9f7517a 100644 --- a/Core/Telemetry/SeqLoggingTelemetryChannel.cs +++ b/Core/Telemetry/SeqLoggingTelemetryChannel.cs @@ -1,11 +1,10 @@ using Microsoft.ApplicationInsights.Channel; using System.Net.Http.Headers; -namespace Core.Telemetry +namespace PlanTempus.Core.Telemetry { public class SeqLoggingTelemetryChannel : InMemoryChannel, ITelemetryChannel { - private readonly string _filePath; public ITelemetryChannel _defaultChannel; static HttpClient _client = new HttpClient(); @@ -22,9 +21,8 @@ namespace Core.Telemetry } - public SeqLoggingTelemetryChannel(string filePath) + public SeqLoggingTelemetryChannel() { - _filePath = filePath; } public new void Send(ITelemetry telemetry) { diff --git a/Database/Common/Validations.cs b/Database/Common/Validations.cs index 5145b04..55e298d 100644 --- a/Database/Common/Validations.cs +++ b/Database/Common/Validations.cs @@ -1,6 +1,6 @@ using System.Text.RegularExpressions; -namespace Database.Common +namespace PlanTempus.Database.Common { internal class Validations { diff --git a/Database/ConfigurationManagementSystem/SetupConfiguration.cs b/Database/ConfigurationManagementSystem/SetupConfiguration.cs index 27b5974..d8b82c7 100644 --- a/Database/ConfigurationManagementSystem/SetupConfiguration.cs +++ b/Database/ConfigurationManagementSystem/SetupConfiguration.cs @@ -1,53 +1,54 @@ using Insight.Database; +using PlanTempus.Database.Core; using System.Data; -namespace Database.ConfigurationManagementSystem; +namespace PlanTempus.Database.ConfigurationManagementSystem; -public class SetupConfiguration : Core.IDbConfigure +public class SetupConfiguration : IDbConfigure { - public class Command - { - - } + public class Command + { - private readonly IDbConnection _db; + } - public SetupConfiguration(IDbConnection connection) - { - _db = connection; - } - public void With(Command notInUse) - { - using (var transaction = _db.OpenWithTransaction()) - { - try - { - CreateConfigurationTable(); - CreateHistoryTable(); - CreateConfigurationIndexes(); - CreateModifiedAtTrigger(); - CreateNotifyTrigger(); - CreateHistoryTrigger(); + private readonly IDbConnection _db; - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - throw new InvalidOperationException("Failed to SetupConfiguration in Database", ex); - } - } + public SetupConfiguration(IDbConnection connection) + { + _db = connection; + } + public void With(Command notInUse) + { + using (var transaction = _db.OpenWithTransaction()) + { + try + { + CreateConfigurationTable(); + CreateHistoryTable(); + CreateConfigurationIndexes(); + CreateModifiedAtTrigger(); + CreateNotifyTrigger(); + CreateHistoryTrigger(); - } + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw new InvalidOperationException("Failed to SetupConfiguration in Database", ex); + } + } - private void ExecuteSql(string sql) - { - _db.ExecuteSql(sql); - } + } - void CreateConfigurationTable() - { - const string sql = @" + private void ExecuteSql(string sql) + { + _db.ExecuteSql(sql); + } + + void CreateConfigurationTable() + { + const string sql = @" CREATE TABLE IF NOT EXISTS app_configuration ( id bigserial NOT NULL, ""key"" varchar(255) NOT NULL, @@ -61,12 +62,12 @@ public class SetupConfiguration : Core.IDbConfigure etag uuid DEFAULT gen_random_uuid() NULL, CONSTRAINT app_configuration_pkey PRIMARY KEY (id) );"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - void CreateHistoryTable() - { - const string sql = @" + void CreateHistoryTable() + { + const string sql = @" CREATE TABLE IF NOT EXISTS app_configuration_history ( history_id bigserial NOT NULL, action_type char(1) NOT NULL, @@ -84,20 +85,20 @@ public class SetupConfiguration : Core.IDbConfigure etag uuid NULL, CONSTRAINT app_configuration_history_pkey PRIMARY KEY (history_id) );"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - void CreateConfigurationIndexes() - { - const string sql = @" + void CreateConfigurationIndexes() + { + const string sql = @" CREATE INDEX IF NOT EXISTS idx_app_configuration_key ON app_configuration(""key""); CREATE INDEX IF NOT EXISTS idx_app_configuration_validity ON app_configuration(valid_from, expires_at);"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - void CreateModifiedAtTrigger() - { - const string sql = @" + void CreateModifiedAtTrigger() + { + const string sql = @" CREATE OR REPLACE FUNCTION update_app_configuration_modified_at() RETURNS TRIGGER AS $$ BEGIN @@ -110,12 +111,12 @@ public class SetupConfiguration : Core.IDbConfigure BEFORE UPDATE ON app_configuration FOR EACH ROW EXECUTE FUNCTION update_app_configuration_modified_at();"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - void CreateNotifyTrigger() - { - const string sql = @" + void CreateNotifyTrigger() + { + const string sql = @" CREATE OR REPLACE FUNCTION notify_app_configuration_change() RETURNS TRIGGER AS $$ BEGIN @@ -128,12 +129,12 @@ public class SetupConfiguration : Core.IDbConfigure AFTER INSERT OR UPDATE ON app_configuration FOR EACH ROW EXECUTE FUNCTION notify_app_configuration_change();"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - void CreateHistoryTrigger() - { - const string sql = @" + void CreateHistoryTrigger() + { + const string sql = @" CREATE OR REPLACE FUNCTION log_app_configuration_changes() RETURNS TRIGGER AS $$ BEGIN @@ -172,8 +173,8 @@ public class SetupConfiguration : Core.IDbConfigure CREATE OR REPLACE TRIGGER trg_app_configuration_history AFTER INSERT OR UPDATE OR DELETE ON app_configuration FOR EACH ROW EXECUTE FUNCTION log_app_configuration_changes();"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } } diff --git a/Database/Core/DCL/SetupApplicationUser.cs b/Database/Core/DCL/SetupApplicationUser.cs index f4236ff..e1afbd6 100644 --- a/Database/Core/DCL/SetupApplicationUser.cs +++ b/Database/Core/DCL/SetupApplicationUser.cs @@ -1,113 +1,114 @@ using System.Data; -using Database.Common; using Insight.Database; +using PlanTempus.Database.Common; +using PlanTempus.Database.Core; -namespace Database.Core.DCL +namespace PlanTempus.Database.Core.DCL { - /// - /// Only a superadmin or similar can create Application Users - /// - public class SetupApplicationUser : IDbConfigure - { - public class Command - { - public required string Schema { get; init; } - public required string User { get; init; } - public required string Password { get; init; } - } + /// + /// Only a superadmin or similar can create Application Users + /// + public class SetupApplicationUser : IDbConfigure + { + public class Command + { + public required string Schema { get; init; } + public required string User { get; init; } + public required string Password { get; init; } + } - IDbConnection _db; - Command _command; + IDbConnection _db; + Command _command; - public SetupApplicationUser(IDbConnection db) - { - _db = db; - } - - public void With(Command command) - { - _command = command; + public SetupApplicationUser(IDbConnection db) + { + _db = db; + } - if (!Validations.IsValidSchemaName(_command.Schema)) - throw new ArgumentException("Invalid schema name", _command.Schema); + public void With(Command command) + { + _command = command; - using (var transaction = _db.OpenWithTransaction()) - { - try - { - CreateSchema(); - CreateRole(); - GrantSchemaRights(); + if (!Validations.IsValidSchemaName(_command.Schema)) + throw new ArgumentException("Invalid schema name", _command.Schema); - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - throw new InvalidOperationException("Failed to SetupApplicationUser in Database", ex); - } - } + using (var transaction = _db.OpenWithTransaction()) + { + try + { + CreateSchema(); + CreateRole(); + GrantSchemaRights(); - } - private void ExecuteSql(string sql) - { - _db.ExecuteSql(sql); - } + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw new InvalidOperationException("Failed to SetupApplicationUser in Database", ex); + } + } - private void CreateSchema() - { - var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; - ExecuteSql(sql); - } + } + private void ExecuteSql(string sql) + { + _db.ExecuteSql(sql); + } - private void CreateRole() - { - var sql = $@" + private void CreateSchema() + { + var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; + ExecuteSql(sql); + } + + private void CreateRole() + { + var sql = $@" DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{_command.User}') THEN CREATE ROLE {_command.User} WITH CREATEDB CREATEROLE LOGIN PASSWORD '{_command.Password}'; END IF; END $$;"; - ExecuteSql(sql); + ExecuteSql(sql); - var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; - ExecuteSql(sql1); - } + var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; + ExecuteSql(sql1); + } - private void GrantSchemaRights() - { - // Grant USAGE og alle CREATE rettigheder på schema niveau - var sql = $@" + private void GrantSchemaRights() + { + // Grant USAGE og alle CREATE rettigheder på schema niveau + var sql = $@" GRANT USAGE ON SCHEMA {_command.Schema} TO {_command.User}; GRANT ALL ON SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql); + ExecuteSql(sql); - // Grant rettigheder på eksisterende og fremtidige tabeller - var sql1 = $"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql1); + // Grant rettigheder på eksisterende og fremtidige tabeller + var sql1 = $"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA {_command.Schema} TO {_command.User};"; + ExecuteSql(sql1); - var sql2 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT ALL PRIVILEGES ON TABLES TO {_command.User};"; - ExecuteSql(sql2); + var sql2 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT ALL PRIVILEGES ON TABLES TO {_command.User};"; + ExecuteSql(sql2); - // Grant sequence rettigheder - var sql3 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql3); + // Grant sequence rettigheder + var sql3 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};"; + ExecuteSql(sql3); - // Grant execute på functions - var sql4 = $"GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql4); + // Grant execute på functions + var sql4 = $"GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA {_command.Schema} TO {_command.User};"; + ExecuteSql(sql4); - // Grant for fremtidige functions - var sql5 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT EXECUTE ON FUNCTIONS TO {_command.User};"; - ExecuteSql(sql5); + // Grant for fremtidige functions + var sql5 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT EXECUTE ON FUNCTIONS TO {_command.User};"; + ExecuteSql(sql5); - // Grant for fremtidige sequences - var sql6 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT USAGE ON SEQUENCES TO {_command.User};"; - ExecuteSql(sql6); - } + // Grant for fremtidige sequences + var sql6 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT USAGE ON SEQUENCES TO {_command.User};"; + ExecuteSql(sql6); + } - } + } } diff --git a/Database/Core/DCL/SetupDbAdmin.cs b/Database/Core/DCL/SetupDbAdmin.cs index e929faa..3156e2c 100644 --- a/Database/Core/DCL/SetupDbAdmin.cs +++ b/Database/Core/DCL/SetupDbAdmin.cs @@ -1,8 +1,9 @@ using System.Data; -using Database.Common; using Insight.Database; +using PlanTempus.Database.Common; +using PlanTempus.Database.Core; -namespace Database.Core.DCL +namespace PlanTempus.Database.Core.DCL { /// @@ -76,7 +77,7 @@ namespace Database.Core.DCL var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; ExecuteSql(sql1); - + var sql2 = $"ALTER SCHEMA {_command.Schema} OWNER TO {_command.User};"; ExecuteSql(sql2); diff --git a/Database/Core/DCL/SetupOrganizationUser.cs b/Database/Core/DCL/SetupOrganizationUser.cs index e5f4f16..5b878bb 100644 --- a/Database/Core/DCL/SetupOrganizationUser.cs +++ b/Database/Core/DCL/SetupOrganizationUser.cs @@ -1,93 +1,94 @@ using System.Data; -using Database.Common; using Insight.Database; +using PlanTempus.Database.Common; +using PlanTempus.Database.Core; -namespace Database.Core.DCL +namespace PlanTempus.Database.Core.DCL { - public class SetupOrganization : IDbConfigure - { - public class Command - { - public required string Schema { get; init; } - public required string User { get; init; } - public required string Password { get; init; } - } + public class SetupOrganization : IDbConfigure + { + public class Command + { + public required string Schema { get; init; } + public required string User { get; init; } + public required string Password { get; init; } + } - IDbConnection _db; - Command _command; + IDbConnection _db; + Command _command; - public SetupOrganization(IDbConnection db) - { - _db = db; - } + public SetupOrganization(IDbConnection db) + { + _db = db; + } - public void With(Command command) - { + public void With(Command command) + { - _command = command; + _command = command; - if (!Validations.IsValidSchemaName(_command.Schema)) - throw new ArgumentException("Invalid schema name", _command.Schema); + if (!Validations.IsValidSchemaName(_command.Schema)) + throw new ArgumentException("Invalid schema name", _command.Schema); - using (var transaction = _db.BeginTransaction()) - { - try - { - CreateSchema(); - CreateRole(); - GrantSchemaRights(); + using (var transaction = _db.BeginTransaction()) + { + try + { + CreateSchema(); + CreateRole(); + GrantSchemaRights(); - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - throw new InvalidOperationException("Failed to SetupOrganization in Database", ex); - } - } + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw new InvalidOperationException("Failed to SetupOrganization in Database", ex); + } + } - } - private void ExecuteSql(string sql) - { - _db.ExecuteSql(sql); - } + } + private void ExecuteSql(string sql) + { + _db.ExecuteSql(sql); + } - private void CreateSchema() - { - var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; - ExecuteSql(sql); - } + private void CreateSchema() + { + var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; + ExecuteSql(sql); + } - private void CreateRole() - { - var sql = $"CREATE ROLE {_command.User} LOGIN PASSWORD '{_command.Password}';"; - ExecuteSql(sql); + private void CreateRole() + { + var sql = $"CREATE ROLE {_command.User} LOGIN PASSWORD '{_command.Password}';"; + ExecuteSql(sql); - var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; - ExecuteSql(sql1); + var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; + ExecuteSql(sql1); - } + } - private void GrantSchemaRights() - { - var sql = $"GRANT USAGE ON SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql); + private void GrantSchemaRights() + { + var sql = $"GRANT USAGE ON SCHEMA {_command.Schema} TO {_command.User};"; + ExecuteSql(sql); - var sql1 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} " + - $"GRANT INSERT, SELECT, UPDATE PRIVILEGES ON TABLES TO {_command.User};"; - ExecuteSql(sql1); + var sql1 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} " + + $"GRANT INSERT, SELECT, UPDATE PRIVILEGES ON TABLES TO {_command.User};"; + ExecuteSql(sql1); - var sql2 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql2); + var sql2 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};"; + ExecuteSql(sql2); - var sql3 = $"GRANT CREATE TABLE ON SCHEMA {_command.Schema} TO {_command.User};"; - ExecuteSql(sql3); - } - public void RevokeCreateTable() - { - var sql = $"REVOKE CREATE TABLE ON SCHEMA {_command.Schema} FROM {_command.User};"; - ExecuteSql(sql); - } - } + var sql3 = $"GRANT CREATE TABLE ON SCHEMA {_command.Schema} TO {_command.User};"; + ExecuteSql(sql3); + } + public void RevokeCreateTable() + { + var sql = $"REVOKE CREATE TABLE ON SCHEMA {_command.Schema} FROM {_command.User};"; + ExecuteSql(sql); + } + } } diff --git a/Database/Core/DDL/SetupIdentitySystem.cs b/Database/Core/DDL/SetupIdentitySystem.cs index 9ce0fba..98a5fbc 100644 --- a/Database/Core/DDL/SetupIdentitySystem.cs +++ b/Database/Core/DDL/SetupIdentitySystem.cs @@ -1,7 +1,8 @@ using Insight.Database; +using PlanTempus.Database.Core; using System.Data; -namespace Database.Core.DDL +namespace PlanTempus.Database.Core.DDL { /// /// This is by purpose not async await diff --git a/Database/Core/IDbConfigure.cs b/Database/Core/IDbConfigure.cs index c591665..998d6cc 100644 --- a/Database/Core/IDbConfigure.cs +++ b/Database/Core/IDbConfigure.cs @@ -1,7 +1,7 @@ -namespace Database.Core +namespace PlanTempus.Database.Core { - public interface IDbConfigure - { - void With(T command); - } + public interface IDbConfigure + { + void With(T command); + } } diff --git a/Database/Core/UserService.cs b/Database/Core/UserService.cs index c6b1cb5..0cbdcb4 100644 --- a/Database/Core/UserService.cs +++ b/Database/Core/UserService.cs @@ -1,8 +1,8 @@ -using Core.Entities.Users; -using Insight.Database; +using Insight.Database; +using PlanTempus.Core.Entities.Users; using System.Data; -namespace Database.Core +namespace PlanTempus.Database.Core { public class UserService { diff --git a/Database/ModuleRegistry/DbPostgreSqlModule.cs b/Database/ModuleRegistry/DbPostgreSqlModule.cs index 4b9eabb..b22afe9 100644 --- a/Database/ModuleRegistry/DbPostgreSqlModule.cs +++ b/Database/ModuleRegistry/DbPostgreSqlModule.cs @@ -1,22 +1,22 @@ using Autofac; using Npgsql; using System.Data; -namespace Database.ModuleRegistry +namespace PlanTempus.Database.ModuleRegistry { - public class DbPostgreSqlModule : Module - { - public required string ConnectionString { get; set; } - protected override void Load(ContainerBuilder builder) - { - Insight.Database.Providers.PostgreSQL.PostgreSQLInsightDbProvider.RegisterProvider(); + public class DbPostgreSqlModule : Module + { + public required string ConnectionString { get; set; } + protected override void Load(ContainerBuilder builder) + { + Insight.Database.Providers.PostgreSQL.PostgreSQLInsightDbProvider.RegisterProvider(); - builder.Register(c => - { - IDbConnection connection = new NpgsqlConnection(ConnectionString); - return connection; - }) - .InstancePerLifetimeScope(); + builder.Register(c => + { + IDbConnection connection = new NpgsqlConnection(ConnectionString); + return connection; + }) + .InstancePerLifetimeScope(); - } - } + } + } } diff --git a/Database/NavigationSystem/Setup.cs b/Database/NavigationSystem/Setup.cs index 24e4a01..4108029 100644 --- a/Database/NavigationSystem/Setup.cs +++ b/Database/NavigationSystem/Setup.cs @@ -1,26 +1,26 @@ using Insight.Database; using System.Data; -namespace Database.NavigationSystem +namespace PlanTempus.Database.NavigationSystem { - internal class Setup - { + internal class Setup + { - private readonly IDbConnection _db; + private readonly IDbConnection _db; - public Setup(IDbConnection db) - { - _db = db; - } - public void CreateSystem() - { - //await CreateNavigationLinkTemplatesTable(schema); - //await CreateNavigationLinkTemplateTranslationsTable(schema); - } + public Setup(IDbConnection db) + { + _db = db; + } + public void CreateSystem() + { + //await CreateNavigationLinkTemplatesTable(schema); + //await CreateNavigationLinkTemplateTranslationsTable(schema); + } - private async Task CreateNavigationLinkTemplatesTable() - { - var sql = $@" + private async Task CreateNavigationLinkTemplatesTable() + { + var sql = $@" CREATE TABLE IF NOT EXISTS navigation_link_templates ( id SERIAL PRIMARY KEY, parent_id INTEGER NULL, @@ -31,12 +31,12 @@ namespace Database.NavigationSystem FOREIGN KEY (permission_id) REFERENCES permissions(id), FOREIGN KEY (parent_id) REFERENCES navigation_link_templates(id) )"; - await _db.ExecuteAsync(sql); - } + await _db.ExecuteAsync(sql); + } - private async Task CreateNavigationLinkTemplateTranslationsTable(string schema) - { - var sql = $@" + private async Task CreateNavigationLinkTemplateTranslationsTable(string schema) + { + var sql = $@" CREATE TABLE IF NOT EXISTS navigation_link_template_translations ( id SERIAL PRIMARY KEY, template_id INTEGER NOT NULL, @@ -44,7 +44,7 @@ namespace Database.NavigationSystem display_name VARCHAR(100) NOT NULL, FOREIGN KEY (template_id) REFERENCES navigation_link_templates(id) )"; - await _db.ExecuteAsync(sql); - } - } + await _db.ExecuteAsync(sql); + } + } } diff --git a/Database/Database.csproj b/Database/PlanTempus.Database.csproj similarity index 80% rename from Database/Database.csproj rename to Database/PlanTempus.Database.csproj index b281c0c..50d49a6 100644 --- a/Database/Database.csproj +++ b/Database/PlanTempus.Database.csproj @@ -6,7 +6,7 @@ - + diff --git a/Database/RolesPermissionSystem/Setup.cs b/Database/RolesPermissionSystem/Setup.cs index 09a70c2..b405fc9 100644 --- a/Database/RolesPermissionSystem/Setup.cs +++ b/Database/RolesPermissionSystem/Setup.cs @@ -1,92 +1,91 @@ using System.Data; -using Database.Common; using Insight.Database; -namespace Database.RolesPermissionSystem +namespace PlanTempus.Database.RolesPermissionSystem { - /// - /// This is by purpose not async await - /// It is intended that this is created with the correct Application User, which is why the schema name is omitted. - /// - public class Setup - { - IDbConnection _db; + /// + /// This is by purpose not async await + /// It is intended that this is created with the correct Application User, which is why the schema name is omitted. + /// + public class Setup + { + IDbConnection _db; - public Setup(IDbConnection db) - { - _db = db; - } + public Setup(IDbConnection db) + { + _db = db; + } - /// - /// Creates the system tables in the specified schema within a transaction. - /// - /// The schema name where the tables will be created. - public void CreateSystem() - { + /// + /// Creates the system tables in the specified schema within a transaction. + /// + /// The schema name where the tables will be created. + public void CreateSystem() + { - //if (!Validations.IsValidSchemaName(_schema)) - // throw new ArgumentException("Invalid schema name", _schema); + //if (!Validations.IsValidSchemaName(_schema)) + // throw new ArgumentException("Invalid schema name", _schema); - using (var transaction = _db.BeginTransaction()) - { - try - { - CreateRolesTable(); - CreatePermissionsTable(); - CreatePermissionTypesTable(); - CreateRolePermissionsTable(); + using (var transaction = _db.BeginTransaction()) + { + try + { + CreateRolesTable(); + CreatePermissionsTable(); + CreatePermissionTypesTable(); + CreateRolePermissionsTable(); - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - throw new InvalidOperationException("Failed to create system tables.", ex); - } - } - } + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw new InvalidOperationException("Failed to create system tables.", ex); + } + } + } - private void ExecuteSql(string sql) - { - _db.ExecuteSql(sql); - } + private void ExecuteSql(string sql) + { + _db.ExecuteSql(sql); + } - private void CreatePermissionTypesTable() - { - var sql = $@" + private void CreatePermissionTypesTable() + { + var sql = $@" CREATE TABLE IF NOT EXISTS permission_types ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE )"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - private void CreatePermissionsTable() - { - var sql = $@" + private void CreatePermissionsTable() + { + var sql = $@" CREATE TABLE IF NOT EXISTS permissions ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE, type_id INTEGER NOT NULL, FOREIGN KEY (type_id) REFERENCES permission_types(id) )"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - private void CreateRolesTable() - { - var sql = $@" + private void CreateRolesTable() + { + var sql = $@" CREATE TABLE IF NOT EXISTS roles ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE )"; - ExecuteSql(sql); - } + ExecuteSql(sql); + } - private void CreateRolePermissionsTable() - { - var sql = $@" + private void CreateRolePermissionsTable() + { + var sql = $@" CREATE TABLE IF NOT EXISTS role_permissions ( role_id INTEGER NOT NULL, permission_id INTEGER NOT NULL, @@ -94,7 +93,7 @@ namespace Database.RolesPermissionSystem FOREIGN KEY (role_id) REFERENCES roles(id), FOREIGN KEY (permission_id) REFERENCES permissions(id) )"; - ExecuteSql(sql); - } - } + ExecuteSql(sql); + } + } } \ No newline at end of file diff --git a/Database/Tenants/InitializeTenantData.cs b/Database/Tenants/InitializeTenantData.cs index 7b607a8..25be517 100644 --- a/Database/Tenants/InitializeTenantData.cs +++ b/Database/Tenants/InitializeTenantData.cs @@ -1,7 +1,7 @@ using Insight.Database; using System.Data; -namespace Database.Tenants +namespace PlanTempus.Database.Tenants { internal class InitializeOrganizationData { diff --git a/PlanTempus.sln b/PlanTempus.sln index 6d9ec53..5138f3d 100644 --- a/PlanTempus.sln +++ b/PlanTempus.sln @@ -2,15 +2,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.10.35013.160 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", "{7B554252-1CE4-44BD-B108-B0BDCCB24742}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Core", "Core\PlanTempus.Core.csproj", "{7B554252-1CE4-44BD-B108-B0BDCCB24742}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{85614050-CFB0-4E39-81D3-7D99946449D9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Tests", "Tests\PlanTempus.Tests.csproj", "{85614050-CFB0-4E39-81D3-7D99946449D9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "Application\Application.csproj", "{111CE8AE-E637-4376-A5A3-88D33E77EA88}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Application", "Application\PlanTempus.Application.csproj", "{111CE8AE-E637-4376-A5A3-88D33E77EA88}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Database", "Database\Database.csproj", "{D5096A7F-E6D4-4C87-874E-2D9A6BEAD57F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Database", "Database\PlanTempus.Database.csproj", "{D5096A7F-E6D4-4C87-874E-2D9A6BEAD57F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetupInfrastructure", "SetupInfrastructure\SetupInfrastructure.csproj", "{48300227-BCBB-45A3-8359-9064DA85B1F9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.SetupInfrastructure", "SetupInfrastructure\PlanTempus.SetupInfrastructure.csproj", "{48300227-BCBB-45A3-8359-9064DA85B1F9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/SetupInfrastructure/SetupInfrastructure.csproj b/SetupInfrastructure/PlanTempus.SetupInfrastructure.csproj similarity index 83% rename from SetupInfrastructure/SetupInfrastructure.csproj rename to SetupInfrastructure/PlanTempus.SetupInfrastructure.csproj index 9f1d266..0e86a79 100644 --- a/SetupInfrastructure/SetupInfrastructure.csproj +++ b/SetupInfrastructure/PlanTempus.SetupInfrastructure.csproj @@ -7,7 +7,7 @@ - + diff --git a/SetupInfrastructure/Program.cs b/SetupInfrastructure/Program.cs index 068aa9f..abaf66a 100644 --- a/SetupInfrastructure/Program.cs +++ b/SetupInfrastructure/Program.cs @@ -1,88 +1,91 @@ using Autofac; using Insight.Database; +using PlanTempus.Database.ConfigurationManagementSystem; +using PlanTempus.Database.Core.DCL; +using PlanTempus.Database.Core.DDL; using System.Data; using System.Diagnostics; -namespace SetupInfrastructure +namespace PlanTempus.SetupInfrastructure { - /// - /// SETUP APPLICATION USER NAMED sathumper - /// - /// This should be handled on the Postgresql db server with a superadmin or similar. - /// - /// Execute SQL CreateRole.txt - /// - /// After that is executed it is time for running this main program - /// Remember to use the newly created sathumper - /// "ConnectionStrings": { - /// "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id=;Password=;" - /// - internal class Program - { - static IContainer _container; - static ConsoleColor _backgroundColor = Console.BackgroundColor; - static ConsoleColor _foregroundColor = Console.ForegroundColor; + /// + /// SETUP APPLICATION USER NAMED sathumper + /// + /// This should be handled on the Postgresql db server with a superadmin or similar. + /// + /// Execute SQL CreateRole.txt + /// + /// After that is executed it is time for running this main program + /// Remember to use the newly created sathumper + /// "ConnectionStrings": { + /// "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptdb01;User Id=;Password=;" + /// + internal class Program + { + static IContainer _container; + static ConsoleColor _backgroundColor = Console.BackgroundColor; + static ConsoleColor _foregroundColor = Console.ForegroundColor; - static async Task Main(string[] args) - { - Welcome(); - string userPass; + static async Task Main(string[] args) + { + Welcome(); + string userPass; - try - { - do - { - Console.WriteLine("Input username:password for a superadmin role"); - userPass = Console.ReadLine() ?? string.Empty; - } while (!userPass.Contains(":") || userPass.Split(":").Length != 2 || - string.IsNullOrEmpty(userPass.Split(":")[0]) || - string.IsNullOrEmpty(userPass.Split(":")[1])); + try + { + do + { + Console.WriteLine("Input username:password for a superadmin role"); + userPass = Console.ReadLine() ?? string.Empty; + } while (!userPass.Contains(":") || userPass.Split(":").Length != 2 || + string.IsNullOrEmpty(userPass.Split(":")[0]) || + string.IsNullOrEmpty(userPass.Split(":")[1])); - var ctp = new Startup.ConnectionStringTemplateParameters( - user: userPass.Split(":")[0], - pwd: userPass.Split(":")[1] - ); - _container = new Startup().ConfigureContainer(ctp); + var ctp = new Startup.ConnectionStringTemplateParameters( + user: userPass.Split(":")[0], + pwd: userPass.Split(":")[1] + ); + _container = new Startup().ConfigureContainer(ctp); - if (IsSuperAdmin()) - { - Console.ForegroundColor = ConsoleColor.Green; - var sw = new Stopwatch(); + if (IsSuperAdmin()) + { + Console.ForegroundColor = ConsoleColor.Green; + var sw = new Stopwatch(); Console.Write("Database.Core.DCL.SetupDbAdmin..."); sw.Start(); - var setupDbAdmin = _container.Resolve(); - setupDbAdmin.With(new Database.Core.DCL.SetupDbAdmin.Command { Password = "3911", Schema = "system", User = "heimdall" }); + var setupDbAdmin = _container.Resolve(); + setupDbAdmin.With(new SetupDbAdmin.Command { Password = "3911", Schema = "system", User = "heimdall" }); Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); - - Console.WriteLine("::"); - Console.WriteLine("::"); - Console.Write("Database.Core.DDL.SetupIdentitySystem..."); - sw.Restart(); - //create new container with application user, we use that role from now. - _container = new Startup().ConfigureContainer(new Startup.ConnectionStringTemplateParameters("heimdall", "3911")); + Console.WriteLine("::"); + Console.WriteLine("::"); + Console.Write("Database.Core.DDL.SetupIdentitySystem..."); + sw.Restart(); - var setupIdentitySystem = _container.Resolve(); - setupIdentitySystem.With(new Database.Core.DDL.SetupIdentitySystem.Command { Schema = "system"}); - Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); + //create new container with application user, we use that role from now. + _container = new Startup().ConfigureContainer(new Startup.ConnectionStringTemplateParameters("heimdall", "3911")); - Console.WriteLine("::"); - Console.WriteLine("::"); - Console.Write("Database.ConfigurationManagementSystem.SetupConfiguration..."); - sw.Restart(); - var setupConfigurationSystem = _container.Resolve(); - setupConfigurationSystem.With(new Database.ConfigurationManagementSystem.SetupConfiguration.Command()); - Console.Write($"DONE, took: {sw.ElapsedMilliseconds} ms"); + var setupIdentitySystem = _container.Resolve(); + setupIdentitySystem.With(new SetupIdentitySystem.Command { Schema = "system" }); + Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); + + Console.WriteLine("::"); + Console.WriteLine("::"); + Console.Write("Database.ConfigurationManagementSystem.SetupConfiguration..."); + sw.Restart(); + var setupConfigurationSystem = _container.Resolve(); + setupConfigurationSystem.With(new SetupConfiguration.Command()); + Console.Write($"DONE, took: {sw.ElapsedMilliseconds} ms"); Console.WriteLine("::"); Console.WriteLine("::"); Console.Write("Database.Core.DCL.SetupApplicationUser..."); sw.Start(); - var setupApplicationUser = _container.Resolve(); - setupApplicationUser.With(new Database.Core.DCL.SetupApplicationUser.Command { Password = "3911", Schema = "system", User = "sathumper" }); + var setupApplicationUser = _container.Resolve(); + setupApplicationUser.With(new SetupApplicationUser.Command { Password = "3911", Schema = "system", User = "sathumper" }); Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); @@ -91,86 +94,86 @@ namespace SetupInfrastructure // input configurations!!! TODO:Missing Console.ForegroundColor = _foregroundColor; - } + } - } + } - catch (Exception e) - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(e); + catch (Exception e) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(e); - } + } - } + } - static bool IsSuperAdmin() - { + static bool IsSuperAdmin() + { - //test db access - Console.WriteLine("Testing db access..."); + //test db access + Console.WriteLine("Testing db access..."); - string query = @"SELECT usename, usesuper FROM pg_user WHERE usename = CURRENT_USER;"; + string query = @"SELECT usename, usesuper FROM pg_user WHERE usename = CURRENT_USER;"; - var conn = _container.Resolve(); - var result = (dynamic)conn.QuerySql(query).Single(); + var conn = _container.Resolve(); + var result = (dynamic)conn.QuerySql(query).Single(); - string username = result.usename; - bool isSuperuser = (bool)result.usesuper; + string username = result.usename; + bool isSuperuser = (bool)result.usesuper; - if ((bool)result.usesuper) - { - Console.ForegroundColor = ConsoleColor.Green; - Console.BackgroundColor = ConsoleColor.Yellow; - Console.WriteLine(); - Console.WriteLine("TEST SUCCESSFULLY"); - Console.WriteLine(); - Console.ForegroundColor = ConsoleColor.White; - Console.BackgroundColor = _backgroundColor; - Console.WriteLine("-------------------------------"); - Console.WriteLine(); - Console.WriteLine($"Username: {username}"); - Console.WriteLine($"Super admin: true"); - Console.WriteLine(); - Console.WriteLine("-------------------------------"); + if ((bool)result.usesuper) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.BackgroundColor = ConsoleColor.Yellow; + Console.WriteLine(); + Console.WriteLine("TEST SUCCESSFULLY"); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.White; + Console.BackgroundColor = _backgroundColor; + Console.WriteLine("-------------------------------"); + Console.WriteLine(); + Console.WriteLine($"Username: {username}"); + Console.WriteLine($"Super admin: true"); + Console.WriteLine(); + Console.WriteLine("-------------------------------"); - Console.WriteLine("Press any key to start database setup"); - Console.Read(); + Console.WriteLine("Press any key to start database setup"); + Console.Read(); - return true; - } + return true; + } - Console.ForegroundColor = ConsoleColor.Green; - Console.BackgroundColor = ConsoleColor.Red; - Console.WriteLine(); - Console.WriteLine("TEST WAS NOT SUCCESSFULLY"); - Console.WriteLine(); - Console.ForegroundColor = ConsoleColor.White; - Console.BackgroundColor = _backgroundColor; - Console.WriteLine("-------------------------------"); - Console.WriteLine(); - Console.WriteLine($"Username: {username}"); - Console.WriteLine($"Super admin: false"); - Console.WriteLine(); - Console.WriteLine("-------------------------------"); + Console.ForegroundColor = ConsoleColor.Green; + Console.BackgroundColor = ConsoleColor.Red; + Console.WriteLine(); + Console.WriteLine("TEST WAS NOT SUCCESSFULLY"); + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.White; + Console.BackgroundColor = _backgroundColor; + Console.WriteLine("-------------------------------"); + Console.WriteLine(); + Console.WriteLine($"Username: {username}"); + Console.WriteLine($"Super admin: false"); + Console.WriteLine(); + Console.WriteLine("-------------------------------"); - Console.WriteLine("User is required to be super admin"); - Console.Read(); + Console.WriteLine("User is required to be super admin"); + Console.Read(); - return false; + return false; - } - static void Welcome() - { - Console.ForegroundColor = ConsoleColor.Blue; - Console.WriteLine(@"__________.__ ___________ + } + static void Welcome() + { + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine(@"__________.__ ___________ \______ \ | _____ ___\__ ___/___ _____ ______ __ __ ______ | ___/ | \__ \ / \| |_/ __ \ / \\____ \| | \/ ___/ | | | |__/ __ \| | \ |\ ___/| Y Y \ |_> > | /\___ \ @@ -182,9 +185,9 @@ namespace SetupInfrastructure / \ ___/| | | | / |_> > /_______ /\___ >__| |____/| __/ \/ \/ |__|"); - Console.WriteLine(); - Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(); + Console.ForegroundColor = ConsoleColor.White; - } - } + } + } } diff --git a/SetupInfrastructure/Startup.cs b/SetupInfrastructure/Startup.cs index 7e9c07c..fe40b5a 100644 --- a/SetupInfrastructure/Startup.cs +++ b/SetupInfrastructure/Startup.cs @@ -1,45 +1,46 @@ using Autofac; -using Core.Configurations; -using Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.Configurations; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.ModuleRegistry; +using PlanTempus.Database.Core; - -namespace SetupInfrastructure +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 Core.ModuleRegistry.TelemetryModule - { - TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject() - }); + builder.RegisterModule(new TelemetryModule + { + TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject() + }); - builder.RegisterAssemblyTypes(typeof(Database.Core.IDbConfigure<>).Assembly) - .AsClosedTypesOf(typeof(Database.Core.IDbConfigure<>)) - .AsSelf(); + builder.RegisterAssemblyTypes(typeof(IDbConfigure<>).Assembly) + .AsClosedTypesOf(typeof(IDbConfigure<>)) + .AsSelf(); - return builder.Build(); - } + return builder.Build(); + } - public record ConnectionStringTemplateParameters(string user, string pwd); - } + public record ConnectionStringTemplateParameters(string user, string pwd); + } } diff --git a/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs b/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs index cae464b..be895fe 100644 --- a/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs +++ b/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs @@ -1,141 +1,142 @@ -using Core.Configurations; using FluentAssertions; using Newtonsoft.Json.Linq; -using Core.Configurations.JsonConfigProvider; -using Core.Configurations.SmartConfigProvider; +using PlanTempus.Tests; +using PlanTempus.Core.Configurations; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.Configurations.SmartConfigProvider; -namespace Tests.ConfigurationTests +namespace PlanTempus.Tests.ConfigurationTests { - [TestClass] - public class JsonConfigurationProviderTests : TestFixture - { - const string _testFolder = "ConfigurationTests/"; + [TestClass] + public class JsonConfigurationProviderTests : TestFixture + { + const string _testFolder = "ConfigurationTests/"; public JsonConfigurationProviderTests() : base(_testFolder) { } - [TestMethod] - public void GetSection_ShouldReturnCorrectFeatureSection() - { - // Arrange - var expectedJObject = JObject.Parse(@"{ + [TestMethod] + public void GetSection_ShouldReturnCorrectFeatureSection() + { + // Arrange + var expectedJObject = JObject.Parse(@"{ 'Enabled': true, 'RolloutPercentage': 25, 'AllowedUserGroups': ['beta'] }") as JToken; - var builder = new ConfigurationBuilder() - .AddJsonFile($"{_testFolder}appconfiguration.dev.json") - .Build(); - - // Act - var section = builder.GetSection("Feature"); - - // Assert - section.Should().NotBeNull(); - section.Value.Should().BeEquivalentTo(expectedJObject); - } - - [TestMethod] - public void Get_ShouldReturnCorrectFeatureObject() - { - // Arrange - var expectedFeature = new Feature - { - Enabled = true, - RolloutPercentage = 25, - AllowedUserGroups = new() { "beta" } - }; - - var builder = new ConfigurationBuilder() + var builder = new ConfigurationBuilder() .AddJsonFile($"{_testFolder}appconfiguration.dev.json") .Build(); - // Act - var actualFeature = builder.GetSection("Feature").ToObject(); + // Act + var section = builder.GetSection("Feature"); + + // Assert + section.Should().NotBeNull(); + section.Value.Should().BeEquivalentTo(expectedJObject); + } + + [TestMethod] + public void Get_ShouldReturnCorrectFeatureObject() + { + // Arrange + var expectedFeature = new Feature + { + Enabled = true, + RolloutPercentage = 25, + AllowedUserGroups = new() { "beta" } + }; + + var builder = new ConfigurationBuilder() + .AddJsonFile($"{_testFolder}appconfiguration.dev.json") + .Build(); + + // Act + var actualFeature = builder.GetSection("Feature").ToObject(); #pragma warning disable CS0618 // Type or member is obsolete - var actualFeatureObsoleted = builder.GetSection("Feature").Get(); + var actualFeatureObsoleted = builder.GetSection("Feature").Get(); #pragma warning restore CS0618 // Type or member is obsolete - // Assert - actualFeature.Should().BeEquivalentTo(expectedFeature); - actualFeatureObsoleted.Should().BeEquivalentTo(expectedFeature); + // Assert + actualFeature.Should().BeEquivalentTo(expectedFeature); + actualFeatureObsoleted.Should().BeEquivalentTo(expectedFeature); - } - [TestMethod] - public void Get_ShouldReturnCorrectValueAsString() - { - // Arrange - var expectedFeature = "123"; + } + [TestMethod] + public void Get_ShouldReturnCorrectValueAsString() + { + // Arrange + var expectedFeature = "123"; - var builder = new ConfigurationBuilder() + var builder = new ConfigurationBuilder() .AddJsonFile($"{_testFolder}appconfiguration.dev.json") .Build(); - // Act - var actualFeature = builder.GetSection("AnotherSetting").Get("Thresholds:High"); + // Act + var actualFeature = builder.GetSection("AnotherSetting").Get("Thresholds:High"); - // Assert - actualFeature.Should().BeEquivalentTo(expectedFeature); - } - /// - /// Testing a stupid indexer for compability with Microsoft ConfigurationBuilder - /// - [TestMethod] - public void Indexer_ShouldReturnValueAsString() - { - // Arrange - var expected = "SHA256"; + // Assert + actualFeature.Should().BeEquivalentTo(expectedFeature); + } + /// + /// Testing a stupid indexer for compability with Microsoft ConfigurationBuilder + /// + [TestMethod] + public void Indexer_ShouldReturnValueAsString() + { + // Arrange + var expected = "SHA256"; - var builder = new ConfigurationBuilder() + var builder = new ConfigurationBuilder() .AddJsonFile($"{_testFolder}appconfiguration.dev.json") .Build(); - // Act - var actual = builder["Authentication"]; + // Act + var actual = builder["Authentication"]; - // Assert - actual.Should().BeEquivalentTo(expected); - } - [TestMethod] - public void Get_ShouldReturnCorrectValueAsInt() - { - // Arrange - var expectedFeature = 22; + // Assert + actual.Should().BeEquivalentTo(expected); + } + [TestMethod] + public void Get_ShouldReturnCorrectValueAsInt() + { + // Arrange + var expectedFeature = 22; - var builder = new ConfigurationBuilder() + var builder = new ConfigurationBuilder() .AddJsonFile($"{_testFolder}appconfiguration.dev.json") .Build(); - // Act - var actualFeature = builder.GetSection("AnotherSetting:Temperature").Get("Indoor:Max:Limit"); + // Act + var actualFeature = builder.GetSection("AnotherSetting:Temperature").Get("Indoor:Max:Limit"); - // Assert - actualFeature.Should().Be(expectedFeature); - } - [TestMethod] - public void Get_ShouldReturnCorrectValueAsBool() - { - // Arrange - var expectedFeature = true; + // Assert + actualFeature.Should().Be(expectedFeature); + } + [TestMethod] + public void Get_ShouldReturnCorrectValueAsBool() + { + // Arrange + var expectedFeature = true; - var configRoot = new ConfigurationBuilder() + var configRoot = new ConfigurationBuilder() .AddJsonFile($"{_testFolder}appconfiguration.dev.json") .AddSmartConfig() - .Build(); + .Build(); - // Act - var actualFeature = configRoot.Get("Database:UseSSL"); + // Act + var actualFeature = configRoot.Get("Database:UseSSL"); - // Assert - actualFeature.Should().Be(expectedFeature); - } - } + // Assert + actualFeature.Should().Be(expectedFeature); + } + } - public class Feature - { - public bool Enabled { get; set; } - public int RolloutPercentage { get; set; } - public List AllowedUserGroups { get; set; } - } + public class Feature + { + public bool Enabled { get; set; } + public int RolloutPercentage { get; set; } + public List AllowedUserGroups { get; set; } + } } \ No newline at end of file diff --git a/Tests/ConfigurationTests/KeyValueJsonHandlingTests.cs b/Tests/ConfigurationTests/KeyValueJsonHandlingTests.cs index 940c282..7d89439 100644 --- a/Tests/ConfigurationTests/KeyValueJsonHandlingTests.cs +++ b/Tests/ConfigurationTests/KeyValueJsonHandlingTests.cs @@ -1,7 +1,8 @@ -using Newtonsoft.Json.Linq; -using Core.Configurations.Common; +using Newtonsoft.Json.Linq; +using PlanTempus.Core.Configurations.Common; +using PlanTempus.Tests; -namespace Tests.ConfigurationTests; +namespace PlanTempus.Tests.ConfigurationTests; [TestClass] public class ConfigurationTests : TestFixture diff --git a/Tests/ConfigurationTests/SmartConfigProviderTests.cs b/Tests/ConfigurationTests/SmartConfigProviderTests.cs index 97f735d..225e695 100644 --- a/Tests/ConfigurationTests/SmartConfigProviderTests.cs +++ b/Tests/ConfigurationTests/SmartConfigProviderTests.cs @@ -1,13 +1,14 @@ -using Core.Configurations; -using FluentAssertions; -using Core.Configurations.JsonConfigProvider; +using FluentAssertions; using Autofac; using System.Data; using Insight.Database; using Npgsql; -using Core.Configurations.SmartConfigProvider; +using PlanTempus.Tests; +using PlanTempus.Core.Configurations; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.Configurations.SmartConfigProvider; -namespace Tests.ConfigurationTests +namespace PlanTempus.Tests.ConfigurationTests { [TestClass] public class SmartConfigProviderTests : TestFixture diff --git a/Tests/ConfigurationTests/appconfiguration.dev.json b/Tests/ConfigurationTests/appconfiguration.dev.json index 9575ea2..56202bc 100644 --- a/Tests/ConfigurationTests/appconfiguration.dev.json +++ b/Tests/ConfigurationTests/appconfiguration.dev.json @@ -4,7 +4,8 @@ "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id=sathumper;Password=3911;" }, "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 }, "Authentication": "SHA256", "Feature": { diff --git a/Tests/Logging/SeqBackgroundServiceTest.cs b/Tests/Logging/SeqBackgroundServiceTest.cs index dd6da41..6f4c53e 100644 --- a/Tests/Logging/SeqBackgroundServiceTest.cs +++ b/Tests/Logging/SeqBackgroundServiceTest.cs @@ -1,11 +1,11 @@ using Autofac; -using Core.Telemetry; using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.DataContracts; -using Core.Logging; +using PlanTempus.Core.Logging; +using PlanTempus.Core.Telemetry; -namespace Tests.Logging +namespace PlanTempus.Tests.Logging { [TestClass] public class SeqBackgroundServiceTest : TestFixture @@ -23,9 +23,7 @@ namespace Tests.Logging var config = new SeqConfiguration("http://localhost:5341", null, "MSTEST"); var httpClient = new SeqHttpClient(config); - var logger = new SeqLogger(httpClient, Environment.MachineName, config); - - + var logger = new SeqLogger(httpClient, Environment.MachineName, config); _service = new SeqBackgroundService(telemetryClient, _messageChannel, logger); _cts = new CancellationTokenSource(); @@ -40,15 +38,15 @@ namespace Tests.Logging for (int i = 0; i < 5; i++) { - var eventTelemetry = new EventTelemetry - { - Name = "Test Event", - Timestamp = DateTimeOffset.UtcNow - }; - eventTelemetry.Properties.Add("TestId", Guid.NewGuid().ToString()); - eventTelemetry.Metrics.Add("TestMetric", 42.0); + var eventTelemetry = new EventTelemetry + { + Name = "Test Event", + Timestamp = DateTimeOffset.UtcNow + }; + eventTelemetry.Properties.Add("TestId", Guid.NewGuid().ToString()); + eventTelemetry.Metrics.Add("TestMetric", 42.0); - await _messageChannel.Writer.WriteAsync(eventTelemetry); + await _messageChannel.Writer.WriteAsync(eventTelemetry); } // wait for processing diff --git a/Tests/Logging/SeqLoggerTests.cs b/Tests/Logging/SeqLoggerTests.cs index e010fe3..f81e47a 100644 --- a/Tests/Logging/SeqLoggerTests.cs +++ b/Tests/Logging/SeqLoggerTests.cs @@ -1,146 +1,144 @@ using Autofac; -using Core.Logging; using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.DataContracts; +using PlanTempus.Core.Logging; -namespace Tests.Logging +namespace PlanTempus.Tests.Logging { - [TestClass] - public class SeqLoggerTests : TestFixture - { - private SeqLogger _logger; - private SeqHttpClient _httpClient; - private readonly string _testId; + [TestClass] + public class SeqLoggerTests : TestFixture + { + private SeqLogger _logger; + private SeqHttpClient _httpClient; + private readonly string _testId; - public SeqLoggerTests() - { - _testId = Guid.NewGuid().ToString(); - var config = new SeqConfiguration("http://localhost:5341", null, "MSTEST"); - _httpClient = new SeqHttpClient(config); - _logger = new SeqLogger(_httpClient, Environment.MachineName, config); - } + public SeqLoggerTests() + { + _testId = Guid.NewGuid().ToString(); + var config = new SeqConfiguration("http://localhost:5341", null, "MSTEST"); + _httpClient = new SeqHttpClient(config); + _logger = new SeqLogger(_httpClient, Environment.MachineName, config); + } - [TestMethod] - public async Task LogTraceTelemetry_SendsCorrectDataWithErrorLevel() - { - // Arrange - var traceTelemetry = new TraceTelemetry - { - Message = "Test trace error message", - SeverityLevel = SeverityLevel.Error, - Timestamp = DateTimeOffset.UtcNow - }; - traceTelemetry.Properties.Add("TestId", _testId); + [TestMethod] + public async Task LogTraceTelemetry_SendsCorrectDataWithErrorLevel() + { + // Arrange + var traceTelemetry = new TraceTelemetry + { + Message = "Test trace error message", + SeverityLevel = SeverityLevel.Error, + Timestamp = DateTimeOffset.UtcNow + }; + traceTelemetry.Properties.Add("TestId", _testId); - // Act - await _logger.LogAsync(traceTelemetry); + // Act + await _logger.LogAsync(traceTelemetry); - } - [TestMethod] - public async Task LogTraceTelemetry_SendsCorrectDataWithWarningLevel() - { - // Arrange - var traceTelemetry = new TraceTelemetry - { - Message = "Test trace warning message", - SeverityLevel = SeverityLevel.Warning, - Timestamp = DateTimeOffset.UtcNow - }; - traceTelemetry.Properties.Add("TestId", _testId); + } + [TestMethod] + public async Task LogTraceTelemetry_SendsCorrectDataWithWarningLevel() + { + // Arrange + var traceTelemetry = new TraceTelemetry + { + Message = "Test trace warning message", + SeverityLevel = SeverityLevel.Warning, + Timestamp = DateTimeOffset.UtcNow + }; + traceTelemetry.Properties.Add("TestId", _testId); - // Act - await _logger.LogAsync(traceTelemetry); + // Act + await _logger.LogAsync(traceTelemetry); - } - [TestMethod] - public async Task LogEventTelemetry_SendsCorrectData() - { - // Arrange - var eventTelemetry = new EventTelemetry - { - Name = "Test Event", - Timestamp = DateTimeOffset.UtcNow - }; - eventTelemetry.Properties.Add("TestId", _testId); - eventTelemetry.Metrics.Add("TestMetric", 42.0); + } + [TestMethod] + public async Task LogEventTelemetry_SendsCorrectData() + { + // Arrange + var eventTelemetry = new EventTelemetry + { + Name = "Test Event", + Timestamp = DateTimeOffset.UtcNow + }; + eventTelemetry.Properties.Add("TestId", _testId); + eventTelemetry.Metrics.Add("TestMetric", 42.0); - // Act - await _logger.LogAsync(eventTelemetry); - } + // Act + await _logger.LogAsync(eventTelemetry); + } - [TestMethod] - public async Task LogExceptionTelemetry_SendsCorrectData() - { - try - { - int t = 0; - var result = 10 / t; + [TestMethod] + public async Task LogExceptionTelemetry_SendsCorrectData() + { + try + { + int t = 0; + var result = 10 / t; - } - catch (Exception e) - { + } + catch (Exception e) + { - // Arrange - var exceptionTelemetry = new ExceptionTelemetry(e) - { - Timestamp = DateTimeOffset.UtcNow - }; - exceptionTelemetry.Properties.Add("TestId", _testId); + // Arrange + var exceptionTelemetry = new ExceptionTelemetry(e) + { + Timestamp = DateTimeOffset.UtcNow + }; + exceptionTelemetry.Properties.Add("TestId", _testId); - // Act - await _logger.LogAsync(exceptionTelemetry); - } - } + // Act + await _logger.LogAsync(exceptionTelemetry); + } + } - [TestMethod] - public async Task LogDependencyTelemetry_SendsCorrectData() - { - // Arrange - var dependencyTelemetry = new DependencyTelemetry - { - Name = "SQL Query", - Type = "SQL", - Target = "TestDB", - Success = true, - Duration = TimeSpan.FromMilliseconds(100), - Timestamp = DateTimeOffset.UtcNow - }; - dependencyTelemetry.Properties.Add("TestId", _testId); + [TestMethod] + public async Task LogDependencyTelemetry_SendsCorrectData() + { + // Arrange + var dependencyTelemetry = new DependencyTelemetry + { + Name = "SQL Query", + Type = "SQL", + Target = "TestDB", + Success = true, + Duration = TimeSpan.FromMilliseconds(100), + Timestamp = DateTimeOffset.UtcNow + }; + dependencyTelemetry.Properties.Add("TestId", _testId); - // Act - await _logger.LogAsync(dependencyTelemetry); - } + // Act + await _logger.LogAsync(dependencyTelemetry); + } - [TestMethod] - public async Task LogRequestTelemetry_SendsCorrectData() - { - var telemetryClient = Container.Resolve(); + [TestMethod] + public async Task LogRequestTelemetryInOperationHolderWithParentChild_SendsCorrectData() + { + var telemetryClient = Container.Resolve(); - var operationId = "op123"; + using (Microsoft.ApplicationInsights.Extensibility.IOperationHolder parent = telemetryClient.StartOperation("Parent First")) + { - using (Microsoft.ApplicationInsights.Extensibility.IOperationHolder operation = telemetryClient.StartOperation("GET /api/parent")) - { + parent.Telemetry.Duration = TimeSpan.FromMilliseconds(250); + parent.Telemetry.Url = new Uri("http://parent.test.com/api/test"); - using (var child = telemetryClient.StartOperation("api/test")) - // Arrange - { + using (var child = telemetryClient.StartOperation("Child 1")) + { + child.Telemetry.Success = true; + child.Telemetry.ResponseCode = "200"; + child.Telemetry.Duration = TimeSpan.FromMilliseconds(50); + child.Telemetry.Url = new Uri("http://child.test.com/api/test"); + child.Telemetry.Timestamp = DateTimeOffset.UtcNow; - //child.Telemetry.Name = "/api/test"; - child.Telemetry.Success = true; - child.Telemetry.ResponseCode = "200"; - child.Telemetry.Duration = TimeSpan.FromMilliseconds(50); - child.Telemetry.Url = new Uri("http://test.com/api/test"); - child.Telemetry.Timestamp = DateTimeOffset.UtcNow; + child.Telemetry.Properties.Add("httpMethod", HttpMethod.Get.ToString()); + child.Telemetry.Properties.Add("TestId", _testId); - child.Telemetry.Properties.Add("httpMethod", HttpMethod.Get.ToString()); - child.Telemetry.Properties.Add("TestId", _testId); + await _logger.LogAsync(child); + }; - await _logger.LogAsync(child); - }; - - } - // Act - } - } + await _logger.LogAsync(parent); + } + } + } } diff --git a/Tests/PasswordHasherTest.cs b/Tests/PasswordHasherTest.cs index 512e706..bc9ad3f 100644 --- a/Tests/PasswordHasherTest.cs +++ b/Tests/PasswordHasherTest.cs @@ -1,14 +1,8 @@ -using Autofac; -using System.Data; -using Insight.Database; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.Extensions.Logging; -using Core.Telemetry; -using Core.Entities.Users; using System.Diagnostics; using Sodium; +using PlanTempus.Core.Entities.Users; -namespace Tests +namespace PlanTempus.Tests { [TestClass] public class PasswordHasherTests : TestFixture diff --git a/Tests/Tests.csproj b/Tests/PlanTempus.Tests.csproj similarity index 88% rename from Tests/Tests.csproj rename to Tests/PlanTempus.Tests.csproj index 49bd897..e5a1cc2 100644 --- a/Tests/Tests.csproj +++ b/Tests/PlanTempus.Tests.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/Tests/PostgresTests.cs b/Tests/PostgresTests.cs index cbfe0a5..c31b713 100644 --- a/Tests/PostgresTests.cs +++ b/Tests/PostgresTests.cs @@ -1,11 +1,8 @@ using Autofac; using System.Data; using Insight.Database; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.Extensions.Logging; -using Core.Telemetry; -namespace Tests +namespace PlanTempus.Tests { [TestClass] public class PostgresTests : TestFixture @@ -39,11 +36,11 @@ namespace Tests // ); // } // var logger = Container.Resolve(); - - + + // for (int i = 0; i < 5; i++) // { - + // logger.TrackTrace("Hello 23", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information); // } diff --git a/Tests/SecureConnectionStringTests.cs b/Tests/SecureConnectionStringTests.cs index 40d1549..791fbf4 100644 --- a/Tests/SecureConnectionStringTests.cs +++ b/Tests/SecureConnectionStringTests.cs @@ -1,11 +1,6 @@ -using Autofac; -using System.Data; -using Insight.Database; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Microsoft.Extensions.Logging; -using Core.Telemetry; -namespace Tests + +namespace PlanTempus.Tests { - + } \ No newline at end of file diff --git a/Tests/TestFixture.cs b/Tests/TestFixture.cs index c357397..fa06392 100644 --- a/Tests/TestFixture.cs +++ b/Tests/TestFixture.cs @@ -1,12 +1,12 @@ using System; using System.Diagnostics; using Autofac; -using Core.Configurations; -using Core.ModuleRegistry; using Microsoft.ApplicationInsights; using Microsoft.Extensions.Logging; -using Core.Configurations.JsonConfigProvider; -namespace Tests +using PlanTempus.Core.Configurations; +using PlanTempus.Core.Configurations.JsonConfigProvider; +using PlanTempus.Core.ModuleRegistry; +namespace PlanTempus.Tests { /// /// Act as base class for tests. Avoids duplication of test setup code @@ -72,9 +72,9 @@ namespace Tests ConnectionString = configuration.GetConnectionString("DefaultConnection") }); - builder.RegisterModule(new Core.ModuleRegistry.TelemetryModule + builder.RegisterModule(new TelemetryModule { - TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject() + TelemetryConfig = configuration.GetSection("ApplicationInsights").ToObject() }); diff --git a/Tests/appconfiguration.dev.json b/Tests/appconfiguration.dev.json index 7afbfa5..f938c66 100644 --- a/Tests/appconfiguration.dev.json +++ b/Tests/appconfiguration.dev.json @@ -3,6 +3,7 @@ "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id=sathumper;Password=3911;" }, "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 } } \ No newline at end of file