private unsafe void DispatchEventsToEventListeners()
        {
            // Struct to fill with the call to GetNextEvent.
            EventPipeEventInstanceData instanceData;

            while (!m_stopDispatchTask)
            {
                bool eventsReceived = false;
                // Get the next event.
                while (!m_stopDispatchTask && EventPipeInternal.GetNextEvent(m_sessionID, &instanceData))
                {
                    eventsReceived = true;

                    // Filter based on provider.
                    if (instanceData.ProviderID == m_RuntimeProviderID)
                    {
                        // Dispatch the event.
                        ReadOnlySpan <byte> payload       = new ReadOnlySpan <byte>((void *)instanceData.Payload, (int)instanceData.PayloadLength);
                        DateTime            dateTimeStamp = TimeStampToDateTime(instanceData.TimeStamp);
                        NativeRuntimeEventSource.Log.ProcessEvent(instanceData.EventID, instanceData.ThreadID, dateTimeStamp, instanceData.ActivityId, instanceData.ChildActivityId, payload);
                    }
                }

                // Wait for more events.
                if (!m_stopDispatchTask)
                {
                    if (!eventsReceived)
                    {
                        EventPipeInternal.WaitForSessionSignal(m_sessionID, Timeout.Infinite);
                    }

                    Thread.Sleep(10);
                }
            }
        }
