123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Valve.VR.InteractionSystem;
- namespace Logging.Base
- {
- public class FileLogger
- {
- #region signleton
- private static Lazy<FileLogger>
- instance =
- new Lazy<FileLogger>
- (() => new FileLogger());
- public static FileLogger Instance => instance.Value;
- public static void DestroyInstance()
- {
- if (instance.IsValueCreated)
- {
- instance.Value.Dispose();
- instance =
- new Lazy<FileLogger>
- (() => new FileLogger());
- }
- }
- #endregion
- private readonly DateTime startTimestamp;
- private AsyncLogFileWriter writer;
- private readonly List<ILogable> logables;
- private bool writerAvailable = false;
- private readonly Dictionary<string, Dictionary<long, string[]>> waitingBuffers;
- public string SubFolderName { get; set; }
- public string Condition { get; set; }
- private FileLogger()
- {
- waitingBuffers = new Dictionary<string, Dictionary<long, string[]>>();
- startTimestamp = DateTime.Now;
- logables = new List<ILogable>();
- }
- public void RegisterLogable(ILogable l) => logables.Add(l);
- private IEnumerable<string> MergedHeaders()
- {
- var headers = new List<string> {"timestamp"};
- foreach (var l in logables)
- {
- headers.AddRange(l.HeaderNames);
- }
- return headers.ToArray();
- }
- private IEnumerable<long> MergeTimestamps()
- {
- var allTimestamps = new HashSet<long>();
- long minBegin = -1;
- long minEnd = -1;
- foreach (var l in logables)
- {
- var keys = l.BufferLines.Keys.ToArray();
- var begin = keys.Length > 0 ? keys.First() : -1;
- var end = keys.Length > 0 ? keys.Last() : -1;
- if (minBegin == -1 || begin >= 0 && begin < minBegin) minBegin = begin;
- if (minEnd == -1 || end >= 0 && end < minEnd) minEnd = end;
- }
- foreach (var l in logables)
- {
- var bufferLines = l.BufferLines;
- var timestamps = new HashSet<long>(bufferLines.Keys);
- var logableKey = l.Key;
- var hasWaiting = waitingBuffers.TryGetValue(logableKey, out var waiting);
- if (hasWaiting)
- {
- foreach (var waitingTs in waiting.Keys)
- {
- if (waitingTs <= minEnd)
- {
- allTimestamps.Add(waitingTs);
- }
- }
- }
- foreach (var t in timestamps)
- {
- if (t >= minBegin && t <= minEnd)
- {
- allTimestamps.Add(t);
- }
- else
- {
- if (waitingBuffers.ContainsKey(l.Key))
- {
- waitingBuffers[l.Key][t] = bufferLines[t];
- }
- else
- {
- waitingBuffers[l.Key] = new Dictionary<long, string[]> {{t, bufferLines[t]}};
- }
- }
- }
- }
- logables.ForEach(l => allTimestamps.UnionWith(l.BufferLines.Keys.Where(k => k >= minBegin && k <= minEnd)));
- return allTimestamps;
- }
- private IEnumerable<IEnumerable<string>> MergedLines()
- {
- var lines = new List<List<string>>();
- var allKeys = MergeTimestamps();
- var mergedDict = new SortedDictionary<long, List<string>>();
- foreach (var timestamp in allKeys)
- {
- var newItem = new List<string>();
- foreach (var l in logables)
- {
- var logableKey = l.Key;
- var hasWaiting = waitingBuffers.TryGetValue(logableKey, out var waiting);
- string[] linePart;
- if (l.BufferLines.ContainsKey(timestamp))
- {
- linePart = l.BufferLines[timestamp];
- }
- else if (hasWaiting && waiting.ContainsKey(timestamp))
- {
- linePart = waiting[timestamp];
- waiting.Remove(timestamp);
- }
- else
- {
- /*var lastAvailableKey =
- l.BufferLines.Keys.Where(k => k < timestamp).DefaultIfEmpty(-1).LastOrDefault();
- linePart = lastAvailableKey >= 0
- ? l.BufferLines[lastAvailableKey]
- : new string[l.HeaderNames.ToArray().Length];*/
- linePart = new string[l.HeaderNames.ToArray().Length];
- }
- newItem.AddRange(linePart);
- }
- mergedDict[timestamp] = newItem;
- }
- mergedDict.ForEach(item =>
- {
- var listItem = new List<string> {item.Key.ToString("D")};
- listItem.AddRange(item.Value);
- lines.Add(listItem);
- });
- return lines;
- }
- public async Task UpdateRegisteredLogs()
- {
- if (!writerAvailable)
- {
- var subfolder = SubFolderName != null ? $"/{SubFolderName}/" : "";
- var condition = $"_{Condition}" ?? "";
- writer = new AsyncLogFileWriter(
- $"Assets/Logs/{subfolder}{startTimestamp:yyyy-MM-dd_HHmmss}{condition}.tsv");
- await writer.WriteDataLine(MergedHeaders());
- writerAvailable = true;
- }
- await writer.WriteDataLines(MergedLines());
- logables.ForEach(l => l.ClearBuffer());
- }
- private void Dispose()
- {
- if (writerAvailable)
- {
- writer.Dispose();
- }
- logables.Clear();
- }
- }
- }
|