# HG changeset patch # User cin # Date 2014-04-14 14:25:26 # Node ID 2880242f987a0dffb724d7dfe9330673f13464ec # Parent dabf79fde388d19cd5b762a3dc4a37541f226344 initial log capabilities diff --git a/Implab.v11.suo b/Implab.v11.suo index c371d5afdf7e3cfb5ab2092a2baa4b698305b78e..abba552222ef3eaa7ffdb49cf74135550b033615 GIT binary patch literal 90112 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 R_@!!5(xJ@z7mH=({~ttuNJIbt diff --git a/Implab/Diagnostics/IEventListener.cs b/Implab/Diagnostics/IEventListener.cs new file mode 100644 --- /dev/null +++ b/Implab/Diagnostics/IEventListener.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Diagnostics { + public interface IEventListener { + void TraceEvent(LogContext context, TraceEventType type, string format, params object[] args); + } +} diff --git a/Implab/Diagnostics/Log.cs b/Implab/Diagnostics/Log.cs new file mode 100644 --- /dev/null +++ b/Implab/Diagnostics/Log.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Diagnostics { + public static class Log { + [Conditional("TRACE")] + public static void Transfer(LogContext from) { + LogContext.Transfer(from); + } + + [Conditional("TRACE")] + public static void StartLogicalOperation() { + LogContext.Current.StartLogicalOperation(); + } + + [Conditional("TRACE")] + public static void StartLogicalOperation(string name) { + LogContext.Current.StartLogicalOperation(name); + } + + [Conditional("TRACE")] + public static void EndLogicalOperation() { + LogContext.Current.EndLogicalOperation(); + } + + [Conditional("TRACE")] + public static void TraceInformation(string format, params object[] arguments) { + LogContext.Current.TraceEvent(TraceEventType.Information, format, arguments); + } + + [Conditional("TRACE")] + public static void TraceWarning(string format, params object[] arguments) { + LogContext.Current.TraceEvent(TraceEventType.Warning, format, arguments); + } + + [Conditional("TRACE")] + public static void TraceError(string format, params object[] arguments) { + LogContext.Current.TraceEvent(TraceEventType.Error, format, arguments); + } + + [Conditional("TRACE")] + public static void TraceError(Exception err) { + TraceError("{0}", err); + } + } +} diff --git a/Implab/Diagnostics/LogContext.cs b/Implab/Diagnostics/LogContext.cs new file mode 100644 --- /dev/null +++ b/Implab/Diagnostics/LogContext.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Implab.Diagnostics { + public class LogContext { + LogicalOperation m_currentOperation; + readonly LogicalOperation m_traceBound; + readonly int m_threadId; + readonly LogContext m_parent; + + readonly static object _consoleLock = new object(); + + [ThreadStatic] + static LogContext _current; + + public static LogContext Current { + get { + if (_current == null) + _current = new LogContext(); + return _current; + } + } + + LogContext(LogContext context) { + if (context == null) + throw new ArgumentNullException("context"); + + m_parent = context; + m_currentOperation = context.CurrentOperation; + m_traceBound = context.CurrentOperation; + m_threadId = Thread.CurrentThread.ManagedThreadId; + + TraceEvent(TraceEventType.Transfer, String.Empty); + } + + LogContext() { + m_currentOperation = new LogicalOperation(); + m_traceBound = m_currentOperation; + m_threadId = Thread.CurrentThread.ManagedThreadId; + } + + public static void Transfer(LogContext from) { + _current = from == null ? new LogContext() : new LogContext(from); + } + + public LogContext ParentContext { + get { + return m_parent; + } + } + + public LogicalOperation CurrentOperation { + get { + return m_currentOperation; + } + } + + public LogicalOperation TraceBound { + get { + return m_traceBound; + } + } + + public int ThreadId { + get { + return m_threadId; + } + } + + public void StartLogicalOperation() { + StartLogicalOperation(null); + } + + public void StartLogicalOperation(string name) { + TraceEvent(TraceEventType.OperationStarted, "{0}", name); + m_currentOperation = new LogicalOperation(name, m_currentOperation); + } + + public void EndLogicalOperation() { + if (m_traceBound == m_currentOperation) { + TraceEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace"); + } else { + var op = m_currentOperation; + m_currentOperation = m_currentOperation.Parent; + TraceEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration); + } + } + + public void TraceEvent(TraceEventType type, string format, params object[] args) { + /*var msg = new StringBuilder(); + for (int i = 0; i < CurrentOperation.Level; i++) + msg.Append(" "); + msg.Append(type); + msg.AppendFormat("[{0}]: ",m_threadId); + msg.AppendFormat(format, args); + + lock (_consoleLock) { + Console.ForegroundColor = (ConsoleColor)(m_threadId % 15 + 1); + Console.WriteLine(msg.ToString()); + }*/ + } + } +} diff --git a/Implab/Diagnostics/LogicalOperation.cs b/Implab/Diagnostics/LogicalOperation.cs new file mode 100644 --- /dev/null +++ b/Implab/Diagnostics/LogicalOperation.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Diagnostics { + public class LogicalOperation { + readonly LogicalOperation m_parent; + readonly string m_name; + readonly int m_level; + readonly int m_timestamp; + + public LogicalOperation() + : this(null, null) { + } + + public LogicalOperation(string name, LogicalOperation parent) { + m_name = name ?? String.Empty; + m_parent = parent; + + m_level = parent == null ? 0 : parent.Level + 1; + m_timestamp = Environment.TickCount; + } + + public int Duration { + get { + var dt = Environment.TickCount - m_timestamp; + return dt < 0 ? int.MaxValue + dt : dt; // handle overflow + } + } + + public LogicalOperation Parent { + get { + return m_parent; + } + } + + public int Level { + get { return m_level; } + } + + public string Name { + get { return m_name; } + } + } +} diff --git a/Implab/Diagnostics/TraceEventType.cs b/Implab/Diagnostics/TraceEventType.cs new file mode 100644 --- /dev/null +++ b/Implab/Diagnostics/TraceEventType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Implab.Diagnostics { + public enum TraceEventType { + Information = 1, + Warning, + Error, + OperationStarted, + OperationCompleted, + Transfer + } +} diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -15,7 +15,7 @@ <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug</OutputPath> - <DefineConstants>DEBUG;</DefineConstants> + <DefineConstants>TRACE;DEBUG;</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <ConsolePause>false</ConsolePause> @@ -32,6 +32,11 @@ <Reference Include="System" /> </ItemGroup> <ItemGroup> + <Compile Include="Diagnostics\IEventListener.cs" /> + <Compile Include="Diagnostics\LogicalOperation.cs" /> + <Compile Include="Diagnostics\Log.cs" /> + <Compile Include="Diagnostics\LogContext.cs" /> + <Compile Include="Diagnostics\TraceEventType.cs" /> <Compile Include="ICancellable.cs" /> <Compile Include="IProgressHandler.cs" /> <Compile Include="IProgressNotifier.cs" /> @@ -43,7 +48,6 @@ <Compile Include="Parallels\ArrayTraits.cs" /> <Compile Include="Parallels\MTQueue.cs" /> <Compile Include="Parallels\WorkerPool.cs" /> - <Compile Include="PromiseState.cs" /> <Compile Include="TaskController.cs" /> <Compile Include="ProgressInitEventArgs.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> diff --git a/Implab/Parallels/AsyncPool.cs b/Implab/Parallels/AsyncPool.cs --- a/Implab/Parallels/AsyncPool.cs +++ b/Implab/Parallels/AsyncPool.cs @@ -1,3 +1,4 @@ +using Implab.Diagnostics; using System; using System.Threading; @@ -13,8 +14,10 @@ namespace Implab.Parallels { public static Promise<T> Invoke<T>(Func<T> func) { var p = new Promise<T>(); + var caller = LogContext.Current; ThreadPool.QueueUserWorkItem(param => { + Log.Transfer(caller); try { p.Resolve(func()); } catch(Exception e) { @@ -28,7 +31,10 @@ namespace Implab.Parallels { public static Promise<T> InvokeNewThread<T>(Func<T> func) { var p = new Promise<T>(); + var caller = LogContext.Current; + var worker = new Thread(() => { + Log.Transfer(caller); try { p.Resolve(func()); } catch (Exception e) { diff --git a/Implab/Parallels/WorkerPool.cs b/Implab/Parallels/WorkerPool.cs --- a/Implab/Parallels/WorkerPool.cs +++ b/Implab/Parallels/WorkerPool.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; +using Implab.Diagnostics; namespace Implab.Parallels { public class WorkerPool : DispatchPool<Action> { @@ -41,7 +42,10 @@ namespace Implab.Parallels { var promise = new Promise<T>(); + var caller = LogContext.Current; + EnqueueTask(delegate() { + Log.Transfer(caller); try { promise.Resolve(task()); } catch (Exception e) { diff --git a/Implab/PromiseState.cs b/Implab/PromiseState.cs deleted file mode 100644 --- a/Implab/PromiseState.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Implab -{ - public enum PromiseState - { - Unresolved, - Resolved, - Cancelled, - Rejected - } -}