Пример #2
0
        private unsafe void DispatchEventsToEventListeners()
        {
            // Struct to fill with the call to GetNextEvent.
            EventPipeEventInstanceData instanceData;

            while (!m_stopDispatchTask)
            {
                // Get the next event.
                while (!m_stopDispatchTask && EventPipeInternal.GetNextEvent(&instanceData))
                {
                    // Filter based on provider.
                    if (instanceData.ProviderID == m_RuntimeProviderID)
                    {
                        // Dispatch the event.
                        ReadOnlySpan <Byte> payload       = new ReadOnlySpan <byte>((void *)instanceData.Payload, (int)instanceData.PayloadLength);
                        DateTime            dateTimeStamp = TimeStampToDateTime(instanceData.TimeStamp);
                        RuntimeEventSource.Log.ProcessEvent(instanceData.EventID, instanceData.ThreadID, dateTimeStamp, instanceData.ActivityId, instanceData.ChildActivityId, payload);
                    }
                }

                // Wait for more events.
                if (!m_stopDispatchTask)
                {
                    Thread.Sleep(10);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// When a thread starts work that is on behalf of 'something else' (typically another
        /// thread or network request) it should mark the thread as working on that other work.
        /// This API marks the current thread as working on activity 'activityID'. It returns
        /// whatever activity the thread was previously marked with. There is a convention that
        /// callers can assume that callees restore this activity mark before the callee returns.
        /// To encourage this, this API returns the old activity, so that it can be restored later.
        ///
        /// All events created with the EventSource on this thread are also tagged with the
        /// activity ID of the thread.
        ///
        /// It is common, and good practice after setting the thread to an activity to log an event
        /// with a 'start' opcode to indicate that precise time/thread where the new activity
        /// started.
        /// </summary>
        /// <param name="activityId">A Guid that represents the new activity with which to mark
        /// the current thread</param>
        /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
        /// which will continue at some point in the future, on the current thread</param>
        public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
        {
            oldActivityThatWillContinue = activityId;
#if FEATURE_MANAGED_ETW
            // We ignore errors to keep with the convention that EventSources do not throw errors.
            // Note we can't access m_throwOnWrites because this is a static method.

#if FEATURE_PERFTRACING && PLATFORM_WINDOWS
            EventPipeInternal.EventActivityIdControl(
                (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
                ref oldActivityThatWillContinue);
#elif FEATURE_PERFTRACING
            EventPipeInternal.EventActivityIdControl(
                (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
                ref oldActivityThatWillContinue);
#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS

#if PLATFORM_WINDOWS
            UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
                UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
                ref oldActivityThatWillContinue);
#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW

            // We don't call the activityDying callback here because the caller has declared that
            // it is not dying.
            if (TplEtwProvider.Log != null)
            {
                TplEtwProvider.Log.SetActivityId(activityId);
            }
        }
Пример #4
0
        // Write an event.
        unsafe int IEventProvider.EventWriteTransferWrapper(
            long registrationHandle,
            ref EventDescriptor eventDescriptor,
            IntPtr eventHandle,
            Guid *activityId,
            Guid *relatedActivityId,
            int userDataCount,
            EventProvider.EventData *userData)
        {
            uint eventID = (uint)eventDescriptor.EventId;

            if (eventID != 0 && eventHandle != IntPtr.Zero)
            {
                if (userDataCount == 0)
                {
                    EventPipeInternal.WriteEventData(eventHandle, eventID, null, 0, activityId, relatedActivityId);
                    return(0);
                }

                // If Channel == 11, this is a TraceLogging event.
                // The first 3 descriptors contain event metadata that is emitted for ETW and should be discarded on EventPipe.
                // EventPipe metadata is provided via the EventPipeEventProvider.DefineEventHandle.
                if (eventDescriptor.Channel == 11)
                {
                    userData      = userData + 3;
                    userDataCount = userDataCount - 3;
                    Debug.Assert(userDataCount >= 0);
                }
                EventPipeInternal.WriteEventData(eventHandle, eventID, userData, (uint)userDataCount, activityId, relatedActivityId);
            }
            return(0);
        }
        private void CommitDispatchConfiguration()
        {
            Debug.Assert(Monitor.IsEntered(m_dispatchControlLock));

            // Ensure that the dispatch task is stopped.
            // This is a no-op if the task is already stopped.
            StopDispatchTask();

            // Stop tracing.
            // This is a no-op if it's already disabled.
            EventPipeInternal.Disable(m_sessionID);

            // Check to see if tracing should be enabled.
            if (m_subscriptions.Count <= 0)
            {
                return;
            }

            // Determine the keywords and level that should be used based on the set of enabled EventListeners.
            EventKeywords aggregatedKeywords = EventKeywords.None;
            EventLevel    highestLevel       = EventLevel.LogAlways;

            foreach (EventListenerSubscription subscription in m_subscriptions.Values)
            {
                aggregatedKeywords |= subscription.MatchAnyKeywords;
                highestLevel        = (subscription.Level > highestLevel) ? subscription.Level : highestLevel;
            }

            // Enable the EventPipe session.
            EventPipeProviderConfiguration[] providerConfiguration = new EventPipeProviderConfiguration[]
            {
                new EventPipeProviderConfiguration(RuntimeEventSource.EventSourceName, (ulong)aggregatedKeywords, (uint)highestLevel, null)
            };

            m_sessionID = EventPipeInternal.Enable(null, 1024, 1, providerConfiguration, 1, 0);
            Debug.Assert(m_sessionID != 0);

            // Get the session information that is required to properly dispatch events.
            EventPipeSessionInfo sessionInfo;

            unsafe
            {
                if (!EventPipeInternal.GetSessionInfo(m_sessionID, &sessionInfo))
                {
                    Debug.Assert(false, "GetSessionInfo returned false.");
                }
            }

            m_syncTimeUtc      = DateTime.FromFileTimeUtc(sessionInfo.StartTimeAsUTCFileTime);
            m_syncTimeQPC      = sessionInfo.StartTimeStamp;
            m_timeQPCFrequency = sessionInfo.TimeStampFrequency;

            // Start the dispatch task.
            StartDispatchTask();
        }
        private void StopDispatchTask()
        {
            Debug.Assert(Monitor.IsEntered(m_dispatchControlLock));

            if (m_dispatchTask != null)
            {
                m_stopDispatchTask = true;
                EventPipeInternal.SignalSession(m_sessionID);
                m_dispatchTask.Wait();
                m_dispatchTask = null;
            }
        }
Пример #7
0
        private void StartDispatchTask()
        {
            Debug.Assert(Monitor.IsEntered(m_dispatchControlLock));

            if (m_dispatchTask == null)
            {
                m_stopDispatchTask = false;
                // Create a SafeWaitHandle that won't release the handle when done
                m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(EventPipeInternal.GetWaitHandle(m_sessionID), false);

                m_dispatchTask = Task.Factory.StartNew(DispatchEventsToEventListeners, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
            }
        }
Пример #8
0
        // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
        /// <summary>
        /// When a thread starts work that is on behalf of 'something else' (typically another
        /// thread or network request) it should mark the thread as working on that other work.
        /// This API marks the current thread as working on activity 'activityID'. This API
        /// should be used when the caller knows the thread's current activity (the one being
        /// overwritten) has completed. Otherwise, callers should prefer the overload that
        /// return the oldActivityThatWillContinue (below).
        ///
        /// All events created with the EventSource on this thread are also tagged with the
        /// activity ID of the thread.
        ///
        /// It is common, and good practice after setting the thread to an activity to log an event
        /// with a 'start' opcode to indicate that precise time/thread where the new activity
        /// started.
        /// </summary>
        /// <param name="activityId">A Guid that represents the new activity with which to mark
        /// the current thread</param>
        public static void SetCurrentThreadActivityId(Guid activityId)
        {
            if (TplEtwProvider.Log != null)
            {
                TplEtwProvider.Log.SetActivityId(activityId);
            }
#if FEATURE_MANAGED_ETW
#if FEATURE_ACTIVITYSAMPLING
            Guid newId = activityId;
#endif // FEATURE_ACTIVITYSAMPLING
            // We ignore errors to keep with the convention that EventSources do not throw errors.
            // Note we can't access m_throwOnWrites because this is a static method.

#if FEATURE_PERFTRACING && PLATFORM_WINDOWS
            // Set the activity id via EventPipe.
            EventPipeInternal.EventActivityIdControl(
                (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
                ref activityId);

            // Set the activity id via ETW and fetch the previous id.
            if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
                    UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
                    ref activityId) == 0)
#elif FEATURE_PERFTRACING
            if (EventPipeInternal.EventActivityIdControl(
                    (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
                    ref activityId) == 0)
#elif PLATFORM_WINDOWS
            if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
                    UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
                    ref activityId) == 0)
#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS
            {
#if FEATURE_ACTIVITYSAMPLING
                var activityDying = s_activityDying;
                if (activityDying != null && newId != activityId)
                {
                    if (activityId == Guid.Empty)
                    {
                        activityId = FallbackActivityId;
                    }
                    // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId));
                    activityDying(activityId);     // This is actually the OLD activity ID.
                }
#endif // FEATURE_ACTIVITYSAMPLING
            }
#endif // FEATURE_MANAGED_ETW
        }
Пример #9
0
        internal static void Enable(EventPipeConfiguration configuration)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            EventPipeProviderConfiguration[] providers = configuration.Providers;

            EventPipeInternal.Enable(
                configuration.OutputFile,
                configuration.CircularBufferSizeInMB,
                configuration.ProfilerSamplingRateInNanoseconds,
                providers,
                providers.Length);
        }
Пример #10
0
        internal static void Enable(EventPipeConfiguration configuration)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (configuration.Providers == null)
            {
                throw new ArgumentNullException(nameof(configuration.Providers));
            }

            EventPipeProviderConfiguration[] providers = configuration.Providers;

            s_sessionID = EventPipeInternal.Enable(
                configuration.OutputFile,
                configuration.Format,
                configuration.CircularBufferSizeInMB,
                providers);
        }
Пример #11
0
        // Write an event.
        unsafe int IEventProvider.EventWriteTransferWrapper(
            long registrationHandle,
            ref EventDescriptor eventDescriptor,
            IntPtr eventHandle,
            Guid *activityId,
            Guid *relatedActivityId,
            int userDataCount,
            EventProvider.EventData *userData)
        {
            uint eventID = (uint)eventDescriptor.EventId;

            if (eventID != 0 && eventHandle != IntPtr.Zero)
            {
                if (userDataCount == 0)
                {
                    EventPipeInternal.WriteEvent(eventHandle, eventID, null, 0, activityId, relatedActivityId);
                    return(0);
                }

                uint length = 0;
                for (int i = 0; i < userDataCount; i++)
                {
                    length += userData[i].Size;
                }

                byte[] data = new byte[length];
                fixed(byte *pData = data)
                {
                    uint offset = 0;

                    for (int i = 0; i < userDataCount; i++)
                    {
                        byte *singleUserDataPtr  = (byte *)(userData[i].Ptr);
                        uint  singleUserDataSize = userData[i].Size;
                        WriteToBuffer(pData, length, ref offset, singleUserDataPtr, singleUserDataSize);
                    }
                    EventPipeInternal.WriteEvent(eventHandle, eventID, pData, length, activityId, relatedActivityId);
                }
            }
            return(0);
        }
Пример #12
0
        internal static void Enable(EventPipeConfiguration configuration)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (configuration.Providers == null)
            {
                throw new ArgumentNullException(nameof(configuration.Providers));
            }

            EventPipeProviderConfiguration[] providers = configuration.Providers;

            s_sessionID = EventPipeInternal.Enable(
                configuration.OutputFile,
                configuration.CircularBufferSizeInMB,
                (ulong)configuration.ProfilerSamplingRateInNanoseconds,
                providers,
                (uint)providers.Length,
                configuration.MultiFileTraceLengthInSeconds);
        }
