view Implab/Diagnostics/TraceContext.cs @ 37:c2c043520724 diagnostics

working version of diagnostics logging
author cin
date Tue, 15 Apr 2014 02:46:18 +0400
parents 313f708a50e9
children fe33f4e02ad5
line wrap: on
line source

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Implab.Diagnostics {
    public class TraceContext {
        LogicalOperation m_currentOperation;
        readonly LogicalOperation m_traceBound;
        readonly int m_threadId;
        readonly TraceContext m_parent;

        readonly static object _consoleLock = new object();

        [ThreadStatic]
        static TraceContext _current;

        public static TraceContext Current {
            get {
                if (_current == null)
                    _current = new TraceContext();
                return _current;
            }
        }

        TraceContext(TraceContext context) {
            if (context == null)
                throw new ArgumentNullException("context");

            m_parent = context;
            m_currentOperation = context.CurrentOperation;
            m_traceBound = context.CurrentOperation;
            m_threadId = Thread.CurrentThread.ManagedThreadId;

            LogEvent(TraceEventType.Transfer, "FORK {0}", context.ThreadId);
        }

        TraceContext() {
            m_currentOperation = new LogicalOperation();
            m_traceBound = m_currentOperation;
            m_threadId = Thread.CurrentThread.ManagedThreadId;
        }

        public static void Transfer(TraceContext from) {
            _current = from == null ? new TraceContext() : new TraceContext(from);
        }

        public TraceContext 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) {
            LogEvent(TraceEventType.OperationStarted, "{0}", name);
            m_currentOperation = new LogicalOperation(name, m_currentOperation);
        }

        public void EndLogicalOperation() {
            if (m_traceBound == m_currentOperation) {
                LogEvent(TraceEventType.Error, "Trying to end the operation which isn't belongs to current trace");
            } else {
                var op = m_currentOperation;
                m_currentOperation = m_currentOperation.Parent;
                LogEvent(TraceEventType.OperationCompleted, "{0} {1} ms", op.Name, op.Duration);
            }
        }

        void LogEvent(TraceEventType type, string format, params object[] args) {
            LogChannel<TraceEvent>.Default.LogEvent(this, TraceEvent.Create(type, format, args));
        }
    }
}