Ditched app.metrics

This commit is contained in:
2020-05-24 21:51:03 +00:00
parent f0153eaa0f
commit c2f6fd94c1
12 changed files with 404 additions and 499 deletions

View File

@@ -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

View File

@@ -14,9 +14,7 @@
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="App.Metrics.AspNetCore.Mvc" Version="3.2.0-dev0002" />
<PackageReference Include="App.Metrics.Reporting.InfluxDB" Version="3.2.0-dev0002" />
<ItemGroup>
<PackageReference Include="Bogus" Version="28.4.1" />
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.5" />
<PackageReference Include="Enums.NET" Version="3.0.2" />

View File

@@ -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";

View File

@@ -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<AuthController> log;
private readonly IConfiguration _configuration;
private readonly ApiServerState serverState;
private readonly IMetrics metrics;
private const int JWT_LIFETIME_DAYS = 7;
/// <summary>
@@ -38,15 +36,13 @@ namespace AyaNova.Api.Controllers
/// <param name="context"></param>
/// <param name="logger"></param>
/// <param name="configuration"></param>
/// <param name="apiServerState"></param>
/// <param name="Metrics"></param>
public AuthController(AyContext context, ILogger<AuthController> logger, IConfiguration configuration, ApiServerState apiServerState, IMetrics Metrics)//these two are injected, see startup.cs
/// <param name="apiServerState"></param>
public AuthController(AyContext context, ILogger<AuthController> 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));

View File

@@ -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
// {
/// <summary>
/// Log files controller
/// </summary>
[ApiController]
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/metric")]
[Authorize]
public class MetricsController : ControllerBase
{
private readonly AyContext ct;
private readonly ILogger<LogFilesController> log;
private readonly ApiServerState serverState;
private readonly IMetrics metrics;
// /// <summary>
// /// Log files controller
// /// </summary>
// [ApiController]
// [ApiVersion("8.0")]
// [Route("api/v{version:apiVersion}/metric")]
// [Authorize]
// public class MetricsController : ControllerBase
// {
// private readonly AyContext ct;
// private readonly ILogger<LogFilesController> log;
// private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
/// <param name="Metrics"></param>
public MetricsController(AyContext dbcontext, ILogger<LogFilesController> logger, ApiServerState apiServerState, IMetrics Metrics)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
metrics = Metrics;
}
// /// <summary>
// /// ctor
// /// </summary>
// /// <param name="dbcontext"></param>
// /// <param name="logger"></param>
// /// <param name="apiServerState"></param>
// public MetricsController(AyContext dbcontext, ILogger<LogFilesController> logger, ApiServerState apiServerState)
// {
// ct = dbcontext;
// log = logger;
// serverState = apiServerState;
// }
/// <summary>
/// Get metrics as text document
/// </summary>
/// <returns>Snapshot of metrics</returns>
[HttpGet("textsnapshot")]
public async Task<IActionResult> GetMetrics()
{
if (serverState.IsClosed)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
// /// <summary>
// /// Get metrics as text document
// /// </summary>
// /// <returns>Snapshot of metrics</returns>
// [HttpGet("textsnapshot")]
// public async Task<IActionResult> 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);
// }
/// <summary>
/// Get metrics as json object
/// </summary>
/// <returns>Snapshot of metrics</returns>
[HttpGet("jsonsnapshot")]
public async Task<IActionResult> GetJsonMetrics()
{
if (serverState.IsClosed)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
// /// <summary>
// /// Get metrics as json object
// /// </summary>
// /// <returns>Snapshot of metrics</returns>
// [HttpGet("jsonsnapshot")]
// public async Task<IActionResult> 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));
// }
/// <summary>
/// Get the metrics snapshot
/// </summary>
/// <param name="format">Either "json" for json format or "plain" for plaintext format</param>
/// <returns></returns>
private async Task<string> GetTheMetrics(string format)
{
var snapshot = metrics.Snapshot.Get();
// /// <summary>
// /// Get the metrics snapshot
// /// </summary>
// /// <param name="format">Either "json" for json format or "plain" for plaintext format</param>
// /// <returns></returns>
// private async Task<string> 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;
// }
//------------
// //------------
}
}
// }
// }

View File

@@ -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<Startup>()
.ConfigureLogging((context, logging) =>
{
@@ -286,7 +245,7 @@ namespace AyaNova
})
.UseNLog(); // NLog: setup NLog for Dependency injection
});
}
}
}//eoc

