Files
sockeye/server/generator/CoreJobMetricsSnapshot.cs
2022-12-16 06:01:23 +00:00

191 lines
8.0 KiB
C#

using System;
using System.Linq;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Sockeye.Util;
using Sockeye.Models;
using Microsoft.EntityFrameworkCore;
//using StackExchange.Profiling;
namespace Sockeye.Biz
{
/// <summary>
/// called by Generator to gather server metrics and insert in db
/// </summary>
internal static class CoreJobMetricsSnapshot
{
private static ILogger log = Sockeye.Util.ApplicationLogging.CreateLogger("CoreJobMetricsSnapshot");
private static TimeSpan tsDataRetention = new TimeSpan(365, 0, 0, 0, 0);//one year
private static Process _process = Process.GetCurrentProcess();
private static TimeSpan _oldCPUTime = TimeSpan.Zero;
private static DateTime _lastMMSnapshot = DateTime.UtcNow.Subtract(new TimeSpan(1, 1, 1, 1, 1));//ensure it captures on a fresh boot;
private static DateTime _lastDDSnapshot = DateTime.UtcNow.Subtract(new TimeSpan(1, 1, 1, 1, 1));//ensure it captures on a fresh boot;
private static double _cpu = 0;
#if (DEBUG)
private static TimeSpan tsMMFrequency = new TimeSpan(0, 5, 0);
private static TimeSpan tsDDFrequency = new TimeSpan(24, 0, 0);
#else
private static TimeSpan tsMMFrequency = new TimeSpan(0, 5, 0);
private static TimeSpan tsDDFrequency = new TimeSpan(24, 0, 0);//changed to 12 hours from 24 due to weird issue not gathering like it should diagnosis
#endif
////////////////////////////////////////////////////////////////////////////////////////////////
//
//
public static void DoWork()
{
if (DateUtil.IsAfterDuration(_lastMMSnapshot, tsMMFrequency))
{
/////////////////////////////////////////////
//ONE MINUTE SNAPS
//
log.LogDebug("MM metrics snapshot");
var now = DateTime.UtcNow;
_process.Refresh();
//CPU
var cpuElapsedTime = now.Subtract(_lastMMSnapshot).TotalMilliseconds;
var newCPUTime = _process.TotalProcessorTime;
var elapsedCPU = (newCPUTime - _oldCPUTime).TotalMilliseconds;
_cpu = elapsedCPU * 100 / Environment.ProcessorCount / cpuElapsedTime;
_oldCPUTime = newCPUTime;
//MEMORY
// The memory occupied by objects.
var Allocated = GC.GetTotalMemory(false);//bigint
// The working set includes both shared and private data. The shared data includes the pages that contain all the
// instructions that the process executes, including instructions in the process modules and the system libraries.
var WorkingSet = _process.WorkingSet64;//bigint
// The value returned by this property represents the current size of memory used by the process, in bytes, that
// cannot be shared with other processes.
var PrivateBytes = _process.PrivateMemorySize64;//bigint
//NOTE: CPU percentage is *our* process cpu percentage over timeframe of last captured avg
//So it does *not* show the entire server cpu load, only for RAVEN.
//Overall, server stats need to be captured / viewed independently (digital ocean control panel for example or windows task manager)
var CPU = _cpu;// double precision
//In some cases the first snapshot taken after a reboot
//is a huge number way beyond 100 which fucks up the charts
//likely due to the algorithm above and new values but not worth looking into atm
if (CPU > 100)
{
CPU = 0;
}
using (AyContext ct = ServiceProviderProvider.DBContext)
{
//write to db
MetricMM mm = new MetricMM(Allocated, WorkingSet, PrivateBytes, CPU);
ct.MetricMM.Add(mm);
ct.SaveChanges();
}
_lastMMSnapshot = now;
}
/////////////////////////////////////////////
//ONCE A DAY SNAPS AND CLEANUP
//
if (DateUtil.IsAfterDuration(_lastDDSnapshot, tsDDFrequency))
{
#if (DEBUG)
log.LogInformation($"DD metrics snapshot, _lastDDSnapshot:{_lastDDSnapshot}, tsDDFrequency:{tsDDFrequency}");
#endif
log.LogDebug("DD metrics snapshot");
var now = DateTime.UtcNow;
//FILES ON DISK
var UtilFilesInfo = FileUtil.GetBackupFolderSizeInfo();
var AttachmentFilesInfo = FileUtil.GetAttachmentFolderSizeInfo();
//Available space
long UtilityFilesAvailableSpace = 0;
try
{
UtilityFilesAvailableSpace = FileUtil.BackupFilesDriveAvailableSpace();
}
catch (Exception ex)
{
log.LogError(ex, "Metrics::FileUtil::UtilityFilesDriveAvailableSpace error getting available space");
}
long AttachmentFilesAvailableSpace = 0;
try
{
AttachmentFilesAvailableSpace = FileUtil.AttachmentFilesDriveAvailableSpace();
}
catch (Exception ex)
{
log.LogError(ex, "Metrics::FileUtil::AttachmentFilesDriveAvailableSpace error getting available space");
}
using (AyContext ct = ServiceProviderProvider.DBContext)
{
//DB total size
long DBTotalSize = 0;
using (var command = ct.Database.GetDbConnection().CreateCommand())
{
command.CommandText = "select pg_database_size(current_database());";
ct.Database.OpenConnection();
using (var dr = command.ExecuteReader())
{
if (dr.HasRows)
{
DBTotalSize = dr.Read() ? dr.GetInt64(0) : 0;
}
ct.Database.CloseConnection();
}
}
//write to db
MetricDD dd = new MetricDD()
{
AttachmentFileSize = AttachmentFilesInfo.SizeWithChildren,
AttachmentFileCount = AttachmentFilesInfo.FileCountWithChildren,
AttachmentFilesAvailableSpace = AttachmentFilesAvailableSpace,
UtilityFileSize = UtilFilesInfo.SizeWithChildren,
UtilityFileCount = UtilFilesInfo.FileCountWithChildren,
UtilityFilesAvailableSpace = UtilityFilesAvailableSpace,
DBTotalSize = DBTotalSize
};
ct.MetricDD.Add(dd);
ct.SaveChanges();
}
/////////////////////////////////
//CLEAR OLD ENTRIES
//
DateTime ClearDate = DateTime.UtcNow - tsDataRetention;
using (AyContext ct = ServiceProviderProvider.DBContext)
{
ct.Database.ExecuteSqlInterpolated($"delete from ametricmm where t < {ClearDate.ToUniversalTime()}");
ct.Database.ExecuteSqlInterpolated($"delete from ametricdd where t < {ClearDate.ToUniversalTime()}");
}
_lastDDSnapshot = now;
}
//----
}
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons