diff --git a/ATXCommon/FsUtils.cs b/ATXCommon/FsUtils.cs index a7192a84efaa5451ccdc372837306453edaea98b..a9eb50bfdcd764b92273e1986df3bd4d44951efa 100644 --- a/ATXCommon/FsUtils.cs +++ b/ATXCommon/FsUtils.cs @@ -137,8 +137,9 @@ namespace ATXCommon foreach (var userdir in expired.Keys) { report += "\n - user '" + userdir + "'\n"; foreach (var subdir in expired[userdir]) { - report += string.Format(" - {0} [age: {2} days, size: {1}]\n", - subdir.Item1, Conv.BytesToString(subdir.Item2), subdir.Item3); + report += string.Format(" - {0} [age: {2}, size: {1}]\n", + subdir.Item1, Conv.BytesToString(subdir.Item2), + TimeUtils.DaysToHuman(subdir.Item3)); } } if (string.IsNullOrEmpty(report)) diff --git a/ATXCommon/Serializables/ServiceConfig.cs b/ATXCommon/Serializables/ServiceConfig.cs index 367f4def51281fa8766ae245d69b5f7718c20574..bb2a06605a9b2f6415fe96c01a6f3704961a7807 100644 --- a/ATXCommon/Serializables/ServiceConfig.cs +++ b/ATXCommon/Serializables/ServiceConfig.cs @@ -322,13 +322,14 @@ namespace ATXCommon.Serializables "IncomingDirectory: " + IncomingDirectory + "\n" + "MarkerFile: " + MarkerFile + "\n" + "ManagedDirectory: " + ManagedDirectory + "\n" + - "GracePeriod: " + GracePeriod + "\n" + + "GracePeriod: " + GracePeriod + " (" + + TimeUtils.DaysToHuman(GracePeriod) + ")\n" + "DestinationDirectory: " + DestinationDirectory + "\n" + "TmpTransferDir: " + TmpTransferDir + "\n" + "EnforceInheritedACLs: " + EnforceInheritedACLs + "\n" + - "ServiceTimer: " + ServiceTimer + "\n" + + "ServiceTimer: " + ServiceTimer + " ms\n" + "InterPacketGap: " + InterPacketGap + "\n" + - "MaxCpuUsage: " + MaxCpuUsage + "\n" + + "MaxCpuUsage: " + MaxCpuUsage + "%\n" + "MinAvailableMemory: " + MinAvailableMemory + "\n"; foreach (var processName in BlacklistedProcesses) { msg += "BlacklistedProcess: " + processName + "\n"; @@ -347,9 +348,12 @@ namespace ATXCommon.Serializables "EmailFrom: " + EmailFrom + "\n" + "AdminEmailAdress: " + AdminEmailAdress + "\n" + "AdminDebugEmailAdress: " + AdminDebugEmailAdress + "\n" + - "StorageNotificationDelta: " + StorageNotificationDelta + "\n" + - "AdminNotificationDelta: " + AdminNotificationDelta + "\n" + - "GraceNotificationDelta: " + GraceNotificationDelta + "\n"; + "StorageNotificationDelta: " + StorageNotificationDelta + " (" + + TimeUtils.MinutesToHuman(StorageNotificationDelta) + ")\n" + + "AdminNotificationDelta: " + AdminNotificationDelta + " (" + + TimeUtils.MinutesToHuman(AdminNotificationDelta) + ")\n" + + "GraceNotificationDelta: " + GraceNotificationDelta + " (" + + TimeUtils.MinutesToHuman(GraceNotificationDelta) + ")\n"; } return msg; } diff --git a/ATXCommon/Serializables/ServiceStatus.cs b/ATXCommon/Serializables/ServiceStatus.cs index ef2fc29f0343fb6e4d051c0ab046b9d5b01f88d6..cda77dedafa0321f9eb40fad5127887081543733 100644 --- a/ATXCommon/Serializables/ServiceStatus.cs +++ b/ATXCommon/Serializables/ServiceStatus.cs @@ -283,13 +283,21 @@ namespace ATXCommon.Serializables "TransferInProgress: " + TransferInProgress + "\n" + "CurrentTransferSize: " + CurrentTransferSize + "\n" + "LastStatusUpdate: " + - LastStatusUpdate.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + + LastStatusUpdate.ToString("yyyy-MM-dd HH:mm:ss") + " (" + + TimeUtils.SecondsToHuman(TimeUtils.SecondsSince(LastStatusUpdate)) + + " ago)\n" + "LastStorageNotification: " + - LastStorageNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + + LastStorageNotification.ToString("yyyy-MM-dd HH:mm:ss") + " (" + + TimeUtils.SecondsToHuman(TimeUtils.SecondsSince(LastStorageNotification)) + + " ago)\n" + "LastAdminNotification: " + - LastAdminNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n" + + LastAdminNotification.ToString("yyyy-MM-dd HH:mm:ss") + " (" + + TimeUtils.SecondsToHuman(TimeUtils.SecondsSince(LastAdminNotification)) + + " ago)\n" + "LastGraceNotification: " + - LastGraceNotification.ToString("yyyy-MM-dd HH:mm:ss") + "\n"; + LastGraceNotification.ToString("yyyy-MM-dd HH:mm:ss") + " (" + + TimeUtils.SecondsToHuman(TimeUtils.SecondsSince(LastGraceNotification)) + + " ago)\n"; } #endregion validate and report diff --git a/ATXCommon/TimeUtils.cs b/ATXCommon/TimeUtils.cs index 8a27393df67448dfb35237c3e500ff39c3f87799..e334161f08708c8a42e240bbc65064ea6a57e3f7 100644 --- a/ATXCommon/TimeUtils.cs +++ b/ATXCommon/TimeUtils.cs @@ -29,5 +29,58 @@ namespace ATXCommon public static int SecondsSince(DateTime refDate) { return (int)(DateTime.Now - refDate).TotalSeconds; } + + /// <summary> + /// Convert a number of seconds to a human readable string. + /// </summary> + /// <param name="delta">The time span in seconds.</param> + /// <returns>A string describing the duration, e.g. "2 hours 34 minutes".</returns> + public static string SecondsToHuman(int delta) { + const int second = 1; + const int minute = second * 60; + const int hour = minute * 60; + const int day = hour * 24; + const int week = day * 7; + + if (delta < minute) + return delta + " seconds"; + + if (delta < 2 * minute) + return "a minute"; + + if (delta < hour) + return delta / minute + " minutes"; + + if (delta < day) { + var hours = delta / hour; + var mins = (delta - hours * hour) / minute; + if (mins > 0) + return hours + " hours " + mins + " minutes"; + return hours + " hours"; + } + + if (delta < 2 * week) + return delta / day + " days"; + + return delta / week + " weeks"; + } + + /// <summary> + /// Wrapper to use <see cref="SecondsToHuman"/> with minutes as input. + /// </summary> + /// <param name="delta">The time span in minutes.</param> + /// <returns>A string describing the duration, e.g. "2 hours 34 minutes".</returns> + public static string MinutesToHuman(int delta) { + return SecondsToHuman(delta * 60); + } + + /// <summary> + /// Wrapper to use <see cref="SecondsToHuman"/> with days as input. + /// </summary> + /// <param name="delta">The time span in days.</param> + /// <returns>A string describing the duration, e.g. "12 days" or "3 weeks".</returns> + public static string DaysToHuman(int delta) { + return MinutesToHuman(delta * 60 * 24); + } } } diff --git a/AutoTx/AutoTx.cs b/AutoTx/AutoTx.cs index 3b7f881956337a290e7ed010e3279fa537486cd9..12aefb2aada5c1916551fe00f8aec4fb166f1ab0 100644 --- a/AutoTx/AutoTx.cs +++ b/AutoTx/AutoTx.cs @@ -417,8 +417,9 @@ namespace AutoTx if (_mainTimer.Interval > maxInterval) _mainTimer.Interval = maxInterval; Log.Error("Unhandled exception in OnTimedEvent(): {0}\n\n" + - "Trying exponential backoff, setting timer interval to {1} ms.\n\n" + - "StackTrace: {2}", ex.Message, _mainTimer.Interval, ex.StackTrace); + "Trying exponential backoff, setting timer interval to {1} ms ({3}).\n\n" + + "StackTrace: {2}", ex.Message, _mainTimer.Interval, ex.StackTrace, + TimeUtils.SecondsToHuman((int)_mainTimer.Interval / 1000)); } finally { // make sure to enable the timer again: diff --git a/AutoTx/Email.cs b/AutoTx/Email.cs index dc6b34dbd87ec10c5565b8ec91955f17d7db9610..ff85da3e12c972a0dcbf3ab6d29d8ecefb434969 100644 --- a/AutoTx/Email.cs +++ b/AutoTx/Email.cs @@ -95,7 +95,8 @@ namespace AutoTx var delta = TimeUtils.MinutesSince(_status.LastAdminNotification); if (delta < _config.AdminNotificationDelta) { Log.Warn("Suppressed admin email, interval too short ({0} vs. {1}):\n\n{2}\n{3}", - delta, _config.AdminNotificationDelta, subject, body); + TimeUtils.MinutesToHuman(delta), + TimeUtils.MinutesToHuman(_config.AdminNotificationDelta), subject, body); return; } @@ -123,7 +124,8 @@ namespace AutoTx var delta = TimeUtils.MinutesSince(_status.LastStorageNotification); if (delta < _config.StorageNotificationDelta) { - Log.Trace("Only {0} minutes since last low-space-notification, skipping.", delta); + Log.Trace("Only {0} since last low-space-notification, skipping.", + TimeUtils.MinutesToHuman(delta)); return; } @@ -234,7 +236,8 @@ namespace AutoTx return ""; var delta = TimeUtils.MinutesSince(_status.LastGraceNotification); - report += "\nTime since last grace notification: " + delta + "\n"; + report += "\nTime since last grace notification: " + + TimeUtils.MinutesToHuman(delta) + "\n"; if (delta < _config.GraceNotificationDelta) return report;