View File

@@ -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);

View File

@@ -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;

View File

@@ -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
// {
/// <summary>
/// called by Generator to flush metrics to reporter
///
/// </summary>
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;
// /// <summary>
// /// called by Generator to flush metrics to reporter
// ///
// /// </summary>
// 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

View File

@@ -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
// {
/// <summary>
/// called by Generator to gather server metrics and check on things
/// See MetricsRegistry for defined metrics
///
/// </summary>
internal static class CoreJobMetricsSnapshot
{
private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobMetricsSnapshot");
// /// <summary>
// /// called by Generator to gather server metrics and check on things
// /// See MetricsRegistry for defined metrics
// ///
// /// </summary>
// 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<string> allTableNames = await DbUtil.GetAllTablenamesAsync();
// //Get a count of important tables in db
// List<string> allTableNames = await DbUtil.GetAllTablenamesAsync();
//Skip some tables as they are internal and / or only ever have one record
List<string> skipTableNames = new List<string>();
skipTableNames.Add("alicense");
skipTableNames.Add("aschemaversion");
// //Skip some tables as they are internal and / or only ever have one record
// List<string> skipTableNames = new List<string>();
// 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

View File

@@ -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
{
/// <summary>
/// All metrics gathered by AyaNova are defined here
/// (except for endpoint ones gathered automatically by App.Metrics)
/// https://www.app-metrics.io
/// </summary>
public static class MetricsRegistry
{
// namespace AyaNova.Util
// {
// /// <summary>
// /// All metrics gathered by AyaNova are defined here
// /// (except for endpoint ones gathered automatically by App.Metrics)
// /// https://www.app-metrics.io
// /// </summary>
// public static class MetricsRegistry
// {
/// <summary>
/// Physical memory
/// Memory being used by this process (RAVEN)
/// </summary>
public static GaugeOptions PhysicalMemoryGauge = new GaugeOptions
{
Name = "Process Physical Memory",
MeasurementUnit = Unit.Bytes
};
// /// <summary>
// /// Physical memory
// /// Memory being used by this process (RAVEN)
// /// </summary>
// public static GaugeOptions PhysicalMemoryGauge = new GaugeOptions
// {
// Name = "Process Physical Memory",
// MeasurementUnit = Unit.Bytes
// };
/// <summary>
/// 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.
/// </summary>
public static GaugeOptions PrivateBytesGauge = new GaugeOptions
{
Name = "Process Private Bytes",
MeasurementUnit = Unit.Bytes
};
// /// <summary>
// /// 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.
// /// </summary>
// public static GaugeOptions PrivateBytesGauge = new GaugeOptions
// {
// Name = "Process Private Bytes",
// MeasurementUnit = Unit.Bytes
// };
/// <summary>
/// Exceptions that are handled by the ApiCustomExceptionFilter
/// Basically any exception that is not normal and expected
/// </summary>
public static MeterOptions UnhandledExceptionsMeter => new MeterOptions
{
Name = "Exceptions Meter",
MeasurementUnit = Unit.Calls
};
// /// <summary>
// /// Exceptions that are handled by the ApiCustomExceptionFilter
// /// Basically any exception that is not normal and expected
// /// </summary>
// public static MeterOptions UnhandledExceptionsMeter => new MeterOptions
// {
// Name = "Exceptions Meter",
// MeasurementUnit = Unit.Calls
// };
/// <summary>
/// Login failed meter
/// </summary>
public static MeterOptions FailedLoginMeter => new MeterOptions
{
Name = "Failed Login Meter",
MeasurementUnit = Unit.Calls
};
// /// <summary>
// /// Login failed meter
// /// </summary>
// public static MeterOptions FailedLoginMeter => new MeterOptions
// {
// Name = "Failed Login Meter",
// MeasurementUnit = Unit.Calls
// };
/// <summary>
/// Login failed meter
/// </summary>
public static MeterOptions SuccessfulLoginMeter => new MeterOptions
{
Name = "Successful Login Meter",
MeasurementUnit = Unit.Calls
};
// /// <summary>
// /// Login failed meter
// /// </summary>
// public static MeterOptions SuccessfulLoginMeter => new MeterOptions
// {
// Name = "Successful Login Meter",
// MeasurementUnit = Unit.Calls
// };
/// <summary>
/// Records in db
/// </summary>
public static GaugeOptions DBRecordsGauge = new GaugeOptions
{
Name = "DB Records",
MeasurementUnit = Unit.Items
};
// /// <summary>
// /// Records in db
// /// </summary>
// public static GaugeOptions DBRecordsGauge = new GaugeOptions
// {
// Name = "DB Records",
// MeasurementUnit = Unit.Items
// };
/// <summary>
/// Jobs in db
/// </summary>
public static GaugeOptions JobsGauge = new GaugeOptions
{
Name = "Jobs",
MeasurementUnit = Unit.Items
};
// /// <summary>
// /// Jobs in db
// /// </summary>
// public static GaugeOptions JobsGauge = new GaugeOptions
// {
// Name = "Jobs",
// MeasurementUnit = Unit.Items
// };
/// <summary>
/// File count on disk
/// </summary>
public static GaugeOptions FileCountGauge = new GaugeOptions
{
Name = "File count",
MeasurementUnit = Unit.Items
};
// /// <summary>
// /// File count on disk
// /// </summary>
// public static GaugeOptions FileCountGauge = new GaugeOptions
// {
// Name = "File count",
// MeasurementUnit = Unit.Items
// };
/// <summary>
/// File size on disk
/// </summary>
public static GaugeOptions FileSizeGauge = new GaugeOptions
{
Name = "File size",
MeasurementUnit = Unit.Bytes
};
// /// <summary>
// /// File size on disk
// /// </summary>
// public static GaugeOptions FileSizeGauge = new GaugeOptions
// {
// Name = "File size",
// MeasurementUnit = Unit.Bytes
// };
@@ -110,58 +110,58 @@ namespace AyaNova.Util
// ==================================================================
// /// <summary>
// ///
// /// </summary>
// public static GaugeOptions Errors => new GaugeOptions
// {
// Context = "My_Gauge_context",
// Name = "Errors"
// };
// // ==================================================================
// // /// <summary>
// // ///
// // /// </summary>
// // public static GaugeOptions Errors => new GaugeOptions
// // {
// // Context = "My_Gauge_context",
// // Name = "Errors"
// // };
// /// <summary>
// ///
// /// </summary>
// public static HistogramOptions SampleHistogram => new HistogramOptions
// {
// Name = "Sample Histogram",
// Reservoir = () => new DefaultAlgorithmRReservoir(),
// MeasurementUnit = Unit.MegaBytes
// };
// // /// <summary>
// // ///
// // /// </summary>
// // public static HistogramOptions SampleHistogram => new HistogramOptions
// // {
// // Name = "Sample Histogram",
// // Reservoir = () => new DefaultAlgorithmRReservoir(),
// // MeasurementUnit = Unit.MegaBytes
// // };
// /// <summary>
// ///
// /// </summary>
// public static MeterOptions SampleMeter => new MeterOptions
// {
// Name = "Sample Meter",
// MeasurementUnit = Unit.Calls
// };
// // /// <summary>
// // ///
// // /// </summary>
// // public static MeterOptions SampleMeter => new MeterOptions
// // {
// // Name = "Sample Meter",
// // MeasurementUnit = Unit.Calls
// // };
// /// <summary>
// ///
// /// </summary>
// 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)
// };
// // /// <summary>
// // ///
// // /// </summary>
// // 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)
// // };
// /// <summary>
// ///
// /// </summary>
// public static ApdexOptions SampleApdex => new ApdexOptions
// {
// Name = "Sample Apdex"
// };
// // /// <summary>
// // ///
// // /// </summary>
// // public static ApdexOptions SampleApdex => new ApdexOptions
// // {
// // Name = "Sample Apdex"
// // };
}
}
// }
// }

View File

@@ -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; }
/// <summary>
/// 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<bool?>("AYANOVA_METRICS_USE_INFLUXDB");
AYANOVA_METRICS_USE_INFLUXDB = (null == bTemp) ? false : (bool)bTemp;
AYANOVA_METRICS_INFLUXDB_BASEURL = config.GetValue<string>("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<string>("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<string>("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<string>("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<string>("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<string>("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<bool?>("AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS");
AYANOVA_METRICS_INFLUXDB_CREATE_DATABASE_IF_NOT_EXISTS = (null == bTemp) ? true : (bool)bTemp;
#endregion
}