Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions sp_HumanEvents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ EXECUTE dbo.sp_HumanEvents

This was originally a companion script to analyze the blocked process report Extended Event created by sp_HumanEvents, but has since turned into its own monster.

It will work on any Extended Event that captures the blocked process report. If you need to set that up, run these two pieces of code.
It will work on any Extended Event that captures the blocked process report. If you need to set that up, run the next two pieces of code.

The system_health Extended Event works, but its blocked process report is much less comprehensive than the real thing. I do not allow logging to a table from this, because the set of columns and available data is too incomplete, and I don't want to juggle multiple table definitions.

## Setup

Expand Down Expand Up @@ -172,28 +174,28 @@ ON SERVER

## Parameters

| parameter_name | data_type | description | valid_inputs | defaults |
|-----------------------|-----------|-------------------------------------------------|------------------------------------------------------------------------|------------------------------------|
| @session_name | sysname | name of the extended event session to pull from | extended event session name capturing sqlserver.blocked_process_report | keeper_HumanEvents_blocking |
| @target_type | sysname | target of the extended event session | event_file or ring_buffer | NULL |
| @start_date | datetime2 | filter by date | a reasonable date | NULL; will shortcut to last 7 days |
| @end_date | datetime2 | filter by date | a reasonable date | NULL |
| @database_name | sysname | filter by database name | a database that exists on this server | NULL |
| @object_name | sysname | filter by table name | a schema-prefixed table name | NULL |
| @target_database | sysname | database containing the table with BPR data | a valid database name | NULL |
| @target_schema | sysname | schema of the table | a valid schema name | NULL |
| @target_table | sysname | table name | a valid table name | NULL |
| @target_column | sysname | column containing XML data | a valid column name | NULL |
| @timestamp_column | sysname | column containing timestamp (optional) | a valid column name | NULL |
| @log_to_table | bit | enable logging to permanent tables | 0 or 1 | 0 |
| @log_database_name | sysname | database to store logging tables | a valid database name | NULL |
| @log_schema_name | sysname | schema to store logging tables | a valid schema name | NULL |
| @log_table_name_prefix| sysname | prefix for all logging tables | a valid table name prefix | 'HumanEventsBlockViewer' |
| @log_retention_days | integer | Number of days to keep logs, 0 = keep indefinitely | a valid integer | 30 |
| @help | bit | how you got here | 0 or 1 | 0 |
| @debug | bit | dumps raw temp table contents | 0 or 1 | 0 |
| @version | varchar | OUTPUT; for support | none; OUTPUT | none; OUTPUT |
| @version_date | datetime | OUTPUT; for support | none; OUTPUT | none; OUTPUT |
| parameter_name | data_type | description | valid_inputs | defaults |
|-----------------------|-----------|----------------------------------------------------|--------------------------------------------------------------------------------------------------|------------------------------------|
| @session_name | sysname | name of the extended event session to pull from | extended event session name capturing sqlserver.blocked_process_report, system_health also works | keeper_HumanEvents_blocking |
| @target_type | sysname | target of the extended event session | event_file or ring_buffer or table | NULL |
| @start_date | datetime2 | filter by date | a reasonable date | NULL; will shortcut to last 7 days |
| @end_date | datetime2 | filter by date | a reasonable date | NULL |
| @database_name | sysname | filter by database name | a database that exists on this server | NULL |
| @object_name | sysname | filter by table name | a schema-prefixed table name | NULL |
| @target_database | sysname | database containing the table with BPR data | a valid database name | NULL |
| @target_schema | sysname | schema of the table | a valid schema name | NULL |
| @target_table | sysname | table name | a valid table name | NULL |
| @target_column | sysname | column containing XML data | a valid column name | NULL |
| @timestamp_column | sysname | column containing timestamp (optional) | a valid column name | NULL |
| @log_to_table | bit | enable logging to permanent tables | 0 or 1 | 0 |
| @log_database_name | sysname | database to store logging tables | a valid database name | NULL |
| @log_schema_name | sysname | schema to store logging tables | a valid schema name | NULL |
| @log_table_name_prefix| sysname | prefix for all logging tables | a valid table name prefix | 'HumanEventsBlockViewer' |
| @log_retention_days | integer | Number of days to keep logs, 0 = keep indefinitely | a valid integer | 30 |
| @help | bit | how you got here | 0 or 1 | 0 |
| @debug | bit | dumps raw temp table contents | 0 or 1 | 0 |
| @version | varchar | OUTPUT; for support | none; OUTPUT | none; OUTPUT |
| @version_date | datetime | OUTPUT; for support | none; OUTPUT | none; OUTPUT |

## Usage Examples

Expand All @@ -219,4 +221,4 @@ EXECUTE dbo.sp_HumanEventsBlockViewer
@log_to_table = 1,
@log_database_name = 'DBA',
@log_schema_name = 'dbo';
```
```
66 changes: 53 additions & 13 deletions sp_HumanEvents/sp_HumanEventsBlockViewer.sql
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ BEGIN
SELECT 'it will also work with any other extended event session that captures blocking' UNION ALL
SELECT 'just use the @session_name parameter to point me there' UNION ALL
SELECT 'EXECUTE dbo.sp_HumanEventsBlockViewer @session_name = N''blocked_process_report'';' UNION ALL
SELECT 'the system_health session also works, if you are okay with its lousy blocked process report'
SELECT 'all scripts and documentation are available here: https://code.erikdarling.com' UNION ALL
SELECT 'from your loving sql server consultant, erik darling: https://erikdarling.com';

Expand Down Expand Up @@ -137,8 +138,8 @@ BEGIN
END,
valid_inputs =
CASE ap.name
WHEN N'@session_name' THEN 'extended event session name capturing sqlserver.blocked_process_report'
WHEN N'@target_type' THEN 'event_file or ring_buffer'
WHEN N'@session_name' THEN 'extended event session name capturing sqlserver.blocked_process_report, system_health also works'
WHEN N'@target_type' THEN 'event_file or ring_buffer or table'
WHEN N'@start_date' THEN 'a reasonable date'
WHEN N'@end_date' THEN 'a reasonable date'
WHEN N'@database_name' THEN 'a database that exists on this server'
Expand Down Expand Up @@ -195,7 +196,7 @@ BEGIN
N'check the messages tab for setup commands';

RAISERROR('
The blocked process report needs to be enabled:
Unless you want to use the lousy version in system_health, the blocked process report needs to be enabled:
EXECUTE sys.sp_configure ''show advanced options'', 1;
EXECUTE sys.sp_configure ''blocked process threshold'', 5; /* Seconds of blocking before a report is generated */
RECONFIGURE;', 0, 1) WITH NOWAIT;
Expand Down Expand Up @@ -273,8 +274,9 @@ IF EXISTS
WHERE c.name = N'blocked process threshold (s)'
AND CONVERT(int, c.value_in_use) = 0
)
AND @session_name NOT LIKE N'system%health'
BEGIN
RAISERROR(N'The blocked process report needs to be enabled:
RAISERROR(N'Unless you want to use the lousy version in system_health, the blocked process report needs to be enabled:
EXECUTE sys.sp_configure ''show advanced options'', 1;
EXECUTE sys.sp_configure ''blocked process threshold'', 5; /* Seconds of blocking before a report is generated */
RECONFIGURE;',
Expand All @@ -291,6 +293,7 @@ IF EXISTS
WHERE c.name = N'blocked process threshold (s)'
AND CONVERT(int, c.value_in_use) <> 5
)
AND @session_name NOT LIKE N'system%health'
BEGIN
RAISERROR(N'For best results, set up the blocked process report like this:
EXECUTE sys.sp_configure ''show advanced options'', 1;
Expand Down Expand Up @@ -439,6 +442,47 @@ BEGIN
FROM {table_check};
END;';

IF @debug = 1
AND @is_system_health = 0
BEGIN
RAISERROR('We are not using system_health', 0, 1) WITH NOWAIT;
END;

IF @is_system_health = 1
BEGIN
RAISERROR('For best results, consider not using system_health as your target. Re-run with @help = 1 for guidance.', 0, 1) WITH NOWAIT;
END

/*
Note: I do not allow logging to a table from system_health, because the set of columns
and available data is too incomplete, and I don't want to juggle multiple
table definitions.

Logging to a table is only allowed from a blocked_process_report Extended Event,
but it can either be ring buffer or file target. I don't care about that.
*/
IF @is_system_health = 1
AND
(
LOWER(@target_type) = N'table'
OR @log_to_table = 1
)
BEGIN
RAISERROR('Logging system_health to a table is not supported.
Either pick a different session or change both
@target_type to be ''event_file'' or ''ring_buffer''
and @log_to_table to be 0.', 11, 0) WITH NOWAIT;
RETURN;
END

IF @is_system_health = 1
AND @target_type IS NULL
BEGIN
RAISERROR('No @target_type specified, using the ''event_file'' for system_health.', 0, 1) WITH NOWAIT;
SELECT
@target_type = 'event_file';
END

SELECT
@azure_msg =
CONVERT(nchar(1), @azure),
Expand All @@ -450,6 +494,7 @@ IF ISNULL(@target_database, DB_NAME()) IS NOT NULL
AND ISNULL(@target_schema, N'dbo') IS NOT NULL
AND @target_table IS NOT NULL
AND @target_column IS NOT NULL
AND @is_system_health = 0
BEGIN
SET @target_type = N'table';
END;
Expand Down Expand Up @@ -1125,18 +1170,13 @@ END;

/*
This section is special for the well-hidden and much less comprehensive blocked
process report stored in the system health extended event session

Note: I do not allow logging to a table from this, because the set of columns
and available data is too incomplete, and I don't want to juggle multiple
table definitions.
process report stored in the system health extended event session.

Logging to a table is only allowed from the a blocked_process_report Extended Event,
but it can either be ring buffer or file target. I don't care about that.
We disallow many features here.
See where @is_system_health was declared for details.
That is also where we error out if somebody tries to use an unsupported feature.
*/
IF @is_system_health = 1
AND LOWER(@target_type) <> N'table'
AND @log_to_table = 0
BEGIN
IF @debug = 1
BEGIN
Expand Down