Skip to content

Instantly share code, notes, and snippets.

@JosiahSiegel
Created May 13, 2025 13:26
Show Gist options
  • Save JosiahSiegel/627f2fdb4f535ef1eb80db1384b75626 to your computer and use it in GitHub Desktop.
Save JosiahSiegel/627f2fdb4f535ef1eb80db1384b75626 to your computer and use it in GitHub Desktop.
SQL Server Event Session - LoginTracking
-- Create an Extended Events session to track login activities
CREATE EVENT SESSION [LoginTracking] ON SERVER
ADD EVENT sqlserver.login(
ACTION(
sqlserver.client_app_name, -- Application name
sqlserver.client_hostname, -- Client hostname
sqlserver.client_pid, -- Client process ID
sqlserver.database_name, -- Database name
sqlserver.nt_username, -- Windows username
sqlserver.server_principal_name, -- SQL Server login name
sqlserver.session_id, -- Session ID
sqlserver.session_nt_username, -- Windows username for the session
sqlserver.username -- Username
)
WHERE ([package0].[greater_than_uint64]([sqlserver].[session_id],(50))) -- Filter out system sessions
),
ADD EVENT sqlserver.logout(
ACTION(
sqlserver.client_app_name,
sqlserver.client_hostname,
sqlserver.client_pid,
sqlserver.database_name,
sqlserver.nt_username,
sqlserver.server_principal_name,
sqlserver.session_id,
sqlserver.session_nt_username,
sqlserver.username
)
WHERE ([package0].[greater_than_uint64]([sqlserver].[session_id],(50)))
),
ADD EVENT sqlserver.error_reported(
ACTION(
sqlserver.client_app_name,
sqlserver.client_hostname,
sqlserver.client_pid,
sqlserver.database_name,
sqlserver.nt_username,
sqlserver.server_principal_name,
sqlserver.session_id,
sqlserver.username
)
WHERE (
[error_number]=(18456) -- Login failed error
AND [package0].[greater_than_uint64]([sqlserver].[session_id],(50))
)
)
-- Add file target using relative path (will be stored in SQL Server's default log directory)
ADD TARGET package0.event_file(SET
filename=N'LoginTracking.xel', -- Relative path will place it in SQL Server's log directory
max_file_size=(100),
max_rollover_files=(5)
)
WITH (
MAX_MEMORY=4096 KB,
EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY=30 SECONDS,
MAX_EVENT_SIZE=0 KB,
MEMORY_PARTITION_MODE=NONE,
TRACK_CAUSALITY=OFF,
STARTUP_STATE=ON
);
GO
-- Start the Extended Events session
ALTER EVENT SESSION [LoginTracking] ON SERVER STATE = START;
GO
-- Script to query login data using the relative path for .xel files
SELECT
DATEADD(hour, DATEDIFF(hour, GETUTCDATE(), CURRENT_TIMESTAMP), event_data.value('(event/@timestamp)[1]', 'datetime2')) AS local_time,
event_data.value('(event/action[@name="server_principal_name"]/value)[1]', 'nvarchar(max)') AS login_name,
event_data.value('(event/action[@name="client_app_name"]/value)[1]', 'nvarchar(max)') AS application_name,
event_data.value('(event/action[@name="client_hostname"]/value)[1]', 'nvarchar(max)') AS hostname,
event_data.value('(event/action[@name="database_name"]/value)[1]', 'nvarchar(max)') AS database_name,
object_name AS event_type
FROM
(
SELECT
CAST(event_data AS XML) AS event_data,
object_name
FROM
sys.fn_xe_file_target_read_file('LoginTracking*.xel', NULL, NULL, NULL)
) AS XEvents
ORDER BY local_time DESC;
GO
-- Daily login summary report using the relative path
-- Daily login summary report - Fixed to avoid XML methods in GROUP BY
WITH LoginData AS (
SELECT
DATEADD(hour, DATEDIFF(hour, GETUTCDATE(), CURRENT_TIMESTAMP), event_data.value('(event/@timestamp)[1]', 'datetime2')) AS event_time,
event_data.value('(event/action[@name="server_principal_name"]/value)[1]', 'nvarchar(max)') AS login_name,
event_data.value('(event/action[@name="client_app_name"]/value)[1]', 'nvarchar(max)') AS application_name,
event_data.value('(event/action[@name="database_name"]/value)[1]', 'nvarchar(max)') AS database_name,
event_data.value('(event/action[@name="client_hostname"]/value)[1]', 'nvarchar(max)') AS hostname,
object_name
FROM
(
SELECT
CAST(event_data AS XML) AS event_data,
object_name
FROM
sys.fn_xe_file_target_read_file('LoginTracking*.xel', NULL, NULL, NULL)
) AS XEvents
WHERE object_name = 'login'
)
SELECT TOP 100 PERCENT
CONVERT(date, event_time) AS login_date,
login_name,
application_name,
database_name,
hostname,
COUNT(*) AS login_count
FROM LoginData
GROUP BY
CONVERT(date, event_time),
login_name,
application_name,
database_name,
hostname
ORDER BY
login_date DESC,
login_count DESC;
GO
/*
-- Monitor the Extended Events session with:
SELECT * FROM sys.dm_xe_sessions WHERE name = 'LoginTracking';
GO
-- Stop the Extended Events session (run when you no longer need to track logins)
ALTER EVENT SESSION [LoginTracking] ON SERVER STATE = STOP;
GO
-- Drop the session if needed
DROP EVENT SESSION [LoginTracking] ON SERVER;
GO
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment