| title | XEvent Event File code | ||
|---|---|---|---|
| description | Provides PowerShell and Transact-SQL for a two-phase code sample that demonstrates the Event File target in an extended event on Azure SQL Database and SQL Managed Instance. Azure Storage is a required part of this scenario. | ||
| author | WilliamDAssafMSFT | ||
| ms.author | wiassaf | ||
| ms.reviewer | wiassaf, mathoma | ||
| ms.date | 05/25/2023 | ||
| ms.service | sql-database | ||
| ms.subservice | performance | ||
| ms.topic | sample | ||
| ms.custom |
|
||
| ms.devlang | PowerShell | ||
| monikerRange | = azuresql || = azuresql-db || = azuresql-mi |
[!INCLUDEappliesto-sqldb]
[!INCLUDE sql-database-xevents-selectors-1-include]
You want a complete code sample for a robust way to capture and report information for an extended event.
- In Microsoft SQL Server, the Event File target is used to store event outputs into a locally-stored
.xelfile. - Since local storage is not available to Azure SQL Database or SQL Managed Instance, use Azure Blob Storage to support the Event File target.
This article presents a two-phase code sample:
- PowerShell, to create an Azure Storage container in the cloud.
- Transact-SQL:
- To assign the Azure Storage container to an Event File target.
- To create and start the event session, and so on.
[!INCLUDE updated-for-az]
Important
The PowerShell Azure Resource Manager module is still supported by Azure SQL Database, but all future development is for the Az.Sql module. For these cmdlets, see AzureRM.Sql. The arguments for the commands in the Az module and in the AzureRm modules are substantially identical.
-
An Azure account and subscription. You can sign up for a free trial.
-
Any database you can create a table in.
- Optionally you can create an
AdventureWorksLTdemonstration database in minutes.
- Optionally you can create an
-
SQL Server Management Studio (ssms.exe): Download SQL Server Management Studio
-
You must have the Azure PowerShell modules installed.
- The modules provide commands, such as
New-AzStorageAccount.
- The modules provide commands, such as
This PowerShell is phase 1 of the two-phase code sample.
The script starts with commands to clean up after a possible previous run, and is rerunnable.
-
Paste the PowerShell script into a simple text editor such as Notepad.exe, and save the script as a file with the extension
.ps1. -
Start PowerShell ISE as an Administrator.
-
At the prompt, type
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
and then press Enter. -
In PowerShell ISE, open your .ps1 file. Run the script.
-
The script first starts a new window in which you sign in to Azure.
- If you rerun the script without disrupting your session, you have the convenient option of commenting out the Add-AzureAccount cmdlet.
:::image type="content" source="./media/xevent-code-event-file/event-file-powershell-ise-b30.png" alt-text="A screenshot of the PowerShell ISE, with Azure module installed, ready to run script.":::
This PowerShell script assumes you've already installed the Az module. For information, see Install the Azure PowerShell module.
## TODO: Before running, find all 'TODO' and make each edit!!
cls;
#--------------- 1 -----------------------
'Script assumes you have already logged your PowerShell session into Azure.
But if not, run Connect-AzAccount (or Connect-AzAccount), just one time.';
#Connect-AzAccount; # Same as Connect-AzAccount.
#-------------- 2 ------------------------
'
TODO: Edit the values assigned to these variables, especially the first few!
';
# Ensure the current date is between
# the Expiry and Start time values that you edit here.
$subscriptionName = 'YOUR_SUBSCRIPTION_NAME';
$resourceGroupName = 'YOUR_RESOURCE-GROUP-NAME';
$policySasExpiryTime = '2018-08-28T23:44:56Z';
$policySasStartTime = '2017-10-01';
$storageAccountLocation = 'YOUR_STORAGE_ACCOUNT_LOCATION';
$storageAccountName = 'YOUR_STORAGE_ACCOUNT_NAME';
$containerName = 'YOUR_CONTAINER_NAME';
$policySasToken = ' ? ';
$policySasPermission = 'rwl'; # Leave this value alone, as 'rwl'.
#--------------- 3 -----------------------
# The ending display lists your Azure subscriptions.
# One should match the $subscriptionName value you assigned
# earlier in this PowerShell script.
'Choose an existing subscription for the current PowerShell environment.';
Select-AzSubscription -Subscription $subscriptionName;
#-------------- 4 ------------------------
'
Clean up the old Azure Storage Account after any previous run,
before continuing this new run.';
if ($storageAccountName) {
Remove-AzStorageAccount `
-Name $storageAccountName `
-ResourceGroupName $resourceGroupName;
}
#--------------- 5 -----------------------
[System.DateTime]::Now.ToString();
'
Create a storage account.
This might take several minutes, will beep when ready.
...PLEASE WAIT...';
New-AzStorageAccount `
-Name $storageAccountName `
-Location $storageAccountLocation `
-ResourceGroupName $resourceGroupName `
-SkuName 'Standard_LRS';
[System.DateTime]::Now.ToString();
[System.Media.SystemSounds]::Beep.Play();
'
Get the access key for your storage account.
';
$accessKey_ForStorageAccount = `
(Get-AzStorageAccountKey `
-Name $storageAccountName `
-ResourceGroupName $resourceGroupName
).Value[0];
"`$accessKey_ForStorageAccount = $accessKey_ForStorageAccount";
'Azure Storage Account cmdlet completed.
Remainder of PowerShell .ps1 script continues.
';
#--------------- 6 -----------------------
# The context will be needed to create a container within the storage account.
'Create a context object from the storage account and its primary access key.
';
$context = New-AzStorageContext `
-StorageAccountName $storageAccountName `
-StorageAccountKey $accessKey_ForStorageAccount;
'Create a container within the storage account.
';
$containerObjectInStorageAccount = New-AzStorageContainer `
-Name $containerName `
-Context $context;
'Create a security policy to be applied to the SAS token.
';
New-AzStorageContainerStoredAccessPolicy `
-Container $containerName `
-Context $context `
-Policy $policySasToken `
-Permission $policySasPermission `
-ExpiryTime $policySasExpiryTime `
-StartTime $policySasStartTime;
'
Generate a SAS token for the container.
';
try {
$sasTokenWithPolicy = New-AzStorageContainerSASToken `
-Name $containerName `
-Context $context `
-Policy $policySasToken;
}
catch {
$Error[0].Exception.ToString();
}
#-------------- 7 ------------------------
'Display the values that YOU must edit into the Transact-SQL script next!:
';
"storageAccountName: $storageAccountName";
"containerName: $containerName";
"sasTokenWithPolicy: $sasTokenWithPolicy";
'
REMINDER: sasTokenWithPolicy here might start with "?" character, which you must exclude from Transact-SQL.
';
'
(Later, return here to delete your Azure Storage account. See the preceding Remove-AzStorageAccount -Name $storageAccountName)';
'
Now shift to the Transact-SQL portion of the two-part code sample!';
# EOFileTake note of the few named values that the PowerShell script prints when it ends. You must edit those values into the Transact-SQL script that follows as phase 2.
Note
In the preceding PowerShell code example, SQL extended events are not compatible with the ADLS Gen2 storage accounts.
- In phase 1 of this code sample, you ran a PowerShell script to create an Azure Storage container.
- Next in phase 2, the following Transact-SQL script must use the container.
The script starts with commands to clean up after a possible previous run, and is rerunnable.
The PowerShell script printed a few named values when it ended. You must edit the Transact-SQL script to use those values. Find TODO in the Transact-SQL script to locate the edit points.
- Open SQL Server Management Studio (ssms.exe).
- Connect to your database in Azure SQL Database or SQL Managed Instance.
- Select to open a new query pane.
- Paste the following Transact-SQL script into the query pane.
- Find every TODO in the script and make the appropriate edits.
- Save, and then run the script.
Warning
The SAS key value generated by the preceding PowerShell script might begin with a '?' (question mark). When you use the SAS key in the following T-SQL script, you must remove the leading '?'. Otherwise your efforts might be blocked by security.
---- TODO: First, run the earlier PowerShell portion of this two-part code sample.
---- TODO: Second, find every 'TODO' in this Transact-SQL file, and edit each.
---- Transact-SQL code for Event File target on Azure SQL Database or SQL Managed Instance.
SET NOCOUNT ON;
GO
---- Step 1. Establish one little table, and ---------
---- insert one row of data.
IF EXISTS
(SELECT * FROM sys.objects
WHERE type = 'U' and name = 'gmTabEmployee')
BEGIN
DROP TABLE gmTabEmployee;
END
GO
CREATE TABLE gmTabEmployee
(
EmployeeGuid uniqueIdentifier not null default newid() primary key,
EmployeeId int not null identity(1,1),
EmployeeKudosCount int not null default 0,
EmployeeDescr nvarchar(256) null
);
GO
INSERT INTO gmTabEmployee ( EmployeeDescr )
VALUES ( 'Jane Doe' );
GO
------ Step 2. Create key, and ------------
------ Create credential (your Azure Storage container must already exist).
IF NOT EXISTS
(SELECT * FROM sys.symmetric_keys
WHERE symmetric_key_id = 101)
BEGIN
---- TODO: Provide a strong password in the next line.
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'add strong password here'
END
GO
IF EXISTS
(SELECT * FROM sys.database_scoped_credentials
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
WHERE name = 'https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent')
BEGIN
DROP DATABASE SCOPED CREDENTIAL
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
[https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent] ;
END
GO
CREATE
DATABASE SCOPED
CREDENTIAL
-- use '.blob.', and not '.queue.' or '.table.' etc.
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
[https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent]
WITH
IDENTITY = 'SHARED ACCESS SIGNATURE', -- "SAS" token.
-- TODO: Paste in the long SasToken string here for Secret, but exclude any leading '?'.
SECRET = 'sv=2014-02-14&sr=c&si=gmpolicysastoken&sig=Ej...t8gOKTts%3D'
;
GO
------ Step 3. Create (define) an event session. --------
------ The event session has an event with an action,
------ and a has a target.
IF EXISTS
(SELECT * from sys.database_event_sessions
WHERE name = 'gmeventsessionname240b')
BEGIN
DROP
EVENT SESSION
gmeventsessionname240b
ON DATABASE;
END
GO
CREATE
EVENT SESSION
gmeventsessionname240b
ON DATABASE
ADD EVENT
sqlserver.sql_statement_starting
(
ACTION (sqlserver.sql_text)
WHERE statement LIKE 'UPDATE gmTabEmployee%'
)
ADD TARGET
package0.event_file
(
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
-- Also, tweak the .xel file name at end, if you like.
SET filename =
'https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent/anyfilenamexel242b.xel'
)
WITH
(MAX_MEMORY = 10 MB,
MAX_DISPATCH_LATENCY = 3 SECONDS)
;
GO
------ Step 4. Start the event session. ----------------
------ Issue the SQL Update statements that will be traced.
------ Then stop the session.
------ Note: If the target fails to attach,
------ the session must be stopped and restarted.
ALTER
EVENT SESSION
gmeventsessionname240b
ON DATABASE
STATE = START;
GO
SELECT 'BEFORE_Updates', EmployeeKudosCount, * FROM gmTabEmployee;
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 2
WHERE EmployeeDescr = 'Jane Doe';
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 13
WHERE EmployeeDescr = 'Jane Doe';
SELECT 'AFTER__Updates', EmployeeKudosCount, * FROM gmTabEmployee;
GO
ALTER
EVENT SESSION
gmeventsessionname240b
ON DATABASE
STATE = STOP;
GO
-------------- Step 5. Select the results. ----------
SELECT
*, 'CLICK_NEXT_CELL_TO_BROWSE_ITS_RESULTS!' as [CLICK_NEXT_CELL_TO_BROWSE_ITS_RESULTS],
CAST(event_data AS XML) AS [event_data_XML] -- TODO: In ssms.exe results grid, double-click this cell!
FROM
sys.fn_xe_file_target_read_file
(
-- TODO: Fill in Storage Account name, and the associated Container name.
-- TODO: The name of the .xel file needs to be an exact match to the files in the storage account Container (You can use Storage Account explorer from the portal to find out the exact file names or you can retrieve the name using the following DMV-query: select target_data from sys.dm_xe_database_session_targets. The 3rd xml-node, "File name", contains the name of the file currently written to.)
'https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent/anyfilenamexel242b',
null, null, null
);
GO
-------------- Step 6. Clean up. ----------
DROP
EVENT SESSION
gmeventsessionname240b
ON DATABASE;
GO
DROP DATABASE SCOPED CREDENTIAL
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
[https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent]
;
GO
DROP TABLE gmTabEmployee;
GO
PRINT 'Use PowerShell Remove-AzStorageAccount to delete your Azure Storage account!';
GOIf the target fails to attach when you run, you must stop and restart the event session:
ALTER EVENT SESSION gmeventsessionname240b
ON DATABASE STATE = STOP;
GO
ALTER EVENT SESSION gmeventsessionname240b
ON DATABASE STATE = START;
GOWhen the Transact-SQL script completes, select a cell under the event_data_XML column header. One <event> element is displayed which shows one UPDATE statement.
Here is one <event> element that was generated during testing:
<event name="sql_statement_starting" package="sqlserver" timestamp="2015-09-22T19:18:45.420Z">
<data name="state">
<value>0</value>
<text>Normal</text>
</data>
<data name="line_number">
<value>5</value>
</data>
<data name="offset">
<value>148</value>
</data>
<data name="offset_end">
<value>368</value>
</data>
<data name="statement">
<value>UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 2
WHERE EmployeeDescr = 'Jane Doe'</value>
</data>
<action name="sql_text" package="sqlserver">
<value>
SELECT 'BEFORE_Updates', EmployeeKudosCount, * FROM gmTabEmployee;
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 2
WHERE EmployeeDescr = 'Jane Doe';
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 13
WHERE EmployeeDescr = 'Jane Doe';
SELECT 'AFTER__Updates', EmployeeKudosCount, * FROM gmTabEmployee;
</value>
</action>
</event>- The preceding Transact-SQL script used the sys.fn_xe_file_target_read_file system function to read the event_file.
- For an explanation of advanced options for the viewing of data from extended events, see Advanced Viewing of Target Data from Extended Events.
Suppose you wanted to run the preceding Transact-SQL sample on Microsoft SQL Server.
-
For simplicity, you would want to completely replace use of the Azure Storage container with a simple file such as
C:\myeventdata.xel. The file would be written to the local hard drive of the computer that hosts SQL Server. -
You would not need any kind of Transact-SQL statements for
CREATE MASTER KEYandCREATE CREDENTIAL. -
In the
CREATE EVENT SESSIONstatement, in itsADD TARGETclause, you would replace the http value assigned made tofilename=with a full path string likeC:\myfile.xel. For more information, see CREATE EVENT SESSION (Transact-SQL).- An Azure Storage account is not needed.
For more info about accounts and containers in the Azure Storage service, see:
- How to use Blob storage from .NET
- Naming and Referencing Containers, Blobs, and Metadata
- Working with the Root Container
- Lesson 1: Create a stored access policy and a shared access signature on an Azure container
- Lesson 2: Create a SQL Server credential using a shared access signature
- Extended Events for Microsoft SQL Server