Пример #13
0
        // Write an event.
        unsafe int IEventProvider.EventWriteTransferWrapper(
            long registrationHandle,
            ref EventDescriptor eventDescriptor,
            IntPtr eventHandle,
            Guid *activityId,
            Guid *relatedActivityId,
            int userDataCount,
            EventProvider.EventData *userData)
        {
            uint eventID = (uint)eventDescriptor.EventId;

            if (eventID != 0 && eventHandle != IntPtr.Zero)
            {
                if (userDataCount == 0)
                {
                    EventPipeInternal.WriteEventData(eventHandle, eventID, null, 0, activityId, relatedActivityId);
                    return(0);
                }

                EventPipeInternal.WriteEventData(eventHandle, eventID, &userData, (uint)userDataCount, activityId, relatedActivityId);
            }
            return(0);
        }
Пример #14
0
        // Register an event provider.
        unsafe uint IEventProvider.EventRegister(
            EventSource eventSource,
            UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
            void *callbackContext,
            ref long registrationHandle)
        {
            uint returnStatus = 0;

            m_provHandle = EventPipeInternal.CreateProvider(eventSource.Name, enableCallback);
            if (m_provHandle != IntPtr.Zero)
            {
                // Fixed registration handle because a new EventPipeEventProvider
                // will be created for each new EventSource.
                registrationHandle = 1;
            }
            else
            {
                // Unable to create the provider.
                returnStatus = 1;
            }

            return(returnStatus);
        }
Пример #15
0
        private unsafe void DispatchEventsToEventListeners()
        {
            // Struct to fill with the call to GetNextEvent.
            EventPipeEventInstanceData instanceData;

            while (!m_stopDispatchTask)
            {
                bool eventsReceived = false;
                // Get the next event.
                while (!m_stopDispatchTask && EventPipeInternal.GetNextEvent(m_sessionID, &instanceData))
                {
                    eventsReceived = true;

                    // Filter based on provider.
                    if (instanceData.ProviderID == m_RuntimeProviderID)
                    {
                        // Dispatch the event.
                        ReadOnlySpan <Byte> payload       = new ReadOnlySpan <byte>((void *)instanceData.Payload, (int)instanceData.PayloadLength);
                        DateTime            dateTimeStamp = TimeStampToDateTime(instanceData.TimeStamp);
                        NativeRuntimeEventSource.Log.ProcessEvent(instanceData.EventID, instanceData.ThreadID, dateTimeStamp, instanceData.ActivityId, instanceData.ChildActivityId, payload);
                    }
                }

                // Wait for more events.
                if (!m_stopDispatchTask)
                {
                    if (!eventsReceived)
                    {
                        // Future TODO: this would make more sense to handle in EventPipeSession/EventPipe native code.
                        Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid);
                        m_dispatchTaskWaitHandle.WaitOne();
                    }

                    Thread.Sleep(10);
                }
            }
        }
