mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 18:47:57 -05:00
Adding pausing functionality for the profiler (#634)
* Dropping profiler session on stop request * Changes to IXEventSession to simplify dropping sessions * Stop sessions instead of dropping, disable flaky tests * Initial framework for profiler pause requests * Restructuring profiler session monitoring * Fixes to session monitor * Testing for pause functionality * Fixing comments from PR * Changes to testing * Commenting out flaky test * Deleting leftover testing code
This commit is contained in:
committed by
GitHub
parent
aff0f1afae
commit
f53e532225
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Microsoft.SqlTools.Utility;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Profiler.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pause Profiling request parameters
|
||||||
|
/// </summary>
|
||||||
|
public class PauseProfilingParams : GeneralRequestDetails
|
||||||
|
{
|
||||||
|
public string OwnerUri { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PauseProfilingResult{}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pause Profile request type
|
||||||
|
/// </summary>
|
||||||
|
public class PauseProfilingRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request definition
|
||||||
|
/// </summary>
|
||||||
|
public static readonly
|
||||||
|
RequestType<PauseProfilingParams, PauseProfilingResult> Type =
|
||||||
|
RequestType<PauseProfilingParams, PauseProfilingResult>.Create("profiler/pause");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,12 +16,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler.Contracts
|
|||||||
public string OwnerUri { get; set; }
|
public string OwnerUri { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StopProfilingResult
|
public class StopProfilingResult{}
|
||||||
{
|
|
||||||
public bool Succeeded { get; set; }
|
|
||||||
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start Profile request type
|
/// Start Profile request type
|
||||||
|
|||||||
@@ -22,11 +22,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts monitoring a profiler session
|
/// Starts monitoring a profiler session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool StartMonitoringSession(ProfilerSession session);
|
bool StartMonitoringSession(string viewerId, IXEventSession session);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops monitoring a profiler session
|
/// Stops monitoring a profiler session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool StopMonitoringSession(string sessionId, out ProfilerSession session);
|
bool StopMonitoringSession(string viewerId, out ProfilerSession session);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pauses or Unpauses the stream of events to the viewer
|
||||||
|
/// </summary>
|
||||||
|
void PauseViewer(string viewerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
public interface IXEventSession
|
public interface IXEventSession
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads XEvent XML from the default session target
|
/// Gets unique XEvent session Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string GetTargetXml();
|
int Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts XEvent session
|
||||||
|
/// </summary>
|
||||||
|
void Start();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops XEvent session
|
/// Stops XEvent session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads XEvent XML from the default session target
|
||||||
|
/// </summary>
|
||||||
|
string GetTargetXml();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
public interface IXEventSessionFactory
|
public interface IXEventSessionFactory
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new XEvent session
|
/// Gets or creates an XEvent session with the given template
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IXEventSession CreateXEventSession(ConnectionInfo connInfo);
|
IXEventSession GetOrCreateXEventSession(string template, ConnectionInfo connInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
this.ServiceHost = serviceHost;
|
this.ServiceHost = serviceHost;
|
||||||
this.ServiceHost.SetRequestHandler(StartProfilingRequest.Type, HandleStartProfilingRequest);
|
this.ServiceHost.SetRequestHandler(StartProfilingRequest.Type, HandleStartProfilingRequest);
|
||||||
this.ServiceHost.SetRequestHandler(StopProfilingRequest.Type, HandleStopProfilingRequest);
|
this.ServiceHost.SetRequestHandler(StopProfilingRequest.Type, HandleStopProfilingRequest);
|
||||||
|
this.ServiceHost.SetRequestHandler(PauseProfilingRequest.Type, HandlePauseProfilingRequest);
|
||||||
|
|
||||||
this.SessionMonitor.AddSessionListener(this);
|
this.SessionMonitor.AddSessionListener(this);
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
|
|
||||||
if (connInfo != null)
|
if (connInfo != null)
|
||||||
{
|
{
|
||||||
ProfilerSession session = StartSession(parameters.OwnerUri, connInfo);
|
int xEventSessionId = StartSession(parameters.OwnerUri, parameters.TemplateName, connInfo);
|
||||||
result.SessionId = session.SessionId;
|
result.SessionId = xEventSessionId.ToString();
|
||||||
result.Succeeded = true;
|
result.Succeeded = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -158,10 +159,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
monitor.StopMonitoringSession(parameters.OwnerUri, out session);
|
monitor.StopMonitoringSession(parameters.OwnerUri, out session);
|
||||||
session.XEventSession.Stop();
|
session.XEventSession.Stop();
|
||||||
|
|
||||||
await requestContext.SendResult(new StopProfilingResult
|
await requestContext.SendResult(new StopProfilingResult{});
|
||||||
{
|
|
||||||
Succeeded = true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -170,48 +168,53 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts a new profiler session for the provided connection
|
/// Handle request to pause a profiling session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal ProfilerSession StartSession(string sessionId, ConnectionInfo connInfo)
|
internal async Task HandlePauseProfilingRequest(PauseProfilingParams parameters, RequestContext<PauseProfilingResult> requestContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
monitor.PauseViewer(parameters.OwnerUri);
|
||||||
|
|
||||||
|
await requestContext.SendResult(new PauseProfilingResult{});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts a new profiler session or connects to an existing session
|
||||||
|
/// for the provided connection and template info
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The XEvent Session Id that was started
|
||||||
|
/// </returns>
|
||||||
|
internal int StartSession(string ownerUri, string template, ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
// create a new XEvent session and Profiler session
|
// create a new XEvent session and Profiler session
|
||||||
var xeSession = this.XEventSessionFactory.CreateXEventSession(connInfo);
|
var xeSession = this.XEventSessionFactory.GetOrCreateXEventSession(template, connInfo);
|
||||||
var profilerSession = new ProfilerSession()
|
|
||||||
{
|
|
||||||
SessionId = sessionId,
|
|
||||||
XEventSession = xeSession
|
|
||||||
};
|
|
||||||
|
|
||||||
// start monitoring the profiler session
|
// start monitoring the profiler session
|
||||||
monitor.StartMonitoringSession(profilerSession);
|
monitor.StartMonitoringSession(ownerUri, xeSession);
|
||||||
|
|
||||||
return profilerSession;
|
return xeSession.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new XEvent sessions per the IXEventSessionFactory contract
|
/// Gets or creates an XEvent session with the given template per the IXEventSessionFactory contract
|
||||||
/// </summary>
|
|
||||||
public IXEventSession CreateXEventSession(ConnectionInfo connInfo)
|
|
||||||
{
|
|
||||||
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo);
|
|
||||||
SqlStoreConnection connection = new SqlStoreConnection(sqlConnection);
|
|
||||||
Session session = ProfilerService.GetOrCreateSession(connection, "Profiler");
|
|
||||||
|
|
||||||
// create xevent session wrapper
|
|
||||||
return new XEventSession()
|
|
||||||
{
|
|
||||||
Session = session
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an existing XEvent session or creates one if no matching session exists.
|
|
||||||
/// Also starts the session if it isn't currently running
|
/// Also starts the session if it isn't currently running
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Session GetOrCreateSession(SqlStoreConnection connection, string sessionName)
|
public IXEventSession GetOrCreateXEventSession(string template, ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
|
string sessionName = "Profiler";
|
||||||
|
|
||||||
|
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo);
|
||||||
|
SqlStoreConnection connection = new SqlStoreConnection(sqlConnection);
|
||||||
XEStore store = new XEStore(connection);
|
XEStore store = new XEStore(connection);
|
||||||
Session session = store.Sessions[sessionName];
|
Session session = store.Sessions[sessionName];
|
||||||
|
|
||||||
// start the session if it isn't already running
|
// start the session if it isn't already running
|
||||||
if (session == null)
|
if (session == null)
|
||||||
{
|
{
|
||||||
@@ -222,7 +225,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
{
|
{
|
||||||
session.Start();
|
session.Start();
|
||||||
}
|
}
|
||||||
return session;
|
|
||||||
|
// create xevent session wrapper
|
||||||
|
return new XEventSession()
|
||||||
|
{
|
||||||
|
Session = session
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Session CreateSession(SqlStoreConnection connection, string sessionName)
|
private static Session CreateSession(SqlStoreConnection connection, string sessionName)
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
private TimeSpan pollingDelay = DefaultPollingDelay;
|
private TimeSpan pollingDelay = DefaultPollingDelay;
|
||||||
private ProfilerEvent lastSeenEvent = null;
|
private ProfilerEvent lastSeenEvent = null;
|
||||||
|
|
||||||
/// <summary>
|
public bool pollImmediatly = false;
|
||||||
/// Unique ID for the session
|
|
||||||
/// </summary>
|
|
||||||
public string SessionId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connection to use for the session
|
/// Connection to use for the session
|
||||||
@@ -47,10 +44,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
{
|
{
|
||||||
lock (this.pollingLock)
|
lock (this.pollingLock)
|
||||||
{
|
{
|
||||||
if (!this.isPolling && DateTime.Now.Subtract(this.lastPollTime) >= pollingDelay)
|
if (pollImmediatly || (!this.isPolling && DateTime.Now.Subtract(this.lastPollTime) >= pollingDelay))
|
||||||
{
|
{
|
||||||
this.isPolling = true;
|
this.isPolling = true;
|
||||||
this.lastPollTime = DateTime.Now;
|
this.lastPollTime = DateTime.Now;
|
||||||
|
this.pollImmediatly = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -81,7 +79,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The delay between session polls
|
/// The delay between session polls
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan PollingDelay
|
public TimeSpan PollingDelay
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -108,15 +106,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removed profiler polling events from event list
|
/// Removed profiler polling events from event list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ProfilerEvent> FilterProfilerEvents(List<ProfilerEvent> events)
|
public List<ProfilerEvent> FilterProfilerEvents(List<ProfilerEvent> events)
|
||||||
{
|
{
|
||||||
int idx = events.Count;
|
int idx = events.Count;
|
||||||
while (--idx >= 0)
|
while (--idx >= 0)
|
||||||
{
|
{
|
||||||
if (IsProfilerEvent(events[idx]))
|
if (IsProfilerEvent(events[idx]))
|
||||||
{
|
{
|
||||||
events.RemoveAt(idx);
|
events.RemoveAt(idx);
|
||||||
@@ -126,7 +124,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Filter the event list to not include previously seen events,
|
/// Filter the event list to not include previously seen events,
|
||||||
/// and to exclude events that happened before the profiling session began.
|
/// and to exclude events that happened before the profiling session began.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void FilterOldEvents(List<ProfilerEvent> events)
|
public void FilterOldEvents(List<ProfilerEvent> events)
|
||||||
@@ -151,7 +149,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
events.RemoveRange(0, idx + 1);
|
events.RemoveRange(0, idx + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the last event so we know where to clean-up the list from next time
|
// save the last event so we know where to clean-up the list from next time
|
||||||
if (events.Count > 0)
|
if (events.Count > 0)
|
||||||
{
|
{
|
||||||
lastSeenEvent = events.LastOrDefault();
|
lastSeenEvent = events.LastOrDefault();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using Microsoft.SqlTools.Utility;
|
|||||||
namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Classs to monitor active profiler sessions
|
/// Class to monitor active profiler sessions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProfilerSessionMonitor : IProfilerSessionMonitor
|
public class ProfilerSessionMonitor : IProfilerSessionMonitor
|
||||||
{
|
{
|
||||||
@@ -30,9 +30,33 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
|
|
||||||
private object listenersLock = new object();
|
private object listenersLock = new object();
|
||||||
|
|
||||||
|
private object pollingLock = new object();
|
||||||
|
|
||||||
private Task processorThread = null;
|
private Task processorThread = null;
|
||||||
|
|
||||||
private Dictionary<string, ProfilerSession> monitoredSessions = new Dictionary<string, ProfilerSession>();
|
private struct Viewer
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public bool active { get; set; }
|
||||||
|
|
||||||
|
public int xeSessionId { get; set; }
|
||||||
|
|
||||||
|
public Viewer(string Id, bool active, int xeId)
|
||||||
|
{
|
||||||
|
this.Id = Id;
|
||||||
|
this.active = active;
|
||||||
|
this.xeSessionId = xeId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// XEvent Session Id's matched to the Profiler Id's watching them
|
||||||
|
private Dictionary<int, List<string>> sessionViewers = new Dictionary<int, List<string>>();
|
||||||
|
|
||||||
|
// XEvent Session Id's matched to their Profiler Sessions
|
||||||
|
private Dictionary<int, ProfilerSession> monitoredSessions = new Dictionary<int, ProfilerSession>();
|
||||||
|
|
||||||
|
// ViewerId -> Viewer objects
|
||||||
|
private Dictionary<string, Viewer> allViewers = new Dictionary<string, Viewer>();
|
||||||
|
|
||||||
private List<IProfilerSessionListener> listeners = new List<IProfilerSessionListener>();
|
private List<IProfilerSessionListener> listeners = new List<IProfilerSessionListener>();
|
||||||
|
|
||||||
@@ -40,29 +64,58 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
/// Registers a session event listener to receive a callback when events arrive
|
/// Registers a session event listener to receive a callback when events arrive
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddSessionListener(IProfilerSessionListener listener)
|
public void AddSessionListener(IProfilerSessionListener listener)
|
||||||
{
|
{
|
||||||
lock (this.listenersLock)
|
lock (this.listenersLock)
|
||||||
{
|
{
|
||||||
this.listeners.Add(listener);
|
this.listeners.Add(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start monitoring the provided sessions
|
/// Start monitoring the provided session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StartMonitoringSession(ProfilerSession session)
|
public bool StartMonitoringSession(string viewerId, IXEventSession session)
|
||||||
{
|
{
|
||||||
lock (this.sessionsLock)
|
lock (this.sessionsLock)
|
||||||
{
|
{
|
||||||
// start the monitoring thread
|
// start the monitoring thread
|
||||||
if (this.processorThread == null)
|
if (this.processorThread == null)
|
||||||
{
|
{
|
||||||
this.processorThread = Task.Factory.StartNew(ProcessSessions);;
|
this.processorThread = Task.Factory.StartNew(ProcessSessions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.monitoredSessions.ContainsKey(session.SessionId))
|
// create new profiling session if needed
|
||||||
|
if (!this.monitoredSessions.ContainsKey(session.Id))
|
||||||
{
|
{
|
||||||
this.monitoredSessions.Add(session.SessionId, session);
|
var profilerSession = new ProfilerSession();
|
||||||
|
profilerSession.XEventSession = session;
|
||||||
|
|
||||||
|
this.monitoredSessions.Add(session.Id, profilerSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new viewer, or configure existing viewer
|
||||||
|
Viewer viewer;
|
||||||
|
if (!this.allViewers.TryGetValue(viewerId, out viewer))
|
||||||
|
{
|
||||||
|
viewer = new Viewer(viewerId, true, session.Id);
|
||||||
|
allViewers.Add(viewerId, viewer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewer.active = true;
|
||||||
|
viewer.xeSessionId = session.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add viewer to XEvent session viewers
|
||||||
|
List<string> viewers;
|
||||||
|
if (this.sessionViewers.TryGetValue(session.Id, out viewers))
|
||||||
|
{
|
||||||
|
viewers.Add(viewerId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewers = new List<string>{ viewerId };
|
||||||
|
sessionViewers.Add(session.Id, viewers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,15 +123,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop monitoring the session specified by the sessionId
|
/// Stop monitoring the session watched by viewerId
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool StopMonitoringSession(string sessionId, out ProfilerSession session)
|
public bool StopMonitoringSession(string viewerId, out ProfilerSession session)
|
||||||
{
|
{
|
||||||
lock (this.sessionsLock)
|
lock (this.sessionsLock)
|
||||||
{
|
{
|
||||||
if (this.monitoredSessions.ContainsKey(sessionId))
|
Viewer v;
|
||||||
|
if (this.allViewers.TryGetValue(viewerId, out v))
|
||||||
{
|
{
|
||||||
return this.monitoredSessions.Remove(sessionId, out session);
|
return RemoveSession(v.xeSessionId, out session);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -88,23 +142,84 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggle the pause state for the viewer
|
||||||
|
/// </summary>
|
||||||
|
public void PauseViewer(string viewerId)
|
||||||
|
{
|
||||||
|
lock (this.sessionsLock)
|
||||||
|
{
|
||||||
|
Viewer v = this.allViewers[viewerId];
|
||||||
|
v.active = !v.active;
|
||||||
|
this.allViewers[viewerId] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool RemoveSession(int sessionId, out ProfilerSession session)
|
||||||
|
{
|
||||||
|
lock (this.sessionsLock)
|
||||||
|
{
|
||||||
|
if (this.monitoredSessions.Remove(sessionId, out session))
|
||||||
|
{
|
||||||
|
//remove all viewers for this session
|
||||||
|
List<string> viewerIds;
|
||||||
|
if (sessionViewers.Remove(sessionId, out viewerIds))
|
||||||
|
{
|
||||||
|
foreach (String viewerId in viewerIds)
|
||||||
|
{
|
||||||
|
this.allViewers.Remove(viewerId);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
session = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PollSession(int sessionId)
|
||||||
|
{
|
||||||
|
lock (this.sessionsLock)
|
||||||
|
{
|
||||||
|
this.monitoredSessions[sessionId].pollImmediatly = true;
|
||||||
|
}
|
||||||
|
lock (this.pollingLock)
|
||||||
|
{
|
||||||
|
Monitor.Pulse(pollingLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The core queue processing method
|
/// The core queue processing method
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state"></param>
|
/// <param name="state"></param>
|
||||||
private void ProcessSessions()
|
private void ProcessSessions()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
lock (this.sessionsLock)
|
lock (this.pollingLock)
|
||||||
{
|
{
|
||||||
foreach (var session in this.monitoredSessions.Values)
|
lock (this.sessionsLock)
|
||||||
{
|
{
|
||||||
ProcessSession(session);
|
foreach (var session in this.monitoredSessions.Values)
|
||||||
|
{
|
||||||
|
List<string> viewers = this.sessionViewers[session.XEventSession.Id];
|
||||||
|
if (viewers.Any(v => allViewers[v].active))
|
||||||
|
{
|
||||||
|
ProcessSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Monitor.Wait(this.pollingLock, PollingLoopDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread.Sleep(PollingLoopDelay);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,12 +230,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
{
|
{
|
||||||
if (session.TryEnterPolling())
|
if (session.TryEnterPolling())
|
||||||
{
|
{
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
var events = PollSession(session);
|
var events = PollSession(session);
|
||||||
if (events.Count > 0)
|
if (events.Count > 0)
|
||||||
{
|
{
|
||||||
SendEventsToListeners(session.SessionId, events);
|
// notify all viewers for the polled session
|
||||||
|
List<string> viewerIds = this.sessionViewers[session.XEventSession.Id];
|
||||||
|
foreach (string viewerId in viewerIds)
|
||||||
|
{
|
||||||
|
if (allViewers[viewerId].active)
|
||||||
|
{
|
||||||
|
SendEventsToListeners(viewerId, events);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -151,7 +274,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Warning, "Failed to pool session. error: " + ex.Message);
|
Logger.Write(LogLevel.Warning, "Failed to pool session. error: " + ex.Message);
|
||||||
}
|
}
|
||||||
@@ -187,7 +310,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
|||||||
var timestamp = node.Attributes["timestamp"];
|
var timestamp = node.Attributes["timestamp"];
|
||||||
|
|
||||||
var profilerEvent = new ProfilerEvent(name.InnerText, timestamp.InnerText);
|
var profilerEvent = new ProfilerEvent(name.InnerText, timestamp.InnerText);
|
||||||
|
|
||||||
foreach (XmlNode childNode in node.ChildNodes)
|
foreach (XmlNode childNode in node.ChildNodes)
|
||||||
{
|
{
|
||||||
var childName = childNode.Attributes["name"];
|
var childName = childNode.Attributes["name"];
|
||||||
|
|||||||
@@ -10,10 +10,23 @@ using Microsoft.SqlTools.ServiceLayer.Profiler.Contracts;
|
|||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
namespace Microsoft.SqlTools.ServiceLayer.Profiler
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class to access underlying XEvent session.
|
||||||
|
/// </summary>
|
||||||
public class XEventSession : IXEventSession
|
public class XEventSession : IXEventSession
|
||||||
{
|
{
|
||||||
public Session Session { get; set; }
|
public Session Session { get; set; }
|
||||||
|
|
||||||
|
public int Id
|
||||||
|
{
|
||||||
|
get { return Session.ID; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
this.Session.Start();
|
||||||
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
this.Session.Stop();
|
this.Session.Stop();
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Profiler
|
|||||||
string sessionId = null;
|
string sessionId = null;
|
||||||
var startContext = new Mock<RequestContext<StartProfilingResult>>();
|
var startContext = new Mock<RequestContext<StartProfilingResult>>();
|
||||||
startContext.Setup(rc => rc.SendResult(It.IsAny<StartProfilingResult>()))
|
startContext.Setup(rc => rc.SendResult(It.IsAny<StartProfilingResult>()))
|
||||||
.Returns<StartProfilingResult>((result) =>
|
.Returns<StartProfilingResult>((result) =>
|
||||||
{
|
{
|
||||||
// capture the session id for sending the stop message
|
// capture the session id for sending the stop message
|
||||||
sessionId = result.SessionId;
|
sessionId = result.SessionId;
|
||||||
@@ -71,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Profiler
|
|||||||
await profilerService.HandleStopProfilingRequest(stopParams, stopContext.Object);
|
await profilerService.HandleStopProfilingRequest(stopParams, stopContext.Object);
|
||||||
|
|
||||||
stopContext.VerifyAll();
|
stopContext.VerifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -82,7 +82,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Profiler
|
|||||||
{
|
{
|
||||||
var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");
|
var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");
|
||||||
ProfilerService profilerService = new ProfilerService();
|
ProfilerService profilerService = new ProfilerService();
|
||||||
IXEventSession xeSession = profilerService.CreateXEventSession(liveConnection.ConnectionInfo);
|
IXEventSession xeSession = profilerService.GetOrCreateXEventSession("Profiler", liveConnection.ConnectionInfo);
|
||||||
Assert.NotNull(xeSession);
|
Assert.NotNull(xeSession);
|
||||||
Assert.NotNull(xeSession.GetTargetXml());
|
Assert.NotNull(xeSession.GetTargetXml());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.SqlServer.Management.XEvent;
|
using Microsoft.SqlServer.Management.XEvent;
|
||||||
using Microsoft.SqlTools.Hosting.Protocol;
|
using Microsoft.SqlTools.Hosting.Protocol;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
@@ -32,6 +33,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
public async Task TestStartProfilingRequest()
|
public async Task TestStartProfilingRequest()
|
||||||
{
|
{
|
||||||
string sessionId = null;
|
string sessionId = null;
|
||||||
|
bool recievedEvents = false;
|
||||||
string testUri = "profiler_uri";
|
string testUri = "profiler_uri";
|
||||||
var requestContext = new Mock<RequestContext<StartProfilingResult>>();
|
var requestContext = new Mock<RequestContext<StartProfilingResult>>();
|
||||||
requestContext.Setup(rc => rc.SendResult(It.IsAny<StartProfilingResult>()))
|
requestContext.Setup(rc => rc.SendResult(It.IsAny<StartProfilingResult>()))
|
||||||
@@ -42,10 +44,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
var sessionListener = new TestSessionListener();
|
// capture listener event notifications
|
||||||
|
var mockListener = new Mock<IProfilerSessionListener>();
|
||||||
|
mockListener.Setup(p => p.EventsAvailable(It.IsAny<string>(), It.IsAny<List<ProfilerEvent>>())).Callback(() =>
|
||||||
|
{
|
||||||
|
recievedEvents = true;
|
||||||
|
});
|
||||||
|
|
||||||
var profilerService = new ProfilerService();
|
var profilerService = new ProfilerService();
|
||||||
profilerService.SessionMonitor.AddSessionListener(sessionListener);
|
profilerService.SessionMonitor.AddSessionListener(mockListener.Object);
|
||||||
profilerService.ConnectionServiceInstance = TestObjects.GetTestConnectionService();
|
profilerService.ConnectionServiceInstance = TestObjects.GetTestConnectionService();
|
||||||
ConnectionInfo connectionInfo = TestObjects.GetTestConnectionInfo();
|
ConnectionInfo connectionInfo = TestObjects.GetTestConnectionInfo();
|
||||||
profilerService.ConnectionServiceInstance.OwnerToConnectionMap.Add(testUri, connectionInfo);
|
profilerService.ConnectionServiceInstance.OwnerToConnectionMap.Add(testUri, connectionInfo);
|
||||||
@@ -55,15 +62,33 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
requestParams.OwnerUri = testUri;
|
requestParams.OwnerUri = testUri;
|
||||||
requestParams.TemplateName = "Standard";
|
requestParams.TemplateName = "Standard";
|
||||||
|
|
||||||
|
// start profiling session
|
||||||
await profilerService.HandleStartProfilingRequest(requestParams, requestContext.Object);
|
await profilerService.HandleStartProfilingRequest(requestParams, requestContext.Object);
|
||||||
|
|
||||||
// wait a bit for profile sessions to be polled
|
profilerService.SessionMonitor.PollSession(1);
|
||||||
Thread.Sleep(500);
|
// simulate a short polling delay
|
||||||
|
Thread.Sleep(200);
|
||||||
|
profilerService.SessionMonitor.PollSession(1);
|
||||||
|
|
||||||
|
// wait for polling to finish, or for timeout
|
||||||
|
System.Timers.Timer pollingTimer = new System.Timers.Timer();
|
||||||
|
pollingTimer.Interval = 10000;
|
||||||
|
pollingTimer.Start();
|
||||||
|
bool timeout = false;
|
||||||
|
pollingTimer.Elapsed += new System.Timers.ElapsedEventHandler((s_, e_) => {timeout = true;});
|
||||||
|
while (sessionId == null && !timeout)
|
||||||
|
{
|
||||||
|
Thread.Sleep(250);
|
||||||
|
}
|
||||||
|
pollingTimer.Stop();
|
||||||
|
|
||||||
requestContext.VerifyAll();
|
requestContext.VerifyAll();
|
||||||
|
|
||||||
Assert.Equal(sessionListener.PreviousSessionId, sessionId);
|
// Check that the correct XEvent session was started
|
||||||
Assert.Equal(sessionListener.PreviousEvents.Count, 1);
|
Assert.Equal(sessionId, "1");
|
||||||
|
|
||||||
|
// check that the proper owner Uri was used
|
||||||
|
Assert.True(recievedEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -82,11 +107,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
requestContext.Setup(rc => rc.SendResult(It.IsAny<StopProfilingResult>()))
|
requestContext.Setup(rc => rc.SendResult(It.IsAny<StopProfilingResult>()))
|
||||||
.Returns<StopProfilingResult>((result) =>
|
.Returns<StopProfilingResult>((result) =>
|
||||||
{
|
{
|
||||||
success = result.Succeeded;
|
success = true;
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// capture if session was dropped
|
// capture if session was stopped
|
||||||
var mockSession = new Mock<IXEventSession>();
|
var mockSession = new Mock<IXEventSession>();
|
||||||
mockSession.Setup(p => p.Stop()).Callback(() =>
|
mockSession.Setup(p => p.Stop()).Callback(() =>
|
||||||
{
|
{
|
||||||
@@ -104,17 +129,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
var requestParams = new StopProfilingParams();
|
var requestParams = new StopProfilingParams();
|
||||||
requestParams.OwnerUri = testUri;
|
requestParams.OwnerUri = testUri;
|
||||||
|
|
||||||
ProfilerSession session = new ProfilerSession();
|
profilerService.SessionMonitor.StartMonitoringSession(testUri, mockSession.Object);
|
||||||
session.XEventSession = mockSession.Object;
|
|
||||||
session.SessionId = testUri;
|
|
||||||
|
|
||||||
profilerService.SessionMonitor.StartMonitoringSession(session);
|
|
||||||
|
|
||||||
await profilerService.HandleStopProfilingRequest(requestParams, requestContext.Object);
|
await profilerService.HandleStopProfilingRequest(requestParams, requestContext.Object);
|
||||||
|
|
||||||
requestContext.VerifyAll();
|
requestContext.VerifyAll();
|
||||||
|
|
||||||
// check that session was succesfully stopped and drop was called
|
// check that session was succesfully stopped and stop was called
|
||||||
Assert.True(success);
|
Assert.True(success);
|
||||||
Assert.True(stopped);
|
Assert.True(stopped);
|
||||||
|
|
||||||
@@ -122,5 +143,97 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
ProfilerSession ps;
|
ProfilerSession ps;
|
||||||
Assert.False(profilerService.SessionMonitor.StopMonitoringSession(testUri, out ps));
|
Assert.False(profilerService.SessionMonitor.StopMonitoringSession(testUri, out ps));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test pausing then resuming a session
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Fact]
|
||||||
|
public async Task TestPauseProfilingRequest()
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
string testUri = "test_session";
|
||||||
|
bool recievedEvents = false;
|
||||||
|
|
||||||
|
// capture pausing results
|
||||||
|
var requestContext = new Mock<RequestContext<PauseProfilingResult>>();
|
||||||
|
requestContext.Setup(rc => rc.SendResult(It.IsAny<PauseProfilingResult>()))
|
||||||
|
.Returns<PauseProfilingResult>((result) =>
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
return Task.FromResult(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// capture listener event notifications
|
||||||
|
var mockListener = new Mock<IProfilerSessionListener>();
|
||||||
|
mockListener.Setup(p => p.EventsAvailable(It.IsAny<string>(), It.IsAny<List<ProfilerEvent>>())).Callback(() =>
|
||||||
|
{
|
||||||
|
recievedEvents = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// setup profiler service
|
||||||
|
var profilerService = new ProfilerService();
|
||||||
|
profilerService.SessionMonitor.AddSessionListener(mockListener.Object);
|
||||||
|
profilerService.ConnectionServiceInstance = TestObjects.GetTestConnectionService();
|
||||||
|
ConnectionInfo connectionInfo = TestObjects.GetTestConnectionInfo();
|
||||||
|
profilerService.ConnectionServiceInstance.OwnerToConnectionMap.Add(testUri, connectionInfo);
|
||||||
|
|
||||||
|
var requestParams = new PauseProfilingParams();
|
||||||
|
requestParams.OwnerUri = testUri;
|
||||||
|
|
||||||
|
// begin monitoring session
|
||||||
|
profilerService.SessionMonitor.StartMonitoringSession(testUri, new TestXEventSession1());
|
||||||
|
|
||||||
|
// poll the session
|
||||||
|
profilerService.SessionMonitor.PollSession(1);
|
||||||
|
Thread.Sleep(500);
|
||||||
|
profilerService.SessionMonitor.PollSession(1);
|
||||||
|
|
||||||
|
// wait for polling to finish, or for timeout
|
||||||
|
System.Timers.Timer pollingTimer = new System.Timers.Timer();
|
||||||
|
pollingTimer.Interval = 10000;
|
||||||
|
pollingTimer.Start();
|
||||||
|
bool timeout = false;
|
||||||
|
pollingTimer.Elapsed += new System.Timers.ElapsedEventHandler((s_, e_) => {timeout = true;});
|
||||||
|
while (!recievedEvents && !timeout)
|
||||||
|
{
|
||||||
|
Thread.Sleep(250);
|
||||||
|
}
|
||||||
|
pollingTimer.Stop();
|
||||||
|
|
||||||
|
// confirm that polling works
|
||||||
|
Assert.True(recievedEvents);
|
||||||
|
|
||||||
|
// pause viewer
|
||||||
|
await profilerService.HandlePauseProfilingRequest(requestParams, requestContext.Object);
|
||||||
|
Assert.True(success);
|
||||||
|
|
||||||
|
recievedEvents = false;
|
||||||
|
success = false;
|
||||||
|
|
||||||
|
profilerService.SessionMonitor.PollSession(1);
|
||||||
|
|
||||||
|
// confirm that no events were sent to paused listener
|
||||||
|
Assert.False(recievedEvents);
|
||||||
|
|
||||||
|
// unpause viewer
|
||||||
|
await profilerService.HandlePauseProfilingRequest(requestParams, requestContext.Object);
|
||||||
|
Assert.True(success);
|
||||||
|
|
||||||
|
profilerService.SessionMonitor.PollSession(1);
|
||||||
|
|
||||||
|
// wait for polling to finish, or for timeout
|
||||||
|
timeout = false;
|
||||||
|
pollingTimer.Start();
|
||||||
|
while (!recievedEvents && !timeout)
|
||||||
|
{
|
||||||
|
Thread.Sleep(250);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that events got sent to listener
|
||||||
|
Assert.True(recievedEvents);
|
||||||
|
|
||||||
|
requestContext.VerifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,19 +188,168 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler
|
|||||||
" </event>" +
|
" </event>" +
|
||||||
"</RingBufferTarget>";
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int Id { get { return 51; } }
|
||||||
|
|
||||||
|
public void Start(){}
|
||||||
|
|
||||||
|
public void Stop(){}
|
||||||
public string GetTargetXml()
|
public string GetTargetXml()
|
||||||
{
|
{
|
||||||
return testXEventXml;
|
return testXEventXml;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestXEventSession1 : IXEventSession
|
||||||
|
{
|
||||||
|
private const string testXEventXml_1 =
|
||||||
|
"<RingBufferTarget truncated=\"0\" processingTime=\"3\" totalEventsProcessed=\"1\" eventCount=\"1\" droppedCount=\"0\" memoryUsed=\"47996\">" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-09-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>1</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
private const string testXEventXml_2 =
|
||||||
|
"<RingBufferTarget truncated=\"0\" processingTime=\"3\" totalEventsProcessed=\"1\" eventCount=\"1\" droppedCount=\"0\" memoryUsed=\"47996\">" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-09-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>1</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-10-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>1</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
private const string testXEventXml_3 =
|
||||||
|
"<RingBufferTarget truncated=\"0\" processingTime=\"3\" totalEventsProcessed=\"1\" eventCount=\"1\" droppedCount=\"0\" memoryUsed=\"47996\">" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-09-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>1</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-10-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>1</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-11-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>1</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
public int Id { get { return 1; } }
|
||||||
|
|
||||||
|
public void Start(){}
|
||||||
|
|
||||||
public void Stop(){}
|
public void Stop(){}
|
||||||
|
|
||||||
|
private int pollCount = 0;
|
||||||
|
private string[] poll_returns = { testXEventXml_1, testXEventXml_2, testXEventXml_3 };
|
||||||
|
public string GetTargetXml()
|
||||||
|
{
|
||||||
|
string res = poll_returns[pollCount];
|
||||||
|
pollCount++;
|
||||||
|
pollCount = pollCount > 2 ? 0 : pollCount;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestXEventSession2 : IXEventSession
|
||||||
|
{
|
||||||
|
private const string testXEventXml_1 =
|
||||||
|
"<RingBufferTarget truncated=\"0\" processingTime=\"3\" totalEventsProcessed=\"1\" eventCount=\"1\" droppedCount=\"0\" memoryUsed=\"47996\">" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-09-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>2</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
private const string testXEventXml_2 =
|
||||||
|
"<RingBufferTarget truncated=\"0\" processingTime=\"3\" totalEventsProcessed=\"1\" eventCount=\"1\" droppedCount=\"0\" memoryUsed=\"47996\">" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-09-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>2</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-10-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>2</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
private const string testXEventXml_3 =
|
||||||
|
"<RingBufferTarget truncated=\"0\" processingTime=\"3\" totalEventsProcessed=\"1\" eventCount=\"1\" droppedCount=\"0\" memoryUsed=\"47996\">" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-09-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>2</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-10-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>2</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
" <event name=\"existing_connection\" package=\"sqlserver\" timestamp=\"2017-11-08T07:46:53.579Z\">" +
|
||||||
|
" <data name=\"session_id\">" +
|
||||||
|
" <type name=\"int16\" package=\"package0\"></type>" +
|
||||||
|
" <value>2</value>" +
|
||||||
|
" </data>" +
|
||||||
|
" </event>" +
|
||||||
|
"</RingBufferTarget>";
|
||||||
|
|
||||||
|
public int Id { get { return 2; } }
|
||||||
|
|
||||||
|
public void Start(){}
|
||||||
|
|
||||||
|
public void Stop(){}
|
||||||
|
|
||||||
|
private int pollCount = 0;
|
||||||
|
private string[] poll_returns = { testXEventXml_1, testXEventXml_2, testXEventXml_3 };
|
||||||
|
public string GetTargetXml()
|
||||||
|
{
|
||||||
|
string res = poll_returns[pollCount];
|
||||||
|
pollCount++;
|
||||||
|
pollCount = pollCount > 2 ? 0 : pollCount;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TestXEventSessionFactory : IXEventSessionFactory
|
public class TestXEventSessionFactory : IXEventSessionFactory
|
||||||
{
|
{
|
||||||
public IXEventSession CreateXEventSession(ConnectionInfo connInfo)
|
private int sessionNum = 1;
|
||||||
|
public IXEventSession GetOrCreateXEventSession(string template, ConnectionInfo connInfo)
|
||||||
{
|
{
|
||||||
return new TestXEventSession();
|
if(sessionNum == 1)
|
||||||
|
{
|
||||||
|
sessionNum = 2;
|
||||||
|
return new TestXEventSession1();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sessionNum = 1;
|
||||||
|
return new TestXEventSession2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user