17 using System.Collections.Generic;
19 using System.Threading;
20 using Newtonsoft.Json;
34 private TextWriter _succeededDataRequestsWriter;
35 private TextWriter _failedDataRequestsWriter;
37 private long _succeededDataRequestsCount;
38 private long _failedDataRequestsCount;
40 private long _succeededUniverseDataRequestsCount;
41 private long _failedUniverseDataRequestsCount;
43 private readonly List<double> _requestRates =
new();
44 private long _prevRequestsCount;
45 private DateTime _lastRequestRateCalculationTime;
47 private Thread _requestRateCalculationThread;
48 private CancellationTokenSource _cancellationTokenSource;
50 private readonly
string _succeededDataRequestsFileName;
51 private readonly
string _failedDataRequestsFileName;
52 private readonly
string _resultsDestinationFolder;
54 private readonly
object _threadLock =
new();
62 _succeededDataRequestsFileName = GetFilePath(
"succeeded-data-requests.txt");
63 _failedDataRequestsFileName = GetFilePath(
"failed-data-requests.txt");
78 if (e.
Path.Contains(
"map_files", StringComparison.OrdinalIgnoreCase) ||
79 e.
Path.Contains(
"factor_files", StringComparison.OrdinalIgnoreCase))
84 var path = StripDataFolder(e.
Path);
85 var isUniverseData = path.Contains(
"coarse", StringComparison.OrdinalIgnoreCase) ||
86 path.Contains(
"universe", StringComparison.OrdinalIgnoreCase);
90 WriteLineToFile(_succeededDataRequestsWriter, path, _succeededDataRequestsFileName);
91 Interlocked.Increment(ref _succeededDataRequestsCount);
94 Interlocked.Increment(ref _succeededUniverseDataRequestsCount);
99 WriteLineToFile(_failedDataRequestsWriter, path, _failedDataRequestsFileName);
100 Interlocked.Increment(ref _failedDataRequestsCount);
103 Interlocked.Increment(ref _failedUniverseDataRequestsCount);
106 if (Logging.Log.DebuggingEnabled)
108 Logging.Log.Debug($
"DataMonitor.OnNewDataRequest(): Data from {path} could not be fetched");
118 if (_exited || _requestRateCalculationThread ==
null)
124 _requestRateCalculationThread.StopSafely(TimeSpan.FromSeconds(5), _cancellationTokenSource);
125 _succeededDataRequestsWriter?.Close();
126 _failedDataRequestsWriter?.Close();
128 StoreDataMonitorReport(GenerateReport());
130 _succeededDataRequestsWriter.DisposeSafely();
131 _failedDataRequestsWriter.DisposeSafely();
132 _cancellationTokenSource.DisposeSafely();
135 public void Dispose()
140 protected virtual string StripDataFolder(
string path)
153 private void Initialize()
155 if (_requestRateCalculationThread !=
null)
161 if (_requestRateCalculationThread !=
null)
166 _succeededDataRequestsWriter = OpenStream(_succeededDataRequestsFileName);
167 _failedDataRequestsWriter = OpenStream(_failedDataRequestsFileName);
169 _cancellationTokenSource =
new CancellationTokenSource();
171 _requestRateCalculationThread =
new Thread(() =>
173 while (!_cancellationTokenSource.Token.WaitHandle.WaitOne(3000))
175 ComputeFileRequestFrequency();
178 { IsBackground =
true };
179 _requestRateCalculationThread.Start();
183 private DataMonitorReport GenerateReport()
185 var report =
new DataMonitorReport(_succeededDataRequestsCount,
186 _failedDataRequestsCount,
187 _succeededUniverseDataRequestsCount,
188 _failedUniverseDataRequestsCount,
191 Logging.Log.Trace($
"DataMonitor.GenerateReport():{Environment.NewLine}" +
192 $
"DATA USAGE:: Total data requests {report.TotalRequestsCount}{Environment.NewLine}" +
193 $
"DATA USAGE:: Succeeded data requests {report.SucceededDataRequestsCount}{Environment.NewLine}" +
194 $
"DATA USAGE:: Failed data requests {report.FailedDataRequestsCount}{Environment.NewLine}" +
195 $
"DATA USAGE:: Failed data requests percentage {report.FailedDataRequestsPercentage}%{Environment.NewLine}" +
196 $
"DATA USAGE:: Total universe data requests {report.TotalUniverseDataRequestsCount}{Environment.NewLine}" +
197 $
"DATA USAGE:: Succeeded universe data requests {report.SucceededUniverseDataRequestsCount}{Environment.NewLine}" +
198 $
"DATA USAGE:: Failed universe data requests {report.FailedUniverseDataRequestsCount}{Environment.NewLine}" +
199 $
"DATA USAGE:: Failed universe data requests percentage {report.FailedUniverseDataRequestsPercentage}%");
204 private void ComputeFileRequestFrequency()
206 var requestsCount = _succeededDataRequestsCount + _failedDataRequestsCount;
208 if (_lastRequestRateCalculationTime ==
default)
212 _lastRequestRateCalculationTime = DateTime.UtcNow;
213 _prevRequestsCount = requestsCount;
217 var requestsCountDelta = requestsCount - _prevRequestsCount;
218 var now = DateTime.UtcNow;
219 var timeDelta = now - _lastRequestRateCalculationTime;
221 _requestRates.Add(Math.Round(requestsCountDelta / timeDelta.TotalSeconds));
222 _prevRequestsCount = requestsCount;
223 _lastRequestRateCalculationTime = now;
230 private void StoreDataMonitorReport(DataMonitorReport report)
237 var path = GetFilePath(
"data-monitor-report.json");
238 var data = JsonConvert.SerializeObject(report, Formatting.None);
239 File.WriteAllText(path, data);
242 private string GetFilePath(
string filename)
244 var baseFilename = Path.GetFileNameWithoutExtension(filename);
245 var timestamp = DateTime.UtcNow.ToStringInvariant(
"yyyyMMddHHmmssfff");
246 var extension = Path.GetExtension(filename);
247 return Path.Combine(_resultsDestinationFolder, $
"{baseFilename}-{timestamp}{extension}");
250 private static TextWriter OpenStream(
string filename)
252 var writer =
new StreamWriter(filename);
253 return TextWriter.Synchronized(writer);
256 private static void WriteLineToFile(TextWriter writer,
string line,
string filename)
260 writer.WriteLine(line);
262 catch (IOException exception)
264 Logging.Log.Error($
"DataMonitor.OnNewDataRequest(): Failed to write to file {filename}: {exception.Message}");