diff --git a/Power/Power.sln b/Power/Power.sln index a25aa10..034a935 100644 --- a/Power/Power.sln +++ b/Power/Power.sln @@ -1,9 +1,8 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28705.295 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.csproj", "{914B9DB9-3BCD-4B55-8289-2E59D6CA96BA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Service", "Service\Service.csproj", "{914B9DB9-3BCD-4B55-8289-2E59D6CA96BA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Power/Service/Controllers/StatusController.cs b/Power/Service/Controllers/StatusController.cs index 502c772..8307188 100644 --- a/Power/Service/Controllers/StatusController.cs +++ b/Power/Service/Controllers/StatusController.cs @@ -6,29 +6,21 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace ChrisKaczor.HomeMonitor.Power.Service.Controllers +namespace ChrisKaczor.HomeMonitor.Power.Service.Controllers; + +[Route("[controller]")] +[ApiController] +public class StatusController(Database database) : ControllerBase { - [Route("[controller]")] - [ApiController] - public class StatusController : ControllerBase + [HttpGet("recent")] + public async Task> GetRecent() { - private readonly Database _database; + return await database.GetRecentStatus(); + } - public StatusController(Database database) - { - _database = database; - } - - [HttpGet("recent")] - public async Task> GetRecent() - { - return await _database.GetRecentStatus(); - } - - [HttpGet("history-grouped")] - public async Task>> GetHistoryGrouped(DateTimeOffset start, DateTimeOffset end, int bucketMinutes = 2) - { - return (await _database.GetStatusHistoryGrouped(start, end, bucketMinutes)).ToList(); - } + [HttpGet("history-grouped")] + public async Task>> GetHistoryGrouped(DateTimeOffset start, DateTimeOffset end, int bucketMinutes = 2) + { + return (await database.GetStatusHistoryGrouped(start, end, bucketMinutes)).ToList(); } } \ No newline at end of file diff --git a/Power/Service/Data/Database.cs b/Power/Service/Data/Database.cs index df03bab..6e1012f 100644 --- a/Power/Service/Data/Database.cs +++ b/Power/Service/Data/Database.cs @@ -6,95 +6,89 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -namespace ChrisKaczor.HomeMonitor.Power.Service.Data +namespace ChrisKaczor.HomeMonitor.Power.Service.Data; + +public class Database(IConfiguration configuration) { - public class Database + public void EnsureDatabase() { - private readonly IConfiguration _configuration; - - public Database(IConfiguration configuration) + var connectionStringBuilder = new SqlConnectionStringBuilder { - _configuration = configuration; - } + DataSource = $"{configuration["Power:Database:Host"]},{configuration["Power:Database:Port"]}", + UserID = configuration["Power:Database:User"], + Password = configuration["Power:Database:Password"], + InitialCatalog = "master", + TrustServerCertificate = bool.Parse(configuration["Power:Database:TrustServerCertificate"] ?? "false") + }; - public void EnsureDatabase() + using var connection = new SqlConnection(connectionStringBuilder.ConnectionString); + + var command = new SqlCommand { Connection = connection }; + + connection.Open(); + + // Check to see if the database exists + command.CommandText = $"SELECT CAST(1 as bit) from sys.databases WHERE name='{configuration["Power:Database:Name"]}'"; + var databaseExists = (bool?)command.ExecuteScalar(); + + // Create database if needed + if (!(databaseExists ?? false)) { - var connectionStringBuilder = new SqlConnectionStringBuilder - { - DataSource = $"{_configuration["Power:Database:Host"]},{_configuration["Power:Database:Port"]}", - UserID = _configuration["Power:Database:User"], - Password = _configuration["Power:Database:Password"], - InitialCatalog = "master" - }; - - using var connection = new SqlConnection(connectionStringBuilder.ConnectionString); - - var command = new SqlCommand { Connection = connection }; - - connection.Open(); - - // Check to see if the database exists - command.CommandText = $"SELECT CAST(1 as bit) from sys.databases WHERE name='{_configuration["Power:Database:Name"]}'"; - var databaseExists = (bool?)command.ExecuteScalar(); - - // Create database if needed - if (!(databaseExists ?? false)) - { - command.CommandText = $"CREATE DATABASE {_configuration["Power:Database:Name"]}"; - command.ExecuteNonQuery(); - } - - // Switch to the database now that we're sure it exists - connection.ChangeDatabase(_configuration["Power:Database:Name"]); - - var schema = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.Schema.sql"); - - // Make sure the database is up to date - command.CommandText = schema; + command.CommandText = $"CREATE DATABASE {configuration["Power:Database:Name"]}"; command.ExecuteNonQuery(); } - private SqlConnection CreateConnection() + // Switch to the database now that we're sure it exists + connection.ChangeDatabase(configuration["Power:Database:Name"]!); + + var schema = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.Schema.sql"); + + // Make sure the database is up-to-date + command.CommandText = schema; + command.ExecuteNonQuery(); + } + + private SqlConnection CreateConnection() + { + var connectionStringBuilder = new SqlConnectionStringBuilder { - var connectionStringBuilder = new SqlConnectionStringBuilder - { - DataSource = $"{_configuration["Power:Database:Host"]},{_configuration["Power:Database:Port"]}", - UserID = _configuration["Power:Database:User"], - Password = _configuration["Power:Database:Password"], - InitialCatalog = _configuration["Power:Database:Name"] - }; + DataSource = $"{configuration["Power:Database:Host"]},{configuration["Power:Database:Port"]}", + UserID = configuration["Power:Database:User"], + Password = configuration["Power:Database:Password"], + InitialCatalog = configuration["Power:Database:Name"], + TrustServerCertificate = bool.Parse(configuration["Power:Database:TrustServerCertificate"] ?? "false") + }; - var connection = new SqlConnection(connectionStringBuilder.ConnectionString); - connection.Open(); + var connection = new SqlConnection(connectionStringBuilder.ConnectionString); + connection.Open(); - return connection; - } + return connection; + } - public void StorePowerData(PowerStatus powerStatus) - { - using var connection = CreateConnection(); + public void StorePowerData(PowerStatus powerStatus) + { + using var connection = CreateConnection(); - var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.CreateStatus.sql"); + var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.CreateStatus.sql"); - connection.Query(query, powerStatus); - } + connection.Query(query, powerStatus); + } - public async Task GetRecentStatus() - { - await using var connection = CreateConnection(); + public async Task GetRecentStatus() + { + await using var connection = CreateConnection(); - var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.GetRecentStatus.sql"); + var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.GetRecentStatus.sql"); - return await connection.QueryFirstOrDefaultAsync(query); - } + return await connection.QueryFirstOrDefaultAsync(query); + } - public async Task> GetStatusHistoryGrouped(DateTimeOffset start, DateTimeOffset end, int bucketMinutes) - { - await using var connection = CreateConnection(); + public async Task> GetStatusHistoryGrouped(DateTimeOffset start, DateTimeOffset end, int bucketMinutes) + { + await using var connection = CreateConnection(); - var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.GetStatusHistoryGrouped.sql"); + var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Power.Service.Data.Resources.GetStatusHistoryGrouped.sql"); - return await connection.QueryAsync(query, new { Start = start, End = end, BucketMinutes = bucketMinutes }); - } + return await connection.QueryAsync(query, new { Start = start, End = end, BucketMinutes = bucketMinutes }); } } \ No newline at end of file diff --git a/Power/Service/Dockerfile b/Power/Service/Dockerfile index e2aeeb2..012315c 100644 --- a/Power/Service/Dockerfile +++ b/Power/Service/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build WORKDIR /src COPY ["./Service.csproj", "./"] RUN dotnet restore "Service.csproj" diff --git a/Power/Service/Models/PowerChannel.cs b/Power/Service/Models/PowerChannel.cs index f5670b0..f90eecd 100644 --- a/Power/Service/Models/PowerChannel.cs +++ b/Power/Service/Models/PowerChannel.cs @@ -1,30 +1,29 @@ using JetBrains.Annotations; using System.Text.Json.Serialization; -namespace ChrisKaczor.HomeMonitor.Power.Service.Models +namespace ChrisKaczor.HomeMonitor.Power.Service.Models; + +[PublicAPI] +public class PowerChannel { - [PublicAPI] - public class PowerChannel - { - [JsonPropertyName("type")] - public string Type { get; set; } + [JsonPropertyName("type")] + public string Type { get; set; } - [JsonPropertyName("ch")] - public long ChannelNumber { get; set; } + [JsonPropertyName("ch")] + public long ChannelNumber { get; set; } - [JsonPropertyName("eImp_Ws")] - public long ImportedEnergy { get; set; } + [JsonPropertyName("eImp_Ws")] + public long ImportedEnergy { get; set; } - [JsonPropertyName("eExp_Ws")] - public long ExportedEnergy { get; set; } + [JsonPropertyName("eExp_Ws")] + public long ExportedEnergy { get; set; } - [JsonPropertyName("p_W")] - public long RealPower { get; set; } + [JsonPropertyName("p_W")] + public long RealPower { get; set; } - [JsonPropertyName("q_VAR")] - public long ReactivePower { get; set; } + [JsonPropertyName("q_VAR")] + public long ReactivePower { get; set; } - [JsonPropertyName("v_V")] - public double Voltage { get; set; } - } -} + [JsonPropertyName("v_V")] + public double Voltage { get; set; } +} \ No newline at end of file diff --git a/Power/Service/Models/PowerSample.cs b/Power/Service/Models/PowerSample.cs index e3aac0e..3bcecc7 100644 --- a/Power/Service/Models/PowerSample.cs +++ b/Power/Service/Models/PowerSample.cs @@ -3,21 +3,20 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -namespace ChrisKaczor.HomeMonitor.Power.Service.Models +namespace ChrisKaczor.HomeMonitor.Power.Service.Models; + +[PublicAPI] +public class PowerSample { - [PublicAPI] - public class PowerSample - { - [JsonPropertyName("sensorId")] - public string SensorId { get; set; } + [JsonPropertyName("sensorId")] + public string SensorId { get; set; } - [JsonPropertyName("timestamp")] - public DateTimeOffset Timestamp { get; set; } + [JsonPropertyName("timestamp")] + public DateTimeOffset Timestamp { get; set; } - [JsonPropertyName("channels")] - public PowerChannel[] Channels { get; set; } + [JsonPropertyName("channels")] + public PowerChannel[] Channels { get; set; } - [JsonPropertyName("cts")] - public Dictionary[] CurrentTransformers { get; set; } - } -} + [JsonPropertyName("cts")] + public Dictionary[] CurrentTransformers { get; set; } +} \ No newline at end of file diff --git a/Power/Service/Models/PowerStatus.cs b/Power/Service/Models/PowerStatus.cs index 2fd86d4..43d43bf 100644 --- a/Power/Service/Models/PowerStatus.cs +++ b/Power/Service/Models/PowerStatus.cs @@ -1,13 +1,12 @@ using JetBrains.Annotations; using System; -namespace ChrisKaczor.HomeMonitor.Power.Service.Models +namespace ChrisKaczor.HomeMonitor.Power.Service.Models; + +[PublicAPI] +public class PowerStatus { - [PublicAPI] - public class PowerStatus - { - public DateTimeOffset Timestamp { get; set; } = DateTimeOffset.UtcNow; - public long Generation { get; set; } - public long Consumption { get; set; } - } -} + public DateTimeOffset Timestamp { get; set; } = DateTimeOffset.UtcNow; + public long Generation { get; set; } + public long Consumption { get; set; } +} \ No newline at end of file diff --git a/Power/Service/Models/PowerStatusGrouped.cs b/Power/Service/Models/PowerStatusGrouped.cs index f82a68c..c2ad870 100644 --- a/Power/Service/Models/PowerStatusGrouped.cs +++ b/Power/Service/Models/PowerStatusGrouped.cs @@ -1,13 +1,12 @@ using JetBrains.Annotations; using System; -namespace ChrisKaczor.HomeMonitor.Power.Service.Models +namespace ChrisKaczor.HomeMonitor.Power.Service.Models; + +[PublicAPI] +public class PowerStatusGrouped { - [PublicAPI] - public class PowerStatusGrouped - { - public DateTimeOffset Bucket { get; set; } - public long AverageGeneration { get; set; } - public long AverageConsumption { get; set; } - } -} + public DateTimeOffset Bucket { get; set; } + public long AverageGeneration { get; set; } + public long AverageConsumption { get; set; } +} \ No newline at end of file diff --git a/Power/Service/PowerReader.cs b/Power/Service/PowerReader.cs index ab4ad38..e568705 100644 --- a/Power/Service/PowerReader.cs +++ b/Power/Service/PowerReader.cs @@ -1,102 +1,94 @@ using ChrisKaczor.HomeMonitor.Power.Service.Data; using ChrisKaczor.HomeMonitor.Power.Service.Models; using JetBrains.Annotations; -using Microsoft.ApplicationInsights; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using RestSharp; using System; +using System.Diagnostics; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -namespace ChrisKaczor.HomeMonitor.Power.Service +namespace ChrisKaczor.HomeMonitor.Power.Service; + +[UsedImplicitly] +public class PowerReader(IConfiguration configuration, Database database, ILogger logger) : IHostedService { - [UsedImplicitly] - public class PowerReader : IHostedService + private readonly ActivitySource _activitySource = new(nameof(PowerReader)); + + private HubConnection _hubConnection; + private Timer _readTimer; + + public Task StartAsync(CancellationToken cancellationToken) { - private readonly IConfiguration _configuration; - private readonly Database _database; - private readonly TelemetryClient _telemetryClient; + logger.LogInformation($"{nameof(PowerReader)} - Start"); - private HubConnection _hubConnection; - private Timer _readTimer; + _readTimer = new Timer(GetCurrentSample, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); - public PowerReader(IConfiguration configuration, Database database, TelemetryClient telemetryClient) + if (!string.IsNullOrEmpty(configuration["Hub:Power"])) + _hubConnection = new HubConnectionBuilder().WithUrl(configuration["Hub:Power"]).Build(); + + return Task.CompletedTask; + } + + private void GetCurrentSample(object state) + { + using var activity = _activitySource.StartActivity(); + + try { - _configuration = configuration; - _database = database; - _telemetryClient = telemetryClient; + var client = new RestClient(configuration["Power:Host"]!); + + var request = new RestRequest("current-sample"); + request.AddHeader("Authorization", configuration["Power:AuthorizationHeader"]!); + + var response = client.Execute(request); + + var content = response.Content!; + + logger.LogInformation("API response: {content}", content); + + var sample = JsonSerializer.Deserialize(content); + + var generation = Array.Find(sample.Channels, c => c.Type == "GENERATION"); + var consumption = Array.Find(sample.Channels, c => c.Type == "CONSUMPTION"); + + if (generation == null || consumption == null) + return; + + var status = new PowerStatus { Generation = generation.RealPower, Consumption = consumption.RealPower }; + + database.StorePowerData(status); + + var json = JsonSerializer.Serialize(status); + + logger.LogInformation("Output message: {json}", json); + + if (_hubConnection == null) + return; + + if (_hubConnection.State == HubConnectionState.Disconnected) + _hubConnection.StartAsync().Wait(); + + _hubConnection.InvokeAsync("SendLatestSample", json).Wait(); } - - public Task StartAsync(CancellationToken cancellationToken) + catch (Exception exception) { - _telemetryClient.TrackTrace($"{nameof(PowerReader)} - Start"); - - _readTimer = new Timer(OnTimer, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); - - if (!string.IsNullOrEmpty(_configuration["Hub:Power"])) - _hubConnection = new HubConnectionBuilder().WithUrl(_configuration["Hub:Power"]).Build(); - - return Task.CompletedTask; - } - - private void OnTimer(object state) - { - try - { - var client = new RestClient(_configuration["Power:Host"]); - - var request = new RestRequest("current-sample", Method.GET); - request.AddHeader("Authorization", _configuration["Power:AuthorizationHeader"]); - - var response = client.Execute(request); - - var sample = JsonSerializer.Deserialize(response.Content); - - var generation = Array.Find(sample.Channels, c => c.Type == "GENERATION"); - var consumption = Array.Find(sample.Channels, c => c.Type == "CONSUMPTION"); - - if (generation == null || consumption == null) - return; - - var status = new PowerStatus { Generation = generation.RealPower, Consumption = consumption.RealPower }; - - _database.StorePowerData(status); - - var json = JsonSerializer.Serialize(status); - - Console.WriteLine(json); - - if (_hubConnection == null) - return; - - if (_hubConnection.State == HubConnectionState.Disconnected) - _hubConnection.StartAsync().Wait(); - - _hubConnection.InvokeAsync("SendLatestSample", json).Wait(); - } - catch (Exception exception) - { - WriteLog($"Exception: {exception}"); - } - } - - public Task StopAsync(CancellationToken cancellationToken) - { - _telemetryClient.TrackTrace($"{nameof(PowerReader)} - Stop"); - - _readTimer.Dispose(); - - _hubConnection?.StopAsync(cancellationToken).Wait(cancellationToken); - - return Task.CompletedTask; - } - - private static void WriteLog(string message) - { - Console.WriteLine(message); + logger.LogError(exception, "Exception"); } } + + public Task StopAsync(CancellationToken cancellationToken) + { + logger.LogInformation($"{nameof(PowerReader)} - Stop"); + + _readTimer.Dispose(); + + _hubConnection?.StopAsync(cancellationToken).Wait(cancellationToken); + + return Task.CompletedTask; + } } \ No newline at end of file diff --git a/Power/Service/Program.cs b/Power/Service/Program.cs index e29ce87..d426e41 100644 --- a/Power/Service/Program.cs +++ b/Power/Service/Program.cs @@ -1,19 +1,127 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +using ChrisKaczor.HomeMonitor.Power.Service.Data; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.ResponseCompression; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using OpenTelemetry.Exporter; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; +using System; +using System.IO.Compression; +using System.Reflection; -namespace ChrisKaczor.HomeMonitor.Power.Service +namespace ChrisKaczor.HomeMonitor.Power.Service; + +public static class Program { - public static class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CreateWebHostBuilder(args).Build().Run(); - } + var builder = WebApplication.CreateBuilder(args); - private static IWebHostBuilder CreateWebHostBuilder(string[] args) + builder.Configuration.AddEnvironmentVariables(); + + builder.Services.AddControllers(); + + // --- + + var openTelemetry = builder.Services.AddOpenTelemetry(); + + AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); + + var name = Assembly.GetExecutingAssembly().GetName().Name; + + openTelemetry.ConfigureResource(resource => resource.AddService(name!)); + + openTelemetry.WithMetrics(meterProviderBuilder => meterProviderBuilder + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddProcessInstrumentation() + .AddMeter("Microsoft.AspNetCore.Hosting") + .AddMeter("Microsoft.AspNetCore.Server.Kestrel")); + + openTelemetry.WithTracing(tracerProviderBuilder => { - return WebHost.CreateDefaultBuilder(args).ConfigureAppConfiguration((_, config) => config.AddEnvironmentVariables()).UseStartup(); - } + tracerProviderBuilder.AddAspNetCoreInstrumentation(instrumentationOptions => instrumentationOptions.RecordException = true); + + tracerProviderBuilder.AddHttpClientInstrumentation(instrumentationOptions => instrumentationOptions.RecordException = true); + + tracerProviderBuilder.AddSqlClientInstrumentation(o => + { + o.RecordException = true; + o.SetDbStatementForText = true; + }); + + tracerProviderBuilder.AddSource(nameof(PowerReader)); + + if (builder.Environment.IsDevelopment()) + tracerProviderBuilder.AddConsoleExporter(); + + tracerProviderBuilder.SetErrorStatusOnException(); + + tracerProviderBuilder.AddOtlpExporter(exporterOptions => + { + exporterOptions.Endpoint = new Uri(builder.Configuration["Telemetry:Endpoint"]!); + exporterOptions.Protocol = OtlpExportProtocol.Grpc; + }); + }); + + builder.Services.AddLogging((loggingBuilder) => + { + loggingBuilder.SetMinimumLevel(LogLevel.Information); + loggingBuilder.AddOpenTelemetry(options => + { + if (builder.Environment.IsDevelopment()) + options.AddConsoleExporter(); + + options.AddOtlpExporter(exporterOptions => + { + exporterOptions.Endpoint = new Uri(builder.Configuration["Telemetry:Endpoint"]!); + exporterOptions.Protocol = OtlpExportProtocol.Grpc; + }); + } + ); + }); + + builder.Services.AddTransient(); + + builder.Services.AddHostedService(); + + builder.Services.Configure(options => options.Level = CompressionLevel.Optimal); + + builder.Services.AddResponseCompression(options => + { + options.Providers.Add(); + options.EnableForHttps = true; + }); + + builder.Services.AddCors(o => o.AddPolicy("CorsPolicy", corsPolicyBuilder => corsPolicyBuilder.AllowAnyMethod().AllowAnyHeader().AllowCredentials().WithOrigins("http://localhost:4200"))); + + builder.Services.AddMvc(); + + // --- + + var app = builder.Build(); + + if (builder.Environment.IsDevelopment()) + app.UseDeveloperExceptionPage(); + + var database = app.Services.GetRequiredService(); + database.EnsureDatabase(); + + app.UseCors("CorsPolicy"); + + app.UseResponseCompression(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.MapControllers(); + + app.Run(); } } \ No newline at end of file diff --git a/Power/Service/ResourceReader.cs b/Power/Service/ResourceReader.cs index d81ee8a..5836bce 100644 --- a/Power/Service/ResourceReader.cs +++ b/Power/Service/ResourceReader.cs @@ -2,21 +2,20 @@ using System.IO; using System.Reflection; -namespace ChrisKaczor.HomeMonitor.Power.Service +namespace ChrisKaczor.HomeMonitor.Power.Service; + +public static class ResourceReader { - public static class ResourceReader + public static string GetString(string resourceName) { - public static string GetString(string resourceName) - { - var assembly = Assembly.GetExecutingAssembly(); - using var stream = assembly.GetManifestResourceStream(resourceName); + var assembly = Assembly.GetExecutingAssembly(); + using var stream = assembly.GetManifestResourceStream(resourceName); - if (stream == null) - throw new Exception($"Resource {resourceName} not found in {assembly.FullName}. Valid resources are: {string.Join(", ", assembly.GetManifestResourceNames())}."); + if (stream == null) + throw new Exception($"Resource {resourceName} not found in {assembly.FullName}. Valid resources are: {string.Join(", ", assembly.GetManifestResourceNames())}."); - using var reader = new StreamReader(stream); + using var reader = new StreamReader(stream); - return reader.ReadToEnd(); - } + return reader.ReadToEnd(); } } \ No newline at end of file diff --git a/Power/Service/Service.csproj b/Power/Service/Service.csproj index 0197698..0fb7cb6 100644 --- a/Power/Service/Service.csproj +++ b/Power/Service/Service.csproj @@ -1,36 +1,35 @@  - - net5.0 + net8.0 InProcess ChrisKaczor.HomeMonitor.Power.Service ChrisKaczor.HomeMonitor.Power.Service - ../../ChrisKaczor.ruleset - false + false - + + - - - - - - - - - + + + + + + + + + + - - + \ No newline at end of file diff --git a/Power/Service/Startup.cs b/Power/Service/Startup.cs deleted file mode 100644 index c63be1a..0000000 --- a/Power/Service/Startup.cs +++ /dev/null @@ -1,69 +0,0 @@ -using ChrisKaczor.HomeMonitor.Power.Service.Data; -using Microsoft.ApplicationInsights; -using Microsoft.ApplicationInsights.Extensibility; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.ResponseCompression; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System.IO.Compression; -using System.Threading; - -namespace ChrisKaczor.HomeMonitor.Power.Service -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddSingleton(); - - services.AddApplicationInsightsTelemetry(options => - { - options.EnableDependencyTrackingTelemetryModule = false; - }); - - services.AddTransient(); - - services.AddHostedService(); - - services.Configure(options => options.Level = CompressionLevel.Optimal); - - services.AddResponseCompression(options => - { - options.Providers.Add(); - options.EnableForHttps = true; - }); - - services.AddCors(o => o.AddPolicy("CorsPolicy", builder => builder.AllowAnyMethod().AllowAnyHeader().AllowCredentials().WithOrigins("http://localhost:4200"))); - - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0); - } - - public void Configure(IApplicationBuilder applicationBuilder, IWebHostEnvironment environment, IHostApplicationLifetime hostApplicationLifetime) - { - if (environment.IsDevelopment()) - applicationBuilder.UseDeveloperExceptionPage(); - - hostApplicationLifetime.ApplicationStopping.Register(() => - { - var telemetryClient = applicationBuilder.ApplicationServices.GetRequiredService(); - - telemetryClient.Flush(); - - Thread.Sleep(5000); - }); - - var database = applicationBuilder.ApplicationServices.GetRequiredService(); - database.EnsureDatabase(); - - applicationBuilder.UseCors("CorsPolicy"); - - applicationBuilder.UseResponseCompression(); - - applicationBuilder.UseRouting(); - - applicationBuilder.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); - } - } -} \ No newline at end of file diff --git a/Power/Service/TelemetryInitializer.cs b/Power/Service/TelemetryInitializer.cs deleted file mode 100644 index 157be8a..0000000 --- a/Power/Service/TelemetryInitializer.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.ApplicationInsights.Channel; -using Microsoft.ApplicationInsights.Extensibility; -using System.Reflection; - -namespace ChrisKaczor.HomeMonitor.Power.Service -{ - public class TelemetryInitializer : ITelemetryInitializer - { - public void Initialize(ITelemetry telemetry) - { - telemetry.Context.Cloud.RoleName = Assembly.GetEntryAssembly()?.GetName().Name; - } - } -} diff --git a/Power/Service/appsettings.json b/Power/Service/appsettings.json index cf0025a..7a331a4 100644 --- a/Power/Service/appsettings.json +++ b/Power/Service/appsettings.json @@ -1,16 +1,20 @@ { - "Logging": { - "LogLevel": { - "Default": "Warning" + "Logging": { + "LogLevel": { + "Default": "Information" + } + }, + "Power": { + "Database": { + "Name": "Power", + "Port": 1434, + "TrustServerCertificate": true + } + }, + "Hub": { + "Power": "" + }, + "Telemetry": { + "Endpoint": "http://signoz-otel-collector.platform:4317/" } - }, - "Power": { - "Database": { - "Name": "Power", - "Port": 1434 - } - }, - "Hub": { - "Power": "http://hub-server/power" - } } \ No newline at end of file diff --git a/Power/Service/deploy/manifest.yaml b/Power/Service/deploy/manifest.yaml index 9b13961..7efbb80 100644 --- a/Power/Service/deploy/manifest.yaml +++ b/Power/Service/deploy/manifest.yaml @@ -94,11 +94,6 @@ spec: securityContext: privileged: true env: - - name: ApplicationInsights__ConnectionString - valueFrom: - secretKeyRef: - name: telemetry - key: key - name: Power__Database__Host value: power-database - name: Power__Database__User