using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Diagnostics; using Microsoft.Extensions.Logging; using App.Metrics; using AyaNova.Util; using AyaNova.Models; namespace AyaNova.Biz { /// /// called by Generator to gather server metrics and check on things /// See MetricsRegistry for defined metrics /// /// internal static class CoreJobMetricsSnapshot { private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobMetricsSnapshot"); #if (DEBUG) private static TimeSpan DO_EVERY_INTERVAL = new TimeSpan(0, 1, 0);//DEBUG do a check every 60 seconds #else private static TimeSpan DO_EVERY_INTERVAL = new TimeSpan(0, 15, 0);//RELEASE do a check every 15 minutes #endif private static DateTime lastServerCheckDone = DateTime.MinValue; private static DateTime lastRecordCountCheck = DateTime.MinValue; private static DateTime lastFileCountCheck = DateTime.MinValue; //////////////////////////////////////////////////////////////////////////////////////////////// // DoAsync // public static async Task DoJobAsync(AyContext ct) { //https://www.app-metrics.io/ IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics)); //This will get triggered roughly every minute (10 seconds in debug), but we don't want to healthcheck that frequently if (!DateUtil.IsAfterDuration(lastServerCheckDone, DO_EVERY_INTERVAL)) return; log.LogTrace("Starting metrics snapshot"); //Gather core metrics here var process = Process.GetCurrentProcess(); //PHYSICAL MEMORY metrics.Measure.Gauge.SetValue(MetricsRegistry.PhysicalMemoryGauge, process.WorkingSet64); //PRIVATE BYTES metrics.Measure.Gauge.SetValue(MetricsRegistry.PrivateBytesGauge, process.PrivateMemorySize64); //RECORDS IN TABLE //Only do this once per hour if (DateUtil.IsAfterDuration(lastRecordCountCheck, 1)) { lastRecordCountCheck = DateTime.UtcNow; log.LogTrace("Counting table records"); //Get a count of important tables in db List allTableNames = await DbUtil.GetAllTablenamesAsync(); //Skip some tables as they are internal and / or only ever have one record List skipTableNames = new List(); skipTableNames.Add("alicense"); skipTableNames.Add("aschemaversion"); foreach (string table in allTableNames) { if (!skipTableNames.Contains(table)) { var tags = new MetricTags("TableTagKey", table); metrics.Measure.Gauge.SetValue(MetricsRegistry.DBRecordsGauge, tags, await DbUtil.CountOfRecordsAsync(table)); } } } //JOB COUNTS (DEAD, RUNNING, COMPLETED, SLEEPING) foreach (JobStatus stat in Enum.GetValues(typeof(JobStatus))) { var jobtag = new MetricTags("JobStatus", stat.ToString()); metrics.Measure.Gauge.SetValue(MetricsRegistry.JobsGauge, jobtag, await JobsBiz.GetCountForJobStatusAsync(ct, stat)); } //FILES ON DISK //Only do this once per hour if (DateUtil.IsAfterDuration(lastFileCountCheck, 1)) { lastFileCountCheck = DateTime.UtcNow; log.LogTrace("Files on disk information"); var UtilFilesInfo = FileUtil.GetUtilityFolderSizeInfo(); var UserFilesInfo = FileUtil.GetAttachmentFolderSizeInfo(); var mtag = new MetricTags("File type", "Business object files"); metrics.Measure.Gauge.SetValue(MetricsRegistry.FileCountGauge, mtag, UserFilesInfo.FileCountWithChildren); metrics.Measure.Gauge.SetValue(MetricsRegistry.FileSizeGauge, mtag, UserFilesInfo.SizeWithChildren); mtag = new MetricTags("File type", "OPS files"); metrics.Measure.Gauge.SetValue(MetricsRegistry.FileCountGauge, mtag, UtilFilesInfo.FileCountWithChildren); metrics.Measure.Gauge.SetValue(MetricsRegistry.FileSizeGauge, mtag, UtilFilesInfo.SizeWithChildren); } lastServerCheckDone = DateTime.UtcNow; //just to hide compiler warning for now await Task.CompletedTask; } ///////////////////////////////////////////////////////////////////// }//eoc }//eons