Skip to content

Commit 7af63e2

Browse files
Merge pull request #764 from erikdarlingdata/dev
Release v4.20
2 parents b5974bc + a376719 commit 7af63e2

11 files changed

Lines changed: 765 additions & 285 deletions

File tree

sp_HealthParser/sp_HealthParser.sql

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ BEGIN
7272
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
7373

7474
SELECT
75-
@version = '3.4',
76-
@version_date = '20260401';
75+
@version = '3.5',
76+
@version_date = '20260420';
7777

7878
IF @help = 1
7979
BEGIN
@@ -435,15 +435,24 @@ AND ca.utc_timestamp < @end_date';
435435
END;
436436
ELSE
437437
BEGIN
438-
/* 2017+ handling */
438+
/*
439+
2017+ handling. Use the same half-open (>= @start_date AND
440+
< @end_date) shape as the pre-2017 branch so an event captured
441+
at exactly @end_date is not included on 2017+ while excluded
442+
on pre-2017 — previously BETWEEN meant a closed interval on
443+
2017+ and a row at the boundary could appear or not depending
444+
on which branch ran.
445+
*/
439446
SET @cross_apply = N'CROSS APPLY xml.{object_name}.nodes(''/event'') AS e(x)';
440447

441448
IF @timestamp_utc_mode = 1
442449
SET @time_filter = N'
443-
AND CONVERT(datetimeoffset(7), fx.timestamp_utc) BETWEEN @start_date AND @end_date';
450+
AND CONVERT(datetimeoffset(7), fx.timestamp_utc) >= @start_date
451+
AND CONVERT(datetimeoffset(7), fx.timestamp_utc) < @end_date';
444452
ELSE
445453
SET @time_filter = N'
446-
AND fx.timestamp_utc BETWEEN @start_date AND @end_date';
454+
AND fx.timestamp_utc >= @start_date
455+
AND fx.timestamp_utc < @end_date';
447456
END;
448457

449458
SET @sql_template =
@@ -2218,7 +2227,21 @@ AND ca.utc_timestamp < @end_date';
22182227
),
22192228
tc.wait_type,
22202229
waits = SUM(CONVERT(bigint, tc.waits)),
2221-
average_wait_time_ms = CONVERT(bigint, AVG(tc.average_wait_time_ms)),
2230+
/*
2231+
Weighted average rather than AVG(avg): tc.average_wait_time_ms
2232+
is already a per-event average, so AVG() over the bucket was
2233+
an unweighted mean of means — events with one wait got the
2234+
same pull on the output as events with thousands. Weight by
2235+
waits to get the true bucket-scoped average. NULLIF keeps us
2236+
safe if every contributing row had waits = 0.
2237+
*/
2238+
average_wait_time_ms =
2239+
CONVERT
2240+
(
2241+
bigint,
2242+
SUM(CONVERT(decimal(38, 2), tc.average_wait_time_ms) * CONVERT(decimal(38, 2), tc.waits))
2243+
/ NULLIF(SUM(CONVERT(decimal(38, 2), tc.waits)), 0)
2244+
),
22222245
max_wait_time_ms = CONVERT(bigint, MAX(tc.max_wait_time_ms))
22232246
INTO #tc
22242247
FROM #topwaits_count AS tc
@@ -2951,7 +2974,11 @@ AND ca.utc_timestamp < @end_date';
29512974
CROSS APPLY wi.sp_server_diagnostics_component_result.nodes('/event') AS w(x)
29522975
WHERE w.x.exist('(data[@name="component"]/text[.= "QUERY_PROCESSING"])') = 1
29532976
AND (w.x.exist('(data[@name="state"]/text[.= "WARNING"])') = @warnings_only OR @warnings_only = 0)
2954-
AND (w.x.exist('(/event/data[@name="data"]/value/queryProcessing/@pendingTasks[.>= sql:variable("@pending_task_threshold")])') = 1 OR @warnings_only = 0)
2977+
/* Threshold is honored whether or not @warnings_only is set — the
2978+
parameter documents "minimum pending tasks to display" and the
2979+
previous `OR @warnings_only = 0` short-circuit silently ignored
2980+
the user-supplied value whenever warnings-only was off. */
2981+
AND w.x.exist('(/event/data[@name="data"]/value/queryProcessing/@pendingTasks[.>= sql:variable("@pending_task_threshold")])') = 1
29552982
OPTION(RECOMPILE, MAXDOP 1);
29562983

29572984
IF @debug = 1
@@ -3176,7 +3203,10 @@ AND ca.utc_timestamp < @end_date';
31763203
INTO #pending_task_details
31773204
FROM #sp_server_diagnostics_component_result AS wi
31783205
CROSS APPLY wi.sp_server_diagnostics_component_result.nodes('/event') AS w(x)
3179-
CROSS APPLY w.x.nodes('/event/data[@name="data"]/value/queryProcessing[@pendingTasks > 1]/pendingTasks/entryPoint') AS ep(e)
3206+
/* Hardcoded threshold > 1 ignored the @pending_task_threshold
3207+
parameter. Replaced with sql:variable() binding so the user's
3208+
value actually takes effect here too. */
3209+
CROSS APPLY w.x.nodes('/event/data[@name="data"]/value/queryProcessing[@pendingTasks >= sql:variable("@pending_task_threshold")]/pendingTasks/entryPoint') AS ep(e)
31803210
WHERE w.x.exist('(data[@name="component"]/text[.= "QUERY_PROCESSING"])') = 1
31813211
AND (w.x.exist('(data[@name="state"]/text[.= "WARNING"])') = @warnings_only OR @warnings_only = 0)
31823212
OPTION(RECOMPILE, MAXDOP 1);
@@ -5721,9 +5751,16 @@ AND ca.utc_timestamp < @end_date';
57215751
FROM #deadlocks AS d
57225752
CROSS APPLY d.xml_deadlock_report.nodes('//deadlock/process-list/process') AS e(x)
57235753
) AS x
5754+
/* Standard "filter if supplied, pass-through if NULL" predicate
5755+
pairs must be combined with AND between the groups — OR let
5756+
rows through whenever either parameter was NULL, which makes
5757+
the @database_name/@dbid filter loose whenever only one side
5758+
was supplied. Currently masked because the validation block
5759+
above aborts when the two disagree, but the shape was
5760+
wrong and would break if that validation ever relaxed. */
57245761
WHERE (x.database_id = @dbid
57255762
OR @dbid IS NULL)
5726-
OR (x.current_database_name = @database_name
5763+
AND (x.current_database_name = @database_name
57275764
OR @database_name IS NULL)
57285765
OPTION(RECOMPILE, MAXDOP 1);
57295766

0 commit comments

Comments
 (0)