Skip to content
Snippets Groups Projects
Commit de81291b authored by Niko Ehrenfeuchter's avatar Niko Ehrenfeuchter :keyboard:
Browse files

Merge branch 'feature/startup-healthreport'

parents c41bef33 1b4af9fe
No related branches found
No related tags found
No related merge requests found
......@@ -17,6 +17,8 @@ namespace ATxCommon.Serializables
{
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
private string _healthReportEmailAddress;
#region required configuration parameters
......@@ -200,6 +202,20 @@ namespace ATxCommon.Serializables
/// </summary>
public string AdminDebugEmailAddress { get; set; }
/// <summary>
/// The mail recipient address for system health reports, falling back to AdminEmailAddress
/// in case it is not set explicitly.
/// </summary>
public string HealthReportEmailAddress {
get {
if (string.IsNullOrEmpty(_healthReportEmailAddress))
return AdminEmailAddress;
return _healthReportEmailAddress;
}
set => _healthReportEmailAddress = value;
}
/// <summary>
/// Send an email to the user upon completed transfers. Default: true.
/// </summary>
......@@ -561,6 +577,7 @@ namespace ATxCommon.Serializables
$"EmailPrefix: {EmailPrefix}\n" +
$"AdminEmailAddress: {AdminEmailAddress}\n" +
$"AdminDebugEmailAddress: {AdminDebugEmailAddress}\n" +
$"HealthReportEmailAddress: {HealthReportEmailAddress}\n" +
$"SendTransferNotification: {SendTransferNotification}\n" +
$"SendAdminNotification: {SendAdminNotification}\n" +
$"AdminNotificationDelta: {AdminNotificationDelta} min (" +
......
......@@ -41,7 +41,7 @@ namespace ATxCommon
}
/// <summary>
/// Number of expired directories in the grace location.
/// Number of expired (1st-level) directories in the grace location.
/// </summary>
public int ExpiredDirsCount {
get {
......@@ -50,6 +50,11 @@ namespace ATxCommon
}
}
/// <summary>
/// Total number of expired (2nd-level) directories in the grace location.
/// </summary>
public int ExpiredSubDirsCount { get; private set; }
/// <summary>
/// Check if free space on all configured drives is above their threshold.
/// </summary>
......@@ -82,6 +87,7 @@ namespace ATxCommon
/// and all expired directories, grouped by the topmost level (i.e. user dirs).</returns>
public string GraceLocationSummary() {
UpdateGraceLocation();
long totalSizeExpired = 0;
var summary = "------ Grace location status, " +
$"threshold: {_gracePeriod} days ({_gracePeriodHuman}) ------\n\n" +
$" - location: [{_graceLocation}]\n";
......@@ -92,12 +98,16 @@ namespace ATxCommon
foreach (var dir in _expiredDirs.Keys) {
summary += "\n - directory '" + dir + "'\n";
foreach (var subdir in _expiredDirs[dir]) {
totalSizeExpired += subdir.Size;
summary += $" - {subdir.Dir.Name} " +
$"[age: {subdir.HumanAgeFromName}, " +
$"size: {subdir.HumanSize}]\n";
}
}
summary += $"\n - summary: {ExpiredSubDirsCount} expired folders with a total size " +
$"of {Conv.BytesToString(totalSizeExpired)}\n";
return summary;
}
......@@ -166,6 +176,7 @@ namespace ATxCommon
Log.Debug("Updating storage status: checking grace location...");
_expiredDirs.Clear();
ExpiredSubDirsCount = 0;
foreach (var userdir in _graceLocation.GetDirectories()) {
Log.Trace("Scanning directory [{0}]", userdir.Name);
var expired = new List<DirectoryDetails>();
......@@ -178,6 +189,7 @@ namespace ATxCommon
Log.Trace("Found expired directory [{0}]", dirDetails.Dir.Name);
expired.Add(dirDetails);
ExpiredSubDirsCount++;
}
Log.Trace("Found {0} expired dirs.", expired.Count);
if (expired.Count > 0)
......@@ -185,10 +197,11 @@ namespace ATxCommon
}
_lastUpdateGraceLocation = DateTime.Now;
if (_expiredDirs.Count > 0) {
Log.Debug("Updated storage status: {0} expired directories in grace location.",
_expiredDirs.Count);
}
if (_expiredDirs.Count == 0)
return;
Log.Debug("Updated grace location status: {0} top-level dirs with a total of {1}" +
"expired sub-directories found.", _expiredDirs.Count, ExpiredSubDirsCount);
}
/// <summary>
......
......@@ -155,11 +155,13 @@ namespace ATxCommon
/// Generate an overall system health report with free space, grace location status, etc.
/// </summary>
/// <param name="storage">StorageStatus object used for space and grace reports.</param>
/// <param name="humanSystemName">A human-friendly name/description of the system.</param>
/// <returns>A multi-line string containing the details assembled in the report. These
/// comprise system uptime, free RAM, free storage space and current grace location status.
/// </returns>
public static string HealthReport(StorageStatus storage) {
public static string HealthReport(StorageStatus storage, string humanSystemName="N/A") {
var report = "------ System health report ------\n\n" +
$" - human name: {humanSystemName}\n" +
$" - hostname: {Environment.MachineName}\n" +
$" - uptime: {TimeUtils.SecondsToHuman(Uptime(), false)}\n" +
$" - free system memory: {GetFreeMemory()} MB" + "\n\n";
......
......@@ -408,7 +408,7 @@ namespace ATxService
"\n------ Loaded configuration settings ------\n" + _config.Summary();
var health = SystemChecks.HealthReport(_storage);
var health = SystemChecks.HealthReport(_storage, _config.HostAlias);
SendHealthReport(health);
msg += "\n" + health;
......
......@@ -16,13 +16,14 @@ namespace ATxService
/// <param name="recipient">A full email address OR a valid ActiveDirectory account.</param>
/// <param name="subject">The subject, might be prefixed with a configurable string.</param>
/// <param name="body">The email body.</param>
private void SendEmail(string recipient, string subject, string body) {
/// <returns>True in case an email was sent, false otherwise.</returns>
private bool SendEmail(string recipient, string subject, string body) {
subject = $"{_config.EmailPrefix}{ServiceName} - {subject} - {_config.HostAlias}";
body += $"\n\n--\n[{_versionSummary}]\n";
if (string.IsNullOrEmpty(_config.SmtpHost)) {
Log.Debug("SendEmail: config option <SmtpHost> is unset, not sending mail - " +
"content shown below.\n[Subject] {0}\n[Body] {1}", subject, body);
return;
return false;
}
if (!recipient.Contains(@"@")) {
Log.Trace("Invalid recipient, trying to resolve via AD: {0}", recipient);
......@@ -31,10 +32,10 @@ namespace ATxService
if (string.IsNullOrWhiteSpace(recipient)) {
Log.Info("Invalid or empty recipient given, NOT sending email!");
Log.Debug("SendEmail: {0}\n{1}", subject, body);
return;
return false;
}
try {
var smtpClient = new SmtpClient() {
var smtpClient = new SmtpClient {
Port = _config.SmtpPort,
Host = _config.SmtpHost,
EnableSsl = true,
......@@ -52,7 +53,10 @@ namespace ATxService
catch (Exception ex) {
Log.Error("Error in SendEmail(): {0}\nInnerException: {1}\nStackTrace: {2}",
ex.Message, ex.InnerException, ex.StackTrace);
return false;
}
return true;
}
/// <summary>
......@@ -250,7 +254,8 @@ namespace ATxService
report += $"\nPrevious system health report notification was sent {elapsedHuman}.\n";
_status.LastStartupNotification = DateTime.Now;
return SendAdminEmail(report, "system health report");
Log.Debug("Sending system health report, previous one was sent {0}", elapsedHuman);
return SendEmail(_config.HealthReportEmailAddress, "system health report", report);
}
}
}
\ No newline at end of file
......@@ -100,6 +100,10 @@
messages to, e.g. on completed transfers -->
<AdminDebugEmailAddress>admin@mydomain.xy</AdminDebugEmailAddress>
<!-- HealthReportEmailAddress: an email address where to send system health
reports to, falling back to AdminEmailAddress if empty -->
<HealthReportEmailAddress>admin@mydomain.xy</HealthReportEmailAddress>
<!-- SendTransferNotification: send email to user on finished transfers -->
<SendTransferNotification>true</SendTransferNotification>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment