Skip to content

Commit 0121531

Browse files
authored
Bugs fixes so XEvent profiler isn't broken (#577)
* Fix a few issues with profiler method handlers * Filter out profiler polling events * Add a unit test for profiler events * Add method comment headers
1 parent 7b1a88f commit 0121531

File tree

7 files changed

+110
-12
lines changed

7 files changed

+110
-12
lines changed

src/Microsoft.SqlTools.ServiceLayer/Profiler/Contracts/ProfilerEventsAvailableNotification.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler.Contracts
1111
{
1212
public class ProfilerEventsAvailableParams
1313
{
14-
public string SessionId { get; set; }
14+
public string OwnerUri { get; set; }
1515

1616
public List<ProfilerEvent> Events { get; set; }
1717
}
@@ -23,5 +23,3 @@ public static readonly
2323
EventType<ProfilerEventsAvailableParams>.Create("profiler/eventsavailable");
2424
}
2525
}
26-
27-

src/Microsoft.SqlTools.ServiceLayer/Profiler/Contracts/StopProfilingRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler.Contracts
1313
/// </summary>
1414
public class StopProfilingParams
1515
{
16-
public string SessionId { get; set; }
16+
public string OwnerUri { get; set; }
1717
}
1818

1919
public class StopProfilingResult

src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerService.cs

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ internal async Task HandleStartProfilingRequest(StartProfilingParams parameters,
129129

130130
if (connInfo != null)
131131
{
132-
ProfilerSession session = StartSession(connInfo);
132+
ProfilerSession session = StartSession(parameters.OwnerUri, connInfo);
133133
result.SessionId = session.SessionId;
134134
result.Succeeded = true;
135135
}
@@ -154,7 +154,7 @@ internal async Task HandleStopProfilingRequest(StopProfilingParams parameters, R
154154
{
155155
try
156156
{
157-
monitor.StopMonitoringSession(parameters.SessionId);
157+
monitor.StopMonitoringSession(parameters.OwnerUri);
158158
await requestContext.SendResult(new StopProfilingResult
159159
{
160160
Succeeded = true
@@ -169,13 +169,13 @@ await requestContext.SendResult(new StopProfilingResult
169169
/// <summary>
170170
/// Starts a new profiler session for the provided connection
171171
/// </summary>
172-
internal ProfilerSession StartSession(ConnectionInfo connInfo)
172+
internal ProfilerSession StartSession(string sessionId, ConnectionInfo connInfo)
173173
{
174174
// create a new XEvent session and Profiler session
175175
var xeSession = this.XEventSessionFactory.CreateXEventSession(connInfo);
176176
var profilerSession = new ProfilerSession()
177177
{
178-
SessionId = Guid.NewGuid().ToString(),
178+
SessionId = sessionId,
179179
XEventSession = xeSession
180180
};
181181

@@ -208,15 +208,52 @@ public IXEventSession CreateXEventSession(ConnectionInfo connInfo)
208208
private static Session GetOrCreateSession(SqlStoreConnection connection, string sessionName)
209209
{
210210
XEStore store = new XEStore(connection);
211-
Session session = store.Sessions["Profiler"];
211+
Session session = store.Sessions[sessionName];
212212
// start the session if it isn't already running
213+
if (session == null)
214+
{
215+
session = CreateSession(connection, sessionName);
216+
}
217+
213218
if (session != null && !session.IsRunning)
214219
{
215220
session.Start();
216221
}
217222
return session;
218223
}
219224

225+
private static Session CreateSession(SqlStoreConnection connection, string sessionName)
226+
{
227+
string createSessionSql =
228+
@"
229+
CREATE EVENT SESSION [Profiler] ON SERVER
230+
ADD EVENT sqlserver.attention(
231+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
232+
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
233+
ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1)
234+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)),
235+
ADD EVENT sqlserver.login(SET collect_options_text=(1)
236+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)),
237+
ADD EVENT sqlserver.logout(
238+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)),
239+
ADD EVENT sqlserver.rpc_completed(
240+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
241+
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
242+
ADD EVENT sqlserver.sql_batch_completed(
243+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
244+
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
245+
ADD EVENT sqlserver.sql_batch_starting(
246+
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
247+
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))))
248+
ADD TARGET package0.ring_buffer(SET max_events_limit=(1000),max_memory=(51200))
249+
WITH (MAX_MEMORY=8192 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)";
250+
251+
connection.ServerConnection.ExecuteNonQuery(createSessionSql);
252+
253+
XEStore store = new XEStore(connection);
254+
return store.Sessions[sessionName];
255+
}
256+
220257
/// <summary>
221258
/// Callback when profiler events are available
222259
/// </summary>
@@ -227,7 +264,7 @@ public void EventsAvailable(string sessionId, List<ProfilerEvent> events)
227264
ProfilerEventsAvailableNotification.Type,
228265
new ProfilerEventsAvailableParams()
229266
{
230-
SessionId = sessionId,
267+
OwnerUri = sessionId,
231268
Events = events
232269
});
233270
}

src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerSession.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,42 @@ public TimeSpan PollingDelay
8989
}
9090
}
9191

