/// <summary>
        /// Print data.  Note that this method is called FROM DIFFERNET THREADS which means you need to properly
        /// lock any read-write data you access.   It turns out Out.Writeline is already thread safe so
        /// there is nothing I have to do in this case. 
        /// </summary>
        static void Print(TraceEvent data)
        {
            // There are a lot of data collection start on entry that I don't want to see (but often they are quite handy
            if (data.Opcode == TraceEventOpcode.DataCollectionStart || data.Opcode == TraceEventOpcode.DataCollectionStop)
                return;

            // Merging inject some 'symbol' events that are not that interesting so we ignore those too.  
            if (data.ProviderGuid == SymbolTraceEventParser.ProviderGuid)
                return;

            // To avoid 'rundown' events that happen in the beginning and end of the trace filter out things during those times
            if (data.TimeStampRelativeMSec < 1000 || 9000 < data.TimeStampRelativeMSec)
                return;

            Out.WriteLine(data.ToString());
        }
        /// <summary>
        /// Print data.  Note that this method is called FROM DIFFERNET THREADS which means you need to properly
        /// lock any read-write data you access.   It turns out Out.Writeline is already thread safe so
        /// there is nothing I have to do in this case. 
        /// </summary>
        static void Print(TraceEvent data, SymbolReader symbolReader)
        {
            // There are a lot of data collection start on entry that I don't want to see (but often they are quite handy
            if (data.Opcode == TraceEventOpcode.DataCollectionStart)
                return;
            // V3.5 runtimes don't log the stack and in fact don't event log the exception name (it shows up as an empty string)
            // Just ignore these as they are not that interesting. 
            if (data is ExceptionTraceData && ((ExceptionTraceData) data).ExceptionType.Length == 0)
                return;

            Out.WriteLine("EVENT: {0}", data.ToString());
            var callStack = data.CallStack();
            if (callStack != null)
            {
                // Because symbol lookup is complex, error prone, and expensive TraceLog requires you to be explicit.  
                // Here we look up names in this call stack using the symbol reader.  
                ResolveNativeCode(callStack, symbolReader);
                Out.WriteLine("CALLSTACK: {0}", callStack.ToString());
            }
        }
        /// <summary>
        /// Print data.  Note that this method is called FROM DIFFERNET THREADS which means you need to properly
        /// lock any read-write data you access.   It turns out Out.Writeline is already thread safe so
        /// there is nothing I have to do in this case. 
        /// </summary>
        static void Print(TraceEvent data)
        {
            if (s_stopping)        // Ctrl-C will stop the sessions, but buffered events may still come in, ignore these.  
                return;

            // There are a lot of data collection start on entry that I don't want to see (but often they are quite handy
            if (data.Opcode == TraceEventOpcode.DataCollectionStart)
                return;

            Out.WriteLine(data.ToString());
            if (data is UnhandledTraceEvent)
                Out.WriteLine(data.Dump());
        }
        /// <summary>
        /// Print data.  Note that this method is called FROM DIFFERNET THREADS which means you need to properly
        /// lock any read-write data you access.   It turns out Out.Writeline is already thread safe so
        /// there is nothing I have to do in this case. 
        /// </summary>
        static void Print(TraceEvent data)
        {
            // There are a lot of data collection start on entry that I don't want to see (but often they are quite handy
            if (data.Opcode == TraceEventOpcode.DataCollectionStart)
                return;

            Out.WriteLine(data.ToString());
            if (data is UnhandledTraceEvent)
                Out.WriteLine(data.Dump());
        }