view Implab/Diagnostics/Trace.cs @ 281:e0916ddc9950 v3 tip

code cleanup and refactoring
author cin
date Fri, 01 Jun 2018 21:35:24 +0300
parents f07be402ab02
children
line wrap: on
line source

// enable System.Diagnostics trace methods
#define TRACE

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

namespace Implab.Diagnostics {
    public static class Trace<T> {

        static Lazy<TraceSource> _traceSource = new Lazy<TraceSource>(CreateChannel, LazyThreadSafetyMode.ExecutionAndPublication);

        static int _nextId;

        static TraceSource CreateChannel() {
            var id = Interlocked.Increment(ref _nextId);
            return new TraceSource(typeof(T).Name);
        }

        public static TraceSource TraceSource { get { return _traceSource.Value; } }

        public static IDisposable Subscribe() {
            
            throw new NotImplementedException();
        }

#if NETFX_TRACE_BUG
        readonly static AsyncLocal<object> m_currentOperation = new AsyncLocal<object>();
#endif 

        /// <summary>
        /// Starts the logical operation nested to the current operation nested to the current one.
        /// </summary>
        public static void StartLogicalOperation() {
            Trace.CorrelationManager.StartLogicalOperation();

        }

        /// <summary>
        /// Starts the logical operation with the specified name, this name is usefull in logs.
        /// </summary>
        /// <param name="name">Name.</param>
#if NETFX_TRACE_BUG
        public static void StartLogicalOperation(object name) {
            m_currentOperation.Value = name;
            Trace.CorrelationManager.StartLogicalOperation(name);
        }
#else
        public static void StartLogicalOperation(object name) {
            Trace.CorrelationManager.StartLogicalOperation(name);
        }
#endif

        /// <summary>
        /// Ends the logical operation and restores the previous one.
        /// </summary>
        public static void StopLogicalOperation() {
            Trace.CorrelationManager.StopLogicalOperation();
        }

        /// <summary>
        /// Writes a debug message.
        /// </summary>
        /// <param name="format">Format.</param>
        /// <param name="arguments">Arguments.</param>
        [Conditional("DEBUG")]
        public static void Debug(string format, params object[] arguments) {

        }

        /// <summary>
        /// Writes an informational message.
        /// </summary>
        /// <param name="format">Format.</param>
        /// <param name="arguments">Arguments.</param>
        [Conditional("TRACE")]
        public static void Log(string format, params object[] arguments) {
            TraceSource.TraceEvent(TraceEventType.Information, 0, format, arguments);
        }

        /// <summary>
        /// Writes a warning message.
        /// </summary>
        /// <param name="format">Format.</param>
        /// <param name="arguments">Arguments.</param>
        public static void Warn(string format, params object[] arguments) {
            TraceSource.TraceEvent(TraceEventType.Warning, 0, format, arguments);
        }

        /// <summary>
        /// Writes a error message.
        /// </summary>
        /// <param name="format">Format.</param>
        /// <param name="arguments">Arguments.</param>
        public static void Error(string format, params object[] arguments) {
            TraceSource.TraceEvent(TraceEventType.Error, 0, format, arguments);
        }

        public static void Error(Exception err) {
            TraceSource.TraceData(TraceEventType.Error, 0, err);
        }

        /// <summary>
        /// This method save the current activity, and transfers to the specified activity,
        /// emits <see cref="TraceEventType.Start"/> and returns a scope of the new
        /// activity.
        /// </summary>
        /// <param name="activityName">The name of the new activity/</param>
        /// <param name="activityId">The identifier of the activity to which 
        /// the control will be transferred</param>
        /// <returns>A scope of the new activity, dispose it to transfer
        /// the control back to the original activity.</returns>
        public static ActivityScope TransferActivity(string activityName, Guid activityId) {
            var prev = Trace.CorrelationManager.ActivityId;

            TraceSource.TraceTransfer(0, "Transfer", activityId);
            Trace.CorrelationManager.ActivityId = activityId;
            TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);

            return new ActivityScope(TraceSource, prev, 0, activityName);
        }

        /// <summary>
        /// Emits <see cref="TraceEventType.Start"/> and returns a scope of the
        /// activity.
        /// </summary>
        /// <param name="activityName">The name of the activity to start</param>
        /// <returns>A scope of the new activity, dispose it to emit
        /// <see cref="TraceEventType.Stop"/> for the current activity.</returns>
        public static ActivityScope StartActivity(string activityName) {
            if (Trace.CorrelationManager.ActivityId == Guid.Empty)
                Trace.CorrelationManager.ActivityId = Guid.NewGuid();

            var prev = Trace.CorrelationManager.ActivityId;
            
            TraceSource.TraceEvent(TraceEventType.Start, 0, activityName);
            return new ActivityScope(TraceSource, prev, 0, activityName);
        }

        /// <summary>
        /// Creates new <see cref="LogicalOperation(string)"/> and calls
        /// to <see cref="CorrelationManager.StartLogicalOperation(object)"/>
        /// passing the created operation as identity. Calls
        /// <see cref="TraceSource.TraceData(TraceEventType, int, object)"/>
        /// to notify listeners on operation start.
        /// </summary>
        /// <param name="name">The name of the logical operation.</param>
        /// <returns>Logical operation scope, disposing it will stop
        /// logical operation and notify trace listeners.</returns>
        public static LogicalOperationScope LogicalOperation(string name) {
            var operation = new LogicalOperation(name);
            TraceSource.TraceData(TraceEventType.Information, TraceEventCodes.StartLogicalOperation, operation);
            StartLogicalOperation(operation);
            return new LogicalOperationScope(TraceSource, operation);
        }
    }
}