VEU.WathBody/3-app/1-lib/Kit.Helpers/Log/CallStackLog.cs

193 lines
5.2 KiB
C#

using System.Collections.Concurrent;
using System.Diagnostics;
using System.Text;
namespace Kit.Helpers.Log
{
public interface ICallStackLog
{
string LogMessage { get; }
ICallStackLog NextLevel();
void FinishLevel();
void BeginCall(string message);
void EndCall();
}
public class EmptyCallStackLog : ICallStackLog
{
public string LogMessage
{
get { return ""; }
}
public ICallStackLog NextLevel()
{
return CallStackLog.Empty;
}
public void FinishLevel()
{
return;
}
public void BeginCall(string message)
{
return;
}
public void EndCall()
{
return;
}
}
public class CallStackLog : ICallStackLog
{
protected ConcurrentDictionary<string, long> Logs { get; }
protected ConcurrentBag<CallStackLog> ChildCallStackLogs { get; set; }
protected readonly int _level;
protected readonly string _path;
protected string _currentCall;
protected int _number;
protected readonly Stopwatch _stopwatch = new Stopwatch();
public static ICallStackLog Empty { get { return new EmptyCallStackLog(); } }
protected string Number
{
get
{
if (_number <= 9)
return "0" + _number;
return _number.ToString();
}
}
public CallStackLog()
{
Logs = new ConcurrentDictionary<string, long>();
ChildCallStackLogs = new ConcurrentBag<CallStackLog>();
_level = 0;
_path = "";
_number = 1;
}
public CallStackLog(int level, string path)
{
Logs = new ConcurrentDictionary<string, long>();
ChildCallStackLogs = new ConcurrentBag<CallStackLog>();
_level = level;
_path = path;
_number = 1;
}
public string LogMessage
{
get
{
StringBuilder stringBuilder = new StringBuilder();
foreach (var logLine in Logs.OrderBy(x => x.Key))
{
stringBuilder.AppendLine(logLine.Key + $". Time - {logLine.Value} ms");
}
return stringBuilder.ToString();
}
}
public ConcurrentDictionary<string, long> GetLogs
{
get {
return this.Logs;
}
}
public ICallStackLog NextLevel()
{
var childCallStackLog = new CallStackLog(_level + 1, _path + this.Number + ".");
ChildCallStackLogs.Add(childCallStackLog);
return childCallStackLog;
}
public void FinishLevel()
{
foreach (CallStackLog childCallStackLog in ChildCallStackLogs)
{
lock (Logs)
{
foreach (var logLine in childCallStackLog.Logs)
{
if (Logs.ContainsKey(logLine.Key))
{
Logs[logLine.Key] += logLine.Value;
continue;
}
Logs.TryAdd(logLine.Key, logLine.Value);
}
}
}
ChildCallStackLogs = new ConcurrentBag<CallStackLog>();
}
public void BeginCall(string message)
{
_currentCall = message;
_stopwatch.Restart();
}
public void EndCall()
{
_stopwatch.Stop();
lock (Logs)
{
Logs.TryAdd($"{_path}{this.Number} {_currentCall.ToStringOrEmpty()}", _stopwatch.ElapsedMilliseconds);
_number++;
}
}
}
public class CallStackLogDB: CallStackLog, IDisposable
{
protected string _sessionKey;
protected LogMessageType _type;
protected string _target;
protected string _action;
protected DateTime _dateCreated;
private bool disposed = false;
public CallStackLogDB(string sessionKey, LogMessageType type, string target, string action):base()
{
_sessionKey = sessionKey;
_type = type;
_target = target;
_action = action;
_dateCreated = DateTime.UtcNow;
}
public void Dispose()
{
Dispose(true);
// подавляем финализацию
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
this.Logs.TryAdd($"Full Time", Convert.ToInt64((DateTime.UtcNow - _dateCreated).TotalMilliseconds));
Kit.Helpers.Log.LoggerDB.Commit(this._sessionKey, this._type, this._target, this._action, _dateCreated, this.Logs.ToDictionary(x => x.Key, x => x.Value));
}
// освобождаем неуправляемые объекты
disposed = true;
}
}
}
}