diff --git a/Workbooks/Database watcher/Azure SQL Database/database/connectivity/connectivity.workbook b/Workbooks/Database watcher/Azure SQL Database/database/connectivity/connectivity.workbook index b15951ffbf..948e550330 100644 --- a/Workbooks/Database watcher/Azure SQL Database/database/connectivity/connectivity.workbook +++ b/Workbooks/Database watcher/Azure SQL Database/database/connectivity/connectivity.workbook @@ -86,7 +86,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "aggregation": 3, "title": "Select a sample", @@ -124,7 +124,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "noDataMessage": "No connectivity samples are available", "queryType": 9, @@ -150,7 +150,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityLatestSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -162,7 +162,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityHistoricalSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -223,7 +223,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "noDataMessage": "No sample is selected", "queryType": 9, @@ -289,7 +289,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and database names\\r\\nlet connection_server_target = (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where database_name =~ @\\\"{databaseName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "title": "Connectivity probes", diff --git a/Workbooks/Database watcher/Azure SQL Database/elastic pool/connectivity/connectivity.workbook b/Workbooks/Database watcher/Azure SQL Database/elastic pool/connectivity/connectivity.workbook index 09fd5e2038..85f4aec73a 100644 --- a/Workbooks/Database watcher/Azure SQL Database/elastic pool/connectivity/connectivity.workbook +++ b/Workbooks/Database watcher/Azure SQL Database/elastic pool/connectivity/connectivity.workbook @@ -86,7 +86,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "aggregation": 3, "title": "Select a sample", @@ -124,7 +124,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "noDataMessage": "No connectivity samples are available", "queryType": 9, @@ -150,7 +150,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityLatestSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -162,7 +162,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityHistoricalSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -223,7 +223,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "noDataMessage": "No sample is selected", "queryType": 9, @@ -289,7 +289,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_target = (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where logical_server_name =~ @\\\"{serverName}\\\"\\r\\n| where elastic_pool_name =~ @\\\"{elasticPoolName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "title": "Connectivity probes", diff --git a/Workbooks/Database watcher/Azure SQL Database/estate/estate.workbook b/Workbooks/Database watcher/Azure SQL Database/estate/estate.workbook index 624841a1d2..91fe11e205 100644 --- a/Workbooks/Database watcher/Azure SQL Database/estate/estate.workbook +++ b/Workbooks/Database watcher/Azure SQL Database/estate/estate.workbook @@ -3473,7 +3473,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server name, database name, and replica type\\r\\nlet connection_server_database_target = materialize (\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nlet expected_probe_count = toscalar(\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n{databaseNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by logical_server_name, database_name, replica_type\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nlet database_properties = (\\r\\nsqldb_database_properties\\r\\n| where sample_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n{databaseNameFilter}\\r\\n| summarize arg_max(sample_time_utc, elastic_pool_name) by logical_server_name, database_name, replica_type\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_database_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{databaseNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by logical_server_name, database_name, replica_type\\r\\n| join kind=leftouter database_properties on logical_server_name, database_name, replica_type\\r\\n{elasticPoolNameFilter}\\r\\n| project logical_server_name, database_name, replica_type, elastic_pool_name, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\ncolor = case(\\r\\ntoreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all servers\\r\\ncount_failed_probes > 0, \\\"orange\\\",\\r\\ncount_successful_probes > 0, \\\"green\\\",\\r\\n\\\"\\\"\\r\\n),\\r\\ngrouper = case(\\r\\n\\\"{databaseHeatmapGroupBy}\\\" == \\\"server\\\", logical_server_name,\\r\\n\\\"{databaseHeatmapGroupBy}\\\" == \\\"server_and_pool\\\", strcat(logical_server_name, \\\" | \\\", iif(isempty(elastic_pool_name), \\\"(None)\\\", elastic_pool_name)),\\r\\nstrcat(logical_server_name, \\\" | \\\", database_name)\\r\\n),\\r\\nreplica_type_indicator = case(\\r\\nreplica_type == \\\"Primary\\\", \\\"🔵\\\",\\r\\nreplica_type == \\\"HA secondary\\\", \\\"🔘\\\",\\r\\nreplica_type == \\\"Geo-replication forwarder\\\", \\\"🟣\\\",\\r\\nreplica_type == \\\"Named secondary\\\", \\\"🟢\\\",\\r\\n\\\"\\\"\\r\\n)\\r\\n| project logical_server_name, database_name, decorated_database_name = strcat(replica_type_indicator, database_name), replica_type, elastic_pool_name, health_ratio, count_failed_probes, color, grouper = iif(\\\"{databaseHeatmapGroupBy}\\\" == \\\"none\\\", \\\"All databases\\\", grouper), top_tooltip = strcat(database_name, \\\" | \\\", logical_server_name, \\\" | \\\", replica_type_indicator, replica_type), ha_secondary = tolower(tostring(replica_type == \\\"HA secondary\\\"))\\r\\n| top {topHitters} by health_ratio asc\\r\\n| sort by health_ratio asc, tolower(grouper) asc, tolower(logical_server_name) asc, tolower(elastic_pool_name) asc, tolower(database_name) asc, iif(replica_type == \\\"HA secondary\\\", 1, 0) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server name, database name, and replica type\\r\\nlet connection_server_database_target = materialize (\\r\\nsqldb_database_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, database_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nlet expected_probe_count = toscalar(\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n{databaseNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by logical_server_name, database_name, replica_type\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nlet database_properties = (\\r\\nsqldb_database_properties\\r\\n| where sample_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n{databaseNameFilter}\\r\\n| summarize arg_max(sample_time_utc, elastic_pool_name) by logical_server_name, database_name, replica_type\\r\\n);\\r\\nsqldb_database_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_database_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and database_name. Look it up for the most recent successful probe with the same connection names.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n database_name = iif(isempty(database_name), database_name1, database_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{databaseNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by logical_server_name, database_name, replica_type\\r\\n| join kind=leftouter database_properties on logical_server_name, database_name, replica_type\\r\\n{elasticPoolNameFilter}\\r\\n| project logical_server_name, database_name, replica_type, elastic_pool_name, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\ncolor = case(\\r\\ntoreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all servers\\r\\ncount_failed_probes > 0, \\\"orange\\\",\\r\\ncount_successful_probes > 0, \\\"green\\\",\\r\\n\\\"\\\"\\r\\n),\\r\\ngrouper = case(\\r\\n\\\"{databaseHeatmapGroupBy}\\\" == \\\"server\\\", logical_server_name,\\r\\n\\\"{databaseHeatmapGroupBy}\\\" == \\\"server_and_pool\\\", strcat(logical_server_name, \\\" | \\\", iif(isempty(elastic_pool_name), \\\"(None)\\\", elastic_pool_name)),\\r\\nstrcat(logical_server_name, \\\" | \\\", database_name)\\r\\n),\\r\\nreplica_type_indicator = case(\\r\\nreplica_type == \\\"Primary\\\", \\\"🔵\\\",\\r\\nreplica_type == \\\"HA secondary\\\", \\\"🔘\\\",\\r\\nreplica_type == \\\"Geo-replication forwarder\\\", \\\"🟣\\\",\\r\\nreplica_type == \\\"Named secondary\\\", \\\"🟢\\\",\\r\\n\\\"\\\"\\r\\n)\\r\\n| project logical_server_name, database_name, decorated_database_name = strcat(replica_type_indicator, database_name), replica_type, elastic_pool_name, health_ratio, count_failed_probes, color, grouper = iif(\\\"{databaseHeatmapGroupBy}\\\" == \\\"none\\\", \\\"All databases\\\", grouper), top_tooltip = strcat(database_name, \\\" | \\\", logical_server_name, \\\" | \\\", replica_type_indicator, replica_type), ha_secondary = tolower(tostring(replica_type == \\\"HA secondary\\\"))\\r\\n| top {topHitters} by health_ratio asc\\r\\n| sort by health_ratio asc, tolower(grouper) asc, tolower(logical_server_name) asc, tolower(elastic_pool_name) asc, tolower(database_name) asc, iif(replica_type == \\\"HA secondary\\\", 1, 0) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "noDataMessage": "There is no data for specified parameters.", @@ -5231,7 +5231,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_pool_target = materialize (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nlet expected_probe_count = toscalar(\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by logical_server_name, elastic_pool_name, replica_type\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_pool_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by logical_server_name, elastic_pool_name, replica_type\\r\\n| project logical_server_name, elastic_pool_name, replica_type, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\ncolor = case(\\r\\ntoreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all servers\\r\\ncount_failed_probes > 0, \\\"orange\\\",\\r\\ncount_successful_probes > 0, \\\"green\\\",\\r\\n\\\"\\\"\\r\\n),\\r\\ngrouper = case(\\r\\n\\\"{poolHeatmapGroupBy}\\\" == \\\"server\\\", logical_server_name,\\r\\n\\\"{poolHeatmapGroupBy}\\\" == \\\"none\\\", \\\"All elastic pools\\\",\\r\\nstrcat(logical_server_name, \\\" | \\\", elastic_pool_name)\\r\\n),\\r\\nreplica_type_indicator = case(\\r\\nreplica_type == \\\"Primary\\\", \\\"🔵\\\",\\r\\nreplica_type == \\\"HA secondary\\\", \\\"🔘\\\",\\r\\n\\\"\\\"\\r\\n)\\r\\n| project logical_server_name, elastic_pool_name, decorated_elastic_pool_name = strcat(replica_type_indicator, elastic_pool_name), replica_type, health_ratio, count_failed_probes, grouper, top_tooltip = strcat(elastic_pool_name, \\\" | \\\", logical_server_name, \\\" | \\\", replica_type_indicator, replica_type), ha_secondary = tolower(tostring(replica_type == \\\"HA secondary\\\"))\\r\\n| top {topHitters} by health_ratio asc\\r\\n| sort by health_ratio asc, tolower(logical_server_name) asc, tolower(elastic_pool_name) asc, iif(replica_type == \\\"HA secondary\\\", 1, 0) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server/database name to target logical server and elastic pool names\\r\\nlet connection_server_pool_target = materialize (\\r\\nsqldb_elastic_pool_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, logical_server_name, elastic_pool_name, replica_type) by connection_server_name, connection_database_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nlet expected_probe_count = toscalar(\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by logical_server_name, elastic_pool_name, replica_type\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nsqldb_elastic_pool_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_pool_target on connection_server_name, connection_database_name, connection_application_intent // A failed probe has empty logical_server_name and elastic_pool_name. Look them up from the most recent successful probe for the same elastic pool.\\r\\n| extend logical_server_name = iif(isempty(logical_server_name), logical_server_name1, logical_server_name),\\r\\n elastic_pool_name = iif(isempty(elastic_pool_name), elastic_pool_name1, elastic_pool_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{serverNameFilter}\\r\\n{elasticPoolNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by logical_server_name, elastic_pool_name, replica_type\\r\\n| project logical_server_name, elastic_pool_name, replica_type, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\ncolor = case(\\r\\ntoreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all servers\\r\\ncount_failed_probes > 0, \\\"orange\\\",\\r\\ncount_successful_probes > 0, \\\"green\\\",\\r\\n\\\"\\\"\\r\\n),\\r\\ngrouper = case(\\r\\n\\\"{poolHeatmapGroupBy}\\\" == \\\"server\\\", logical_server_name,\\r\\n\\\"{poolHeatmapGroupBy}\\\" == \\\"none\\\", \\\"All elastic pools\\\",\\r\\nstrcat(logical_server_name, \\\" | \\\", elastic_pool_name)\\r\\n),\\r\\nreplica_type_indicator = case(\\r\\nreplica_type == \\\"Primary\\\", \\\"🔵\\\",\\r\\nreplica_type == \\\"HA secondary\\\", \\\"🔘\\\",\\r\\n\\\"\\\"\\r\\n)\\r\\n| project logical_server_name, elastic_pool_name, decorated_elastic_pool_name = strcat(replica_type_indicator, elastic_pool_name), replica_type, health_ratio, count_failed_probes, grouper, top_tooltip = strcat(elastic_pool_name, \\\" | \\\", logical_server_name, \\\" | \\\", replica_type_indicator, replica_type), ha_secondary = tolower(tostring(replica_type == \\\"HA secondary\\\"))\\r\\n| top {topHitters} by health_ratio asc\\r\\n| sort by health_ratio asc, tolower(logical_server_name) asc, tolower(elastic_pool_name) asc, iif(replica_type == \\\"HA secondary\\\", 1, 0) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "noDataMessage": "There is no data for specified parameters.", diff --git a/Workbooks/Database watcher/Azure SQL Managed Instance/estate/estate.workbook b/Workbooks/Database watcher/Azure SQL Managed Instance/estate/estate.workbook index d9e3484153..5221ebfffb 100644 --- a/Workbooks/Database watcher/Azure SQL Managed Instance/estate/estate.workbook +++ b/Workbooks/Database watcher/Azure SQL Managed Instance/estate/estate.workbook @@ -2446,7 +2446,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = materialize (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nlet expected_probe_count = toscalar(\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{managedInstanceNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by managed_instance_name, replica_type\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nlet instance_properties = (\\r\\nsqlmi_instance_properties\\r\\n| where sample_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{managedInstanceNameFilter}\\r\\n| summarize arg_max(sample_time_utc, service_tier = case(service_tier =~ \\\"GeneralPurpose\\\", \\\"General Purpose\\\", service_tier =~ \\\"BusinessCritical\\\", \\\"Business Critical\\\", service_tier)) by managed_instance_name, replica_type\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty managed_instance_name. Look it up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{managedInstanceNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by managed_instance_name, replica_type\\r\\n| join kind=leftouter instance_properties on managed_instance_name, replica_type\\r\\n| project managed_instance_name, replica_type, service_tier, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\ncolor = case(\\r\\ntoreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all instances\\r\\ncount_failed_probes > 0, \\\"orange\\\",\\r\\ncount_successful_probes > 0, \\\"green\\\",\\r\\n\\\"\\\"\\r\\n),\\r\\ngrouper = case(\\r\\n\\\"{HeatmapGroupBy}\\\" == \\\"service_tier\\\", service_tier,\\r\\nmanaged_instance_name\\r\\n),\\r\\nreplica_type_indicator = case(\\r\\nreplica_type == \\\"Primary\\\", \\\"🔵\\\",\\r\\nreplica_type == \\\"HA secondary\\\", \\\"🔘\\\",\\r\\n\\\"\\\"\\r\\n)\\r\\n| project managed_instance_name, decorated_managed_instance_name = strcat(replica_type_indicator, tostring(split(managed_instance_name, \\\".\\\")[0])), replica_type, health_ratio, count_failed_probes, color, grouper = iif(\\\"{HeatmapGroupBy}\\\" == \\\"none\\\", \\\"\\\", grouper), top_tooltip = strcat(managed_instance_name, \\\" | \\\", replica_type_indicator, replica_type), ha_secondary = tolower(tostring(replica_type == \\\"HA secondary\\\"))\\r\\n| top {topHitters} by health_ratio asc\\r\\n| sort by health_ratio asc, tolower(grouper) asc, tolower(managed_instance_name) asc, iif(replica_type == \\\"HA secondary\\\", 1, 0) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = materialize (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nlet expected_probe_count = toscalar(\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{managedInstanceNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by managed_instance_name, replica_type\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nlet instance_properties = (\\r\\nsqlmi_instance_properties\\r\\n| where sample_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{managedInstanceNameFilter}\\r\\n| summarize arg_max(sample_time_utc, service_tier = case(service_tier =~ \\\"GeneralPurpose\\\", \\\"General Purpose\\\", service_tier =~ \\\"BusinessCritical\\\", \\\"Business Critical\\\", service_tier)) by managed_instance_name, replica_type\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty managed_instance_name. Look it up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{managedInstanceNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by managed_instance_name, replica_type\\r\\n| join kind=leftouter instance_properties on managed_instance_name, replica_type\\r\\n| project managed_instance_name, replica_type, service_tier, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\ncolor = case(\\r\\ntoreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all instances\\r\\ncount_failed_probes > 0, \\\"orange\\\",\\r\\ncount_successful_probes > 0, \\\"green\\\",\\r\\n\\\"\\\"\\r\\n),\\r\\ngrouper = case(\\r\\n\\\"{HeatmapGroupBy}\\\" == \\\"service_tier\\\", service_tier,\\r\\nmanaged_instance_name\\r\\n),\\r\\nreplica_type_indicator = case(\\r\\nreplica_type == \\\"Primary\\\", \\\"🔵\\\",\\r\\nreplica_type == \\\"HA secondary\\\", \\\"🔘\\\",\\r\\n\\\"\\\"\\r\\n)\\r\\n| project managed_instance_name, decorated_managed_instance_name = strcat(replica_type_indicator, tostring(split(managed_instance_name, \\\".\\\")[0])), replica_type, health_ratio, count_failed_probes, color, grouper = iif(\\\"{HeatmapGroupBy}\\\" == \\\"none\\\", \\\"\\\", grouper), top_tooltip = strcat(managed_instance_name, \\\" | \\\", replica_type_indicator, replica_type), ha_secondary = tolower(tostring(replica_type == \\\"HA secondary\\\"))\\r\\n| top {topHitters} by health_ratio asc\\r\\n| sort by health_ratio asc, tolower(grouper) asc, tolower(managed_instance_name) asc, iif(replica_type == \\\"HA secondary\\\", 1, 0) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "noDataMessage": "There is no data for specified parameters.", diff --git a/Workbooks/Database watcher/Azure SQL Managed Instance/instance/connectivity/connectivity.workbook b/Workbooks/Database watcher/Azure SQL Managed Instance/instance/connectivity/connectivity.workbook index 0f574620a6..25d1755e51 100644 --- a/Workbooks/Database watcher/Azure SQL Managed Instance/instance/connectivity/connectivity.workbook +++ b/Workbooks/Database watcher/Azure SQL Managed Instance/instance/connectivity/connectivity.workbook @@ -86,7 +86,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "aggregation": 3, "title": "Select a sample", @@ -124,7 +124,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "noDataMessage": "No connectivity samples are available", "queryType": 9, @@ -150,7 +150,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityLatestSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -162,7 +162,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityHistoricalSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -223,7 +223,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "noDataMessage": "No sample is selected", "queryType": 9, @@ -289,7 +289,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target instance name\\r\\nlet connection_server_target = (\\r\\nsqlmi_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, managed_instance_name, replica_type) by connection_server_name, connection_application_intent\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqlmi_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name, connection_application_intent // A failed probe has empty instance name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend managed_instance_name = iif(isempty(managed_instance_name), managed_instance_name1, managed_instance_name),\\r\\n replica_type = iif(isempty(replica_type), replica_type1, replica_type)\\r\\n| where managed_instance_name =~ @\\\"{managedInstanceName}\\\"\\r\\n| where ({haReplica} and replica_type == \\\"HA secondary\\\") or (not ({haReplica}) and replica_type != \\\"HA secondary\\\")\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "title": "Connectivity probes", diff --git a/Workbooks/Database watcher/SQL Server/estate/estate.workbook b/Workbooks/Database watcher/SQL Server/estate/estate.workbook index ff51b6383e..9278fe5965 100644 --- a/Workbooks/Database watcher/SQL Server/estate/estate.workbook +++ b/Workbooks/Database watcher/SQL Server/estate/estate.workbook @@ -2336,7 +2336,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = materialize (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// typical count of probes per machine, server in selected time range\\r\\nlet expected_probe_count = toscalar(\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{machineNameFilter}\\r\\n{serverNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by machine_name, server_name\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nlet server_properties = (\\r\\nsqlserver_properties\\r\\n| where sample_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{machineNameFilter}\\r\\n{serverNameFilter}\\r\\n| summarize arg_max(sample_time_utc, cluster_name) by machine_name, server_name\\r\\n);\\r\\nlet agg_connectivity = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{machineNameFilter}\\r\\n{serverNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by machine_name, server_name\\r\\n| join kind=leftouter server_properties on machine_name, server_name\\r\\n| project machine_name, server_name, cluster_name, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\n color = case(\\r\\n toreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all servers\\r\\n count_failed_probes > 0, \\\"orange\\\",\\r\\n count_successful_probes > 0, \\\"green\\\",\\r\\n \\\"\\\"\\r\\n ),\\r\\n grouper = case(\\r\\n \\\"{HeatmapGroupBy}\\\" == \\\"machine\\\", machine_name,\\r\\n \\\"{HeatmapGroupBy}\\\" == \\\"cluster\\\" and isnotempty(cluster_name), cluster_name,\\r\\n \\\"{HeatmapGroupBy}\\\" == \\\"cluster\\\" and isempty(cluster_name), strcat(server_name, \\\" (not clustered)\\\"),\\r\\n server_name\\r\\n )\\r\\n);\\r\\n// Get the max value across servers in each grouper. This is used to limit to top N servers without tearing groups (machines, clusters).\\r\\nlet agg_connectivity_grouper = (\\r\\nagg_connectivity\\r\\n| summarize health_ratio = min(health_ratio) by grouper\\r\\n| sort by health_ratio asc\\r\\n| project grouper, health_ratio, grouper_number = row_number()\\r\\n);\\r\\nagg_connectivity\\r\\n| lookup agg_connectivity_grouper on grouper\\r\\n| where grouper_number <= {topHitters} // limit to top hitters\\r\\n| project machine_name, server_name, cluster_name, health_ratio, grouper_health_ratio = health_ratio1, count_failed_probes, color, grouper = iif(\\\"{HeatmapGroupBy}\\\" == \\\"none\\\", \\\"\\\", grouper)\\r\\n| sort by health_ratio asc, tolower(grouper) asc, tolower(machine_name) asc, tolower(server_name) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = materialize (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// typical count of probes per machine, server in selected time range\\r\\nlet expected_probe_count = toscalar(\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{machineNameFilter}\\r\\n{serverNameFilter}\\r\\n| summarize count_samples = dcount(probe_time_utc) by machine_name, server_name\\r\\n| summarize percentile(count_samples, 90)\\r\\n);\\r\\nlet server_properties = (\\r\\nsqlserver_properties\\r\\n| where sample_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{machineNameFilter}\\r\\n{serverNameFilter}\\r\\n| summarize arg_max(sample_time_utc, cluster_name) by machine_name, server_name\\r\\n);\\r\\nlet agg_connectivity = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n{subscriptionFilter}\\r\\n{resourceGroupFilter}\\r\\n{machineNameFilter}\\r\\n{serverNameFilter}\\r\\n| summarize count_failed_probes = countif(probe_return_value != 1),\\r\\n count_successful_probes = countif(probe_return_value == 1),\\r\\n count_probes = count()\\r\\n by machine_name, server_name\\r\\n| join kind=leftouter server_properties on machine_name, server_name\\r\\n| project machine_name, server_name, cluster_name, health_ratio = iif(toreal(count_probes)/expected_probe_count < 0.5, real(null), toreal(count_successful_probes) / toreal(count_probes)), count_failed_probes = iif(count_failed_probes > 0, count_failed_probes, int(null)),\\r\\n color = case(\\r\\n toreal(count_probes)/expected_probe_count < 0.5, \\\"gray\\\", // show color as grey (unknown) if the number of samples is much less than the representative number across all servers\\r\\n count_failed_probes > 0, \\\"orange\\\",\\r\\n count_successful_probes > 0, \\\"green\\\",\\r\\n \\\"\\\"\\r\\n ),\\r\\n grouper = case(\\r\\n \\\"{HeatmapGroupBy}\\\" == \\\"machine\\\", machine_name,\\r\\n \\\"{HeatmapGroupBy}\\\" == \\\"cluster\\\" and isnotempty(cluster_name), cluster_name,\\r\\n \\\"{HeatmapGroupBy}\\\" == \\\"cluster\\\" and isempty(cluster_name), strcat(server_name, \\\" (not clustered)\\\"),\\r\\n server_name\\r\\n )\\r\\n);\\r\\n// Get the max value across servers in each grouper. This is used to limit to top N servers without tearing groups (machines, clusters).\\r\\nlet agg_connectivity_grouper = (\\r\\nagg_connectivity\\r\\n| summarize health_ratio = min(health_ratio) by grouper\\r\\n| sort by health_ratio asc\\r\\n| project grouper, health_ratio, grouper_number = row_number()\\r\\n);\\r\\nagg_connectivity\\r\\n| lookup agg_connectivity_grouper on grouper\\r\\n| where grouper_number <= {topHitters} // limit to top hitters\\r\\n| project machine_name, server_name, cluster_name, health_ratio, grouper_health_ratio = health_ratio1, count_failed_probes, color, grouper = iif(\\\"{HeatmapGroupBy}\\\" == \\\"none\\\", \\\"\\\", grouper)\\r\\n| sort by health_ratio asc, tolower(grouper) asc, tolower(machine_name) asc, tolower(server_name) asc\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "noDataMessage": "There is no data for specified parameters.", diff --git a/Workbooks/Database watcher/SQL Server/instance/connectivity/connectivity.workbook b/Workbooks/Database watcher/SQL Server/instance/connectivity/connectivity.workbook index c3ef0b06d9..1242312fb8 100644 --- a/Workbooks/Database watcher/SQL Server/instance/connectivity/connectivity.workbook +++ b/Workbooks/Database watcher/SQL Server/instance/connectivity/connectivity.workbook @@ -86,7 +86,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where \\\"{connectivitySampleSubtype}\\\" == \\\"all\\\" or (\\\"{connectivitySampleSubtype}\\\" == \\\"failed\\\" and sample_subtype == \\\"{connectivitySampleSubtype}\\\")\\r\\n| make-series metric = count() default = long(null) on probe_time_utc from {timeRange:start} to {timeRange:end} step {timeRange:grain}/{grainFactor}*2 by sample_subtype\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "aggregation": 3, "title": "Select a sample", @@ -124,7 +124,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between ({timeRange:start} .. {timeRange:end})\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| summarize count_successful_samples = countif(sample_subtype == \\\"successful\\\"),\\r\\n count_failed_samples = countif(sample_subtype == \\\"failed\\\")\\r\\n| project strcat(\\\"There are `\\\", count_successful_samples, \\\"` successful and `\\\", count_failed_samples, \\\"` failed connectivity probe(s) in the selected time range. Each vertical bar stands for a group of probes. Bar height is the total number of probes in a group. Select a bar to view one probe from that group, and its preceding and following probes. Zoom in to see smaller groups, down to individual probes.\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "noDataMessage": "No connectivity samples are available", "queryType": 9, @@ -150,7 +150,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityLatestSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:start} - 1h), {timeRange:start})\\r\\n ..\\r\\n iif(({timeRange:end} - {timeRange:start}) <= 1h, ({timeRange:end} + 1h), {timeRange:end})\\r\\n ) // Expand the range if selected range is shorter than the least frequent collection interval (1h)\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| summarize probe_time_utc = max(probe_time_utc)\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -162,7 +162,7 @@ "version": "KqlParameterItem/1.0", "name": "connectivityHistoricalSampleTime", "type": 1, - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Selected time from the history chart is a binned time generated by make-series and is unlikely to match an actual sample.\\r\\n// Look up an actual sample within the sample group selected on the history chart, differentiating between samples in different series.\\r\\n// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") .. (todatetime(\\\"{connectivityHistoricalSample:$.x}\\\") + {timeRange:grain}))\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| extend sample_subtype = iif(probe_return_value != 1, \\\"failed\\\", \\\"successful\\\")\\r\\n| where sample_subtype == \\\"{connectivityHistoricalSample:$.series}\\\"\\r\\n| summarize probe_time_utc = min(probe_time_utc) // Selecting any sample within a sample group is valid. Use the earliest for determinism.\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "isHiddenWhenLocked": true, "timeContext": { "durationMs": 86400000 @@ -223,7 +223,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc == todatetime(\\\"{connectivitySampleTime}\\\")\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| project sample_time = probe_time_utc, probe_time_utc, probe_age = format_timespan(now() - probe_time_utc, \\\"d.hh:mm:ss\\\")\\r\\n\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 4, "noDataMessage": "No sample is selected", "queryType": 9, @@ -289,7 +289,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start} - 1h) .. ({timeRange:end} + 1h))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", + "query": "{\"version\":\"AzureDataExplorerQuery/1.0\",\"queryText\":\"// Map connection server name to target server/machine name\\r\\nlet connection_server_target = (\\r\\nsqlserver_connectivity\\r\\n| extend time_padding = 5 * ({timeRange:end} - {timeRange:start})\\r\\n| where probe_time_utc between (({timeRange:start} - time_padding) .. ({timeRange:end} + time_padding))\\r\\n| where probe_return_value == 1\\r\\n| summarize arg_max(probe_time_utc, server_name, machine_name) by connection_server_name\\r\\n| project-away probe_time_utc\\r\\n);\\r\\n// Get the latest successful probe before the current probe, and the earliest successful probe after the current probe\\r\\n// For a failed probe, these will be the last successful probe before outage and first successful probe after outage\\r\\n// For a successful probe, these will be the immediately preceding and immediately following probes\\r\\nlet range_bounds = toscalar(\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc between (({timeRange:start}) .. ({timeRange:end}))\\r\\n| lookup connection_server_target on connection_server_name\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| summarize left_bound_probe_time_utc = maxif(probe_time_utc, probe_time_utc < todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1),\\r\\n right_bound_probe_time_utc = minif(probe_time_utc, probe_time_utc > todatetime(\\\"{connectivitySampleTime}\\\") and probe_return_value == 1)\\r\\n| extend bound_probe_times = pack_array(left_bound_probe_time_utc, right_bound_probe_time_utc)\\r\\n| project-away left_bound_probe_time_utc, right_bound_probe_time_utc\\r\\n);\\r\\nsqlserver_connectivity\\r\\n| where probe_time_utc in (todatetime(\\\"{connectivitySampleTime}\\\"), range_bounds[0], range_bounds[1]) // The number of returned rows may be less than 3 if left/right bound probes fall outside selected time range\\r\\n| lookup connection_server_target on connection_server_name // A failed probe has empty machine_name/server_name. Look them up for the most recent successful probe with the same connection server name.\\r\\n| extend machine_name = iif(isempty(machine_name), machine_name1, machine_name),\\r\\n server_name = iif(isempty(server_name), server_name1, server_name)\\r\\n| where machine_name =~ @\\\"{machineName}\\\"\\r\\n| where server_name =~ @\\\"{serverName}\\\"\\r\\n| order by probe_time_utc asc\\r\\n| project probe_time_utc,\\r\\n probe_age = format_timespan(probe_time_utc - todatetime(\\\"{connectivitySampleTime}\\\"), \\\"d.hh:mm:ss\\\"),\\r\\n probe_return_value,\\r\\n error_number,\\r\\n error_message,\\r\\n error_state,\\r\\n connection_server_name,\\r\\n connection_database_name,\\r\\n connection_application_intent,\\r\\n connection_timeout_seconds,\\r\\n execution_timeout_seconds,\\r\\n client_connection_id\\r\\n;\",\"clusterName\":\"{adxClusterUri}\",\"databaseName\":\"{adxDatabase}\"}", "size": 3, "showAnalytics": true, "title": "Connectivity probes",