Exemplo n.º 1
0
        private void Initialize(string fileOrSessionName, TraceEventSourceType type)
        {
            // Allocate the LOGFILE and structures and arrays that hold them
            // Figure out how many log files we have
            if (type == TraceEventSourceType.MergeAll)
            {
                List <string> allLogFiles = GetMergeAllLogFiles(fileOrSessionName);

                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[allLogFiles.Count];
                for (int i = 0; i < allLogFiles.Count; i++)
                {
                    logFiles[i].LogFileName = allLogFiles[i];
                }
            }
            else
            {
                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[1];
                if (type == TraceEventSourceType.FileOnly)
                {
                    logFiles[0].LogFileName = fileOrSessionName;
                }
                else
                {
                    Debug.Assert(type == TraceEventSourceType.Session);
                    logFiles[0].LoggerName   = fileOrSessionName;
                    logFiles[0].LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
                    IsRealTime = true;
                }
            }

            InitializeFiles();
        }
Exemplo n.º 2
0
 /// <summary>
 /// Open multiple etl files as one trace for processing.
 /// </summary>
 /// <param name="fileOrSessionName">
 /// <param name="type">If type == MergeAll, call Initialize.</param>
 // [SecuritySafeCritical]
 public ETWTraceEventSource(IEnumerable <string> fileNames, TraceEventSourceType type)
 {
     if (type == TraceEventSourceType.MergeAll)
     {
         Initialize(fileNames);
     }
     else
     {
         this.fileNames = fileNames;
     }
 }
 public static Task <bool> RealTimeTraceEventSessionAsync
 (
     string providerName
     , string sessionName
     , string tracingFileName = null
     , string[] traceEvents   = null
     , Action
     <
         long
         , TraceEventDispatcher
         , TraceEventSession
         , TraceEvent
     > onOneEventTracedOnceProcessAction = null
     , TraceEventProviderOptions traceEventProviderOptions = null
     , TraceEventSessionOptions traceEventSessionOptions   = TraceEventSessionOptions.Create
     , TraceEventSourceType traceEventSourceType           = TraceEventSourceType.MergeAll
     , TraceEventLevel traceEventLevel = TraceEventLevel.Always
     , ulong matchKeywords             = ulong.MaxValue
     , bool needCountHits = false
 )
 {
     return
         (Task
          .Factory
          .StartNew <bool>
          (
              () =>
     {
         return
         RealTimeTraceEventSession
         (
             providerName
             , sessionName
             , tracingFileName
             , traceEvents
             , onOneEventTracedOnceProcessAction
             , traceEventProviderOptions
             , traceEventSessionOptions
             , traceEventSourceType
             , traceEventLevel
             , matchKeywords
             , needCountHits
         );
     }
              ,
              TaskCreationOptions.LongRunning
              |
              TaskCreationOptions.DenyChildAttach
          ));
 }
        public bool RealTimeTraceEventSession
        (
            string providerName
            , string sessionName
            , string tracingFileName = null
            , string[] traceEvents   = null
            , Action
            <
                long
                , TraceEventDispatcher
                , TraceEventSession
                , TraceEvent
            > onOneEventTracedOnceProcessAction = null
            , TraceEventProviderOptions traceEventProviderOptions = null
            , TraceEventSessionOptions traceEventSessionOptions   = TraceEventSessionOptions.Create
            , TraceEventSourceType traceEventSourceType           = TraceEventSourceType.MergeAll
            , TraceEventLevel traceEventLevel = TraceEventLevel.Always
            , ulong matchKeywords             = ulong.MaxValue
            , bool needCountHits = false)
        {
            var r = false;

            if
            (
                traceEvents != null
                &&
                traceEvents.Length > 0
                &&
                onOneEventTracedOnceProcessAction != null
            )
            {
                r = TraceEventsHelper
                    .RealTimeTraceEventSession
                    (
                    providerName
                    , sessionName
                    , tracingFileName
                    , traceEvents
                    , onOneEventTracedOnceProcessAction
                    , traceEventProviderOptions
                    , traceEventSessionOptions
                    , traceEventSourceType
                    , traceEventLevel
                    , matchKeywords
                    , needCountHits
                    );
            }
            return(r);
        }
 public Task <bool> TraceETWTraceEventSourceAsync
 (
     string providerName
     , string tracedFileName
     , string[] traceEvents = null
     , Action
     <
         long
         , TraceEventDispatcher
         , TraceEventSession
         , TraceEvent
     > onOneEventTracedOnceProcessAction = null
     , TraceEventProviderOptions traceEventProviderOptions = null
     , TraceEventSourceType traceEventSourceType           = TraceEventSourceType.MergeAll
     , TraceEventLevel traceEventLevel = TraceEventLevel.Always
     , ulong matchKeywords             = ulong.MaxValue
     , bool needCountHits = false
 )
 {
     return
         (Task
          .Factory
          .StartNew <bool>
          (
              () =>
     {
         return
         TraceETWTraceEventSource
         (
             providerName
             , tracedFileName
             , traceEvents
             , onOneEventTracedOnceProcessAction
             , traceEventProviderOptions
             , traceEventSourceType
             , traceEventLevel
             , matchKeywords
             , needCountHits
         );
     }
          ));
 }
Exemplo n.º 6
0
        /// <summary>
        /// Create an ETWReloggerTraceEventSource that can takes its input from a variety of sources (either a single file,
        /// a set of files, or a real time ETW session (based on 'type'), and can write these events to a new ETW output
        /// file 'outputFileName.
        /// </summary>
        public ETWReloggerTraceEventSource(string fileOrSessionName, TraceEventSourceType type, string outputFileName)
            : base()
        {
            var version = Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor;

            if (version < 62)
            {
                throw new NotSupportedException("System Tracing is only supported on Windows 8 and above.");
            }

            m_relogger = new CTraceRelogger();
            if (type == TraceEventSourceType.FileOnly)
            {
                m_traceHandleForFirstStream = m_relogger.AddLogfileTraceStream(fileOrSessionName, IntPtr.Zero);
            }
            else if (type == TraceEventSourceType.Session)
            {
                m_traceHandleForFirstStream = m_relogger.AddRealtimeTraceStream(fileOrSessionName, IntPtr.Zero);
            }
            else
            {
                Debug.Assert(type == TraceEventSourceType.MergeAll);
                List <string> logFileNames = ETWTraceEventSource.GetMergeAllLogFiles(fileOrSessionName);
                bool          first        = true;
                foreach (var logFileName in logFileNames)
                {
                    var handle = m_relogger.AddLogfileTraceStream(logFileName, IntPtr.Zero);
                    if (first)
                    {
                        m_traceHandleForFirstStream = handle;
                        first = false;
                    }
                }
            }

            m_relogger.SetOutputFilename(outputFileName);
            m_myCallbacks = new ReloggerCallbacks(this);
            m_relogger.RegisterCallback(m_myCallbacks);
        }
 public static bool TraceETWTraceEventSource
                     (
                         string providerName
                         , string tracedFileName
                         , string[] traceEvents = null
                         , Action
                                 <
                                     long
                                     , TraceEventDispatcher
                                     , TraceEventSession
                                     , TraceEvent
                                 > onOneEventTracedOnceProcessAction = null
                         , TraceEventProviderOptions traceEventProviderOptions = null
                         , TraceEventSourceType traceEventSourceType = TraceEventSourceType.MergeAll
                         , TraceEventLevel traceEventLevel = TraceEventLevel.Always
                         , ulong matchKeywords = ulong.MaxValue
                         , bool needCountHits = false
                     )
 {
     var r = false;
     if (!(TraceEventSession.IsElevated() ?? false))
     {
         Out.WriteLine("To turn on ETW events you need to be Administrator, please run from an Admin process.");
         return r;
     }
     if
         (
             traceEvents != null
             &&
             traceEvents.Length > 0
             &&
             onOneEventTracedOnceProcessAction != null
         )
     {
         using (var source = new ETWTraceEventSource(tracedFileName, traceEventSourceType))
         {
             //闭包
             long sequence = 0;
             RegisterCallbacks
                 (
                     providerName
                     , traceEvents
                     , source
                     , null
                     , (x, y, z) =>
                     {
                         long id = 0;
                         if (needCountHits)
                         {
                             id = Interlocked.Increment(ref sequence);
                         }
                         onOneEventTracedOnceProcessAction
                                         (
                                             id
                                             , x
                                             , y
                                             , z
                                         );
                     }
                 );
             source.Process();   // call the callbacks for each event
         }
     }
     return true;
 }
 public bool TraceETWTraceEventSource
             (
                 string providerName
                 , string tracedFileName
                 , string[] traceEvents = null
                 , Action
                         <
                             long
                             , TraceEventDispatcher
                             , TraceEventSession
                             , TraceEvent
                         > onOneEventTracedOnceProcessAction = null
                 , TraceEventProviderOptions traceEventProviderOptions = null
                 , TraceEventSourceType traceEventSourceType = TraceEventSourceType.MergeAll
                 , TraceEventLevel traceEventLevel = TraceEventLevel.Always
                 , ulong matchKeywords = ulong.MaxValue
                 , bool needCountHits = false
             )
 {
     var r = false;
     if
         (
             traceEvents != null
             &&
             traceEvents.Length > 0
             &&
             onOneEventTracedOnceProcessAction != null
         )
     {
         r = TraceEventsHelper
                     .TraceETWTraceEventSource
                         (
                             providerName
                             , tracedFileName
                             , traceEvents
                             , onOneEventTracedOnceProcessAction
                             , traceEventProviderOptions
                             , traceEventSourceType
                             , traceEventLevel
                             , matchKeywords
                             , needCountHits
                         );
     }
     return r;
 }
 public Task<bool> TraceETWTraceEventSourceAsync
             (
                 string providerName
                 , string tracedFileName
                 , string[] traceEvents = null
                 , Action
                         <
                             long
                             , TraceEventDispatcher
                             , TraceEventSession
                             , TraceEvent
                         > onOneEventTracedOnceProcessAction = null
                 , TraceEventProviderOptions traceEventProviderOptions = null
                 , TraceEventSourceType traceEventSourceType = TraceEventSourceType.MergeAll
                 , TraceEventLevel traceEventLevel = TraceEventLevel.Always
                 , ulong matchKeywords = ulong.MaxValue
                 , bool needCountHits = false
             )
 {
     return
         Task
             .Factory
             .StartNew<bool>
                 (
                     () =>
                     {
                         return
                             TraceETWTraceEventSource
                             (
                                 providerName
                                 , tracedFileName
                                 , traceEvents
                                 , onOneEventTracedOnceProcessAction
                                 , traceEventProviderOptions
                                 , traceEventSourceType
                                 , traceEventLevel
                                 , matchKeywords
                                 , needCountHits
                             );
                     }
                 );
 }
Exemplo n.º 10
0
 /// <summary>
 /// Open a ETW event source for processing.  This can either be a moduleFile or a real time ETW session
 /// </summary>
 /// <param name="fileOrSessionName">
 /// If type == ModuleFile this is the name of the moduleFile to open.
 /// If type == Session this is the name of real time session to open.</param>
 /// <param name="type"></param>
 // [SecuritySafeCritical]
 public ETWTraceEventSource(string fileOrSessionName, TraceEventSourceType type)
 {
     Initialize(fileOrSessionName, type);
 }
Exemplo n.º 11
0
        private void Initialize(string fileOrSessionName, TraceEventSourceType type)
        {
            // Allocate the LOGFILE and structures and arrays that hold them
            // Figure out how many log files we have
            if (type == TraceEventSourceType.MergeAll)
            {
                List <string> allLogFiles = GetMergeAllLogFiles(fileOrSessionName);

                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[allLogFiles.Count];
                for (int i = 0; i < allLogFiles.Count; i++)
                {
                    logFiles[i].LogFileName = allLogFiles[i];
                }
            }
            else
            {
                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[1];
                if (type == TraceEventSourceType.FileOnly)
                {
                    logFiles[0].LogFileName = fileOrSessionName;
                }
                else
                {
                    Debug.Assert(type == TraceEventSourceType.Session);
                    logFiles[0].LoggerName   = fileOrSessionName;
                    logFiles[0].LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
                    IsRealTime = true;
                }
            }
            handles = new ulong[logFiles.Length];

            // Fill  out the first log file information (we will clone it later if we have multiple files).
            logFiles[0].BufferCallback = this.TraceEventBufferCallback;
            handles[0]    = TraceEventNativeMethods.INVALID_HANDLE_VALUE;
            useClassicETW = !OperatingSystemVersion.AtLeast(OperatingSystemVersion.Vista);
            if (useClassicETW)
            {
                IntPtr mem = Marshal.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader           = (TraceEventNativeMethods.EVENT_RECORD *)mem;
                logFiles[0].EventCallback = RawDispatchClassic;
            }
            else
            {
                logFiles[0].LogFileMode  |= TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                logFiles[0].EventCallback = RawDispatch;
            }
            // We want the raw timestamp because it is needed to match up stacks with the event they go with.
            logFiles[0].LogFileMode |= TraceEventNativeMethods.PROCESS_TRACE_MODE_RAW_TIMESTAMP;

            // Copy the information to any additional log files
            for (int i = 1; i < logFiles.Length; i++)
            {
                logFiles[i].BufferCallback = logFiles[0].BufferCallback;
                logFiles[i].EventCallback  = logFiles[0].EventCallback;
                logFiles[i].LogFileMode    = logFiles[0].LogFileMode;
                handles[i] = handles[0];
            }

            DateTime minSessionStartTimeUTC = DateTime.MaxValue;
            DateTime maxSessionEndTimeUTC   = DateTime.MinValue + new TimeSpan(1 * 365, 0, 0, 0); // TO avoid roundoff error when converting to QPC add a year.

            // Open all the traces
            for (int i = 0; i < handles.Length; i++)
            {
                handles[i] = TraceEventNativeMethods.OpenTrace(ref logFiles[i]);
                if (handles[i] == TraceEventNativeMethods.INVALID_HANDLE_VALUE)
                {
                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());
                }

                // Start time is minimum of all start times
                DateTime logFileStartTimeUTC = SafeFromFileTimeUtc(logFiles[i].LogfileHeader.StartTime);
                DateTime logFileEndTimeUTC   = SafeFromFileTimeUtc(logFiles[i].LogfileHeader.EndTime);

                if (logFileStartTimeUTC < minSessionStartTimeUTC)
                {
                    minSessionStartTimeUTC = logFileStartTimeUTC;
                }
                // End time is maximum of all start times
                if (logFileEndTimeUTC > maxSessionEndTimeUTC)
                {
                    maxSessionEndTimeUTC = logFileEndTimeUTC;
                }

                // TODO do we even need log pointer size anymore?
                // We take the max pointer size.
                if ((int)logFiles[i].LogfileHeader.PointerSize > pointerSize)
                {
                    pointerSize = (int)logFiles[i].LogfileHeader.PointerSize;
                }
            }

            _QPCFreq = logFiles[0].LogfileHeader.PerfFreq;
            if (_QPCFreq == 0)
            {
                _QPCFreq = Stopwatch.Frequency;
            }

            // Real time providers don't set this to something useful
            if ((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0)
            {
                DateTime nowUTC = DateTime.UtcNow;
                long     nowQPC = QPCTime.GetUTCTimeAsQPC(nowUTC);

                _syncTimeQPC = nowQPC;
                _syncTimeUTC = nowUTC;

                sessionStartTimeQPC = nowQPC - _QPCFreq / 10;           // Subtract 1/10 sec to keep now and nowQPC in sync.
                sessionEndTimeQPC   = long.MaxValue;                    // Represents infinity.

                Debug.Assert(SessionStartTime < SessionEndTime);
            }
            else
            {
                _syncTimeUTC = minSessionStartTimeUTC;

                // UTCDateTimeToQPC is actually going to give the wrong value for these because we have
                // not set _syncTimeQPC, but will be adjusted when we see the event Header and know _syncTypeQPC.
                sessionStartTimeQPC = this.UTCDateTimeToQPC(minSessionStartTimeUTC);
                sessionEndTimeQPC   = this.UTCDateTimeToQPC(maxSessionEndTimeUTC);
            }
            Debug.Assert(_QPCFreq != 0);
            if (pointerSize == 0)       // Real time does not set this (grrr).
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            cpuSpeedMHz        = (int)logFiles[0].LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)logFiles[0].LogfileHeader.NumberOfProcessors;

            // We ask for raw timestamps, but the log file may have used system time as its raw timestamp.
            // SystemTime is like a QPC time that happens 10M times a second (100ns).
            // ReservedFlags is actually the ClockType 0 = Raw, 1 = QPC, 2 = SystemTimne 3 = CpuTick (we don't support)
            if (logFiles[0].LogfileHeader.ReservedFlags == 2)   // If ClockType == EVENT_TRACE_CLOCK_SYSTEMTIME
            {
                _QPCFreq = 10000000;
            }

            Debug.Assert(_QPCFreq != 0);
            int ver = (int)logFiles[0].LogfileHeader.Version;

            osVersion = new Version((byte)ver, (byte)(ver >> 8));

            // Logic for looking up process names
            processNameForID = new Dictionary <int, string>();

            var kernelParser = new KernelTraceEventParser(this, KernelTraceEventParser.ParserTrackingOptions.None);

            kernelParser.ProcessStartGroup += delegate(ProcessTraceData data)
            {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures.
                string path     = data.KernelImageFileName;
                int    startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                {
                    startIdx++;
                }
                else
                {
                    startIdx = 0;
                }
                int endIdx = path.LastIndexOf('.');
                if (endIdx <= startIdx)
                {
                    endIdx = path.Length;
                }
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
            kernelParser.ProcessEndGroup += delegate(ProcessTraceData data)
            {
                processNameForID.Remove(data.ProcessID);
            };
            kernelParser.EventTraceHeader += delegate(EventTraceHeaderTraceData data)
            {
                if (_syncTimeQPC == 0)
                {   // In merged files there can be more of these, we only set the QPC time on the first one
                    // We were using a 'start location' of 0, but we want it to be the timestamp of this events, so we add this to our
                    // existing QPC values.
                    _syncTimeQPC         = data.TimeStampQPC;
                    sessionStartTimeQPC += data.TimeStampQPC;
                    sessionEndTimeQPC   += data.TimeStampQPC;
                }
            };
        }
Exemplo n.º 12
0
        public ETWTraceEventSource(string fileOrSessionName, TraceEventSourceType type)
        {
            long now = DateTime.Now.ToFileTime() - 100000;     // subtract 10ms to avoid negative times.

            primaryLogFile = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW();
            primaryLogFile.BufferCallback = this.TraceEventBufferCallback;

            useClassicETW = Environment.OSVersion.Version.Major < 6;
            if (useClassicETW)
            {
                IntPtr mem = TraceEventNativeMethods.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, (uint)sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader = (TraceEventNativeMethods.EVENT_RECORD*)mem;
                primaryLogFile.EventCallback = RawDispatchClassic;

            }
            else
            {
                primaryLogFile.LogFileMode = TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                primaryLogFile.EventCallback = RawDispatch;
            }

            if (type == TraceEventSourceType.Session)
            {
                primaryLogFile.LoggerName = fileOrSessionName;
                primaryLogFile.LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
            }
            else
            {
                if (type == TraceEventSourceType.UserAndKernelFile)
                {
                    // See if we have also have kernel log moduleFile.
                    if (fileOrSessionName.Length > 4 && string.Compare(fileOrSessionName, fileOrSessionName.Length - 4, ".etl", 0, 4, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        string kernelFileName = fileOrSessionName.Substring(0, fileOrSessionName.Length - 4) + ".kernel.etl";
                        if (File.Exists(kernelFileName))
                        {
                            if (File.Exists(fileOrSessionName))
                            {
                                handles = new ulong[2];
                                handles[0] = TraceEventNativeMethods.INVALID_HANDLE_VALUE;

                                kernelModeLogFile = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW();
                                kernelModeLogFile.BufferCallback = primaryLogFile.BufferCallback;
                                kernelModeLogFile.EventCallback = primaryLogFile.EventCallback;
                                kernelModeLogFile.LogFileName = kernelFileName;
                                kernelModeLogFile.LogFileMode = primaryLogFile.LogFileMode;

                                handles[1] = TraceEventNativeMethods.OpenTrace(ref kernelModeLogFile);

                                if (TraceEventNativeMethods.INVALID_HANDLE_VALUE == handles[1])
                                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());

                            }
                            else
                            {
                                // we have ONLY a *.kernel.etl moduleFile, treat it as the primary moduleFile.
                                fileOrSessionName = kernelFileName;
                            }
                        }
                    }
                    if (!File.Exists(fileOrSessionName))
                        throw new FileNotFoundException("Unable to find the file " + fileOrSessionName);
                }
                primaryLogFile.LogFileName = fileOrSessionName;
            }

            // Open the main data source
            if (handles == null)
                handles = new ulong[1];

            handles[0] = TraceEventNativeMethods.OpenTrace(ref primaryLogFile);

            if (TraceEventNativeMethods.INVALID_HANDLE_VALUE == handles[0])
                Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());

            // Session offset time is the minimum of all times.
            sessionStartTime100ns = primaryLogFile.LogfileHeader.StartTime;
            if (handles.Length == 2 && kernelModeLogFile.LogfileHeader.StartTime < sessionStartTime100ns)
                sessionStartTime100ns = kernelModeLogFile.LogfileHeader.StartTime;

            // Real time providers don't set this to something useful
            if (sessionStartTime100ns == 0)
                sessionStartTime100ns = now;

            sessionEndTime100ns = primaryLogFile.LogfileHeader.EndTime;
            if (handles.Length == 2 && sessionEndTime100ns < kernelModeLogFile.LogfileHeader.EndTime)
                sessionEndTime100ns = kernelModeLogFile.LogfileHeader.EndTime;

            if (sessionEndTime100ns == 0)
                sessionEndTime100ns = sessionStartTime100ns;

            // TODO remove when we do per-event stuff.
            pointerSize = (int)primaryLogFile.LogfileHeader.PointerSize;
            if (handles.Length == 2)
                pointerSize = (int) kernelModeLogFile.LogfileHeader.PointerSize;

            if (pointerSize == 0)
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((primaryLogFile.LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            eventsLost = (int)primaryLogFile.LogfileHeader.EventsLost;
            cpuSpeedMHz = (int)primaryLogFile.LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)primaryLogFile.LogfileHeader.NumberOfProcessors;

            // Logic for looking up process names
            processNameForID = new Dictionary<int, string>();
            Kernel.ProcessStartGroup += delegate(ProcessTraceData data) {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures.
                string path = data.KernelImageFileName;
                int startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                    startIdx++;
                else
                    startIdx = 0;
                int endIdx = path.LastIndexOf('.', startIdx);
                if (endIdx < 0)
                    endIdx = path.Length;
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
        }
 public static Task<bool> RealTimeTraceEventSessionAsync
                     (
                         string providerName
                         , string sessionName
                         , string tracingFileName = null
                         , string[] traceEvents = null
                         , Action
                                 <
                                     long
                                     , TraceEventDispatcher
                                     , TraceEventSession
                                     , TraceEvent
                                 > onOneEventTracedOnceProcessAction = null
                         , TraceEventProviderOptions traceEventProviderOptions = null
                         , TraceEventSessionOptions traceEventSessionOptions = TraceEventSessionOptions.Create
                         , TraceEventSourceType traceEventSourceType = TraceEventSourceType.MergeAll
                         , TraceEventLevel traceEventLevel = TraceEventLevel.Always
                         , ulong matchKeywords = ulong.MaxValue
                         , bool needCountHits = false
                     )
 {
     return
         Task
             .Factory
             .StartNew<bool>
                 (
                     () =>
                     {
                         return
                             RealTimeTraceEventSession
                                 (
                                     providerName
                                     , sessionName
                                     , tracingFileName
                                     , traceEvents
                                     , onOneEventTracedOnceProcessAction
                                     , traceEventProviderOptions
                                     , traceEventSessionOptions
                                     , traceEventSourceType
                                     , traceEventLevel
                                     , matchKeywords
                                     , needCountHits
                                 );
                     }
                     ,
                         TaskCreationOptions.LongRunning
                         |
                         TaskCreationOptions.DenyChildAttach
                 );
 }
        public static bool TraceETWTraceEventSource
        (
            string providerName
            , string tracedFileName
            , string[] traceEvents = null
            , Action
            <
                long
                , TraceEventDispatcher
                , TraceEventSession
                , TraceEvent
            > onOneEventTracedOnceProcessAction = null
            , TraceEventProviderOptions traceEventProviderOptions = null
            , TraceEventSourceType traceEventSourceType           = TraceEventSourceType.MergeAll
            , TraceEventLevel traceEventLevel = TraceEventLevel.Always
            , ulong matchKeywords             = ulong.MaxValue
            , bool needCountHits = false
        )
        {
            var r = false;

            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Out.WriteLine("To turn on ETW events you need to be Administrator, please run from an Admin process.");
                return(r);
            }
            if
            (
                traceEvents != null
                &&
                traceEvents.Length > 0
                &&
                onOneEventTracedOnceProcessAction != null
            )
            {
                using (var source = new ETWTraceEventSource(tracedFileName, traceEventSourceType))
                {
                    //闭包
                    long sequence = 0;
                    RegisterCallbacks
                    (
                        providerName
                        , traceEvents
                        , source
                        , null
                        , (x, y, z) =>
                    {
                        long id = 0;
                        if (needCountHits)
                        {
                            id = Interlocked.Increment(ref sequence);
                        }
                        onOneEventTracedOnceProcessAction
                        (
                            id
                            , x
                            , y
                            , z
                        );
                    }
                    );
                    source.Process();   // call the callbacks for each event
                }
            }
            return(true);
        }
        /// <summary>
        /// Open a ETW event source for processing.  This can either be a moduleFile or a real time ETW session
        /// </summary>
        /// <param name="fileOrSessionName">
        /// If type == ModuleFile this is the name of the moduleFile to open.
        /// If type == Session this is the name of real time sessing to open.</param>
        /// <param name="type"></param>
        // [SecuritySafeCritical]
        public ETWTraceEventSource(string fileOrSessionName, TraceEventSourceType type)
        {
            long now = DateTime.Now.ToFileTime() - 100000;     // used as the start time for real time sessions (sub 10msec to avoid negative times)

            // Allocate the LOGFILE and structures and arrays that hold them  
            // Figure out how many log files we have
            if (type == TraceEventSourceType.MergeAll)
            {
                string fileBaseName = Path.GetFileNameWithoutExtension(fileOrSessionName);
                string dir = Path.GetDirectoryName(fileOrSessionName);
                if (dir.Length == 0)
                    dir = ".";
                List<string> allLogFiles = new List<string>();
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".etl"));
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".kernel.etl"));
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".clr*.etl"));
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".user*.etl"));

                if (allLogFiles.Count == 0)
                    throw new FileNotFoundException("Could not find file     " + fileOrSessionName);

                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[allLogFiles.Count];
                for (int i = 0; i < allLogFiles.Count; i++)
                    logFiles[i].LogFileName = allLogFiles[i];
            }
            else
            {
                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[1];
                if (type == TraceEventSourceType.FileOnly)
                    logFiles[0].LogFileName = fileOrSessionName;
                else
                {
                    Debug.Assert(type == TraceEventSourceType.Session);
                    logFiles[0].LoggerName = fileOrSessionName;
                    logFiles[0].LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
                }
            }
            handles = new ulong[logFiles.Length];

            // Fill  out the first log file information (we will clone it later if we have mulitple files). 
            logFiles[0].BufferCallback = this.TraceEventBufferCallback;
            handles[0] = TraceEventNativeMethods.INVALID_HANDLE_VALUE;
            useClassicETW = Environment.OSVersion.Version.Major < 6;
            if (useClassicETW)
            {
                IntPtr mem = Marshal.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, (uint)sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader = (TraceEventNativeMethods.EVENT_RECORD*)mem;
                logFiles[0].EventCallback = RawDispatchClassic;
            }
            else
            {
                logFiles[0].LogFileMode |= TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                logFiles[0].EventCallback = RawDispatch;
            }
            // We want the raw timestamp because it is needed to match up stacks with the event they go with.  
            logFiles[0].LogFileMode |= TraceEventNativeMethods.PROCESS_TRACE_MODE_RAW_TIMESTAMP;

            // Copy the information to any additional log files 
            for (int i = 1; i < logFiles.Length; i++)
            {
                logFiles[i].BufferCallback = logFiles[0].BufferCallback;
                logFiles[i].EventCallback = logFiles[0].EventCallback;
                logFiles[i].LogFileMode = logFiles[0].LogFileMode;
                handles[i] = handles[0];
            }

            sessionStartTime100ns = long.MaxValue;
            sessionEndTime100ns = long.MinValue;
            eventsLost = 0;

            // Open all the traces
            for (int i = 0; i < handles.Length; i++)
            {
                handles[i] = TraceEventNativeMethods.OpenTrace(ref logFiles[i]);
                if (handles[i] == TraceEventNativeMethods.INVALID_HANDLE_VALUE)
                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());

                // Start time is minimum of all start times 
                if (logFiles[i].LogfileHeader.StartTime < sessionStartTime100ns)
                    sessionStartTime100ns = logFiles[i].LogfileHeader.StartTime;
                // End time is maximum of all start times
                if (logFiles[i].LogfileHeader.EndTime > sessionEndTime100ns)
                    sessionEndTime100ns = logFiles[i].LogfileHeader.EndTime;

                // TODO do we even need log pointer size anymore?   
                // We take the max pointer size.  
                if ((int)logFiles[i].LogfileHeader.PointerSize > pointerSize)
                    pointerSize = (int)logFiles[i].LogfileHeader.PointerSize;

                eventsLost += (int)logFiles[i].LogfileHeader.EventsLost;
            }

            // Real time providers don't set this to something useful
            if (sessionStartTime100ns == 0)
                sessionStartTime100ns = now;
            if (sessionEndTime100ns == 0)
                sessionEndTime100ns = long.MaxValue;

            if (pointerSize == 0)       // Real time does not set this (grrr). 
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            cpuSpeedMHz = (int)logFiles[0].LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)logFiles[0].LogfileHeader.NumberOfProcessors;
            _QPCFreq = logFiles[0].LogfileHeader.PerfFreq;
            if (_QPCFreq == 0)          // Real time does not set this all the time 
            {
                _QPCFreq = Stopwatch.Frequency;
                Debug.Assert((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(_QPCFreq != 0);
            int ver = (int) logFiles[0].LogfileHeader.Version;
            osVersion = new Version((byte) ver, (byte) (ver>> 8));

            // Logic for looking up process names
            processNameForID = new Dictionary<int, string>();
            Kernel.ProcessStartGroup += delegate(ProcessTraceData data)
            {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures. 
                string path = data.KernelImageFileName;
                int startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                    startIdx++;
                else
                    startIdx = 0;
                int endIdx = path.LastIndexOf('.');
                if (endIdx <= startIdx) 
                    endIdx = path.Length;
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
        }
Exemplo n.º 16
0
        /// <summary>
        /// Open a ETW event source for processing.  This can either be a moduleFile or a real time ETW session
        /// </summary>
        /// <param name="fileOrSessionName">
        /// If type == ModuleFile this is the name of the moduleFile to open.
        /// If type == Session this is the name of real time sessing to open.</param>
        /// <param name="type"></param>
        // [SecuritySafeCritical]
        public ETWTraceEventSource(string fileOrSessionName, TraceEventSourceType type)
        {
            long now = DateTime.Now.ToFileTime() - 100000;     // used as the start time for real time sessions (sub 10msec to avoid negative times)

            // Allocate the LOGFILE and structures and arrays that hold them
            // Figure out how many log files we have
            if (type == TraceEventSourceType.MergeAll)
            {
                string fileBaseName = Path.GetFileNameWithoutExtension(fileOrSessionName);
                string dir          = Path.GetDirectoryName(fileOrSessionName);
                if (dir.Length == 0)
                {
                    dir = ".";
                }
                List <string> allLogFiles = new List <string>();
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".etl"));
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".kernel.etl"));
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".clr*.etl"));
                allLogFiles.AddRange(Directory.GetFiles(dir, fileBaseName + ".user*.etl"));

                if (allLogFiles.Count == 0)
                {
                    throw new FileNotFoundException("Could not find file     " + fileOrSessionName);
                }

                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[allLogFiles.Count];
                for (int i = 0; i < allLogFiles.Count; i++)
                {
                    logFiles[i].LogFileName = allLogFiles[i];
                }
            }
            else
            {
                logFiles = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW[1];
                if (type == TraceEventSourceType.FileOnly)
                {
                    logFiles[0].LogFileName = fileOrSessionName;
                }
                else
                {
                    Debug.Assert(type == TraceEventSourceType.Session);
                    logFiles[0].LoggerName   = fileOrSessionName;
                    logFiles[0].LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
                }
            }
            handles = new ulong[logFiles.Length];

            // Fill  out the first log file information (we will clone it later if we have mulitple files).
            logFiles[0].BufferCallback = this.TraceEventBufferCallback;
            handles[0]    = TraceEventNativeMethods.INVALID_HANDLE_VALUE;
            useClassicETW = Environment.OSVersion.Version.Major < 6;
            if (useClassicETW)
            {
                IntPtr mem = Marshal.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, (uint)sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader           = (TraceEventNativeMethods.EVENT_RECORD *)mem;
                logFiles[0].EventCallback = RawDispatchClassic;
            }
            else
            {
                logFiles[0].LogFileMode  |= TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                logFiles[0].EventCallback = RawDispatch;
            }
            // We want the raw timestamp because it is needed to match up stacks with the event they go with.
            logFiles[0].LogFileMode |= TraceEventNativeMethods.PROCESS_TRACE_MODE_RAW_TIMESTAMP;

            // Copy the information to any additional log files
            for (int i = 1; i < logFiles.Length; i++)
            {
                logFiles[i].BufferCallback = logFiles[0].BufferCallback;
                logFiles[i].EventCallback  = logFiles[0].EventCallback;
                logFiles[i].LogFileMode    = logFiles[0].LogFileMode;
                handles[i] = handles[0];
            }

            sessionStartTime100ns = long.MaxValue;
            sessionEndTime100ns   = long.MinValue;
            eventsLost            = 0;

            // Open all the traces
            for (int i = 0; i < handles.Length; i++)
            {
                handles[i] = TraceEventNativeMethods.OpenTrace(ref logFiles[i]);
                if (handles[i] == TraceEventNativeMethods.INVALID_HANDLE_VALUE)
                {
                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());
                }

                // Start time is minimum of all start times
                if (logFiles[i].LogfileHeader.StartTime < sessionStartTime100ns)
                {
                    sessionStartTime100ns = logFiles[i].LogfileHeader.StartTime;
                }
                // End time is maximum of all start times
                if (logFiles[i].LogfileHeader.EndTime > sessionEndTime100ns)
                {
                    sessionEndTime100ns = logFiles[i].LogfileHeader.EndTime;
                }

                // TODO do we even need log pointer size anymore?
                // We take the max pointer size.
                if ((int)logFiles[i].LogfileHeader.PointerSize > pointerSize)
                {
                    pointerSize = (int)logFiles[i].LogfileHeader.PointerSize;
                }

                eventsLost += (int)logFiles[i].LogfileHeader.EventsLost;
            }

            // Real time providers don't set this to something useful
            if (sessionStartTime100ns == 0)
            {
                sessionStartTime100ns = now;
            }
            if (sessionEndTime100ns == 0)
            {
                sessionEndTime100ns = long.MaxValue;
            }

            if (pointerSize == 0)       // Real time does not set this (grrr).
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            cpuSpeedMHz        = (int)logFiles[0].LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)logFiles[0].LogfileHeader.NumberOfProcessors;
            _QPCFreq           = logFiles[0].LogfileHeader.PerfFreq;
            if (_QPCFreq == 0)          // Real time does not set this all the time
            {
                _QPCFreq = Stopwatch.Frequency;
                Debug.Assert((logFiles[0].LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(_QPCFreq != 0);
            int ver = (int)logFiles[0].LogfileHeader.Version;

            osVersion = new Version((byte)ver, (byte)(ver >> 8));

            // Logic for looking up process names
            processNameForID          = new Dictionary <int, string>();
            Kernel.ProcessStartGroup += delegate(ProcessTraceData data)
            {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures.
                string path     = data.KernelImageFileName;
                int    startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                {
                    startIdx++;
                }
                else
                {
                    startIdx = 0;
                }
                int endIdx = path.LastIndexOf('.');
                if (endIdx <= startIdx)
                {
                    endIdx = path.Length;
                }
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
        }
        public static bool RealTimeTraceEventSession
        (
            string providerName
            , string sessionName
            , string tracingFileName = null
            , string[] traceEvents   = null
            , Action
            <
                long
                , TraceEventDispatcher
                , TraceEventSession
                , TraceEvent
            > onOneEventTracedOnceProcessAction = null
            , TraceEventProviderOptions traceEventProviderOptions = null
            , TraceEventSessionOptions traceEventSessionOptions   = TraceEventSessionOptions.Create
            , TraceEventSourceType traceEventSourceType           = TraceEventSourceType.MergeAll
            , TraceEventLevel traceEventLevel = TraceEventLevel.Always
            , ulong matchKeywords             = ulong.MaxValue
            , bool needCountHits = false
        )
        {
            var r = false;

            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Out.WriteLine("To turn on ETW events you need to be Administrator, please run from an Admin process.");
                return(r);
            }
            var needTracingFile = !string.IsNullOrEmpty(tracingFileName);

            if
            (
                traceEvents != null
                &&
                traceEvents.Length > 0
                &&
                onOneEventTracedOnceProcessAction != null
            )
            {
                using
                (
                    var session =
                        (
                            needTracingFile
                                    ?
                            new TraceEventSession
                            (
                                sessionName
                                , tracingFileName
                                , traceEventSessionOptions
                            )
                {
                    StopOnDispose = true
                }
                                    :
                            new TraceEventSession
                            (
                                sessionName
                                , traceEventSessionOptions
                            )
                {
                    StopOnDispose = true
                }
                        )
                )
                {
                    using
                    (
                        var source =
                            (
                                needTracingFile
                                            ?
                                new ETWTraceEventSource(tracingFileName)
                                            :
                                session.Source
                            )
                    )
                    {
                        long sequence = 0;
                        RegisterCallbacks
                        (
                            providerName
                            , traceEvents
                            , source
                            , session
                            , (x, y, z) =>
                        {
                            long id = 0;
                            if (needCountHits)
                            {
                                id = Interlocked.Increment(ref sequence);
                            }
                            onOneEventTracedOnceProcessAction
                            (
                                id
                                , x
                                , y
                                , z
                            );
                        }
                        );
                        var restarted = session
                                        .EnableProvider
                                        (
                            providerName
                            , traceEventLevel
                            , matchKeywords
                            , traceEventProviderOptions
                                        );
                        source
                        .Process();
                        r = true;
                    }
                }
            }
            return(r);
        }
        public static bool RealTimeTraceEventSession
            (
                string providerName
                , string sessionName
                , string tracingFileName = null
                , string[] traceEvents = null
                , Action
                        <
                            long
                            , TraceEventDispatcher
                            , TraceEventSession
                            , TraceEvent
                        > onOneEventTracedOnceProcessAction = null
                , TraceEventProviderOptions traceEventProviderOptions = null
                , TraceEventSessionOptions traceEventSessionOptions = TraceEventSessionOptions.Create
                , TraceEventSourceType traceEventSourceType = TraceEventSourceType.MergeAll
                , TraceEventLevel traceEventLevel = TraceEventLevel.Always
                , ulong matchKeywords = ulong.MaxValue
                , bool needCountHits = false
            )
        {
            var r = false;
            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Out.WriteLine("To turn on ETW events you need to be Administrator, please run from an Admin process.");
                return r;
            }
            var needTracingFile = !string.IsNullOrEmpty(tracingFileName);
            if
                (
                    traceEvents != null
                    &&
                    traceEvents.Length > 0
                    &&
                    onOneEventTracedOnceProcessAction != null
                )
            {
                using
                    (
                        var session =
                                (
                                    needTracingFile
                                    ?
                                    new TraceEventSession
                                                (
                                                    sessionName
                                                    , tracingFileName
                                                    , traceEventSessionOptions
                                                )
                                    {
                                        StopOnDispose = true
                                    }
                                    :
                                    new TraceEventSession
                                                (
                                                    sessionName
                                                    , traceEventSessionOptions
                                                )
                                    {
                                        StopOnDispose = true
                                    }
                                )
                    )
                {
                    using
                        (
                            var source =
                                        (
                                            needTracingFile
                                            ?
                                            new ETWTraceEventSource(tracingFileName)
                                            :
                                            session.Source
                                        )
                            )
                    {
                        long sequence = 0;
                        RegisterCallbacks
                            (
                                providerName
                                , traceEvents
                                , source
                                , session
                                , (x, y, z) =>
                                {
                                    long id = 0;
                                    if (needCountHits)
                                    {
                                        id = Interlocked.Increment(ref sequence);
                                    }
                                    onOneEventTracedOnceProcessAction
                                                    (
                                                        id
                                                        , x
                                                        , y
                                                        , z
                                                    );
                                }
                            );
                        var restarted = session
                                            .EnableProvider
                                                (
                                                    providerName
                                                    , traceEventLevel
                                                    , matchKeywords
                                                    , traceEventProviderOptions
                                                );
                        source
                            .Process();
                        r = true;
                    }
                }

            }
            return r;
        }
Exemplo n.º 19
0
        public ETWTraceEventSource(string fileOrSessionName, TraceEventSourceType type)
        {
            long now = DateTime.Now.ToFileTime() - 100000;     // subtract 10ms to avoid negative times.

            primaryLogFile = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW();
            primaryLogFile.BufferCallback = this.TraceEventBufferCallback;

            useClassicETW = Environment.OSVersion.Version.Major < 6;
            if (useClassicETW)
            {
                IntPtr mem = TraceEventNativeMethods.AllocHGlobal(sizeof(TraceEventNativeMethods.EVENT_RECORD));
                TraceEventNativeMethods.ZeroMemory(mem, (uint)sizeof(TraceEventNativeMethods.EVENT_RECORD));
                convertedHeader = (TraceEventNativeMethods.EVENT_RECORD *)mem;
                primaryLogFile.EventCallback = RawDispatchClassic;
            }
            else
            {
                primaryLogFile.LogFileMode   = TraceEventNativeMethods.PROCESS_TRACE_MODE_EVENT_RECORD;
                primaryLogFile.EventCallback = RawDispatch;
            }

            if (type == TraceEventSourceType.Session)
            {
                primaryLogFile.LoggerName   = fileOrSessionName;
                primaryLogFile.LogFileMode |= TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE;
            }
            else
            {
                if (type == TraceEventSourceType.UserAndKernelFile)
                {
                    // See if we have also have kernel log moduleFile.
                    if (fileOrSessionName.Length > 4 && string.Compare(fileOrSessionName, fileOrSessionName.Length - 4, ".etl", 0, 4, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        string kernelFileName = fileOrSessionName.Substring(0, fileOrSessionName.Length - 4) + ".kernel.etl";
                        if (File.Exists(kernelFileName))
                        {
                            if (File.Exists(fileOrSessionName))
                            {
                                handles    = new ulong[2];
                                handles[0] = TraceEventNativeMethods.INVALID_HANDLE_VALUE;

                                kernelModeLogFile = new TraceEventNativeMethods.EVENT_TRACE_LOGFILEW();
                                kernelModeLogFile.BufferCallback = primaryLogFile.BufferCallback;
                                kernelModeLogFile.EventCallback  = primaryLogFile.EventCallback;
                                kernelModeLogFile.LogFileName    = kernelFileName;
                                kernelModeLogFile.LogFileMode    = primaryLogFile.LogFileMode;

                                handles[1] = TraceEventNativeMethods.OpenTrace(ref kernelModeLogFile);

                                if (TraceEventNativeMethods.INVALID_HANDLE_VALUE == handles[1])
                                {
                                    Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());
                                }
                            }
                            else
                            {
                                // we have ONLY a *.kernel.etl moduleFile, treat it as the primary moduleFile.
                                fileOrSessionName = kernelFileName;
                            }
                        }
                    }
                    if (!File.Exists(fileOrSessionName))
                    {
                        throw new FileNotFoundException("Unable to find the file " + fileOrSessionName);
                    }
                }
                primaryLogFile.LogFileName = fileOrSessionName;
            }

            // Open the main data source
            if (handles == null)
            {
                handles = new ulong[1];
            }

            handles[0] = TraceEventNativeMethods.OpenTrace(ref primaryLogFile);

            if (TraceEventNativeMethods.INVALID_HANDLE_VALUE == handles[0])
            {
                Marshal.ThrowExceptionForHR(TraceEventNativeMethods.GetHRForLastWin32Error());
            }

            // Session offset time is the minimum of all times.
            sessionStartTime100ns = primaryLogFile.LogfileHeader.StartTime;
            if (handles.Length == 2 && kernelModeLogFile.LogfileHeader.StartTime < sessionStartTime100ns)
            {
                sessionStartTime100ns = kernelModeLogFile.LogfileHeader.StartTime;
            }

            // Real time providers don't set this to something useful
            if (sessionStartTime100ns == 0)
            {
                sessionStartTime100ns = now;
            }

            sessionEndTime100ns = primaryLogFile.LogfileHeader.EndTime;
            if (handles.Length == 2 && sessionEndTime100ns < kernelModeLogFile.LogfileHeader.EndTime)
            {
                sessionEndTime100ns = kernelModeLogFile.LogfileHeader.EndTime;
            }

            if (sessionEndTime100ns == 0)
            {
                sessionEndTime100ns = sessionStartTime100ns;
            }

            pointerSize = (int)primaryLogFile.LogfileHeader.PointerSize;
            if (handles.Length == 2)
            {
                pointerSize = (int)kernelModeLogFile.LogfileHeader.PointerSize;
            }

            if (pointerSize == 0)
            {
                pointerSize = sizeof(IntPtr);
                Debug.Assert((primaryLogFile.LogFileMode & TraceEventNativeMethods.EVENT_TRACE_REAL_TIME_MODE) != 0);
            }
            Debug.Assert(pointerSize == 4 || pointerSize == 8);

            eventsLost         = (int)primaryLogFile.LogfileHeader.EventsLost;
            cpuSpeedMHz        = (int)primaryLogFile.LogfileHeader.CpuSpeedInMHz;
            numberOfProcessors = (int)primaryLogFile.LogfileHeader.NumberOfProcessors;

            // Logic for looking up process names
            processNameForID          = new Dictionary <int, string>();
            Kernel.ProcessStartGroup += delegate(ProcessTraceData data) {
                // Get just the file name without the extension.  Can't use the 'Path' class because
                // it tests to make certain it does not have illegal chars etc.  Since KernelImageFileName
                // is not a true user mode path, we can get failures.
                string path     = data.KernelImageFileName;
                int    startIdx = path.LastIndexOf('\\');
                if (0 <= startIdx)
                {
                    startIdx++;
                }
                else
                {
                    startIdx = 0;
                }
                int endIdx = path.LastIndexOf('.', startIdx);
                if (endIdx < 0)
                {
                    endIdx = path.Length;
                }
                processNameForID[data.ProcessID] = path.Substring(startIdx, endIdx - startIdx);
            };
        }