92+
/// <summary>
93+
/// Determine if an event was caused by the XEvent polling queries
94+
/// </summary>
95+
private bool IsProfilerEvent(ProfilerEvent currentEvent)
96+
{
97+
if (string.IsNullOrWhiteSpace(currentEvent.Name) || currentEvent.Values == null)
98+
{
99+
return false;
100+
}
101+
102+
if ((currentEvent.Name.Equals("sql_batch_completed")
103+
|| currentEvent.Name.Equals("sql_batch_starting"))
104+
&& currentEvent.Values.ContainsKey("batch_text"))
105+
{
106+
return currentEvent.Values["batch_text"].Contains("SELECT target_data FROM sys.dm_xe_session_targets");
107+
}
108+
109+
return false;
110+
}
111+
112+
/// <summary>
113+
/// Removed profiler polling events from event list
114+
/// </summary>
115+
public List<ProfilerEvent> FilterProfilerEvents(List<ProfilerEvent> events)
116+
{
117+
int idx = events.Count;
118+
while (--idx >= 0)
119+
{
120+
if (IsProfilerEvent(events[idx]))
121+
{
122+
events.RemoveAt(idx);
123+
}
124+
}
125+
return events;
126+
}
127+
92128
/// <summary>
93129
/// Filter the event list to not include previously seen events
94130
/// </summary>

src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerSessionMonitor.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ private List<ProfilerEvent> PollSession(ProfilerSession session)
160160
session.IsPolling = false;
161161
}
162162

163-
return session.FilterOldEvents(events);
163+
return session.FilterProfilerEvents(
164+
session.FilterOldEvents(events)
165+
);
164166
}
165167

166168
/// <summary>

src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ public virtual ScriptFile GetFile(string filePath)
104104
if (!this.workspaceFiles.TryGetValue(keyName, out scriptFile))
105105
{
106106
if (IsUntitled(resolvedFile.FilePath)
107-
|| !resolvedFile.CanReadFromDisk)
107+
|| !resolvedFile.CanReadFromDisk
108+
|| !File.Exists(resolvedFile.FilePath))
108109
{
109110
// It's either not a registered untitled file, or not a valid file on disk
110111
// so any attempt to read from disk will fail.

test/Microsoft.SqlTools.ServiceLayer.UnitTests/Profiler/ProfilerSessionTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ public void TestFilterOldEvents()
4848
Assert.Equal(newProfilerEvents.Count, 0);
4949
}
5050

51+
52+
/// <summary>
53+
/// Test the FilterProfilerEvents method
54+
/// </summary>
55+
[Fact]
56+
public void TestFilterProfilerEvents()
57+
{
58+
// create a profiler session and get some test events
59+
var profilerSession = new ProfilerSession();
60+
var profilerEvents = ProfilerTestObjects.TestProfilerEvents;
61+
62+
int expectedEventCount = profilerEvents.Count;
63+
64+
// add a new "Profiler Polling" event
65+
var newEvent = new ProfilerEvent("sql_batch_completed", "1/1/2017");
66+
newEvent.Values.Add("batch_text", "SELECT target_data FROM sys.dm_xe_session_targets");
67+
profilerEvents.Add(newEvent);
68+
69+
// verify that the polling event is removed
70+
Assert.Equal(profilerEvents.Count, expectedEventCount + 1);
71+
var newProfilerEvents = profilerSession.FilterProfilerEvents(profilerEvents);
72+
Assert.Equal(newProfilerEvents.Count, expectedEventCount);
73+
}
74+
5175
/// <summary>
5276
/// Test the TryEnterPolling method
5377
/// </summary>

0 commit comments

Comments
 (0)