diff --git a/devdocs/todo.txt b/devdocs/todo.txt index c8e990fc..e7011641 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -29,6 +29,7 @@ todo: (BREAK THIS OUT INTO LATER/NOW/CASES) there are several outstanding AUTHEN todo: Look into 2fa https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3395 todo: look into how to use an SSL certificate with the RAVEN server directly when not behind nginx + https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1 - this should be supported by default out of the box working with Let's encrypt ideally - is it now considered ok to host .net core web api directly internet facing? todo: onboarding and default manager account password diff --git a/server/AyaNova/AyaNova.csproj b/server/AyaNova/AyaNova.csproj index 2b35936f..183a2168 100644 --- a/server/AyaNova/AyaNova.csproj +++ b/server/AyaNova/AyaNova.csproj @@ -14,9 +14,7 @@ - - - + diff --git a/server/AyaNova/ControllerHelpers/ApiCustomExceptionFilter.cs b/server/AyaNova/ControllerHelpers/ApiCustomExceptionFilter.cs index 129a3798..349a33f9 100644 --- a/server/AyaNova/ControllerHelpers/ApiCustomExceptionFilter.cs +++ b/server/AyaNova/ControllerHelpers/ApiCustomExceptionFilter.cs @@ -7,7 +7,6 @@ using System.Net.Http; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Microsoft.Extensions.Logging; -using App.Metrics; using AyaNova.Util; using AyaNova.Biz; @@ -82,11 +81,6 @@ namespace AyaNova.Api.ControllerHelpers log.LogError(context.Exception, "Error"); - //Track this exception - IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics)); - metrics.Measure.Meter.Mark(MetricsRegistry.UnhandledExceptionsMeter, context.Exception.GetType().ToString()); - - HttpResponse response = context.HttpContext.Response; response.StatusCode = (int)status; response.ContentType = "application/json; charset=utf-8"; diff --git a/server/AyaNova/Controllers/AuthController.cs b/server/AyaNova/Controllers/AuthController.cs index 771373b1..25ba7360 100644 --- a/server/AyaNova/Controllers/AuthController.cs +++ b/server/AyaNova/Controllers/AuthController.cs @@ -8,7 +8,6 @@ using AyaNova.Api.ControllerHelpers; using System.Linq; using System; using System.Threading.Tasks; -using App.Metrics; using AyaNova.Biz; //required to inject configuration in constructor @@ -29,7 +28,6 @@ namespace AyaNova.Api.Controllers private readonly ILogger log; private readonly IConfiguration _configuration; private readonly ApiServerState serverState; - private readonly IMetrics metrics; private const int JWT_LIFETIME_DAYS = 7; /// @@ -38,15 +36,13 @@ namespace AyaNova.Api.Controllers /// /// /// - /// - /// - public AuthController(AyContext context, ILogger logger, IConfiguration configuration, ApiServerState apiServerState, IMetrics Metrics)//these two are injected, see startup.cs + /// + public AuthController(AyContext context, ILogger logger, IConfiguration configuration, ApiServerState apiServerState) { ct = context; log = logger; _configuration = configuration; serverState = apiServerState; - metrics = Metrics; } //AUTHENTICATE CREDS @@ -149,7 +145,6 @@ namespace AyaNova.Api.Controllers if (string.IsNullOrWhiteSpace(creds.Login) || string.IsNullOrWhiteSpace(creds.Password)) { - metrics.Measure.Meter.Mark(MetricsRegistry.FailedLoginMeter); //Make a failed pw wait await Task.Delay(nFailedAuthDelay); return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); @@ -214,7 +209,7 @@ namespace AyaNova.Api.Controllers await ct.SaveChangesAsync(); log.LogDebug($"User number \"{u.Id}\" logged in from \"{Util.StringUtil.MaskIPAddress(HttpContext.Connection.RemoteIpAddress.ToString())}\" ok"); - metrics.Measure.Meter.Mark(MetricsRegistry.SuccessfulLoginMeter); + return Ok(ApiOkResponse.Response(new { @@ -228,8 +223,7 @@ namespace AyaNova.Api.Controllers } //No users matched, it's a failed login - //Make a failed pw wait - metrics.Measure.Meter.Mark(MetricsRegistry.FailedLoginMeter); + //Make a failed pw wait await Task.Delay(nFailedAuthDelay); return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); } @@ -258,7 +252,6 @@ namespace AyaNova.Api.Controllers if (string.IsNullOrWhiteSpace(changecreds.OldPassword) || string.IsNullOrWhiteSpace(changecreds.LoginName)) { - metrics.Measure.Meter.Mark(MetricsRegistry.FailedLoginMeter); //Make a failed pw wait await Task.Delay(nFailedAuthDelay); return StatusCode(401, new ApiErrorResponse(ApiErrorCode.AUTHENTICATION_FAILED)); diff --git a/server/AyaNova/Controllers/MetricsController.cs b/server/AyaNova/Controllers/MetricsController.cs index 673b6d86..581a135c 100644 --- a/server/AyaNova/Controllers/MetricsController.cs +++ b/server/AyaNova/Controllers/MetricsController.cs @@ -1,128 +1,127 @@ -using System.IO; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; -using App.Metrics; -using AyaNova.Models; -using AyaNova.Api.ControllerHelpers; -using AyaNova.Biz; +// using System.IO; +// using System.Threading.Tasks; +// using Microsoft.AspNetCore.Http; +// using Microsoft.AspNetCore.Mvc; +// using Microsoft.AspNetCore.Routing; +// using Microsoft.AspNetCore.Authorization; +// using Microsoft.Extensions.Logging; +// using Newtonsoft.Json.Linq; + +// using AyaNova.Models; +// using AyaNova.Api.ControllerHelpers; +// using AyaNova.Biz; -namespace AyaNova.Api.Controllers -{ +// namespace AyaNova.Api.Controllers +// { - /// - /// Log files controller - /// - [ApiController] - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/metric")] - [Authorize] - public class MetricsController : ControllerBase - { - private readonly AyContext ct; - private readonly ILogger log; - private readonly ApiServerState serverState; - private readonly IMetrics metrics; +// /// +// /// Log files controller +// /// +// [ApiController] +// [ApiVersion("8.0")] +// [Route("api/v{version:apiVersion}/metric")] +// [Authorize] +// public class MetricsController : ControllerBase +// { +// private readonly AyContext ct; +// private readonly ILogger log; +// private readonly ApiServerState serverState; + - /// - /// ctor - /// - /// - /// - /// - /// - public MetricsController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState, IMetrics Metrics) - { - ct = dbcontext; - log = logger; - serverState = apiServerState; - metrics = Metrics; - } +// /// +// /// ctor +// /// +// /// +// /// +// /// + +// public MetricsController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) +// { +// ct = dbcontext; +// log = logger; +// serverState = apiServerState; +// } - /// - /// Get metrics as text document - /// - /// Snapshot of metrics - [HttpGet("textsnapshot")] - public async Task GetMetrics() - { - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); +// /// +// /// Get metrics as text document +// /// +// /// Snapshot of metrics +// [HttpGet("textsnapshot")] +// public async Task GetMetrics() +// { +// if (serverState.IsClosed) +// return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.Metrics)) - { - return StatusCode(403, new ApiNotAuthorizedResponse()); - } +// if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.Metrics)) +// { +// return StatusCode(403, new ApiNotAuthorizedResponse()); +// } - string sResult = await GetTheMetrics("plain"); +// string sResult = await GetTheMetrics("plain"); - //Log - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct); +// //Log +// await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct); - return Content(sResult); - } +// return Content(sResult); +// } - /// - /// Get metrics as json object - /// - /// Snapshot of metrics - [HttpGet("jsonsnapshot")] - public async Task GetJsonMetrics() - { - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); +// /// +// /// Get metrics as json object +// /// +// /// Snapshot of metrics +// [HttpGet("jsonsnapshot")] +// public async Task GetJsonMetrics() +// { +// if (serverState.IsClosed) +// return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.Metrics)) - { - return StatusCode(403, new ApiNotAuthorizedResponse()); - } +// if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.Metrics)) +// { +// return StatusCode(403, new ApiNotAuthorizedResponse()); +// } - string sResult = await GetTheMetrics("json"); - JObject json = JObject.Parse(sResult); +// string sResult = await GetTheMetrics("json"); +// JObject json = JObject.Parse(sResult); - //Log - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct); +// //Log +// await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.Metrics, AyaEvent.Retrieved), ct); - return Ok(ApiOkResponse.Response(json)); - } +// return Ok(ApiOkResponse.Response(json)); +// } - /// - /// Get the metrics snapshot - /// - /// Either "json" for json format or "plain" for plaintext format - /// - private async Task GetTheMetrics(string format) - { - var snapshot = metrics.Snapshot.Get(); +// /// +// /// Get the metrics snapshot +// /// +// /// Either "json" for json format or "plain" for plaintext format +// /// +// private async Task GetTheMetrics(string format) +// { +// var snapshot = metrics.Snapshot.Get(); - var formatters = ((IMetricsRoot)metrics).OutputMetricsFormatters; - string sResult = $"ERROR GETTING METRICS IN {format} FORMAT"; +// var formatters = ((IMetricsRoot)metrics).OutputMetricsFormatters; +// string sResult = $"ERROR GETTING METRICS IN {format} FORMAT"; - foreach (var formatter in formatters) - { - if (formatter.MediaType.Format == format) - { - using (var stream = new MemoryStream()) - { - await formatter.WriteAsync(stream, snapshot); - sResult = System.Text.Encoding.UTF8.GetString(stream.ToArray()); - } - } - } +// foreach (var formatter in formatters) +// { +// if (formatter.MediaType.Format == format) +// { +// using (var stream = new MemoryStream()) +// { +// await formatter.WriteAsync(stream, snapshot); +// sResult = System.Text.Encoding.UTF8.GetString(stream.ToArray()); +// } +// } +// } - return sResult; - } +// return sResult; +// } - //------------ +// //------------ - } -} \ No newline at end of file +// } +// } \ No newline at end of file diff --git a/server/AyaNova/Program.cs b/server/AyaNova/Program.cs index 89603dea..a21d0771 100644 --- a/server/AyaNova/Program.cs +++ b/server/AyaNova/Program.cs @@ -9,8 +9,6 @@ using Microsoft.Extensions.Logging; using NLog.Web; using NLog.Targets; using NLog.Config; -using App.Metrics; -using App.Metrics.AspNetCore; using AyaNova.Util; namespace AyaNova @@ -157,13 +155,13 @@ namespace AyaNova //This is the first log entry logger.Info($"AYANOVA SERVER {AyaNovaVersion.VersionString} BOOTING"); - + //log configuration try - { - var AyaNovaConfig=config.AsEnumerable().Where(z => z.Key.StartsWith("AYANOVA") && z.Key!="AYANOVA_JWT_SECRET").Select(z=>z.Key+ "="+ z.Value).ToList(); - var DiagConfig=string.Join(",", AyaNovaConfig); - DiagConfig=DbUtil.PasswordRedactedConnectionString(DiagConfig); + { + var AyaNovaConfig = config.AsEnumerable().Where(z => z.Key.StartsWith("AYANOVA") && z.Key != "AYANOVA_JWT_SECRET").Select(z => z.Key + "=" + z.Value).ToList(); + var DiagConfig = string.Join(",", AyaNovaConfig); + DiagConfig = DbUtil.PasswordRedactedConnectionString(DiagConfig); logger.Info($"Config {DiagConfig}"); } catch (Exception ex) @@ -172,9 +170,9 @@ namespace AyaNova } logger.Debug($"Full configuration is {config.GetDebugView()}"); - if (ServerBootConfig.AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG) + if (ServerBootConfig.AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG) logger.Warn("AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG is enabled, this will cause the server to run very slowly"); - + //Log environmental settings logger.Info("OS - {0}", Environment.OSVersion.ToString()); @@ -182,7 +180,7 @@ namespace AyaNova logger.Debug("User - {0}", Environment.UserName); logger.Debug(".Net Version - {0}", Environment.Version.ToString()); logger.Debug("CPU count - {0}", Environment.ProcessorCount); - + #endregion @@ -237,46 +235,7 @@ namespace AyaNova .UseSetting("detailedErrors", "true") .UseUrls(ServerBootConfig.AYANOVA_USE_URLS)//default port and urls, set first can be overridden by any later setting here .UseConfiguration(configuration)//support command line override of port (dotnet run urls=http://*:8081) - .UseIISIntegration()//support IIS integration just in case, it appears here to override prior settings if necessary (port) - .ConfigureMetricsWithDefaults(builder => - { - if (ServerBootConfig.AYANOVA_METRICS_USE_INFLUXDB) - { - builder.Report.ToInfluxDb( - options => - { - - options.InfluxDb.BaseUri = new Uri(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_BASEURL); - options.InfluxDb.Database = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_DBNAME; - if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY)) - { - options.InfluxDb.Consistenency = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY; - } - options.InfluxDb.UserName = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_USERNAME; - options.InfluxDb.Password = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_PASSWORD; - if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY)) - { - options.InfluxDb.RetentionPolicy = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY; - } - - options.InfluxDb.CreateDataBaseIfNotExists = true; - options.HttpPolicy.BackoffPeriod = TimeSpan.FromSeconds(30); - options.HttpPolicy.FailuresBeforeBackoff = 5; - options.HttpPolicy.Timeout = TimeSpan.FromSeconds(10); - //options.MetricsOutputFormatter = new App.Metrics.Formatters.Json.MetricsJsonOutputFormatter(); - //options.Filter = filter; - options.FlushInterval = TimeSpan.FromSeconds(20); - }); - } - - }) - .UseMetricsEndpoints(opt => - { - opt.EnvironmentInfoEndpointEnabled = false; - opt.MetricsEndpointEnabled = false; - opt.MetricsTextEndpointEnabled = false; - }) - .UseMetrics() + .UseIISIntegration()//support IIS integration just in case, it appears here to override prior settings if necessary (port) .UseStartup() .ConfigureLogging((context, logging) => { @@ -286,7 +245,7 @@ namespace AyaNova }) .UseNLog(); // NLog: setup NLog for Dependency injection }); - } + } }//eoc diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index 03cba693..76a8904e 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -101,10 +101,6 @@ namespace AyaNova services.AddHttpClient(); - //2019-10-17 METRICS will not work just yet with .netcore 3.1 see here https://github.com/AppMetrics/AppMetrics/issues/480 - //awaiting a new release from them - _newLog.LogDebug("Metrics"); - services.AddMetrics(); _newLog.LogDebug("Ensuring user and backup folders exist and are separate locations..."); FileUtil.EnsureUserAndUtilityFoldersExistAndAreNotIdentical(_hostingEnvironment.ContentRootPath); diff --git a/server/AyaNova/biz/JobsBiz.cs b/server/AyaNova/biz/JobsBiz.cs index db202394..6a645cfe 100644 --- a/server/AyaNova/biz/JobsBiz.cs +++ b/server/AyaNova/biz/JobsBiz.cs @@ -300,11 +300,7 @@ namespace AyaNova.Biz ActivelyProcessing = true; try { - //Flush metrics report before anything else happens - log.LogTrace("Flushing metrics to reporters"); - await CoreJobMetricsReport.DoJobAsync(); - - + //BIZOBJECT DYNAMIC JOBS //get a list of exclusive jobs that are due to happen //Call into each item in turn @@ -350,16 +346,9 @@ namespace AyaNova.Biz } } - - //STOCK JOBS - //Sweep jobs table - await CoreJobSweeper.DoSweepAsync(ct); - - //Health check / metrics - await CoreJobMetricsSnapshot.DoJobAsync(ct); - + await CoreJobSweeper.DoSweepAsync(ct); //License check long CurrentActiveCount = await UserBiz.ActiveCountAsync(); long LicensedUserCount = AyaNova.Core.License.ActiveKey.ActiveNumber; diff --git a/server/AyaNova/generator/CoreJobMetricsReport.cs b/server/AyaNova/generator/CoreJobMetricsReport.cs index 0a093fec..69f0fb96 100644 --- a/server/AyaNova/generator/CoreJobMetricsReport.cs +++ b/server/AyaNova/generator/CoreJobMetricsReport.cs @@ -1,54 +1,65 @@ -using System; -using System.Threading.Tasks; -using App.Metrics; -using AyaNova.Util; -using System.Linq; +// using System; +// using System.Threading.Tasks; +// using App.Metrics; +// using AyaNova.Util; +// using System.Linq; -namespace AyaNova.Biz -{ +// namespace AyaNova.Biz +// { - /// - /// called by Generator to flush metrics to reporter - /// - /// - internal static class CoreJobMetricsReport - { - private static TimeSpan DO_EVERY_INTERVAL = new TimeSpan(0, 0, 20);//FLUSH EVERY 20 SECONDS - private static DateTime lastReportFlushDone = DateTime.MinValue; +// /// +// /// called by Generator to flush metrics to reporter +// /// +// /// +// internal static class CoreJobMetricsReport +// { +// private static TimeSpan DO_EVERY_INTERVAL = new TimeSpan(0, 0, 20);//FLUSH EVERY 20 SECONDS +// private static DateTime lastReportFlushDone = DateTime.MinValue; - //////////////////////////////////////////////////////////////////////////////////////////////// - // DoAsync - // - public static async Task DoJobAsync() - { - //https://www.app-metrics.io/ - IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics)); - - //No more quickly than doeveryinterval - if (!DateUtil.IsAfterDuration(lastReportFlushDone, DO_EVERY_INTERVAL)) - return; - - //RUN ALL REPORTS - FLUSH STATS - var mr = (IMetricsRoot)metrics; - Task.WaitAll(mr.ReportRunner.RunAllAsync().ToArray()); +// //////////////////////////////////////////////////////////////////////////////////////////////// +// // DoAsync +// // +// public static async Task DoJobAsync() +// { +// //https://www.app-metrics.io/ +// IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics)); - lastReportFlushDone = DateTime.UtcNow; +// //No more quickly than doeveryinterval +// if (!DateUtil.IsAfterDuration(lastReportFlushDone, DO_EVERY_INTERVAL)) +// return; - //just to hide compiler warning for now - await Task.CompletedTask; +// //RUN ALL REPORTS - FLUSH STATS +// var mr = (IMetricsRoot)metrics; +// //Task.WaitAll(mr.ReportRunner.RunAllAsync().ToArray()); +// await Task.WhenAll(mr.ReportRunner.RunAllAsync()); - } +// lastReportFlushDone = DateTime.UtcNow; + +// //just to hide compiler warning for now +// // await Task.CompletedTask; + + +// // var scheduler = new AppMetricsTaskScheduler( +// // TimeSpan.FromSeconds(3), +// // async () => +// // { +// // await Task.WhenAll(metrics.ReportRunner.RunAllAsync()); +// // }); +// // scheduler.Start(); + + +// } - ///////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////// - }//eoc +// }//eoc -}//eons +// }//eons diff --git a/server/AyaNova/generator/CoreJobMetricsSnapshot.cs b/server/AyaNova/generator/CoreJobMetricsSnapshot.cs index 30e4b96c..fca38da7 100644 --- a/server/AyaNova/generator/CoreJobMetricsSnapshot.cs +++ b/server/AyaNova/generator/CoreJobMetricsSnapshot.cs @@ -1,132 +1,132 @@ -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; +// 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 -{ +// 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"); +// /// +// /// 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 +// #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; +// 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)); +// //////////////////////////////////////////////////////////////////////////////////////////////// +// // 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; +// //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"); +// log.LogTrace("Starting metrics snapshot"); - //Gather core metrics here - var process = Process.GetCurrentProcess(); +// //Gather core metrics here +// var process = Process.GetCurrentProcess(); - //PHYSICAL MEMORY - metrics.Measure.Gauge.SetValue(MetricsRegistry.PhysicalMemoryGauge, process.WorkingSet64); +// //PHYSICAL MEMORY +// metrics.Measure.Gauge.SetValue(MetricsRegistry.PhysicalMemoryGauge, process.WorkingSet64); - //PRIVATE BYTES - metrics.Measure.Gauge.SetValue(MetricsRegistry.PrivateBytesGauge, process.PrivateMemorySize64); +// //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"); +// //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(); +// //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"); +// //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)); - } - } - } +// 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) +// //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)); - } +// 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(); +// //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); +// 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); +// 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; +// lastServerCheckDone = DateTime.UtcNow; - //just to hide compiler warning for now - await Task.CompletedTask; +// //just to hide compiler warning for now +// await Task.CompletedTask; - } +// } - ///////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////// - }//eoc +// }//eoc -}//eons +// }//eons diff --git a/server/AyaNova/util/MetricsRegistry.cs b/server/AyaNova/util/MetricsRegistry.cs index 8a7f157b..9f16de3b 100644 --- a/server/AyaNova/util/MetricsRegistry.cs +++ b/server/AyaNova/util/MetricsRegistry.cs @@ -1,108 +1,108 @@ -using App.Metrics; -using App.Metrics.Counter; -using App.Metrics.Gauge; -using App.Metrics.Histogram; -using App.Metrics.ReservoirSampling.Uniform; -using App.Metrics.Meter; -using App.Metrics.Timer; -using App.Metrics.Apdex; -using App.Metrics.ReservoirSampling.ExponentialDecay; +// using App.Metrics; +// using App.Metrics.Counter; +// using App.Metrics.Gauge; +// using App.Metrics.Histogram; +// using App.Metrics.ReservoirSampling.Uniform; +// using App.Metrics.Meter; +// using App.Metrics.Timer; +// using App.Metrics.Apdex; +// using App.Metrics.ReservoirSampling.ExponentialDecay; -namespace AyaNova.Util -{ - /// - /// All metrics gathered by AyaNova are defined here - /// (except for endpoint ones gathered automatically by App.Metrics) - /// https://www.app-metrics.io - /// - public static class MetricsRegistry - { +// namespace AyaNova.Util +// { +// /// +// /// All metrics gathered by AyaNova are defined here +// /// (except for endpoint ones gathered automatically by App.Metrics) +// /// https://www.app-metrics.io +// /// +// public static class MetricsRegistry +// { - /// - /// Physical memory - /// Memory being used by this process (RAVEN) - /// - public static GaugeOptions PhysicalMemoryGauge = new GaugeOptions - { - Name = "Process Physical Memory", - MeasurementUnit = Unit.Bytes - }; +// /// +// /// Physical memory +// /// Memory being used by this process (RAVEN) +// /// +// public static GaugeOptions PhysicalMemoryGauge = new GaugeOptions +// { +// Name = "Process Physical Memory", +// MeasurementUnit = Unit.Bytes +// }; - /// - /// Private bytes - /// The current size, in bytes, of the committed memory owned by this process. - /// Memory leaks are identified by a consistent and prolonged increase in Private Bytes. - /// This is the best performance counter for detecting memory leaks. - /// - public static GaugeOptions PrivateBytesGauge = new GaugeOptions - { - Name = "Process Private Bytes", - MeasurementUnit = Unit.Bytes - }; +// /// +// /// Private bytes +// /// The current size, in bytes, of the committed memory owned by this process. +// /// Memory leaks are identified by a consistent and prolonged increase in Private Bytes. +// /// This is the best performance counter for detecting memory leaks. +// /// +// public static GaugeOptions PrivateBytesGauge = new GaugeOptions +// { +// Name = "Process Private Bytes", +// MeasurementUnit = Unit.Bytes +// }; - /// - /// Exceptions that are handled by the ApiCustomExceptionFilter - /// Basically any exception that is not normal and expected - /// - public static MeterOptions UnhandledExceptionsMeter => new MeterOptions - { - Name = "Exceptions Meter", - MeasurementUnit = Unit.Calls - }; +// /// +// /// Exceptions that are handled by the ApiCustomExceptionFilter +// /// Basically any exception that is not normal and expected +// /// +// public static MeterOptions UnhandledExceptionsMeter => new MeterOptions +// { +// Name = "Exceptions Meter", +// MeasurementUnit = Unit.Calls +// }; - /// - /// Login failed meter - /// - public static MeterOptions FailedLoginMeter => new MeterOptions - { - Name = "Failed Login Meter", - MeasurementUnit = Unit.Calls - }; +// /// +// /// Login failed meter +// /// +// public static MeterOptions FailedLoginMeter => new MeterOptions +// { +// Name = "Failed Login Meter", +// MeasurementUnit = Unit.Calls +// }; - /// - /// Login failed meter - /// - public static MeterOptions SuccessfulLoginMeter => new MeterOptions - { - Name = "Successful Login Meter", - MeasurementUnit = Unit.Calls - }; +// /// +// /// Login failed meter +// /// +// public static MeterOptions SuccessfulLoginMeter => new MeterOptions +// { +// Name = "Successful Login Meter", +// MeasurementUnit = Unit.Calls +// }; - /// - /// Records in db - /// - public static GaugeOptions DBRecordsGauge = new GaugeOptions - { - Name = "DB Records", - MeasurementUnit = Unit.Items - }; +// /// +// /// Records in db +// /// +// public static GaugeOptions DBRecordsGauge = new GaugeOptions +// { +// Name = "DB Records", +// MeasurementUnit = Unit.Items +// }; - /// - /// Jobs in db - /// - public static GaugeOptions JobsGauge = new GaugeOptions - { - Name = "Jobs", - MeasurementUnit = Unit.Items - }; +// /// +// /// Jobs in db +// /// +// public static GaugeOptions JobsGauge = new GaugeOptions +// { +// Name = "Jobs", +// MeasurementUnit = Unit.Items +// }; - /// - /// File count on disk - /// - public static GaugeOptions FileCountGauge = new GaugeOptions - { - Name = "File count", - MeasurementUnit = Unit.Items - }; +// /// +// /// File count on disk +// /// +// public static GaugeOptions FileCountGauge = new GaugeOptions +// { +// Name = "File count", +// MeasurementUnit = Unit.Items +// }; - /// - /// File size on disk - /// - public static GaugeOptions FileSizeGauge = new GaugeOptions - { - Name = "File size", - MeasurementUnit = Unit.Bytes - }; +// /// +// /// File size on disk +// /// +// public static GaugeOptions FileSizeGauge = new GaugeOptions +// { +// Name = "File size", +// MeasurementUnit = Unit.Bytes +// }; @@ -110,58 +110,58 @@ namespace AyaNova.Util - // ================================================================== - // /// - // /// - // /// - // public static GaugeOptions Errors => new GaugeOptions - // { - // Context = "My_Gauge_context", - // Name = "Errors" - // }; +// // ================================================================== +// // /// +// // /// +// // /// +// // public static GaugeOptions Errors => new GaugeOptions +// // { +// // Context = "My_Gauge_context", +// // Name = "Errors" +// // }; - // /// - // /// - // /// - // public static HistogramOptions SampleHistogram => new HistogramOptions - // { - // Name = "Sample Histogram", - // Reservoir = () => new DefaultAlgorithmRReservoir(), - // MeasurementUnit = Unit.MegaBytes - // }; +// // /// +// // /// +// // /// +// // public static HistogramOptions SampleHistogram => new HistogramOptions +// // { +// // Name = "Sample Histogram", +// // Reservoir = () => new DefaultAlgorithmRReservoir(), +// // MeasurementUnit = Unit.MegaBytes +// // }; - // /// - // /// - // /// - // public static MeterOptions SampleMeter => new MeterOptions - // { - // Name = "Sample Meter", - // MeasurementUnit = Unit.Calls - // }; +// // /// +// // /// +// // /// +// // public static MeterOptions SampleMeter => new MeterOptions +// // { +// // Name = "Sample Meter", +// // MeasurementUnit = Unit.Calls +// // }; - // /// - // /// - // /// - // public static TimerOptions SampleTimer => new TimerOptions - // { - // Name = "Sample Timer", - // MeasurementUnit = Unit.Items, - // DurationUnit = TimeUnit.Milliseconds, - // RateUnit = TimeUnit.Milliseconds, - // Reservoir = () => new DefaultForwardDecayingReservoir(sampleSize: 1028, alpha: 0.015) - // }; +// // /// +// // /// +// // /// +// // public static TimerOptions SampleTimer => new TimerOptions +// // { +// // Name = "Sample Timer", +// // MeasurementUnit = Unit.Items, +// // DurationUnit = TimeUnit.Milliseconds, +// // RateUnit = TimeUnit.Milliseconds, +// // Reservoir = () => new DefaultForwardDecayingReservoir(sampleSize: 1028, alpha: 0.015) +// // }; - // /// - // /// - // /// - // public static ApdexOptions SampleApdex => new ApdexOptions - // { - // Name = "Sample Apdex" - // }; +// // /// +// // /// +// // /// +// // public static ApdexOptions SampleApdex => new ApdexOptions +// // { +// // Name = "Sample Apdex" +// // }; - } -} +// } +// } diff --git a/server/AyaNova/util/ServerBootConfig.cs b/server/AyaNova/util/ServerBootConfig.cs index 41bd5d98..0fc58474 100644 --- a/server/AyaNova/util/ServerBootConfig.cs +++ b/server/AyaNova/util/ServerBootConfig.cs @@ -51,17 +51,7 @@ namespace AyaNova.Util internal static string AYANOVA_LOG_LEVEL { get; set; } internal static bool AYANOVA_LOG_ENABLE_LOGGER_DIAGNOSTIC_LOG { get; set; } - - - //METRICS - internal static bool AYANOVA_METRICS_USE_INFLUXDB { get; set; } - internal static string AYANOVA_METRICS_INFLUXDB_BASEURL { get; set; } - internal static string AYANOVA_METRICS_INFLUXDB_DBNAME { get; set; } - internal static string AYANOVA_METRICS_INFLUXDB_CONSISTENCY { get; set; } - internal static string AYANOVA_METRICS_INFLUXDB_USERNAME { get; set; } - internal static string AYANOVA_METRICS_INFLUXDB_PASSWORD { get; set; } - internal static string AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY { get; set; } - internal static bool AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS { get; set; } + /// /// Populate the config from the configuration found at boot @@ -168,32 +158,7 @@ namespace AyaNova.Util #endregion server BASICS - #region METRICS - //InfluxDB - bTemp = config.GetValue("AYANOVA_METRICS_USE_INFLUXDB"); - AYANOVA_METRICS_USE_INFLUXDB = (null == bTemp) ? false : (bool)bTemp; - - AYANOVA_METRICS_INFLUXDB_BASEURL = config.GetValue("AYANOVA_METRICS_INFLUXDB_BASEURL"); - AYANOVA_METRICS_INFLUXDB_BASEURL = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_BASEURL) ? "http://127.0.0.1:8086" : AYANOVA_METRICS_INFLUXDB_BASEURL; - - AYANOVA_METRICS_INFLUXDB_DBNAME = config.GetValue("AYANOVA_METRICS_INFLUXDB_DBNAME"); - AYANOVA_METRICS_INFLUXDB_DBNAME = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_DBNAME) ? "AyaNova" : AYANOVA_METRICS_INFLUXDB_DBNAME; - - AYANOVA_METRICS_INFLUXDB_CONSISTENCY = config.GetValue("AYANOVA_METRICS_INFLUXDB_CONSISTENCY"); - //No default value, if it's null or empty or whitespace then it won't be set - - AYANOVA_METRICS_INFLUXDB_USERNAME = config.GetValue("AYANOVA_METRICS_INFLUXDB_USERNAME"); - AYANOVA_METRICS_INFLUXDB_USERNAME = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_USERNAME) ? "root" : AYANOVA_METRICS_INFLUXDB_USERNAME; - - AYANOVA_METRICS_INFLUXDB_PASSWORD = config.GetValue("AYANOVA_METRICS_INFLUXDB_PASSWORD"); - AYANOVA_METRICS_INFLUXDB_PASSWORD = string.IsNullOrWhiteSpace(AYANOVA_METRICS_INFLUXDB_PASSWORD) ? "root" : AYANOVA_METRICS_INFLUXDB_PASSWORD; - - AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY = config.GetValue("AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY"); - //No default value, if it's null or empty or whitespace then it won't be set - - bTemp = config.GetValue("AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS"); - AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS = (null == bTemp) ? true : (bool)bTemp; - #endregion + }