From 84d1b07301f050d2b6afb3d89a8b748d5e5f9612 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Tue, 22 Oct 2024 09:48:28 -0700 Subject: [PATCH] HelperCamstarOracle --- .vscode/.UserSecrets/file-watcher.json | 17 +- .vscode/settings.json | 1 + .vscode/tasks.json | 10 + File-Watcher.csproj | 4 +- Helpers/HelperCamstarOracle.cs | 116 +++++++++++ Helpers/HelperInfinityQS.cs | 43 ---- Infineon/Monitoring/MonA/IMonIn.cs | 145 ++++++++++++++ Infineon/Monitoring/MonA/MonIn.cs | 266 +++++++++++++++++++++++++ Infineon/Monitoring/MonA/State.cs | 11 + Models/AppSettings.cs | 3 +- Models/Binder/AppSettings.cs | 5 +- Models/CamstarOracleConfiguration.cs | 28 +++ Program.cs | 1 + Worker.cs | 20 +- 14 files changed, 622 insertions(+), 48 deletions(-) create mode 100644 Helpers/HelperCamstarOracle.cs create mode 100644 Infineon/Monitoring/MonA/IMonIn.cs create mode 100644 Infineon/Monitoring/MonA/MonIn.cs create mode 100644 Infineon/Monitoring/MonA/State.cs create mode 100644 Models/CamstarOracleConfiguration.cs diff --git a/.vscode/.UserSecrets/file-watcher.json b/.vscode/.UserSecrets/file-watcher.json index d3a2044..046ffc1 100644 --- a/.vscode/.UserSecrets/file-watcher.json +++ b/.vscode/.UserSecrets/file-watcher.json @@ -1,4 +1,18 @@ { + "CamstarOracleConfiguration": { + "DateFormat": "yyyy-MM-dd HH:mm:ss:fff", + "DirectoryX": "C:/Users/ECUSLEOCamstarTsvc/AppData/Local/IFXApps/WinLog/Logs", + "Directory": "D:/Tmp/Phares/WinLog/Logs", + "LogFilter": "Camstar", + "MessageFilters": [ + "Connection Dead", + "not connected to ORACLE" + ], + "MillisecondsDelay": 90000, + "MonitorApplicationResource": "LEO_CAMSTAR_ORACLE_P21_COUNT", + "MonitorApplicationSite": "auc", + "RollingMinutes": 998877123 + }, "CompassConfiguration": { "Destination": "\\\\10.95.1.211\\Share\\RawData\\TRENDLOG", "HoursBack": 4, @@ -38,8 +52,9 @@ }, "InfinityQSConfiguration": { "ConnectionStringX": "Data Source=messad1001\\test1,59583;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;", - "ConnectionString": "Data Source=messqlec1.infineon.com\\PROD1,53959;Initial Catalog=Metrology;User ID=metrology_rouser;Password=Metrologyrouser2024!;", + "ConnectionStringXX": "Data Source=messqlec1.infineon.com\\PROD1,53959;Initial Catalog=Metrology;User ID=metrology_rouser;Password=Metrologyrouser2024!;", "ConnectionStringXXX": "Data Source=messqlec1.infineon.com\\PROD1,53959;Initial Catalog=IRMNSPC;User ID=IRMNSPC;Password=dsaf;", + "ConnectionString": "Data Source=messqlec1.infineon.com\\PROD1,53959;Initial Catalog=IRMNSPC;Integrated Security=True;", "DestinationDirectory": "L:/File-Watcher/Helper/InfinityQS", "SubGroupTime": 1727177147, "TestsFile": "L:/File-Watcher/Helper/InfinityQS/.json", diff --git a/.vscode/settings.json b/.vscode/settings.json index c40bf3b..a816981 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,7 @@ "cSpell.words": [ "ASPNETCORE", "BIRT", + "Camstar", "CHIL", "DEAT", "endianness", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4375b57..7d0e388 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -54,6 +54,16 @@ ], "problemMatcher": "$msCompile" }, + { + "label": "Format-Whitespaces", + "command": "dotnet", + "type": "process", + "args": [ + "format", + "whitespace" + ], + "problemMatcher": "$msCompile" + }, { "label": "Publish AOT", "command": "dotnet", diff --git a/File-Watcher.csproj b/File-Watcher.csproj index 0603b5d..d2f67d5 100644 --- a/File-Watcher.csproj +++ b/File-Watcher.csproj @@ -1,4 +1,4 @@ - + enable enable @@ -13,9 +13,11 @@ + + diff --git a/Helpers/HelperCamstarOracle.cs b/Helpers/HelperCamstarOracle.cs new file mode 100644 index 0000000..a33e0a2 --- /dev/null +++ b/Helpers/HelperCamstarOracle.cs @@ -0,0 +1,116 @@ +using File_Watcher.Infineon.Monitoring.MonA; +using File_Watcher.Models; +using System.Diagnostics; +using System.Globalization; + +namespace File_Watcher.Helpers; + +internal static partial class HelperCamstarOracle +{ + + private static IMonIn? _MonIn; + private static int? _LastValue; + private static Calendar? _Calendar; + private static DateTime? _LastUpload; + + internal static void Heartbeat(AppSettings appSettings, IHttpClientFactory httpClientFactory, ILogger logger, State state, CancellationToken cancellationToken) + { + _MonIn ??= MonIn.GetInstance(httpClientFactory); + CamstarOracleConfiguration camstarOracleConfiguration = appSettings.CamstarOracleConfiguration; + Task httpResponseMessage = _MonIn.SendStatus(camstarOracleConfiguration.MonitorApplicationSite, camstarOracleConfiguration.MonitorApplicationResource, "Heartbeat", state); + httpResponseMessage.Wait(cancellationToken); + if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) + throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); + Task body = httpResponseMessage.Result.Content.ReadAsStringAsync(cancellationToken); + body.Wait(cancellationToken); + logger.LogDebug(body.Result); + } + +#pragma warning disable CA1416 + + private static List GetOracleEventLogEntries(CamstarOracleConfiguration camstarOracleConfiguration, DateTime dateTime, CancellationToken cancellationToken) + { + List results = []; + EventLog[] eventLogs = EventLog.GetEventLogs(); + long ticks = dateTime.AddMinutes(-camstarOracleConfiguration.RollingMinutes).Ticks; + foreach (EventLog eventLog in eventLogs) + { + if (cancellationToken.IsCancellationRequested) + break; + if (!eventLog.Log.Contains(camstarOracleConfiguration.LogFilter)) + continue; + foreach (object? item in eventLog.Entries) + { + if (cancellationToken.IsCancellationRequested) + break; + if (item is not EventLogEntry eventLogEntry) + continue; + if (eventLogEntry.TimeGenerated.Ticks < ticks) + continue; + if (!camstarOracleConfiguration.MessageFilters.Any(eventLogEntry.Message.Contains)) + continue; + results.Add(eventLogEntry); + } + } + return results; + } + + private static List<(DateTime, string)> GetOracleEventLogEntryMessages(CamstarOracleConfiguration camstarOracleConfiguration, DateTime dateTime, CancellationToken cancellationToken) + { + List<(DateTime, string)> results = []; + List collection = GetOracleEventLogEntries(camstarOracleConfiguration, dateTime, cancellationToken); + foreach (EventLogEntry eventLogEntry in collection) + { + if (cancellationToken.IsCancellationRequested) + break; + results.Add(new(eventLogEntry.TimeGenerated, eventLogEntry.Message)); + } + return results; + } + + internal static bool Check(AppSettings appSettings, ILogger logger, CancellationToken cancellationToken) + { + if (_MonIn is null) + throw new NullReferenceException(nameof(_MonIn)); + string directory; + DateTime dateTime; + string weekOfYear; + string weekDirectory; + string formattedDateTime; + List lines = []; + _Calendar ??= new CultureInfo("en-US").Calendar; + CamstarOracleConfiguration camstarOracleConfiguration = appSettings.CamstarOracleConfiguration; + string performanceName = string.Concat(camstarOracleConfiguration.MonitorApplicationResource, "_Count"); + lines.Clear(); + dateTime = DateTime.Now; + weekOfYear = _Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00"); + weekDirectory = $"{dateTime:yyyy}_Week_{weekOfYear}{@"\"}{dateTime:yyyy-MM-dd}"; + directory = Path.Combine(camstarOracleConfiguration.Directory, weekDirectory); + if (!Directory.Exists(directory)) + _ = Directory.CreateDirectory(directory); + logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); + List<(DateTime, string)> collection = GetOracleEventLogEntryMessages(camstarOracleConfiguration, dateTime, cancellationToken); + foreach ((DateTime timeGenerated, string message) in collection) + { + if (cancellationToken.IsCancellationRequested) + break; + formattedDateTime = timeGenerated.ToString(camstarOracleConfiguration.DateFormat); + lines.Add($"{formattedDateTime}\t{message}"); + } + File.WriteAllLines(Path.Combine(directory, $"{dateTime.Ticks}.tsv"), lines); + if (_LastValue is null || _LastUpload is null || _LastValue.Value != lines.Count || new TimeSpan(dateTime.Ticks - _LastUpload.Value.Ticks).TotalMinutes > 5) + { + Task httpResponseMessage = _MonIn.SendPerformanceMessage(camstarOracleConfiguration.MonitorApplicationSite, camstarOracleConfiguration.MonitorApplicationResource, performanceName, value: lines.Count, description: string.Empty); + httpResponseMessage.Wait(cancellationToken); + if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) + throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); + Task body = httpResponseMessage.Result.Content.ReadAsStringAsync(cancellationToken); + body.Wait(cancellationToken); + logger.LogDebug(body.Result); + _LastUpload = DateTime.Now; + _LastValue = lines.Count; + } + return true; + } + +} \ No newline at end of file diff --git a/Helpers/HelperInfinityQS.cs b/Helpers/HelperInfinityQS.cs index 00d0963..606bce2 100644 --- a/Helpers/HelperInfinityQS.cs +++ b/Helpers/HelperInfinityQS.cs @@ -1,54 +1,11 @@ using File_Watcher.Models; -using System.Collections.ObjectModel; -using System.Data; -using System.Data.SqlClient; using System.Diagnostics; -using System.Text; -using System.Text.Json.Serialization; namespace File_Watcher.Helpers; internal static partial class HelperInfinityQS { - internal record Record([property: JsonPropertyName("count_se_sgtm")] int CountSeSubgroupTime, - [property: JsonPropertyName("date_time")] DateTime DateTime, - [property: JsonPropertyName("max_se_lot")] int MaxSeLot, - [property: JsonPropertyName("max_se_prcs")] int MaxSeProcess, - [property: JsonPropertyName("max_se_sgrp")] int MaxSeSubgroup, - [property: JsonPropertyName("max_se_test")] int MaxSeTest, - [property: JsonPropertyName("max_se_val")] float MaxSeValue, - [property: JsonPropertyName("min_se_sgrp")] int MinSeSubgroup, - [property: JsonPropertyName("test")] string Test); - - [JsonSourceGenerationOptions(WriteIndented = true)] - [JsonSerializable(typeof(Record[]))] - internal partial class RecordCollectionSourceGenerationContext : JsonSerializerContext - { - } - - private static string GetCommandText(ReadOnlyCollection subGroups) - { // cSpell:disable - List results = []; - results.Add(" update [spcepiworld].[dbo].[sgrp_ext] "); - results.Add(" set f_flag = 1 "); - results.Add(" where f_flag = 0 "); - results.Add($" and f_sgrp in ({string.Join(',', subGroups)}) "); - return string.Join(Environment.NewLine, results); - } // cSpell:enable - - private static StringBuilder GetForJsonPath(InfinityQSConfiguration infinityQSConfiguration, string commandText) - { - StringBuilder stringBuilder = new(); - using SqlConnection sqlConnection = new(infinityQSConfiguration.ConnectionString); - sqlConnection.Open(); - using SqlCommand sqlCommand = new(commandText, sqlConnection); - SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess); - while (sqlDataReader.Read()) - _ = stringBuilder.Append(sqlDataReader.GetString(0)); - return stringBuilder; - } - private static void RunMI() { #pragma warning disable CA1416 diff --git a/Infineon/Monitoring/MonA/IMonIn.cs b/Infineon/Monitoring/MonA/IMonIn.cs new file mode 100644 index 0000000..a5d91c4 --- /dev/null +++ b/Infineon/Monitoring/MonA/IMonIn.cs @@ -0,0 +1,145 @@ +namespace File_Watcher.Infineon.Monitoring.MonA; + +public interface IMonIn +{ + Task SendStatus(string site, string resource, string stateName, State state); + + Task SendStatus(string site, + DateTime timeStamp, + string resource, + string stateName, + State state); + + Task SendStatus(string site, + string resource, + string stateName, + State state, + string description); + + Task SendStatus(string site, + DateTime timeStamp, + string resource, + string stateName, + State state, + string description); + + Task SendStatus(string site, + string resource, + string subResource, + string stateName, + State state); + + Task SendStatus(string site, + DateTime timeStamp, + string resource, + string subResource, + string stateName, + State state); + + Task SendStatus(string site, + string resource, + string subResource, + string stateName, + State state, + string description); + + Task SendStatus(string site, + DateTime? timeStamp, + string resource, + string subResource, + string stateName, + State state, + string description); + + Task SendPerformanceMessage(string site, + string resource, + string performanceName, + double value); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value); + + Task SendPerformanceMessage(string site, + string resource, + string performanceName, + double value, + string description); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value, + string description); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value, + int? interval); + + Task SendPerformanceMessage(string site, + string resource, + DateTime? timeStamp, + string performanceName, + double value, + string unit); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value, + string unit, + int? interval); + + Task SendPerformanceMessage(string site, + string resource, + string subResource, + string performanceName, + double value); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value); + + Task SendPerformanceMessage(string site, + string resource, + string subResource, + string performanceName, + double value, + string description); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + int? interval); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + string unit); + + Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + string description, + string unit, + int? interval); +} \ No newline at end of file diff --git a/Infineon/Monitoring/MonA/MonIn.cs b/Infineon/Monitoring/MonA/MonIn.cs new file mode 100644 index 0000000..aed84e7 --- /dev/null +++ b/Infineon/Monitoring/MonA/MonIn.cs @@ -0,0 +1,266 @@ +using System.Globalization; +using System.Text; + +namespace File_Watcher.Infineon.Monitoring.MonA; + +public class MonIn : IMonIn +{ + private readonly string _MonInUrl; + private readonly HttpClient _HttpClient; + private static CultureInfo? _CultureInfo; + private static readonly Dictionary _Instances = []; + public const string MonInUrl = "http://moninhttp.{0}.infineon.com/input/text"; + private static readonly DateTime _Utc1970DateTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + public static MonIn GetInstance(IHttpClientFactory httpClientFactory, string url = MonInUrl) + { + MonIn instance; + if (_Instances.ContainsKey(url)) + { + instance = _Instances[url]; + } + else + { + lock (_Instances) + { + if (!_Instances.ContainsKey(url)) + { + instance = new MonIn(httpClientFactory, url); + _Instances.Add(url, instance); + } + else + instance = _Instances[url]; + } + } + return instance; + } + + private MonIn(IHttpClientFactory httpClientFactory, string url) + { + _MonInUrl = url; + _CultureInfo = new CultureInfo("en-US"); + _HttpClient = httpClientFactory.CreateClient(); + } + + public Task SendStatus(string site, string resource, string stateName, State state) => + SendStatus(site, new DateTime?(), resource, string.Empty, stateName, state, string.Empty); + + public Task SendStatus(string site, + DateTime timeStamp, + string resource, + string stateName, + State state) => + SendStatus(site, new DateTime?(timeStamp), resource, string.Empty, stateName, state, string.Empty); + + public Task SendStatus(string site, + string resource, + string stateName, + State state, + string description) => + SendStatus(site, new DateTime?(), resource, string.Empty, stateName, state, description); + + public Task SendStatus(string site, + DateTime timeStamp, + string resource, + string stateName, + State state, + string description) => + SendStatus(site, new DateTime?(timeStamp), resource, string.Empty, stateName, state, description); + + public Task SendStatus(string site, + string resource, + string subResource, + string stateName, + State state) => + SendStatus(site, new DateTime?(), resource, subResource, stateName, state, string.Empty); + + public Task SendStatus(string site, + DateTime timeStamp, + string resource, + string subResource, + string stateName, + State state) => + SendStatus(site, new DateTime?(timeStamp), resource, subResource, stateName, state, string.Empty); + + public Task SendStatus(string site, + string resource, + string subResource, + string stateName, + State state, + string description) => + SendStatus(site, new DateTime?(), resource, subResource, stateName, state, description); + + public Task SendStatus( + string site, + DateTime? timeStamp, + string resource, + string subResource, + string stateName, + State state, + string description) + { + string statusMessage = CreateStatusMessage(site, timeStamp, resource, subResource, stateName, state.ToString(), description); + StringContent stringContent = new(statusMessage, Encoding.UTF8, "application/text"); + lock (_HttpClient) + return _HttpClient.PostAsync(string.Format(_MonInUrl, site), stringContent); + } + + public Task SendPerformanceMessage(string site, + string resource, + string performanceName, + double value) => + SendPerformanceMessage(site, new DateTime?(), resource, string.Empty, performanceName, value, string.Empty, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value) => + SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + string resource, + string performanceName, + double value, + string description) => + SendPerformanceMessage(site, new DateTime?(), resource, string.Empty, performanceName, value, description, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value, + string description) => + SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, description, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value, + int? interval) => + SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, string.Empty, interval); + + public Task SendPerformanceMessage(string site, + string resource, + DateTime? timeStamp, + string performanceName, + double value, + string unit) => + SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, unit, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string performanceName, + double value, + string unit, + int? interval) => + SendPerformanceMessage(site, timeStamp, resource, string.Empty, performanceName, value, string.Empty, unit, interval); + + public Task SendPerformanceMessage(string site, + string resource, + string subResource, + string performanceName, + double value) => + SendPerformanceMessage(site, new DateTime?(), resource, subResource, performanceName, value, string.Empty, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value) => + SendPerformanceMessage(site, timeStamp, resource, subResource, performanceName, value, string.Empty, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + string resource, + string subResource, + string performanceName, + double value, + string description) => + SendPerformanceMessage(site, new DateTime?(), resource, subResource, performanceName, value, description, string.Empty, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + int? interval) => + SendPerformanceMessage(site, timeStamp, resource, subResource, performanceName, value, string.Empty, string.Empty, interval); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + string unit) => + SendPerformanceMessage(site, timeStamp, resource, subResource, performanceName, value, string.Empty, unit, new int?()); + + public Task SendPerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + string description, + string unit, + int? interval) + { + string performanceMessage = CreatePerformanceMessage(site, timeStamp, resource, subResource, performanceName, value, description, unit, interval); + StringContent stringContent = new(performanceMessage, Encoding.UTF8, "application/text"); + lock (_HttpClient) + return _HttpClient.PostAsync(string.Format(_MonInUrl, site), stringContent); + } + + private static string CreateStatusMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string stateName, + string state, + string description) + { + StringBuilder stringBuilder = new(); + if (string.IsNullOrEmpty(subResource)) + _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), stateName.Trim(), state.Trim(), description.Trim()); + else + _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subResource.Trim(), stateName.Trim(), state.Trim(), description.Trim()); + return stringBuilder.ToString(); + } + + private static string CreatePerformanceMessage(string site, + DateTime? timeStamp, + string resource, + string subResource, + string performanceName, + double value, + string description, + string unit, + int? interval) + { + StringBuilder stringBuilder = new(); + if (string.IsNullOrEmpty(subResource)) + { + if (unit.Equals(string.Empty) && !interval.HasValue) + _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} \n{5}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), performanceName.Trim(), value, description.Trim()); + else + _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" {4} {5} {{interval={6}, unit={7}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : (object)string.Empty, unit.Trim()); + } + else if (unit.Equals(string.Empty) && !interval.HasValue) + _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} \n{6}", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subResource.Trim(), performanceName.Trim(), value, description.Trim()); + else + _ = stringBuilder.AppendFormat(_CultureInfo, "> {0} {1} \"{2}\" \"{3}\" \"{4}\" {5} {6} {{interval={7}, unit={8}}}\n", site.Trim(), timeStamp.HasValue ? GetDateTimeNowAsPosix(timeStamp.Value) : (object)"now", resource.Trim(), subResource.Trim(), performanceName.Trim(), value, description.Trim(), interval.HasValue ? interval.Value.ToString() : (object)string.Empty, unit.Trim()); + return stringBuilder.ToString(); + } + + private static string GetDateTimeNowAsPosix(DateTime timeStamp) + { + if (timeStamp > DateTime.Now) + timeStamp = DateTime.Now; + return ((int)timeStamp.ToUniversalTime().Subtract(_Utc1970DateTime).TotalSeconds).ToString(CultureInfo.InvariantCulture); + } + +} \ No newline at end of file diff --git a/Infineon/Monitoring/MonA/State.cs b/Infineon/Monitoring/MonA/State.cs new file mode 100644 index 0000000..afba72e --- /dev/null +++ b/Infineon/Monitoring/MonA/State.cs @@ -0,0 +1,11 @@ +namespace File_Watcher.Infineon.Monitoring.MonA; + +public enum State +{ + Up, + Ok, + Warning, + Critical, + Down, + Unknown, +} \ No newline at end of file diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs index 50117ae..6fbe22e 100644 --- a/Models/AppSettings.cs +++ b/Models/AppSettings.cs @@ -3,7 +3,8 @@ using System.Text.Json.Serialization; namespace File_Watcher.Models; -public record AppSettings(CompassConfiguration CompassConfiguration, +public record AppSettings(CamstarOracleConfiguration CamstarOracleConfiguration, + CompassConfiguration CompassConfiguration, DriveConfiguration DriveConfiguration, EAFLogConfiguration EAFLogConfiguration, EDADatabaseConfiguration EDADatabaseConfiguration, diff --git a/Models/Binder/AppSettings.cs b/Models/Binder/AppSettings.cs index f504ee0..e49dc0e 100644 --- a/Models/Binder/AppSettings.cs +++ b/Models/Binder/AppSettings.cs @@ -44,6 +44,7 @@ public class AppSettings } private static Models.AppSettings Get(AppSettings? appSettings, + CamstarOracleConfiguration camstarOracleConfiguration, CompassConfiguration compassConfiguration, DriveConfiguration driveConfiguration, EAFLogConfiguration eafLogConfiguration, @@ -66,7 +67,8 @@ public class AppSettings if (appSettings.MillisecondsDelay is null) throw new NullReferenceException(nameof(MillisecondsDelay)); if (appSettings.WatchDirectory is null) throw new NullReferenceException(nameof(WatchDirectory)); Verify(appSettings); - result = new(compassConfiguration, + result = new(camstarOracleConfiguration, + compassConfiguration, driveConfiguration, eafLogConfiguration, edaDatabaseConfiguration, @@ -112,6 +114,7 @@ public class AppSettings results = (string.IsNullOrEmpty(json) ? null : results = JsonSerializer.Deserialize(json, AppSettingsSourceGenerationContext.Default.AppSettings)) ?? throw new NullReferenceException(nameof(Models.AppSettings)); results = Get(appSettings, + results.CamstarOracleConfiguration, results.CompassConfiguration, results.DriveConfiguration, results.EAFLogConfiguration, diff --git a/Models/CamstarOracleConfiguration.cs b/Models/CamstarOracleConfiguration.cs new file mode 100644 index 0000000..650686e --- /dev/null +++ b/Models/CamstarOracleConfiguration.cs @@ -0,0 +1,28 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace File_Watcher.Models; + +public record CamstarOracleConfiguration(string DateFormat, + string Directory, + string LogFilter, + string[] MessageFilters, + string MonitorApplicationResource, + string MonitorApplicationSite, + int MillisecondsDelay, + int RollingMinutes) +{ + + public override string ToString() + { + string result = JsonSerializer.Serialize(this, CamstarOracleConfigurationSourceGenerationContext.Default.CamstarOracleConfiguration); + return result; + } + +} + +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(CamstarOracleConfiguration))] +internal partial class CamstarOracleConfigurationSourceGenerationContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index d91295e..2d8bd32 100644 --- a/Program.cs +++ b/Program.cs @@ -20,6 +20,7 @@ public class Program try { List collection = []; + _ = webApplicationBuilder.Services.AddHttpClient(); _ = webApplicationBuilder.Services.AddHostedService(); _ = webApplicationBuilder.Services.AddSingleton(collection); _ = webApplicationBuilder.Services.AddSingleton(appSettings); diff --git a/Worker.cs b/Worker.cs index 28617b2..06ae561 100644 --- a/Worker.cs +++ b/Worker.cs @@ -7,24 +7,41 @@ namespace File_Watcher; public partial class Worker : BackgroundService { + private bool? _First; private readonly bool _IsWindowsService; private readonly ILogger _Logger; private readonly AppSettings _AppSettings; + private readonly IHttpClientFactory _HttpClientFactory; - public Worker(IServiceProvider serviceProvider, ILogger logger, AppSettings appSettings, List collection) + public override Task StopAsync(CancellationToken cancellationToken) + { + if (_AppSettings.Helper == nameof(Helpers.HelperCamstarOracle)) + Helpers.HelperCamstarOracle.Heartbeat(_AppSettings, _HttpClientFactory, _Logger, Infineon.Monitoring.MonA.State.Down, cancellationToken); + return base.StopAsync(cancellationToken); + } + + public Worker(IHttpClientFactory httpClientFactory, ILogger logger, IServiceProvider serviceProvider, AppSettings appSettings, List collection) { _Logger = logger; _AppSettings = appSettings; + _HttpClientFactory = httpClientFactory; logger.LogInformation("{buildNumber}-{gitCommitSeven}", _AppSettings.BuildNumber, _AppSettings.GitCommitSeven); try { logger.LogInformation("<{folder}>", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); } catch (Exception) { } + _First = null; _IsWindowsService = collection.Contains(nameof(WindowsServiceLifetime)); } private void BodyInner(CancellationToken cancellationToken) { _Logger.LogInformation("A) Next execute will be at {date}", DateTime.Now.AddMilliseconds(_AppSettings.MillisecondsDelay).ToString("yyyy-MM-dd hh:mm:ss.fff tt")); + if (_First is null || _First.Value) + { + _First = false; + if (_AppSettings.Helper == nameof(Helpers.HelperCamstarOracle)) + Helpers.HelperCamstarOracle.Heartbeat(_AppSettings, _HttpClientFactory, _Logger, Infineon.Monitoring.MonA.State.Up, cancellationToken); + } if (!Directory.Exists(_AppSettings.WatchDirectory)) _ = Directory.CreateDirectory(_AppSettings.WatchDirectory); else @@ -42,6 +59,7 @@ public partial class Worker : BackgroundService nameof(Helpers.HelperWaferCounter) => Helpers.HelperWaferCounter.MoveFile(_AppSettings, _Logger), nameof(Helpers.HelperSerial) => Helpers.HelperSerial.ReadWrite(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperMetrologyFiles) => Helpers.HelperMetrologyFiles.SortAndDelete(_AppSettings, _Logger), + nameof(Helpers.HelperCamstarOracle) => Helpers.HelperCamstarOracle.Check(_AppSettings, _Logger, cancellationToken), nameof(Helpers.HelperEDADatabase) => Helpers.HelperEDADatabase.SaveDataCollectionPlans(_AppSettings, _Logger, cancellationToken), _ => throw new NotSupportedException() };