/// <summary> /// This method is the callback used by GetSessions() when it calls into GetSessionInfo(). /// It updates a List<SessionInfo> based on the etwSessionId and matchAllKeywords that /// GetSessionInfo() passes in. /// </summary> private static void GetSessionInfoCallback(int etwSessionId, long matchAllKeywords, ref List <SessionInfo> sessionList) { uint sessionIdBitMask = (uint)SessionMask.FromEventKeywords((ulong)matchAllKeywords); // an ETW controller that specifies more than the mandated bit for our EventSource // will be ignored... if (bitcount(sessionIdBitMask) > 1) { return; } if (sessionList == null) { sessionList = new List <SessionInfo>(8); } if (bitcount(sessionIdBitMask) == 1) { // activity-tracing-aware etw session sessionList.Add(new SessionInfo(bitindex(sessionIdBitMask) + 1, etwSessionId)); } else { // legacy etw session sessionList.Add(new SessionInfo(bitcount((uint)SessionMask.All) + 1, etwSessionId)); } }
// Token: 0x06003343 RID: 13123 RVA: 0x000C2DE0 File Offset: 0x000C0FE0 private static void GetSessionInfoCallback(int etwSessionId, long matchAllKeywords, ref List <EventProvider.SessionInfo> sessionList) { uint n = (uint)SessionMask.FromEventKeywords((ulong)matchAllKeywords); if (EventProvider.bitcount(n) > 1) { return; } if (sessionList == null) { sessionList = new List <EventProvider.SessionInfo>(8); } if (EventProvider.bitcount(n) == 1) { sessionList.Add(new EventProvider.SessionInfo(EventProvider.bitindex(n) + 1, etwSessionId)); return; } sessionList.Add(new EventProvider.SessionInfo(EventProvider.bitcount((uint)SessionMask.All) + 1, etwSessionId)); }
internal void WriteStringToListener(EventListener listener, string msg, SessionMask m) { Contract.Assert(listener == null || (uint)m == (uint)SessionMask.FromId(0)); if (m_eventSourceEnabled) { if (listener == null) { WriteEventString(0, (long) m.ToEventKeywords(), msg); } else { List<object> arg = new List<object>(); arg.Add(msg); EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this); eventCallbackArgs.EventId = 0; eventCallbackArgs.Payload = new ReadOnlyCollection<object>(arg); listener.OnEventWritten(eventCallbackArgs); } } }
private void Initialize(Guid eventSourceGuid, string eventSourceName) { if (eventSourceGuid == Guid.Empty) { throw new ArgumentException(Environment.GetResourceString("EventSource_NeedGuid")); } if (eventSourceName == null) { throw new ArgumentException(Environment.GetResourceString("EventSource_NeedName")); } m_name = eventSourceName; m_guid = eventSourceGuid; #if FEATURE_ACTIVITYSAMPLING m_curLiveSessions = new SessionMask(0); m_etwSessionIdMap = new EtwSession[SessionMask.MAX]; #endif // FEATURE_ACTIVITYSAMPLING #if FEATURE_MANAGED_ETW m_provider = new OverideEventProvider(this); try { m_provider.Register(eventSourceGuid); } catch (ArgumentException) { // Failed to register. Don't crash the app, just don't write events to ETW. m_provider = null; } #endif // Add the eventSource to the global (weak) list. This also sets m_id, which is the // index in the list. EventListener.AddEventSource(this); // We are logically completely initialized at this point. m_completelyInited = true; // report any possible errors ReportOutOfBandMessage(null, true); #if FEATURE_ACTIVITYSAMPLING // we cue sending sampling info here based on whether we had to defer sending // the manifest // note: we do *not* send sampling info to any EventListeners because // the following common code pattern would cause an AV: // class MyEventSource: EventSource // { // public static EventSource Log; // } // class MyEventListener: EventListener // { // protected override void OnEventWritten(...) // { MyEventSource.Log.anything; } <-- AV, as the static Log was not set yet // } if (m_eventSourceEnabled && m_deferedSendManifest) ReportActivitySamplingInfo(null, m_curLiveSessions); #endif // FEATURE_ACTIVITYSAMPLING // If we are active and we have not sent our manifest, do so now. if (m_eventSourceEnabled && m_deferedSendManifest) SendManifest(m_rawManifest); }
internal void WriteString(string msg, SessionMask m) { if (m_eventSourceEnabled) { WriteEventString(0, (long) m.ToEventKeywords(), msg); WriteStringToAllListeners(msg); } }
public SessionMask(SessionMask m) { m_mask = m.m_mask; }
public bool IsEqualOrSupersetOf(SessionMask m) { return (this.m_mask | m.m_mask) == this.m_mask; }
private void ReportActivitySamplingInfo(EventListener listener, SessionMask sessions) { Contract.Assert(listener == null || (uint)sessions == (uint)SessionMask.FromId(0)); for (int perEventSourceSessionId = 0; perEventSourceSessionId < SessionMask.MAX; ++perEventSourceSessionId) { if (!sessions[perEventSourceSessionId]) continue; ActivityFilter af; if (listener == null) { EtwSession etwSession = m_etwSessionIdMap[perEventSourceSessionId]; Contract.Assert(etwSession != null); af = etwSession.m_activityFilter; } else { af = listener.m_activityFilter; } if (af == null) continue; SessionMask m = new SessionMask(); m[perEventSourceSessionId] = true; foreach (var t in af.GetFilterAsTuple(m_guid)) { WriteStringToListener(listener, string.Format(CultureInfo.InvariantCulture, "Session {0}: {1} = {2}", perEventSourceSessionId, t.Item1, t.Item2), m); } bool participateInSampling = (listener == null) ? m_activityFilteringForETWEnabled[perEventSourceSessionId] : GetDispatcher(listener).m_activityFilteringEnabled; WriteStringToListener(listener, string.Format(CultureInfo.InvariantCulture, "Session {0}: Activity Sampling support: {1}", perEventSourceSessionId, participateInSampling ? "enabled" : "disabled"), m); } }
// This is the internal entry point that code:EventListeners call when wanting to send a command to a // eventSource. The logic is as follows // // * if Command == Update // * perEventSourceSessionId specifies the per-provider ETW session ID that the command applies // to (if listener != null) // perEventSourceSessionId = 0 - reserved for EventListeners // perEventSourceSessionId = 1..SessionMask.MAX - reserved for activity tracing aware ETW sessions // perEventSourceSessionId-1 represents the bit in the reserved field (bits 44..47) in // Keywords that identifies the session // perEventSourceSessionId = SessionMask.MAX+1 - reserved for legacy ETW sessions; these are // discriminated by etwSessionId // * etwSessionId specifies a machine-wide ETW session ID; this allows correlation of // activity tracing across different providers (which might have different sessionIds // for the same ETW session) // * enable, level, matchAnyKeywords are used to set a default for all events for the // eventSource. In particular, if 'enabled' is false, 'level' and // 'matchAnyKeywords' are not used. // * OnEventCommand is invoked, which may cause calls to // code:EventSource.EnableEventForDispatcher which may cause changes in the filtering // depending on the logic in that routine. // * else (command != Update) // * Simply call OnEventCommand. The expectation is that filtering is NOT changed. // * The 'enabled' 'level', matchAnyKeyword' arguments are ignored (must be true, 0, 0). // // dispatcher == null has special meaning. It is the 'ETW' dispatcher. internal void SendCommand(EventListener listener, int perEventSourceSessionId, int etwSessionId, EventCommand command, bool enable, EventLevel level, EventKeywords matchAnyKeyword, IDictionary<string, string> commandArguments) { m_lastCommandException = null; bool shouldReport = (perEventSourceSessionId > 0) && (perEventSourceSessionId <= SessionMask.MAX); try { lock (EventListener.EventListenersLock) { EnsureInitialized(); // Find the per-EventSource dispatcher cooresponding to registered dispatcher EventDispatcher eventSourceDispatcher = GetDispatcher(listener); if (eventSourceDispatcher == null && listener != null) // dispatcher == null means ETW dispatcher throw new ArgumentException(Environment.GetResourceString("EventSource_ListenerNotFound")); if (commandArguments == null) commandArguments = new Dictionary<string, string>(); if (command == EventCommand.Update) { // Set it up using the 'standard' filtering bitfields (use the "global" enable, not session specific one) for (int i = 0; i < m_eventData.Length; i++) EnableEventForDispatcher(eventSourceDispatcher, i, IsEnabledByDefault(i, enable, level, matchAnyKeyword)); if (enable) { if (!m_eventSourceEnabled) { // EventSource turned on for the first time, simply copy the bits. m_level = level; m_matchAnyKeyword = matchAnyKeyword; } else { // Already enabled, make it the most verbose of the existing and new filter if (level > m_level) m_level = level; if (matchAnyKeyword == 0) m_matchAnyKeyword = 0; else if (m_matchAnyKeyword != 0) m_matchAnyKeyword |= matchAnyKeyword; } } // interpret perEventSourceSessionId's sign, and adjust perEventSourceSessionId to // represent 0-based positive values bool bSessionEnable = (perEventSourceSessionId >= 0); if (perEventSourceSessionId == 0 && enable == false) bSessionEnable = false; if (listener == null) { if (!bSessionEnable) perEventSourceSessionId = -perEventSourceSessionId; // for "global" enable/disable (passed in with listener == null and // perEventSourceSessionId == 0) perEventSourceSessionId becomes -1 --perEventSourceSessionId; } command = bSessionEnable ? EventCommand.Enable : EventCommand.Disable; // perEventSourceSessionId = -1 when ETW sent a notification, but the set of active sessions // hasn't changed. // sesisonId = SessionMask.MAX when one of the legacy ETW sessions changed // 0 <= perEventSourceSessionId < SessionMask.MAX for activity-tracing aware sessions Contract.Assert(perEventSourceSessionId >= -1 && perEventSourceSessionId <= SessionMask.MAX); // Send the manifest if we are enabling an ETW session if (bSessionEnable && eventSourceDispatcher == null) { // eventSourceDispatcher == null means this is the ETW manifest // SendCommand can be called from the EventSource constructor as a side effect of // ETW registration. Unfortunately when this callback is active the provider is // not actually enabled (WriteEvents will fail). Thus if we detect this condition // (that we are still being constructed), we simply skip sending the manifest. // When the constructor completes we will try again and send the manifest at that time. // // Note that we unconditionally send the manifest whenever we are enabled, even if // we were already enabled. This is because there may be multiple sessions active // and we can't know that all the sessions have seen the manifest. if (m_completelyInited) SendManifest(m_rawManifest); else m_deferedSendManifest = true; } #if FEATURE_ACTIVITYSAMPLING if (bSessionEnable && perEventSourceSessionId != -1) { bool participateInSampling = false; string activityFilters; int sessionIdBit; ParseCommandArgs(commandArguments, out participateInSampling, out activityFilters, out sessionIdBit); if (listener == null && commandArguments.Count > 0 && perEventSourceSessionId != sessionIdBit) { throw new ArgumentException(Environment.GetResourceString("EventSource_SessionIdError", perEventSourceSessionId+SessionMask.SHIFT_SESSION_TO_KEYWORD, sessionIdBit+SessionMask.SHIFT_SESSION_TO_KEYWORD)); } if (listener == null) { UpdateEtwSession(perEventSourceSessionId, etwSessionId, true, activityFilters, participateInSampling); } else { ActivityFilter.UpdateFilter(ref listener.m_activityFilter, this, 0, activityFilters); eventSourceDispatcher.m_activityFilteringEnabled = participateInSampling; } } else if (!bSessionEnable && listener == null) { // if we disable an ETW session, indicate that in a synthesized command argument if (perEventSourceSessionId >= 0 && perEventSourceSessionId < SessionMask.MAX) { commandArguments["EtwSessionKeyword"] = (perEventSourceSessionId+SessionMask.SHIFT_SESSION_TO_KEYWORD).ToString(CultureInfo.InvariantCulture); } } #endif // FEATURE_ACTIVITYSAMPLING this.OnEventCommand(new EventCommandEventArgs(command, commandArguments, this, eventSourceDispatcher)); #if FEATURE_ACTIVITYSAMPLING if (listener == null && !bSessionEnable && perEventSourceSessionId != -1) { // if we disable an ETW session, complete disabling it UpdateEtwSession(perEventSourceSessionId, etwSessionId, false, null, false); } #endif // FEATURE_ACTIVITYSAMPLING if (enable) { m_eventSourceEnabled = true; } else { // If we are disabling, maybe we can turn on 'quick checks' to filter // quickly. These are all just optimizations (since later checks will still filter) #if FEATURE_ACTIVITYSAMPLING // Turn off (and forget) any information about Activity Tracing. if (listener == null) { // reset all filtering information for activity-tracing-aware sessions for (int i = 0; i < SessionMask.MAX; ++i) { EtwSession etwSession = m_etwSessionIdMap[i]; if (etwSession != null) ActivityFilter.DisableFilter(ref etwSession.m_activityFilter, this); } m_activityFilteringForETWEnabled = new SessionMask(0); m_curLiveSessions = new SessionMask(0); // reset activity-tracing-aware sessions if (m_etwSessionIdMap != null) for (int i = 0; i < SessionMask.MAX; ++i) m_etwSessionIdMap[i] = null; // reset legacy sessions if (m_legacySessions != null) m_legacySessions.Clear(); } else { ActivityFilter.DisableFilter(ref listener.m_activityFilter, this); eventSourceDispatcher.m_activityFilteringEnabled = false; } #endif // FEATURE_ACTIVITYSAMPLING // There is a good chance EnabledForAnyListener are not as accurate as // they could be, go ahead and get a better estimate. for (int i = 0; i < m_eventData.Length; i++) { bool isEnabledForAnyListener = false; for (EventDispatcher dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next) { if (dispatcher.m_EventEnabled[i]) { isEnabledForAnyListener = true; break; } } m_eventData[i].EnabledForAnyListener = isEnabledForAnyListener; } // If no events are enabled, disable the global enabled bit. if (!AnyEventEnabled()) { m_level = 0; m_matchAnyKeyword = 0; m_eventSourceEnabled = false; } } #if FEATURE_ACTIVITYSAMPLING UpdateKwdTriggers(enable); #endif // FEATURE_ACTIVITYSAMPLING } else { if (command == EventCommand.SendManifest) SendManifest(m_rawManifest); // These are not used for non-update commands and thus should always be 'default' values Contract.Assert(enable == true); Contract.Assert(m_level == EventLevel.LogAlways); Contract.Assert(m_matchAnyKeyword == EventKeywords.None); this.OnEventCommand(new EventCommandEventArgs(command, commandArguments, null, null)); } #if FEATURE_ACTIVITYSAMPLING if (m_completelyInited && (listener != null || shouldReport)) { SessionMask m = SessionMask.FromId(perEventSourceSessionId); ReportActivitySamplingInfo(listener, m); } OutputDebugString(string.Format(CultureInfo.InvariantCulture, "{0}.SendCommand(session {1}, cmd {2}, enable {3}, level {4}): live sessions {5:x}, sampling {6:x}", m_name, perEventSourceSessionId, command, enable, level, (ulong) m_curLiveSessions, (ulong) m_activityFilteringForETWEnabled)); #endif // FEATURE_ACTIVITYSAMPLING } } catch (Exception e) { // Remember any exception and rethrow. m_lastCommandException = e; throw; } }
unsafe private SessionMask GetEtwSessionMask(int eventId, Guid* childActivityID) { SessionMask etwSessions = new SessionMask(); for (int i = 0; i < SessionMask.MAX; ++i) { EtwSession etwSession = m_etwSessionIdMap[i]; if (etwSession != null) { ActivityFilter activityFilter = etwSession.m_activityFilter; // PassesActivityFilter() will flow "interesting" activities, so make sure // to perform this test first, before ORing with ~m_activityFilteringForETWEnabled // (note: the first test for !m_activityFilteringForETWEnabled[i] ensures we // do not fire events indiscriminately, when no filters are specified, but only // if, in addition, the session did not also enable ActivitySampling) if (activityFilter == null && !m_activityFilteringForETWEnabled[i] || activityFilter != null && ActivityFilter.PassesActivityFilter(activityFilter, childActivityID, m_eventData[eventId].TriggersActivityTracking > 0, this, eventId) || !m_activityFilteringForETWEnabled[i]) { etwSessions[i] = true; } } } // flow "interesting" activities for all legacy sessions in which there's some // level of activity tracing enabled (even other EventSources) if (m_legacySessions != null && m_legacySessions.Count > 0 && (EventOpcode)m_eventData[eventId].Descriptor.Opcode == EventOpcode.Send) { // only calculate InternalCurrentThreadActivityId once Guid *pCurrentActivityId = null; Guid currentActivityId; foreach (var legacyEtwSession in m_legacySessions) { if (legacyEtwSession == null) continue; ActivityFilter activityFilter = legacyEtwSession.m_activityFilter; if (activityFilter != null) { if (pCurrentActivityId == null) { currentActivityId = InternalCurrentThreadActivityId; pCurrentActivityId = ¤tActivityId; } ActivityFilter.FlowActivityIfNeeded(activityFilter, pCurrentActivityId, childActivityID); } } } return etwSessions; }
// Token: 0x0600343F RID: 13375 RVA: 0x000CA56F File Offset: 0x000C876F public SessionMask(SessionMask m) { this.m_mask = m.m_mask; }
// Token: 0x06003441 RID: 13377 RVA: 0x000CA589 File Offset: 0x000C8789 public bool IsEqualOrSupersetOf(SessionMask m) { return((this.m_mask | m.m_mask) == this.m_mask); }