Пример #16
0
        // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
        /// <summary>
        /// When a thread starts work that is on behalf of 'something else' (typically another
        /// thread or network request) it should mark the thread as working on that other work.
        /// This API marks the current thread as working on activity 'activityID'. This API
        /// should be used when the caller knows the thread's current activity (the one being
        /// overwritten) has completed. Otherwise, callers should prefer the overload that
        /// return the oldActivityThatWillContinue (below).
        ///
        /// All events created with the EventSource on this thread are also tagged with the
        /// activity ID of the thread.
        ///
        /// It is common, and good practice after setting the thread to an activity to log an event
        /// with a 'start' opcode to indicate that precise time/thread where the new activity
        /// started.
        /// </summary>
        /// <param name="activityId">A Guid that represents the new activity with which to mark
        /// the current thread</param>
        public static void SetCurrentThreadActivityId(Guid activityId)
        {
            if (TplEventSource.Log != null)
            {
                TplEventSource.Log.SetActivityId(activityId);
            }

            // We ignore errors to keep with the convention that EventSources do not throw errors.
            // Note we can't access m_throwOnWrites because this is a static method.
#if FEATURE_MANAGED_ETW
#if FEATURE_PERFTRACING
            // Set the activity id via EventPipe.
            EventPipeInternal.EventActivityIdControl(
                (uint)UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
                ref activityId);
#endif // FEATURE_PERFTRACING
#if PLATFORM_WINDOWS
            // Set the activity id via ETW.
            UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
                UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
                ref activityId);
#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW
        }
Пример #17
0
        private void CommitDispatchConfiguration()
        {
            // Ensure that the dispatch task is stopped.
            // This is a no-op if the task is already stopped.
            StopDispatchTask();

            // Stop tracing.
            // This is a no-op if it's already disabled.
            EventPipeInternal.Disable();

            // Check to see if tracing should be enabled.
            if (m_subscriptions.Count <= 0)
            {
                return;
            }

            // Start collecting events.
            EventKeywords aggregatedKeywords = EventKeywords.None;
            EventLevel    highestLevel       = EventLevel.LogAlways;

            foreach (EventListenerSubscription subscription in m_subscriptions.Values)
            {
                aggregatedKeywords |= subscription.MatchAnyKeywords;
                highestLevel        = (subscription.Level > highestLevel) ? subscription.Level : highestLevel;
            }

            EventPipeProviderConfiguration[] providerConfiguration = new EventPipeProviderConfiguration[]
            {
                new EventPipeProviderConfiguration(RuntimeEventSource.EventSourceName, (ulong)aggregatedKeywords, (uint)highestLevel)
            };

            EventPipeInternal.Enable(null, 1024, 1, providerConfiguration, 1);

            // Start the dispatch task.
            StartDispatchTask();
        }
Пример #18
0
 // Unregister an event provider.
 uint IEventProvider.EventUnregister(long registrationHandle)
 {
     EventPipeInternal.DeleteProvider(m_provHandle);
     return(0);
 }
 private EventPipeEventDispatcher()
 {
     // Get the ID of the runtime provider so that it can be used as a filter when processing events.
     m_RuntimeProviderID = EventPipeInternal.GetProvider(RuntimeEventSource.EventSourceName);
 }
Пример #20
0
 private EventPipeEventDispatcher()
 {
     // Get the ID of the runtime provider so that it can be used as a filter when processing events.
     m_RuntimeProviderID = EventPipeInternal.GetProvider(NativeRuntimeEventSource.EventSourceName);
     m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(IntPtr.Zero, false);
 }
Пример #21
0
 internal static void Disable()
 {
     EventPipeInternal.Disable();
 }
Пример #22
0
 // Get or set the per-thread activity ID.
 int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
 {
     return(EventPipeInternal.EventActivityIdControl((uint)ControlCode, ref ActivityId));
 }
Пример #23
0
        // Define an EventPipeEvent handle.
        unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
        {
            IntPtr eventHandlePtr = EventPipeInternal.DefineEvent(m_provHandle, eventID, keywords, eventVersion, level, pMetadata, metadataLength);

            return(eventHandlePtr);
        }
Пример #24
0
 internal static void Disable()
 {
     EventPipeInternal.Disable(s_sessionID);
 }