Extended Events sessions have a way of quietly accumulating on a busy instance. Someone stood up a trace for a specific investigation six months ago, and it’s still running, still writing files, and nobody remembers why. Before you start a new session, or clean up an old one, you need one honest answer to “what’s actually running right now, and where is it writing.”
Two scripts answer that here, and they answer different halves of it. The first is the inventory: every non-default Extended Events session currently active, its target, its output file, and whether it is set to survive a service restart. The second is the bill: what those sessions are costing the instance in buffers, dropped events, and blocked firing time.
Why Active XE Sessions Matters
Extended Events is low overhead per session, but sessions left running indefinitely still cost something, disk space filling up with rolling .xel files nobody’s reading, buffer memory held for events nobody’s consuming, and the simple operational risk of not knowing what’s collecting data on your server:
- A session created for a one-off investigation and never removed keeps consuming disk and buffer resources long after anyone needs the data.
startup_statedetermines whether a session survives a service restart, a session you thought was temporary can turn out to be permanent if it was created withSTARTUP_STATE = ON.- Dropped events or dropped buffers on a running session are an early sign it’s under more load than its configuration can keep up with.
When to Run This Script
- Before creating a new Extended Events session, to check whether a similarly-named or overlapping session is already running
- As part of a routine health check, to catch abandoned sessions from past investigations
- Immediately after starting one of the trace sessions in this series, to confirm it’s actually running and pointed at the file path you expect
- Before a cleanup pass with Remove XE Session, to see what’s currently active before deciding what to stop
The Scripts
Run these against your SQL Server instance. The first tells you what exists; the second tells you what it costs.
1. Get-ActiveXeSessions — What Is Running, and Where Its Files Are
- Tested on: SQL Server 2025 (RTM CU8), Windows lab instance
- Last verified: 2026-08-30 (all 2 scripts on this page run, saved outputs from real runs)
- Permissions: VIEW SERVER STATE
- Safety: read-only, impact low
/*
Script Name : Get-ActiveXeSessions
Category : traces
Purpose : Shows all currently running Extended Events sessions with their targets and file output paths.
Author : Peter Whyte (https://sqldba.blog/dba-scripts-get-active-xe-sessions/)
Requires : VIEW SERVER STATE
*/
-- SAFE:ReadOnly
-- IMPACT:Low
SET NOCOUNT ON;
SELECT
s.name AS session_name,
s.create_time AS started_at,
DATEDIFF(HOUR, s.create_time, GETDATE()) AS running_hours,
t.target_name,
CAST(
CAST(t.target_data AS XML).value(
'(EventFileTarget/File/@name)[1]', 'nvarchar(500)')
AS NVARCHAR(500)) AS output_file,
s.total_buffer_size / 1024 / 1024 AS buffer_size_mb,
s.dropped_event_count,
s.dropped_buffer_count,
ses.startup_state AS auto_start_on_restart
FROM sys.dm_xe_sessions s
JOIN sys.dm_xe_session_targets t ON t.event_session_address = s.address
JOIN sys.server_event_sessions ses ON ses.name = s.name
WHERE s.name NOT IN (
'system_health', 'telemetry_xevents', 'hkenginexesession',
'AlwaysOn_health', 'sp_server_diagnostics session'
)
ORDER BY s.create_time DESC;
Reads sys.dm_xe_sessions joined to its running targets and sys.server_event_sessions, excludes the built-in system sessions (system_health, telemetry_xevents, hkenginexesession, AlwaysOn_health, sp_server_diagnostics session), and returns every DBA-created session that’s currently active, newest first.
2. Get-ExtendedEventsSessions — What Those Sessions Are Costing
The inventory tells you a session exists. This one tells you whether it is paying its way: memory held in buffers, events dropped because those buffers could not keep up, and time the server spent blocked while the session fired. It is part of the standard health check for that reason.
/*
Script Name : Get-ExtendedEventsSessions
Category : monitoring
Purpose : Active Extended Events sessions — name, state, targets, and estimated disk impact.
Surfaces unexpected or high-overhead XE sessions on inherited servers.
Author : Peter Whyte (https://sqldba.blog/dba-scripts-get-extended-events-sessions/)
Requires : VIEW SERVER STATE
HealthCheck : Yes
*/
-- SAFE:ReadOnly
-- IMPACT:Low
SET NOCOUNT ON;
SET QUOTED_IDENTIFIER ON;
SELECT
s.name AS session_name,
s.create_time,
CASE s.pending_buffers WHEN 0 THEN 'ACTIVE' ELSE 'ACTIVE (pending writes)' END AS state,
s.total_regular_buffers AS buffer_count,
s.regular_buffer_size AS buffer_size_bytes,
s.total_large_buffers AS large_buffer_count,
s.large_buffer_size AS large_buffer_size_bytes,
s.dropped_event_count AS dropped_events,
s.dropped_buffer_count AS dropped_buffers,
s.blocked_event_fire_time AS blocked_fire_time_ms,
STUFF((
SELECT ', ' + t.target_name
FROM sys.dm_xe_session_targets t
WHERE t.event_session_address = s.address
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(500)'), 1, 2, '') AS targets,
CASE
WHEN EXISTS (
SELECT 1 FROM sys.dm_xe_session_targets t
WHERE t.event_session_address = s.address
AND t.target_name IN ('asynchronous_file_target', 'ring_buffer')
) THEN 'File/ring buffer - potential I/O or memory overhead'
ELSE 'OK'
END AS overhead_note,
CASE s.name
WHEN 'system_health' THEN 'Built-in - monitors deadlocks, connectivity errors, scheduler health'
WHEN 'AlwaysOn_health' THEN 'Built-in - AG health events (present on AG instances)'
WHEN 'telemetry_xevents' THEN 'Built-in - SQL Server telemetry collection'
WHEN 'hkenginexesession' THEN 'Built-in - In-Memory OLTP (Hekaton) session'
WHEN 'sp_server_diagnostics session'
THEN 'Built-in - WSFC diagnostics for AG/FCI'
ELSE 'Custom or third-party session - verify purpose and owner'
END AS session_note
FROM sys.dm_xe_sessions AS s
ORDER BY
CASE WHEN s.name IN ('system_health','AlwaysOn_health','telemetry_xevents',
'hkenginexesession','sp_server_diagnostics session')
THEN 1 ELSE 0 END,
s.name;
Same source DMVs, a different question: this reports buffer allocation and the two loss counters per session, then labels the overhead so a session that is quietly hurting the instance is obvious without reading the numbers. One scope difference worth knowing: unlike the inventory above, this one includes SQL Server’s own sessions, so expect system_health and telemetry_xevents in the results.
How To Run From The Repo
Clone DBA Tools, initialize and run the script:
# Clone dba-tools repo:
git clone https://github.com/peterwhyte-lgtm/dba-tools
# Initialize environment:
cd dba-tools
.\Initialize-Environment.ps1
# List every non-default Extended Events session currently running:
.\run.ps1 Get-ActiveXeSessions
# To run against a remote sql server:
.\run.ps1 Get-ActiveXeSessions -ServerInstance SQLSERVER01
This script lives in the repo at:
Example Output
1. What is running. Three sessions, all created by a DBA, none of them SQL Server’s own. Every output_file shows the real name on disk, with the sequence and timestamp suffix SQL Server appends, which is the path to hand to the read-back script.

2. What it costs. The same instance through the overhead script, and note the row count: seven, not three. This one does not filter out SQL Server’s own sessions, so system_health, telemetry_xevents and friends appear alongside yours. That is deliberate, and it is why system_health showing 205 dropped events here is not an alarm: the built-ins drop events routinely under load and are not yours to tune. Read the loss counters against the sessions you created.

Understanding the Results
running_hoursoutput_fileauto_start_on_restartSTARTUP_STATE as a bit. 1 means the session comes back by itself after a service restart: useful for something meant to be permanent, a trap if you thought it was temporary.buffer_countbuffer_size_bytesdropped_eventsdropped_buffersblocked_fire_time_msoverhead_noteBest Practices
- Run this before starting any new session, a name collision or an overlapping capture wastes effort and disk space.
- Treat a session with a
running_hourscount in the thousands as a question, not a fact, find out why it’s still running before assuming it’s fine. - Watch
dropped_event_count/dropped_buffer_counton anything you’re relying on for an audit or decommission decision, dropped data undermines the “we saw nothing” conclusion you’re trying to prove. - Pair this with Remove XE Session as a routine two-step check: see what’s running here, then decide what to clean up there.
Microsoft’s reference covers sys.dm_xe_sessions, sys.server_event_sessions and sp_server_diagnostics in full.
Related Scripts
You may also find these scripts useful:
- Create Decommission Audit Session
- Create Login Activity Session
- Create SP Execution Session
- Get XE Session Activity
- Remove XE Session
- DBA Scripts: The Complete Guide, the map across every script on this site
Frequently Asked Questions
Why does system_health not appear in the results?
It is filtered out deliberately, along with telemetry_xevents and the other built-in sessions SQL Server ships and runs itself. This script answers “what did we put here,” so an empty result means no DBA-created session is running, not that Extended Events is idle.
A session shows as running but its file is empty. Why?
Events sit in memory until dispatch latency flushes them to the file target, so a session only seconds old genuinely has nothing on disk yet. Give it a minute. If it stays empty after that, check the session’s filters, and check dropped_event_count here before assuming the instance is quiet.
Summary
A running Extended Events session is easy to start and easy to forget. This script is the honest inventory, what’s actually collecting data on this instance right now, where it’s writing, and whether it survives a restart, so a trace never becomes a permanent fixture nobody remembers creating.
Run it before starting anything new, and make it a routine check alongside cleanup with Remove XE Session.
Leave a Reply