Ξεκινώντας από την έκδοση 2012 του SQL Server η Microsoft προσφέρει μαζί με τα SQL Server Management Objects και το Extended Events Reader API το οποίο περιέχει το Microsoft.SqlServer.XEvent.Linq dll το οποίο μας δίνει την δυνατότητα να ανοίξουμε ένα connection προς ένα event file (.xem, .xel) και να διαβάσουμε, αναλύσουμε και παρουσιάσουμε τα δεδομένα που έχουμε κάνει capture με ένα extended event session.
Αρχικά ας δημιουργήσουμε ένα Extented Events session το οποίο θα κάνει capture τα SQL Batches που ολοκληρώνονται στον SQL Server:/p>
-- Session creation for SQL Statements
-- Max data size to be traced before rollover: 10GB
-- Rollover files: 50
CREATE EVENT SESSION [SQL Statements] ON SERVER
ADD EVENT sqlserver.sql_batch_completed(SET collect_batch_text = 1
ACTION(sqlserver.client_hostname,sqlserver.database_name,sqlserver.session_id,sqlserver.username))
ADD TARGET package0.event_file(SET FILENAME = N'C:\SQL Results\QueryResults.xel',MAX_FILE_SIZE = 200, MAX_ROLLOVER_FILES = 50, INCREMENT = 50)
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=20 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF);
GO
--Session Start
ALTER EVENT SESSION [SQL Statements] ON SERVER
STATE = START;
GO
--Long running batch
SELECT *
FROM sys.all_objects AS obj1
CROSS JOIN sys.all_objects AS obj2;
GO
--Session Stop
ALTER EVENT SESSION [SQL Statements] ON SERVER
STATE = STOP;
GO
--Cleanup
DROP EVENT SESSION [SQL Statements] ON SERVER;
GO
Το παραπάνω query δημιουργεί ένα session με όνομα SQL Statements το οποίο κάνει capture τα sql_batch_completed events στα οποία πέρα από τις default πληροφορίες οι οποίες γίνονται capture από τον SQL Sever (duration,name κτλ) κρατάμε και το batch_text.Στην συνέχεια ξεκινάμε το session και τρέχουμε ένα χρονοβόρο query. Τα αποτελέσματα του session αποθηκεύονται σε αρχείο με πρόθεμα QueryResults και κατάληξη .xel.
Ας δοκιμάσουμε τώρα να φτιάξουμε ένα WPF application το οποίο θα διαβάζει αυτό το αρχείο, θα βρίσκει το longest running query και θα μας επιστρέφει την διάρκεια και το text του, χρησιμοποιώντας LINQ to Extended Events:
//class to store the events holding the name of the event, the duration
//and the actual query text.
public class MaxEventSelected
{
public string eventName { get; set; }
public string timeElapsed { get; set; }
public string sqlText { get; set; }
}
public MainWindow()
{
InitializeComponent();
{
//.xel file path on the disk of the
string file = @"C:\Users\Sotiris\Desktop\QueryResults.xel";
//opening connection to the file to LINQ the Extended events
using (QueryableXEventData events = new QueryableXEventData(file))
{
var eventSelected = (MaxEventSelected)events.AsEnumerable()
.OrderByDescending(x => x.Fields["duration"].Value) //Order extended events by duration descenting
.Select(y => new MaxEventSelected() //creating an object of the details of the highest duration event
{ eventName = y.Name, timeElapsed = y.Fields["duration"].Value.ToString(), sqlText = y.Fields["batch_text"].Value.ToString() })
.First();
//UI bindings
EventText.Text = eventSelected.eventName;
TimeElapsedText.Text = eventSelected.timeElapsed;
SQLText.Text = eventSelected.sqlText.Trim();
}
}
}
Παρατηρούμε ότι αρχικά δημιουργούμε ένα QueryableXEventData object το οποίο έχει ανοίξει μία σύνδεση με το αρχείο το οποίο παράχθηκε από το παραπάνω session. Στην συνέχεια, χρησιμοποιώντας LINQ κάνουμε sort με το duration descending τα events που περιέχονται σε αυτό και δημιουργούμε ένα ExtendedEvent object (του οποίου έχουμε ορίσει εμείς την κλάση) με το μεγαλύτερο σε διάρκεια event. Όντως τρέχοντας το παραπάνω κομμάτι κώδικα το αποτέλεσμα είναι: