From 90e56aeaf741338eae669129035b5155b5a09652 Mon Sep 17 00:00:00 2001 From: JosephPilov-MSFT <23519517+PiJoCoder@users.noreply.github.com> Date: Thu, 1 May 2025 18:13:20 -0500 Subject: [PATCH 1/2] Release v6.25.04.25 --- .../Bin/CleanupIncompleteShutdown.ps1 | 35 +- SQL LogScout/Bin/CommonFunctions.psm1 | 350 +- SQL LogScout/Bin/CustomImportModule.psm1 | 67 + SQL LogScout/Bin/GUIHandler.psm1 | 8 +- SQL LogScout/Bin/InstanceDiscovery.psm1 | 22 +- SQL LogScout/Bin/LoggingFacility.psm1 | 13 +- SQL LogScout/Bin/README.md | 469 +- SQL LogScout/Bin/Readme.htm | 732 ++- SQL LogScout/Bin/SQLDumpHelper.ps1 | 2 +- SQL LogScout/Bin/SQLLogScoutPs.ps1 | 90 +- SQL LogScout/Bin/SQLLogScoutPs.psm1 | 1052 +++- SQL LogScout/Bin/SQLScript_MSDiagProcs.psm1 | 4659 ----------------- SQL LogScout/Bin/SQLScript_MiscDiagInfo.psm1 | 378 ++ .../SQLScript_NeverEndingQuery_perfstats.psm1 | 190 +- .../SQLScript_Repl_Metadata_Collector.psm1 | 12 +- .../Bin/SQLScript_SQL_Server_Mem_Stats.psm1 | 158 +- .../Bin/SQLScript_SQL_Server_PerfStats.psm1 | 179 +- ...LScript_SQL_Server_PerfStats_Snapshot.psm1 | 8 +- .../Bin/SQLScript_SSB_DbMail_Diag.psm1 | 8 +- .../SQLScript_TempDB_and_Tran_Analysis.psm1 | 990 ++-- .../Bin/SQLScript_xevent_detailed.psm1 | 42 +- .../Bin/ScheduleSQLLogScoutAsTask.ps1 | 8 +- SQL LogScout/Bin/SqlVersionsTable.psm1 | 10 + .../ConsistentQualityTests.ps1 | 109 +- .../FilecountandtypeValidation.ps1 | 35 +- .../TestingInfrastructure/Scenarios_Test.ps1 | 43 +- .../azuredevops-pipelines.yml | 29 +- .../sqlnexus_tablecheck_proc.sql | 18 +- SQL LogScout/SQL_LogScout.ps1 | 11 +- 29 files changed, 3545 insertions(+), 6182 deletions(-) create mode 100644 SQL LogScout/Bin/CustomImportModule.psm1 delete mode 100644 SQL LogScout/Bin/SQLScript_MSDiagProcs.psm1 diff --git a/SQL LogScout/Bin/CleanupIncompleteShutdown.ps1 b/SQL LogScout/Bin/CleanupIncompleteShutdown.ps1 index ce1fa35..d1e3e53 100644 --- a/SQL LogScout/Bin/CleanupIncompleteShutdown.ps1 +++ b/SQL LogScout/Bin/CleanupIncompleteShutdown.ps1 @@ -47,7 +47,7 @@ function HandleCatchBlockCleanup ([string] $function_name, [System.Management.Au function Initialize-CleanupIncompleteShutdownTaskLog ( - [string]$LogFilePath = $env:TEMP, + [string]$LogFilePath, [string]$LogFileName = "##SQLLogScout_CleanupIncompleteShutdown" ) { @@ -59,11 +59,15 @@ function Initialize-CleanupIncompleteShutdownTaskLog #> try { + #Create log file in temp directory using full path. The temp var can come back as 8.3 format and so ensure we have the full path. + $shortEnvTempPath = $env:TEMP + $LogFilePath = (Get-Item $shortEnvTempPath).FullName + #Cache LogFileName without date so we can delete old records properly $LogFileNameStringToDelete = $LogFileName #update file with date - $LogFileName = ($LogFileName -replace "$LogFileName", ($LogFileName+"_" + @(Get-Date -Format "yyyyMMddTHHmmssffff") + ".log")) + $LogFileName = $LogFileName + "_" + (Get-Date -Format "yyyyMMddTHHmmssffff") + ".log" $global:CleanupIncompleteShutdownLog = $LogFilePath + '\' + $LogFileName New-Item -ItemType "file" -Path $global:CleanupIncompleteShutdownLog -Force | Out-Null Write-Host "Created log file $global:CleanupIncompleteShutdownLog" @@ -205,7 +209,7 @@ Log-CleanupIncompleteShutdownTask "============================================= if ([string]::IsNullOrWhiteSpace($ServerName)) { - Select-SQLServerForDiagnostics + Select-SQLServerForDiagnostics | Out-Null } else { @@ -219,7 +223,7 @@ $xevent_alwayson_session = "SQLLogScout_AlwaysOn_Data_Movement" try { - Log-CleanupIncompleteShutdownTask "Testing connection into: '$global:sql_instance_conn_str'. If connection fails, verify instance name." -WriteToConsole $true + Log-CleanupIncompleteShutdownTask "Testing connection into: '$global:sql_instance_conn_str'. If connection fails, verify instance name or running status." -WriteToConsole $true $ConnectionResult = Test-SQLConnection ($global:sql_instance_conn_str) if ($ConnectionResult -eq $false) @@ -282,18 +286,12 @@ try Start-Process -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden #stop perf Xevent - Log-CleanupIncompleteShutdownTask "Executing 'Stop_SQLLogScout_Xevent' session. It will stop the SQLLogScout performance Xevent trace in case it was found to be running..." -WriteToConsole $true - $query = "IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 BEGIN ALTER EVENT SESSION [$xevent_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_session] ON SERVER; END" - $executable = "sqlcmd.exe" - $argument_list = "-S" + $server + " -E -w8000 -Q`"" + $query + "`"" - Start-Process -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden + Log-CleanupIncompleteShutdownTask "Executing 'Stop_$xevent_session' session. It will stop the SQLLogScout performance Xevent trace in case it was found to be running..." -WriteToConsole $true - - $query = "IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 BEGIN ALTER EVENT SESSION [$xevent_alwayson_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_alwayson_session] ON SERVER; END" + $query = "IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 BEGIN ALTER EVENT SESSION [$xevent_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_session] ON SERVER; END" $executable = "sqlcmd.exe" - $argument_list = "-S" + $server + " -E -w8000 -Q`"" + $query + "`"" + $argument_list = "-S" + $global:sql_instance_conn_str + " -E -w8000 -Q`"" + $query + "`"" Start-Process -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden - $xevent_session = "xevent_SQLLogScout" $query = "ALTER EVENT SESSION [$xevent_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_session] ON SERVER;" @@ -302,9 +300,14 @@ try Start-Process -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden #stop always on data movement Xevent - Log-CleanupIncompleteShutdownTask "Executing 'Stop_SQLLogScout_AlwaysOn_Data_Movement'. It will stop the SQLLogScout AlwaysOn Xevent trace in case it was found to be running..." -WriteToConsole $true - $xevent_session = "SQLLogScout_AlwaysOn_Data_Movement" - $query = "ALTER EVENT SESSION [$xevent_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_session] ON SERVER;" + Log-CleanupIncompleteShutdownTask "Executing 'Stop_$xevent_alwayson_session'. It will stop the SQLLogScout AlwaysOn Xevent trace in case it was found to be running..." -WriteToConsole $true + + $query = "IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 BEGIN ALTER EVENT SESSION [$xevent_alwayson_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_alwayson_session] ON SERVER; END" + $executable = "sqlcmd.exe" + $argument_list = "-S" + $global:sql_instance_conn_str + " -E -w8000 -Q`"" + $query + "`"" + Start-Process -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden + + $query = "ALTER EVENT SESSION [$xevent_alwayson_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$xevent_alwayson_session] ON SERVER;" $executable = "sqlcmd.exe" $argument_list ="-S" + $global:sql_instance_conn_str + " -E -w8000 -Q`""+ $query + "`" " Start-Process -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden diff --git a/SQL LogScout/Bin/CommonFunctions.psm1 b/SQL LogScout/Bin/CommonFunctions.psm1 index 5239e86..a740fe8 100644 --- a/SQL LogScout/Bin/CommonFunctions.psm1 +++ b/SQL LogScout/Bin/CommonFunctions.psm1 @@ -28,6 +28,7 @@ function InitCriticalDirectories() } Set-OutputPath Set-InternalPath + Set-StopFilePath } catch { @@ -80,7 +81,7 @@ function Set-OutputPath() } elseif ($global:custom_user_directory -eq "PromptForCustomDir" -And !$global:gui_mode) { - $userlogfolder = Read-Host "Would your like the logs to be collected on a non-default drive and directory?" -CustomLogMessage "Prompt CustomDir Console Input:" + $userlogfolder = Read-Host "Would you like the logs to be collected on a non-default drive and directory?" -CustomLogMessage "Prompt CustomDir Console Input:" $HelpMessage = "Please enter a valid input (Y or N)" $ValidInput = "Y","N" @@ -162,6 +163,20 @@ function Set-InternalPath() } } +function Set-StopFilePath() +{ + Write-LogDebug "inside" $MyInvocation.MyCommand + try + { + #set the stop file path to the \internal folder + $global:stopFilePath = ($global:internal_output_folder + "logscout.stop") + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + } +} + function CreatePartialOutputFilename ([string]$server) { Write-LogDebug "inside" $MyInvocation.MyCommand @@ -283,7 +298,8 @@ function ReuseOrRecreateOutputFolder() if (Test-Path -Path $global:output_folder) { Remove-Item -Path $global:output_folder -Force -Recurse | Out-Null - Write-LogWarning "Deleted $global:output_folder and its contents" + Write-LogInformation "Deleting '$global:output_folder' and its contents. Please wait..." + Write-LogWarning "Deleted '$global:output_folder' folder and its contents" } } elseif ($DeleteOrNew -eq "N") @@ -715,7 +731,7 @@ function getSQLConnectionString ([Boolean] $SkipStatusCheck = $false, [int] $try { if ( - ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) -or + ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) -or ($true -eq $global:instance_independent_collection ) -or ( ("Running" -ne $global:sql_instance_service_status) -and (-$false -eq $SkipStatusCheck) ) ) @@ -757,7 +773,11 @@ function getSQLConnectionString ([Boolean] $SkipStatusCheck = $false, [int] $try $connectionStringBuilder["TrustServerCertificate"] = "Yes" } else { + + #only for the classic SQL Server driver use no encryption as it doesn't support it in all OS versions. But also convenient for WID connections $connectionStringBuilder["Integrated Security"] = "True" + $global:is_connection_encrypted = $false + Write-LogWarning ("*"*70) Write-LogWarning "* SQL LogScout is switching to the classic SQL Server ODBC driver." Write-LogWarning "* Thus, this local connection is unencrypted to ensure it is successful" @@ -1002,6 +1022,8 @@ function GetSQLCmdPath() try { + [string] $sqlcmd_executable = "" + # use the global sqlcmdpath variable if it isn't empty. The Test-Path validation will be done just once for perf reasons. # If empty, populate by finding the path to sqlcmd.exe with highest version if (([string]::IsNullOrWhiteSpace($global:sqlcmdPath) -eq $false) -and ($global:sqlcmdPath -match "sqlcmd.exe")) @@ -1010,7 +1032,8 @@ function GetSQLCmdPath() } else { - #if no path to sqlcmd, find the highest version of sqlcmd.exe on the sytem (assuming C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\... most common case) + #if no path to sqlcmd, find the highest version of sqlcmd.exe on the system + # first start by trying the common case C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\... $sqlcmd_fullpath = (Get-ChildItem "C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\*\Tools\Binn\SQLCMD.EXE" -ErrorAction SilentlyContinue| Sort-Object -Property FullName -Descending | Select-Object -First 1 -Property FullName).FullName @@ -1019,11 +1042,11 @@ function GetSQLCmdPath() if (([string]::IsNullOrWhiteSpace($sqlcmd_fullpath) -eq $false) -and (Test-Path -Path $sqlcmd_fullpath)) { $sqlcmd_executable = $global:sqlcmdPath = $sqlcmd_fullpath - Write-LogDebug "SQLCMD path assigned to global variable: '$global:sqlcmdPath'" -DebugLogLevel 2 + Write-LogDebug "SQLCMD path found in common location and assigned to global variable is '$global:sqlcmdPath'" -DebugLogLevel 2 } else { - #if no path found, try to get the path from the registry and append the executable name + #if no path found thus far, second choice is to get the path from the registry and append the executable name # Get the ODBCToolsPath values from the registry $paths = (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\*\Tools\ClientSetup\" -Name "ODBCToolsPath" -ErrorAction SilentlyContinue).ODBCToolsPath @@ -1049,12 +1072,39 @@ function GetSQLCmdPath() if (([string]::IsNullOrWhiteSpace($sqlcmd_path_reg) -eq $false) -and (Test-Path -Path $sqlcmd_path_reg)) { $sqlcmd_executable = $global:sqlcmdPath = $sqlcmd_path_reg - Write-LogDebug "SQLCMD path discovered in registry assigned to global variable : '$global:sqlcmdPath'" -DebugLogLevel 2 + Write-LogDebug "SQLCMD.EXE path discovered in registry and assigned to global variable is '$global:sqlcmdPath'" -DebugLogLevel 2 } else { - #last resort, just use the executable name without the path, and let the system find it if at all present - $sqlcmd_executable = "sqlcmd.exe" + #if no path found thus far, third choice is to look in the Environment variable PATH and pick one if found (last one seems the highest version typically) + $sqlcmd_path_env = ((Get-Command -Name "sqlcmd.exe" -CommandType Application -ErrorAction SilentlyContinue) | Select-Object -Last 1) + + #if path is valid, assign to global variable and local return variable + # else log an error and continue without T-SQL collections + if (($sqlcmd_path_env).Name -match "sqlcmd") + { + + if ( ([string]::IsNullOrWhiteSpace(($sqlcmd_path_env.Source)) -eq $false) -and (Test-Path -Path ($sqlcmd_path_env.Source) )) + { + $sqlcmd_executable = $global:sqlcmdPath = $sqlcmd_path_env.Source + Write-LogDebug "SQLCMD.EXE path discovered in environment variable PATH and assigned to global variable is '$global:sqlcmdPath'" -DebugLogLevel 2 + + } + # in older version like SQL 2012, the registry key ODBCToolsPath is not present AND the Get-Command.Source property is not populated, so hard-codiing the sqlcmd.exe directly + else + { + $sqlcmd_executable = "sqlcmd.exe" + Write-LogDebug "SQLCMD.EXE discovered in environment variable PATH, but it's an older version so assigned executable directly: '$sqlcmd_executable'" -DebugLogLevel 2 + } + + } + else + { + $sqlcmd_executable = $null + Write-LogError "SQLCMD.EXE not found. Continuing without T-SQL script execution." + Write-LogInformation "To enable T-SQL collections, install SQLCMD (ODBC) from your installation media or download from Microsoft." + } + } } } @@ -1086,13 +1136,31 @@ function Start-SQLCmdProcess([string]$collector_name, [string]$input_script_name $collector_name = "blank_collector_name" } + + Write-LogInformation "Executing Collector: $collector_name" + + #get the path to the input script $input_script = BuildInputScript $global:present_directory $input_script_name #get the path to sqlcmd.exe $executable = GetSQLCmdPath + if ([string]::IsNullOrWhiteSpace($executable)) + { + #if we can't find sqlcmd.exe, we can't execute the script so just return + return + } + #command arguments for sqlcmd; server connection, trusted connection, Hostname, wide output, and encryption negotiation - $argument_list = "-S" + $server + " -E -Hsqllogscout -w8000 -C -N" + $argument_list = "-S" + $server + " -E -Hsqllogscout -w8000" + + #if we connected with unencrypted connection earlier with the SQL Server driver, remove -C -N from the command line + #otherwise, default to using encrypted connection with the ODBC driver + if ($global:is_connection_encrypted -eq $true) + { + $argument_list += " -C -N" + } + #if secondary replica has read-intent, we add -KReadOnly to avoid failures on those secondaries if ($global:is_secondary_read_intent_only -eq $true) @@ -1145,7 +1213,7 @@ function Start-SQLCmdProcess([string]$collector_name, [string]$input_script_name $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name ($collector_name+"_stderr") -needExtraQuotes $false $stdoutput_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name ($collector_name+"_stdout") -needExtraQuotes $false - Write-LogInformation "Executing Collector: $collector_name" + #start the process StartNewProcess -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden -RedirectStandardError $error_file -RedirectStandardOutput $stdoutput_file -Wait $wait_sync | Out-Null } @@ -1180,6 +1248,28 @@ function isHADREnabled() return $false +} +function IsSqlFCI() +{ + Write-LogDebug "Inside" $MyInvocation.MyCommand + + $propertiesList = $global:SQLSERVERPROPERTYTBL + + if (!$propertiesList) { + #We didn't receive server properteis + Write-LogError " getServerproperty returned no results " + return $false + } + + $isSqlFci = $propertiesList."IsClustered" + + if ($isSqlFci -eq "1") { + Write-LogDebug "SQL Server is FCI on this system" -DebugLogLevel 2 + return $true + } + + return $false + } #check if cluster - based on cluster service status and cluster registry key @@ -1448,10 +1538,6 @@ Function GetRegistryKeys [int]$CurrentPSMajorVer = ($PSVersionTable.PSVersion).Major - # This variable is used to hold the PowerShell Major version for calling the appropriate cmdlet that is compatible with the PS Version - [int]$CurrentPSMajorVer = ($PSVersionTable.PSVersion).Major - - # for each nested key perform an iteration to get all the properties for writing to the output file foreach ($k in $keys) { @@ -1655,6 +1741,7 @@ function GetLogPathFromReg([string]$server, [string]$logType) try { $vInstance = "" + $vInstanceType = "" $vRegInst = "" $RegPathParams = "" $retLogPath = "" @@ -1662,21 +1749,29 @@ function GetLogPathFromReg([string]$server, [string]$logType) # extract the instance name from the server name - $instByPort = GetSQLInstanceNameByPortNo($server) - Write-LogDebug "Result from GetSQLInstanceNameByPortNo is '$instByPort'" -DebugLogLevel 2 + $instByPortObj = GetSQLInstanceNameByPortNo($server) + Write-LogDebug "Result from GetSQLInstanceNameByPortNo is '$instByPortObj'" -DebugLogLevel 2 - if ($true -ne [String]::IsNullOrWhiteSpace($instByPort)) + if (-not ([String]::IsNullOrWhiteSpace($instByPortObj.InstanceName))) { - $vInstance = $instByPort + $vInstance = $instByPortObj.InstanceName + $vInstanceType = $instByPortObj.Type } else { # get the instance name from the server name (registry stores MSSQLSERVER if default instance) $vInstanceObj = Get-InstanceNameObject($server) $vInstance = $vInstanceObj.InstanceName + $vInstanceType = $vInstanceObj.Type } - Write-LogDebug "Instance name is $vInstance" -DebugLogLevel 2 + # if the instance name is default instance on an FCI, we need to set it to the MSSQLSERVER because the registry stores it that way + if ($vInstanceType -eq $global:SQLInstanceType["DefaultInstanceVNN"]) + { + $vInstance = "MSSQLSERVER" + } + + Write-LogDebug "Instance name for the purpose of reg key lookup is '$vInstance'" -DebugLogLevel 2 # make sure a Instance Names is a valid registry key (could be missing if SQL Server is not installed or registry is corrupt) if (Test-Path -Path $regInstNames) @@ -1692,49 +1787,130 @@ function GetLogPathFromReg([string]$server, [string]$logType) # validate the registry value with the instance name appended to the end # for example, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL\SQL2017 - if ([String]::IsNullOrWhiteSpace($vRegInst) -eq $true) + # special case for WID + if (([String]::IsNullOrWhiteSpace($vRegInst) -eq $true) -and ($vInstance -ne "MSWIN8.SQLWID")) { Write-LogDebug "Registry value vRegInst is null or empty. Not getting files from Log directory" -DebugLogLevel 2 return $false } else { + #special case for WID + # if the server name (alias) to connect to is "MSWIN8.SQLWID", then hard-code the $vRegInst to "MSWIN8.SQLWID" + if ($vInstance -eq "MSWIN8.SQLWID") + { + $vRegInst = "MSWIN8.SQLWID" + Write-LogDebug "It appears this is WID, assigning vRegInst to '$vRegInst'" -DebugLogLevel 2 + } + # get the SQL Server registry key + instance name - $RegPathParams = "HKLM:SOFTWARE\Microsoft\Microsoft SQL Server\" + $vRegInst + $RegPathInstance = "HKLM:SOFTWARE\Microsoft\Microsoft SQL Server\" + $vRegInst - switch ($logType) + + # go after the startup params registry key + $RegPathParams = $RegPathInstance + "\MSSQLSERVER\Parameters" + + if (Test-Path -Path $RegPathParams) { - {($_ -eq "ERRORLOG") -or ($_ -eq "POLYBASELOG")} + Write-LogDebug "Registry RegPathParams='$RegPathParams' is valid. Getting SQLArg keys" -DebugLogLevel 2 + + # Get all the SQLArg keys + $keys = Get-ItemProperty -Path $RegPathParams | Select-Object -Property SQLArg* + + # Initialize the errorLogPath and data path variables + $errorLogPath = $null + $DataFilesPath = $null + + # Loop through the keys to find the one containing "-e" + foreach ($key in $keys.PSObject.Properties) { - # go after the startup params registry key - $RegPathParams += "\MSSQLServer\Parameters" - - # validate key to get the path to the ERRORLOG - if (Test-Path -Path $RegPathParams) + #find the error log path and store it in the errorLogPath variable + if ($key.Value -like "-e*") { - # strip the -e from the beginning of the string - $retLogPath = (Get-ItemProperty -Path $RegPathParams).SQLArg1 -replace "^-e", "" - - # strip the word ERRORLOG from the end of the string - $retLogPath = Split-Path $retLogPath -Parent + $errorLogPath = $key.Value + + } - if ($logType -eq "POLYBASELOG") - { - # append the PolyBase folder name to the end of the path - $retLogPath = $retLogPath + "\PolyBase\" - } + #find the data files path and store it in the DataFilesPath variable + if ($key.Value -like "-d*") + { + $DataFilesPath = $key.Value } - else + + } + + Write-LogDebug "Registry - Error log path: '$errorLogPath'. Data files path found: '$DataFilesPath'" -DebugLogLevel 3 + + # validate key to get the path to the ERRORLOG and strip the -e from the beginning of the string + if ([string]::IsNullOrWhiteSpace($errorLogPath) -eq $false) + { + Write-LogDebug "Error log path found: $errorLogPath" -DebugLogLevel 3 + + # strip the -e from the beginning of the string + $errorLogPath = $errorLogPath -replace "^-e", "" + } + else + { + Write-LogDebug "No error log path found in the registry with '-e'. How does SQL Server even start?" -DebugLogLevel 3 + return $false + } + + + #validate key to the data files path and strip the -d from the beginning of the string + if ([string]::IsNullOrWhiteSpace($DataFilesPath) -eq $false) + { + Write-LogDebug "Data files path found: $DataFilesPath" -DebugLogLevel 3 + + # strip the -d from the beginning of the string + $DataFilesPath = $DataFilesPath -replace "^-d", "" + } + else + { + Write-LogDebug "No data files path found in the registry with '-d'. How does SQL Server even start?" -DebugLogLevel 3 + return $false + } + + } + else + { + Write-LogDebug "Registry RegPathParams='$RegPathParams' is not valid or doesn't exist" -DebugLogLevel 2 + return $false + } + + + switch ($logType) + { + "ERRORLOG" + { + # just return the full path with log file name + # the file name will be extracted by the caller + + $retLogPath = $errorLogPath + + } + "FDLAUNCHERRORLOG" + { + # strip the master.mdf from the end of the string and then the \DATA (or whatever name) folder from the end of the string + $retLogPath = $DataFilesPath | Split-Path -Parent | Split-Path -Parent + $retLogPath = $retLogPath + "\Log\" + } + {($_ -eq "LOG") -or ($_ -eq "POLYBASELOG") -or ($_ -eq "SQLFTLOG")} + { + + # strip the word ERRORLOG (or whatever name is stored) from the end of the string + $retLogPath = Split-Path $errorLogPath -Parent + + if ($logType -eq "POLYBASELOG") { - Write-LogDebug "Registry RegPathParams='$RegPathParams' is not valid or doesn't exist" -DebugLogLevel 2 - return $false + # append the PolyBase folder name to the end of the path + $retLogPath = $retLogPath + "\PolyBase\" } } "DUMPLOG" { # go after the dump configured registry key # HKLM:SOFTWARE\Microsoft\Microsoft SQL Server\vRegInst\CPE - $vRegDmpPath = $RegPathParams + "\CPE" + $vRegDmpPath = $RegPathInstance + "\CPE" if (Test-Path -Path $vRegDmpPath) { @@ -1743,8 +1919,11 @@ function GetLogPathFromReg([string]$server, [string]$logType) } else { - Write-LogDebug "Registry RegDmpPath='$vRegDmpPath' is not valid or doesn't exist" -DebugLogLevel 2 - return $false + # if the \CPE reg key doesn't exist, then memory dumps are stored in the \LOG folder in SQL Server + Write-LogDebug "Registry RegDmpPath='$vRegDmpPath' is not valid or doesn't exist. Defaulting to \LOG folder" -DebugLogLevel 2 + + # default to the \LOG folder by removing the ERORLOG file name from the path + $retLogPath = Split-Path $errorLogPath -Parent } } Default @@ -1756,7 +1935,7 @@ function GetLogPathFromReg([string]$server, [string]$logType) } # make sure the path to the log directory is valid - if (Test-Path -Path $retLogPath -PathType Container) + if (Test-Path -Path $retLogPath) { Write-LogDebug "Log path is $retLogPath" -DebugLogLevel 2 } @@ -1829,4 +2008,81 @@ function ParseRelativeTime ([string]$relativeTime, [datetime]$baseDateTime) HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem return } -} \ No newline at end of file +} + +function GetTotalRAMSize() +{ + try + { + Write-LogDebug "inside" $MyInvocation.MyCommand + + # get the total physical memory in GB + $TotalRAM = (Get-CimInstance -ClassName CIM_ComputerSystem).TotalPhysicalMemory / 1GB + Write-LogDebug "Total RAM: $($TotalRAM.ToString("F2")) GB" -DebugLogLevel 2 + return $TotalRAM + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + return 0 + } +} + +function GetCoutLogicalCPUs() +{ + try + { + Write-LogDebug "inside" $MyInvocation.MyCommand + + # get the count of logical CPUs + $NumLogicalCPUs = (Get-CimInstance -ClassName Win32_Processor | Select-Object -Property NumberOfLogicalProcessors).NumberOfLogicalProcessors + Write-LogDebug "Number of logical CPUs: $NumLogicalCPUs" -DebugLogLevel 2 + return $NumLogicalCPUs + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + return 0 + } +} + +function GetComputerPlatform +{ + Write-LogDebug "inside" $MyInvocation.MyCommand + + try { + # Determine if the OS is 64-bit + $is64BitOS = [System.Environment]::Is64BitOperatingSystem + + # Get the processor architecture from the environment variable + $processorArchitecture = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" -Name "PROCESSOR_ARCHITECTURE").PROCESSOR_ARCHITECTURE + + # Map the processor architecture to a human-readable platform + switch ($processorArchitecture) { + "AMD64" { + if ($is64BitOS) { + return "x64" #AMD64 + } else { + return "WOW64" #x86 on x64 + } + } + "x86" { + return "x86" + } + "ARM64" { + return "ARM64" + } + "IA64" { + return "Itanium (IA-64)" + } + default { + return "Unknown platform: $processorArchitecture" + } + } + } + catch { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + return $null + } +} + diff --git a/SQL LogScout/Bin/CustomImportModule.psm1 b/SQL LogScout/Bin/CustomImportModule.psm1 new file mode 100644 index 0000000..d44ec8b --- /dev/null +++ b/SQL LogScout/Bin/CustomImportModule.psm1 @@ -0,0 +1,67 @@ +<# + This function will confirm if a module is imported in the system or not, it will help prevent + repeat loading of modules and provide extra logging in debug log. +#> +function confirm-ModuleLoaded ([String] $moduleName, [String] $fullFileName) +{ + Write-LogDebug "Inside" $MyInvocation.MyCommand + + # if user passed fullFileName (e.g. c:\foldr\ModuleName.psm1) then we need to extract the module name + # to be able to use PS Get-Module + if ([String]::IsNullOrEmpty -ne $fullFileName) + { + $moduleName = (Split-Path $fullFileName -Leaf) -replace '\.[^.]+$', '' + Write-LogDebug "Module Name extracted from file : $moduleName" + } + + $module = Get-Module -Name $moduleName + + #confirm returned module object has the module name we are looking for + if ($module -and $module.Name -eq $moduleName) + { + Write-LogDebug "module $($module.Name) is imported before" + return $true + } + Write-LogDebug "Module `"$moduleName`" is not imported in the system yet" + + return $false +} + +<# +This function will replace the standard Import-Module cmdlet in powershell +it is meant to provide more logging in debug log to help identify if a particulare module fails to load +At the time of writing this function quarantined files by Anti-Virus was the main cause of such issue +#> +function Import-Module { + param ( + [Parameter(Mandatory=$true)] + [string]$Name, + [Parameter()] + [switch]$Force, + [Parameter()] + [switch]$DisableNameChecking, + [Parameter()] + [switch] $Global + ) + Write-LogDebug "Inside" $MyInvocation.MyCommand + + Write-LogDebug "Import-Module : $Name" + + #if module is loaded or user used force switch (which will prevent check for loaded module) we perform import-module + if ($Force -or $false -eq $(confirm-ModuleLoaded -fullFileName $Name) ) + { + # Call the original Import-Module cmdlet, we default to force, disableNamechecking to avoid issues with some modules + # Global is needed to make the import work for all modules imported and called subsequently. + + $m = Microsoft.PowerShell.Core\Import-Module -Name $Name -Force -DisableNameChecking -Global -PassThru -ErrorVariable ErrorMessage + + #check returned -PassThru value to make sure successful import happeend + if ($m) { + Write-LogDebug "Module `"$Name`" is imported successfully" + } else { + Write-LogDebug "Module `"$Name`" Failed import, error : $ErrorMessage" + } + } else { + Write-LogDebug "Module `"$Name`" already loaded, no action performed" + } +} diff --git a/SQL LogScout/Bin/GUIHandler.psm1 b/SQL LogScout/Bin/GUIHandler.psm1 index e0ebdcd..d9f31f5 100644 --- a/SQL LogScout/Bin/GUIHandler.psm1 +++ b/SQL LogScout/Bin/GUIHandler.psm1 @@ -630,9 +630,9 @@ function BuildXEventsModel_detailed() { Write-LogDebug "inside" $MyInvocation.MyCommand $xevent_string = New-Object -TypeName System.Text.StringBuilder $GenericModelobj = New-Object GenericModel - $content = xevent_General_Query -returnVariable $true + $content = xevent_detailed_Query -returnVariable $true - foreach ($element in $content <#Get-Content .\xevent_detailed.sql#>) { + foreach ($element in $content) { if ($element.Trim() -eq "GO") { $GenericModelobj.Value = $xevent_string $GenericModelobj.State = $true @@ -671,7 +671,7 @@ function BuildXEventsModel_AlwaysOn() { $xevent_string = New-Object -TypeName System.Text.StringBuilder $GenericModelobj = New-Object GenericModel $content = xevent_AlwaysOn_Data_Movement_Query -returnVariable $true - foreach ($element in $content <#Get-Content .\xevent_AlwaysOn_Data_Movement.sql#>) { + foreach ($element in $content ) { if ($element.Trim() -eq "GO") { $GenericModelobj.Value = $xevent_string $GenericModelobj.State = $true @@ -711,7 +711,7 @@ function BuildXEventsModel_servicebroker_dbmail() { $GenericModelobj = New-Object GenericModel $content = xevent_servicebroker_dbmail_Query -returnVariable $true - foreach ($element in $content <#Get-Content .\xevent_servicebroker_dbmail.sql#>) { + foreach ($element in $content ) { if ($element.Trim() -eq "GO") { $GenericModelobj.Value = $xevent_string $GenericModelobj.State = $true diff --git a/SQL LogScout/Bin/InstanceDiscovery.psm1 b/SQL LogScout/Bin/InstanceDiscovery.psm1 index f1f9f05..31eaf61 100644 --- a/SQL LogScout/Bin/InstanceDiscovery.psm1 +++ b/SQL LogScout/Bin/InstanceDiscovery.psm1 @@ -11,13 +11,13 @@ function Get-ClusterVNN ($instance_name) if (($instance_name -ne "") -and ($null -ne $instance_name)) { - $sql_fci_object = Get-ClusterResource | Where-Object {($_.ResourceType -eq "SQL Server")} | get-clusterparameter | Where-Object {($_.Name -eq "InstanceName") -and ($_.Value -eq $instance_name)} - $vnn_obj = Get-ClusterResource | Where-Object {($_.ResourceType -eq "SQL Server") -and ($_.OwnerGroup -eq $sql_fci_object.ClusterObject.OwnerGroup.Name)} | get-clusterparameter -Name VirtualServerName | Select-Object Value + $sql_fci_object = Get-ClusterResource | Where-Object {($_.ResourceType -eq "SQL Server")} | Get-ClusterParameter | Where-Object {($_.Name -eq "InstanceName") -and ($_.Value -eq $instance_name)} + $vnn_obj = Get-ClusterResource | Where-Object {($_.ResourceType -eq "SQL Server") -and ($_.OwnerGroup -eq $sql_fci_object.ClusterObject.OwnerGroup.Name)} | Get-ClusterParameter -Name VirtualServerName | Select-Object Value $vnn = $vnn_obj.Value } else { - Write-LogError "Instance name is empty and it shouldn't be at this point" + Write-LogError "Instance name is empty and it shouldn't be at this point ($($MyInvocation.MyCommand))" } Write-LogDebug "The VNN Matched to Instance = '$instance_name' is '$vnn' " -DebugLogLevel 2 @@ -41,7 +41,7 @@ function Get-ClusterVnnPlusInstance([string]$instance) if (($instance -eq "") -or ($null -eq $instance)) { - Write-LogError "Instance name is empty and it shouldn't be at this point" + Write-LogError "Instance name is empty and it shouldn't be at this point ($($MyInvocation.MyCommand))" } else { @@ -87,7 +87,7 @@ function Get-HostnamePlusInstance([string]$instance) if (($instance -eq "") -or ($null -eq $instance)) { - Write-LogError "Instance name is empty and it shouldn't be at this point" + Write-LogError "Instance name is empty and it shouldn't be at this point ($($MyInvocation.MyCommand))" } else { @@ -157,8 +157,8 @@ function Get-SQLServiceNameAndStatus() if ($sql_services.Count -eq 0) { #Insert dummy row in array to keep object type consistent - [PSCustomObject]$sql_services = @{Name='no_instance_found'; Status='UNKNOWN'} - Write-LogDebug "No installed SQL Server instances found. Array value: $sql_services" -DebugLogLevel 1 + [PSCustomObject]$sql_services = @{Name=$global:NO_INSTANCE_NAME; Status='UNKNOWN'} + Write-LogDebug "No installed SQL Server instances found. Name='$($sql_services.Name)', Status='$($sql_services.Status)'" -DebugLogLevel 1 Write-LogInformation "There are currently no installed instances of SQL Server. Would you like to proceed with OS-only log collection?" -ForegroundColor Green @@ -551,7 +551,7 @@ function Select-SQLServerForDiagnostics() else # this is not likely to happen, but just in case we need to handle it and cause a failure { Write-LogError "The instance name passed in is not valid." - $global:sql_instance_conn_str = "invalid_instance_name" + $global:sql_instance_conn_str = $global:NO_INSTANCE_NAME } } else @@ -570,10 +570,14 @@ function Select-SQLServerForDiagnostics() } } + #return instance in case this function needs to be called externally + return $global:sql_instance_conn_str + } catch { HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + return $global:NO_INSTANCE_NAME } } @@ -583,7 +587,7 @@ function Set-NoInstanceToHostName() Write-LogDebug "inside" $MyInvocation.MyCommand try { - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { $global:sql_instance_conn_str = $global:host_name } diff --git a/SQL LogScout/Bin/LoggingFacility.psm1 b/SQL LogScout/Bin/LoggingFacility.psm1 index dcd5f94..67e6fc3 100644 --- a/SQL LogScout/Bin/LoggingFacility.psm1 +++ b/SQL LogScout/Bin/LoggingFacility.psm1 @@ -15,6 +15,13 @@ if ($CommonFuncModule -ne "CommonFunctions") $global:consoleLogBuffer = @() $global:debugLogBuffer = @() +if($null -eq $global:EnvTempVarFullPath) +{ + $global:EnvTempVarFullPath = $Env:TEMP +} + + + #=======================================Init ===================================== #cleanup from previous script runs #NOT needed when running script from CMD @@ -368,9 +375,9 @@ param( # before we create the long-term debug log # we prune these files leaving only the 9 most recent ones # after that we create the 10th - Write-LogDebug "Pruning older SQL LogScout DEBUG Logs in $env:TEMP" -DebugLogLevel 1 + Write-LogDebug "Pruning older SQL LogScout DEBUG Logs in '$global:EnvTempVarFullPath'" -DebugLogLevel 1 $LogFileName = ($LogFileName -replace "_DEBUG.LOG", ("_DEBUG_*.LOG")) - $FilesToDelete = (Get-ChildItem -Path ($env:TEMP + "\" + $LogFileName) | Sort-Object -Property LastWriteTime -Descending | Select-Object -Skip 9) + $FilesToDelete = (Get-ChildItem -Path ($global:EnvTempVarFullPath + "\" + $LogFileName) | Sort-Object -Property LastWriteTime -Descending | Select-Object -Skip 9) $NumFilesToDelete = $FilesToDelete.Count Write-LogDebug "Found $NumFilesToDelete older SQL LogScout DEBUG Logs" -DebugLogLevel 2 @@ -392,7 +399,7 @@ param( $LogFileName = ($LogFileName -replace "_DEBUG_\*.LOG", ("_DEBUG_" + @(Get-Date -Format "yyyyMMddTHHmmssffff") + ".LOG")) # create the long-term debug log and keep a reference to it - $full_log_file_path = $env:TEMP + "\" + $LogFileName + $full_log_file_path = $global:EnvTempVarFullPath + "\" + $LogFileName Write-LogInformation "Creating long term debug log file $full_log_file_path" $global:ltDebugLogStream = New-Object -TypeName System.IO.StreamWriter -ArgumentList ($full_log_file_path, $false, [System.Text.Encoding]::ASCII) diff --git a/SQL LogScout/Bin/README.md b/SQL LogScout/Bin/README.md index 41a2083..37607a1 100644 --- a/SQL LogScout/Bin/README.md +++ b/SQL LogScout/Bin/README.md @@ -10,14 +10,14 @@ - [Examples](#examples) 1. [Scenarios](#scenarios) 1. [Output folders](#output-folders) +1. [SQL LogScout as a scheduled task in Windows Task Scheduler](#schedule-sql-logscout-as-a-task-to-automate-execution) 1. [Logging](#logging) -1. [Permissions](#permissions) 1. [Targeted SQL instances](#targeted-sql-instances) 1. [Security](#security) 1. [Sample output](#sample-output) 1. [Test Suite](#test-suite) 1. [Script to cleanup an incomplete shutdown of SQL LogScout](#script-to-cleanup-an-incomplete-shutdown-of-sql-logscout) -1. [SQL LogScout as a scheduled task in Windows Task Scheduler](#schedule-sql-logscout-as-a-task-to-automate-execution) +1. [How to connect to and collect data from Windows Internal Database (WID)](#how-to-connect-to-and-collect-data-from-windows-internal-database-wid) # Introduction @@ -111,10 +111,17 @@ There are 3 possible ways to run and interact with SQL LogScout: 1. Run the following PS script by itself or by using [parameters](#parameters). For example: ```powershell - PS > .\SQL_LogScout.ps1 -Scenario "Basic" -ServerName "Win2022machine\inst2022" + .\SQL_LogScout.ps1 -Scenario "Basic" -ServerName "Win2022machine\inst2022" ``` -**Note:** Using the PowerShell script `SQL_LogScout.ps1` is the recommended way to run SQL LogScout, but `SQL_LogScout.cmd` is supported for backwards compatibility. The introduction of `SQL_LogScount.ps1` was brought about for several reasons: +### Accept to run signed files for first time + +You may be prompted to accept to run the digitally-signed PowerShell scripts for the very first time. See [Prompt to accept usage of digitally-signed files](#prompt-to-accept-usage-of-digitally-signed-files) + + +### Recommendation to use SQL_LogScout.ps1 script + +Using the PowerShell script `SQL_LogScout.ps1` is the recommended way to run SQL LogScout, but `SQL_LogScout.cmd` is supported for backwards compatibility. The introduction of `SQL_LogScount.ps1` was brought about for several reasons: 1. The ability to invoke SQL LogScout with named parameters in any order and with the option to omit parameters that aren't required. The .CMD file has been inflexible in this respect. 1. The introduction of a new feature RepeatCollections or continuous mode and the ability to retain a certain number of output folders when run with continuous mode. @@ -128,7 +135,7 @@ There are 3 possible ways to run and interact with SQL LogScout: |:---------------------------| | Please make sure that the SQL Server startup account has **write** permissions to the folder you selected. Typically folders like %USERPROFILE%\Downloads, %USERPROFILE%\Documents AND %USERPROFILE%\Desktop folders are **not** write-accessible by the SQL Server service account by default.| -1. Open a PowerShell prompot or a Command Prompt as an Administrator and change to the folder where SQL LogScout files reside. For example: +1. Open a PowerShell prompt as an Administrator and change to the folder where SQL LogScout files reside. For example: ```console cd d:\sqllogscout @@ -137,7 +144,7 @@ There are 3 possible ways to run and interact with SQL LogScout: 1. Start the tool via `SQL_LogScout.ps1` before or while the issue is occurring and follow the menus ```console - SQL_LogScout.ps1 + .\SQL_LogScout.ps1 ``` 1. When prompted `Would you like to use GUI mode ?> (Y/N):` type 'y' and you will be presented with a GUI @@ -203,6 +210,71 @@ If the need arises, you can interrupt the execution of SQL LogScout by pressing |:---------------------------| | Do **not** close the Command Prompt window where SQL LogScout is running because this may leave a data collector running on your system. You can safely do so when SQL LogScout completes.| +## Stop execution automatically by using a .stop file + +In some cases the user may not be present to type 'STOP' and terminate the SQL LogScout collection. You may need to have an event trigger an automatic stop. To do so, you can create a blank or non-blank file named `logscout.stop` in the **\internal** folder. The file can be created either manually or programmatically. SQL LogScout detects the file within 5 seconds and initiates a graceful stop. A message is printed on teh screen and in the log that states this "Stop file detected. Shutting down the collector". + +Here are examples of how to create a logscout.stop file programmatically + +In PowerShell: + +```powershell +Set-Content -Value "stop please" -Path "G:\SQLLogScout\output\internal\logscout.stop" +``` + +In a batch file or from Command Prompt + +```bash +ECHO abc > F:\SQLLogScout\output_20240919T114819\internal\logscout.stop +``` + +There are two situations where this action is possible: + +- Manually choose to wait for a stop file to be created +- Create a stop file while SQL LogScout is waiting for an end time (DiagStopTime) to expire + +### Manually choose to wait for a stop file to be created + +You can set up SQL LogScout to stop only when a .stop file is created. If you manually start SQL LogScout and follow the prompts, you are asked whether you'd like to type 'STOP' or 'STOPEVENT'. If you type 'STOPEVENT', SQL LogScout continues to collect logs until a .stop file is created. The user experience looks like this: + +```bash +2025-03-28 14:49:16.302 INFO Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue. +2025-03-28 14:49:16.302 INFO You can type 'STOPEVENT' and wait for a stop file to automatically end the diagnostics collection. +>: stopevent +2025-03-28 14:49:25.809 INFO StopCollection Console input: stopevent +2025-03-28 14:49:25.821 INFO Waiting for stop file to be created... +2025-03-28 14:49:35.839 INFO Stop file detected. Shutting down the collector +2025-03-28 14:49:35.884 INFO Executing Collector: Xevents_Stop +2025-03-28 14:49:36.000 INFO Executing Collector: PerfmonStop +2025-03-28 14:49:39.126 INFO Executing Collector: KillActiveLogscoutSessions +2025-03-28 14:49:40.234 INFO Collecting logs for 'Basic' scenario +2025-03-28 14:49:40.266 INFO Executing Collector: TaskListVerbose +2025-03-28 14:49:45.465 INFO Executing Collector: TaskListServices +2025-03-28 14:49:48.582 INFO Executing Collector: FLTMC_Filters +``` + +### Create a stop file while waiting for an end time to expire + +If you have configured SQL LogScout to run until a predefined time using the -DiagStopTime parameter, then it waits for that time to be reached and automatically stop. However, if you decide to stop collection before that end time is reached, you can create a stop file in the \internal folder and SQL LogScout stops. The user experience looks like this (note that 14:48 is not reached because a stop file is created at 14:46): + +```bash +2025-03-28 14:46:18.245 INFO Executing Collector: HighCPU_perfstats +2025-03-28 14:46:18.322 INFO Executing Collector: PerfStats +2025-03-28 14:46:20.455 INFO Executing Collector: PerfStatsSnapshotStartup +2025-03-28 14:46:20.541 INFO Executing Collector: QueryStore +2025-03-28 14:46:22.649 INFO Executing Collector: TempDB_and_Tran_Analysis +2025-03-28 14:46:22.728 INFO Executing Collector: linked_server_config +2025-03-28 14:46:22.966 WARN Waiting until the specified stop time '2025-Mar-28 14:48:00' is reached...(CTRL+C to stop - wait for response) +2025-03-28 14:46:41.108 INFO Stop file detected. Shutting down the collector +2025-03-28 14:46:41.116 INFO Checking for errors in collector logs +2025-03-28 14:46:41.140 INFO Shutting down automatically. No user interaction to stop collectors +2025-03-28 14:46:41.145 INFO Waiting 10-15 seconds to capture a few snapshots of Perfmon before shutting down. +2025-03-28 14:46:53.152 INFO Shutting down the collector +2025-03-28 14:46:53.179 INFO Executing Collector: Xevents_Stop +2025-03-28 14:46:53.303 INFO Executing Collector: PerfmonStop +2025-03-28 14:46:56.415 INFO Executing Collector: KillActiveLogscoutSessions +``` + ## Parameters `SQL_LogScout.ps1` and `SQL_LogScout.cmd` accepts several optional parameters. If you are using the PS1 PowerShell script, you can pass named parameters and omit most of them or specify them in any order. However, if you are using `SQL_LogScout.cmd` because this is a batch file, you have to specify all the parameters in the sequence listed below and cannot omit parameters. For example if you would like to specify the server instance (3rd parameter), you must specify the Scenario parameter before it. @@ -225,6 +297,7 @@ Possible values are: - IO - LightPerf - ProcessMonitor + - ServiceBrokerDBMail - NeverEndingQuery - MenuChoice - this directs SQL LogScout to present an interactive menu with Scenario choices. The option is available in cases where multiple parameters are used with SQL_LogScout.cmd. Combining MenuChoice with another scenario choice, causes SQL LogScout to ignore MenuChoice and pick the selected scenario(s). For more information on what data each scenario collects, see [Scenarios](#scenarios) - NoBasic - this instructs SQL LogScout to skip the collection of basic logs, when Basic scenario is part of another scenario by default. For example if you use GeneralPerf+NoBasic, only the performance logs will be collected and static logs (Basic) will be skipped. If NoBasic+Basic is specified by mistake, the assumption is you intend to collect data; therefore Basic is enabled and NoBasic flag is disabled. Similarly, if NoBasic+Basic+A_VALID_SCENARIO is selected, again the assumption is that data collection is intended. In this case, Basic is enabled, NoBasic is disabled and A_VALID_SCENARIO will collect Basic logs. @@ -302,7 +375,7 @@ If you do not select any option in the GUI (e.g. scenario or server name) and cl This is the most common method to execute SQL LogScout which allows you to pick your choices from a menu of options ```powershell -SQL_LogScout.ps1 +.\SQL_LogScout.ps1 ``` ### B. Execute SQL LogScout using a specific scenario @@ -310,7 +383,7 @@ SQL_LogScout.ps1 This command starts the diagnostic collection specifying the GeneralPerf scenario. ```powershell -SQL_LogScout.ps1 -Scenario "GeneralPerf" +.\SQL_LogScout.ps1 -Scenario "GeneralPerf" ``` ### C. Execute SQL LogScout by specifying folder creation option @@ -318,7 +391,7 @@ SQL_LogScout.ps1 -Scenario "GeneralPerf" Execute SQL LogScout using the DetailedPerf Scenario, specifies the Server name, use the present directory and folder option to delete the default \output folder if present ```powershell -SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" +.\SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" ``` ### D. Execute SQL LogScout with start and stop times (absolute values) @@ -326,7 +399,7 @@ SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOut The following example collects the AlwaysOn scenario against the "DbSrv" default instance, prompts user to choose a custom path and a new custom subfolder, and sets the stop time to some time in the future, while setting the start time in the past to ensure the collectors start without delay. ```powershell -SQL_LogScout.ps1 -Scenario AlwaysOn -ServerName "DbSrv" -CustomOutputPath "PromptForCustomDir" -DeleteExistingOrCreateNew "NewCustomFolder" -DiagStartTime "2000-01-01 19:26:00" -DiagStopTime "2020-10-29 13:55:00" +.\SQL_LogScout.ps1 -Scenario AlwaysOn -ServerName "DbSrv" -CustomOutputPath "PromptForCustomDir" -DeleteExistingOrCreateNew "NewCustomFolder" -DiagStartTime "2000-01-01 19:26:00" -DiagStopTime "2020-10-29 13:55:00" ``` This is how you would do the same using the .CMD file. @@ -340,7 +413,7 @@ SQL_LogScout.cmd AlwaysOn "DbSrv" PromptForCustomDir NewCustomFolder "2000-01-01 The following example collects the Replication and LightPerf scenarios without getting Basic logs against the "DbSrv\SQL2022" named instance, uses the current directory as root and overwrites the \output subfolder. Then uses relative time from current time to set the start time 3 minutes from now and stop time to seven minutes from now. ```powershell -SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQL2022" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "+00:03:00" -DiagStopTime "+00:07:00" +.\SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQL2022" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "+00:03:00" -DiagStopTime "+00:07:00" ``` **Note:** If you are using SQL_LogScout.cmd, all parameters are required when you need to specify the last parameter. For example, if you need to specify stop time, the 5 prior parameters have to be passed. @@ -350,7 +423,7 @@ SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQ The example collects data for GeneralPerf, AlwaysOn, and BackupRestore scenarios against the "DbSrv" default instance, re-uses the default output folder but creates it in the D:\Log custom path, and sets the stop time to some time in the future, while setting the start time in the past to ensure the collectors start without delay. It also automatically accepts the prompts by using Quiet mode and helps a full automation with no interaction. ```powershell -SQL_LogScout.ps1 -Scenario "GeneralPerf+AlwaysOn+BackupRestore" -ServerName "DbSrv" -CustomOutputPath "d:\log" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "01-01-2000" -DiagStopTime "04-01-2021 17:00" -InteractivePrompts "Quiet" +.\SQL_LogScout.ps1 -Scenario "GeneralPerf+AlwaysOn+BackupRestore" -ServerName "DbSrv" -CustomOutputPath "d:\log" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "01-01-2000" -DiagStopTime "04-01-2021 17:00" -InteractivePrompts "Quiet" ``` When you use SQL_LogScout.cmd (available for backwards compatibility), pass the parameters in order @@ -390,9 +463,10 @@ Collects snapshot or static logs. It captures information on: - Installed Windows Hotfixes - OS disk information - Running filter drivers +- .NET Framework and .NET Core versions - Event logs (system and application in both .CSV and .TXT formats) - Full-Text Search Log files and output file with Full-Text metadata -- SQL Server dumps found in the errorlog directory. We collect up to 20 dumps if they were created in the last 2 months and are less than 100 MB in size. +- SQL Server dumps found in the errorlog directory. SQL LogScout collects up to 20 dumps if they were created in the last 2 months and are less than 200 MB in size. - Memory dump .txt files (most recent 200 files) - IPConfig, DNSClientInfo, and TCP and UDP endpoints - SQL Errorlogs @@ -486,7 +560,7 @@ Allows you to collect a [Windows Performance Recorder](https://docs.microsoft.co | :warning: WARNING | |:---------------------------| -| WPR traces collect system-wide diagnostic data. Thus a large set of trace data may be collected and it may take several minutes to stop the trace. Therefore the WPR trace is limited to 45 seconds of data collection. You can specify a custom value between 3 and 45 seconds.| +| WPR traces collect system-wide diagnostic data. Thus a large set of trace data may be collected and it may take several minutes to stop the trace. Therefore the WPR trace is limited to 45 seconds of data collection. You can specify a custom value between 3 and 45 seconds. Since the WPR scenario is run for a very short time and can be impactful to systems, this scenario is not designed to be run as a scheduled task and requires the user's interaction with SQL LogScout to run it.| ## 9. Setup scenario @@ -494,7 +568,9 @@ Collects Setup logs and allows analysis of installation issues of SQL Server com - Basic scenario logs - All SQL Setup logs from the SQL Server \Setup Bootstrap\ folders on the system. +- Registry keys of the installed programs on the system - Missing MSI/MSP output files showing what installation packages may be missing. The summary file shows the only missing and potentially corrupt packages and the detailed one provides details on each SQL Server MSI/MSP and if it's in place, missing, or corrupt and what actions can be taken. +- A list of installed programs on the system ## 10. BackupRestore scenario @@ -557,7 +633,7 @@ SQL LogScout can be scheduled as a task in Windows Task Scheduler. This allows y - **-LogScoutPath** - this is the executable path to the `SQL_LogScout.cmd` file. It defaults to the current path you are running the script from. - **-Scenario** - you can input the scenario (s) you want to collect data for. Examples include "Basic", "GeneralPerf" or "Basic+Replication". For more information see [Scenarios](#scenarios) -- **-SQLInstance** - this is the name of the SQL Server instance to connect to. Please provide correct name (for example: "MACHINE1\SQLINST1") +- **-SQLInstance** - this is the name of the SQL Server instance to connect to. Please provide correct name. For example you would use "MACHINE1\SQLINST1" for a named instance or "MACHINE2" for a default instance. For SQL Server failover clustered instances use a virtual network name: for example "SQL01FCIVNN" for a default instance or "SQL01FCIVNN\SQLINST2" for a named instance. - **-OutputPath** - you specify whether you want a custom output path by providing the path itself, or specify 'UsePresentDir' to use the current folder as a base under which an output folder will be created. This corresponds to `CustomOutputPath` in SQL LogScout [Parameters](#parameters). Do NOT use `PromptForCustomDir` for a scheduled task, because you have to present to accept this on the screen. - **-CmdTaskName** - this is the name of the task as it appears in Windows Task Scheduler. This is an optional parameter that allows you to create multiple scheduled tasks. If you pass a value which already exists, you will be prompted to overwrite or keep original task. Default value is "SQL LogScout Task". - **-DeleteFolderOrNew** - this controls the sub-folder name where the output data goes. For more information see, `DeleteExistingOrCreateNew` in [Parameters](#parameters). Options for it are: @@ -578,32 +654,43 @@ SQL LogScout can be scheduled as a task in Windows Task Scheduler. This allows y Examples: 1. Run SQL_LogScout one time for the GeneralPerf scenario, starting at 05/06/2024 at 2:18 PM ending after 10 minutes (2:28 PM). The Output folder is overwritten (if it exists already). User will be logged in during execution. + ```powershell -.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstanceName" -StartTime "2024-05-06 14:18" -EndTime "+00:10:00" -Once -DeleteFolderOrNew "DeleteDefaultFolder" -LogonType "S4U" +.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstance01" -StartTime "2024-05-06 14:18" -EndTime "+00:10:00" -Once -DeleteFolderOrNew "DeleteDefaultFolder" -LogonType "S4U" ``` -2. Run SQL_LogScout starting 6 hours from now, running continously for 48 executions recycling the logs every 30 minutes. The total run time would be 24 hours (48 runs * 30 minutes). A new folder is created for each execution and the user isn't to be logged in during runtime. + +1. Run SQL_LogScout starting 6 hours from now, running continously for 48 executions recycling the logs every 30 minutes. The total run time would be 24 hours (48 runs * 30 minutes). A new folder is created for each execution and the user isn't to be logged in during runtime. + ```powershell -.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstanceName" -StartTime "+06:00:00" -EndTime "+00:30:00" -Continuous -DeleteFolderOrNew "NewCustomFolder" -LogonType "Interactive" -RepeatCollections 47 +.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance "SQLPRODMACHINE" -StartTime "+06:00:00" -EndTime "+00:30:00" -Continuous -DeleteFolderOrNew "NewCustomFolder" -LogonType "Interactive" -RepeatCollections 47 ``` # Logging +There are several logs generated by SQL LogScout based on the activities used. + ### ##SQLLOGSCOUT.LOG file + SQL LogScout logs the flow of activity in two files ##SQLLOGSCOUT.LOG and ##SQLLOGSCOUT_DEBUG.LOG. The activity flow on the console is logged in ##SQLLOGSCOUT.LOG. The design goal is to match what the user sees on the screen with what is written in the log file so that a post-mortem analysis can be performed. This file can be found in the **\Internal** folder ### ##STDERR.LOG file + If SQL LogScout main script generates any runtime errors that were not caught, those will be written to the ##STDERR.LOG file and the contents of that file is displayed in the console after the main script completes execution. The ##STDERR.LOG file is stored in the root directory where SQL LogScout runs because any failures that occur early before the creation of an output folder may be logged in this file. This file can be found together with the scripts (**\Bin** folder). ### ##SQLLOGSCOUT_DEBUG.LOG file + This file contains everything the ##SQLLOGSCOUT.LOG contains, but also adds many debug-level, detailed messages. These can be used to investigate any issues with SQL LogScout and examine the flow of execution in detail. This file can be found in the **\Internal** folder. In addition, the %temp% folder stores copies of ##SQLLOGSCOUT_DEBUG.LOG from the last 10 executions. ### SQL_LogScout_Repeated_Execution_yyyyMMddhhmmss.txt + This file is created when repeated collections (continuous mode) is used. It logs the number of repetitions, the number of folders to be preserved, the names of output folders created by the repeated mode. It is created in the Windows **%temp%** folder (commonly C:\Users\\\AppData\Local\Temp). ### ##SQLLogScout_ScheduledTask_yyyyMMddhhmmss.log + This file is created when the functionality to automate the SQL_LogScout collection task through Windows Task Scheduler is used. This file can be found in the user's **%temp%** folder where you can find copies of the latest 10 executions of the task scheduling script `ScheduleSQLLogScoutAsTask.ps1`. ### ##SQLLogScout_CleanupIncompleteShutdown_yyyyMMddhhmmss.log + This file is created when the functionality to cleanup an incomplete shutdown of SQL_LogScout is used. The last 10 instances of this file can be found in the user's **%temp%** folder. @@ -625,6 +712,37 @@ The following is security-related information: SQL LogScout is released with digitally-signed Powershell files. For other files, SQL LogScout calculates a SHA512 hash and compares it to the expected value of each file. If the stored hash does not match the calculated hash on disk, then SQL LogScout will not run. +### Prompt to accept usage of digitally-signed files + +When you download and run a new version of SQL LogScout on your system for the first time, you will be prompted to confim and accept running these scripts if your PowerShell execution policy requires signed files. In order to successfully run SQL LogScout, read the message on screen that shows that Microsoft has signed these files and accept to run. You may see messages similar to these: + +```powershell + +Do you want to run software from this untrusted publisher? +File C:\Temp\SQL_LogScout.ps1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, +S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers. +[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"): a +Launching SQL LogScout... + + + +Do you want to run software from this untrusted publisher? +File C:\Temp\Bin\CommonFunctions.psm1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers. +[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"): a +Copyright (c) 2022 Microsoft Corporation. All rights reserved. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +... + +``` + +### Validate digital signatures of Powershell scripts To manually validate script signature, you may execute the following: ```bash @@ -669,7 +787,7 @@ SignerCertificate : [Subject] ## Encrypted connection to SQL Server -SQL LogScout negotiates connection encryption with the SQL Server it collects data from. It does so by using "Encrypt=True;TrustServerCertificate=true;" and "sqlcmd -C -N" values. +SQL LogScout negotiates connection encryption with the SQL Server it collects data from. It does so by using "Encrypt=True;TrustServerCertificate=true;" and "sqlcmd -C -N" values. In cases where encryption isn't supported by the back-end SQL Server (for example WID), SQL LogScout will attempt to use an unencrypted connection via the classic SQL Server ODBC driver. # Sample output @@ -695,138 +813,139 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -2021-09-10 11:03:32.148 INFO Initializing log C:\temp\log scout\Test 2\output\internal\##SQLLOGSCOUT.LOG -2021-09-10 11:03:26.230 INFO SQL LogScout version: 4.5.33 -2021-09-10 11:03:26.302 INFO The Present folder for this collection is C:\temp\log scout\Test 2 -2021-09-10 11:03:30.479 INFO Prompt CustomDir Console Input: n -2021-09-10 11:03:30.551 INFO -2021-09-10 11:03:30.560 WARN It appears that output folder 'C:\temp\log scout\Test 2\output\' has been used before. -2021-09-10 11:03:30.562 WARN You can choose to: -2021-09-10 11:03:30.562 WARN - Delete (D) the \output folder contents and recreate it -2021-09-10 11:03:30.572 WARN - Create a new (N) folder using \Output_ddMMyyhhmmss format. -2021-09-10 11:03:30.572 WARN You can delete the new folder manually in the future -2021-09-10 11:03:31.954 INFO Output folder Console input: d -2021-09-10 11:03:32.118 WARN Deleted C:\temp\log scout\Test 2\output\ and its contents -2021-09-10 11:03:32.126 INFO Output path: C:\temp\log scout\Test 2\output\ -2021-09-10 11:03:32.126 INFO Error path is C:\temp\log scout\Test 2\output\internal\ -2021-09-10 11:03:32.168 INFO Validating attributes for non-Powershell script files -2021-09-10 11:03:32.648 INFO -2021-09-10 11:03:32.656 INFO Initiating diagnostics collection... -2021-09-10 11:03:32.659 INFO Please select one of the following scenarios: +2025-03-10 11:03:32.148 INFO Initializing log C:\temp\log scout\Test 2\output\internal\##SQLLOGSCOUT.LOG +2025-03-10 11:03:26.230 INFO SQL LogScout version: 4.5.33 +2025-03-10 11:03:26.302 INFO The Present folder for this collection is C:\temp\log scout\Test 2 +2025-03-10 11:03:30.479 INFO Prompt CustomDir Console Input: n +2025-03-10 11:03:30.551 INFO +2025-03-10 11:03:30.560 WARN It appears that output folder 'C:\temp\log scout\Test 2\output\' has been used before. +2025-03-10 11:03:30.562 WARN You can choose to: +2025-03-10 11:03:30.562 WARN - Delete (D) the \output folder contents and recreate it +2025-03-10 11:03:30.572 WARN - Create a new (N) folder using \Output_ddMMyyhhmmss format. +2025-03-10 11:03:30.572 WARN You can delete the new folder manually in the future +2025-03-10 11:03:31.954 INFO Output folder Console input: d +2025-03-10 11:03:32.118 WARN Deleted C:\temp\log scout\Test 2\output\ and its contents +2025-03-10 11:03:32.126 INFO Output path: C:\temp\log scout\Test 2\output\ +2025-03-10 11:03:32.126 INFO Error path is C:\temp\log scout\Test 2\output\internal\ +2025-03-10 11:03:32.168 INFO Validating attributes for non-Powershell script files +2025-03-10 11:03:32.648 INFO +2025-03-10 11:03:32.656 INFO Initiating diagnostics collection... +2025-03-10 11:03:32.659 INFO Please select one of the following scenarios: -2021-09-10 11:03:32.659 INFO -2021-09-10 11:03:32.669 INFO ID Scenario -2021-09-10 11:03:32.669 INFO -- --------------- -2021-09-10 11:03:32.677 INFO 0 Basic -2021-09-10 11:03:32.679 INFO 1 GeneralPerf -2021-09-10 11:03:32.679 INFO 2 DetailedPerf -2021-09-10 11:03:32.687 INFO 3 Replication -2021-09-10 11:03:32.689 INFO 4 AlwaysOn -2021-09-10 11:03:32.689 INFO 5 NetworkTrace -2021-09-10 11:03:32.689 INFO 6 Memory -2021-09-10 11:03:32.689 INFO 7 DumpMemory -2021-09-10 11:03:32.697 INFO 8 WPR -2021-09-10 11:03:32.699 INFO 9 Setup -2021-09-10 11:03:32.699 INFO 10 BackupRestore -2021-09-10 11:03:32.699 INFO 11 IO -2021-09-10 11:03:32.699 INFO 12 LightPerf -2021-09-10 11:03:32.709 INFO -2021-09-10 11:03:32.709 WARN Type one or more Scenario IDs (separated by '+') for which you want to collect diagnostic data. Then press Enter -2021-09-10 11:04:02.077 INFO Scenario Console input: 1+4+10 -2021-09-10 11:04:02.208 INFO The scenarios selected are: 'GeneralPerf AlwaysOn BackupRestore Basic' -2021-09-10 11:04:02.665 INFO Discovered the following SQL Server instance(s) +2025-03-10 11:03:32.659 INFO +2025-03-10 11:03:32.669 INFO ID Scenario +2025-03-10 11:03:32.669 INFO -- --------------- +2025-03-10 11:03:32.677 INFO 0 Basic +2025-03-10 11:03:32.679 INFO 1 GeneralPerf +2025-03-10 11:03:32.679 INFO 2 DetailedPerf +2025-03-10 11:03:32.687 INFO 3 Replication +2025-03-10 11:03:32.689 INFO 4 AlwaysOn +2025-03-10 11:03:32.689 INFO 5 NetworkTrace +2025-03-10 11:03:32.689 INFO 6 Memory +2025-03-10 11:03:32.689 INFO 7 DumpMemory +2025-03-10 11:03:32.697 INFO 8 WPR +2025-03-10 11:03:32.699 INFO 9 Setup +2025-03-10 11:03:32.699 INFO 10 BackupRestore +2025-03-10 11:03:32.699 INFO 11 IO +2025-03-10 11:03:32.699 INFO 12 LightPerf +2025-03-10 11:03:32.709 INFO +2025-03-10 11:03:32.709 WARN Type one or more Scenario IDs (separated by '+') for which you want to collect diagnostic data. Then press Enter +2025-03-10 11:04:02.077 INFO Scenario Console input: 1+4+10 +2025-03-10 11:04:02.208 INFO The scenarios selected are: 'GeneralPerf AlwaysOn BackupRestore Basic' +2025-03-10 11:04:02.665 INFO Discovered the following SQL Server instance(s) -2021-09-10 11:04:02.665 INFO -2021-09-10 11:04:02.676 INFO ID SQL Instance Name -2021-09-10 11:04:02.678 INFO -- ---------------- -2021-09-10 11:04:02.679 INFO 0 DbServerMachine -2021-09-10 11:04:02.679 INFO 1 DbServerMachine\SQL2014 -2021-09-10 11:04:02.686 INFO 2 DbServerMachine\SQL2017 -2021-09-10 11:04:02.686 INFO 3 DbServerMachine\SQL2019 -2021-09-10 11:04:02.686 INFO -2021-09-10 11:04:02.686 WARN Enter the ID of the SQL instance for which you want to collect diagnostic data. Then press Enter -2021-09-10 11:04:11.899 INFO SQL Instance Console input: 3 -2021-09-10 11:04:11.911 INFO You selected instance 'DbServerMachine\SQL2019' to collect diagnostic data. -2021-09-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has VIEW SERVER STATE on SQL Server Instance 'DbServerMachine\SQL2019' -2021-09-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has ALTER ANY EVENT SESSION on SQL Server Instance 'DbServerMachine\SQL2019' -2021-09-10 11:04:12.735 WARN At least one of the selected 'GeneralPerf AlwaysOn BackupRestore Basic' scenarios collects Xevent traces -2021-09-10 11:04:12.751 WARN The service account 'NT Service\MSSQL$SQL2019' for SQL Server instance 'DbServerMachine\SQL2019' must have write/modify permissions on the 'C:\temp\log scout\Test 2\output\' folder -2021-09-10 11:04:12.751 WARN The easiest way to validate write permissions on the folder is to test-run SQL LogScout for 1-2 minutes and ensure an *.XEL file exists that you can open and read in SSMS -2021-09-10 11:04:15.822 INFO Access verification Console input: y -2021-09-10 11:04:15.841 INFO LogmanConfig.txt copied to C:\temp\log scout\Test 2\output\internal\LogmanConfig.txt -2021-09-10 11:04:15.922 INFO Basic collectors will execute on shutdown -2021-09-10 11:04:15.934 INFO Collecting logs for 'GeneralPerf' scenario -2021-09-10 11:04:15.964 INFO Executing Collector: Perfmon -2021-09-10 11:04:17.055 INFO Executing Collector: Xevent_Core_AddSession -2021-09-10 11:04:17.088 INFO Executing Collector: Xevent_General_AddSession -2021-09-10 11:04:19.130 INFO Executing Collector: Xevent_General_Target -2021-09-10 11:04:19.152 INFO Executing Collector: Xevent_General_Start -2021-09-10 11:04:19.214 INFO Executing Collector: ExistingProfilerXeventTraces -2021-09-10 11:04:21.313 INFO Executing Collector: HighCPU_perfstats -2021-09-10 11:04:21.364 INFO Executing Collector: SQLServerPerfStats -2021-09-10 11:04:23.441 INFO Executing Collector: SQLServerPerfStatsSnapshotStartup -2021-09-10 11:04:23.492 INFO Executing Collector: QueryStore -2021-09-10 11:04:25.552 INFO Executing Collector: TempDBAnalysis -2021-09-10 11:04:25.601 INFO Executing Collector: linked_server_config -2021-09-10 11:04:25.708 INFO Collecting logs for 'AlwaysOn' scenario -2021-09-10 11:04:25.740 INFO Executing Collector: AlwaysOnDiagScript -2021-09-10 11:04:25.788 INFO Executing Collector: Xevent_CoreAddSesion -2021-09-10 11:04:25.809 INFO Executing Collector: Xevent_AlwaysOn_Data_Movement -2021-09-10 11:04:27.853 INFO Executing Collector: AlwaysOn_Data_Movement_target -2021-09-10 11:04:27.881 INFO Executing Collector: AlwaysOn_Data_Movement_Start -2021-09-10 11:04:27.922 INFO Executing Collector: AlwaysOnHealthXevent -2021-09-10 11:04:28.007 INFO Collecting logs for 'BackupRestore' scenario -2021-09-10 11:04:28.023 INFO Executing Collector: Xevent_BackupRestore_AddSession -2021-09-10 11:04:30.070 INFO Executing Collector: EnableTraceFlag -2021-09-10 11:04:30.088 INFO Executing collector: SetVerboseSQLVSSWriterLog -2021-09-10 11:04:30.159 WARN To enable SQL VSS VERBOSE loggging, the SQL VSS Writer service must be restarted now and when shutting down data collection. This is a very quick process. -2021-09-10 11:04:36.697 INFO Console Input: n -2021-09-10 11:04:36.705 INFO You have chosen not to restart SQLWriter Service. No verbose logging will be collected for SQL VSS Writer (2019 or later) -2021-09-10 11:04:36.737 INFO Executing Collector: VSSAdmin_Providers -2021-09-10 11:04:36.778 INFO Executing Collector: VSSAdmin_Shadows -2021-09-10 11:04:37.832 INFO Executing Collector: VSSAdmin_Shadowstorage -2021-09-10 11:04:37.873 INFO Executing Collector: VSSAdmin_Writers -2021-09-10 11:04:37.924 INFO Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue -2021-09-10 11:04:43.012 INFO StopCollection Console input: stop -2021-09-10 11:04:43.014 INFO Shutting down the collector -2021-09-10 11:04:43.032 INFO Executing shutdown command: Xevents_Stop -2021-09-10 11:04:43.073 INFO Executing shutdown command: Xevents_Alwayson_Data_Movement_Stop -2021-09-10 11:04:43.098 INFO Executing shutdown command: Disable_BackupRestore_Trace_Flags -2021-09-10 11:04:43.145 INFO Executing shutdown command: PerfmonStop -2021-09-10 11:04:46.228 INFO Executing shutdown command: KillActiveLogscoutSessions -2021-09-10 11:04:47.277 INFO Collecting logs for 'Basic' scenario -2021-09-10 11:04:47.298 INFO Executing Collector: TaskListVerbose -2021-09-10 11:04:47.339 INFO Executing Collector: TaskListServices -2021-09-10 11:04:47.407 INFO Executing Collector: FLTMC_Filters -2021-09-10 11:04:47.464 INFO Executing Collector: FLTMC_Instances -2021-09-10 11:04:47.533 INFO Executing Collector: SystemInfo_Summary -2021-09-10 11:04:47.618 INFO Executing Collector: MiscDiagInfo -2021-09-10 11:04:47.681 INFO Executing Collector: SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel -2021-09-10 11:04:50.501 INFO Executing Collector: PolybaseLogs -2021-09-10 11:04:50.533 INFO Executing Collector: SQLAssessmentAPI -2021-09-10 11:05:09.554 INFO Executing Collector: UserRights -2021-09-10 11:05:12.266 INFO Executing Collector: RunningDrivers -2021-09-10 11:05:14.217 INFO Executing Collector: PowerPlan -2021-09-10 11:05:14.308 INFO Executing Collector: WindowsHotfixes -2021-09-10 11:05:16.694 INFO Executing Collector: GetEventLogs -2021-09-10 11:05:16.707 INFO Gathering Application EventLog in TXT and CSV format -2021-09-10 11:05:23.218 INFO Produced 10000 records in the EventLog -2021-09-10 11:05:29.011 INFO Produced 20000 records in the EventLog -2021-09-10 11:05:35.914 INFO Produced 30000 records in the EventLog -2021-09-10 11:05:41.975 INFO Produced 39129 records in the EventLog -2021-09-10 11:05:41.975 INFO Application EventLog in TXT and CSV format completed! -2021-09-10 11:05:41.975 INFO Gathering System EventLog in TXT and CSV format -2021-09-10 11:05:50.913 INFO Produced 10000 records in the EventLog -2021-09-10 11:05:59.494 INFO Produced 20000 records in the EventLog -2021-09-10 11:06:04.839 INFO Produced 26007 records in the EventLog -2021-09-10 11:06:04.842 INFO System EventLog in TXT and CSV format completed! -2021-09-10 11:06:04.879 INFO Executing Collector: PerfStatsSnapshotShutdown -2021-09-10 11:06:04.888 INFO Executing collector: GetSQLVSSWriterLog -2021-09-10 11:06:04.900 INFO SQLWriter Service has been restarted -2021-09-10 11:06:04.917 INFO Waiting 3 seconds to ensure files are written to and closed by any program including anti-virus... -2021-09-10 11:06:08.518 INFO Ending data collection -2021-09-10 11:06:08.533 WARN Launching cleanup and exit routine... please wait -2021-09-10 11:06:13.780 INFO Thank you for using SQL LogScout! +2025-03-10 11:04:02.665 INFO +2025-03-10 11:04:02.676 INFO ID SQL Instance Name +2025-03-10 11:04:02.678 INFO -- ---------------- +2025-03-10 11:04:02.679 INFO 0 DbServerMachine +2025-03-10 11:04:02.679 INFO 1 DbServerMachine\SQL2014 +2025-03-10 11:04:02.686 INFO 2 DbServerMachine\SQL2017 +2025-03-10 11:04:02.686 INFO 3 DbServerMachine\SQL2019 +2025-03-10 11:04:02.686 INFO +2025-03-10 11:04:02.686 WARN Enter the ID of the SQL instance for which you want to collect diagnostic data. Then press Enter +2025-03-10 11:04:11.899 INFO SQL Instance Console input: 3 +2025-03-10 11:04:11.911 INFO You selected instance 'DbServerMachine\SQL2019' to collect diagnostic data. +2025-03-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has VIEW SERVER STATE on SQL Server Instance 'DbServerMachine\SQL2019' +2025-03-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has ALTER ANY EVENT SESSION on SQL Server Instance 'DbServerMachine\SQL2019' +2025-03-10 11:04:12.735 WARN At least one of the selected 'GeneralPerf AlwaysOn BackupRestore Basic' scenarios collects Xevent traces +2025-03-10 11:04:12.751 WARN The service account 'NT Service\MSSQL$SQL2019' for SQL Server instance 'DbServerMachine\SQL2019' must have write/modify permissions on the 'C:\temp\log scout\Test 2\output\' folder +2025-03-10 11:04:12.751 WARN The easiest way to validate write permissions on the folder is to test-run SQL LogScout for 1-2 minutes and ensure an *.XEL file exists that you can open and read in SSMS +2025-03-10 11:04:15.822 INFO Access verification Console input: y +2025-03-10 11:04:15.841 INFO LogmanConfig.txt copied to C:\temp\log scout\Test 2\output\internal\LogmanConfig.txt +2025-03-10 11:04:15.922 INFO Basic collectors will execute on shutdown +2025-03-10 11:04:15.934 INFO Collecting logs for 'GeneralPerf' scenario +2025-03-10 11:04:15.964 INFO Executing Collector: Perfmon +2025-03-10 11:04:17.055 INFO Executing Collector: Xevent_Core_AddSession +2025-03-10 11:04:17.088 INFO Executing Collector: Xevent_General_AddSession +2025-03-10 11:04:19.130 INFO Executing Collector: Xevent_General_Target +2025-03-10 11:04:19.152 INFO Executing Collector: Xevent_General_Start +2025-03-10 11:04:19.214 INFO Executing Collector: ExistingProfilerXeventTraces +2025-03-10 11:04:21.313 INFO Executing Collector: HighCPU_perfstats +2025-03-10 11:04:21.364 INFO Executing Collector: SQLServerPerfStats +2025-03-10 11:04:23.441 INFO Executing Collector: SQLServerPerfStatsSnapshotStartup +2025-03-10 11:04:23.492 INFO Executing Collector: QueryStore +2025-03-10 11:04:25.552 INFO Executing Collector: TempDBAnalysis +2025-03-10 11:04:25.601 INFO Executing Collector: linked_server_config +2025-03-10 11:04:25.708 INFO Collecting logs for 'AlwaysOn' scenario +2025-03-10 11:04:25.740 INFO Executing Collector: AlwaysOnDiagScript +2025-03-10 11:04:25.788 INFO Executing Collector: Xevent_CoreAddSesion +2025-03-10 11:04:25.809 INFO Executing Collector: Xevent_AlwaysOn_Data_Movement +2025-03-10 11:04:27.853 INFO Executing Collector: AlwaysOn_Data_Movement_target +2025-03-10 11:04:27.881 INFO Executing Collector: AlwaysOn_Data_Movement_Start +2025-03-10 11:04:27.922 INFO Executing Collector: AlwaysOnHealthXevent +2025-03-10 11:04:28.007 INFO Collecting logs for 'BackupRestore' scenario +2025-03-10 11:04:28.023 INFO Executing Collector: Xevent_BackupRestore_AddSession +2025-03-10 11:04:30.070 INFO Executing Collector: EnableTraceFlag +2025-03-10 11:04:30.088 INFO Executing collector: SetVerboseSQLVSSWriterLog +2025-03-10 11:04:30.159 WARN To enable SQL VSS VERBOSE loggging, the SQL VSS Writer service must be restarted now and when shutting down data collection. This is a very quick process. +2025-03-10 11:04:36.697 INFO Console Input: n +2025-03-10 11:04:36.705 INFO You have chosen not to restart SQLWriter Service. No verbose logging will be collected for SQL VSS Writer (2019 or later) +2025-03-10 11:04:36.737 INFO Executing Collector: VSSAdmin_Providers +2025-03-10 11:04:36.778 INFO Executing Collector: VSSAdmin_Shadows +2025-03-10 11:04:37.832 INFO Executing Collector: VSSAdmin_Shadowstorage +2025-03-10 11:04:37.873 INFO Executing Collector: VSSAdmin_Writers +2025-03-10 11:04:37.924 INFO Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue. +2025-03-10 11:04:37.924 INFO You can type 'StopFile' and wait for the presence of a '\internal\logscout.stop' file to automatically end the diagnostics collection. +2025-03-10 11:04:43.012 INFO StopCollection Console input: stop +2025-03-10 11:04:43.014 INFO Shutting down the collector +2025-03-10 11:04:43.032 INFO Executing shutdown command: Xevents_Stop +2025-03-10 11:04:43.073 INFO Executing shutdown command: Xevents_Alwayson_Data_Movement_Stop +2025-03-10 11:04:43.098 INFO Executing shutdown command: Disable_BackupRestore_Trace_Flags +2025-03-10 11:04:43.145 INFO Executing shutdown command: PerfmonStop +2025-03-10 11:04:46.228 INFO Executing shutdown command: KillActiveLogscoutSessions +2025-03-10 11:04:47.277 INFO Collecting logs for 'Basic' scenario +2025-03-10 11:04:47.298 INFO Executing Collector: TaskListVerbose +2025-03-10 11:04:47.339 INFO Executing Collector: TaskListServices +2025-03-10 11:04:47.407 INFO Executing Collector: FLTMC_Filters +2025-03-10 11:04:47.464 INFO Executing Collector: FLTMC_Instances +2025-03-10 11:04:47.533 INFO Executing Collector: SystemInfo_Summary +2025-03-10 11:04:47.618 INFO Executing Collector: MiscDiagInfo +2025-03-10 11:04:47.681 INFO Executing Collector: SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel +2025-03-10 11:04:50.501 INFO Executing Collector: PolybaseLogs +2025-03-10 11:04:50.533 INFO Executing Collector: SQLAssessmentAPI +2025-03-10 11:05:09.554 INFO Executing Collector: UserRights +2025-03-10 11:05:12.266 INFO Executing Collector: RunningDrivers +2025-03-10 11:05:14.217 INFO Executing Collector: PowerPlan +2025-03-10 11:05:14.308 INFO Executing Collector: WindowsHotfixes +2025-03-10 11:05:16.694 INFO Executing Collector: GetEventLogs +2025-03-10 11:05:16.707 INFO Gathering Application EventLog in TXT and CSV format +2025-03-10 11:05:23.218 INFO Produced 10000 records in the EventLog +2025-03-10 11:05:29.011 INFO Produced 20000 records in the EventLog +2025-03-10 11:05:35.914 INFO Produced 30000 records in the EventLog +2025-03-10 11:05:41.975 INFO Produced 39129 records in the EventLog +2025-03-10 11:05:41.975 INFO Application EventLog in TXT and CSV format completed! +2025-03-10 11:05:41.975 INFO Gathering System EventLog in TXT and CSV format +2025-03-10 11:05:50.913 INFO Produced 10000 records in the EventLog +2025-03-10 11:05:59.494 INFO Produced 20000 records in the EventLog +2025-03-10 11:06:04.839 INFO Produced 26007 records in the EventLog +2025-03-10 11:06:04.842 INFO System EventLog in TXT and CSV format completed! +2025-03-10 11:06:04.879 INFO Executing Collector: PerfStatsSnapshotShutdown +2025-03-10 11:06:04.888 INFO Executing collector: GetSQLVSSWriterLog +2025-03-10 11:06:04.900 INFO SQLWriter Service has been restarted +2025-03-10 11:06:04.917 INFO Waiting 3 seconds to ensure files are written to and closed by any program including anti-virus... +2025-03-10 11:06:08.518 INFO Ending data collection +2025-03-10 11:06:08.533 WARN Launching cleanup and exit routine... please wait +2025-03-10 11:06:13.780 INFO Thank you for using SQL LogScout! Checking for console execution errors logged into .\##STDERR.LOG... Removed .\##STDERR.LOG which was 0 bytes @@ -948,4 +1067,54 @@ xecuting 'PerfmonStop'. It will stop Perfmon started by SQL LogScout in case it Executing 'NetworkTraceStop'. It will stop network tracing initiated by SQLLogScout in case it was found to be running... Cleanup script execution completed. PS C:\SQL LogScout\Bin> -``` \ No newline at end of file +``` + +# How to connect to and collect data from Windows Internal Database (WID) + +WID uses a modified version of SQL Server and has some limitations or behaves differently. SQL LogScout has been adapted to support WID with some lmitations: + +1. Doesn't connect with encryption because WID doesn't support encryption (less of a concern since connection is local). You will get an error message initially that a connection fails, but it would eventually succeed to connect. +1. Cannot use the SQL LogScout GUI because an client alias must be created. You can use command line only with ServerName specified explicitly. +1. Might not collect WID errorlogs unless you create a specific connection alias (see the [steps](#steps-to-collect-data-with-sql-logscout-on-wid) below) + +## Steps to collect data with SQL LogScout on WID + +1. Open Services app (services.msc) on Windows and find the **Windows Internal Database** service +1. Under the General tab, find the **Path to executable** and copy the WID instance name that appears after the -S parameter. Most commonly it is **MSWIN8.SQLWID** +1. Close Serivces app +1. Open SQL Client Network Utility (cliconfg.exe) and define an alias to the custom WID named pipe `np:\\.\pipe\MICROSOFT##WID\tsql\query`. Use the WiD instance you found, as a name in **Server alias**. For example use `MSWIN8.SQLWID` + + - Start->Run->Cliconfg.exe + - Click Add to create a new alias. + - In the Server alias field, enter the instance name you discovered in prior steps: `MSWIN8.SQLWID`. + - In the Network libraries section, select Named Pipes. + - In the Pipe Name section, enter `\\.\pipe\MICROSOFT##WID\tsql\query` + +1. Alternatively, you can use [SQL Server Configuration Manager](https://learn.microsoft.com/sql/relational-databases/sql-server-configuration-manager) to create an alias. For more information, see [Create or delete a server alias for use by a client](https://learn.microsoft.com/sql/database-engine/configure-windows/create-or-delete-a-server-alias-for-use-by-a-client) and [Aliases - Named Pipes connections](https://learn.microsoft.com/sql/tools/configuration-manager/aliases-sql-server-configuration-manager#named-pipes-connections) + +1. Then run SQL LogScout with that alias. For example + + ```PowerShell + .\SQL_LogScout.ps1 -ServerName "MSWIN8.SQLWID" -Scenario "GeneralPerf" + ``` + +1. You will get connection errors when trying to connect with a ODBC driver using encryption, but after a few attempts, an unencrypted connection succeeds. The output may look like this: + + ```output + 2025-01-08 00:14:31.229 WARN Could not connect to SQL Server + 2025-01-08 00:14:31.229 ERROR Function 'getSQLConnection' failed with error: Exception calling "Open" with "0" argument(s): "ERROR [08001] [Microsoft][ODBC Driver 17 for SQL Server]Encryption not supported on SQL Server. + ERROR [08001] [Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection + ERROR [01S00] [Microsoft][ODBC Driver 17 for SQL Server]Invalid connection string attribute" (line: 628, offset: 13, file: C:\Tools\SQLLogScout\Bin\CommonFunctions.psm1) + 2025-01-08 00:14:31.276 WARN Could not connect to SQL Server + 2025-01-08 00:14:31.276 ERROR Function 'getSQLConnection' failed with error: Exception calling "Open" with "0" argument(s): "ERROR [08001] [Microsoft][SQL Server Native Client 11.0]Encryption not supported on SQL Server. + ERROR [08001] [Microsoft][SQL Server Native Client 11.0]Client unable to establish connection + ERROR [01S00] [Microsoft][SQL Server Native Client 11.0]Invalid connection string attribute" (line: 628, offset: 13, file: C:\Tools\SQLLogScout\Bin\CommonFunctions.psm1) + 2025-01-08 00:14:31.307 WARN ********************************************************************** + 2025-01-08 00:14:31.323 WARN * SQL LogScout is switching to the classic SQL Server ODBC driver. + 2025-01-08 00:14:31.323 WARN * Thus, this local connection is unencrypted to ensure it is successful + 2025-01-08 00:14:31.323 WARN * To exit without collecting LogScout press Ctrl+C + 2025-01-08 00:14:31.323 WARN ********************************************************************** + 2025-01-08 00:14:37.489 INFO Confirmed that WIN2022SQL1\Administrator has VIEW SERVER STATE on SQL Server Instance 'MSWIN8.SQLWID' + 2025-01-08 00:14:37.489 INFO Confirmed that WIN2022SQL1\Administrator has ALTER ANY EVENT SESSION on SQL Server Instance 'MSWIN8.SQLWID' + 2025-01-08 00:14:37.489 INFO Confirmed that SQL Server Instance WIDAlias can write Extended Event Session Target at C:\Tools\SQLLogScout\output\WIDAlias_20250108T0014373961_xevent_LogScout_target_test.xel + ``` diff --git a/SQL LogScout/Bin/Readme.htm b/SQL LogScout/Bin/Readme.htm index 81317b6..fba5731 100644 --- a/SQL LogScout/Bin/Readme.htm +++ b/SQL LogScout/Bin/Readme.htm @@ -7,9 +7,6 @@ SQL LogScout Documentation -
@@ -246,8 +253,9 @@

SQL LogScout Documentation

  • Scenarios
  • Output folders
  • +
  • SQL +LogScout as a scheduled task in Windows Task Scheduler
  • Logging
  • -
  • Permissions
  • Targeted SQL instances
  • Security
  • Sample output
  • @@ -255,8 +263,10 @@

    SQL LogScout Documentation

  • Script to cleanup an incomplete shutdown of SQL LogScout
  • -
  • SQL -LogScout as a scheduled task in Windows Task Scheduler
  • +
  • How +to connect to and collect data from Windows Internal Database +(WID)
  • Introduction

    SQL LogScout allows you to collect diagnostic logs from your SQL @@ -353,12 +363,12 @@

    Use PowerShell script

    - + :warning: WARNING - + Please make sure that the SQL Server startup account has write permissions to the folder you selected. Typically folders like %USERPROFILE%, %USERPROFILE%AND @@ -381,13 +391,21 @@

    Use PowerShell script

  • Run the following PS script by itself or by using parameters. For example:

    PS > .\SQL_LogScout.ps1 -Scenario "Basic" -ServerName "Win2022machine\inst2022"
  • +class="sourceCode powershell">.\SQL_LogScout.ps1 -Scenario "Basic" -ServerName "Win2022machine\inst2022" -

    Note: Using the PowerShell script -SQL_LogScout.ps1 is the recommended way to run SQL -LogScout, but SQL_LogScout.cmd is supported for backwards -compatibility. The introduction of SQL_LogScount.ps1 was -brought about for several reasons:

    +

    Accept to run signed +files for first time

    +

    You may be prompted to accept to run the digitally-signed PowerShell +scripts for the very first time. See Prompt to +accept usage of digitally-signed files

    +

    Recommendation to +use SQL_LogScout.ps1 script

    +

    Using the PowerShell script SQL_LogScout.ps1 is the +recommended way to run SQL LogScout, but SQL_LogScout.cmd +is supported for backwards compatibility. The introduction of +SQL_LogScount.ps1 was brought about for several +reasons:

    1. The ability to invoke SQL LogScout with named parameters in any order and with the option to omit parameters that aren’t required. The @@ -411,12 +429,12 @@

      Use graphical user interface - + :warning: WARNING - + Please make sure that the SQL Server startup account has write permissions to the folder you selected. Typically folders like %USERPROFILE%, %USERPROFILE%AND @@ -426,13 +444,12 @@

      Use graphical user interface
        -
      1. Open a PowerShell prompot or a Command Prompt as an Administrator -and change to the folder where SQL LogScout files reside. For -example:

        +
      2. Open a PowerShell prompt as an Administrator and change to the +folder where SQL LogScout files reside. For example:

        cd d:\sqllogscout
      3. Start the tool via SQL_LogScout.ps1 before or while the issue is occurring and follow the menus

        -
        SQL_LogScout.ps1
      4. +
        .\SQL_LogScout.ps1
      5. When prompted Would you like to use GUI mode ?> (Y/N): type ‘y’ and you will be presented with a GUI

      6. @@ -456,12 +473,12 @@

        Use batch file (backward - + :warning: WARNING - + Please make sure that the SQL Server startup account has write permissions to the folder you selected. Typically folders like %USERPROFILE%, %USERPROFILE%AND @@ -524,12 +541,12 @@

        Interrupt execution

        - + :warning: WARNING - + Do not close the Command Prompt window where SQL LogScout is running because this may leave a data collector running on your system. You can safely do so when SQL @@ -537,6 +554,77 @@

        Interrupt execution

        +

        Stop +execution automatically by using a .stop file

        +

        In some cases the user may not be present to type ‘STOP’ and +terminate the SQL LogScout collection. You may need to have an event +trigger an automatic stop. To do so, you can create a blank or non-blank +file named logscout.stop in the *** folder. The file can be +created either manually or programmatically. SQL LogScout detects the +file within 5 seconds and initiates a graceful stop. A message is +printed on teh screen and in the log that states this “Stop file +detected. Shutting down the collector”.

        +

        Here are examples of how to create a logscout.stop file +programmatically

        +

        In PowerShell:

        +
        Set-Content -Value "stop please" -Path "G:\SQLLogScout\output\internal\logscout.stop"
        +

        In a batch file or from Command Prompt

        +
        ECHO abc > F:\SQLLogScout\output_20240919T114819\internal\logscout.stop
        +

        There are two situations where this action is possible:

        +
          +
        • Manually choose to wait for a stop file to be created
        • +
        • Create a stop file while SQL LogScout is waiting for an end time +(DiagStopTime) to expire
        • +
        +

        Manually +choose to wait for a stop file to be created

        +

        You can set up SQL LogScout to stop only when a .stop file is +created. If you manually start SQL LogScout and follow the prompts, you +are asked whether you’d like to type ‘STOP’ or ‘STOPEVENT’. If you type +‘STOPEVENT’, SQL LogScout continues to collect logs until a .stop file +is created. The user experience looks like this:

        +
        2025-03-28 14:49:16.302 INFO    Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue.
        +2025-03-28 14:49:16.302 INFO    You can type 'STOPEVENT' and wait for a stop file to automatically end the diagnostics collection.
        +>: stopevent
        +2025-03-28 14:49:25.809 INFO    StopCollection Console input: stopevent
        +2025-03-28 14:49:25.821 INFO    Waiting for stop file to be created...
        +2025-03-28 14:49:35.839 INFO    Stop file detected. Shutting down the collector
        +2025-03-28 14:49:35.884 INFO    Executing Collector: Xevents_Stop
        +2025-03-28 14:49:36.000 INFO    Executing Collector: PerfmonStop
        +2025-03-28 14:49:39.126 INFO    Executing Collector: KillActiveLogscoutSessions
        +2025-03-28 14:49:40.234 INFO    Collecting logs for 'Basic' scenario
        +2025-03-28 14:49:40.266 INFO    Executing Collector: TaskListVerbose
        +2025-03-28 14:49:45.465 INFO    Executing Collector: TaskListServices
        +2025-03-28 14:49:48.582 INFO    Executing Collector: FLTMC_Filters
        +

        Create a +stop file while waiting for an end time to expire

        +

        If you have configured SQL LogScout to run until a predefined time +using the -DiagStopTime parameter, then it waits for that time to be +reached and automatically stop. However, if you decide to stop +collection before that end time is reached, you can create a stop file +in the folder and SQL LogScout stops. The user experience looks like +this (note that 14:48 is not reached because a stop file is created at +14:46):

        +
        2025-03-28 14:46:18.245 INFO    Executing Collector: HighCPU_perfstats
        +2025-03-28 14:46:18.322 INFO    Executing Collector: PerfStats
        +2025-03-28 14:46:20.455 INFO    Executing Collector: PerfStatsSnapshotStartup
        +2025-03-28 14:46:20.541 INFO    Executing Collector: QueryStore
        +2025-03-28 14:46:22.649 INFO    Executing Collector: TempDB_and_Tran_Analysis
        +2025-03-28 14:46:22.728 INFO    Executing Collector: linked_server_config
        +2025-03-28 14:46:22.966 WARN    Waiting until the specified stop time '2025-Mar-28 14:48:00' is reached...(CTRL+C to stop - wait for response)
        +2025-03-28 14:46:41.108 INFO    Stop file detected. Shutting down the collector
        +2025-03-28 14:46:41.116 INFO    Checking for errors in collector logs
        +2025-03-28 14:46:41.140 INFO    Shutting down automatically. No user interaction to stop collectors
        +2025-03-28 14:46:41.145 INFO    Waiting 10-15 seconds to capture a few snapshots of Perfmon before shutting down.
        +2025-03-28 14:46:53.152 INFO    Shutting down the collector
        +2025-03-28 14:46:53.179 INFO    Executing Collector: Xevents_Stop
        +2025-03-28 14:46:53.303 INFO    Executing Collector: PerfmonStop
        +2025-03-28 14:46:56.415 INFO    Executing Collector: KillActiveLogscoutSessions

        Parameters

        SQL_LogScout.ps1 and SQL_LogScout.cmd accepts several optional parameters. If you are using the PS1 PowerShell @@ -563,6 +651,7 @@

        Scenario

      7. IO
      8. LightPerf
      9. ProcessMonitor
      10. +
      11. ServiceBrokerDBMail
      12. NeverEndingQuery
      13. MenuChoice - this directs SQL LogScout to present an interactive menu with Scenario choices. The option is available in cases where @@ -734,21 +823,21 @@

        A. Execute SQL LogScout (most common execution)

        This is the most common method to execute SQL LogScout which allows you to pick your choices from a menu of options

        -
        SQL_LogScout.ps1
        +
        .\SQL_LogScout.ps1

        B. Execute SQL LogScout using a specific scenario

        This command starts the diagnostic collection specifying the GeneralPerf scenario.

        -
        SQL_LogScout.ps1 -Scenario "GeneralPerf"
        +
        .\SQL_LogScout.ps1 -Scenario "GeneralPerf"

        C. Execute SQL LogScout by specifying folder creation option

        Execute SQL LogScout using the DetailedPerf Scenario, specifies the Server name, use the present directory and folder option to delete the default folder if present

        -
        SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder"
        +
        .\SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder"

        D. Execute SQL LogScout with start and stop times (absolute values)

        @@ -757,11 +846,11 @@

        C. custom subfolder, and sets the stop time to some time in the future, while setting the start time in the past to ensure the collectors start without delay.

        -
        SQL_LogScout.ps1 -Scenario AlwaysOn -ServerName "DbSrv" -CustomOutputPath "PromptForCustomDir" -DeleteExistingOrCreateNew "NewCustomFolder" -DiagStartTime "2000-01-01 19:26:00" -DiagStopTime "2020-10-29 13:55:00"
        +
        .\SQL_LogScout.ps1 -Scenario AlwaysOn -ServerName "DbSrv" -CustomOutputPath "PromptForCustomDir" -DeleteExistingOrCreateNew "NewCustomFolder" -DiagStartTime "2000-01-01 19:26:00" -DiagStopTime "2020-10-29 13:55:00"

        This is how you would do the same using the .CMD file.

        -
        SQL_LogScout.cmd AlwaysOn "DbSrv" PromptForCustomDir NewCustomFolder "2000-01-01 19:26:00" "2020-10-29 13:55:00"
        +
        SQL_LogScout.cmd AlwaysOn "DbSrv" PromptForCustomDir NewCustomFolder "2000-01-01 19:26:00" "2020-10-29 13:55:00"

        E. Execute SQL LogScout with relative start and stop times (time @@ -771,8 +860,8 @@

        C. uses the current directory as root and overwrites the subfolder. Then uses relative time from current time to set the start time 3 minutes from now and stop time to seven minutes from now.

        -
        SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQL2022" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "+00:03:00" -DiagStopTime "+00:07:00"
        +
        .\SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQL2022" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "+00:03:00" -DiagStopTime "+00:07:00"

        Note: If you are using SQL_LogScout.cmd, all parameters are required when you need to specify the last parameter. For example, if you need to specify stop time, the 5 prior parameters have @@ -787,12 +876,12 @@

        C. in the past to ensure the collectors start without delay. It also automatically accepts the prompts by using Quiet mode and helps a full automation with no interaction.

        -
        SQL_LogScout.ps1 -Scenario "GeneralPerf+AlwaysOn+BackupRestore" -ServerName "DbSrv" -CustomOutputPath "d:\log" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "01-01-2000" -DiagStopTime "04-01-2021 17:00" -InteractivePrompts "Quiet"
        +
        .\SQL_LogScout.ps1 -Scenario "GeneralPerf+AlwaysOn+BackupRestore" -ServerName "DbSrv" -CustomOutputPath "d:\log" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "01-01-2000" -DiagStopTime "04-01-2021 17:00" -InteractivePrompts "Quiet"

        When you use SQL_LogScout.cmd (available for backwards compatibility), pass the parameters in order

        -
        SQL_LogScout.cmd GeneralPerf+AlwaysOn+BackupRestore DbSrv "d:\log" DeleteDefaultFolder "01-01-2000" "04-01-2021 17:00" Quiet
        +
        SQL_LogScout.cmd GeneralPerf+AlwaysOn+BackupRestore DbSrv "d:\log" DeleteDefaultFolder "01-01-2000" "04-01-2021 17:00" Quiet

        Note: Selecting Quiet mode implicitly selects “Y” to all the screens that requires your agreement to proceed.

        C. run and 10 repeat runs), and keeps only the last 2 output folders of the 11 collections. It starts collection 2 seconds after the initialization and runs for 10 seconds.

        -
        .\SQL_LogScout.ps1 -Scenario "Memory+NoBasic" -ServerName "." -RepeatCollections 10  -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew 2 -DiagStartTime "+00:00:02" -DiagStopTime "+00:00:10"
        +
        .\SQL_LogScout.ps1 -Scenario "Memory+NoBasic" -ServerName "." -RepeatCollections 10  -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew 2 -DiagStartTime "+00:00:02" -DiagStopTime "+00:00:10"

        Note: You can only use SQL_LogScout.ps1, and not SQL_LogScout.cmd for RepeatCollections mode.

        @@ -827,13 +916,14 @@

        0. Basic scenario

      14. Installed Windows Hotfixes
      15. OS disk information
      16. Running filter drivers
      17. +
      18. .NET Framework and .NET Core versions
      19. Event logs (system and application in both .CSV and .TXT formats)
      20. Full-Text Search Log files and output file with Full-Text metadata
      21. -
      22. SQL Server dumps found in the errorlog directory. We collect up to -20 dumps if they were created in the last 2 months and are less than 100 -MB in size.
      23. +
      24. SQL Server dumps found in the errorlog directory. SQL LogScout +collects up to 20 dumps if they were created in the last 2 months and +are less than 200 MB in size.
      25. Memory dump .txt files (most recent 200 files)
      26. IPConfig, DNSClientInfo, and TCP and UDP endpoints
      27. SQL Errorlogs
      28. @@ -988,17 +1078,20 @@

        8. Windows - + :warning: WARNING - + WPR traces collect system-wide diagnostic data. Thus a large set of trace data may be collected and it may take several minutes to stop the trace. Therefore the WPR trace is limited to 45 seconds of data collection. You can specify a custom value between 3 -and 45 seconds. +and 45 seconds. Since the WPR scenario is run for a very short time and +can be impactful to systems, this scenario is not designed to be run as +a scheduled task and requires the user’s interaction with SQL LogScout +to run it. @@ -1009,11 +1102,13 @@

        9. Setup scenario

      29. Basic scenario logs
      30. All SQL Setup logs from the SQL Server Bootstrap folders on the system.
      31. +
      32. Registry keys of the installed programs on the system
      33. Missing MSI/MSP output files showing what installation packages may be missing. The summary file shows the only missing and potentially corrupt packages and the detailed one provides details on each SQL Server MSI/MSP and if it’s in place, missing, or corrupt and what actions can be taken.
      34. +
      35. A list of installed programs on the system
      36. 10. BackupRestore scenario

        Collects various logs related to backup and restore activities in SQL @@ -1130,8 +1225,11 @@

        Schedule “Basic+Replication”. For more information see Scenarios
      37. -SQLInstance - this is the name of the SQL Server -instance to connect to. Please provide correct name (for example: -“MACHINE1”)
      38. +instance to connect to. Please provide correct name. For example you +would use “MACHINE1” for a named instance or “MACHINE2” for a default +instance. For SQL Server failover clustered instances use a virtual +network name: for example “SQL01FCIVNN” for a default instance or +“SQL01FCIVNN” for a named instance.
      39. -OutputPath - you specify whether you want a custom output path by providing the path itself, or specify ‘UsePresentDir’ to use the current folder as a base under which an output folder will be @@ -1238,17 +1336,19 @@

        Schedule folder is overwritten (if it exists already). User will be logged in during execution.

      -
      .\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstanceName" -StartTime "2024-05-06 14:18" -EndTime "+00:10:00" -Once -DeleteFolderOrNew "DeleteDefaultFolder" -LogonType "S4U"
      -
        +
        .\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstance01" -StartTime "2024-05-06 14:18" -EndTime "+00:10:00" -Once -DeleteFolderOrNew "DeleteDefaultFolder" -LogonType "S4U"
        +
        1. Run SQL_LogScout starting 6 hours from now, running continously for 48 executions recycling the logs every 30 minutes. The total run time would be 24 hours (48 runs * 30 minutes). A new folder is created for each execution and the user isn’t to be logged in during runtime.
        -
        .\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstanceName" -StartTime "+06:00:00" -EndTime "+00:30:00" -Continuous -DeleteFolderOrNew "NewCustomFolder" -LogonType "Interactive" -RepeatCollections 47
        +
        .\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance "SQLPRODMACHINE" -StartTime "+06:00:00" -EndTime "+00:30:00" -Continuous -DeleteFolderOrNew "NewCustomFolder" -LogonType "Interactive" -RepeatCollections 47

        Logging

        +

        There are several logs generated by SQL LogScout based on the +activities used.

        ##SQLLOGSCOUT.LOG file

        SQL LogScout logs the flow of activity in two files ##SQLLOGSCOUT.LOG and ##SQLLOGSCOUT_DEBUG.LOG. The activity flow on the console is logged @@ -1313,13 +1413,46 @@

        Digitally signed files other files, SQL LogScout calculates a SHA512 hash and compares it to the expected value of each file. If the stored hash does not match the calculated hash on disk, then SQL LogScout will not run.

        +

        Prompt to +accept usage of digitally-signed files

        +

        When you download and run a new version of SQL LogScout on your +system for the first time, you will be prompted to confim and accept +running these scripts if your PowerShell execution policy requires +signed files. In order to successfully run SQL LogScout, read the +message on screen that shows that Microsoft has signed these files and +accept to run. You may see messages similar to these:

        +
        
        +Do you want to run software from this untrusted publisher?
        +File C:\Temp\SQL_LogScout.ps1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond,
        +S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers.
        +[V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help (default is "D"): a
        +Launching SQL LogScout...
        +
        +
        +
        +Do you want to run software from this untrusted publisher?
        +File C:\Temp\Bin\CommonFunctions.psm1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers.
        +[V] Never run  [D] Do not run  [R] Run once  [A] Always run  [?] Help (default is "D"): a
        +Copyright (c) 2022 Microsoft Corporation. All rights reserved.
        +
        +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        +    THE SOFTWARE.
        +...
        +

        Validate +digital signatures of Powershell scripts

        To manually validate script signature, you may execute the following:

        -
        Get-ChildItem <SQL LogScout unzipped folder>\*.ps*1 | Get-AuthenticodeSignature | Format-List -Property Path, Status, StatusMessage, SignerCertificate`
        +
        Get-ChildItem <SQL LogScout unzipped folder>\*.ps*1 | Get-AuthenticodeSignature | Format-List -Property Path, Status, StatusMessage, SignerCertificate`

        Example:

        -
        Get-ChildItem -Path "c:\SQL_LogScout\*" -Recurse -Include "*.ps*1" | Get-AuthenticodeSignature | Format-List -Property Path, Status, StatusMessage, SignerCertificate
        +
        Get-ChildItem -Path "c:\SQL_LogScout\*" -Recurse -Include "*.ps*1" | Get-AuthenticodeSignature | Format-List -Property Path, Status, StatusMessage, SignerCertificate

        For each file:

        1. Confirm the path and filename in Path property.
        2. @@ -1332,191 +1465,194 @@

          Digitally signed files certificate.

        Example output for successful validation:

        -
        Path              : C:\SQL_LogScout_v4.1.11_Signed\SQLLogScoutPs.ps1
        -Status            : Valid
        -StatusMessage     : Signature verified.
        -SignerCertificate : [Subject]
        -                      CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
        -
        -                    [Issuer]
        -                      CN=Microsoft Code Signing PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
        -
        -                    [Serial Number]
        -                      33000001DF6BF02E92A74AB4D00000000001DF
        -
        -                    [Not Before]
        -                      12/15/2020 6:31:45 PM
        -
        -                    [Not After]
        -                      12/2/2021 6:31:45 PM
        -
        -                    [Thumbprint]
        -                      ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B
        +
        Path              : C:\SQL_LogScout_v4.1.11_Signed\SQLLogScoutPs.ps1
        +Status            : Valid
        +StatusMessage     : Signature verified.
        +SignerCertificate : [Subject]
        +                      CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
        +
        +                    [Issuer]
        +                      CN=Microsoft Code Signing PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
        +
        +                    [Serial Number]
        +                      33000001DF6BF02E92A74AB4D00000000001DF
        +
        +                    [Not Before]
        +                      12/15/2020 6:31:45 PM
        +
        +                    [Not After]
        +                      12/2/2021 6:31:45 PM
        +
        +                    [Thumbprint]
        +                      ABDCA79AF9DD48A0EA702AD45260B3C03093FB4B

        Encrypted connection to SQL Server

        SQL LogScout negotiates connection encryption with the SQL Server it collects data from. It does so by using -“Encrypt=True;TrustServerCertificate=true;” and “sqlcmd -C -N” -values.

        +“Encrypt=True;TrustServerCertificate=true;” and “sqlcmd -C -N” values. +In cases where encryption isn’t supported by the back-end SQL Server +(for example WID), SQL LogScout will attempt to use an unencrypted +connection via the classic SQL Server ODBC driver.

        Sample output

        -
             ======================================================================================================
        -              #####   #####  #          #                      #####
        -             #     # #     # #          #        ####   ####  #     #  ####   ####  #    # #####
        -             #       #     # #          #       #    # #    # #       #    # #    # #    #   #
        -              #####  #     # #          #       #    # #       #####  #      #    # #    #   #
        -                   # #   # # #          #       #    # #  ###       # #      #    # #    #   #
        -             #     # #    #  #          #       #    # #    # #     # #    # #    # #    #   #
        -              #####   #### # #######    #######  ####   ####   #####   ####   ####   ####    #
        -     ======================================================================================================
        -
        -Launching SQL LogScout...
        -Copyright (c) 2021 Microsoft Corporation. All rights reserved.
        -
        -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        -    THE SOFTWARE.
        -
        -2021-09-10 11:03:32.148 INFO    Initializing log C:\temp\log scout\Test 2\output\internal\##SQLLOGSCOUT.LOG 
        -2021-09-10 11:03:26.230 INFO    SQL LogScout version: 4.5.33 
        -2021-09-10 11:03:26.302 INFO    The Present folder for this collection is C:\temp\log scout\Test 2 
        -2021-09-10 11:03:30.479 INFO    Prompt CustomDir Console Input: n 
        -2021-09-10 11:03:30.551 INFO     
        -2021-09-10 11:03:30.560 WARN    It appears that output folder 'C:\temp\log scout\Test 2\output\' has been used before. 
        -2021-09-10 11:03:30.562 WARN    You can choose to: 
        -2021-09-10 11:03:30.562 WARN     - Delete (D) the \output folder contents and recreate it 
        -2021-09-10 11:03:30.572 WARN     - Create a new (N) folder using \Output_ddMMyyhhmmss format. 
        -2021-09-10 11:03:30.572 WARN       You can delete the new folder manually in the future 
        -2021-09-10 11:03:31.954 INFO    Output folder Console input: d 
        -2021-09-10 11:03:32.118 WARN    Deleted C:\temp\log scout\Test 2\output\ and its contents 
        -2021-09-10 11:03:32.126 INFO    Output path: C:\temp\log scout\Test 2\output\ 
        -2021-09-10 11:03:32.126 INFO    Error  path is C:\temp\log scout\Test 2\output\internal\ 
        -2021-09-10 11:03:32.168 INFO    Validating attributes for non-Powershell script files 
        -2021-09-10 11:03:32.648 INFO     
        -2021-09-10 11:03:32.656 INFO    Initiating diagnostics collection...  
        -2021-09-10 11:03:32.659 INFO    Please select one of the following scenarios:
        - 
        -2021-09-10 11:03:32.659 INFO     
        -2021-09-10 11:03:32.669 INFO    ID   Scenario 
        -2021-09-10 11:03:32.669 INFO    --   --------------- 
        -2021-09-10 11:03:32.677 INFO    0    Basic 
        -2021-09-10 11:03:32.679 INFO    1    GeneralPerf 
        -2021-09-10 11:03:32.679 INFO    2    DetailedPerf 
        -2021-09-10 11:03:32.687 INFO    3    Replication 
        -2021-09-10 11:03:32.689 INFO    4    AlwaysOn 
        -2021-09-10 11:03:32.689 INFO    5    NetworkTrace 
        -2021-09-10 11:03:32.689 INFO    6    Memory 
        -2021-09-10 11:03:32.689 INFO    7    DumpMemory 
        -2021-09-10 11:03:32.697 INFO    8    WPR 
        -2021-09-10 11:03:32.699 INFO    9    Setup 
        -2021-09-10 11:03:32.699 INFO    10   BackupRestore 
        -2021-09-10 11:03:32.699 INFO    11   IO 
        -2021-09-10 11:03:32.699 INFO    12   LightPerf 
        -2021-09-10 11:03:32.709 INFO     
        -2021-09-10 11:03:32.709 WARN    Type one or more Scenario IDs (separated by '+') for which you want to collect diagnostic data. Then press Enter 
        -2021-09-10 11:04:02.077 INFO    Scenario Console input: 1+4+10 
        -2021-09-10 11:04:02.208 INFO    The scenarios selected are: 'GeneralPerf AlwaysOn BackupRestore Basic' 
        -2021-09-10 11:04:02.665 INFO    Discovered the following SQL Server instance(s)
        - 
        -2021-09-10 11:04:02.665 INFO     
        -2021-09-10 11:04:02.676 INFO    ID  SQL Instance Name 
        -2021-09-10 11:04:02.678 INFO    --  ---------------- 
        -2021-09-10 11:04:02.679 INFO    0    DbServerMachine 
        -2021-09-10 11:04:02.679 INFO    1    DbServerMachine\SQL2014 
        -2021-09-10 11:04:02.686 INFO    2    DbServerMachine\SQL2017 
        -2021-09-10 11:04:02.686 INFO    3    DbServerMachine\SQL2019 
        -2021-09-10 11:04:02.686 INFO     
        -2021-09-10 11:04:02.686 WARN    Enter the ID of the SQL instance for which you want to collect diagnostic data. Then press Enter 
        -2021-09-10 11:04:11.899 INFO    SQL Instance Console input: 3 
        -2021-09-10 11:04:11.911 INFO    You selected instance 'DbServerMachine\SQL2019' to collect diagnostic data.  
        -2021-09-10 11:04:12.022 INFO    Confirmed that MYDOMAIN\Joseph has VIEW SERVER STATE on SQL Server Instance 'DbServerMachine\SQL2019' 
        -2021-09-10 11:04:12.022 INFO    Confirmed that MYDOMAIN\Joseph has ALTER ANY EVENT SESSION on SQL Server Instance 'DbServerMachine\SQL2019' 
        -2021-09-10 11:04:12.735 WARN    At least one of the selected 'GeneralPerf AlwaysOn BackupRestore Basic' scenarios collects Xevent traces 
        -2021-09-10 11:04:12.751 WARN    The service account 'NT Service\MSSQL$SQL2019' for SQL Server instance 'DbServerMachine\SQL2019' must have write/modify permissions on the 'C:\temp\log scout\Test 2\output\' folder 
        -2021-09-10 11:04:12.751 WARN    The easiest way to validate write permissions on the folder is to test-run SQL LogScout for 1-2 minutes and ensure an *.XEL file exists that you can open and read in SSMS 
        -2021-09-10 11:04:15.822 INFO    Access verification Console input: y 
        -2021-09-10 11:04:15.841 INFO    LogmanConfig.txt copied to  C:\temp\log scout\Test 2\output\internal\LogmanConfig.txt 
        -2021-09-10 11:04:15.922 INFO    Basic collectors will execute on shutdown 
        -2021-09-10 11:04:15.934 INFO    Collecting logs for 'GeneralPerf' scenario 
        -2021-09-10 11:04:15.964 INFO    Executing Collector: Perfmon 
        -2021-09-10 11:04:17.055 INFO    Executing Collector: Xevent_Core_AddSession 
        -2021-09-10 11:04:17.088 INFO    Executing Collector: Xevent_General_AddSession 
        -2021-09-10 11:04:19.130 INFO    Executing Collector: Xevent_General_Target 
        -2021-09-10 11:04:19.152 INFO    Executing Collector: Xevent_General_Start 
        -2021-09-10 11:04:19.214 INFO    Executing Collector: ExistingProfilerXeventTraces 
        -2021-09-10 11:04:21.313 INFO    Executing Collector: HighCPU_perfstats 
        -2021-09-10 11:04:21.364 INFO    Executing Collector: SQLServerPerfStats 
        -2021-09-10 11:04:23.441 INFO    Executing Collector: SQLServerPerfStatsSnapshotStartup 
        -2021-09-10 11:04:23.492 INFO    Executing Collector: QueryStore 
        -2021-09-10 11:04:25.552 INFO    Executing Collector: TempDBAnalysis 
        -2021-09-10 11:04:25.601 INFO    Executing Collector: linked_server_config 
        -2021-09-10 11:04:25.708 INFO    Collecting logs for 'AlwaysOn' scenario 
        -2021-09-10 11:04:25.740 INFO    Executing Collector: AlwaysOnDiagScript 
        -2021-09-10 11:04:25.788 INFO    Executing Collector: Xevent_CoreAddSesion 
        -2021-09-10 11:04:25.809 INFO    Executing Collector: Xevent_AlwaysOn_Data_Movement 
        -2021-09-10 11:04:27.853 INFO    Executing Collector: AlwaysOn_Data_Movement_target 
        -2021-09-10 11:04:27.881 INFO    Executing Collector: AlwaysOn_Data_Movement_Start 
        -2021-09-10 11:04:27.922 INFO    Executing Collector: AlwaysOnHealthXevent 
        -2021-09-10 11:04:28.007 INFO    Collecting logs for 'BackupRestore' scenario 
        -2021-09-10 11:04:28.023 INFO    Executing Collector: Xevent_BackupRestore_AddSession 
        -2021-09-10 11:04:30.070 INFO    Executing Collector: EnableTraceFlag 
        -2021-09-10 11:04:30.088 INFO    Executing collector: SetVerboseSQLVSSWriterLog
        -2021-09-10 11:04:30.159 WARN    To enable SQL VSS VERBOSE loggging, the SQL VSS Writer service must be restarted now and when shutting down data collection. This is a very quick process.
        -2021-09-10 11:04:36.697 INFO    Console Input: n 
        -2021-09-10 11:04:36.705 INFO    You have chosen not to restart SQLWriter Service. No verbose logging will be collected for SQL VSS Writer (2019 or later)
        -2021-09-10 11:04:36.737 INFO    Executing Collector: VSSAdmin_Providers 
        -2021-09-10 11:04:36.778 INFO    Executing Collector: VSSAdmin_Shadows 
        -2021-09-10 11:04:37.832 INFO    Executing Collector: VSSAdmin_Shadowstorage 
        -2021-09-10 11:04:37.873 INFO    Executing Collector: VSSAdmin_Writers 
        -2021-09-10 11:04:37.924 INFO    Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue 
        -2021-09-10 11:04:43.012 INFO    StopCollection Console input: stop 
        -2021-09-10 11:04:43.014 INFO    Shutting down the collector 
        -2021-09-10 11:04:43.032 INFO    Executing shutdown command: Xevents_Stop 
        -2021-09-10 11:04:43.073 INFO    Executing shutdown command: Xevents_Alwayson_Data_Movement_Stop 
        -2021-09-10 11:04:43.098 INFO    Executing shutdown command: Disable_BackupRestore_Trace_Flags
        -2021-09-10 11:04:43.145 INFO    Executing shutdown command: PerfmonStop 
        -2021-09-10 11:04:46.228 INFO    Executing shutdown command: KillActiveLogscoutSessions 
        -2021-09-10 11:04:47.277 INFO    Collecting logs for 'Basic' scenario 
        -2021-09-10 11:04:47.298 INFO    Executing Collector: TaskListVerbose 
        -2021-09-10 11:04:47.339 INFO    Executing Collector: TaskListServices 
        -2021-09-10 11:04:47.407 INFO    Executing Collector: FLTMC_Filters 
        -2021-09-10 11:04:47.464 INFO    Executing Collector: FLTMC_Instances 
        -2021-09-10 11:04:47.533 INFO    Executing Collector: SystemInfo_Summary 
        -2021-09-10 11:04:47.618 INFO    Executing Collector: MiscDiagInfo 
        -2021-09-10 11:04:47.681 INFO    Executing Collector: SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel 
        -2021-09-10 11:04:50.501 INFO    Executing Collector: PolybaseLogs 
        -2021-09-10 11:04:50.533 INFO    Executing Collector: SQLAssessmentAPI 
        -2021-09-10 11:05:09.554 INFO    Executing Collector: UserRights 
        -2021-09-10 11:05:12.266 INFO    Executing Collector: RunningDrivers 
        -2021-09-10 11:05:14.217 INFO    Executing Collector: PowerPlan 
        -2021-09-10 11:05:14.308 INFO    Executing Collector: WindowsHotfixes 
        -2021-09-10 11:05:16.694 INFO    Executing Collector: GetEventLogs 
        -2021-09-10 11:05:16.707 INFO    Gathering Application EventLog in TXT and CSV format   
        -2021-09-10 11:05:23.218 INFO       Produced 10000 records in the EventLog 
        -2021-09-10 11:05:29.011 INFO       Produced 20000 records in the EventLog 
        -2021-09-10 11:05:35.914 INFO       Produced 30000 records in the EventLog 
        -2021-09-10 11:05:41.975 INFO       Produced 39129 records in the EventLog 
        -2021-09-10 11:05:41.975 INFO    Application EventLog in TXT and CSV format completed! 
        -2021-09-10 11:05:41.975 INFO    Gathering System EventLog in TXT and CSV format   
        -2021-09-10 11:05:50.913 INFO       Produced 10000 records in the EventLog 
        -2021-09-10 11:05:59.494 INFO       Produced 20000 records in the EventLog 
        -2021-09-10 11:06:04.839 INFO       Produced 26007 records in the EventLog 
        -2021-09-10 11:06:04.842 INFO    System EventLog in TXT and CSV format completed! 
        -2021-09-10 11:06:04.879 INFO    Executing Collector: PerfStatsSnapshotShutdown
        -2021-09-10 11:06:04.888 INFO    Executing collector: GetSQLVSSWriterLog
        -2021-09-10 11:06:04.900 INFO    SQLWriter Service has been restarted
        -2021-09-10 11:06:04.917 INFO    Waiting 3 seconds to ensure files are written to and closed by any program including anti-virus... 
        -2021-09-10 11:06:08.518 INFO    Ending data collection 
        -2021-09-10 11:06:08.533 WARN    Launching cleanup and exit routine... please wait 
        -2021-09-10 11:06:13.780 INFO    Thank you for using SQL LogScout! 
        -
        -Checking for console execution errors logged into .\##STDERR.LOG...
        -Removed .\##STDERR.LOG which was 0 bytes
        +
             ======================================================================================================
        +              #####   #####  #          #                      #####
        +             #     # #     # #          #        ####   ####  #     #  ####   ####  #    # #####
        +             #       #     # #          #       #    # #    # #       #    # #    # #    #   #
        +              #####  #     # #          #       #    # #       #####  #      #    # #    #   #
        +                   # #   # # #          #       #    # #  ###       # #      #    # #    #   #
        +             #     # #    #  #          #       #    # #    # #     # #    # #    # #    #   #
        +              #####   #### # #######    #######  ####   ####   #####   ####   ####   ####    #
        +     ======================================================================================================
        +
        +Launching SQL LogScout...
        +Copyright (c) 2021 Microsoft Corporation. All rights reserved.
        +
        +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        +    THE SOFTWARE.
        +
        +2025-03-10 11:03:32.148 INFO    Initializing log C:\temp\log scout\Test 2\output\internal\##SQLLOGSCOUT.LOG 
        +2025-03-10 11:03:26.230 INFO    SQL LogScout version: 4.5.33 
        +2025-03-10 11:03:26.302 INFO    The Present folder for this collection is C:\temp\log scout\Test 2 
        +2025-03-10 11:03:30.479 INFO    Prompt CustomDir Console Input: n 
        +2025-03-10 11:03:30.551 INFO     
        +2025-03-10 11:03:30.560 WARN    It appears that output folder 'C:\temp\log scout\Test 2\output\' has been used before. 
        +2025-03-10 11:03:30.562 WARN    You can choose to: 
        +2025-03-10 11:03:30.562 WARN     - Delete (D) the \output folder contents and recreate it 
        +2025-03-10 11:03:30.572 WARN     - Create a new (N) folder using \Output_ddMMyyhhmmss format. 
        +2025-03-10 11:03:30.572 WARN       You can delete the new folder manually in the future 
        +2025-03-10 11:03:31.954 INFO    Output folder Console input: d 
        +2025-03-10 11:03:32.118 WARN    Deleted C:\temp\log scout\Test 2\output\ and its contents 
        +2025-03-10 11:03:32.126 INFO    Output path: C:\temp\log scout\Test 2\output\ 
        +2025-03-10 11:03:32.126 INFO    Error  path is C:\temp\log scout\Test 2\output\internal\ 
        +2025-03-10 11:03:32.168 INFO    Validating attributes for non-Powershell script files 
        +2025-03-10 11:03:32.648 INFO     
        +2025-03-10 11:03:32.656 INFO    Initiating diagnostics collection...  
        +2025-03-10 11:03:32.659 INFO    Please select one of the following scenarios:
        + 
        +2025-03-10 11:03:32.659 INFO     
        +2025-03-10 11:03:32.669 INFO    ID   Scenario 
        +2025-03-10 11:03:32.669 INFO    --   --------------- 
        +2025-03-10 11:03:32.677 INFO    0    Basic 
        +2025-03-10 11:03:32.679 INFO    1    GeneralPerf 
        +2025-03-10 11:03:32.679 INFO    2    DetailedPerf 
        +2025-03-10 11:03:32.687 INFO    3    Replication 
        +2025-03-10 11:03:32.689 INFO    4    AlwaysOn 
        +2025-03-10 11:03:32.689 INFO    5    NetworkTrace 
        +2025-03-10 11:03:32.689 INFO    6    Memory 
        +2025-03-10 11:03:32.689 INFO    7    DumpMemory 
        +2025-03-10 11:03:32.697 INFO    8    WPR 
        +2025-03-10 11:03:32.699 INFO    9    Setup 
        +2025-03-10 11:03:32.699 INFO    10   BackupRestore 
        +2025-03-10 11:03:32.699 INFO    11   IO 
        +2025-03-10 11:03:32.699 INFO    12   LightPerf 
        +2025-03-10 11:03:32.709 INFO     
        +2025-03-10 11:03:32.709 WARN    Type one or more Scenario IDs (separated by '+') for which you want to collect diagnostic data. Then press Enter 
        +2025-03-10 11:04:02.077 INFO    Scenario Console input: 1+4+10 
        +2025-03-10 11:04:02.208 INFO    The scenarios selected are: 'GeneralPerf AlwaysOn BackupRestore Basic' 
        +2025-03-10 11:04:02.665 INFO    Discovered the following SQL Server instance(s)
        + 
        +2025-03-10 11:04:02.665 INFO     
        +2025-03-10 11:04:02.676 INFO    ID  SQL Instance Name 
        +2025-03-10 11:04:02.678 INFO    --  ---------------- 
        +2025-03-10 11:04:02.679 INFO    0    DbServerMachine 
        +2025-03-10 11:04:02.679 INFO    1    DbServerMachine\SQL2014 
        +2025-03-10 11:04:02.686 INFO    2    DbServerMachine\SQL2017 
        +2025-03-10 11:04:02.686 INFO    3    DbServerMachine\SQL2019 
        +2025-03-10 11:04:02.686 INFO     
        +2025-03-10 11:04:02.686 WARN    Enter the ID of the SQL instance for which you want to collect diagnostic data. Then press Enter 
        +2025-03-10 11:04:11.899 INFO    SQL Instance Console input: 3 
        +2025-03-10 11:04:11.911 INFO    You selected instance 'DbServerMachine\SQL2019' to collect diagnostic data.  
        +2025-03-10 11:04:12.022 INFO    Confirmed that MYDOMAIN\Joseph has VIEW SERVER STATE on SQL Server Instance 'DbServerMachine\SQL2019' 
        +2025-03-10 11:04:12.022 INFO    Confirmed that MYDOMAIN\Joseph has ALTER ANY EVENT SESSION on SQL Server Instance 'DbServerMachine\SQL2019' 
        +2025-03-10 11:04:12.735 WARN    At least one of the selected 'GeneralPerf AlwaysOn BackupRestore Basic' scenarios collects Xevent traces 
        +2025-03-10 11:04:12.751 WARN    The service account 'NT Service\MSSQL$SQL2019' for SQL Server instance 'DbServerMachine\SQL2019' must have write/modify permissions on the 'C:\temp\log scout\Test 2\output\' folder 
        +2025-03-10 11:04:12.751 WARN    The easiest way to validate write permissions on the folder is to test-run SQL LogScout for 1-2 minutes and ensure an *.XEL file exists that you can open and read in SSMS 
        +2025-03-10 11:04:15.822 INFO    Access verification Console input: y 
        +2025-03-10 11:04:15.841 INFO    LogmanConfig.txt copied to  C:\temp\log scout\Test 2\output\internal\LogmanConfig.txt 
        +2025-03-10 11:04:15.922 INFO    Basic collectors will execute on shutdown 
        +2025-03-10 11:04:15.934 INFO    Collecting logs for 'GeneralPerf' scenario 
        +2025-03-10 11:04:15.964 INFO    Executing Collector: Perfmon 
        +2025-03-10 11:04:17.055 INFO    Executing Collector: Xevent_Core_AddSession 
        +2025-03-10 11:04:17.088 INFO    Executing Collector: Xevent_General_AddSession 
        +2025-03-10 11:04:19.130 INFO    Executing Collector: Xevent_General_Target 
        +2025-03-10 11:04:19.152 INFO    Executing Collector: Xevent_General_Start 
        +2025-03-10 11:04:19.214 INFO    Executing Collector: ExistingProfilerXeventTraces 
        +2025-03-10 11:04:21.313 INFO    Executing Collector: HighCPU_perfstats 
        +2025-03-10 11:04:21.364 INFO    Executing Collector: SQLServerPerfStats 
        +2025-03-10 11:04:23.441 INFO    Executing Collector: SQLServerPerfStatsSnapshotStartup 
        +2025-03-10 11:04:23.492 INFO    Executing Collector: QueryStore 
        +2025-03-10 11:04:25.552 INFO    Executing Collector: TempDBAnalysis 
        +2025-03-10 11:04:25.601 INFO    Executing Collector: linked_server_config 
        +2025-03-10 11:04:25.708 INFO    Collecting logs for 'AlwaysOn' scenario 
        +2025-03-10 11:04:25.740 INFO    Executing Collector: AlwaysOnDiagScript 
        +2025-03-10 11:04:25.788 INFO    Executing Collector: Xevent_CoreAddSesion 
        +2025-03-10 11:04:25.809 INFO    Executing Collector: Xevent_AlwaysOn_Data_Movement 
        +2025-03-10 11:04:27.853 INFO    Executing Collector: AlwaysOn_Data_Movement_target 
        +2025-03-10 11:04:27.881 INFO    Executing Collector: AlwaysOn_Data_Movement_Start 
        +2025-03-10 11:04:27.922 INFO    Executing Collector: AlwaysOnHealthXevent 
        +2025-03-10 11:04:28.007 INFO    Collecting logs for 'BackupRestore' scenario 
        +2025-03-10 11:04:28.023 INFO    Executing Collector: Xevent_BackupRestore_AddSession 
        +2025-03-10 11:04:30.070 INFO    Executing Collector: EnableTraceFlag 
        +2025-03-10 11:04:30.088 INFO    Executing collector: SetVerboseSQLVSSWriterLog
        +2025-03-10 11:04:30.159 WARN    To enable SQL VSS VERBOSE loggging, the SQL VSS Writer service must be restarted now and when shutting down data collection. This is a very quick process.
        +2025-03-10 11:04:36.697 INFO    Console Input: n 
        +2025-03-10 11:04:36.705 INFO    You have chosen not to restart SQLWriter Service. No verbose logging will be collected for SQL VSS Writer (2019 or later)
        +2025-03-10 11:04:36.737 INFO    Executing Collector: VSSAdmin_Providers 
        +2025-03-10 11:04:36.778 INFO    Executing Collector: VSSAdmin_Shadows 
        +2025-03-10 11:04:37.832 INFO    Executing Collector: VSSAdmin_Shadowstorage 
        +2025-03-10 11:04:37.873 INFO    Executing Collector: VSSAdmin_Writers 
        +2025-03-10 11:04:37.924 INFO    Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue. 
        +2025-03-10 11:04:37.924 INFO    You can type 'StopFile' and wait for the presence of a '\internal\logscout.stop' file to automatically end the diagnostics collection.
        +2025-03-10 11:04:43.012 INFO    StopCollection Console input: stop 
        +2025-03-10 11:04:43.014 INFO    Shutting down the collector 
        +2025-03-10 11:04:43.032 INFO    Executing shutdown command: Xevents_Stop 
        +2025-03-10 11:04:43.073 INFO    Executing shutdown command: Xevents_Alwayson_Data_Movement_Stop 
        +2025-03-10 11:04:43.098 INFO    Executing shutdown command: Disable_BackupRestore_Trace_Flags
        +2025-03-10 11:04:43.145 INFO    Executing shutdown command: PerfmonStop 
        +2025-03-10 11:04:46.228 INFO    Executing shutdown command: KillActiveLogscoutSessions 
        +2025-03-10 11:04:47.277 INFO    Collecting logs for 'Basic' scenario 
        +2025-03-10 11:04:47.298 INFO    Executing Collector: TaskListVerbose 
        +2025-03-10 11:04:47.339 INFO    Executing Collector: TaskListServices 
        +2025-03-10 11:04:47.407 INFO    Executing Collector: FLTMC_Filters 
        +2025-03-10 11:04:47.464 INFO    Executing Collector: FLTMC_Instances 
        +2025-03-10 11:04:47.533 INFO    Executing Collector: SystemInfo_Summary 
        +2025-03-10 11:04:47.618 INFO    Executing Collector: MiscDiagInfo 
        +2025-03-10 11:04:47.681 INFO    Executing Collector: SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel 
        +2025-03-10 11:04:50.501 INFO    Executing Collector: PolybaseLogs 
        +2025-03-10 11:04:50.533 INFO    Executing Collector: SQLAssessmentAPI 
        +2025-03-10 11:05:09.554 INFO    Executing Collector: UserRights 
        +2025-03-10 11:05:12.266 INFO    Executing Collector: RunningDrivers 
        +2025-03-10 11:05:14.217 INFO    Executing Collector: PowerPlan 
        +2025-03-10 11:05:14.308 INFO    Executing Collector: WindowsHotfixes 
        +2025-03-10 11:05:16.694 INFO    Executing Collector: GetEventLogs 
        +2025-03-10 11:05:16.707 INFO    Gathering Application EventLog in TXT and CSV format   
        +2025-03-10 11:05:23.218 INFO       Produced 10000 records in the EventLog 
        +2025-03-10 11:05:29.011 INFO       Produced 20000 records in the EventLog 
        +2025-03-10 11:05:35.914 INFO       Produced 30000 records in the EventLog 
        +2025-03-10 11:05:41.975 INFO       Produced 39129 records in the EventLog 
        +2025-03-10 11:05:41.975 INFO    Application EventLog in TXT and CSV format completed! 
        +2025-03-10 11:05:41.975 INFO    Gathering System EventLog in TXT and CSV format   
        +2025-03-10 11:05:50.913 INFO       Produced 10000 records in the EventLog 
        +2025-03-10 11:05:59.494 INFO       Produced 20000 records in the EventLog 
        +2025-03-10 11:06:04.839 INFO       Produced 26007 records in the EventLog 
        +2025-03-10 11:06:04.842 INFO    System EventLog in TXT and CSV format completed! 
        +2025-03-10 11:06:04.879 INFO    Executing Collector: PerfStatsSnapshotShutdown
        +2025-03-10 11:06:04.888 INFO    Executing collector: GetSQLVSSWriterLog
        +2025-03-10 11:06:04.900 INFO    SQLWriter Service has been restarted
        +2025-03-10 11:06:04.917 INFO    Waiting 3 seconds to ensure files are written to and closed by any program including anti-virus... 
        +2025-03-10 11:06:08.518 INFO    Ending data collection 
        +2025-03-10 11:06:08.533 WARN    Launching cleanup and exit routine... please wait 
        +2025-03-10 11:06:13.780 INFO    Thank you for using SQL LogScout! 
        +
        +Checking for console execution errors logged into .\##STDERR.LOG...
        +Removed .\##STDERR.LOG which was 0 bytes

        Test Suite

        The test suite is intended to be used by developers. The set of tests will grow over time. To run a test, simply execute the @@ -1537,9 +1673,9 @@

        Test Suite

        Execute overall test suite

        Here is an example of how to execute the entire test suite:

        -
        cd .\Bin\TestingInfrastructure 
        -.\ConsistentQualityTests.ps1 -ServerName <SQL Instance Name> -SqlNexusPath <PathToSQLNexusExe> -SqlNexusDb <SQLNexusDbName> -DoProcmonTest <$True/$False>
        +
        cd .\Bin\TestingInfrastructure 
        +.\ConsistentQualityTests.ps1 -ServerName <SQL Instance Name> -SqlNexusPath <PathToSQLNexusExe> -SqlNexusDb <SQLNexusDbName> -DoProcmonTest <$True/$False>

        The full test suite may take a about 2 hours to run and test all the scenarios.

        Parameters details used in above command:

        @@ -1572,12 +1708,12 @@

        Execute overall test suite

        - + :warning: WARNING - + Don’t close the Command prompt window or you may orphan some processes. @@ -1585,9 +1721,9 @@

        Execute overall test suite

        Examples of SQL LogScout Tests

        -
        cd TestingInfrastructure 
        -RunIndividualTest.bat
        +
        cd TestingInfrastructure 
        +RunIndividualTest.bat

        Sample testing output

        TEST: ExecutingCollectors Validation
         Status: SUCCESS
        @@ -1625,12 +1761,12 @@ 

        Script - + :warning: WARNING - + Do not close the Command Prompt or PowerShell window where SQL LogScout is running because this may leave a data collector running on your system. You can safely do so @@ -1645,12 +1781,12 @@

        Script script without any parameters or use the optional parameters.

        Example passing -ServerName which results in no prompt:

        -
        .\CleanupIncompleteShutdown.ps1 -ServerName "DbServerMachine\SQL2016"
        +
        .\CleanupIncompleteShutdown.ps1 -ServerName "DbServerMachine\SQL2016"

        To execute the script and be prompted for a server name, do the following:

        -
        powershell -File CleanupIncompleteShutdown.ps1
        +
        powershell -File CleanupIncompleteShutdown.ps1

        Here is a sample output:

        INFO    Created log file C:\Users\ADMINI~1\AppData\Local\Temp\2\##SQLLogScout_CleanupIncompleteShutdown_20241009T1750455751.log
         INFO    Log initialization complete!
        @@ -1679,5 +1815,79 @@ 

        Script Executing 'NetworkTraceStop'. It will stop network tracing initiated by SQLLogScout in case it was found to be running... Cleanup script execution completed. PS C:\SQL LogScout\Bin>

        +

        How +to connect to and collect data from Windows Internal Database (WID)

        +

        WID uses a modified version of SQL Server and has some limitations or +behaves differently. SQL LogScout has been adapted to support WID with +some lmitations:

        +
          +
        1. Doesn’t connect with encryption because WID doesn’t support +encryption (less of a concern since connection is local). You will get +an error message initially that a connection fails, but it would +eventually succeed to connect.
        2. +
        3. Cannot use the SQL LogScout GUI because an client alias must be +created. You can use command line only with ServerName specified +explicitly.
        4. +
        5. Might not collect WID errorlogs unless you create a specific +connection alias (see the steps +below)
        6. +
        +

        Steps to collect +data with SQL LogScout on WID

        +
          +
        1. Open Services app (services.msc) on Windows and find the +Windows Internal Database service

        2. +
        3. Under the General tab, find the Path to +executable and copy the WID instance name that appears after +the -S parameter. Most commonly it is +MSWIN8.SQLWID

        4. +
        5. Close Serivces app

        6. +
        7. Open SQL Client Network Utility (cliconfg.exe) and define an +alias to the custom WID named pipe +np:\\.\pipe\MICROSOFT##WID\tsql\query. Use the WiD instance +you found, as a name in Server alias. For example use +MSWIN8.SQLWID

          +
            +
          • Start->Run->Cliconfg.exe
          • +
          • Click Add to create a new alias.
          • +
          • In the Server alias field, enter the instance name you discovered in +prior steps: MSWIN8.SQLWID.
          • +
          • In the Network libraries section, select Named Pipes.
          • +
          • In the Pipe Name section, enter +\\.\pipe\MICROSOFT##WID\tsql\query
          • +
        8. +
        9. Alternatively, you can use SQL +Server Configuration Manager to create an alias. For more +information, see Create +or delete a server alias for use by a client and Aliases +- Named Pipes connections

        10. +
        11. Then run SQL LogScout with that alias. For example

          +
          .\SQL_LogScout.ps1 -ServerName "MSWIN8.SQLWID" -Scenario "GeneralPerf"
        12. +
        13. You will get connection errors when trying to connect with a ODBC +driver using encryption, but after a few attempts, an unencrypted +connection succeeds. The output may look like this:

          +
          2025-01-08 00:14:31.229 WARN    Could not connect to SQL Server
          +2025-01-08 00:14:31.229 ERROR   Function 'getSQLConnection' failed with error:  Exception calling "Open" with "0" argument(s): "ERROR [08001] [Microsoft][ODBC    Driver 17 for SQL Server]Encryption not supported on SQL Server.
          +ERROR [08001] [Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection
          +ERROR [01S00] [Microsoft][ODBC Driver 17 for SQL Server]Invalid connection string attribute" (line: 628, offset: 13, file:    C:\Tools\SQLLogScout\Bin\CommonFunctions.psm1)
          +2025-01-08 00:14:31.276 WARN    Could not connect to SQL Server
          +2025-01-08 00:14:31.276 ERROR   Function 'getSQLConnection' failed with error:  Exception calling "Open" with "0" argument(s): "ERROR [08001] [Microsoft][SQL    Server Native Client 11.0]Encryption not supported on SQL Server.
          +ERROR [08001] [Microsoft][SQL Server Native Client 11.0]Client unable to establish connection
          +ERROR [01S00] [Microsoft][SQL Server Native Client 11.0]Invalid connection string attribute" (line: 628, offset: 13, file:    C:\Tools\SQLLogScout\Bin\CommonFunctions.psm1)
          +2025-01-08 00:14:31.307 WARN    **********************************************************************
          +2025-01-08 00:14:31.323 WARN    *  SQL LogScout is switching to the classic SQL Server ODBC driver.
          +2025-01-08 00:14:31.323 WARN    *  Thus, this local connection is unencrypted to ensure it is successful
          +2025-01-08 00:14:31.323 WARN    *  To exit without collecting LogScout press Ctrl+C
          +2025-01-08 00:14:31.323 WARN    **********************************************************************
          +2025-01-08 00:14:37.489 INFO    Confirmed that WIN2022SQL1\Administrator has VIEW SERVER STATE on SQL Server Instance 'MSWIN8.SQLWID'
          +2025-01-08 00:14:37.489 INFO    Confirmed that WIN2022SQL1\Administrator has ALTER ANY EVENT SESSION on SQL Server Instance 'MSWIN8.SQLWID'
          +2025-01-08 00:14:37.489 INFO    Confirmed that SQL Server Instance WIDAlias can write Extended Event Session Target at    C:\Tools\SQLLogScout\output\WIDAlias_20250108T0014373961_xevent_LogScout_target_test.xel
        14. +
        diff --git a/SQL LogScout/Bin/SQLDumpHelper.ps1 b/SQL LogScout/Bin/SQLDumpHelper.ps1 index 03cfa30..267305a 100644 --- a/SQL LogScout/Bin/SQLDumpHelper.ps1 +++ b/SQL LogScout/Bin/SQLDumpHelper.ps1 @@ -405,7 +405,7 @@ $MainBodyBlock = while($OutputFolder -eq "" -or !(Test-Path -Path $OutputFolder)) { Write-Host "" - Write-Host "Where would your like the memory dump stored (output folder)?" -ForegroundColor Yellow + Write-Host "Where would you like the memory dump stored (output folder)?" -ForegroundColor Yellow $OutputFolder = Read-Host "Enter an output folder with no quotes (e.g. C:\MyTempFolder or C:\My Folder)" -CustomLogMessage "Dump Output Folder console input:" if ($OutputFolder -eq "" -or !(Test-Path -Path $OutputFolder)) { diff --git a/SQL LogScout/Bin/SQLLogScoutPs.ps1 b/SQL LogScout/Bin/SQLLogScoutPs.ps1 index c749c9d..6e08c30 100644 --- a/SQL LogScout/Bin/SQLLogScoutPs.ps1 +++ b/SQL LogScout/Bin/SQLLogScoutPs.ps1 @@ -81,8 +81,8 @@ param [string]$global:perfmon_active_counter_file = "LogmanConfig.txt" [string]$global:restart_sqlwriter = "" [bool]$global:perfmon_counters_restored = $false -[string]$NO_INSTANCE_NAME = "no_instance_found" -[string]$global:sql_instance_conn_str = $NO_INSTANCE_NAME #setting the connection sting to $NO_INSTANCE_NAME initially +[string]$global:NO_INSTANCE_NAME = "_no_instance_found_" +[string]$global:sql_instance_conn_str = $global:NO_INSTANCE_NAME #setting the connection sting to $global:NO_INSTANCE_NAME initially [System.Collections.ArrayList]$global:processes = New-Object -TypeName System.Collections.ArrayList [System.Collections.ArrayList] $global:ScenarioChoice = @() [bool] $global:stop_automatically = $false @@ -114,6 +114,8 @@ param [String]$global:dump_helper_outputfolder = "" [int] $global:dump_helper_count = 1 [int] $global:dump_helper_delay = 0 +[bool] $global:is_connection_encrypted = $true +[string] $global:stopFilePath = "logscout.stop" #constants [string] $global:BASIC_NAME = "Basic" @@ -275,32 +277,80 @@ $global:SQLInstanceType = @{ "DefaultInstanceHostName" = 3 } -#=======================================Start of \OUTPUT and \INTERNAL directories and files Section -#======================================== START of Process management section -if ($PSVersionTable.PSVersion.Major -gt 4) { Import-Module .\GUIHandler.psm1 } -Import-Module .\CommonFunctions.psm1 -#=======================================End of \OUTPUT and \INTERNAL directories and files Section -#======================================== END of Process management section +#=======================================Start of Module Import secion +#======================================== START of Console LOG SECTION +Import-Module .\LoggingFacility.psm1 -Force -Global +#======================================== END of Console LOG SECTION -#======================================== START OF NETNAME + INSTANCE SECTION - Instance Discovery -Import-Module .\InstanceDiscovery.psm1 -#======================================== END OF NETNAME + INSTANCE SECTION - Instance Discovery +#======================================== Import-Module replace should happen before any import-module calls +#Remove Import-Module if it is already custom loaded. +Remove-Item -Path Function:\Import-Module -ErrorAction SilentlyContinue + +Import-Module .\CustomImportModule.psm1 -Force -Global +#======================================== END of Import-Module replace should happen before any import-module calls + +# Get all files starting with SQLScript and ending with .psm1 +$scriptFiles = ( 'SQLScript_AlwaysOnDiagScript', +'SQLScript_ChangeDataCapture', +'SQLScript_Change_Tracking', +'SQLScript_FullTextSearchMetadata', +'SQLScript_HighCPU_perfstats', +'SQLScript_High_IO_Perfstats', +'SQLScript_linked_server_config', +'SQLScript_MiscDiagInfo', +'SQLScript_NeverEndingQuery_perfstats', +'SQLScript_ProfilerTraces', +'SQLScript_QueryStore', +'SQLScript_Repl_Metadata_Collector', +'SQLScript_SQL_Server_Mem_Stats', +'SQLScript_SQL_Server_PerfStats', +'SQLScript_SQL_Server_PerfStats_Snapshot', +'SQLScript_SSB_DbMail_Diag', +'SQLScript_TempDB_and_Tran_Analysis', +'SQLScript_xevent_AlwaysOn_Data_Movement', +'SQLScript_xevent_backup_restore', +'SQLScript_xevent_core', +'SQLScript_xevent_detailed', +'SQLScript_xevent_general', +'SQLScript_xevent_servicebroker_dbmail', +'SqlVersionsTable', +'InstanceDiscovery', +'SQLLogScoutPs', +'Confirm-FileAttributes', +#'LoggingFacility', #should be imported first to load write functions +'InstanceDiscovery', +'CommonFunctions' +#'GUIHandler' #will be imported separately since it requires PS 4 and up to function +) +# Import each module +foreach ($file in $scriptFiles) { + try { + Write-LogDebug "Processing $file" + $fileName = "$file.psm1" + $fileFullName = "$PSScriptRoot\$fileName" -#======================================== START of Console LOG SECTION -Import-Module .\LoggingFacility.psm1 -#======================================== END of Console LOG SECTION + Write-LogDebug "Importing file : $fileFullName" -#======================================== START of File Attribute Validation SECTION -Import-Module .\Confirm-FileAttributes.psm1 -#======================================== END of File Attribute Validation SECTION + Import-Module -Name $fileFullName -Force -ErrorAction Stop -#======================================== START of File Attribute Validation SECTION -Import-Module .\SQLLogScoutPs.psm1 -DisableNameChecking -#======================================== END of File Attribute Validation SECTION + Write-LogDebug "Imported module: $($fileName)" + } catch { + Write-LogWarning $("="*75) + Write-LogWarning "Please check if SQL LogScout module files are missing, quarantined or locked by" + Write-LogWarning "an anti-virus program or another service/application." + Write-LogWarning $("="*75) + Write-LogError "Failed to import module: $($fileName). Error: $_" + exit + } +} + +#Importing GUIHandler separately and only if PS version is 4 and up +if ($PSVersionTable.PSVersion.Major -gt 4) { Import-Module .\GUIHandler.psm1 } +#=======================================End of Module Import secion function PrintHelp ([string]$ValidArguments ="", [int]$index=777, [bool]$brief_help = $true) { Try diff --git a/SQL LogScout/Bin/SQLLogScoutPs.psm1 b/SQL LogScout/Bin/SQLLogScoutPs.psm1 index 5ff71ed..f7aecb6 100644 --- a/SQL LogScout/Bin/SQLLogScoutPs.psm1 +++ b/SQL LogScout/Bin/SQLLogScoutPs.psm1 @@ -8,13 +8,10 @@ Import-Module .\CommonFunctions.psm1 #=======================================End of \OUTPUT and \INTERNAL directories and files Section #======================================== END of Process management section - #======================================== START OF NETNAME + INSTANCE SECTION - Instance Discovery Import-Module .\InstanceDiscovery.psm1 #======================================== END OF NETNAME + INSTANCE SECTION - Instance Discovery - - #======================================== START of Console LOG SECTION Import-Module .\LoggingFacility.psm1 #======================================== END of Console LOG SECTION @@ -27,18 +24,16 @@ Import-Module .\Confirm-FileAttributes.psm1 Import-Module .\SqlVersionsTable.psm1 #======================================== END of TextFile Replacement modules - function InitAppVersion() { $major_version = "6" - $minor_version = "24" - $build = "11" - $revision = "02" + $minor_version = "25" + $build = "04" + $revision = "25" $global:app_version = $major_version + "." + $minor_version + "." + $build + "." + $revision Write-LogInformation "SQL LogScout version: $global:app_version" } - function GetWindowsHotfixes () { Write-LogDebug "inside" $MyInvocation.MyCommand @@ -220,7 +215,7 @@ function GetEventLogs($server) $sbWriteLogProcess = { - [string]$TimeGenerated = $_.TimeGenerated.ToString("MM/dd/yyyy hh:mm:ss tt") + [string]$TimeGenerated = $_.TimeGenerated.ToString((Get-Culture)) [string]$EntryType = $_.EntryType.ToString() [string]$MachineName = $_.MachineName.ToString() [string]$EventID = $_.EventID.ToString() @@ -664,36 +659,152 @@ function GetMissingSQLMsiMspFiles() HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem } } -<# -it seems this funciton is never referenced in the code... commenting it for now. -function MSDiagProcsCollector() + +function GetInstalledPrograms { Write-LogDebug "Inside" $MyInvocation.MyCommand - Import-Module .\SQLScript_MSDiagProcs.psm1 + $collector_name = "InstalledPrograms" + Write-LogInformation "Executing Collector: $collector_name" try { - if($global:sql_instance_service_status -eq "Running") + ##create output filenames using the path + servername + date and time + $partial_output_file_name = CreatePartialOutputFilename ($server) + + $output_file = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name $collector_name -needExtraQuotes $false + + # get the computer platform (x86 or x64). Used to determine which registry path to search for installed programs + $Platform = GetComputerPlatform + + # Define registry paths to search for installed programs + $registryPaths = @("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") + if ($Platform -eq "x64") { + $registryPaths += "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" + } + + # Create an array to store program details + $programs = @() + + foreach ($path in $registryPaths) { + # Get all subkeys under the uninstall registry path + $subKeys = Get-ChildItem -Path $path -ErrorAction SilentlyContinue + foreach ($subKey in $subKeys) { + $program = [PSCustomObject]@{ + DisplayName = [string]$null + DisplayVersion = [string]$null + Publisher = [string]$null + ProductCode = [string]$null + } + + # Get the values under the subkey + $values = Get-ItemProperty -Path $subKey.PSPath -ErrorAction SilentlyContinue + if ($values) { + # Map registry values to program properties + if ($values.DisplayName) { + $program.DisplayName = [string]$values.DisplayName + } + if ($values.DisplayVersion) { + $program.DisplayVersion = [string]$values.DisplayVersion + } + if ($values.Publisher) { + $program.Publisher = [string]$values.Publisher + } + if ($values.PSChildName -and $values.WindowsInstaller -eq 1) { + $program.ProductCode = [string]$values.PSChildName + } + + # Add the program to the list if it has a valid DisplayName + if ($program.DisplayName) { + $programs += $program + } + } + } + } + + # Sort programs by DisplayName + $programs = $programs | Sort-Object -Property DisplayName + + # create a string builder object to hold the output text + [System.Text.StringBuilder]$strOutputText = New-Object -TypeName System.Text.StringBuilder + + + # Add rowset identifier information to the output text + [void]$strOutputText.Append("-- InstalledPrograms --`r`n") + + # Output the header + $namePad = 110 + $versionPad = 20 + $publisherPad = 64 + $productCodePad = 40 + [void]$strOutputText.Append( "Name".PadRight($namePad) + "Version".PadRight($versionPad) + "Publisher".PadRight($publisherPad) + "Windows_Installer_Product_Code" + "`r`n") + [void]$strOutputText.Append("-" * $($namePad-1) + " " + "-"* $($versionPad-1) + " "+ "-" * $($publisherPad-1) + " " + "-" * $($productCodePad-1) + "`r`n") + + + # Output program details + foreach ($program in $programs) { - #msdiagprocs.sql - #the output is potential errors so sent to error file - $collector_name = MSDiagProcs_Query #"MSDiagProcs" - Start-SQLCmdProcess -collector_name $collector_name -input_script_name $collector_name + + #if $program.DisplayName is null or empty, we skip this program and go to the next element in $programs + if (-not [string]::IsNullOrWhiteSpace($program.DisplayName)) + { + # Format the DisplayName to remove non-alphanumeric characters and limit length + $program.DisplayName = $program.DisplayName -replace '[^\u0020-\u007E\u00A0-\u024F]', '' # Allow ASCII characters 32 to 127 + + if ($program.DisplayName.Length -gt $namePad) { + $program.DisplayName = $program.DisplayName.Substring(0, $namePad) + } + + # Clean up the Publisher column to remove charactes different from characters included in the Unicode ranges for Latin-1 Supplement, Latin Extended-A, and Latin Extended-B + $cleanPublisher = if ($null -ne $program.Publisher) {$program.Publisher -replace '[^\u0020-\u007E\u00A0-\u024F]', '*'} else {" "} + + if ($cleanPublisher.Length -gt $publisherPad) { + $cleanPublisher = $cleanPublisher.Substring(0, $publisherPad) + } + + # Format the output text + $displayVersion = if ($null -ne $program.DisplayVersion) { $program.DisplayVersion } else { " " } + $productCode = if ($null -ne $program.ProductCode) { $program.ProductCode } else { " " } + + # append the program details to the string builder object + [void]$strOutputText.Append( ($program.DisplayName.PadRight($namePad) + + $displayVersion.PadRight($versionPad) + + $cleanPublisher.PadRight($publisherPad) + + $productCode.PadRight($productCodePad))+ "`r`n") + } + # if $program.DisplayName is null or empty, we skip this program and go to the next element in $programs + else + { + continue + } + + + # write the output to file when it reaches a certain length + # this is to avoid multiple small I/Os and also to avoid the string builder object to grow too big in memory + if ($strOutputText.Length -gt 32768) + { + $outputContent = $strOutputText.ToString().TrimEnd("`r", "`n") + Add-Content -Path $output_file -Value $outputContent -Encoding Unicode + #reset the string builder object + [void]$strOutputText.Clear() + } } - else + + # Final write to file + if ($strOutputText.Length -gt 0) { - Write-LogInformation "SQL Server service is not running. Skipping $collector_name collector" + $finaloutputContent = $strOutputText.ToString().TrimEnd("`r`n") + Add-Content -Path $output_file -Value $finaloutputContent -Encoding Unicode } - } - catch { + } + catch + { HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem - return } - } -#> + + function GetXeventsGeneralPerf() { Write-LogDebug "Inside" $MyInvocation.MyCommand @@ -702,6 +813,7 @@ function GetXeventsGeneralPerf() Import-Module .\SQLScript_xevent_core.psm1 Import-Module .\SQLScript_xevent_general.psm1 + try { ##create output filenames using the path + servername + date and time @@ -1096,7 +1208,7 @@ function GetAlwaysOnHealthXel # get the ERRORLOG path from the registry - $vLogPath = GetLogPathFromReg -server $server -logType "ERRORLOG" + $vLogPath = GetLogPathFromReg -server $server -logType "LOG" if ($vLogPath -eq $false) { @@ -1623,7 +1735,7 @@ function GetPerfStatsSnapshot ([string] $TimeOfCapture="Startup") Write-LogDebug "Inside" $MyInvocation.MyCommand Import-Module .\SQLScript_SQL_Server_PerfStats_Snapshot.psm1 - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of PerfStats shutdown collector" return @@ -3076,7 +3188,8 @@ function GetIPandDNSConfig $hostname = $global:host_name - try{ + try + { $partial_output_file_name = CreatePartialOutputFilename ($server) $partial_error_output_file_name = CreatePartialErrorOutputFilename($server) @@ -3095,36 +3208,50 @@ function GetIPandDNSConfig $collector_name = "NetTCPandUDPConnections" Write-LogInformation "Executing Collector: $collector_name" - $output_file = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name $collector_name -needExtraQuotes $false - $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false - - # Get-NetTCPConnection and Get-NetUDPEndpoint are available in Windows 8 / Windows Server 2012 and later versions. - # concatenate the output of Get-NetTCPConnection and the header string and write it to the output file. Get-NetTCPConnection prints its output to a new line thus the need to contat the variables. - $str_NexusFriendlyHeader = "-- net_tcp_connection --" - $netTcpConnectionOutput = Get-NetTCPConnection | Select-Object Local*, Remote*, State, @{n="ProcessID";e={$_.OwningProcess}}, @{n="ProcessName";e={(Get-Process -Id $_.OwningProcess).ProcessName}} | Format-Table -Auto | Out-String - ($str_NexusFriendlyHeader + "" + $netTcpConnectionOutput) | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 + #TODO: + # Get the total RAM size in GB + $TotalRAM = GetTotalRAMSize + $CPUCount = GetCoutLogicalCPUs + + #if RAM > 2 TB CPUs count > 128 CPUs skip this collector + if (($TotalRAM -ge 2048) -or ($CPUCount -ge 128)) + { + Write-LogWarning "Skipping NetTCPandUDPConnections: total RAM size > 2 TB or CPU count > 128 and the collector may take a long time to complete. Collect manually." + } + else + { + + $output_file = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name $collector_name -needExtraQuotes $false + $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false + + # Get-NetTCPConnection and Get-NetUDPEndpoint are available in Windows 8 / Windows Server 2012 and later versions. + # concatenate the output of Get-NetTCPConnection and the header string and write it to the output file. Get-NetTCPConnection prints its output to a new line thus the need to contat the variables. + $str_NexusFriendlyHeader = "-- net_tcp_connection --" + $netTcpConnectionOutput = Get-NetTCPConnection | Select-Object Local*, Remote*, State, @{n="ProcessID";e={$_.OwningProcess}} | Format-Table -Auto | Out-String + ($str_NexusFriendlyHeader + "" + $netTcpConnectionOutput) | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 - # concatenate the output of Get-NetUDPEndpoint and the header string and write it to the output file. Get-NetUDPEndpoint prints its output to a new line thus the need to contat the variables. - # Get-NetUDPEndpoint is available in Windows 8 / Windows Server 2012 and later versions. - $str_NexusFriendlyHeader = "-- net_udp_endpoint --" - $netUdpConnectionOutput = Get-NetUDPEndpoint | Select-Object Local*, @{n="ProcessID";e={$_.OwningProcess}}, @{n="ProcessName";e={(Get-Process -Id $_.OwningProcess).ProcessName}} | Format-Table -Auto | Out-String - ($str_NexusFriendlyHeader + "" + $netUdpConnectionOutput) | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 - $collector_name = "DNSClientInfo" - Write-LogInformation "Executing Collector: $collector_name" - $output_file = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name $collector_name -needExtraQuotes $false - $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false - $str_NexusFriendlyHeader = "-- dns_client --" - $str_NexusFriendlyHeader | Out-file -FilePath $output_file -Encoding ascii - Get-DnsClient | Select-Object Interface*, Connection*, RegisterThisConnectionsAddress, UseSuffixwhenRegistering | Format-Table -Auto | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 + # concatenate the output of Get-NetUDPEndpoint and the header string and write it to the output file. Get-NetUDPEndpoint prints its output to a new line thus the need to contat the variables. + # Get-NetUDPEndpoint is available in Windows 8 / Windows Server 2012 and later versions. + $str_NexusFriendlyHeader = "-- net_udp_endpoint --" + $netUdpConnectionOutput = Get-NetUDPEndpoint | Select-Object Local*, @{n="ProcessID";e={$_.OwningProcess}} | Format-Table -Auto | Out-String + ($str_NexusFriendlyHeader + "" + $netUdpConnectionOutput) | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 - $str_NexusFriendlyHeader = "-- dns_client_cache --" - $str_NexusFriendlyHeader | Out-file -FilePath $output_file -Encoding ascii -Append - Get-DnsClientCache | Select-Object Entry, RecordName, RecordType, Status, Section, TimeToLive, DataLength, Data | Format-Table -Auto | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 + $collector_name = "DNSClientInfo" + Write-LogInformation "Executing Collector: $collector_name" + $output_file = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name $collector_name -needExtraQuotes $false + $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false + $str_NexusFriendlyHeader = "-- dns_client --" + $str_NexusFriendlyHeader | Out-file -FilePath $output_file -Encoding ascii + Get-DnsClient | Select-Object Interface*, Connection*, RegisterThisConnectionsAddress, UseSuffixwhenRegistering | Format-Table -Auto | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 + $str_NexusFriendlyHeader = "-- dns_client_cache --" + $str_NexusFriendlyHeader | Out-file -FilePath $output_file -Encoding ascii -Append + Get-DnsClientCache | Select-Object Entry, RecordName, RecordType, Status, Section, TimeToLive, DataLength, Data | Format-Table -Auto | Out-File -Append -FilePath $output_file -Encoding ascii -Width 100000 + } } catch { @@ -3136,125 +3263,204 @@ function GetSQLInstanceNameByPortNo($server) { Write-LogDebug "Inside" $MyInvocation.MyCommand - # If User Passed the SQL Instance Name in the form of Ip Address,Port Number + try + { + + # prepare $Result object to return to caller + $resultInstObject = [PSCustomObject]@{ + InstanceName = "" + Type = $global:SQLInstanceType["StartingValue"]} + + $matchFound = $false - $commaPos = $server.IndexOf(",") + 1 - $portno = $server.Substring($commaPos, $server.Length - $commaPos) - $Result= "" + # Check whether there's a comma in the server string, which would indicate a port number is also passed + # If there's no comma, then the server string is just the instance name or an IP address. If IP address only, we'll connect to default instance + if ($server -notmatch ",") + { + Write-LogDebug "No port found in server name. Using $server" + $instance_name_object = Get-InstanceNameObject -NetnamePlusInstance $server + return $instance_name_object + } - [string]$PortString = $portno - [Int32]$portcheck = $null - #if no port is present, just use the instance name and return out of here - if ([Int32]::TryParse($PortString,[ref]$portcheck)) - { - $Result = @() - } - else - { - $instance_name_object = Get-InstanceNameObject -NetnamePlusInstance $selectInstanceName - $Result = $instance_name_object.InstanceName - return $Result; - } + # If User Passed the SQL Instance Name in the form of Ip Address,Port Number then extract the port number + $commaPos = $server.IndexOf(",") + 1 + [string]$portno = $server.Substring($commaPos, $server.Length - $commaPos) + + [Int32]$portInteger = $null - #Get all the registry keys where an instance name is present using "MSSQL" and Property like "(default)" to check TCP/IP Sockets - $InstRegKeys = Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server' | - Where-Object {$_.Name -like '*MSSQL*' -and $_.Property -like "(default)"} | - Select-Object PSChildName + # If the port number is not a valid integer, log an error and return null + if (-not [Int32]::TryParse($portno, [ref]$portInteger)) + { + Write-LogError "Invalid port number: $portno. Expected a valid integer." + return $null + } + Write-LogDebug "The port number is $portno" -DebugLogLevel 3 - foreach ($key in $InstRegKeys) - { - #first extract the instance name from the reg key (e.g. get the part after the . in "MSSQL14.MYSQL2017") - $InstanceName = $key.PSChildName.Substring($key.PSChildName.IndexOf(".")+1) - #build the reg key in the form HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL15.MYSQL2019\MSSQLServer\SuperSocketNetLib\Tcp - $tcpKey = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\" + $key.PSChildName + "\MSSQLServer\SuperSocketNetLib\Tcp" + # Get all the registry keys where an instance name is present using "MSSQL" and Property like "(default)" to check TCP/IP Sockets + $InstancesInReg = Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server' -ErrorAction SilentlyContinue | + Where-Object {$_.Name -like '*MSSQL*' -and $_.Property -like "(default)"} | + Select-Object -ExpandProperty PSChildName - Write-LogDebug "PATH: $tcpKey" -DebugLogLevel 4 + if (-not $InstancesInReg) { + Write-LogError "No SQL Server instances found in the registry." + return $null + } - if (Test-Path -Path $tcpKey) + Write-LogDebug "Found these instances in the registry: $InstancesInReg" -DebugLogLevel 3 + + # Go through each instance in the registry + foreach ($InstKey in $InstancesInReg) { - #check if TCP/IP Sockets is enabled - $tcpEnabled = Get-ItemProperty -Path $tcpKey | Select-Object -Property Enabled + # Extract the instance name from the reg key (e.g. get the part after the . in "MSSQL14.MYSQL2017") + $InstanceName = $InstKey.Substring($InstKey.IndexOf(".") + 1) - #if enabled, go through ports - if ($tcpEnabled.Enabled -eq "1") - { + # Build the reg key in the form HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstKey\MSSQLServer\SuperSocketNetLib\Tcp + $tcpKey = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstKey\MSSQLServer\SuperSocketNetLib\Tcp" - foreach ($Port in (Get-ItemProperty -Path ($tcpKey+"\IP*") | Select-Object TcpPort, TcpDynamicPorts)) - { - if ([String]::IsNullOrWhiteSpace($portno) -ne $true) - { - Write-LogDebug "Comparing port=$portno to dynamic=$($Port.TcpDynamicPorts) or static=$($Port.TcpPort)" -DebugLogLevel 4 + Write-LogDebug "TCP key for instance '$InstanceName' is $tcpKey" -DebugLogLevel 4 + + # Check if the TCP key exists + if (Test-Path -Path $tcpKey) + { + # Check if TCP/IP Sockets is enabled + $tcpEnabled = Get-ItemProperty -Path $tcpKey -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Enabled - if ( (($Port.TcpDynamicPorts) -eq $portno) -or (($Port.TcpPort) -eq $portno) ) + # If enabled, go through ports + if ($tcpEnabled -eq "1") + { + $Ports = Get-ItemProperty -Path "$tcpKey\IP*" -ErrorAction SilentlyContinue | Select-Object TcpPort, TcpDynamicPorts + foreach ($port in $Ports) { - $Result = $InstanceName + + # Skip if the port is not set (0 or null) + if ([string]::IsNullOrWhiteSpace($port.TcpDynamicPorts) -or ($port.TcpDynamicPorts -eq "0") -and ([string]::IsNullOrWhiteSpace($port.TcpPort) -or ($port.TcpPort -eq "0"))) { + continue + } + + Write-LogDebug "Comparing port=$portno to dynamic=$($port.TcpDynamicPorts) or static=$($port.TcpPort)" -DebugLogLevel 4 + + if (($port.TcpDynamicPorts -eq $portno) -or ($port.TcpPort -eq $portno)) + { + Write-LogDebug "Port $portno match found for instance $InstanceName" -DebugLogLevel 3 + $resultInstObject.InstanceName = $InstanceName + $matchFound = $true + break + } } } else { - $Result = $global:host_name + Write-LogDebug "TCP/IP protocol not enabled for instance '$InstanceName'" + $instance_name_object = Get-InstanceNameObject -NetnamePlusInstance $server + $resultInstObject = $instance_name_object } - } - } + } - else - { - $instance_name_object = Get-InstanceNameObject -NetnamePlusInstance $selectInstanceName - $Result = $instance_name_object.InstanceName - } + if ($matchFound) { + break + } } - } - Write-LogDebug "The instance name selected after port look-up is $Result" -DebugLogLevel 3 + Write-LogDebug "The instance name selected after port look-up is '$($resultInstObject.InstanceName)'" -DebugLogLevel 3 - return $Result + return $resultInstObject + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + return $null + } } - function GetSQLErrorLogsDumpsSysHealth() { - Write-LogDebug "Inside" $MyInvocation.MyCommand - $collector_name = "SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel" - Write-LogInformation "Executing Collector: $collector_name" + try + { + GetSQLandAgentErrorlogs + GetSQLMemoryDumpAndLogs + GetSystemAndSQLDiagXELs + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + } + +} + + +function GetSQLandAgentErrorlogs() +{ + Write-LogDebug "Inside" $MyInvocation.MyCommand try { + # Get the server name and set the collector name $server = $global:sql_instance_conn_str - + $collector_name = "SQLErrorlogs_SQLAgentLogs" + Write-LogInformation "Executing Collector: $collector_name" + + # Create the partial output and error file names $partial_error_output_file_name = CreatePartialErrorOutputFilename($server) Write-LogDebug "The partial_error_output_file_name is $partial_error_output_file_name" -DebugLogLevel 3 $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false + # Get the destination folder [string]$DestinationFolder = $global:output_folder - # get XEL files from last three weeks - $time_threshold = (Get-Date).AddDays(-21) # get the path to the ERRORLOG from the registry - $vLogPath = GetLogPathFromReg -server $server -logType "ERRORLOG" + $vErrLogPath = GetLogPathFromReg -server $server -logType "ERRORLOG" - if ($vLogPath -eq $false) + if ($vErrLogPath -eq $false) { # The registry key is not valid, return Write-LogWarning "The registry key for ERRORLOG path is not valid. Continuing with other collectors." return } + # build the filter for the ERRORLOG files + # Extract the last part of the path (the errorlog name) + $errorlogName = Split-Path $vErrLogPath -Leaf + + # Remove the extension part from the file name if any and keep only the file name + $errorlogName = $errorlogName.Split('.') |Select-Object -First 1 + + if ([string]::IsNullOrWhiteSpace($errorlogName) -eq $true) + { + # If the errorlog name is empty, set it to ERRORLOG - last-effort attempt to get the errorlog name + $errorlogName = "ERRORLOG" + + Write-LogDebug "Hard-coding ERRORLOG as a file name" -DebugLogLevel 3 + } + + # Use string interpolation to create the filter + $filter = "${errorlogName}*" + + + # extract the path only from the $vLogPath + $vLogPath = Split-Path $vErrLogPath -Parent + + # check if the path exists + if ((Test-Path -Path $vLogPath)) + { + Write-LogDebug "Getting ERRORLOG files from '$vLogPath'" -DebugLogLevel 3 + } + # for ERRORLOG files that are larger than 1 GB copy only head or tail. Otherwise copy the file itself - Write-LogDebug "Getting ERRORLOG files from '$vLogPath'" -DebugLogLevel 3 + # Also get all ERRORLOG files up to 2 months back [datetime] $ErrorLogDateLimit = (Get-Date).AddMonths(-2) - $ErrlogFiles = Get-ChildItem -Path $vLogPath -Filter "ERRORLOG*" | Where-Object {$_.LastWriteTime -ge $ErrorLogDateLimit} + $ErrlogFiles = Get-ChildItem -Path $vLogPath -Filter $filter | Where-Object {$_.LastWriteTime -ge $ErrorLogDateLimit} Write-LogDebug "Capturing all error logs up to 2 months back, starting from '$ErrorLogDateLimit'" -DebugLogLevel 4 #build a string of servername_instancename, if there is a named instance (\) involved @@ -3289,8 +3495,19 @@ function GetSQLErrorLogsDumpsSysHealth() } else { - Copy-Item -Path $source -Destination $destination | Out-Null - Write-LogDebug "ERRORLOG file '$file' copied." -DebugLogLevel 4 + #copy the file and write any errors to the error file + Copy-Item -Path $source -Destination $destination -ErrorAction SilentlyContinue -ErrorVariable ErrLogCopyError | Out-Null + $ErrLogCopyError | Out-File -FilePath $error_file -Append + + #if there are errors copying the file, log it + if ($false -eq [string]::IsNullOrWhiteSpace($ErrLogCopyError)) + { + Write-LogDebug "Error copying Errorlog file '$file'. For details, see '$error_file' ." -DebugLogLevel 4 + } + else + { + Write-LogDebug "ERRORLOG file '$file' copied." -DebugLogLevel 4 + } } $errorlog_count++ @@ -3336,15 +3553,64 @@ function GetSQLErrorLogsDumpsSysHealth() } else { - Copy-Item -Path $source -Destination $destination | Out-Null - Write-LogDebug "Agent Log file '$agentfile' copied." -DebugLogLevel 4 + #copy the file and write any errors to the error file + Copy-Item -Path $source -Destination $destination -ErrorAction SilentlyContinue -ErrorVariable AgentCopyError | Out-Null + $AgentCopyError | Out-File -FilePath $error_file -Append + + #if there are errors copying the file, log it + if ($false -eq [string]::IsNullOrWhiteSpace($AgentCopyError)) + { + Write-LogDebug "Error copying Agent Log file '$agentfile'. See '$error_file' for more details." -DebugLogLevel 4 + } + else + { + Write-LogDebug "SQL Agent Log file '$agentfile' copied." -DebugLogLevel 4 + } } $agentlog_count++ } } - Write-LogDebug "$agentlog_count Agent Log file(s) copied successfully." -DebugLogLevel 3 + Write-LogDebug "$agentlog_count SQL Agent Log file(s) copied successfully." -DebugLogLevel 3 + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + } +} + +function GetSystemAndSQLDiagXELs() +{ + Write-LogDebug "Inside" $MyInvocation.MyCommand + + try + { + # get XEL files from last three weeks + $time_threshold = (Get-Date).AddDays(-21) + + #set up the collector name + $server = $global:sql_instance_conn_str + $collector_name = "SystemHealth_SQLDiag_XELs" + Write-LogInformation "Executing Collector: $collector_name" + + #set up the error file + $partial_error_output_file_name = CreatePartialErrorOutputFilename($server) + Write-LogDebug "The partial_error_output_file_name is $partial_error_output_file_name" -DebugLogLevel 3 + $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false + + #set up the destination folder + [string]$DestinationFolder = $global:output_folder + + # get the path to the ERRORLOG from the registry + $vLogPath = GetLogPathFromReg -server $server -logType "LOG" + + if ($vLogPath -eq $false) + { + # The registry key is not valid, return + Write-LogWarning "The registry key for LOG path is not valid. Continuing with other collectors." + return + } #get SystemHealth XEL files Write-LogDebug "Getting System_Health*.xel files" -DebugLogLevel 3 @@ -3358,46 +3624,157 @@ function GetSQLErrorLogsDumpsSysHealth() #if System health files found, copy them else { - Copy-Item $syshealth_files.FullName $DestinationFolder 2>> $error_file | Out-Null - Write-LogDebug "$($syshealth_files.Count) System_Health XEL file(s) copied successfully." -DebugLogLevel 3 + $SysHealthXelCopyError = "" + Copy-Item $syshealth_files.FullName $DestinationFolder -ErrorAction SilentlyContinue -ErrorVariable SysHealthXelCopyError | Out-Null + $SysHealthXelCopyError | Out-File -FilePath $error_file -Append + + if($false -eq [string]::IsNullOrWhiteSpace($SysHealthXelCopyError)) + { + $SysHealthXelCopyError | Out-File -FilePath $error_file -Append + Write-LogDebug "Error copying System_Health XEL file(s). For details, see '$error_file'." -DebugLogLevel 4 + } else { + Write-LogDebug "$($syshealth_files.Count) System_Health XEL file(s) copied successfully." -DebugLogLevel 3 + } } + #get SQLDIAG XEL files for cluster troubleshooting + if (IsClustered) + { + Write-LogDebug "Getting MSSQLSERVER_SQLDIAG*.xel files" -DebugLogLevel 3 + $SqlDiagXelCopyError = "" + Get-ChildItem -Path $vLogPath -Filter "*_SQLDIAG*.xel" | Copy-Item -Destination $DestinationFolder -ErrorAction SilentlyContinue -ErrorVariable SqlDiagXelCopyError | Out-Null + $SqlDiagXelCopyError | Out-File -FilePath $error_file -Append + + if($false -eq [string]::IsNullOrWhiteSpace($SqlDiagXelCopyError)) + { + Write-LogDebug "Error copying SQLDIAG XEL file(s). For details, see '$error_file'." -DebugLogLevel 4 + } + else { + Write-LogDebug "SQLDIAG XEL file(s) copied successfully." -DebugLogLevel 3 + } + } + + } + catch + { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + } +} + +function GetSQLMemoryDumpAndLogs() +{ + Write-LogDebug "Inside" $MyInvocation.MyCommand + + try + { + + #set up the collector name and server instance + $server = $global:sql_instance_conn_str + $server_instance = $server -replace "\\", "_" + + $collector_name = "MemoryDumps" + Write-LogInformation "Executing Collector: $collector_name" + + #set up the error file + $partial_error_output_file_name = CreatePartialErrorOutputFilename($server) + Write-LogDebug "The partial_error_output_file_name is $partial_error_output_file_name" -DebugLogLevel 3 + $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false + + # Create the output folder for the dump file list + $partial_output_file_name = CreatePartialOutputFilename ($server) + $output_file_dumplist = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name "AllMemoryDumps_List" -needExtraQuotes $false + + + #set up the destination folder + [string]$DestinationFolder = $global:output_folder #get SQL memory dumps Write-LogDebug "Getting SQL Dump files" -DebugLogLevel 3 - + # get the path to the DUMPLOG from the registry $vDmpPath = GetLogPathFromReg -server $server -logType "DUMPLOG" # Fallback to log directory if registry key not found, which is what SQLDumper will do - if(($false -eq $vDmpPath) -or ($null -eq $vDmpPath)) {$vDmpPath=$vLogPath} + if(($false -eq $vDmpPath) -or ($null -eq $vDmpPath)) + { + $vDmpPath=$vLogPath + } + if (($vDmpPath -eq $false) -or ($null -eq $vDmpPath)) + { + # The registry key is not valid, return + Write-LogWarning "The registry key for DUMPLOG path is not valid. Continuing with other collectors." + return + } # Ensure that there is no trailing backslash as we will append when using the path - if ($vDmpPath.EndsWith("\")) { $vDmpPath = $vDmpPath.TrimEnd("\") } + if ($vDmpPath.EndsWith("\")) + { + $vDmpPath = $vDmpPath.TrimEnd("\") + } Write-LogDebug "ErrorDumpDir is: $vDmpPath" -DebugLogLevel 4 - #first, count how many dump files from the last 2 months - $DumpFilesTemp = Get-ChildItem -Path "$vDmpPath\SQLDump*.mdmp","$vDmpPath\SQLDmpr*.*dmp" | Where-Object {($_.LastWriteTime -gt $ErrorLogDateLimit)} + #get all the dump files in a variable first + $allDumps = Get-ChildItem -Path "$vDmpPath\SQLDump*.mdmp","$vDmpPath\SQLDmpr*.*dmp" - Write-LogDebug "Found $($DumpFilesTemp.Count) memory dumps from the past 2 months (since '$ErrorLogDateLimit')" -DebugLogLevel 4 + if ($allDumps.Count -gt 0) + { + # Sort the files by size in descending order + $sortedMdmpFiles = $allDumps | Sort-Object -Property Length -Descending - # now get the memory dumps for last 2 months, of size < 100 MB, and if too many, get only the most recent 20. Dump file types of mdmp and dmp - $DumpFiles = Get-ChildItem -Path "$vDmpPath\SQLDump*.mdmp","$vDmpPath\SQLDmpr*.*dmp" | ` - Where-Object {($_.LastWriteTime -gt $ErrorLogDateLimit) -and ($_.Length -le 104857600)} | ` - Sort-Object -Property LastWriteTime -Descending | ` - Select-Object -First 20 + # collect the file names, sizes, and modified dates of all dumps just in case we don't get all due to size or other restrictions + $sortedMdmpFiles | ForEach-Object { + [PSCustomObject]@{ + FileName = $_.Name + Size = ($_.Length / 1MB).ToString("F2") + " MB" + ModifiedDate = $_.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") + } + } | Format-Table -AutoSize | Out-File -FilePath $output_file_dumplist -Append - if ($null -ne $DumpFiles) - { - Write-LogDebug "Capturing the most recent $($DumpFiles.Count) memory dumps (max count limit of 20), from the past 2 months, of size < 100 MB " -DebugLogLevel 4 - Write-LogInformation "Gathering '$($DumpFiles.Count)' out of '$($DumpFilesTemp.Count)' memory dumps (max limit of 20) from last 2 months of size < 100 MB" + #count how many dump files from the last 2 months + $months_ago = 2 + [datetime] $ErrorLogDateLimit = (Get-Date).AddMonths(-$months_ago) + $DumpFilesTemp = $allDumps | Where-Object {($_.LastWriteTime -gt $ErrorLogDateLimit)} + + Write-LogDebug "Found $($DumpFilesTemp.Count) memory dumps from the past $months_ago months (since '$ErrorLogDateLimit')" -DebugLogLevel 4 + + + # now get the memory dumps for last 2 months, of size < 100 MB, and if too many, get only the most recent 20. Dump file types of mdmp and dmp + $dumpFileSize = 200MB + $dumpFileSizeinMB = $dumpFileSize/1024/1024 + $dumpLimitCount = 20 + $DumpFiles = $allDumps | Where-Object {($_.LastWriteTime -gt $ErrorLogDateLimit) -and ($_.Length -le $dumpFileSize)} | ` + Sort-Object -Property LastWriteTime -Descending | ` + Select-Object -First $dumpLimitCount + + + if ($DumpFiles) + { + Write-LogDebug "Capturing the most recent $($DumpFiles.Count) memory dumps (max count limit of $dumpLimitCount), from the past $months_ago months, of size < $dumpFileSizeinMB MB " -DebugLogLevel 4 + Write-LogInformation "Gathering '$($DumpFiles.Count)' out of '$($DumpFilesTemp.Count)' memory dumps (max limit of $dumpLimitCount) from last $months_ago months of size < $dumpFileSizeinMB MB" - Copy-Item -Path $DumpFiles -Destination $DestinationFolder 2>> $error_file | Out-Null + #copy the files and write any errors to the error file + $DumpCopyError = "" + Copy-Item -Path $DumpFiles -Destination $DestinationFolder -ErrorAction SilentlyContinue -ErrorVariable DumpCopyError | Out-Null + $DumpCopyError | Out-File -FilePath $error_file -Append + + #if there are errors copying the file, log it + if($false -eq [string]::IsNullOrWhiteSpace($DumpCopyError)) + { + Write-LogDebug "Error copying memory dump file(s). For details, see '$error_file'." -DebugLogLevel 4 + } + + } + else { + Write-LogDebug "Not capturing any memory dumps. There are $($DumpFiles.Count) memory dumps from last $months_ago months of size < $dumpFileSizeinMB MB in the '$vDmpPath' folder." -DebugLogLevel 4 + } } - else { - Write-LogDebug "Not capturing any memory dumps. There are $($DumpFiles.Count) memory dumps from last 2 months of size < 100 MB in the '$vDmpPath' folder." -DebugLogLevel 4 + else + { + $no_memory_dumps_found = "No memory dumps found for this SQL Server instance in the '$($vDmpPath)' folder." + Write-LogDebug $no_memory_dumps_found -DebugLogLevel 4 + $no_memory_dumps_found | Out-File -FilePath $output_file_dumplist -Append } #get SQL Dump*.txt files @@ -3405,10 +3782,19 @@ function GetSQLErrorLogsDumpsSysHealth() Sort-Object -Property LastWriteTime -Descending | ` Select-Object -First 200 - if ($null -ne $DumpTxtFiles) + if ($DumpTxtFiles) { Write-LogDebug "Capturing the most recent $($DumpTxtFiles.Count) SQLDump .txt files" -DebugLogLevel 4 - Copy-Item -Path $DumpTxtFiles -Destination $DestinationFolder 2>> $error_file | Out-Null + # if there are errors copying the file, log it + $DumpTxtCopyError = "" + Copy-Item -Path $DumpTxtFiles -Destination $DestinationFolder -ErrorAction SilentlyContinue -ErrorVariable DumpTxtCopyError | Out-Null + $DumpTxtCopyError | Out-File -FilePath $error_file -Append + + #if there are errors copying the file, log it + if($false -eq [string]::IsNullOrWhiteSpace($DumpTxtCopyError)) + { + Write-LogDebug "Error copying SQLDump .txt file(s). For details, see '$error_file'." -DebugLogLevel 4 + } } else { Write-LogDebug "Not capturing any SQLDump*.txt files. There are $($DumpTxtFiles.Count) SQLDump .txt files in the '$vDmpPath' folder." -DebugLogLevel 4 @@ -3422,43 +3808,64 @@ function GetSQLErrorLogsDumpsSysHealth() if ($null -ne $DumpLogFiles) { Write-LogDebug "Capturing the most recent $($DumpLogFiles.Count) SQLDump .log files" -DebugLogLevel 4 - Copy-Item -Path $DumpLogFiles -Destination $DestinationFolder 2>> $error_file | Out-Null + #Copy-Item -Path $DumpLogFiles -Destination $DestinationFolder 2>> $error_file | Out-Null + $DumpLogCopyError = "" + Copy-Item -Path $DumpLogFiles -Destination $DestinationFolder -ErrorAction SilentlyContinue -ErrorVariable DumpLogCopyError | Out-Null + $DumpLogCopyError | Out-File -FilePath $error_file -Append + + #if there are errors copying the file, log it + if($false -eq [string]::IsNullOrWhiteSpace($DumpLogCopyError)) + { + Write-LogDebug "Error copying SQLDump .log file(s). For details, see '$error_file'." -DebugLogLevel 4 + } } - else { + else + { Write-LogDebug "Not capturing any SQLDump*.log files. There are $($DumpLogFiles.Count) SQLDump .log files in the '$vDmpPath' folder." -DebugLogLevel 4 } - + # We should always attempt to get the SQLDumper errorlog in all scenarios in case it has been invoked, but no dump file was created. Also tagging the instance name to the file for any future usage whith multi-instance collections. $source = $vDmpPath + "\SQLDUMPER_ERRORLOG.log" $destination = $DestinationFolder + $server_instance + "_" + "SQLDUMPER_ERRORLOG.log" if(Test-Path -Path $source -PathType Leaf) { Write-LogDebug "Capturing the SQLDUMPER_ERRORLOG.log" -DebugLogLevel 2 - Get-ChildItem -Path $source | Copy-Item -Destination $destination 2>> $error_file | Out-Null + $DumpErrorLogCopyError = "" + Get-ChildItem -Path $source | Copy-Item -Destination $destination -ErrorAction SilentlyContinue -ErrorVariable DumpErrorLogCopyError | Out-Null + $DumpErrorLogCopyError | Out-File -FilePath $error_file -Append + + if($false -eq [string]::IsNullOrWhiteSpace($DumpErrorLogCopyError)) + { + $DumpErrorLogCopyError | Out-File -FilePath $error_file -Append + Write-LogDebug "Error copying SQLDUMPER_ERRORLOG.log. For details, see '$error_file'." -DebugLogLevel 4 + } } - else { + else + { Write-LogDebug "Not capturing SQL Dumper Error Log. File not found in the '$vDmpPath' directory." } - # We should always attempt to get the exception.log. - $source = $vDmpPath + "\exception.log" - $destination = $DestinationFolder + $server_instance + "_" + "exception.log" - - if(Test-Path -Path $source -PathType Leaf) { - Write-LogDebug "Capturing the exception.log" -DebugLogLevel 2 - Get-ChildItem -Path $source | Copy-Item -Destination $destination 2>> $error_file | Out-Null - } - else { - Write-LogDebug "Not capturing exception.log. File not found in the '$vDmpPath' directory." - } + # We should always attempt to get the exception.log. + $source = $vDmpPath + "\exception.log" + $destination = $DestinationFolder + $server_instance + "_" + "exception.log" - #get SQLDIAG XEL files for cluster troubleshooting - if (IsClustered) + if(Test-Path -Path $source -PathType Leaf) { - Write-LogDebug "Getting MSSQLSERVER_SQLDIAG*.xel files" -DebugLogLevel 3 - Get-ChildItem -Path $vLogPath -Filter "*_SQLDIAG*.xel" | Copy-Item -Destination $DestinationFolder 2>> $error_file | Out-Null + Write-LogDebug "Capturing the exception.log" -DebugLogLevel 2 + $ExceptionLogCopyError = "" + Get-ChildItem -Path $source | Copy-Item -Destination $destination -ErrorAction SilentlyContinue -ErrorVariable ExceptionLogCopyError | Out-Null + $ExceptionLogCopyError | Out-File -FilePath $error_file -Append + + if($false -eq [string]::IsNullOrWhiteSpace($ExceptionLogCopyError)) + { + $ExceptionLogCopyError | Out-File -FilePath $error_file -Append + Write-LogDebug "Error copying exception.log. For details, see '$error_file'." -DebugLogLevel 4 + } + } + else + { + Write-LogDebug "Not capturing exception.log. File not found in the '$vDmpPath' directory." } - } catch { @@ -3477,6 +3884,9 @@ function GetFullTextSearchLogFiles { { $server = $global:sql_instance_conn_str + + #build a string of servername_instancename, if there is a named instance (\) involved + $server_instance = $server -replace "\\", "_" $partial_error_output_file_name = CreatePartialErrorOutputFilename($server) @@ -3486,28 +3896,30 @@ function GetFullTextSearchLogFiles { [string]$DestinationFolder = $global:output_folder - # get the path to the ERRORLOG from the registry - $vLogPath = GetLogPathFromReg -server $server -logType "ERRORLOG" - - if ($vLogPath -eq $false) + # Get the paths to the SQLFT and FDLAUNCHER logs from the registry + $sqlftLogPath = GetLogPathFromReg -server $server -logType "SQLFTLOG" + $fdlauncherLogPath = GetLogPathFromReg -server $server -logType "FDLAUNCHERRORLOG" + + if (($sqlftLogPath -eq $false) -or ($fdlauncherLogPath -eq $false)) { # The registry key is not valid, return - Write-LogWarning "The registry key for ERRORLOG path is not valid. Continuing with other collectors." + Write-LogWarning "The registry key for SQLFTLOG or FDLAUNCHERLOG paths is not valid. Continuing with other collectors." return } - $server_instance = $server -replace "\\", "_" + # Combine the folders into an array + $logPaths = @($sqlftLogPath, $fdlauncherLogPath) - # for ERRORLOG files that are larger than 1 GB copy only head or tail. Otherwise copy the file itself - Write-LogDebug "Getting FullText-Search files from '$vLogPath'" -DebugLogLevel 3 - #get FullText files - Write-LogDebug "Getting Full-Text Search log files" -DebugLogLevel 3 + # print the combined paths to be searched + $logPathsString = $logPaths -join "', '" + Write-LogDebug "Getting FullText-Search files from '$logPathsString'" -DebugLogLevel 3 + - $FTS_logfiles = Get-ChildItem -Path $vLogPath -Filter "*" | Where-Object { $_.Name -like "SQLFT*" -or $_.Name -like "FD*" } + $FTS_logfiles = Get-ChildItem -Path $logPaths -Filter "*" | Where-Object { $_.Name -like "SQLFT*" -or $_.Name -like "FD*" } $FTSlog_count = 0 - #Check if any agent error logs found + #Check if any FTS error logs found if ($FTS_logfiles.Count -eq 0) { #Do not edit message without updating Testing Infra Array. @@ -3706,7 +4118,9 @@ function GetSQLAssessmentAPI() if (Get-Module -ListAvailable -Name sqlserver) { - if ((Get-Module -ListAvailable -Name sqlserver).exportedCommands.Values | Where-Object name -EQ "Invoke-SqlAssessment") + $Invoke_SqlAssessment_command = Get-Command -Module SqlServer -Name Invoke-SqlAssessment -ErrorAction SilentlyContinue + $Get_SqlInstance_command = Get-Command -Module SqlServer -Name Get-SqlInstance -ErrorAction SilentlyContinue + if ($Invoke_SqlAssessment_command -and $Get_SqlInstance_command) { Write-LogDebug "Invoke-SqlAssessment() function present" -DebugLogLevel 3 Get-SqlInstance -ServerInstance $server -TrustServerCertificate -Encrypt Mandatory | Invoke-SqlAssessment -FlattenOutput | Out-File $output_file @@ -4050,6 +4464,131 @@ function GetXeventServiceBrokerDbMail } +function GetDotNetVersions +{ + Write-LogDebug "Inside" $MyInvocation.MyCommand + + try { + # Set up the collector name and server instance + $server = $global:sql_instance_conn_str + + $collector_name = "DotNetVersions" + Write-LogInformation "Executing Collector: $collector_name" + + # Set up the error file + $partial_error_output_file_name = CreatePartialErrorOutputFilename($server) + Write-LogDebug "The partial_error_output_file_name is $partial_error_output_file_name" -DebugLogLevel 3 + $error_file = BuildFinalErrorFile -partial_error_output_file_name $partial_error_output_file_name -collector_name $collector_name -needExtraQuotes $false + + # Create the output folder for the .NET versions + $partial_output_file_name = CreatePartialOutputFilename($server) + $output_file = BuildFinalOutputFile -output_file_name $partial_output_file_name -collector_name $collector_name -needExtraQuotes $false + + # Get .NET Framework version + $frameworkResult = @{} + + Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | + Get-ItemProperty -Name Version -ErrorAction SilentlyContinue | + Where-Object { $_.PSChildName -match '^(?!S)\p{L}'} | + ForEach-Object { + $name = ".NET Framework $($_.PSChildName)" + $frameworkResult[$name] = $_.Version + } + + if ($frameworkResult.Count -eq 0) + { + $frameworkResult[".NET Framework"] = "Not detected" + } + + # Get .NET Core versions + $dotnetCoreSdkVersions = $null + $dotnetCoreRuntimeVersions = $null + + if (Get-Command dotnet -ErrorAction SilentlyContinue) + { + $dotnetCoreSdkVersions = & "dotnet" --list-sdks + $dotnetCoreRuntimeVersions = & "dotnet" --list-runtimes + } + + + # Process .NET Core SDK versions + $coreResults = @() + $netcore_cntr = 0 + if ($dotnetCoreSdkVersions) + { + + foreach ($versionSdk in $dotnetCoreSdkVersions) + { + $netcore_cntr += 1 + $coreResults += @{ $("("+ $netcore_cntr + ") .NET Core SDK" ) = $versionSdk } + } + } else { + $coreResults += @{ ".NET Core SDK" = "Not detected" } + } + + + # Process .NET Core Runtime versions + if ($dotnetCoreRuntimeVersions) + { + foreach ($versionRT in $dotnetCoreRuntimeVersions) + { + $netcore_cntr += 1 + $coreResults += @{ $("("+ $netcore_cntr + ") .NET Core Runtime" ) = $versionRT } + } + } else { + $coreResults += @{ ".NET Core Runtime" = "Not detected" } + } + + # Combine results using Add method + $combinedResults = @{} + foreach ($key in $frameworkResult.Keys) + { + $combinedResults.Add($key, $frameworkResult[$key]) + } + foreach ($result in $coreResults) + { + foreach ($key in $result.Keys) + { + $combinedResults.Add($key, $result[$key]) + } + } + + # Determine the maximum length for each column + $maxFrameworkLength = ($combinedResults.Keys | Measure-Object -Maximum Length).Maximum + $maxVersionLength = ($combinedResults.Values | Measure-Object -Maximum Length).Maximum + + # Create the header and separator + $header = "Framework".PadRight($maxFrameworkLength) + " Version".PadRight($maxVersionLength) + $separator = "-" * $maxFrameworkLength + " " + "-" * $maxVersionLength + + # Store the header, separator, and combined results in a string array + $outputContent = @() + $outputContent += "-- dot_net_versions --" + $outputContent += $header + $outputContent += $separator + + foreach ($key in $combinedResults.Keys) + { + $line = $key.PadRight($maxFrameworkLength) + " " + $combinedResults[$key].PadRight($maxVersionLength) + $outputContent += $line + } + + # Write the entire content to the output file in one operation + try { + $outputContent | Out-File -FilePath $output_file -Append + Write-LogDebug "Collected .NET Framework and .NET Core versions successfully." -DebugLogLevel 3 + } + catch + { + $errorMessage = $_.Exception.Message + $errorMessage | Out-File -FilePath $error_file -Append + } + } + catch { + HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem + } +} + function validateUserInput([string[]]$AllInput) { @@ -4245,8 +4784,9 @@ function Invoke-BasicScenario([bool] $PerfmonOnly = $false) GetTaskList GetFilterDrivers GetSysteminfoSummary + GetDotNetVersions - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4308,7 +4848,7 @@ function Invoke-GeneralPerfScenario() GetPerfmonCounters - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4348,7 +4888,7 @@ function Invoke-DetailedPerfScenario() GetPerfmonCounters - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4386,7 +4926,7 @@ function Invoke-LightPerfScenario () GetPerfmonCounters - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4422,7 +4962,7 @@ function Invoke-AlwaysOnScenario() Write-LogInformation "Collecting logs for '$global:ALWAYSON_NAME' scenario" -ForegroundColor Green - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4458,7 +4998,7 @@ function Invoke-ReplicationScenario() Write-LogDebug "Inside" $MyInvocation.MyCommand Write-LogInformation "Collecting logs for '$global:REPLICATION_NAME' scenario" -ForegroundColor Green - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4530,7 +5070,7 @@ function Invoke-MemoryScenario - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4556,6 +5096,7 @@ function Invoke-SetupScenario GetSQLSetupLogs GetInstallerRegistryKeys GetMissingSQLMsiMspFiles + GetInstalledPrograms } function Invoke-BackupRestoreScenario() @@ -4638,7 +5179,7 @@ function Invoke-ServiceBrokerDbMailScenario () # get Perfmon counters GetPerfmonCounters - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" } @@ -4698,7 +5239,7 @@ function Invoke-NeverEndingQueryScenario() # get Perfmon counters GetPerfmonCounters - if ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) + if ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) { Write-LogDebug $NoCollectionMessage -DebugLogLevel 1 Write-LogWarning "No SQL Server instance specified, thus skipping execution of SQL Server-based collectors" @@ -4873,12 +5414,13 @@ function StartStopTimeForDiagnostics ([PSObject] $timeParam, [string] $startOrSt [int] $increment = 0 - [int] $sleepIntervalSec = 2 + [int] $sleepIntervalSec = 4 while ((Get-Date) -lt (Get-Date $formatted_date_time)) { Start-Sleep -Seconds $sleepIntervalSec + #check if CTRL+C was pressed and exit the loop if ($Host.UI.RawUI.KeyAvailable -and (3 -eq [int]$Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyUp,IncludeKeyDown,NoEcho").Character)) { Write-LogWarning "*******************" @@ -4887,6 +5429,14 @@ function StartStopTimeForDiagnostics ([PSObject] $timeParam, [string] $startOrSt break } + #check if a stop file (logscout.stop) was created and exit the loop + if (Check-StopFile -FilePath $global:stopFilePath) + { + $ValidStop = $true + Write-LogInformation "Stop file detected. Shutting down the collector" -ForegroundColor Green + break + } + $increment += $sleepIntervalSec if ($increment % 120 -eq 0) @@ -5478,6 +6028,13 @@ function Start-DiagCollectors () } } +#helper function to check if a stop file exists +function Check-StopFile ([string]$FilePath) +{ + return Test-Path $FilePath +} + + function Stop-DiagCollectors() { Write-LogDebug "inside" $MyInvocation.MyCommand @@ -5509,31 +6066,69 @@ function Stop-DiagCollectors() CheckInternalFolderError if ($false -eq $global:stop_automatically) - { #wait for user to type "STOP" + { + + $readHostOptions = "" + + if ($global:dump_helper_arguments -ne "none") { + $readHostOptions += "MemDump, " + } + + #wait for user to type "STOP", "StopFile" or "MemDump" + #construct the Read-Host options string + $readHostOptions += "StopFile, Stop" + + + + # get the user input on when and how to stop the collection while ($ValidStop -eq $false) { - Write-LogInformation "Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue" -ForegroundColor Green + + Write-LogInformation "Type 'STOP' to terminate the diagnostics collection or type 'StopFile' to end collection externally by an event." -ForegroundColor Green if ($global:dump_helper_arguments -ne "none") - { - Write-LogInformation "You can invoke MemoryDump by typing 'MemDump'" -ForegroundColor Green + { + #if we have 1 dump, produce message for 1 dump, else for multiple dumps add the interval at the end + # Type 'MemDump' to generate 4 dump(s) on demand, X seconds apart. + if ($global:dump_helper_count -eq 1) { + $memDumpPrompt = "Type 'MemDump' to generate $global:dump_helper_count dump on demand" + } else { + $memDumpPrompt = "Type 'MemDump' to generate $global:dump_helper_count dumps on demand, $global:dump_helper_delay seconds apart." + } + + Write-LogInformation "$memDumpPrompt" -ForegroundColor Green + } - $StopStr = (Read-Host ">" -CustomLogMessage "StopCollection Console input:").ToLower() + $StopStr = (Read-Host "$readHostOptions >" -CustomLogMessage "StopCollection Console input:").ToLower() #validate this PID is in the list discovered Switch ($StopStr ) { "stop"{ - $ValidStop = $true - Write-LogInformation "Shutting down the collector" -ForegroundColor Green #DO NOT CHANGE - Message is backward compatible - break; + $ValidStop = $true + Write-LogInformation "Shutting down the collector" -ForegroundColor Green #DO NOT CHANGE - Message is backward compatible + break; } "memdump"{ - if ($global:dump_helper_arguments -ne "none") { + if ($global:dump_helper_arguments -ne "none") + { Invoke-DumpMemoryScenario } $ValidStop = $false + } + "stopfile" { + #check if a stop file (logscout.stop) was created and exit the loop + Write-LogInformation "Waiting for stop file to be created..." -ForegroundColor Green + while ($ValidStop -eq $false) { + if (Check-StopFile -FilePath $global:stopFilePath) + { + $ValidStop = $true + Write-LogInformation "Stop file detected. Shutting down the collector" -ForegroundColor Green + break + } + Start-Sleep -Seconds 5 } + } Default { $ValidStop = $false @@ -6029,6 +6624,11 @@ function Stop-ProcMonTrace([string]$partial_error_output_file_name) function Invoke-DiagnosticCleanUpAndExit() { + <# + The purpose of this function is to run quickly and therefore we don't call into many of the helper functions in SQL LogScout. + Not using other helper functions also minimizes the risk and increases the reliability of this function. + #> + Write-LogDebug "inside" $MyInvocation.MyCommand try @@ -6036,6 +6636,15 @@ function Invoke-DiagnosticCleanUpAndExit() Write-LogWarning "Launching cleanup and exit routine... please wait" $server = $global:sql_instance_conn_str + #get the sqlcmd.exe path and check if the path is valid and not empty + $is_sqlcmd_valid = $false + $sqlcmd_executable = GetSQLCmdPath + + if ($false -eq [string]::IsNullOrWhiteSpace($sqlcmd_executable)) + { + $is_sqlcmd_valid = $true + } + #quick cleanup to ensure no collectors are running. #Kill existing sessions #send the output file to \internal @@ -6053,31 +6662,29 @@ function Invoke-DiagnosticCleanUpAndExit() close curSession; deallocate curSession; " - if (($server -ne $NO_INSTANCE_NAME) -or ($global:sql_instance_service_status -eq "Running")) + # if a valid server name is provided and the SQL Server service is running, and sqlcmd exist on the machine, then kill the active logscout sessions + if (($server -ne $global:NO_INSTANCE_NAME) -and ($global:sql_instance_service_status -eq "Running") -and ($is_sqlcmd_valid -eq $true)) { - $executable = "sqlcmd.exe" $argument_list ="-S" + $server + " -E -Hsqllogscout_cleanup -w8000 -Q`""+ $query + "`" " - StartNewProcess -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null + StartNewProcess -FilePath $sqlcmd_executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null } #STOP the XEvent sessions - if (($server -ne $NO_INSTANCE_NAME) -or ($global:sql_instance_service_status -eq "Running")) + # if a valid server name is provided and the SQL Server service is running, and sqlcmd exist on the machine, then stop the XEvent session + if (($server -ne $global:NO_INSTANCE_NAME) -and ($global:sql_instance_service_status -eq "Running") -and ($is_sqlcmd_valid -eq $true)) { $alter_event_session_stop = "IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 BEGIN ALTER EVENT SESSION [$global:xevent_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$global:xevent_session] ON SERVER; END" - $executable = "sqlcmd.exe" $argument_list = "-S" + $server + " -E -Hsqllogscout_cleanup -w8000 -Q`"" + $alter_event_session_stop + "`"" - StartNewProcess -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null + StartNewProcess -FilePath $sqlcmd_executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null #avoid errors if there was not Xevent collector started $alter_event_session_ag_stop = "IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 BEGIN ALTER EVENT SESSION [$global:xevent_alwayson_session] ON SERVER STATE = STOP; DROP EVENT SESSION [$global:xevent_alwayson_session] ON SERVER; END" - $executable = "sqlcmd.exe" $argument_list = "-S" + $server + " -E -Hsqllogscout_stop -w8000 -Q`"" + $alter_event_session_ag_stop + "`"" - StartNewProcess -FilePath $executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null - + StartNewProcess -FilePath $sqlcmd_executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null } #STOP Perfmon @@ -6162,12 +6769,18 @@ function Invoke-DiagnosticCleanUpAndExit() } - if (($server -ne $NO_INSTANCE_NAME) -and ($true -eq (IsScenarioEnabled -scenarioBit $global:BackupRestoreBit )) ) + # if a valid server name is provided and the SQL Server service is running, and sqlcmd exist on the machine, + # and the BackupRestoreBit is enabled, then disable the trace flags for Backup/Restore + if (($server -ne $global:NO_INSTANCE_NAME) ` + -and ($global:sql_instance_service_status -eq "Running")` + -and ($is_sqlcmd_valid -eq $true) ` + -and ($true -eq (IsScenarioEnabled -scenarioBit $global:BackupRestoreBit )) + ) { #clean up backup/restore tace flags $Disabled_Trace_Flag = "DBCC TRACEOFF(3004,3212,3605,-1)" $argument_list = "-S" + $server + " -E -Hsqllogscout_stop -w8000 -Q`"" + $Disabled_Trace_Flag + "`"" - StartNewProcess -FilePath "sqlcmd.exe" -ArgumentList $argument_list -WindowStyle Hidden | Out-Null + StartNewProcess -FilePath $sqlcmd_executable -ArgumentList $argument_list -WindowStyle Hidden | Out-Null } @@ -6239,6 +6852,9 @@ function Invoke-DiagnosticCleanUpAndExit() Write-LogInformation "Thank you for using SQL LogScout!" -ForegroundColor Green + #we have to remove importModule early on before we flush and close open streams + Remove-Module -Name CustomImportModule + #close and remove handles to the log files if ($global:debugLogStream) { @@ -6262,8 +6878,22 @@ function Invoke-DiagnosticCleanUpAndExit() } ## Remove all modules from the current session so that the script can be run again without restarting the session - Get-Module | Remove-Module + $LoadedModules = Get-Module + ForEach ($module in $LoadedModules) + { + try + { + Remove-Module -Name $module.Name -Force -ErrorAction SilentlyContinue + } + catch + { + #if we fail to remove a specific module we report and continue + Microsoft.PowerShell.Utility\Write-Host "Could not remove module : $($module.Name)" + continue + } + } + #Clean up global variables, except for the output folder and many of the input parameters #Clean up is necessary to allow the script to be run again without restarting the PS session and causing errors #Also when the script is run from Powershell.exe -File ... the scope of local variables and parameters is treated as global and they get deleted. Thus the exclusion list @@ -6296,6 +6926,8 @@ function Invoke-DiagnosticCleanUpAndExit() } catch { + #Importing commonfunction is needed if the exception happens after removal of the function in the previous block + Import-Module .\CommonFunctions.psm1 HandleCatchBlock -function_name $($MyInvocation.MyCommand) -err_rec $PSItem exit } @@ -6573,9 +7205,9 @@ param ( Write-LogDebug "inside " $MyInvocation.MyCommand - if (($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) -or ($true -eq $global:instance_independent_collection ) -or ($global:sql_instance_service_status -ne "Running")) + if (($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) -or ($true -eq $global:instance_independent_collection ) -or ($global:sql_instance_service_status -ne "Running")) { - Write-LogDebug "Offline status values: NO_INSTANCE_NAME=$NO_INSTANCE_NAME, instance_independent_collection=$global:instance_independent_collection, allow_static_data_because_service_offline=$global:allow_static_data_because_service_offline, sql_instance_service_status=$global:sql_instance_service_status" -DebugLogLevel 3 + Write-LogDebug "Offline status values: NO_INSTANCE_NAME=$global:NO_INSTANCE_NAME, instance_independent_collection=$global:instance_independent_collection, allow_static_data_because_service_offline=$global:allow_static_data_because_service_offline, sql_instance_service_status=$global:sql_instance_service_status" -DebugLogLevel 3 Write-LogWarning "SQL Server instance isn't found, is offline, or scenario is instance independent. SQL Permissions-checking is not necessary" Start-Sleep -Seconds 5 return $true @@ -6991,7 +7623,7 @@ function GetPerformanceDataAndLogs #pick a sql instance - Select-SQLServerForDiagnostics + Select-SQLServerForDiagnostics | Out-Null #If selected SQL instance is not running and the data collection requires connection to SQL Server, exit if ($true -ne $global:allow_static_data_because_service_offline -and $global:sql_instance_service_status -ne "Running") @@ -7051,7 +7683,7 @@ function InitializeGlobalsFromSQL() if ( - ($global:sql_instance_conn_str -eq $NO_INSTANCE_NAME) -or + ($global:sql_instance_conn_str -eq $global:NO_INSTANCE_NAME) -or ($true -eq $global:instance_independent_collection ) -or ("Running" -ne $global:sql_instance_service_status) ) diff --git a/SQL LogScout/Bin/SQLScript_MSDiagProcs.psm1 b/SQL LogScout/Bin/SQLScript_MSDiagProcs.psm1 deleted file mode 100644 index 7547bcf..0000000 --- a/SQL LogScout/Bin/SQLScript_MSDiagProcs.psm1 +++ /dev/null @@ -1,4659 +0,0 @@ - - function MSDiagProcs_Query([Boolean] $returnVariable = $false) - { - Write-LogDebug "Inside" $MyInvocation.MyCommand - - [String] $collectorName = "MSDiagProcs" - [String] $fileName = $global:internal_output_folder + $collectorName + ".sql" - - $content = " - RAISERROR ('NOTE: It''s completely normal for some errors to be generated by this script', 0, 1) WITH NOWAIT - GO - - /* - Procs: - #sp_set_blk_thresholdNN - #sp_tmpregread - #sp_tmpregenumvalues - #sp_sqldiagNN - #sp_traceNN - #sp_sqldiag_cleanupNN - #sp_code_runnerNN - #sp_blocker_pssNN - - */ - - USE tempdb - GO - set nocount on - go - - - /* - - #sp_set_blk_threshold - - */ - - IF OBJECT_ID('dbo.#sp_set_blk_threshold09','P') IS NOT NULL drop proc dbo.#sp_set_blk_threshold09 - GO - PRINT '' - RAISERROR ('===== Creating #sp_set_blk_threshold09', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_set_blk_threshold09 @threshold int - as - print 'skip configuring blockig threshold' - /* - if (select value from sys.sysconfigures where config = 518) = 1 - begin - exec sp_configure 'Blocked process',@threshold - reconfigure with override - end - else - begin - exec sp_configure 'show advanced option',1 - reconfigure with override - exec sp_configure 'Blocked process',@threshold - exec sp_configure 'show advanced option',0 - reconfigure with override - end - */ - - go - - -- Set up a default blocked process threshold in case blocked process event is - -- included in regular trace - if (CHARINDEX('9.00.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Executing #sp_set_blk_threshold09', 0, 1) WITH NOWAIT - exec dbo.#sp_set_blk_threshold09 5 - END - GO - IF OBJECT_ID('dbo.#sp_set_blk_threshold10','P') IS NOT NULL drop proc dbo.#sp_set_blk_threshold10 - GO - PRINT '' - RAISERROR ('===== Creating #sp_set_blk_threshold10', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_set_blk_threshold10 @threshold int - as - BEGIN - exec dbo.#sp_set_blk_threshold09 @threshold - END - GO - -- SQL11 Version Bump - IF OBJECT_ID('dbo.#sp_set_blk_threshold11','P') IS NOT NULL drop proc dbo.#sp_set_blk_threshold11 - GO - PRINT '' - RAISERROR ('===== Creating #sp_set_blk_threshold11', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_set_blk_threshold11 @threshold int - as - BEGIN - exec dbo.#sp_set_blk_threshold10 @threshold - END - GO - - -- SQL14 Version Bump - IF OBJECT_ID('dbo.#sp_set_blk_threshold12','P') IS NOT NULL drop proc dbo.#sp_set_blk_threshold12 - GO - PRINT '' - RAISERROR ('===== Creating #sp_set_blk_threshold12', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_set_blk_threshold12 @threshold int - as - BEGIN - exec dbo.#sp_set_blk_threshold10 @threshold - END - GO - - -- SQL15 Version Bump - IF OBJECT_ID('dbo.#sp_set_blk_threshold13','P') IS NOT NULL drop proc dbo.#sp_set_blk_threshold13 - GO - PRINT '' - RAISERROR ('===== Creating #sp_set_blk_threshold13', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_set_blk_threshold13 @threshold int - as - BEGIN - exec dbo.#sp_set_blk_threshold10 @threshold - END - GO - - - /* - - #sp_sqldiag - - */ - - IF OBJECT_ID ('dbo.#sp_tmpregread','P') IS NOT NULL DROP PROC dbo.#sp_tmpregread - IF OBJECT_ID ('dbo.#sp_tmpregenumvalues','P') IS NOT NULL DROP PROC dbo.#sp_tmpregenumvalues - GO - PRINT '' - RAISERROR ('===== Creating #sp_tmpregread', 0, 1) WITH NOWAIT - GO - -- Create temporary stored procedures in tempdb - CREATE PROCEDURE dbo.#sp_tmpregread - @hive varchar (60), @key nvarchar (2000), @value nvarchar (2000), @data nvarchar (4000) = NULL OUTPUT - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - DECLARE @sql70or80xp sysname - - DECLARE @sqlcmd nvarchar (4000) - -- To avoid osql line wrapping, don't store more than 2000 chars. - CREATE TABLE #regdata (RegValue nvarchar(190), RegData nvarchar (1800)) - IF CHARINDEX ('7.00.', @@VERSION) = 0 - SET @sql70or80xp = 'master.dbo.xp_instance_regread' - ELSE - SET @sql70or80xp = 'master.dbo.xp_regread' - SET @sqlcmd = 'INSERT INTO #regdata EXEC ' + @sql70or80xp + ' @P1, @P2, @P3' - EXEC sp_executesql @sqlcmd, - N'@P1 varchar (40), @P2 nvarchar (2000), @P3 nvarchar (2000)', - @hive, @key, @value - SELECT * FROM #regdata - PRINT '' - GO - PRINT '' - RAISERROR ('===== Creating #sp_tmpregenumvalues', 0, 1) WITH NOWAIT - GO - CREATE PROCEDURE dbo.#sp_tmpregenumvalues - @hive varchar (40), @key nvarchar (2000), @direct_output int = 0 - AS - DECLARE @sql70or80xp sysname - DECLARE @sqlcmd nvarchar (4000) - CREATE TABLE #regdata (RegValue nvarchar(190), RegData nvarchar (1800)) - IF CHARINDEX ('7.00.', @@VERSION) = 0 - SET @sql70or80xp = 'master.dbo.xp_instance_regenumvalues' - ELSE - SET @sql70or80xp = 'master.dbo.xp_regenumvalues' - IF @direct_output = 1 SET @sqlcmd = 'EXEC ' - ELSE SET @sqlcmd = 'INSERT INTO #regdata EXEC ' - SET @sqlcmd = @sqlcmd + @sql70or80xp + ' @P1, @P2' - EXEC sp_executesql @sqlcmd, - N'@P1 varchar (40), @P2 nvarchar (2000)', - @hive, @key - IF @direct_output = 0 SELECT * FROM #regdata - GO - - - IF OBJECT_ID('dbo.#sp_sqldiag07','P') IS NOT NULL drop proc dbo.#sp_sqldiag07 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag07', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag07 @bGetSyscacheobjects int = 0 - AS - - PRINT 'Errorlogs' - PRINT '---------' - - declare @i tinyint, @res int - set @i=0 - while (@i<255) begin - if (0=@i) begin - print 'ERRORLOG' - exec @res=master.dbo.xp_readerrorlog - end else begin - print 'ERRORLOG.'+cast(@i as varchar(3)) - exec @res=master.dbo.xp_readerrorlog @i - end - if (@@error<>0) OR (@res<>0) break - set @i=@i+1 - end - - PRINT 'Registry Information' - PRINT '--------------------' - - PRINT 'SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo:' - PRINT '------------------------------------------------' - EXEC master.dbo.#sp_tmpregenumvalues 'HKEY_LOCAL_MACHINE', - 'Software\Microsoft\MSSQLServer\Client\ConnectTo' - PRINT '' - - PRINT 'SOFTWARE\Microsoft\MSSQLServer\Client\DB-Lib:' - PRINT '---------------------------------------------' - EXEC master.dbo.#sp_tmpregenumvalues 'HKEY_LOCAL_MACHINE', - 'SOFTWARE\Microsoft\MSSQLServer\Client\DB-Lib' - PRINT '' - - PRINT 'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\CurrentVersion:' - PRINT '----------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\CurrentVersion', 'CurrentVersion' - PRINT '' - - PRINT 'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\Parameters:' - PRINT '------------------------------------------------------' - EXEC master.dbo.#sp_tmpregenumvalues 'HKEY_LOCAL_MACHINE', - 'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer\Parameters' - PRINT '' - - PRINT 'SOFTWARE\Microsoft\MSSQLServer\Setup\SQLPath:' - PRINT '---------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'SOFTWARE\Microsoft\MSSQLServer\Setup', 'SQLPath' - PRINT '' - - PRINT 'System\CurrentControlSet\Control\ProductOptions:' - PRINT '------------------------------------------------' - EXEC master.dbo.#sp_tmpregenumvalues 'HKEY_LOCAL_MACHINE', - 'System\CurrentControlSet\Control\ProductOptions', 1 - PRINT '' - - PRINT 'Software\Microsoft\Windows NT\CurrentVersion\SystemRoot:' - PRINT '--------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'Software\Microsoft\Windows NT\CurrentVersion', 'SystemRoot' - PRINT '' - - PRINT 'Software\Microsoft\Windows NT\CurrentVersion\CurrentVersion:' - PRINT '------------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'Software\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion' - PRINT '' - - PRINT 'System\CurrentControlSet\Control\Nls\CodePage:' - PRINT '----------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'System\CurrentControlSet\Control\Nls\CodePage', 'ACP' - PRINT '' - - PRINT 'System\CurrentControlSet\Control\Nls\CodePage:' - PRINT '----------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'System\CurrentControlSet\Control\Nls\CodePage', 'OEMCP' - PRINT '' - - PRINT 'Software\Microsoft\DataAccess:' - PRINT '------------------------------' - EXEC master.dbo.#sp_tmpregenumvalues 'HKEY_LOCAL_MACHINE', - 'Software\Microsoft\DataAccess' - PRINT '' - - PRINT 'SYSTEM\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias:' - PRINT '--------------------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'SYSTEM\CurrentControlSet\Control\TimeZoneInformation', 'ActiveTimeBias' - PRINT '' - - PRINT 'SYSTEM\CurrentControlSet\Control\TimeZoneInformation\Bias:' - PRINT '----------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'SYSTEM\CurrentControlSet\Control\TimeZoneInformation', 'Bias' - PRINT '' - - IF (CHARINDEX('7.0',@@VERSION)<>-1) BEGIN - PRINT 'SYSTEM\CurrentControlSet\Services\LicenseInfo\MSSQL7.00:' - PRINT '--------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'SYSTEM\CurrentControlSet\Services\LicenseInfo\MSSQL7.00', 'ConcurrentLimit' - END ELSE BEGIN - PRINT 'SOFTWARE\Microsoft\Microsoft SQL Server\80\MSSQLLicenseInfo\MSSQL8.00:' - PRINT '----------------------------------------------------------------------' - EXEC master.dbo.#sp_tmpregread 'HKEY_LOCAL_MACHINE', - 'SOFTWARE\Microsoft\Microsoft SQL Server\80\MSSQLLicenseInfo\MSSQL8.00', - 'ConcurrentLimit' - END - PRINT '' - PRINT '' - - - PRINT '-> sp_configure' - declare @show_advance int - if (select value from master.dbo.syscurconfigs where config = 518) = 1 - select @show_advance = 1 - else - select @show_advance = 0 - if @show_advance = 0 - begin - exec sp_configure 'show advanced option',1 - reconfigure with override - exec sp_configure - exec sp_configure 'show advanced option',0 - reconfigure with override - end - else - exec sp_configure - - PRINT '-> sp_who' - exec sp_who - PRINT '' - - PRINT '-> sp_lock' - exec sp_lock - PRINT '' - - PRINT '-> sp_helpdb' - exec sp_helpdb - PRINT '' - - PRINT '-> xp_msver' - exec master.dbo.xp_msver - PRINT '' - - PRINT '-> sp_helpextendedproc' - exec sp_helpextendedproc - PRINT '' - - PRINT '-> Sysprocesses' - select spid, kpid, blocked, waittype, waittime, lastwaittype, - LEFT (waitresource, 50) AS waitresource, dbid, - uid, cpu, physical_io, memusage, login_time, last_batch, ecid, open_tran, - status, sid, LEFT (hostname, 30) AS hostname, - LEFT (program_name, 50) AS program_name, hostprocess, cmd, - LEFT (nt_domain, 30) AS nt_domain, LEFT (nt_username, 30) AS nt_username, - net_address, net_library, loginame, context_info - from master.dbo.sysprocesses - PRINT '' - - -- fn_virtualservernodes is not present in 7.0 - IF (CHARINDEX ('Microsoft SQL Server 7.00', @@VERSION) = 0) - BEGIN - EXEC ('PRINT ''-> ::fn_virtualservernodes()''') - EXEC ('SELECT * FROM ::fn_virtualservernodes()') - EXEC ('PRINT ''''') - END - - PRINT '-> sysdevices' - SELECT * from master.dbo.sysdevices - PRINT '' - - PRINT '-> sysdatabases' - SELECT * from master.dbo.sysdatabases - PRINT '' - - --Input buffers - PRINT 'Input buffer SPIDs' - - declare @spid smallint - declare @i_buff_string char(30) - set nocount on - declare bufCursor CURSOR FOR SELECT spid from master.dbo.sysprocesses where spid > 10 - FOR READ ONLY - open bufCursor - fetch next from bufCursor into @spid - while (@@fetch_status <> -1) - begin - SET @i_buff_string = ('DBCC INPUTBUFFER (' + convert(char(6),@spid) +')') - PRINT '-> '+@i_buff_string - exec (@i_buff_string) - PRINT '' - fetch next from bufCursor into @spid - end - close bufCursor - deallocate bufCursor - - PRINT '-> Head blockers' - - select spid as [Blocking spid],loginame,hostname,program_name as progname,cmd,status,physical_io,waittype - from master.dbo.sysprocesses - where spid in (select blocked from master.dbo.sysprocesses) - and blocked=0 - PRINT '' - - PRINT '-> SELECT @@version:' - PRINT @@VERSION - PRINT '' - - PRINT '-> Current login (SUSER_SNAME):' - PRINT SUSER_SNAME () - PRINT '' - - PRINT '-> SQL Server name (@@SERVERNAME):' - PRINT @@SERVERNAME - PRINT '' - - PRINT '-> Host (client) machine name (HOST_NAME):' - PRINT HOST_NAME() - PRINT '' - - PRINT '-> @@LANGUAGE:' - PRINT @@LANGUAGE - PRINT '' - - /* - PRINT '-> DBCC PSS(n):' - - DBCC TRACEON (3604) - DECLARE @sp int - DECLARE @cmd varchar(255) - DECLARE spid_curs INSENSITIVE CURSOR FOR - SELECT CONVERT (int, spid) AS spid - FROM master.dbo.sysprocesses WHERE spid > 6 - OPEN spid_curs - FETCH NEXT FROM spid_curs INTO @sp - WHILE (@@fetch_status <> -1) - BEGIN - IF (@@fetch_status <> -2) - BEGIN - PRINT '' - SET @cmd = 'DBCC PSS (0, ' + CONVERT (varchar, @sp) + ')' - PRINT '-> ' + @cmd - EXEC (@cmd) - PRINT '' - END - FETCH NEXT FROM spid_curs INTO @sp - END - CLOSE spid_curs - DEALLOCATE spid_curs - DBCC TRACEOFF(3604) - - */ - - PRINT '-> DBCC TRACESTATUS (-1):' - DBCC TRACESTATUS (-1) - PRINT '' - - PRINT '-> DBCC OPENTRAN (''''):' - - DECLARE @dbname sysname - DECLARE @tmpstr varchar(255) - -- Note: won't work for 7.0/2K db's with Unicode names, - -- but nvarchar won't work on 6.5. - DECLARE db_cursor cursor FOR - SELECT name FROM master.dbo.sysdatabases - WHERE status&32 + status&64 + status&128 + status&256 + status&512 = 0 - AND name NOT IN ('master', 'model', 'msdb', 'pubs', 'Northwind') - OPEN db_cursor - FETCH NEXT FROM db_cursor INTO @dbname - WHILE (@@fetch_status <> -1) - BEGIN - IF (@@fetch_status <> -2) - BEGIN - SET @tmpstr = 'DBCC OPENTRAN (''' + @dbname + ''')' - PRINT @tmpstr - EXEC (@tmpstr) - PRINT '' - END - FETCH NEXT FROM db_cursor INTO @dbname - END - CLOSE db_cursor - DEALLOCATE db_cursor - PRINT '' - - PRINT '-> DBCC SQLPERF (THREADS)' - DBCC SQLPERF (THREADS) - PRINT '' - - PRINT '-> DBCC SQLPERF (NETSTATS)' - DBCC SQLPERF (NETSTATS) - PRINT '' - - PRINT '-> DBCC SQLPERF (IOSTATS)' - DBCC SQLPERF (IOSTATS) - PRINT '' - - PRINT '-> DBCC SQLPERF (SPINLOCKSTATS)' - DBCC SQLPERF (SPINLOCKSTATS) - PRINT '' - - -- This is potentially too large (was 80MB in one case) to capture by default. - IF @bGetSyscacheobjects = 1 - BEGIN - PRINT '-> syscacheobjects' - SELECT * FROM master.dbo.syscacheobjects - PRINT '' - END - - PRINT '-> DBCC MEMORYSTATUS' - DBCC MEMORYSTATUS - PRINT '' - - PRINT '-> DBCC SQLPERF (UMSSTATS)' - DBCC SQLPERF (UMSSTATS) - PRINT '' - - PRINT '-> DBCC SQLPERF (WAITSTATS)' - DBCC SQLPERF (WAITSTATS) - PRINT '' - - PRINT '-> DBCC SQLPERF (LRUSTATS)' - DBCC SQLPERF (LRUSTATS) - PRINT '' - - PRINT '-> sysperfinfo snapshot #1' - PRINT CONVERT (varchar, GETDATE(), 109) - SELECT * FROM master.dbo.sysperfinfo - WAITFOR DELAY '0:0:05' - PRINT '-> sysperfinfo snapshot #2' - PRINT CONVERT (varchar, GETDATE(), 109) - SELECT * FROM master.dbo.sysperfinfo - PRINT '' - - PRINT '-> NET START' - EXEC master.dbo.xp_cmdshell 'NET START' - PRINT '' - - DECLARE @IsFullTextInstalled int - PRINT '-> Full-text information' - PRINT '-> FULLTEXTSERVICEPROPERTY (IsFulltextInstalled)' - SET @IsFullTextInstalled = FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled') - PRINT CASE @IsFullTextInstalled - WHEN 1 THEN '1 - Yes' - WHEN 0 THEN '0 - No' - ELSE 'Unknown' - END - IF (@IsFullTextInstalled = 1) - BEGIN - PRINT '-> FULLTEXTSERVICEPROPERTY (ResourceUsage)' - PRINT CASE FULLTEXTSERVICEPROPERTY ('ResourceUsage') - WHEN 0 THEN '0 - MSSearch not running' - WHEN 1 THEN '1 - Background' - WHEN 2 THEN '2 - Low' - WHEN 3 THEN '3 - Normal' - WHEN 4 THEN '4 - High' - WHEN 5 THEN '5 - Highest' - ELSE CONVERT (varchar, FULLTEXTSERVICEPROPERTY ('ResourceUsage')) - END - - PRINT '-> FULLTEXTSERVICEPROPERTY (ConnectTimeout)' - PRINT CONVERT (varchar, FULLTEXTSERVICEPROPERTY ('ConnectTimeout')) + ' sec' - PRINT '' - - DECLARE @dbn varchar(31) - DECLARE @cm varchar(8000) - DECLARE db_cursor CURSOR FOR - SELECT name FROM master.dbo.sysdatabases WHERE DATABASEPROPERTYEX (name, 'IsFulltextEnabled') = 1 - FOR READ ONLY - IF 0 = @@ERROR - BEGIN - OPEN db_cursor - IF 0 = @@ERROR - BEGIN - FETCH db_cursor INTO @dbn - WHILE @@FETCH_STATUS <> -1 AND 0 = @@ERROR - BEGIN - SELECT @cm = ' - USE ' + + @dbn + ' - PRINT ''-> sp_help_fulltext_catalogs'' - EXEC sp_help_fulltext_catalogs - PRINT ''-> sp_help_fulltext_tables'' - EXEC sp_help_fulltext_tables - PRINT ''-> sp_help_fulltext_columns'' - EXEC sp_help_fulltext_columns - PRINT ''-> Catalog properties'' - SELECT name, FULLTEXTCATALOGPROPERTY (name, ''ItemCount'') AS ItemCount, - CONVERT (varchar, FULLTEXTCATALOGPROPERTY (name, ''IndexSize'')) + ''MB'' AS IndexSize, - FULLTEXTCATALOGPROPERTY (name, ''UniqueKeyCount'') AS [Unique word count] - FROM sysfulltextcatalogs - USE master' - PRINT '-> Full text information for db [' + @dbn + ']' - EXEC(@cm) - FETCH db_cursor INTO @dbn - END - CLOSE db_cursor - END - DEALLOCATE db_cursor - END - END - PRINT '' - - PRINT '-> Relative time spent on I/O, CPU, and idle since server start' - SELECT @@CPU_BUSY AS [@@CPU_BUSY], @@IDLE AS [@@IDLE], @@IO_BUSY AS [@@IO_BUSY], - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@CPU_BUSY / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_CPU_BUSY, - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@IDLE / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_IDLE, - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@IO_BUSY / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_IO_BUSY - PRINT '' - - PRINT '-> Misc network and I/O stats' - SELECT @@PACK_RECEIVED AS [@@PACK_RECEIVED], @@PACK_SENT AS [@@PACK_SENT], - @@PACKET_ERRORS AS [@@PACKET_ERRORS (network errors e.g. 17824)] - SELECT @@TOTAL_READ AS [@@TOTAL_READ], @@TOTAL_WRITE AS [@@TOTAL_WRITE], - @@TOTAL_ERRORS AS [@@TOTAL_ERRORS (disk read/write I/O errors)] - ---- Disabled -- On Win2k winmsd calls a MMC snapin and this doesn't - ---- recognize the old winmsd cmd line params. - -- PRINT '' - -- PRINT '======== Generating WinMSD Report' - -- EXEC master.dbo.xp_cmdshell 'c: & cd \ & winmsd -a' - -- GO - PRINT '' - - PRINT '-> GETDATE()' - PRINT CONVERT (varchar, GETDATE(), 109) - PRINT '' - PRINT 'Done.' - GO - /*IF (CHARINDEX('7.00.',@@VERSION)<>0) OR (CHARINDEX('8.00.',@@VERSION)<>0) BEGIN - IF (OBJECT_ID('dbo.#sp_sqldiag07','P') IS NULL) RAISERROR('Error creating #sp_sqldiag07',16,127) - -- If running on 8.0, rename the proc to the 8.0 version - -- since the contents are the same and the collector expects ...08 - IF (CHARINDEX('8.00.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_sqldiag07 to #sp_sqldiag08', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_sqldiag08','P') IS NOT NULL drop proc dbo.#sp_sqldiag08 - EXEC sp_rename '#sp_sqldiag07', '#sp_sqldiag08' - IF (OBJECT_ID('dbo.#sp_sqldiag08','P') IS NULL) RAISERROR('Error renaming #sp_sqldiag07 to #sp_sqldiag08',16,127) - END - END*/ - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag08', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag08 @bGetSyscacheobjects int = 0 - AS - BEGIN - EXEC dbo.#sp_sqldiag07 @bGetSyscacheobjects - END - GO - - IF OBJECT_ID('dbo.#sp_sqldiag09','P') IS NOT NULL drop proc dbo.#sp_sqldiag09 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag09', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag09 @bGetQueryStats int = 0 - AS - - --PRINT 'Errorlogs' - --PRINT '---------' - - /* - declare @i tinyint, @res int - set @i=0 - while (@i<255) begin - if (0=@i) begin - print 'ERRORLOG' - exec @res=master.dbo.xp_readerrorlog - end else begin - print 'ERRORLOG.'+cast(@i as varchar(3)) - exec @res=master.dbo.xp_readerrorlog @i - end - if (@@error<>0) OR (@res<>0) break - set @i=@i+1 - end - */ - print '******************************attention******************************************************************' - print '*The errorlogs are moved to a filed called _SQL_Base_Errorlog_Shutdown.TXT *' - print '*********************************************************************************************************' - - - PRINT '' - - PRINT '-> sp_configure' - if (select value from sys.sysconfigures where config = 518) = 1 - begin - exec sp_configure - end - else - begin - exec sp_configure 'show advanced option',1 - reconfigure with override - exec sp_configure - exec sp_configure 'show advanced option',0 - reconfigure with override - end - - PRINT '-> sp_who' - exec sp_who - PRINT '' - - PRINT '-> sp_lock' - exec sp_lock - PRINT '' - - PRINT '-> sp_helpdb' - exec sp_helpdb - PRINT '' - - PRINT '-> xp_msver' - exec master.dbo.xp_msver - PRINT '' - - PRINT '-> sp_helpextendedproc' - exec sp_helpextendedproc - PRINT '' - - PRINT '-> sysprocesses' - select * from sys.sysprocesses - PRINT '' - - PRINT '-> sys.dm_exec_sessions' - select * from sys.dm_exec_sessions - PRINT '' - - PRINT '-> ::fn_virtualservernodes()' - SELECT * FROM ::fn_virtualservernodes() - PRINT '' - - PRINT '-> sysdevices' - select * from sys.sysdevices - PRINT '' - - PRINT '-> sysdatabases' - SELECT * from sys.sysdatabases - PRINT '' - - PRINT '-> sys.master_files' - select * from sys.master_files - PRINT '' - - --Input buffers - PRINT '-> Non-NULL input buffers by SPID' - SELECT - p.spid, - (select SUBSTRING (REPLACE (REPLACE (text, char(13), ' '), char(10), ' '), 1, 8000) FROM sys.dm_exec_sql_text(p.sql_handle)) AS query_text - FROM sys.sysprocesses p - WHERE p.spid>10 AND (select text FROM sys.dm_exec_sql_text(p.sql_handle)) IS NOT NULL - PRINT '' - - --Query stats - PRINT '-> Stats for currently running queries' - select TOP 10000 - r.*, - t.dbid, - t.objectid, - t.encrypted, - substring(t.text, statement_start_offset / 2, (case when statement_end_offset = -1 then datalength(t.text) else statement_end_offset end - statement_start_offset) / 2) as query_text - from sys.dm_exec_requests as r outer apply sys.dm_exec_sql_text(r.sql_handle) as t - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> Head blockers' - select * - from sys.sysprocesses - where spid in (select blocked from sys.sysprocesses) - and blocked=0 - PRINT '' - - PRINT '-> SELECT @@version:' - PRINT @@VERSION - PRINT '' - - PRINT '-> Current login (SUSER_SNAME):' - PRINT SUSER_SNAME () - PRINT '' - - PRINT '-> SQL Server name (@@SERVERNAME):' - PRINT @@SERVERNAME - PRINT '' - - PRINT '-> Host (client) machine name (HOST_NAME):' - PRINT HOST_NAME() - PRINT '' - - PRINT '-> @@LANGUAGE:' - PRINT @@LANGUAGE - PRINT '' - - PRINT '-> DBCC TRACESTATUS (-1):' - DBCC TRACESTATUS (-1) - PRINT '' - - PRINT '-> sys.dm_tran_database_transactions' - select TOP 10000 db_name(database_id), * from sys.dm_tran_database_transactions - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_tran_active_transactions' - select TOP 10000 * from sys.dm_tran_active_transactions - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - - PRINT '-> sys.dm_os_sys_info' - select TOP 10000 * from sys.dm_os_sys_info - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_schedulers' - select * from sys.dm_os_schedulers - PRINT '' - - PRINT '-> sys.dm_os_threads' - select TOP 10000 * from sys.dm_os_threads - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_workers' - select TOP 10000 * from sys.dm_os_workers - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_tasks' - select TOP 10000 * from sys.dm_os_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_io_pending_io_requests' - select TOP 10000 * from sys.dm_io_pending_io_requests - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_io_virtual_file_stats' - SELECT TOP 10000 * FROM sys.dm_io_virtual_file_stats(NULL, NULL) - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_latch_stats' - select TOP 10000 * from sys.dm_os_latch_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_sublatches' - select TOP 10000 * from sys.dm_os_sublatches - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_memory_pools' - select TOP 10000 * from sys.dm_os_memory_pools - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_memory_clerks' - select TOP 10000 * from sys.dm_os_memory_clerks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_wait_stats' - select TOP 10000 * from sys.dm_os_wait_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_waiting_tasks' - select TOP 10000 * from sys.dm_os_waiting_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_loaded_modules' - select TOP 10000 * from sys.dm_os_loaded_modules - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_cluster_nodes' - select * from sys.dm_os_cluster_nodes - PRINT '' - - PRINT '-> sys.dm_io_cluster_shared_drives' - select TOP 10000 * from sys.dm_io_cluster_shared_drives - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_appdomains' - select TOP 10000 * from sys.dm_clr_appdomains - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_loaded_assemblies' - select TOP 10000 * from sys.dm_clr_loaded_assemblies - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_properties' - select TOP 10000 * from sys.dm_clr_properties - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_tasks' - select TOP 10000 * from sys.dm_clr_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.assemblies' - select TOP 10000 * from sys.assemblies - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.assembly_modules' - select TOP 10000 * from sys.assembly_modules - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.assembly_types' - select TOP 10000 * from sys.assembly_types - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.database_files' - select TOP 10000 * from sys.database_files - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_db_file_space_usage' - select TOP 10000 * from sys.dm_db_file_space_usage - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_db_session_space_usage' - select TOP 10000 * from sys.dm_db_session_space_usage - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_db_task_space_usage' - select TOP 10000 * from sys.dm_db_task_space_usage - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_exec_query_optimizer_info' - select TOP 10000 * from sys.dm_exec_query_optimizer_info - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_broker_activated_tasks' - select TOP 10000 * from sys.dm_broker_activated_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_broker_connections' - select TOP 10000 * from sys.dm_broker_connections - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_broker_queue_monitors' - select TOP 10000 * from sys.dm_broker_queue_monitors - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - - -- This is potentially too large to capture by default. - IF @bGetQueryStats = 1 - BEGIN - PRINT '-> sys.dm_exec_query_stats' - SELECT TOP 10000 * FROM sys.dm_exec_query_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - END - - PRINT '-> sysperfinfo snapshot #1' - PRINT CONVERT (varchar, GETDATE(), 109) - SELECT * FROM sys.sysperfinfo - WAITFOR DELAY '0:0:05' - PRINT '-> sysperfinfo snapshot #2' - PRINT CONVERT (varchar, GETDATE(), 109) - SELECT * FROM sys.sysperfinfo - PRINT '' - - DECLARE @IsFullTextInstalled int - PRINT '-> Full-text information' - PRINT '-> FULLTEXTSERVICEPROPERTY (IsFulltextInstalled)' - SET @IsFullTextInstalled = FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled') - PRINT CASE @IsFullTextInstalled - WHEN 1 THEN '1 - Yes' - WHEN 0 THEN '0 - No' - ELSE 'Unknown' - END - IF (@IsFullTextInstalled = 1) - BEGIN - PRINT '-> FULLTEXTSERVICEPROPERTY (ResourceUsage)' - PRINT CASE FULLTEXTSERVICEPROPERTY ('ResourceUsage') - WHEN 0 THEN '0 - MSSearch not running' - WHEN 1 THEN '1 - Background' - WHEN 2 THEN '2 - Low' - WHEN 3 THEN '3 - Normal' - WHEN 4 THEN '4 - High' - WHEN 5 THEN '5 - Highest' - ELSE CONVERT (varchar, FULLTEXTSERVICEPROPERTY ('ResourceUsage')) - END - - PRINT '-> FULLTEXTSERVICEPROPERTY (ConnectTimeout)' - PRINT CONVERT (varchar, FULLTEXTSERVICEPROPERTY ('ConnectTimeout')) + ' sec' - PRINT '' - - PRINT '-> sys.dm_fts_active_catalogs' - select TOP 10000 * from sys.dm_fts_active_catalogs - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_fts_index_population' - select TOP 10000 * from sys.dm_fts_index_population - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_fts_memory_pools' - select TOP 10000 * from sys.dm_fts_memory_pools - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_fts_population_ranges' - select TOP 10000 * from sys.dm_fts_population_ranges - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> msdb..suspect_pages' - select TOP 10000 * from msdb..suspect_pages - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - DECLARE @dbn varchar(31) - DECLARE @cm varchar(8000) - DECLARE db_cursor CURSOR FOR - SELECT name FROM master.dbo.sysdatabases WHERE DATABASEPROPERTYEX (name, 'IsFulltextEnabled') = 1 - FOR READ ONLY - IF 0 = @@ERROR - BEGIN - OPEN db_cursor - IF 0 = @@ERROR - BEGIN - FETCH db_cursor INTO @dbn - WHILE @@FETCH_STATUS <> -1 AND 0 = @@ERROR - BEGIN - SELECT @cm = ' - USE ' + + @dbn + ' - PRINT ''-> sp_help_fulltext_catalogs'' - EXEC sp_help_fulltext_catalogs - PRINT ''-> sp_help_fulltext_tables'' - EXEC sp_help_fulltext_tables - PRINT ''-> sp_help_fulltext_columns'' - EXEC sp_help_fulltext_columns - PRINT ''-> Catalog properties'' - SELECT name, FULLTEXTCATALOGPROPERTY (name, ''ItemCount'') AS ItemCount, - CONVERT (varchar, FULLTEXTCATALOGPROPERTY (name, ''IndexSize'')) + ''MB'' AS IndexSize, - FULLTEXTCATALOGPROPERTY (name, ''UniqueKeyCount'') AS [Unique word count] - FROM sysfulltextcatalogs - USE tempdb' - PRINT '-> Full text information for db [' + @dbn + ']' - EXEC(@cm) - FETCH db_cursor INTO @dbn - END - CLOSE db_cursor - END - DEALLOCATE db_cursor - END - END - PRINT '' - - PRINT '-> Relative time spent on I/O, CPU, and idle since server start' - SELECT @@CPU_BUSY AS [@@CPU_BUSY], @@IDLE AS [@@IDLE], @@IO_BUSY AS [@@IO_BUSY], - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@CPU_BUSY / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_CPU_BUSY, - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@IDLE / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_IDLE, - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@IO_BUSY / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_IO_BUSY - PRINT '' - - PRINT '-> Misc network and I/O stats' - SELECT @@PACK_RECEIVED AS [@@PACK_RECEIVED], @@PACK_SENT AS [@@PACK_SENT], - @@PACKET_ERRORS AS [@@PACKET_ERRORS (network errors e.g. 17824)] - SELECT @@TOTAL_READ AS [@@TOTAL_READ], @@TOTAL_WRITE AS [@@TOTAL_WRITE], - @@TOTAL_ERRORS AS [@@TOTAL_ERRORS (disk read/write I/O errors)] - PRINT '' - - PRINT '-> GETDATE()' - PRINT CONVERT (varchar, GETDATE(), 109) - PRINT '' - PRINT 'Done.' - GO - - IF (CHARINDEX('9.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag09','P') IS NULL) - RAISERROR('Error creating #sp_sqldiag09',16,127) - GO - - IF OBJECT_ID('dbo.#sp_sqldiag10','P') IS NOT NULL drop proc dbo.#sp_sqldiag10 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag10', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag10 @bGetQueryStats int = 0 - AS - /* - PRINT 'Errorlogs' - PRINT '---------' - - declare @i tinyint, @res int - set @i=0 - while (@i<255) begin - if (0=@i) begin - print 'ERRORLOG' - exec @res=master.dbo.xp_readerrorlog - end else begin - print 'ERRORLOG.'+cast(@i as varchar(3)) - exec @res=master.dbo.xp_readerrorlog @i - end - if (@@error<>0) OR (@res<>0) break - set @i=@i+1 - end - */ - print '******************************attention******************************************************************' - print '*This method will cause errorlog to bloat with many padded empty strings. *' - print '*The errorlogs are moved to a filed called _SQL_Base_Errorlog_Shutdown.TXT *' - print '*********************************************************************************************************' - - PRINT '' - - PRINT '' - - PRINT '-> sp_configure' - if (select value from sys.sysconfigures where config = 518) = 1 - begin - exec sp_configure - end - else - begin - exec sp_configure 'show advanced option',1 - reconfigure with override - exec sp_configure - exec sp_configure 'show advanced option',0 - reconfigure with override - end - - PRINT '-> sp_who' - exec sp_who - PRINT '' - - PRINT '-> sp_lock' - exec sp_lock - PRINT '' - - PRINT '-> sp_helpdb' - exec sp_helpdb - PRINT '' - - PRINT '-> xp_msver' - exec master.dbo.xp_msver - PRINT '' - - PRINT '-> sp_helpextendedproc' - exec sp_helpextendedproc - PRINT '' - - PRINT '-> sysprocesses' - select * from sys.sysprocesses - PRINT '' - - PRINT '-> sys.dm_exec_sessions' - select * from sys.dm_exec_sessions - PRINT '' - - PRINT '-> ::fn_virtualservernodes()' - SELECT * FROM ::fn_virtualservernodes() - PRINT '' - - PRINT '-> sysdevices' - select * from sys.sysdevices - PRINT '' - - PRINT '-> sysdatabases' - SELECT * from sys.sysdatabases - PRINT '' - - PRINT '-> sys.master_files' - select * from sys.master_files - PRINT '' - - --Input buffers - PRINT '-> Non-NULL input buffers by SPID' - SELECT - p.spid, - (select SUBSTRING (REPLACE (REPLACE (text, char(13), ' '), char(10), ' '), 1, 8000) FROM sys.dm_exec_sql_text(p.sql_handle)) AS query_text - FROM sys.sysprocesses p - WHERE p.spid>10 AND (select text FROM sys.dm_exec_sql_text(p.sql_handle)) IS NOT NULL - PRINT '' - - --Query stats - PRINT '-> Stats for currently running queries' - select TOP 10000 - r.*, - t.dbid, - t.objectid, - t.encrypted, - substring(t.text, statement_start_offset / 2, (case when statement_end_offset = -1 then datalength(t.text) else statement_end_offset end - statement_start_offset) / 2) as query_text - from sys.dm_exec_requests as r outer apply sys.dm_exec_sql_text(r.sql_handle) as t - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> Head blockers' - select * - from sys.sysprocesses - where spid in (select blocked from sys.sysprocesses) - and blocked=0 - PRINT '' - - PRINT '-> SELECT @@version:' - PRINT @@VERSION - PRINT '' - - PRINT '-> Current login (SUSER_SNAME):' - PRINT SUSER_SNAME () - PRINT '' - - PRINT '-> SQL Server name (@@SERVERNAME):' - PRINT @@SERVERNAME - PRINT '' - - PRINT '-> Host (client) machine name (HOST_NAME):' - PRINT HOST_NAME() - PRINT '' - - PRINT '-> @@LANGUAGE:' - PRINT @@LANGUAGE - PRINT '' - - PRINT '-> DBCC TRACESTATUS (-1):' - DBCC TRACESTATUS (-1) - PRINT '' - - PRINT '-> sys.dm_tran_database_transactions' - select TOP 10000 db_name(database_id), * from sys.dm_tran_database_transactions - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_tran_active_transactions' - select TOP 10000 * from sys.dm_tran_active_transactions - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - - PRINT '-> sys.dm_os_sys_info' - select TOP 10000 * from sys.dm_os_sys_info - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_schedulers' - select * from sys.dm_os_schedulers - PRINT '' - - PRINT '-> sys.dm_os_threads' - select TOP 10000 * from sys.dm_os_threads - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_workers' - select TOP 10000 * from sys.dm_os_workers - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_tasks' - select TOP 10000 * from sys.dm_os_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_io_pending_io_requests' - select TOP 10000 * from sys.dm_io_pending_io_requests - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_io_virtual_file_stats' - SELECT TOP 10000 * FROM sys.dm_io_virtual_file_stats(NULL, NULL) - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_latch_stats' - select TOP 10000 * from sys.dm_os_latch_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_os_spinlock_stats' - select TOP 10000 * from sys.dm_os_spinlock_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_sublatches' - select TOP 10000 * from sys.dm_os_sublatches - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_memory_pools' - select TOP 10000 * from sys.dm_os_memory_pools - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_memory_clerks' - select TOP 10000 * from sys.dm_os_memory_clerks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_os_memory_brokers' - select TOP 10000 * from sys.dm_os_memory_brokers - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_os_memory_nodes' - select TOP 10000 * from sys.dm_os_memory_nodes - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_wait_stats' - select TOP 10000 * from sys.dm_os_wait_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_waiting_tasks' - select TOP 10000 * from sys.dm_os_waiting_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_loaded_modules' - select TOP 10000 * from sys.dm_os_loaded_modules - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_os_cluster_nodes' - select * from sys.dm_os_cluster_nodes - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_os_nodes' - select TOP 10000 * from sys.dm_os_nodes - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_os_process_memory' - select TOP 10000 * from sys.dm_os_process_memory - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_os_sys_memory' - select TOP 10000 * from sys.dm_os_sys_memory - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_io_cluster_shared_drives' - select TOP 10000 * from sys.dm_io_cluster_shared_drives - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_appdomains' - select TOP 10000 * from sys.dm_clr_appdomains - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_loaded_assemblies' - select TOP 10000 * from sys.dm_clr_loaded_assemblies - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_properties' - select TOP 10000 * from sys.dm_clr_properties - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_clr_tasks' - select TOP 10000 * from sys.dm_clr_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.assemblies' - select TOP 10000 * from sys.assemblies - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.assembly_modules' - select TOP 10000 * from sys.assembly_modules - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.assembly_types' - select TOP 10000 * from sys.assembly_types - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.database_files' - select TOP 10000 * from sys.database_files - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_db_file_space_usage' - select TOP 10000 * from sys.dm_db_file_space_usage - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_db_session_space_usage' - select TOP 10000 * from sys.dm_db_session_space_usage - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_db_task_space_usage' - select TOP 10000 * from sys.dm_db_task_space_usage - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_exec_query_optimizer_info' - select TOP 10000 * from sys.dm_exec_query_optimizer_info - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_exec_query_memory_grants' - select TOP 10000 * from sys.dm_exec_query_memory_grants - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_exec_query_resource_semaphores' - select TOP 10000 * from sys.dm_exec_query_resource_semaphores - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_exec_query_transformation_stats' - select TOP 10000 * from sys.dm_exec_query_transformation_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_broker_activated_tasks' - select TOP 10000 * from sys.dm_broker_activated_tasks - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_broker_connections' - select TOP 10000 * from sys.dm_broker_connections - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_broker_queue_monitors' - select TOP 10000 * from sys.dm_broker_queue_monitors - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_resource_governor_configuration' - select TOP 10000 * from sys.dm_resource_governor_configuration - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_resource_governor_resource_pools' - select TOP 10000 * from sys.dm_resource_governor_resource_pools - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_resource_governor_workload_groups' - select TOP 10000 * from sys.dm_resource_governor_workload_groups - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_database_encryption_keys' - select TOP 10000 * from sys.dm_database_encryption_keys - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_filestream_file_io_handles' - select TOP 10000 * from sys.dm_filestream_file_io_handles - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- New DMV in SQL Server 2008 - PRINT '-> sys.dm_filestream_file_io_requests' - select TOP 10000 * from sys.dm_filestream_file_io_requests - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - -- This is potentially too large to capture by default. - IF @bGetQueryStats = 1 - BEGIN - PRINT '-> sys.dm_exec_query_stats' - SELECT TOP 10000 * FROM sys.dm_exec_query_stats - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - END - - PRINT '-> sysperfinfo snapshot #1' - PRINT CONVERT (varchar, GETDATE(), 109) - SELECT * FROM sys.sysperfinfo - WAITFOR DELAY '0:0:05' - PRINT '-> sysperfinfo snapshot #2' - PRINT CONVERT (varchar, GETDATE(), 109) - SELECT * FROM sys.sysperfinfo - PRINT '' - - DECLARE @IsFullTextInstalled int - PRINT '-> Full-text information' - PRINT '-> FULLTEXTSERVICEPROPERTY (IsFulltextInstalled)' - SET @IsFullTextInstalled = FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled') - PRINT CASE @IsFullTextInstalled - WHEN 1 THEN '1 - Yes' - WHEN 0 THEN '0 - No' - ELSE 'Unknown' - END - IF (@IsFullTextInstalled = 1) - BEGIN - PRINT '-> FULLTEXTSERVICEPROPERTY (ResourceUsage)' - PRINT CASE FULLTEXTSERVICEPROPERTY ('ResourceUsage') - WHEN 0 THEN '0 - MSSearch not running' - WHEN 1 THEN '1 - Background' - WHEN 2 THEN '2 - Low' - WHEN 3 THEN '3 - Normal' - WHEN 4 THEN '4 - High' - WHEN 5 THEN '5 - Highest' - ELSE CONVERT (varchar, FULLTEXTSERVICEPROPERTY ('ResourceUsage')) - END - - PRINT '-> FULLTEXTSERVICEPROPERTY (ConnectTimeout)' - PRINT CONVERT (varchar, FULLTEXTSERVICEPROPERTY ('ConnectTimeout')) + ' sec' - PRINT '' - - PRINT '-> sys.dm_fts_active_catalogs' - select TOP 10000 * from sys.dm_fts_active_catalogs - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_fts_index_population' - select TOP 10000 * from sys.dm_fts_index_population - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_fts_memory_pools' - select TOP 10000 * from sys.dm_fts_memory_pools - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> sys.dm_fts_population_ranges' - select TOP 10000 * from sys.dm_fts_population_ranges - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - PRINT '-> msdb..suspect_pages' - select TOP 10000 * from msdb..suspect_pages - IF @@rowcount >= 10000 PRINT '<<<<< LIMIT OF 10000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' - PRINT '' - - DECLARE @dbn varchar(31) - DECLARE @cm varchar(8000) - DECLARE db_cursor CURSOR FOR - SELECT name FROM master.dbo.sysdatabases WHERE DATABASEPROPERTYEX (name, 'IsFulltextEnabled') = 1 - FOR READ ONLY - IF 0 = @@ERROR - BEGIN - OPEN db_cursor - IF 0 = @@ERROR - BEGIN - FETCH db_cursor INTO @dbn - WHILE @@FETCH_STATUS <> -1 AND 0 = @@ERROR - BEGIN - SELECT @cm = ' - USE ' + + @dbn + ' - PRINT ''-> sp_help_fulltext_catalogs'' - EXEC sp_help_fulltext_catalogs - PRINT ''-> sp_help_fulltext_tables'' - EXEC sp_help_fulltext_tables - PRINT ''-> sp_help_fulltext_columns'' - EXEC sp_help_fulltext_columns - PRINT ''-> Catalog properties'' - SELECT name, FULLTEXTCATALOGPROPERTY (name, ''ItemCount'') AS ItemCount, - CONVERT (varchar, FULLTEXTCATALOGPROPERTY (name, ''IndexSize'')) + ''MB'' AS IndexSize, - FULLTEXTCATALOGPROPERTY (name, ''UniqueKeyCount'') AS [Unique word count] - FROM sysfulltextcatalogs - USE tempdb' - PRINT '-> Full text information for db [' + @dbn + ']' - EXEC(@cm) - FETCH db_cursor INTO @dbn - END - CLOSE db_cursor - END - DEALLOCATE db_cursor - END - END - PRINT '' - - PRINT '-> Relative time spent on I/O, CPU, and idle since server start' - SELECT @@CPU_BUSY AS [@@CPU_BUSY], @@IDLE AS [@@IDLE], @@IO_BUSY AS [@@IO_BUSY], - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@CPU_BUSY / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_CPU_BUSY, - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@IDLE / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_IDLE, - CONVERT (varchar(8), CONVERT (numeric (6, 4), (100.0 * @@IO_BUSY / (@@CPU_BUSY + @@IDLE + @@IO_BUSY)))) + '%' AS Pct_IO_BUSY - PRINT '' - - PRINT '-> Misc network and I/O stats' - SELECT @@PACK_RECEIVED AS [@@PACK_RECEIVED], @@PACK_SENT AS [@@PACK_SENT], - @@PACKET_ERRORS AS [@@PACKET_ERRORS (network errors e.g. 17824)] - SELECT @@TOTAL_READ AS [@@TOTAL_READ], @@TOTAL_WRITE AS [@@TOTAL_WRITE], - @@TOTAL_ERRORS AS [@@TOTAL_ERRORS (disk read/write I/O errors)] - PRINT '' - - PRINT '-> GETDATE()' - PRINT CONVERT (varchar, GETDATE(), 109) - PRINT '' - PRINT 'Done.' - GO - - /* - The board chagned the Product Version format in Katmai. The current foramt starting from Katmai will be single zero for minor version instead of two zeros in previous sql versions. `" 10.m.bbbb.rr `" - */ - IF (CHARINDEX('10.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag10','P') IS NULL) - RAISERROR('Error creating #sp_sqldiag10',16,127) - GO - - /* SQL11 Version Bump */ - - IF OBJECT_ID('dbo.#sp_sqldiag11','P') IS NOT NULL drop proc dbo.#sp_sqldiag11 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag11', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag11 @bGetQueryStats int = 0 - AS - BEGIN - EXEC dbo.#sp_sqldiag10 @bGetQueryStats - END - GO - IF (CHARINDEX('11.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag11','P') IS NULL) - RAISERROR('Error creating #sp_sqldiag11',16,127) - GO - - /* SQL14 Version Bump */ - - IF OBJECT_ID('dbo.#sp_sqldiag12','P') IS NOT NULL drop proc dbo.#sp_sqldiag12 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag12', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag12 @bGetQueryStats int = 0 - AS - BEGIN - EXEC dbo.#sp_sqldiag10 @bGetQueryStats - --Buffer Pool Extensions -- - RAISERROR ('-- sys.dm_os_buffer_pool_extension_configuration --', 0, 1) WITH NOWAIT - SELECT * FROM sys.dm_os_buffer_pool_extension_configuration - - --Smart Backups -- - - RAISERROR ('-- autoadmin_managed_databases --', 0, 1) WITH NOWAIT - select * from [msdb].[dbo].[autoadmin_managed_databases] - - RAISERROR ('-- autoadmin_system_flags --', 0, 1) WITH NOWAIT - select * from [msdb].[dbo].[autoadmin_system_flags] - - RAISERROR ('-- autoadmin_task_agent_metadata --', 0, 1) WITH NOWAIT - select * from [msdb].[dbo].[autoadmin_task_agent_metadata] - - RAISERROR ('-- sysjobhistory --', 0, 1) WITH NOWAIT - select * from [msdb].[dbo].[sysjobhistory] - - - - END - GO - IF (CHARINDEX('12.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag12','P') IS NULL) - RAISERROR('Error creating #sp_sqldiag12',16,127) - GO - - /* SQL15 Version Bump */ - - IF OBJECT_ID('dbo.#sp_sqldiag13','P') IS NOT NULL drop proc dbo.#sp_sqldiag13 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag13', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag13 @bGetQueryStats int = 0 - AS - BEGIN - EXEC dbo.#sp_sqldiag10 @bGetQueryStats - END - GO - IF (CHARINDEX('13.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag13','P') IS NULL) - RAISERROR('Error creating #sp_sqldiag13',16,127) - - /* - - #sp_trace - - */ - - IF OBJECT_ID('dbo.#sp_trace07','P') IS NOT NULL - DROP PROC dbo.#sp_trace07 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace07', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace07 @OnOff varchar(3)='/?', @FileName sysname=NULL, @TraceName sysname='#sp_trace', - @Events varchar(300)=NULL, @Cols int=NULL, - @TraceType int=0, - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, - @IncludeAppFilter sysname=NULL, @ExcludeAppFilter sysname='SQLAgent%;SQL Server Profiler%', - @IncludeConnectionIdFilter int=NULL, - @MinCPUFilter int=0, @MaxCPUFilter int=0, - @IncludeDBIdFilter int=NULL, - @MinDurationFilter int=0, @MaxDurationFilter int=0, - @IncludeNTNameFilter sysname=NULL, @ExcludeNTNameFilter sysname=NULL, - @MinReadFilter int=0, @MaxReadFilter int=0, - @IncludeServerFilter sysname=NULL, @ExcludeServerFilter sysname=NULL, - @IncludeSPIdFilter int=NULL, - @IncludeUserFilter sysname=NULL, @ExcludeUserFilter sysname=NULL, - @MinWriteFilter int=0, @MaxWriteFilter int=0, - @MinSeverityFilter int=0, @MaxSeverityFilter int=0, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname='PSSDIAG%', - @IncludeHpIdFilter int=NULL, - @IncludeIndIdFilter int=NULL, - @IncludeNTDomainFilter sysname=NULL, @ExcludeNTDomainFilter sysname=NULL, - @IncludeSysobjectsFilter int=NULL, - @AppName sysname='PSSDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - SET NOCOUNT ON - - IF (@OnOff='/?') GOTO Help - SET @OnOff=UPPER(@OnOff) - IF (@OnOff<>'ON') AND (@OnOff<>'OFF') BEGIN - RAISERROR('The @OnOff parameter must be either ''ON'' or ''OFF''.',16,10) - RETURN -1 - END - - IF (ABS(@IncludeSysobjectsFilter)>1) BEGIN - RAISERROR('The @IncludeSysobjectsFilter parameter must be either 0 or 1.',16,10) - RETURN -1 - END - - -- Declare variables - DECLARE @OldQueueHandle int -- Queue handle of currently running trace queue - DECLARE @QueueHandle int -- Queue handle for new trace queue - DECLARE @OldFileName sysname -- Output file for currently trace - - -- Stop the trace if running - PRINT 'Stopping the trace if it is running...' - IF OBJECT_ID('tempdb.dbo.PSSDIAGTraceQueue') IS NOT NULL BEGIN - IF EXISTS(SELECT * FROM tempdb.dbo.PSSDIAGTraceQueue WHERE QueueName = @TraceName AND AppName=@AppName) BEGIN - - SELECT @OldQueueHandle = QueueHandle, @OldFileName= QueueFile - FROM tempdb.dbo.PSSDIAGTraceQueue - WHERE QueueName = @TraceName - AND AppName=@AppName - - IF @@ROWCOUNT<>0 BEGIN - EXEC master..xp_trace_destroyqueue @OldQueueHandle - PRINT 'Deleted trace: ' + @TraceName+', Queue: '+CAST(@OldQueueHandle AS varchar)+'.' - PRINT 'The trace output file name is: '+@OldFileName+'.' - DELETE tempdb.dbo.PSSDIAGTraceQueue WHERE QueueName = @TraceName AND AppName=@AppName - END - END ELSE PRINT 'No active traces named '+@TraceName - END ELSE PRINT 'No active traces.' - - IF @OnOff='OFF' RETURN 0 -- We've stopped the trace (if it's running), so exit - - -- Append the datetime to the file name to create a new, unique file name. - IF @FileName IS NULL SET @FileName = 'c:\TEMP\#sp_trace_' + CONVERT(CHAR(8),getdate(),112) + REPLACE(CONVERT(varchar(15),getdate(),114),':','')+'.trc' - - -- Set the column mask for the data columns to capture. - -- Text data | Binary data | Database ID | Transaction ID | Connection ID| - -- Username | Domain name | Host name | Host process ID | Application name| - -- SQL username | SPID | Duration | Start time | End time | Reads | Writes| - -- CPU usage | Severity | Event Subclass | Object ID | Index ID | - -- Integer data | Server name | Event Class - IF @Cols IS NULL - SET @Cols = 1|/*2|*/4|8|16|32|64|128|256|512|1024|2048|4096|8192|16384|32768| - 65536|131072|524288|1048576|2097152|8388608|16777216|33554432|67108864 - - -- Create the trace queue - EXEC master..xp_trace_addnewqueue 11000, 10000, 95, 90, @Cols, @QueueHandle output - - -- Record the trace queue handle for subsequent jobs. (This allows us to know how to stop our trace.) - IF OBJECT_ID('tempdb.dbo.PSSDIAGTraceQueue') IS NULL BEGIN - CREATE TABLE tempdb.dbo.PSSDIAGTraceQueue (QueueHandle int, QueueName sysname, QueueFile sysname, AppName sysname ) - INSERT tempdb.dbo.PSSDIAGTraceQueue VALUES(@QueueHandle, @TraceName, @FileName, @AppName) - END ELSE BEGIN - IF EXISTS(SELECT * FROM tempdb.dbo.PSSDIAGTraceQueue WHERE QueueName = @TraceName AND AppName=@AppName) BEGIN - UPDATE tempdb.dbo.PSSDIAGTraceQueue SET QueueHandle = @QueueHandle WHERE QueueName = @TraceName AND AppName=@AppName - END ELSE BEGIN - INSERT tempdb.dbo.PSSDIAGTraceQueue VALUES(@QueueHandle, @TraceName, @FileName, @AppName) - END - END - - -- Set filters (default values avoid tracing the trace activity itself) - -- You can specify other filters like application name etc. by supplying strings to the @IncludeTextFilter/@ExcludeTextFilter parameters, separated by semicolons - SET @ExcludeTextFilter='EXEC% master..xp_trace%;#sp_trace%;EXEC% #sp_trace%'+ISNULL(';'+@ExcludeTextFilter,'') -- Keep our own activity from showing up - EXEC master..xp_trace_settextfilter @QueueHandle, @IncludeTextFilter, @ExcludeTextFilter - EXEC master..xp_trace_setappfilter @QueueHandle, @IncludeAppFilter, @ExcludeAppFilter - EXEC master..xp_trace_setcpufilter @QueueHandle, @MinCPUFilter, @MaxCPUFilter - EXEC master..xp_trace_setdurationfilter @QueueHandle, @MinDurationFilter, @MaxDurationFilter - EXEC master..xp_trace_setntnmfilter @QueueHandle, @IncludeNTNameFilter, @ExcludeNTNameFilter - EXEC master..xp_trace_setreadfilter @QueueHandle, @MinReadFilter, @MaxReadFilter - EXEC master..xp_trace_setserverfilter @QueueHandle, @IncludeServerFilter, @ExcludeServerFilter - EXEC master..xp_trace_setuserfilter @QueueHandle, @IncludeUserFilter, @ExcludeUserFilter - EXEC master..xp_trace_setwritefilter @QueueHandle, @MinWriteFilter, @MaxWriteFilter - EXEC master..xp_trace_setseverityfilter @QueueHandle, @MinSeverityFilter, @MaxSeverityFilter - EXEC master..xp_trace_sethostfilter @QueueHandle, @IncludeHostFilter, @ExcludeHostFilter - EXEC master..xp_trace_setntdmfilter @QueueHandle, @IncludeNTDomainFilter, @ExcludeNTDomainFilter - IF @IncludeObjIdFilter IS NOT NULL - EXEC master..xp_trace_setobjidfilter @QueueHandle, @IncludeObjIdFilter - IF @IncludeConnectionIdFilter IS NOT NULL - EXEC master..xp_trace_setconnectionidfilter @QueueHandle, @IncludeConnectionIdFilter - IF @IncludeDBIdFilter IS NOT NULL - EXEC master..xp_trace_setdbidfilter @QueueHandle, @IncludeDBIdFilter - IF @IncludeSPIdFilter IS NOT NULL - EXEC master..xp_trace_setspidfilter @QueueHandle, @IncludeSPIdFilter - IF @IncludeHpIdFilter IS NOT NULL - EXEC master..xp_trace_sethpidfilter @QueueHandle, @IncludeHpIdFilter - IF @IncludeIndIdFilter IS NOT NULL - EXEC master..xp_trace_setindidfilter @QueueHandle, @IncludeIndIdFilter - IF @IncludeSysobjectsFilter IS NOT NULL - EXEC master..xp_trace_setsysobjectsfilter @QueueHandle, @IncludeSysobjectsFilter - - -- Specify the event classes to trace - -- To list all the event classes, execute the procedure xp_trace_geteventnames using Query Analyzer - -- or look up for that procedure in SQL Server BOL and add to the following list as needed - IF @Events IS NULL BEGIN - IF @TraceType=0 BEGIN -- Minimal trace - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 55 ,1 -- Hash Warning - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 67 ,1 -- Execution Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 69 ,1 -- Sort Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 11 ,1 -- RPC:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 13 ,1 -- SQL:BatchStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 42 ,1 -- SP:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 43 ,1 -- SP:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 45 ,1 -- SP:StmtCompleted - END ELSE IF @TraceType=1 BEGIN -- Generic replay trace - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 21 ,1 -- EventLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 22 ,1 -- ErrorLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 55 ,1 -- Hash Warning - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 61 ,1 -- OLEDB Errors - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 67 ,1 -- Execution Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 69 ,1 -- Sort Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 25 ,1 -- Lock:Deadlock - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 27 ,1 -- Lock:Timeout - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 59 ,1 -- Lock:Deadlock Chain - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 58 ,1 -- Auto-UpdateStats - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 81 ,1 -- Server Memory Change - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 18 ,1 -- ServiceControl - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 32 ,1 -- ConnectionBeingKilled - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - DBCC TRACEON (8510, -1) -- 8510 is necessary for DTCTransaction to correctly report isolation levels - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 19 ,1 -- DTCTransaction - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 11 ,1 -- RPC:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 10 ,1 -- RPC:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 13 ,1 -- SQL:BatchStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 12 ,1 -- SQL:BatchCompleted - END ELSE IF @TraceType=2 BEGIN -- Minimal performance trace - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 75 ,1 -- Cursor Recompile - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 21 ,1 -- EventLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 22 ,1 -- ErrorLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 55 ,1 -- Hash Warning - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 61 ,1 -- OLEDB Errors - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 67 ,1 -- Execution Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 69 ,1 -- Sort Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 25 ,1 -- Lock:Deadlock - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 27 ,1 -- Lock:Timeout - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 59 ,1 -- Lock:Deadlock Chain - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 58 ,1 -- Auto-UpdateStats - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 81 ,1 -- Server Memory Change - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 18 ,1 -- ServiceControl - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 32 ,1 -- ConnectionBeingKilled - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 37 ,1 -- SP:Recompile - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 10 ,1 -- RPC:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 12 ,1 -- SQL:BatchCompleted - END ELSE IF @TraceType=3 BEGIN -- General performance trace - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 75 ,1 -- Cursor Recompile - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 76 ,1 -- Cursor Implicit Conversion - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 21 ,1 -- EventLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 22 ,1 -- ErrorLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 55 ,1 -- Hash Warning - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 61 ,1 -- OLEDB Errors - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 67 ,1 -- Execution Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 69 ,1 -- Sort Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 25 ,1 -- Lock:Deadlock - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 27 ,1 -- Lock:Timeout - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 59 ,1 -- Lock:Deadlock Chain - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 58 ,1 -- Auto-UpdateStats - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 81 ,1 -- Server Memory Change - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 18 ,1 -- ServiceControl - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 32 ,1 -- ConnectionBeingKilled - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 34 ,1 -- SP:CacheMiss - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 35 ,1 -- SP:CacheInsert - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 36 ,1 -- SP:CacheRemove - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 37 ,1 -- SP:Recompile - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 38 ,1 -- SP:CacheHit - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 39 ,1 -- SP:ExecContextHit - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 50 ,1 -- SQLTransaction - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 11 ,1 -- RPC:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 10 ,1 -- RPC:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 13 ,1 -- SQL:BatchStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 12 ,1 -- SQL:BatchCompleted - END ELSE IF @TraceType=4 BEGIN -- Detailed performance trace - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 53 ,1 -- Cursor Open - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 75 ,1 -- Cursor Recompile - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 76 ,1 -- Cursor Implicit Conversion - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 21 ,1 -- EventLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 22 ,1 -- ErrorLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 55 ,1 -- Hash Warning - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 61 ,1 -- OLEDB Errors - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 67 ,1 -- Execution Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 69 ,1 -- Sort Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 25 ,1 -- Lock:Deadlock - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 27 ,1 -- Lock:Timeout - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 59 ,1 -- Lock:Deadlock Chain - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 60 ,1 -- Lock:Escalation - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 58 ,1 -- Auto-UpdateStats - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 68 ,1 -- Execution Plan - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 20 ,1 -- LoginFailed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 81 ,1 -- Server Memory Change - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 18 ,1 -- ServiceControl - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 32 ,1 -- ConnectionBeingKilled - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 34 ,1 -- SP:CacheMiss - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 35 ,1 -- SP:CacheInsert - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 36 ,1 -- SP:CacheRemove - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 37 ,1 -- SP:Recompile - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 38 ,1 -- SP:CacheHit - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 39 ,1 -- SP:ExecContextHit - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 42 ,1 -- SP:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 43 ,1 -- SP:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 44 ,1 -- SP:StmtStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 45 ,1 -- SP:StmtCompleted - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 50 ,1 -- SQLTransaction - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 11 ,1 -- RPC:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 10 ,1 -- RPC:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 13 ,1 -- SQL:BatchStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 12 ,1 -- SQL:BatchCompleted - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 40 ,1 -- SQL:StmtStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 41 ,1 -- SQL:StmtCompleted - END ELSE IF @TraceType=5 BEGIN -- DTC replay trace - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 11 ,1 -- RPC:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 10 ,1 -- RPC:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 13 ,1 -- SQL:BatchStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 12 ,1 -- SQL:BatchCompleted - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 50 ,1 -- SQLTransaction - DBCC TRACEON (8510, -1) -- 8510 is necessary for DTCTransaction to correctly report isolation levels - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 19 ,1 -- DTCTransaction - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 21 ,1 -- EventLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 22 ,1 -- ErrorLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - END ELSE IF @TraceType=6 BEGIN -- Itemized (semi-detailed) performance trace (no execution plan) - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 53 ,1 -- Cursor Open - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 75 ,1 -- Cursor Recompile - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 76 ,1 -- Cursor Implicit Conversion - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 21 ,1 -- EventLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 22 ,1 -- ErrorLog - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 33 ,1 -- Exception - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 55 ,1 -- Hash Warning - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 61 ,1 -- OLEDB Errors - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 67 ,1 -- Execution Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 69 ,1 -- Sort Warnings - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 79 ,1 -- Missing Column Statistics - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 80 ,1 -- Missing Join Predicate - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 25 ,1 -- Lock:Deadlock - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 27 ,1 -- Lock:Timeout - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 59 ,1 -- Lock:Deadlock Chain - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 60 ,1 -- Lock:Escalation - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 16 ,1 -- Attention - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 58 ,1 -- Auto-UpdateStats - -- EXEC master..xp_trace_seteventclassrequired @QueueHandle, 68 ,1 -- Execution Plan - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 20 ,1 -- LoginFailed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 81 ,1 -- Server Memory Change - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 18 ,1 -- ServiceControl - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 32 ,1 -- ConnectionBeingKilled - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 14 ,1 -- Connect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 15 ,1 -- Disconnect - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 17 ,1 -- Existing Connection - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 34 ,1 -- SP:CacheMiss - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 35 ,1 -- SP:CacheInsert - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 36 ,1 -- SP:CacheRemove - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 37 ,1 -- SP:Recompile - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 38 ,1 -- SP:CacheHit - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 39 ,1 -- SP:ExecContextHit - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 42 ,1 -- SP:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 43 ,1 -- SP:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 44 ,1 -- SP:StmtStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 45 ,1 -- SP:StmtCompleted - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 50 ,1 -- SQLTransaction - - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 11 ,1 -- RPC:Starting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 10 ,1 -- RPC:Completed - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 13 ,1 -- SQL:BatchStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 12 ,1 -- SQL:BatchCompleted - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 40 ,1 -- SQL:StmtStarting - EXEC master..xp_trace_seteventclassrequired @QueueHandle, 41 ,1 -- SQL:StmtCompleted - END ELSE BEGIN - RAISERROR('Invalid trace type.',16,10) - DBCC TRACEOFF(3604) - RETURN -1 - END - END ELSE BEGIN -- Loop through the @Events string, parsing out each event number and adding it to the queue definition - IF RIGHT(@Events,1)<>',' SET @Events=@Events+',' -- Append a comma to satisfy the loop - DECLARE @i int, @Event int - SET @i=CHARINDEX(',',@Events) - WHILE @i<>0 BEGIN - SET @Event=CAST(LEFT(@Events,@i-1) AS int) - EXEC master..xp_trace_seteventclassrequired @QueueHandle, @Event ,1 - SET @Events=SUBSTRING(@Events,@i+1,300) - SET @i=CHARINDEX(',',@Events) - END - END - - - -- Delete the file if it exists - DECLARE @cmd varchar(8000) - SET @cmd='DEL '+@FileName - EXEC master..xp_cmdshell @cmd - - -- Configure the queue to write to a file - PRINT 'The new trace output file name is : '+@FileName+'.' - EXEC master..xp_trace_setqueuedestination @QueueHandle, 2, 1, NULL, @FileName - - -- Start the consumer that actually writes to the file - EXEC master..xp_trace_startconsumer @QueueHandle - - RETURN 0 - - Help: - DECLARE @crlf char(2), @tabc char(1) - SET @crlf=char(13)+char(10) - SET @tabc=char(9) - PRINT '#sp_trace -- Starts/stops a Profiler-like trace using Transact-SQL eXtended Procedure calls' - PRINT @crlf+'Parameters:' - PRINT @tabc+'Parameter Type Default Purpose' - PRINT @tabc+'-------------------------- ------------ ------------------------------ ------------------------------------------------------------------------------------------' - PRINT @tabc+'@OnOff varchar(3) /? Starts/stops the trace (or lists help info)' - PRINT @tabc+'@FileName sysname c:\temp\YYYYMMDDhhmissmmm.trc Trace file name' - PRINT @tabc+'@TraceName sysname #sp_trace Specifies the name of the trace' - PRINT @tabc+'@TraceType int 0 Type of trace: 0=Minimal, 1=Generic replay, 2=Minimal performance, 3=General performance, 4=Detailed performance, 5=DTC replay, 6=Itemized (semi-detailed) performance' - PRINT @tabc+'@Events varchar(300) SP events, errors & warnings Comma-delimited list specifying the events numbers (per xp_trace_geteventnames) to trace' - PRINT @tabc+'@Cols int All columns except BinaryData Bitmask specifying what columns (per xp_trace_addnewqueue) to include in the trace' - PRINT @tabc+'@IncludeTextFilter sysname NULL Semicolon delimited list specifying what TextData strings to include in the trace' - PRINT @tabc+'@ExcludeTextFilter sysname NULL Semicolon delimited list specifying what TextData strings to filter out of the trace' - PRINT @tabc+'@IncludeObjIdFilter sysname NULL Id of an object to target with the trace' - PRINT @tabc+'@IncludeAppFilter sysname NULL Semicolon delimited list of AppNames to include in the trace' - PRINT @tabc+'@ExcludeAppFilter sysname SQLAgent%;SQL Server Profiler% Semicolon delimited list of AppNames to filter out of the trace' - PRINT @tabc+'@IncludeConnectionIdFilter int NULL Id of a connection to target with the trace' - PRINT @tabc+'@MinCPUFilter int 0 Minimum CPU time (in ms) to include for the events specified' - PRINT @tabc+'@MaxCPUFilter int 0 Maximum CPU time (in ms) to include for the events specified' - PRINT @tabc+'@IncludeDBIdFilter int NULL Id of the database to target with the trace' - PRINT @tabc+'@MinDurationFilter int 0 Minimum event duration (in ms) to capture for the events specified' - PRINT @tabc+'@MaxDurationFilter int 0 Maximum event duration (in ms) to capture for the events specified' - PRINT @tabc+'@IncludeNTNameFilter sysname NULL, Semicolon delimited list of NT user names to include in the trace' - PRINT @tabc+'@ExcludeNTNameFilter sysname NULL Semicolon delimited list of NT user names to filter out of the trace' - PRINT @tabc+'@MinReadFilter int 0 Minimum number of logical read operations to capture for the events specified' - PRINT @tabc+'@MaxReadFilter int 0 Maximum number of logical read operations to capture for the events specified' - PRINT @tabc+'@IncludeServerFilter sysname NULL Semicolon delimited list of server names to include in the trace' - PRINT @tabc+'@ExcludeServerFilter sysname NULL Semicolon delimited list of server names to filter out of the trace' - PRINT @tabc+'@IncludeSPIdFilter int NULL Id of the user process to target with the trace' - PRINT @tabc+'@IncludeUserFilter sysname NULL Semicolon delimited list of user names to include in the trace' - PRINT @tabc+'@ExcludeUserFilter sysname NULL Semicolon delimited list of user names to exclude from the trace' - PRINT @tabc+'@MinWriteFilter int 0 Minimum number of logical write operations to capture for the events specified' - PRINT @tabc+'@MaxWriteFilter int 0 Maximum number of logical write operations to capture for the events specified' - PRINT @tabc+'@MinSeverityFilter int 0 Minimum event severity level to capture for the events specified' - PRINT @tabc+'@MaxSeverityFilter int 0 Maximum event severity level to capture for the events specified' - PRINT @tabc+'@IncludeHostFilter sysname NULL Semicolon delimited list of host names to include in the trace' - PRINT @tabc+'@ExcludeHostFilter sysname NULL Semicolon delimited list of host names to exclude from the trace' - PRINT @tabc+'@IncludeHpIdFilter int NULL Id of the host process to target with the trace' - PRINT @tabc+'@IncludeIndIdFilter int NULL Id of the index to target with the trace' - PRINT @tabc+'@IncludeNTDomainFilter sysname NULL Semicolon delimited list of NT domain names to include in the trace' - PRINT @tabc+'@ExcludeNTDomainFilter sysname NULL Semicolon delimited list of NT domain names to exclude from the trace' - PRINT @tabc+'@IncludeSysobjectsFilter int NULL Integer specifying whether to include system objects in the trace (1=Yes, 0=No)' - PRINT @crlf+'Supported events:' - EXEC master..xp_trace_geteventnames - PRINT @crlf+'Examples: ' - PRINT @crlf+@tabc+'EXEC #sp_trace' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON''' - PRINT @crlf+@tabc+'EXEC #sp_trace ''OFF''' - PRINT @crlf+@tabc+'EXEC #sp_trace @OnOff=''ON'', @filename=''d:\mssql7\log\mytrace.trc''' - PRINT @crlf+@tabc+'EXEC #sp_trace @OnOff=''ON'', @Events=''37,43''' - PRINT @crlf+@tabc+'DECLARE @ColsToGet int' - PRINT @tabc+'SET @ColsToGet=4 | 4096 | 2097152' - PRINT @tabc+'EXEC #sp_trace @OnOff=''ON'', @Cols=@ColsToGet' - PRINT @crlf+@tabc+'EXEC #sp_trace @OnOff=''ON'', @IncludeTextFilter=''EXEC FooProc%''' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@tracename=''General Performance''' - PRINT @crlf+@tabc+'EXEC #sp_trace ''OFF'',@tracename=''General Performance''' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@filename = ''d:\mssql7\log\mytrace'',' - PRINT @tabc+@tabc+'@TraceName = ''General Performance'',' - PRINT @tabc+@tabc+'@TraceType = 0,' - PRINT @tabc+@tabc+'@Events = ''10,11,14,15,16,17,27,37,40,41,55'',' - PRINT @tabc+@tabc+'@Cols = DEFAULT,' - PRINT @tabc+@tabc+'@IncludeTextFilter = NULL,' - PRINT @tabc+@tabc+'@IncludeObjIdFilter = NULL' - RETURN 0 - GO - - IF (CHARINDEX('7.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace07','P') IS NULL) - RAISERROR('Error creating #sp_trace07',16,127) - GO - - - - IF OBJECT_ID('dbo.#sp_trace08','P') IS NOT NULL - DROP PROC dbo.#sp_trace08 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace08', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace08 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @TraceId int = NULL, - @AppName sysname='PSSDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - SET NOCOUNT ON - - IF @OnOff='/?' GOTO Help - - SET @OnOff=UPPER(@OnOff) - IF (@OnOff='LIST') BEGIN - IF (OBJECT_ID('tempdb..PSSDIAGTraceQueue') IS NOT NULL) BEGIN - IF (@TraceId IS NULL) BEGIN - DECLARE tc CURSOR FOR SELECT * FROM tempdb..PSSDIAGTraceQueue WHERE AppName=@AppName FOR READ ONLY - DECLARE @tid int, @tname varchar(20), @tfile sysname - OPEN tc - FETCH tc INTO @tid, @tname, @tfile - IF @@ROWCOUNT<>0 BEGIN - WHILE @@FETCH_STATUS=0 BEGIN - SELECT TraceId, TraceName, TraceFile - FROM tempdb..PSSDIAGTraceQueue WHERE TraceId=@tid - - SELECT * FROM ::fn_trace_getinfo(@tid) - - FETCH tc INTO @tid, @tname, @tfile - END - END ELSE PRINT 'No traces in the trace queue.' - CLOSE tc - DEALLOCATE tc - END ELSE BEGIN - SELECT TraceId, TraceName, TraceFile - FROM tempdb..PSSDIAGTraceQueue WHERE TraceId=@TraceId - SELECT * FROM ::fn_trace_getinfo(@TraceId) - END - END ELSE PRINT 'No traces to list.' - RETURN 0 - END - - -- Declare variables - DECLARE @OldQueueHandle int -- Queue handle of currently running trace queue - DECLARE @QueueHandle int -- Queue handle for new running trace queue - DECLARE @On bit -- Necessary because of a bug in some of the #sp_trace_xx procs - DECLARE @OurObjId int -- Used to keep us out of the trace log - DECLARE @OldTraceFile sysname -- File name of running trace - DECLARE @res int -- Result var for sp calls - SET @On=1 - - -- Stop the trace if running - IF OBJECT_ID('tempdb..PSSDIAGTraceQueue') IS NOT NULL BEGIN - IF EXISTS(SELECT * FROM tempdb..PSSDIAGTraceQueue WHERE TraceName = @TraceName AND AppName=@AppName) BEGIN - - SELECT @OldQueueHandle = TraceId, @OldTraceFile=TraceFile - FROM tempdb..PSSDIAGTraceQueue - WHERE TraceName = @TraceName - AND AppName=@AppName - - IF @@ROWCOUNT<>0 BEGIN - EXEC #sp_trace_setstatus @TraceId=@OldQueueHandle, @status=0 - EXEC #sp_trace_setstatus @TraceId=@OldQueueHandle, @status=2 - PRINT 'Deleted trace queue ' + CAST(@OldQueueHandle AS varchar(20))+'.' - PRINT 'The trace output file name is: '+@OldTraceFile+'.trc.' - DELETE tempdb..PSSDIAGTraceQueue WHERE TraceName = @TraceName AND AppName=@AppName - END - END ELSE PRINT 'No active traces named '+@TraceName+' for '+@AppName+'.' - END ELSE PRINT 'No active traces.' - - IF @OnOff='OFF' RETURN 0 -- We've stopped the trace (if it's running), so exit - - -- Do some basic param validation - IF (@Cols IS NULL) BEGIN - RAISERROR('You must specify the columns to trace.',16,10) - RETURN -1 - END - - IF ((@TraceType=0) AND (@Events IS NULL)) BEGIN - RAISERROR('You must specify either @TraceType or @Events.',16,10) - RETURN -1 - END - - -- Append the datetime to the file name to create a new, unique file name. - IF @FileName IS NULL SELECT @FileName = 'c:\TEMP\tsqltrace_' + CONVERT(CHAR(8),getdate(),112) + REPLACE(CONVERT(varchar(15),getdate(),114),':','') - - -- Delete the file if it exists - DECLARE @cmd varchar(8000) - SET @cmd='DEL '+@FileName+'.trc' - SET @cmd=REPLACE(@cmd,'#sp_trace','*') -- Delete all trace files so that SQL Server's rollover functionality works - EXEC master..xp_cmdshell @cmd - - -- Check for proper permissions - -- This check is only valid if xp_cmdshell and SQL Server are running under the same account - - -- First try accessing the output folder - DECLARE @outputfolder varchar(255) - - SET @outputfolder=@FileName - - -- Remove the filename portion of the full file path - SET @outputfolder=REVERSE(@outputfolder) - SET @outputfolder=SUBSTRING(@outputfolder,CHARINDEX('\',@outputfolder)+1,255) - SET @outputfolder=REVERSE(@outputfolder) - - PRINT 'Output folder='+@outputfolder - - /* - - CREATE TABLE #dirlist (linein varchar(8000)) - - SET @cmd='DIR '+@outputfolder - - INSERT #dirlist - EXEC @res=master..xp_cmdshell @cmd - - IF (1=@res) BEGIN - RAISERROR('Warning: Error accessing output folder %s. Reason: The path does not exist or SQL Server lacks sufficient rights to access it',10,10,@outputfolder) - RETURN @res - END ELSE BEGIN - - -- Check the amount of free space - DECLARE @spaceline varchar(255) - SELECT @spaceline=linein - FROM #dirlist - WHERE linein LIKE '% bytes free%' - - IF @spaceline IS NOT NULL BEGIN - - SET @spaceline=LEFT(@spaceline,CHARINDEX(' bytes free',@spaceline)) - - SET @spaceline=SUBSTRING(@spaceline,CHARINDEX('Dir(s) ',@spaceline)+LEN('Dir(s) '),255) - - PRINT 'Free space='+@spaceline+' bytes' - - DECLARE @freespace int - SET @freespace=CAST(REPLACE(@spaceline,',','') AS bigint) / (1024*1024) - - -- If free space < 64MB, issue a warning - IF (@freespace < 64) BEGIN - RAISERROR('Warning: The target drive has only %d MB of free space. Your trace may not complete successfully.',10,10, @freespace) - END - - END - - -- Now try creating a file in the output folder - SET @cmd='ECHO test>'+@outputfolder+'\_ms_pss_tst.txt' - EXEC @res=master..xp_cmdshell @cmd - IF (1=@res) BEGIN - RAISERROR('Warning: Error creating file. Reason: The drive is out of space or SQL Server lacks sufficient rights to write files in %s',10,10,@outputfolder) - END ELSE BEGIN - -- File created; delete it - SET @cmd='DEL '+@outputfolder+'\_ms_pss_tst.txt' - EXEC master..xp_cmdshell @cmd, no_output - END - END - - DROP TABLE #dirlist - - -- End permissions check - */ - - - -- Create the trace queue - --if MaxFileSize is not more than 0, sql server runtime will report invalid parameter error. In this case, set MaxFileSize default value based on BOL - IF @MaxFileSize<=0 SET @MaxFileSize=5 - - EXEC @res=#sp_trace_create @TraceId=@QueueHandle OUT, @options=@Options, @tracefile=@FileName, @maxfilesize=@MaxFileSize, @stoptime=@StopTime - IF @res<>0 BEGIN - IF @res=1 RAISERROR('Trace not started. Reason: Unknown error.',16,10) - ELSE IF @res=10 RAISERROR('Trace not started. Reason: Invalid options. Returned when options specified are incompatible.',16,10) - ELSE IF @res=12 RAISERROR('Trace not started. Reason: Error creating file. Returned if the file already exists, drive is out of space, the path %s does not exist, or SQL Server does not have sufficent rights to write files in it.',16,10, @outputfolder) - ELSE IF @res=13 RAISERROR('Trace not started. Reason: Out of memory. Returned when there is not enough memory to perform the specified action.',16,10) - ELSE IF @res=14 RAISERROR('Trace not started. Reason: Invalid stop time. Returned when the stop time specified has already happened.',16,10) - ELSE IF @res=15 RAISERROR('Trace not started. Reason: Invalid parameters. Returned when the user supplied incompatible parameters.',16,10) - RETURN @res - END - PRINT 'Trace started.' - PRINT 'The trace file name is : '+@FileName+'.' - - -- 2004/03/25 - BD: removed Errorlog event (22) from templates to avoid shiloh bug 471314. - -- Also note that the `"Missing Column Stats`" event (79) was previously removed to avoid bug 356136. - IF @TraceType=1 SET @Events='75,76,92,93,94,95,16,21,33,67,69,55,79,80,61,25,27,59,58,14,15,81,17,10,11,34,35,36,37,38,39,50,11,12' - ELSE IF @TraceType=2 SET @Events='53,75,76,60,92,93,94,95,16,21,28,29,30,31,33,67,69,55,79,80,61,25,27,59,58,14,15,81,17,10,11,34,35,36,37,38,39,50,11,12,97,98,18,100,41,19,' - - -- Specify the event classes and columns to trace - IF @Events IS NOT NULL BEGIN -- Loop through the @Events and @Cols strings, parsing out each event & column number and adding them to the trace definition - IF RIGHT(@Events,1)<>',' SET @Events=@Events+',' -- Append a comma to satisfy the loop - IF RIGHT(@Cols,1)<>',' SET @Cols=@Cols+',' -- Append a comma to satisfy the loop - DECLARE @i int, @j int, @Event int, @Col int, @ColStr varchar(300) - SET @i=CHARINDEX(',',@Events) - WHILE @i<>0 BEGIN - SET @Event=CAST(LEFT(@Events,@i-1) AS int) - SET @ColStr=@Cols - SET @j=CHARINDEX(',',@ColStr) - WHILE @j<>0 BEGIN - SET @Col=CAST(LEFT(@ColStr,@j-1) AS int) - print 'Event ID being traced :' + cast(@Event as varchar(20)) - EXEC #sp_trace_setevent @TraceId=@QueueHandle, @eventid=@Event, @columnid=@Col, @on=@On - SET @ColStr=SUBSTRING(@ColStr,@j+1,300) - SET @j=CHARINDEX(',',@ColStr) - END - SET @Events=SUBSTRING(@Events,@i+1,300) - SET @i=CHARINDEX(',',@Events) - END - END - - -- Set filters (default values avoid tracing the trace activity itself) - -- You can specify other filters like application name etc. by supplying strings to the @IncludeTextFilter/@ExcludeTextFilter parameters, separated by semicolons - --SET @ExcludeTextFilter='#sp_trace%'+ISNULL(';'+@ExcludeTextFilter,'') -- By default, keep our own activity from showing up - SET @OurObjId=OBJECT_ID('master..#sp_trace') - -- EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=1, @logical_operator=0, @comparison_operator=7, @value=N'EXEC% #sp_trace%' - IF @ExcludeTextFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=1, @logical_operator=0, @comparison_operator=7, @value=@ExcludeTextFilter - - - IF @IncludeTextFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=1, @logical_operator=0, @comparison_operator=6, @value=@IncludeTextFilter - IF @IncludeObjIdFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=22, @logical_operator=0, @comparison_operator=0, @value=@IncludeObjIdFilter - -- EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=22, @logical_operator=0, @comparison_operator=1, @value=@OurObjId - IF @ExcludeObjIdFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=22, @logical_operator=0, @comparison_operator=1, @value=@ExcludeObjIdFilter - - IF @IncludeObjNameFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=34, @logical_operator=0, @comparison_operator=6, @value=@IncludeObjNameFilter - IF @ExcludeObjNameFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=34, @logical_operator=0, @comparison_operator=7, @value=@ExcludeObjNameFilter - - IF @IncludeHostFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=8, @logical_operator=0, @comparison_operator=6, @value=@IncludeHostFilter - IF @ExcludeHostFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=8, @logical_operator=0, @comparison_operator=7, @value=@ExcludeHostFilter - - IF @IncludeSpidFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=12, @logical_operator=0, @comparison_operator=0, @value=@IncludeSpidFilter - IF @ExcludeSpidFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=12, @logical_operator=0, @comparison_operator=1, @value=@ExcludeSpidFilter - - -- Turn the trace on - EXEC #sp_trace_setstatus @TraceId=@QueueHandle, @status=1 - - -- Record the trace queue handle for subsequent jobs. (This allows us to know how to stop our trace.) - IF OBJECT_ID('tempdb..PSSDIAGTraceQueue') IS NULL BEGIN - CREATE TABLE tempdb..PSSDIAGTraceQueue (TraceId int, TraceName varchar(20), TraceFile sysname, AppName sysname) - INSERT tempdb..PSSDIAGTraceQueue VALUES(@QueueHandle, @TraceName, @FileName, @AppName) - END ELSE BEGIN - IF EXISTS(SELECT * FROM tempdb..PSSDIAGTraceQueue WHERE TraceName = @TraceName AND AppName=@AppName) BEGIN - UPDATE tempdb..PSSDIAGTraceQueue SET TraceId = @QueueHandle, TraceFile=@FileName WHERE TraceName = @TraceName AND AppName=@AppName - END ELSE BEGIN - INSERT tempdb..PSSDIAGTraceQueue VALUES(@QueueHandle, @TraceName, @FileName, @AppName) - END - END - RETURN 0 - - Help: - PRINT '#sp_trace -- Starts/stops a Profiler-like trace using Transact-SQL eXtended Procedure calls.' - DECLARE @crlf char(2), @tabc char(1) - SET @crlf=char(13)+char(10) - SET @tabc=char(9) - PRINT @crlf+'Parameters:' - PRINT @crlf+@tabc+'@OnOff varchar(3) default: ON -- Starts/stops the trace' - PRINT @crlf+@tabc+'@FileName sysname default: c:\temp\YYYYMMDDhhmissmmm.trc -- Specifies the trace file name (SQL Server always appends .trc extension)' - PRINT @crlf+@tabc+'@TraceName sysname default: tsqltrace -- Specifies the name of the trace' - PRINT @crlf+@tabc+'@TraceType int default: 0 -- Specifies the type of trace to run 1=General performance, 2=Detailed performance' - PRINT @crlf+@tabc+'@Options int default: 2 (TRACE_FILE_ROLLOVER)' - PRINT @crlf+@tabc+'@MaxFileSize bigint default: 2000000000 (MB)' - PRINT @crlf+@tabc+'@StopTime datetime default: NULL' - PRINT @crlf+@tabc+'@Events varchar(300) default: SP-related events and errors/warnings -- Comma-delimited list specifying the events numbers to trace' - PRINT @crlf+@tabc+'@Cols varchar(300) default: All columns -- Comma-delimited list specifying the column numbers to trace' - PRINT @crlf+@tabc+'@IncludeTextFilter sysname default: NULL -- String mask specifying what TextData strings to include in the trace' - PRINT @crlf+@tabc+'@ExcludeTextFilter sysname default: NULL -- String mask specifying what TextData strings to filter out of the trace' - PRINT @crlf+@tabc+'@IncludeObjIdFilter sysname default: NULL -- Specifies the id of an object to target with the trace' - PRINT @crlf+@tabc+'@ExcludeObjIdFilter sysname default: NULL -- Specifies the id of an object to exclude from the trace' - PRINT @crlf+@tabc+'@TraceId int default: NULL -- Specified the id of the trace to list when you specify the LIST option to @OnOff' - PRINT @crlf+@tabc+'@AppName sysname default: PSSDIAG -- Specifies the name of the calling application' - PRINT @crlf+'Examples: ' - PRINT @crlf+@tabc+'EXEC #sp_trace -- Displays this help text' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'' -- Starts a trace' - PRINT @crlf+@tabc+'EXEC #sp_trace ''OFF'' -- Stops a trace' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'', @Filename=''d:\mssql7\log\mytrace'' -- Starts a trace with the specified file name' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@Events=''37,43'' -- Starts a trace the traps the specified event classes' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@Cols=''1,2,3'' -- Starts a trace that includes the specified columns' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@IncludeTextFilter=''EXEC% FooProc%'' -- Starts a trace that includes events matching the specified TextData mask' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@tracename=''General Performance'' -- Starts a trace using the specified name' - PRINT @crlf+@tabc+'EXEC #sp_trace ''OFF'',@tracename=''General Performance'' -- Stops a trace with the specified name' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@filename = ''d:\mssql7\log\mytrace'', -- Starts a trace with the specified parameters' - PRINT @tabc+@tabc+'@TraceName = ''General Performance'',' - PRINT @tabc+@tabc+'@Options = 2, ' - PRINT @tabc+@tabc+'@TraceType = 0,' - PRINT @tabc+@tabc+'@MaxFileSize = 500,' - PRINT @tabc+@tabc+'@StopTime = NULL, ' - PRINT @tabc+@tabc+'@Events = ''10,11,14,15,16,17,27,37,40,41,55,58,67,69,79,80,98'',' - PRINT @tabc+@tabc+'@Cols = DEFAULT,' - PRINT @tabc+@tabc+'@IncludeTextFilter = NULL,' - PRINT @tabc+@tabc+'@IncludeObjIdFilter = NULL,' - PRINT @tabc+@tabc+'@ExcludeObjIdFilter = NULL' - PRINT @crlf+@tabc+'To list all the traces currently running:' - PRINT @crlf+@tabc+@tabc+'#sp_trace ''LIST''' - PRINT @crlf+@tabc+'To list information about a particular trace:' - PRINT @crlf+@tabc+@tabc+'#sp_trace ''LIST'', @TraceId=n -- where n is the trace ID you want to list' - PRINT @crlf+@tabc+'To stop a specific trace, supply the @TraceName parameter when you call #sp_trace ''OFF''.' - RETURN 0 - GO - IF (CHARINDEX('8.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace08','P') IS NULL) - RAISERROR('Error creating #sp_trace08',16,127) - GO - - - /* - IF OBJECT_ID('tempdb.dbo.SQLDIAGTraceQueue') IS NOT NULL - DROP TABLE tempdb.dbo.SQLDIAGTraceQueue - --GO - */ - - IF OBJECT_ID('dbo.#sp_trace09','P') IS NOT NULL - DROP PROC dbo.#sp_trace09 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace09', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace09 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter int=NULL, @ExcludeDatabaseIDFilter int=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - SET NOCOUNT ON - - - - - IF @OnOff='/?' GOTO Help - - SET @OnOff=UPPER(@OnOff) - IF (@OnOff='LIST') BEGIN - IF (OBJECT_ID('tempdb..SQLDIAGTraceQueue') IS NOT NULL) BEGIN - IF (@TraceId IS NULL) BEGIN - DECLARE tc CURSOR FOR SELECT * FROM tempdb..SQLDIAGTraceQueue WHERE AppName=@AppName FOR READ ONLY - DECLARE @tid int, @tname varchar(20), @tfile sysname - OPEN tc - FETCH tc INTO @tid, @tname, @tfile - IF @@ROWCOUNT<>0 BEGIN - WHILE @@FETCH_STATUS=0 BEGIN - SELECT TraceId, TraceName, TraceFile - FROM tempdb..SQLDIAGTraceQueue WHERE TraceId=@tid - - SELECT * FROM ::fn_trace_getinfo(@tid) - - FETCH tc INTO @tid, @tname, @tfile - END - END ELSE PRINT 'No traces in the trace queue.' - CLOSE tc - DEALLOCATE tc - END ELSE BEGIN - SELECT TraceId, TraceName, TraceFile - FROM tempdb..SQLDIAGTraceQueue WHERE TraceId=@TraceId - SELECT * FROM ::fn_trace_getinfo(@TraceId) - END - END ELSE PRINT 'No traces to list.' - RETURN 0 - END - - if (@IncludeTextFilter is not null - or @ExcludeTextFilter is not null - or @IncludeObjIdFilter is not null or @ExcludeObjIdFilter is not null - or @IncludeObjNameFilter is not null or @ExcludeObjNameFilter is not null - or @IncludeHostFilter is not null or @ExcludeHostFilter is not null - or @IncludeSpidFilter is not null or @ExcludeSpidFilter is not null - or @IncludeDatabaseIDFilter is not null or @ExcludeDatabaseIDFilter is not null - or @IncludeDatabaseNameFilter is not null or @ExcludeDatabaseNameFilter is not null ) - begin - print 'filter was used. please check your xml config file for details' - end - - - - -- Declare variables - DECLARE @OldQueueHandle int -- Queue handle of currently running trace queue - DECLARE @QueueHandle int -- Queue handle for new running trace queue - DECLARE @On bit, @Off bit -- Necessary because of a bug in some of the #sp_trace_xx procs - DECLARE @OurObjId int -- Used to keep us out of the trace log - DECLARE @OldTraceFile sysname -- File name of running trace - DECLARE @res int -- Result var for sp calls - SET @On=1 - SET @Off=0 - - -- Stop the trace if running - IF OBJECT_ID('tempdb..SQLDIAGTraceQueue') IS NOT NULL BEGIN - IF EXISTS(SELECT * FROM tempdb..SQLDIAGTraceQueue WHERE TraceName = @TraceName AND AppName=@AppName) BEGIN - - SELECT @OldQueueHandle = TraceId, @OldTraceFile=TraceFile - FROM tempdb..SQLDIAGTraceQueue - WHERE TraceName = @TraceName - AND AppName=@AppName - - IF @@ROWCOUNT<>0 BEGIN - EXEC #sp_trace_setstatus @TraceId=@OldQueueHandle, @status=0 - EXEC #sp_trace_setstatus @TraceId=@OldQueueHandle, @status=2 - PRINT 'Deleted trace queue ' + CAST(@OldQueueHandle AS varchar(20))+'.' - PRINT 'The trace output file name is: '+@OldTraceFile+'.trc.' - DELETE tempdb..SQLDIAGTraceQueue WHERE TraceName = @TraceName AND AppName=@AppName - END - END ELSE PRINT 'No active traces named '+@TraceName+' for '+@AppName+'.' - END ELSE PRINT 'No active traces.' - - IF @OnOff='OFF' RETURN 0 -- We've stopped the trace (if it's running), so exit - - -- Do some basic param validation - IF (@Cols IS NULL) BEGIN - RAISERROR('You must specify the columns to trace.',16,10) - RETURN -1 - END - - IF ((@TraceType=0) AND (@Events IS NULL)) BEGIN - RAISERROR('You must specify either @TraceType or @Events.',16,10) - RETURN -1 - END - - -- Append the datetime to the file name to create a new, unique file name. - IF @FileName IS NULL SELECT @FileName = 'c:\TEMP\tsqltrace_' + CONVERT(CHAR(8),getdate(),112) + REPLACE(CONVERT(varchar(15),getdate(),114),':','') - - -- Delete the file if it exists - - -- Ensure xp_cmdshell is enabled before we try this - if (select value from sys.sysconfigures WHERE config=16390)=1 BEGIN - DECLARE @cmd varchar(8000) - SET @cmd='DEL '+@FileName+'.trc' - SET @cmd=REPLACE(@cmd,'#sp_trace','*') -- Delete all trace files so that SQL Server's rollover functionality works - EXEC master..xp_cmdshell @cmd - END - - -- First try accessing the output folder - DECLARE @outputfolder varchar(255) - - SET @outputfolder=@FileName - - -- Remove the filename portion of the full file path - SET @outputfolder=REVERSE(@outputfolder) - SET @outputfolder=SUBSTRING(@outputfolder,CHARINDEX('\',@outputfolder)+1,255) - SET @outputfolder=REVERSE(@outputfolder) - - PRINT 'Output folder='+@outputfolder - - -- Create the trace queue - - -- found if @filecount parameter is set 1, sql server runtime will report invalid parameter error. only the parameter value is above 1, it works - IF @FileCount<=1 SET @FileCount=NULL - - --if MaxFileSize is not more than 0, sql server runtime will report invalid parameter error. In this case, set MaxFileSize default value based on BOL - IF @MaxFileSize<=0 SET @MaxFileSize=5 - - EXEC @res=#sp_trace_create @TraceId=@QueueHandle OUT, @options=@Options, @tracefile=@FileName, @maxfilesize=@MaxFileSize, @stoptime=@StopTime, @filecount=@FileCount - IF @res<>0 BEGIN - IF @res=1 RAISERROR('Trace not started. Reason: Unknown error.',16,10) - ELSE IF @res=10 RAISERROR('Trace not started. Reason: Invalid options. Returned when options specified are incompatible.',16,10) - ELSE IF @res=12 RAISERROR('Trace not started. Reason: Error creating file. Returned if the file already exists, drive is out of space, the path %s does not exist, or SQL Server does not have sufficent rights to write files in it.',16,10, @outputfolder) - ELSE IF @res=13 RAISERROR('Trace not started. Reason: Out of memory. Returned when there is not enough memory to perform the specified action.',16,10) - ELSE IF @res=14 RAISERROR('Trace not started. Reason: Invalid stop time. Returned when the stop time specified has already happened.',16,10) - ELSE IF @res=15 RAISERROR('Trace not started. Reason: Invalid parameters. Returned when the user supplied incompatible parameters.',16,10) - RETURN @res - END - PRINT 'Trace started.' - PRINT 'The trace file name is : '+@FileName+'.' - - -- 2004/03/25 - BD: removed Errorlog event (22) from templates to avoid shiloh bug 471314. - -- Also note that the `"Missing Column Stats`" event (79) was previously removed to avoid bug 356136. - IF @TraceType=1 SET @Events='75,76,92,93,94,95,16,21,33,67,69,55,79,80,61,25,27,59,58,14,15,81,17,10,11,34,35,36,37,38,39,50,11,12' - ELSE IF @TraceType=2 SET @Events='53,75,76,60,92,93,94,95,16,21,28,29,30,31,33,67,69,55,79,80,61,25,27,59,58,14,15,81,17,10,11,34,35,36,37,38,39,50,11,12,97,98,18,100,41,19,' - - -- Specify the event classes and columns to trace - IF @Events IS NOT NULL BEGIN -- Loop through the @Events and @Cols strings, parsing out each event & column number and adding them to the trace definition - IF RIGHT(@Events,1)<>',' SET @Events=@Events+',' -- Append a comma to satisfy the loop - IF RIGHT(@Cols,1)<>',' SET @Cols=@Cols+',' -- Append a comma to satisfy the loop - DECLARE @i int, @j int, @Event int, @Col int, @ColStr varchar(300) - SET @i=CHARINDEX(',',@Events) - WHILE @i<>0 BEGIN - SET @Event=CAST(LEFT(@Events,@i-1) AS int) - SET @ColStr=@Cols - SET @j=CHARINDEX(',',@ColStr) - WHILE @j<>0 BEGIN - SET @Col=CAST(LEFT(@ColStr,@j-1) AS int) - print 'Event ID being traced :' + cast(@Event as varchar(20)) - if (@Col<>1) OR (not (@Event IN (10,11))) - EXEC #sp_trace_setevent @TraceId=@QueueHandle, @eventid=@Event, @columnid=@Col, @on=@On - else - EXEC #sp_trace_setevent @TraceId=@QueueHandle, @eventid=@Event, @columnid=@Col, @on=@Off - SET @ColStr=SUBSTRING(@ColStr,@j+1,300) - SET @j=CHARINDEX(',',@ColStr) - END - SET @Events=SUBSTRING(@Events,@i+1,300) - SET @i=CHARINDEX(',',@Events) - END - END - - declare @FilterRet int - - -- Set filters (default values avoid tracing the trace activity itself) - -- You can specify other filters like application name etc. by supplying strings to the @IncludeTextFilter/@ExcludeTextFilter parameters, separated by semicolons - --SET @ExcludeTextFilter='#sp_trace%'+ISNULL(';'+@ExcludeTextFilter,'') -- By default, keep our own activity from showing up - SET @OurObjId=OBJECT_ID('master..#sp_trace') - -- EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=1, @logical_operator=0, @comparison_operator=7, @value=N'EXEC% #sp_trace%' - IF @ExcludeTextFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=1, @logical_operator=0, @comparison_operator=7, @value=@ExcludeTextFilter - - - IF @IncludeTextFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=1, @logical_operator=0, @comparison_operator=6, @value=@IncludeTextFilter - IF @IncludeObjIdFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=22, @logical_operator=0, @comparison_operator=0, @value=@IncludeObjIdFilter - -- EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=22, @logical_operator=0, @comparison_operator=1, @value=@OurObjId - - - --filter on object name - IF @IncludeObjNameFilter IS NOT NULL - begin - print '@IncludeObjNameFilter added' - print @IncludeObjNameFilter - - EXEC @FilterRet = #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=34, @logical_operator=0, @comparison_operator=6, @value=@IncludeObjNameFilter - - print '#sp_trace_setfilter returned code ' - select @FilterRet - - --overloading to test for DatabaseName - --EXEC @FilterRet = #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=35, @logical_operator=0, @comparison_operator=6, @value=@IncludeObjNameFilter - --filter out NULL - EXEC @FilterRet = #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=34, @logical_operator=0, @comparison_operator=1, @value=NULL - - print '#sp_trace_setfilter returned code ' - select @FilterRet - - end - - - IF @IncludeDatabaseNameFilter IS NOT NULL - begin - print 'Fitlering on database Name ' - print @IncludeDatabaseNameFilter - EXEC @FilterRet = #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=35, @logical_operator=0, @comparison_operator=6, @value=@IncludeDatabaseNameFilter - select @FilterRet '#sp_trace_setfilter returned code ' - EXEC @FilterRet = #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=35, @logical_operator=0, @comparison_operator=1, @value=NULL - select @FilterRet '#sp_trace_setfilter returned code for NULL filter' - - end - - - IF @IncludeDatabaseIDFilter IS NOT NULL - begin - print 'filtering on database id' - select @IncludeDatabaseIDFilter 'database id' - - EXEC @FilterRet=#sp_trace_setfilter @TraceId=@QueueHandle, @columnid=3, @logical_operator=0, @comparison_operator=0, @value=@IncludeDatabaseIDFilter - select @FilterRet '#sp_trace_setfilter returned code ' - EXEC @FilterRet = #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=3, @logical_operator=0, @comparison_operator=1, @value=NULL - select @FilterRet '#sp_trace_setfilter returned code for NULL filter' - - end - - - - - IF @IncludeHostFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=8, @logical_operator=0, @comparison_operator=6, @value=@IncludeHostFilter - IF @ExcludeHostFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=8, @logical_operator=0, @comparison_operator=7, @value=@ExcludeHostFilter - - IF @IncludeSpidFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=12, @logical_operator=0, @comparison_operator=0, @value=@IncludeSpidFilter - IF @ExcludeSpidFilter IS NOT NULL EXEC #sp_trace_setfilter @TraceId=@QueueHandle, @columnid=12, @logical_operator=0, @comparison_operator=1, @value=@ExcludeSpidFilter - - -- Turn the trace on - EXEC #sp_trace_setstatus @TraceId=@QueueHandle, @status=1 - - -- Record the trace queue handle for subsequent jobs. (This allows us to know how to stop our trace.) - IF OBJECT_ID('tempdb..SQLDIAGTraceQueue') IS NULL BEGIN - CREATE TABLE tempdb..SQLDIAGTraceQueue (TraceId int, TraceName varchar(20), TraceFile sysname, AppName sysname) - INSERT tempdb..SQLDIAGTraceQueue VALUES(@QueueHandle, @TraceName, @FileName, @AppName) - END ELSE BEGIN - IF EXISTS(SELECT * FROM tempdb..SQLDIAGTraceQueue WHERE TraceName = @TraceName AND AppName=@AppName) BEGIN - UPDATE tempdb..SQLDIAGTraceQueue SET TraceId = @QueueHandle, TraceFile=@FileName WHERE TraceName = @TraceName AND AppName=@AppName - END ELSE BEGIN - INSERT tempdb..SQLDIAGTraceQueue VALUES(@QueueHandle, @TraceName, @FileName, @AppName) - END - END - RETURN 0 - - Help: - PRINT '#sp_trace -- Starts/stops a Profiler-like trace using Transact-SQL eXtended Procedure calls.' - DECLARE @crlf char(2), @tabc char(1) - SET @crlf=char(13)+char(10) - SET @tabc=char(9) - PRINT @crlf+'Parameters:' - PRINT @crlf+@tabc+'@OnOff varchar(3) default: ON -- Starts/stops the trace' - PRINT @crlf+@tabc+'@FileName sysname default: c:\temp\YYYYMMDDhhmissmmm.trc -- Specifies the trace file name (SQL Server always appends .trc extension)' - PRINT @crlf+@tabc+'@TraceName sysname default: tsqltrace -- Specifies the name of the trace' - PRINT @crlf+@tabc+'@TraceType int default: 0 -- Specifies the type of trace to run 1=General performance, 2=Detailed performance' - PRINT @crlf+@tabc+'@Options int default: 2 (TRACE_FILE_ROLLOVER)' - PRINT @crlf+@tabc+'@MaxFileSize bigint default: 2000000000 (MB)' - PRINT @crlf+@tabc+'@StopTime datetime default: NULL' - PRINT @crlf+@tabc+'@FileCount int default: NULL' - PRINT @crlf+@tabc+'@Events varchar(300) default: SP-related events and errors/warnings -- Comma-delimited list specifying the events numbers to trace' - PRINT @crlf+@tabc+'@Cols varchar(300) default: All columns -- Comma-delimited list specifying the column numbers to trace' - PRINT @crlf+@tabc+'@IncludeTextFilter sysname default: NULL -- String mask specifying what TextData strings to include in the trace' - PRINT @crlf+@tabc+'@ExcludeTextFilter sysname default: NULL -- String mask specifying what TextData strings to filter out of the trace' - PRINT @crlf+@tabc+'@IncludeObjIdFilter sysname default: NULL -- Specifies the id of an object to target with the trace' - PRINT @crlf+@tabc+'@ExcludeObjIdFilter sysname default: NULL -- Specifies the id of an object to exclude from the trace' - PRINT @crlf+@tabc+'@TraceId int default: NULL -- Specified the id of the trace to list when you specify the LIST option to @OnOff' - PRINT @crlf+@tabc+'@AppName sysname default: SQLDIAG -- Specifies the name of the calling application' - PRINT @crlf+'Examples: ' - PRINT @crlf+@tabc+'EXEC #sp_trace -- Displays this help text' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'' -- Starts a trace' - PRINT @crlf+@tabc+'EXEC #sp_trace ''OFF'' -- Stops a trace' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'', @Filename=''d:\mssql7\log\mytrace'' -- Starts a trace with the specified file name' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@Events=''37,43'' -- Starts a trace the traps the specified event classes' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@Cols=''1,2,3'' -- Starts a trace that includes the specified columns' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@IncludeTextFilter=''EXEC% FooProc%'' -- Starts a trace that includes events matching the specified TextData mask' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@tracename=''General Performance'' -- Starts a trace using the specified name' - PRINT @crlf+@tabc+'EXEC #sp_trace ''OFF'',@tracename=''General Performance'' -- Stops a trace with the specified name' - PRINT @crlf+@tabc+'EXEC #sp_trace ''ON'',@filename = ''d:\mssql7\log\mytrace'', -- Starts a trace with the specified parameters' - PRINT @tabc+@tabc+'@TraceName = ''General Performance'',' - PRINT @tabc+@tabc+'@Options = 2, ' - PRINT @tabc+@tabc+'@TraceType = 0,' - PRINT @tabc+@tabc+'@MaxFileSize = 500,' - PRINT @tabc+@tabc+'@StopTime = NULL, ' - PRINT @tabc+@tabc+'@FileCount = NULL, ' - PRINT @tabc+@tabc+'@Events = ''10,11,14,15,16,17,27,37,40,41,55,58,67,69,79,80,98'',' - PRINT @tabc+@tabc+'@Cols = DEFAULT,' - PRINT @tabc+@tabc+'@IncludeTextFilter = NULL,' - PRINT @tabc+@tabc+'@IncludeObjIdFilter = NULL,' - PRINT @tabc+@tabc+'@ExcludeObjIdFilter = NULL' - PRINT @crlf+@tabc+'To list all the traces currently running:' - PRINT @crlf+@tabc+@tabc+'#sp_trace ''LIST''' - PRINT @crlf+@tabc+'To list information about a particular trace:' - PRINT @crlf+@tabc+@tabc+'#sp_trace ''LIST'', @TraceId=n -- where n is the trace ID you want to list' - PRINT @crlf+@tabc+'To stop a specific trace, supply the @TraceName parameter when you call #sp_trace ''OFF''.' - RETURN 0 - GO - IF (CHARINDEX('9.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace09','P') IS NULL) - RAISERROR('Error creating #sp_trace09',16,127) - GO - - IF OBJECT_ID('dbo.#sp_trace10','P') IS NOT NULL - DROP PROC dbo.#sp_trace10 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace10', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace10 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter sysname=NULL, @ExcludeDatabaseIDFilter sysname=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - BEGIN - exec dbo.#sp_trace09 @OnOff, @FileName, @TraceName, @Options, @MaxFileSize, - @StopTime, @FileCount, @TraceType, @Events, @Cols, - @IncludeTextFilter, @ExcludeTextFilter, - @IncludeObjIdFilter, @ExcludeObjIdFilter, - @IncludeObjNameFilter, @ExcludeObjNameFilter, - @IncludeHostFilter, @ExcludeHostFilter, - @IncludeSpidFilter, @ExcludeSpidFilter, - @IncludeDatabaseIDFilter, @ExcludeDatabaseIDFilter, - @IncludeDatabaseNameFilter, @ExcludeDatabaseNameFilter, - @TraceId, - @AppName - END - GO - /* - The board chagned the Product Version format in Katmai. The current foramt starting from Katmai will be single zero for minor version instead of two zeros in previous sql versions. `" 10.m.bbbb.rr `" - */ - IF (CHARINDEX('10.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace10','P') IS NULL) - RAISERROR('Error creating #sp_trace10',16,127) - GO - - /* SQL11 Version Bump */ - IF OBJECT_ID('dbo.#sp_trace11','P') IS NOT NULL - DROP PROC dbo.#sp_trace11 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace11', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace11 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter sysname=NULL, @ExcludeDatabaseIDFilter sysname=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - BEGIN - exec dbo.#sp_trace10 @OnOff, @FileName, @TraceName, @Options, @MaxFileSize, - @StopTime, @FileCount, @TraceType, @Events, @Cols, - @IncludeTextFilter, @ExcludeTextFilter, - @IncludeObjIdFilter, @ExcludeObjIdFilter, - @IncludeObjNameFilter, @ExcludeObjNameFilter, - @IncludeHostFilter, @ExcludeHostFilter, - @IncludeSpidFilter, @ExcludeSpidFilter, - @IncludeDatabaseIDFilter, @ExcludeDatabaseIDFilter, - @IncludeDatabaseNameFilter, @ExcludeDatabaseNameFilter, - @TraceId, - @AppName - END - GO - - IF (CHARINDEX('11.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace11','P') IS NULL) - RAISERROR('Error creating #sp_trace11',16,127) - GO - - /* SQL14 Version Bump */ - IF OBJECT_ID('dbo.#sp_trace12','P') IS NOT NULL - DROP PROC dbo.#sp_trace12 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace12', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace12 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter sysname=NULL, @ExcludeDatabaseIDFilter sysname=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - BEGIN - exec dbo.#sp_trace10 @OnOff, @FileName, @TraceName, @Options, @MaxFileSize, - @StopTime, @FileCount, @TraceType, @Events, @Cols, - @IncludeTextFilter, @ExcludeTextFilter, - @IncludeObjIdFilter, @ExcludeObjIdFilter, - @IncludeObjNameFilter, @ExcludeObjNameFilter, - @IncludeHostFilter, @ExcludeHostFilter, - @IncludeSpidFilter, @ExcludeSpidFilter, - @IncludeDatabaseIDFilter, @ExcludeDatabaseIDFilter, - @IncludeDatabaseNameFilter, @ExcludeDatabaseNameFilter, - @TraceId, - @AppName - END - GO - - IF (CHARINDEX('12.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace12','P') IS NULL) - RAISERROR('Error creating #sp_trace12',16,127) - GO - - /* SQL15 Version Bump */ - IF OBJECT_ID('dbo.#sp_trace13','P') IS NOT NULL - DROP PROC dbo.#sp_trace13 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace13', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace13 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter sysname=NULL, @ExcludeDatabaseIDFilter sysname=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - BEGIN - - exec dbo.#sp_trace11 @OnOff, @FileName, @TraceName, @Options, @MaxFileSize, - @StopTime, @FileCount, @TraceType, @Events, @Cols, - @IncludeTextFilter, @ExcludeTextFilter, - @IncludeObjIdFilter, @ExcludeObjIdFilter, - @IncludeObjNameFilter, @ExcludeObjNameFilter, - @IncludeHostFilter, @ExcludeHostFilter, - @IncludeSpidFilter, @ExcludeSpidFilter, - @IncludeDatabaseIDFilter, @ExcludeDatabaseIDFilter, - @IncludeDatabaseNameFilter, @ExcludeDatabaseNameFilter, - @TraceId, - @AppName - END - GO - - IF (CHARINDEX('13.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace13','P') IS NULL) - RAISERROR('Error creating #sp_trace13',16,127) - GO - go - - IF OBJECT_ID('dbo.#sp_trace14','P') IS NOT NULL - DROP PROC dbo.#sp_trace14 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace14', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace14 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter sysname=NULL, @ExcludeDatabaseIDFilter sysname=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - BEGIN - - exec dbo.#sp_trace11 @OnOff, @FileName, @TraceName, @Options, @MaxFileSize, - @StopTime, @FileCount, @TraceType, @Events, @Cols, - @IncludeTextFilter, @ExcludeTextFilter, - @IncludeObjIdFilter, @ExcludeObjIdFilter, - @IncludeObjNameFilter, @ExcludeObjNameFilter, - @IncludeHostFilter, @ExcludeHostFilter, - @IncludeSpidFilter, @ExcludeSpidFilter, - @IncludeDatabaseIDFilter, @ExcludeDatabaseIDFilter, - @IncludeDatabaseNameFilter, @ExcludeDatabaseNameFilter, - @TraceId, - @AppName - END - GO - - IF (CHARINDEX('14.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace14','P') IS NULL) - RAISERROR('Error creating #sp_trace14',16,127) - GO - go - - - IF OBJECT_ID('dbo.#sp_trace15','P') IS NOT NULL - DROP PROC dbo.#sp_trace15 - GO - PRINT '' - RAISERROR ('===== Creating #sp_trace15', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_trace15 @OnOff varchar(4)='/?', - @FileName sysname=NULL, - @TraceName sysname='tsqltrace', - @Options int=2, - @MaxFileSize bigint=4000, - @StopTime datetime=NULL, - @FileCount int=NULL, - @TraceType int=0, - @Events varchar(300)= - -- 11 - RPC:Starting - -- 13 - SQL:BatchStarting - -- 14 - Connect - -- 15 - Disconnect - -- 16 - Attention - -- 17 - Existing Connection - -- 33 - Exception - -- 42 - SP:Starting - -- 43 - SP:Completed - -- 45 - SP:StmtCompleted - -- 55 - Hash Warning - -- 67 - Execution Warnings - -- 69 - Sort Warnings - -- 79 - Missing Column Statistics - -- 80 - Missing Join Predicate - '11,13,14,15,16,17,33,42,43,45,55,67,69,79,80', - @Cols varchar(300)= - -- All columns - '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,', - @IncludeTextFilter sysname=NULL, @ExcludeTextFilter sysname=NULL, - @IncludeObjIdFilter int=NULL, @ExcludeObjIdFilter int=NULL, - @IncludeObjNameFilter sysname=NULL, @ExcludeObjNameFilter sysname=NULL, - @IncludeHostFilter sysname=NULL, @ExcludeHostFilter sysname=NULL, - @IncludeSpidFilter int=NULL, @ExcludeSpidFilter int=NULL, - @IncludeDatabaseIDFilter sysname=NULL, @ExcludeDatabaseIDFilter sysname=NULL, - @IncludeDatabaseNameFilter sysname=NULL, @ExcludeDatabaseNameFilter sysname=NULL, - @TraceId int = NULL, - @AppName sysname='SQLDIAG' - AS - BEGIN - - exec dbo.#sp_trace11 @OnOff, @FileName, @TraceName, @Options, @MaxFileSize, - @StopTime, @FileCount, @TraceType, @Events, @Cols, - @IncludeTextFilter, @ExcludeTextFilter, - @IncludeObjIdFilter, @ExcludeObjIdFilter, - @IncludeObjNameFilter, @ExcludeObjNameFilter, - @IncludeHostFilter, @ExcludeHostFilter, - @IncludeSpidFilter, @ExcludeSpidFilter, - @IncludeDatabaseIDFilter, @ExcludeDatabaseIDFilter, - @IncludeDatabaseNameFilter, @ExcludeDatabaseNameFilter, - @TraceId, - @AppName - END - GO - - IF (CHARINDEX('15.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_trace15','P') IS NULL) - RAISERROR('Error creating #sp_trace15',16,127) - GO - go - - - - /* - - #sp_code_runner - - */ - - IF OBJECT_ID('dbo.#sp_code_runner07','P') IS NOT NULL - DROP PROC dbo.#sp_code_runner07 - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner07', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner07 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - SET NOCOUNT ON - - IF @StartCmd='/?' GOTO Help - - -- Do some minimal parm checking - IF COALESCE(@Duration, @StopCondition) IS NULL BEGIN - RAISERROR('You must supply either the @Duration or the @StopCondition parameter.',16,10) - RETURN -1 - END - IF @OutputFileMask='*' BEGIN - RAISERROR('You may not specify an empty file mask.',16,10) - RETURN -1 - END - IF (@OutputDir IS NOT NULL) AND (@OutputFileMask IS NULL) BEGIN - RAISERROR('You must supply a file mask when supplying a directory.',16,10) - RETURN -1 - END - - -- Wait until the start time if there is one - IF @StartTime IS NOT NULL - WAITFOR TIME @StartTime - - -- Declare some variables and assign initial values - DECLARE @Stop int, @i int, @EndTime datetime, @CurDate datetime, @CurDateStr varchar(25), - @FName sysname, @DelCmd varchar(255), @OutputDirCmd varchar(255), @SCmd nvarchar(4000), - @IterationDateTime datetime - SET @CurDate=getdate() - SET @EndTime=@CurDate+@Duration - SET @Stop=CASE WHEN @CurDate >= @EndTime THEN 1 ELSE 0 END -- @Duration of 00:00:00, perhaps? - SET @i=0 - SET @StopCondition='IF ('+@StopCondition+') RAISERROR('''+@StopMessage+''',11,1)' - - IF @OutputDir IS NOT NULL BEGIN -- If we're going to generate file names, delete any old ones - IF RIGHT(@OutputDir,1)<>'\' SET @OutputDir=@OutputDir+'\' - SET @DelCmd='DEL '+@OutputDir+@OutputFileMask - -- EXEC xp_cmdshell @DelCmd, no_output -- Delete all files matching the mask - SET @OutputDirCmd='DIR '+@OutputDir+@OutputFileMask+' /B /ON' -- Prepare for Dir listing (below) - END - - --IF (@Stop<>1) AND (@StopCondition IS NOT NULL) -- Check the stop condition - don't start if it's met - -- EXEC @Stop=sp_executesql @StopCondition - WHILE (@Stop=0) BEGIN - - IF @OutputDir IS NOT NULL BEGIN -- Gen a file name using the current date and time - SET @CurDateStr=CONVERT(CHAR(8),getdate(),112) + REPLACE(CONVERT(varchar(15),getdate(),114),':','') - SET @FName=REPLACE(@OutputFileMask,'*',@CurDateStr) - IF (@@MICROSOFTVERSION >= 134217922 /* SS2K RTM */) BEGIN - DECLARE @p int - SET @p=CHARINDEX('.trc',@FName) - IF (@p<>0) SET @FName=LEFT(@FName,@p-1) - END - SET @SCmd=@StartCmd+', @FileName='''+CAST(@OutputDir+@FName as nvarchar(255))+'''' - END ELSE SET @SCmd=@StartCmd - - EXEC sp_executesql @SCmd -- Execute the start command - - SET @IterationDateTime=getdate()+ISNULL(@IterationTime,'23:59:59.999') - WHILE (@Stop=0) AND (getdate()<@IterationDateTime) BEGIN - - -- IF @IterationTime IS NOT NULL -- Do the per iteration pause - -- WAITFOR DELAY @IterationTime - - /* - -- Special handling for .trc files - IF (CHARINDEX('.TRC',@OutputFileMask)<>0) BEGIN - --Cab and delete inactive trace files -- we won't be able to open active files - SET @DelCmd='for %d in ('+@OutputDir+'*.trc) do '+@OutputDir+'compress '+@OutputDir+' %d' - SELECT @DelCmd - EXEC master..xp_cmdshell @DelCmd, no_output - END - */ - - IF @PollingInterval IS NOT NULL -- Do polling interval delay - WAITFOR DELAY @PollingInterval - - SET @Stop=CASE WHEN getdate() >= @EndTime THEN 1 ELSE 0 END -- Check the duration - - IF (@Stop<>1) AND (@StopCondition IS NOT NULL) -- Check the stop condition - EXEC @Stop=sp_executesql @StopCondition - END - IF @StopCmd IS NOT NULL -- Execute the stop command if there is one - EXEC sp_executesql @StopCmd - - SET @i=@i+1 - IF (@OutputDir IS NOT NULL) AND (@i>@NumFiles) BEGIN -- Get rid of extra files - - CREATE TABLE #files (fname varchar(255) NULL) - - INSERT #files - EXEC master..xp_cmdshell @OutputDirCmd - - SELECT TOP 1 @DelCmd='DEL '+@OutputDir+fname FROM #files WHERE fname IS NOT NULL ORDER BY fname - IF @@ROWCOUNT<>0 - EXEC master..xp_cmdshell @DelCmd, no_output - - DROP TABLE #files - - END - IF @PauseBetweenRuns IS NOT NULL -- Do pause between runs delay - WAITFOR DELAY @PauseBetweenRuns - END - RETURN 0 - - Help: - DECLARE @crlf char(2), @tabc char(1) - SET @crlf=char(13)+char(10) - SET @tabc=char(9) - PRINT 'Procedure: #sp_code_runner' - PRINT @crlf+'Purpose: runs a specified TSQL command batch or stored procedure repetitively for a specified period of time' - PRINT @crlf+'Parameters:' - PRINT @tabc+'@StartCmd nvarchar(4000) default: (none) -- the TSQL command or procedure to start' - PRINT @tabc+'@StartTime char(8) default: NULL -- the time to begin processing' - PRINT @tabc+'@StopCondition nvarchar(4000) default: NULL -- the condition to check to determine whether to stop @StartCmd' - PRINT @tabc+'@StopMessage nvarchar(4000) default: NULL -- the message to display when the stop condition is met' - PRINT @tabc+'@IterationTime char(8) default: NULL -- the time that should elapse between iterations' - PRINT @tabc+'@PollingInterval char(8) default: 00:00:10 -- the time to pause between checks of the @StopCondition' - PRINT @tabc+'@Duration char(8) default: NULL -- the total amount of time @StartCmd should run' - PRINT @tabc+'@StopCmd nvarchar(4000) default: NULL -- the TSQL command or procedure to run to stop @StartCmd' - PRINT @tabc+'@OutputDir sysname default: NULL -- the target directory for the output file (if applicable -- proc must support @FileName parameter)' - PRINT @tabc+'@OutputFileMask sysname default: NULL -- the filemask for output files (if applicable -- proc must support @FileName parameter)' - PRINT @tabc+'@NumFiles int default: 16 -- the number of output files to retain (if applicable -- proc must support @FileName parameter)' - PRINT @crlf+'Examples: ' - PRINT @tabc+'EXEC #sp_code_runner @StartCmd=N''EXEC #sp_trace ''''ON'''''',' - PRINT @tabc+'@StopCondition=N''OBJECT_ID(''''tempdb..stoptab'''') IS NOT NULL'',' - PRINT @tabc+'@StopMessage=N''Trace stopped'', @IterationTime=''00:30:00'',' - PRINT @tabc+'@StopCmd=N''EXEC #sp_trace ''''OFF'''''',' - PRINT @tabc+'@OutputDir=''c:\temp'',@OutputFileMask=''#sp_trace*.trc'', @NumFiles=16' - PRINT @crlf+@tabc+'EXEC #sp_code_runner @StartCmd=N''EXEC #sp_trace ''''ON'''''',' - PRINT @tabc+'@IterationTime=''00:30:00'', @Duration=''12:00:00'',' - PRINT @tabc+'@StopCmd=N''EXEC #sp_trace ''''OFF'''''',' - PRINT @tabc+'@OutputDir=''c:\temp'',@OutputFileMask=''#sp_trace*.trc'', @NumFiles=10' - PRINT @crlf+@tabc+'EXEC #sp_code_runner @StartCmd=N''EXEC #sp_blocker_pss70'',' - PRINT @tabc+'@StopCondition=N''EXISTS(SELECT waittime FROM master..sysprocesses WHERE waittime>60000 AND blocked>0)'',' - PRINT @tabc+'@StopMessage=''Longterm block detected'',' - PRINT @tabc+'@IterationTime=''00:05:00'', @Duration=''12:00:00''' - PRINT @crlf+@tabc+'EXEC #sp_code_runner @StartCmd=N''EXEC #sp_blocker_pss70'',' - PRINT @tabc+'@StartTime=''00:22:00'', @IterationTime=''00:05:00'', @Duration=''12:00:00''' - RETURN 0 - GO - IF (OBJECT_ID('dbo.#sp_code_runner07') IS NULL) - RAISERROR('Error creating #sp_code_runner07',16,127) - GO - /*if (CHARINDEX('8.00.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner08', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner08','P') IS NOT NULL drop proc dbo.#sp_code_runner08 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner08' - IF (OBJECT_ID('dbo.#sp_code_runner08') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner08',16,127) - END - ELSE if (CHARINDEX('9.00.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner09', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner09','P') IS NOT NULL drop proc dbo.#sp_code_runner09 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner09' - IF (OBJECT_ID('dbo.#sp_code_runner09') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner09',16,127) - END*/ - /* - The board chagned the Product Version format in Katmai. The current foramt starting from Katmai will be single zero for minor version instead of two zeros in previous sql versions. `" 10.m.bbbb.rr `" - */ - /*ELSE if (CHARINDEX('10.0.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner10', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner10','P') IS NOT NULL drop proc dbo.#sp_code_runner10 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner10' - IF (OBJECT_ID('dbo.#sp_code_runner10') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner10',16,127) - END*/ - /* - For KJ version 10.50, since sqldiag still use #sp_code_runner10 to capture traces if maxfilesize=-1(if maxfilesize!=-1, sqldiag use #sp_trace10 to capture traces) - we use the same store procedure name #sp_code_runner10 as the katmai version 10.0 does - */ - /*ELSE if (CHARINDEX('10.50.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner10', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner10','P') IS NOT NULL drop proc dbo.#sp_code_runner10 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner10' - IF (OBJECT_ID('dbo.#sp_code_runner10') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner10',16,127) - END*/ - /* - SQL11 Version Bump - */ - /*ELSE if (CHARINDEX('11.0.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner11', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner11','P') IS NOT NULL drop proc dbo.#sp_code_runner11 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner11' - IF (OBJECT_ID('dbo.#sp_code_runner11') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner11',16,127) - END*/ - - /* - SQL14 Version Bump - */ - /*if (CHARINDEX('12.0.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner12', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner12','P') IS NOT NULL drop proc dbo.#sp_code_runner12 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner12' - IF (OBJECT_ID('dbo.#sp_code_runner12') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner12',16,127) - END*/ - /* - SQL 15 Version Bump - */ - /*ELSE if (CHARINDEX('13.0.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_code_runner07 to #sp_code_runner13', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_code_runner13','P') IS NOT NULL drop proc dbo.#sp_code_runner13 - EXEC sp_rename '#sp_code_runner07','#sp_code_runner13' - IF (OBJECT_ID('dbo.#sp_code_runner13') IS NULL) - RAISERROR('Error renaming #sp_code_runner07 to #sp_code_runner13',16,127) - END*/ - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner08', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner08 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - BEGIN - EXEC dbo.#sp_code_runner07 @StartCmd, @StartTime, @StopCondition, - @StopMessage, @IterationTime, @Duration, @StopCmd, - @PollingInterval, @PauseBetweenRuns, - @OutputDir, @OutputFileMask, @NumFiles - END - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner09', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner09 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - BEGIN - EXEC dbo.#sp_code_runner07 @StartCmd, @StartTime, @StopCondition, - @StopMessage, @IterationTime, @Duration, @StopCmd, - @PollingInterval, @PauseBetweenRuns, - @OutputDir, @OutputFileMask, @NumFiles - END - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner10', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner10 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - BEGIN - EXEC dbo.#sp_code_runner07 @StartCmd, @StartTime, @StopCondition, - @StopMessage, @IterationTime, @Duration, @StopCmd, - @PollingInterval, @PauseBetweenRuns, - @OutputDir, @OutputFileMask, @NumFiles - END - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner11', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner11 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - BEGIN - EXEC dbo.#sp_code_runner07 @StartCmd, @StartTime, @StopCondition, - @StopMessage, @IterationTime, @Duration, @StopCmd, - @PollingInterval, @PauseBetweenRuns, - @OutputDir, @OutputFileMask, @NumFiles - END - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner12', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner12 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - BEGIN - EXEC dbo.#sp_code_runner07 @StartCmd, @StartTime, @StopCondition, - @StopMessage, @IterationTime, @Duration, @StopCmd, - @PollingInterval, @PauseBetweenRuns, - @OutputDir, @OutputFileMask, @NumFiles - END - GO - PRINT '' - RAISERROR ('===== Creating #sp_code_runner13', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_code_runner13 @StartCmd nvarchar(4000)='/?', @StartTime char(8)=NULL, @StopCondition nvarchar(4000)=NULL, - @StopMessage nvarchar(4000)='Stop condition met.', @IterationTime char(8)=NULL, @Duration char(8)=NULL, @StopCmd nvarchar(4000)=NULL, - @PollingInterval char(8)='00:00:05', @PauseBetweenRuns char(8)=NULL, - @OutputDir sysname=NULL, @OutputFileMask sysname=NULL, @NumFiles int=16 - AS - BEGIN - EXEC dbo.#sp_code_runner07 @StartCmd, @StartTime, @StopCondition, - @StopMessage, @IterationTime, @Duration, @StopCmd, - @PollingInterval, @PauseBetweenRuns, - @OutputDir, @OutputFileMask, @NumFiles - END - GO - - /* - - #sp_blocker_pss - - */ - - if object_id('dbo.#sp_blocker_pss07','P') IS NOT NULL - drop procedure dbo.#sp_blocker_pss07 - GO - PRINT '' - RAISERROR ('===== Creating #sp_blocker_pss07', 0, 1) WITH NOWAIT - GO - create proc #sp_blocker_pss07 (@latch int = 0, @fast int = 1, @appname sysname='SQLDIAG') - as - --version 12 - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - set nocount on - declare @spid varchar(6) - declare @blocked varchar(6) - declare @time datetime - declare @time2 datetime - declare @time3 datetime - - set @time = getdate() - - select spid, ecid, blocked, waittype, dbid, 'ignore_app' = case when convert(varchar(128),hostname) = @appname then 1 else 0 end into #probclients from master..sysprocesses where blocked!=0 or waittype != 0x0000 - create unique clustered index pc on #probclients (blocked, spid, ecid) - set @time3 = getdate() - - if exists (select spid from #probclients where ignore_app != 1 or waittype != 0x020B) - begin - set @time2 = getdate() - print '' - print '7 Start time: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,@time2)) + ' ' + convert(varchar(12), datediff(ms,@time,@time3)) - - insert #probclients select distinct blocked, 0, 0, 0x0000, 0, 0 from #probclients - where blocked not in (select spid from #probclients) and blocked != 0 - - if (@fast = 1) - begin - print '' - print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion) - select spid, status, blocked, open_tran, waitresource, waittype, - waittime, cmd, lastwaittype, cpu, physical_io, - memusage,last_batch=convert(varchar(26), last_batch,121), - login_time=convert(varchar(26), login_time,121), net_address, - net_library, dbid, ecid, kpid, hostname, hostprocess, - loginame, program_name, nt_domain, nt_username, uid, sid - from master..sysprocesses - where blocked!=0 or waittype != 0x0000 - or spid in (select blocked from #probclients where blocked != 0) - or spid in (select spid from #probclients where blocked != 0) - - print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) - - - print '' - print 'SYSPROC FIRST PASS' - select spid, ecid, waittype from #probclients where waittype != 0x0000 - - if exists(select blocked from #probclients where blocked != 0) - begin - print 'Blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - print 'SPIDs at the head of blocking chains' - - select spid from #probclients - where blocked = 0 and spid in (select blocked from #probclients where spid != 0) - if @latch = 0 - begin - print 'SYSLOCKINFO' - set @time2 = getdate() - - select spid = convert (smallint, req_spid), - ecid = convert (smallint, req_ecid), - rsc_dbid As dbid, - rsc_objid As ObjId, - rsc_indid As IndId, - Type = case rsc_type when 1 then 'NUL' - when 2 then 'DB' - when 3 then 'FIL' - when 4 then 'IDX' - when 5 then 'TAB' - when 6 then 'PAG' - when 7 then 'KEY' - when 8 then 'EXT' - when 9 then 'RID' end, - Resource = substring (rsc_text, 1, 16), - Mode = case req_mode + 1 when 1 then NULL - when 2 then 'Sch-S' - when 3 then 'Sch-M' - when 4 then 'IS' - when 5 then 'SIU' - when 6 then 'IS-S' - when 7 then 'IX' - when 8 then 'SIX' - when 9 then 'S' - when 10 then 'U' - when 11 then 'IIn-Nul' - when 12 then 'IS-X' - when 13 then 'IU' - when 14 then 'IS-U' - when 15 then 'X' - when 16 then 'BU' end, - Status = case req_status when 1 then 'GRANT' - when 2 then 'CNVT' - when 3 then 'WAIT' end - from master.dbo.syslockinfo s, - #probclients p - where p.spid = s.req_spid - - print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) - end -- latch not set - end -- blocking via locks - else - print 'No blocking via locks at ' + convert(varchar(26), @time, 121) - end -- fast set - - else - begin -- Fast not set - print '' - print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion) - - select spid, status, blocked, open_tran, waitresource, waittype, - waittime, cmd, lastwaittype, cpu, physical_io, - memusage,last_batch=convert(varchar(26), last_batch,121), - login_time=convert(varchar(26), login_time,121), net_address, - net_library, dbid, ecid, kpid, hostname, hostprocess, - loginame, program_name, nt_domain, nt_username, uid, sid - from master..sysprocesses - - print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) - - print '' - print 'SYSPROC FIRST PASS' - select spid, ecid, waittype from #probclients where waittype != 0x0000 - - if exists(select blocked from #probclients where blocked != 0) - begin - print 'Blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - print 'SPIDs at the head of blocking chains' - select spid from #probclients - where blocked = 0 and spid in (select blocked from #probclients where spid != 0) - if @latch = 0 - begin - print 'SYSLOCKINFO' - set @time2 = getdate() - - select spid = convert (smallint, req_spid), - ecid = convert (smallint, req_ecid), - rsc_dbid As dbid, - rsc_objid As ObjId, - rsc_indid As IndId, - Type = case rsc_type when 1 then 'NUL' - when 2 then 'DB' - when 3 then 'FIL' - when 4 then 'IDX' - when 5 then 'TAB' - when 6 then 'PAG' - when 7 then 'KEY' - when 8 then 'EXT' - when 9 then 'RID' end, - Resource = substring (rsc_text, 1, 16), - Mode = case req_mode + 1 when 1 then NULL - when 2 then 'Sch-S' - when 3 then 'Sch-M' - when 4 then 'IS' - when 5 then 'SIU' - when 6 then 'IS-S' - when 7 then 'IX' - when 8 then 'SIX' - when 9 then 'S' - when 10 then 'U' - when 11 then 'IIn-Nul' - when 12 then 'IS-X' - when 13 then 'IU' - when 14 then 'IS-U' - when 15 then 'X' - when 16 then 'BU' end, - Status = case req_status when 1 then 'GRANT' - when 2 then 'CNVT' - when 3 then 'WAIT' end - from master.dbo.syslockinfo - - print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) - end -- latch not set - - end - else - print 'No blocking via locks at ' + convert(varchar(26), @time, 121) - - end -- Fast not set - - print '' - print 'DBCC SQLPERF(WAITSTATS)' - dbcc sqlperf(waitstats) - print '' - - print '' - Print '*********************************************************************' - Print 'Print out DBCC INPUTBUFFER for all blocked or blocking spids.' - Print '*********************************************************************' - - declare ibuffer cursor fast_forward for - select cast (spid as varchar(6)) as spid, cast (blocked as varchar(6)) as blocked - from #probclients - where (spid <> @@spid) and (blocked!=0 - or (waittype != 0x0000 and ignore_app = 0) - or spid in (select blocked from #probclients where blocked != 0)) - - open ibuffer - fetch next from ibuffer into @spid, @blocked - while (@@fetch_status != -1) - begin - print '' - exec ('print ''DBCC INPUTBUFFER FOR SPID ' + @spid + '''') - exec ('dbcc inputbuffer (' + @spid + ')') - - fetch next from ibuffer into @spid, @blocked - end - deallocate ibuffer - - Print '' - Print '*******************************************************************************' - Print 'Print out DBCC OPENTRAN for active databases for all blocked or blocking spids.' - Print '*******************************************************************************' - declare ibuffer cursor fast_forward for - select distinct cast (dbid as varchar(6)) from #probclients - where dbid != 0 - open ibuffer - fetch next from ibuffer into @spid - while (@@fetch_status != -1) - begin - print '' - exec ('print ''DBCC OPENTRAN FOR DBID ' + @spid + '''') - exec ('dbcc opentran (' + @spid + ')') - print '' - if @spid = '2' select @blocked = 'Y' - fetch next from ibuffer into @spid - end - deallocate ibuffer - if @blocked != 'Y' - begin - print '' - print 'DBCC OPENTRAN FOR tempdb database' - exec ('dbcc opentran (tempdb)') - end - - print '' - print 'End time: ' + convert(varchar(26), getdate(), 121) - end -- All - else - print '7 No Waittypes: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,@time3)) + ' ' + ISNULL (@@servername,'(null)') - GO - IF (CHARINDEX('7.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_blocker_pss07') IS NULL) - RAISERROR('Error creating #sp_blocker_pss07',16,127) - go - - -- SP3 and later - - if object_id('dbo.#sp_blocker_pss08','P') IS NOT NULL - drop procedure dbo.#sp_blocker_pss08 - GO - PRINT '' - RAISERROR ('===== Creating #sp_blocker_pss08 (SP3 and later)', 0, 1) WITH NOWAIT - GO - create procedure #sp_blocker_pss08 (@latch int = 0, @fast int = 1, @appname sysname='SQLDIAG') - as - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - --version 14SP3 - set nocount on - declare @spid varchar(6) - declare @blocked varchar(6) - declare @time datetime - declare @time2 datetime - - set @time = getdate() - declare @probclients table(spid smallint, ecid smallint, blocked smallint, waittype binary(2), dbid smallint, ignore_app tinyint, primary key (blocked, spid, ecid)) - insert @probclients select spid, ecid, blocked, waittype, dbid, case when convert(varchar(128),hostname) = @appname then 1 else 0 end from master..sysprocesses where blocked!=0 or waittype != 0x0000 - - if exists (select spid from @probclients where ignore_app != 1 or waittype != 0x020B) - begin - set @time2 = getdate() - print '' - print '8.2 Start time: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,@time2)) - - insert @probclients select distinct blocked, 0, 0, 0x0000, 0, 0 from @probclients - where blocked not in (select spid from @probclients) and blocked != 0 - - if (@fast = 1) - begin - print '' - print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion) - - select spid, status, blocked, open_tran, waitresource, waittype, - waittime, cmd, lastwaittype, cpu, physical_io, - memusage, last_batch=convert(varchar(26), last_batch,121), - login_time=convert(varchar(26), login_time,121),net_address, - net_library, dbid, ecid, kpid, hostname, hostprocess, - loginame, program_name, nt_domain, nt_username, uid, sid, - sql_handle, stmt_start, stmt_end - from master..sysprocesses - where blocked!=0 or waittype != 0x0000 - or spid in (select blocked from @probclients where blocked != 0) - or spid in (select spid from @probclients where blocked != 0) - - print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) - - print '' - print 'SYSPROC FIRST PASS' - select spid, ecid, waittype from @probclients where waittype != 0x0000 - - if exists(select blocked from @probclients where blocked != 0) - begin - print 'Blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - print 'SPIDs at the head of blocking chains' - select spid from @probclients - where blocked = 0 and spid in (select blocked from @probclients where spid != 0) - if @latch = 0 - begin - print 'SYSLOCKINFO' - select @time2 = getdate() - - select spid = convert (smallint, req_spid), - ecid = convert (smallint, req_ecid), - rsc_dbid As dbid, - rsc_objid As ObjId, - rsc_indid As IndId, - Type = case rsc_type when 1 then 'NUL' - when 2 then 'DB' - when 3 then 'FIL' - when 4 then 'IDX' - when 5 then 'TAB' - when 6 then 'PAG' - when 7 then 'KEY' - when 8 then 'EXT' - when 9 then 'RID' - when 10 then 'APP' end, - Resource = substring (rsc_text, 1, 16), - Mode = case req_mode + 1 when 1 then NULL - when 2 then 'Sch-S' - when 3 then 'Sch-M' - when 4 then 'S' - when 5 then 'U' - when 6 then 'X' - when 7 then 'IS' - when 8 then 'IU' - when 9 then 'IX' - when 10 then 'SIU' - when 11 then 'SIX' - when 12 then 'UIX' - when 13 then 'BU' - when 14 then 'RangeS-S' - when 15 then 'RangeS-U' - when 16 then 'RangeIn-Null' - when 17 then 'RangeIn-S' - when 18 then 'RangeIn-U' - when 19 then 'RangeIn-X' - when 20 then 'RangeX-S' - when 21 then 'RangeX-U' - when 22 then 'RangeX-X'end, - Status = case req_status when 1 then 'GRANT' - when 2 then 'CNVT' - when 3 then 'WAIT' end, - req_transactionID As TransID, req_transactionUOW As TransUOW - from master.dbo.syslockinfo s, - @probclients p - where p.spid = s.req_spid - - print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) - end -- latch not set - end - else - print 'No blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - end -- fast set - - else - begin -- Fast not set - print '' - print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion) - - select spid, status, blocked, open_tran, waitresource, waittype, - waittime, cmd, lastwaittype, cpu, physical_io, - memusage, last_batch=convert(varchar(26), last_batch,121), - login_time=convert(varchar(26), login_time,121),net_address, - net_library, dbid, ecid, kpid, hostname, hostprocess, - loginame, program_name, nt_domain, nt_username, uid, sid, - sql_handle, stmt_start, stmt_end - from master..sysprocesses - - print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) - - print '' - print 'SYSPROC FIRST PASS' - select spid, ecid, waittype from @probclients where waittype != 0x0000 - - if exists(select blocked from @probclients where blocked != 0) - begin - print 'Blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - print 'SPIDs at the head of blocking chains' - select spid from @probclients - where blocked = 0 and spid in (select blocked from @probclients where spid != 0) - if @latch = 0 - begin - print 'SYSLOCKINFO' - select @time2 = getdate() - - select spid = convert (smallint, req_spid), - ecid = convert (smallint, req_ecid), - rsc_dbid As dbid, - rsc_objid As ObjId, - rsc_indid As IndId, - Type = case rsc_type when 1 then 'NUL' - when 2 then 'DB' - when 3 then 'FIL' - when 4 then 'IDX' - when 5 then 'TAB' - when 6 then 'PAG' - when 7 then 'KEY' - when 8 then 'EXT' - when 9 then 'RID' - when 10 then 'APP' end, - Resource = substring (rsc_text, 1, 16), - Mode = case req_mode + 1 when 1 then NULL - when 2 then 'Sch-S' - when 3 then 'Sch-M' - when 4 then 'S' - when 5 then 'U' - when 6 then 'X' - when 7 then 'IS' - when 8 then 'IU' - when 9 then 'IX' - when 10 then 'SIU' - when 11 then 'SIX' - when 12 then 'UIX' - when 13 then 'BU' - when 14 then 'RangeS-S' - when 15 then 'RangeS-U' - when 16 then 'RangeIn-Null' - when 17 then 'RangeIn-S' - when 18 then 'RangeIn-U' - when 19 then 'RangeIn-X' - when 20 then 'RangeX-S' - when 21 then 'RangeX-U' - when 22 then 'RangeX-X'end, - Status = case req_status when 1 then 'GRANT' - when 2 then 'CNVT' - when 3 then 'WAIT' end, - req_transactionID As TransID, req_transactionUOW As TransUOW - from master.dbo.syslockinfo - - print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) - end -- latch not set - end - else - print 'No blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - end -- Fast not set - - print 'DBCC SQLPERF(WAITSTATS)' - dbcc sqlperf(waitstats) - - Print '' - Print '*********************************************************************' - Print 'Print out DBCC Input buffer for all blocked or blocking spids.' - Print '*********************************************************************' - - declare ibuffer cursor fast_forward for - select cast (spid as varchar(6)) as spid, cast (blocked as varchar(6)) as blocked - from @probclients - where (spid <> @@spid) and - ((blocked!=0 or (waittype != 0x0000 and ignore_app = 0)) - or spid in (select blocked from @probclients where blocked != 0)) - open ibuffer - fetch next from ibuffer into @spid, @blocked - while (@@fetch_status != -1) - begin - print '' - print 'DBCC INPUTBUFFER FOR SPID ' + @spid - exec ('dbcc inputbuffer (' + @spid + ')') - - fetch next from ibuffer into @spid, @blocked - end - deallocate ibuffer - - Print '' - Print '*******************************************************************************' - Print 'Print out DBCC OPENTRAN for active databases for all blocked or blocking spids.' - Print '*******************************************************************************' - declare ibuffer cursor fast_forward for - select distinct cast (dbid as varchar(6)) from @probclients - where dbid != 0 - open ibuffer - fetch next from ibuffer into @spid - while (@@fetch_status != -1) - begin - print '' - print 'DBCC OPENTRAN FOR DBID ' + @spid - exec ('dbcc opentran (' + @spid + ')') - print '' - if @spid = '2' select @blocked = 'Y' - fetch next from ibuffer into @spid - end - deallocate ibuffer - if @blocked != 'Y' - begin - print '' - print 'DBCC OPENTRAN FOR tempdb database' - exec ('dbcc opentran (tempdb)') - end - - print 'End time: ' + convert(varchar(26), getdate(), 121) - end -- All - else - print '8 No Waittypes: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,getdate())) + ' ' + ISNULL (@@servername,'(null)') - GO - - -- Pre-SP3 - /* - PRINT '' - RAISERROR ('===== Creating #sp_blocker_pss08 (pre-SP3)', 0, 1) WITH NOWAIT - GO - create proc #sp_blocker_pss08 (@latch int = 0, @fast int = 1, @appname sysname='SQLDIAG') - as - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - --version 14 - set nocount on - declare @spid varchar(6) - declare @blocked varchar(6) - declare @time datetime - declare @time2 datetime - - set @time = getdate() - declare @probclients table(spid smallint, ecid smallint, blocked smallint, waittype binary(2), dbid smallint, ignore_app tinyint, primary key (blocked, spid, ecid)) - insert @probclients select spid, ecid, blocked, waittype, dbid, case when convert(varchar(128),hostname) = @appname then 1 else 0 end from master..sysprocesses where blocked!=0 or waittype != 0x0000 - - if exists (select spid from @probclients where ignore_app != 1 or waittype != 0x020B) - begin - set @time2 = getdate() - print '' - print '8 Start time: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,@time2)) - - insert @probclients select distinct blocked, 0, 0, 0x0000, 0, 0 from @probclients - where blocked not in (select spid from @probclients) and blocked != 0 - - if (@fast = 1) - begin - print '' - print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion) - - select spid, status, blocked, open_tran, waitresource, waittype, - waittime, cmd, lastwaittype, cpu, physical_io, - memusage,last_batch=convert(varchar(26), last_batch,121), - login_time=convert(varchar(26), login_time,121), net_address, - net_library, dbid, ecid, kpid, hostname, hostprocess, - loginame, program_name, nt_domain, nt_username, uid, sid - from master..sysprocesses - where blocked!=0 or waittype != 0x0000 - or spid in (select blocked from @probclients where blocked != 0) - or spid in (select spid from @probclients where waittype != 0x0000) - - print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) - - print '' - print 'SYSPROC FIRST PASS' - select spid, ecid, waittype from @probclients where waittype != 0x0000 - - if exists(select blocked from @probclients where blocked != 0) - begin - print 'Blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - print 'SPIDs at the head of blocking chains' - select spid from @probclients - where blocked = 0 and spid in (select blocked from @probclients where spid != 0) - if @latch = 0 - begin - print 'SYSLOCKINFO' - select @time2 = getdate() - - select spid = convert (smallint, req_spid), - ecid = convert (smallint, req_ecid), - rsc_dbid As dbid, - rsc_objid As ObjId, - rsc_indid As IndId, - Type = case rsc_type when 1 then 'NUL' - when 2 then 'DB' - when 3 then 'FIL' - when 4 then 'IDX' - when 5 then 'TAB' - when 6 then 'PAG' - when 7 then 'KEY' - when 8 then 'EXT' - when 9 then 'RID' - when 10 then 'APP' end, - Resource = substring (rsc_text, 1, 16), - Mode = case req_mode + 1 when 1 then NULL - when 2 then 'Sch-S' - when 3 then 'Sch-M' - when 4 then 'S' - when 5 then 'U' - when 6 then 'X' - when 7 then 'IS' - when 8 then 'IU' - when 9 then 'IX' - when 10 then 'SIU' - when 11 then 'SIX' - when 12 then 'UIX' - when 13 then 'BU' - when 14 then 'RangeS-S' - when 15 then 'RangeS-U' - when 16 then 'RangeIn-Null' - when 17 then 'RangeIn-S' - when 18 then 'RangeIn-U' - when 19 then 'RangeIn-X' - when 20 then 'RangeX-S' - when 21 then 'RangeX-U' - when 22 then 'RangeX-X'end, - Status = case req_status when 1 then 'GRANT' - when 2 then 'CNVT' - when 3 then 'WAIT' end, - req_transactionID As TransID, req_transactionUOW As TransUOW - from master.dbo.syslockinfo s, - @probclients p - where p.spid = s.req_spid - - print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) - end -- latch not set - end - else - print 'No blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - end -- fast set - - else - begin -- Fast not set - print '' - print 'SYSPROCESSES ' + ISNULL (@@servername,'(null)') + ' ' + str(@@microsoftversion) - - select spid, status, blocked, open_tran, waitresource, waittype, - waittime, cmd, lastwaittype, cpu, physical_io, - memusage,last_batch=convert(varchar(26), last_batch,121), - login_time=convert(varchar(26), login_time,121), net_address, - net_library, dbid, ecid, kpid, hostname, hostprocess, - loginame, program_name, nt_domain, nt_username, uid, sid - from master..sysprocesses - - print 'ESP ' + convert(varchar(12), datediff(ms,@time2,getdate())) - - print '' - print 'SYSPROC FIRST PASS' - select spid, ecid, waittype from @probclients where waittype != 0x0000 - - if exists(select blocked from @probclients where blocked != 0) - begin - print 'Blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - print 'SPIDs at the head of blocking chains' - select spid from @probclients - where blocked = 0 and spid in (select blocked from @probclients where spid != 0) - if @latch = 0 - begin - print 'SYSLOCKINFO' - select @time2 = getdate() - - select spid = convert (smallint, req_spid), - ecid = convert (smallint, req_ecid), - rsc_dbid As dbid, - rsc_objid As ObjId, - rsc_indid As IndId, - Type = case rsc_type when 1 then 'NUL' - when 2 then 'DB' - when 3 then 'FIL' - when 4 then 'IDX' - when 5 then 'TAB' - when 6 then 'PAG' - when 7 then 'KEY' - when 8 then 'EXT' - when 9 then 'RID' - when 10 then 'APP' end, - Resource = substring (rsc_text, 1, 16), - Mode = case req_mode + 1 when 1 then NULL - when 2 then 'Sch-S' - when 3 then 'Sch-M' - when 4 then 'S' - when 5 then 'U' - when 6 then 'X' - when 7 then 'IS' - when 8 then 'IU' - when 9 then 'IX' - when 10 then 'SIU' - when 11 then 'SIX' - when 12 then 'UIX' - when 13 then 'BU' - when 14 then 'RangeS-S' - when 15 then 'RangeS-U' - when 16 then 'RangeIn-Null' - when 17 then 'RangeIn-S' - when 18 then 'RangeIn-U' - when 19 then 'RangeIn-X' - when 20 then 'RangeX-S' - when 21 then 'RangeX-U' - when 22 then 'RangeX-X'end, - Status = case req_status when 1 then 'GRANT' - when 2 then 'CNVT' - when 3 then 'WAIT' end, - req_transactionID As TransID, req_transactionUOW As TransUOW - from master.dbo.syslockinfo - - print 'ESL ' + convert(varchar(12), datediff(ms,@time2,getdate())) - end -- latch not set - end - else - print 'No blocking via locks at ' + convert(varchar(26), @time, 121) - print '' - end -- Fast not set - - print 'DBCC SQLPERF(WAITSTATS)' - dbcc sqlperf(waitstats) - - Print '' - Print '*********************************************************************' - Print 'Print out DBCC Input buffer for all blocked or blocking spids.' - Print '*********************************************************************' - - declare ibuffer cursor fast_forward for - select cast (spid as varchar(6)) as spid, cast (blocked as varchar(6)) as blocked - from @probclients - where (spid <> @@spid) and - ((blocked!=0 or (waittype != 0x0000 and ignore_app = 0)) - or spid in (select blocked from @probclients where blocked != 0)) - open ibuffer - fetch next from ibuffer into @spid, @blocked - while (@@fetch_status != -1) - begin - print '' - print 'DBCC INPUTBUFFER FOR SPID ' + @spid - exec ('dbcc inputbuffer (' + @spid + ')') - - fetch next from ibuffer into @spid, @blocked - end - deallocate ibuffer - - Print '' - Print '*******************************************************************************' - Print 'Print out DBCC OPENTRAN for active databases for all blocked or blocking spids.' - Print '*******************************************************************************' - declare ibuffer cursor fast_forward for - select distinct cast (dbid as varchar(6)) from @probclients - where dbid != 0 - open ibuffer - fetch next from ibuffer into @spid - while (@@fetch_status != -1) - begin - print '' - print 'DBCC OPENTRAN FOR DBID ' + @spid - exec ('dbcc opentran (' + @spid + ')') - print '' - if @spid = '2' select @blocked = 'Y' - fetch next from ibuffer into @spid - end - deallocate ibuffer - if @blocked != 'Y' - begin - print '' - print 'DBCC OPENTRAN FOR tempdb database' - exec ('dbcc opentran (tempdb)') - end - - print 'End time: ' + convert(varchar(26), getdate(), 121) - end -- All - else - print '8 No Waittypes: ' + convert(varchar(26), @time, 121) + ' ' + convert(varchar(12), datediff(ms,@time,getdate())) + ' ' + ISNULL (@@servername,'(null)') - */ - GO - IF (CHARINDEX('8.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_blocker_pss08') IS NULL) - RAISERROR('Error creating #sp_blocker_pss08',16,127) - go - - /* - - #sp_sqldiag_cleanup - - */ - - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup07') IS NOT NULL - DROP PROC dbo.#sp_sqldiag_cleanup07 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag_cleanup07', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag_cleanup07 @AppName sysname='PSSDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - IF (CHARINDEX('7.00.',@@VERSION)<>0) AND object_id('dbo.#sp_trace07') IS NOT NULL - EXEC dbo.#sp_trace07 'OFF', @AppName=@AppName - ELSE IF (CHARINDEX('8.00.',@@VERSION)<>0) AND object_id('dbo.#sp_trace08') IS NOT NULL - EXEC dbo.#sp_trace08 'OFF', @AppName=@AppName - - EXEC('DBCC CACHEPROFILE(2)') -- Turn off cache profiling (wrap in EXEC() to prevent batch-aborting error on 7.0) - - DECLARE @spid int, @cmd varchar(30) - DECLARE osqls CURSOR FOR - SELECT spid FROM master..sysprocesses - WHERE hostname=@AppName AND spid<>@@SPID - FOR READ ONLY - - OPEN osqls - FETCH osqls INTO @spid - WHILE @@FETCH_STATUS=0 BEGIN - SET @cmd='KILL '+CAST(@spid AS varchar) - EXEC(@cmd) - FETCH osqls INTO @spid - END - CLOSE osqls - DEALLOCATE osqls - - GO - IF (CHARINDEX('7.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag_cleanup07') IS NULL) - RAISERROR('Error creating #sp_sqldiag_cleanup07',16,127) - GO - IF (CHARINDEX('8.00.',@@VERSION)<>0) - BEGIN - PRINT '' - RAISERROR ('===== Renaming #sp_sqldiag_cleanup07 to #sp_sqldiag_cleanup08', 0, 1) WITH NOWAIT - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup08','P') IS NOT NULL drop proc dbo.#sp_sqldiag_cleanup08 - EXEC sp_rename '#sp_sqldiag_cleanup07','#sp_sqldiag_cleanup08' - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup08') IS NULL - RAISERROR('Error renaming #sp_sqldiag_cleanup07 to #sp_sqldiag_cleanup08',16,127) - END - GO - - - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup09') IS NOT NULL - DROP PROC dbo.#sp_sqldiag_cleanup09 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag_cleanup09', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag_cleanup09 @AppName sysname='SQLDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - IF object_id('dbo.#sp_trace09') IS NOT NULL BEGIN - EXEC dbo.#sp_trace09 'OFF', @AppName=@AppName - EXEC dbo.#sp_trace09 'OFF', @AppName=@AppName, @TraceName='tsqlblktrace' - END - - DECLARE @spid int, @cmd varchar(30) - DECLARE osqls CURSOR FOR - SELECT spid FROM master..sysprocesses - WHERE hostname=@AppName AND spid<>@@SPID - FOR READ ONLY - - OPEN osqls - FETCH osqls INTO @spid - WHILE @@FETCH_STATUS=0 BEGIN - SET @cmd='KILL '+CAST(@spid AS varchar) - EXEC(@cmd) - FETCH osqls INTO @spid - END - CLOSE osqls - DEALLOCATE osqls - - GO - IF (CHARINDEX('9.00.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag_cleanup09','P') IS NULL) - RAISERROR('Error creating #sp_sqldiag_cleanup09',16,127) - GO - - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup10') IS NOT NULL - DROP PROC dbo.#sp_sqldiag_cleanup10 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag_cleanup10', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag_cleanup10 @AppName sysname='SQLDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - IF object_id('dbo.#sp_trace10') IS NOT NULL BEGIN - EXEC dbo.#sp_trace10 'OFF', @AppName=@AppName - EXEC dbo.#sp_trace10 'OFF', @AppName=@AppName, @TraceName='tsqlblktrace' - END - - DECLARE @spid int, @cmd varchar(30) - DECLARE osqls CURSOR FOR - SELECT spid FROM master..sysprocesses - WHERE hostname=@AppName AND spid<>@@SPID - FOR READ ONLY - - OPEN osqls - FETCH osqls INTO @spid - WHILE @@FETCH_STATUS=0 BEGIN - SET @cmd='KILL '+CAST(@spid AS varchar) - EXEC(@cmd) - FETCH osqls INTO @spid - END - CLOSE osqls - DEALLOCATE osqls - - GO - /* - The board chagned the Product Version format in Katmai. The current foramt starting from Katmai will be single zero for minor version instead of two zeros in previous sql versions. `" 10.m.bbbb.rr `" - */ - IF (CHARINDEX('10.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag_cleanup10') IS NULL) - RAISERROR('Error creating #sp_sqldiag_cleanup10',16,127) - GO - - /* SQL11 Version Bump */ - - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup11') IS NOT NULL - DROP PROC dbo.#sp_sqldiag_cleanup11 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag_cleanup11', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag_cleanup11 @AppName sysname='SQLDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - IF object_id('dbo.#sp_trace11') IS NOT NULL BEGIN - EXEC dbo.#sp_trace11 'OFF', @AppName=@AppName - EXEC dbo.#sp_trace11 'OFF', @AppName=@AppName, @TraceName='tsqlblktrace' - END - - DECLARE @spid int, @cmd varchar(30) - DECLARE osqls CURSOR FOR - SELECT spid FROM master..sysprocesses - WHERE hostname=@AppName AND spid<>@@SPID - FOR READ ONLY - - OPEN osqls - FETCH osqls INTO @spid - WHILE @@FETCH_STATUS=0 BEGIN - SET @cmd='KILL '+CAST(@spid AS varchar) - EXEC(@cmd) - FETCH osqls INTO @spid - END - CLOSE osqls - DEALLOCATE osqls - - GO - - IF (CHARINDEX('11.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag_cleanup11') IS NULL) - RAISERROR('Error creating #sp_sqldiag_cleanup11',16,127) - GO - - /* SQL14 Version Bump */ - - IF OBJECT_ID('dbo.#sp_sqldiag_cleanup12') IS NOT NULL - DROP PROC dbo.#sp_sqldiag_cleanup12 - GO - PRINT '' - RAISERROR ('===== Creating #sp_sqldiag_cleanup12', 0, 1) WITH NOWAIT - GO - CREATE PROC dbo.#sp_sqldiag_cleanup12 @AppName sysname='SQLDIAG' - AS - if is_member('sysadmin')=0 begin - print 'Must be a member of the sysadmin group in order to run this procedure' - return - end - IF object_id('dbo.#sp_trace12') IS NOT NULL BEGIN - EXEC dbo.#sp_trace11 'OFF', @AppName=@AppName - EXEC dbo.#sp_trace11 'OFF', @AppName=@AppName, @TraceName='tsqlblktrace' - END - - DECLARE @spid int, @cmd varchar(30) - DECLARE osqls CURSOR FOR - SELECT spid FROM master..sysprocesses - WHERE hostname=@AppName AND spid<>@@SPID - FOR READ ONLY - - OPEN osqls - FETCH osqls INTO @spid - WHILE @@FETCH_STATUS=0 BEGIN - SET @cmd='KILL '+CAST(@spid AS varchar) - EXEC(@cmd) - FETCH osqls INTO @spid - END - CLOSE osqls - DEALLOCATE osqls - - GO - - IF (CHARINDEX('12.0.',@@VERSION)<>0) AND (OBJECT_ID('dbo.#sp_sqldiag_cleanup12') IS NULL) - RAISERROR('Error creating #sp_sqldiag_cleanup12',16,127) - GO - create procedure #sp_killpssdiagSessions - as - declare curSession - CURSOR for select 'kill ' + cast( session_id as varchar(max)) from sys.dm_exec_sessions where host_name = 'pssdiag' and program_name='SQLCMD' and session_id <> @@spid - open curSession - declare @sql varchar(max) - fetch next from curSession into @sql - while @@FETCH_STATUS = 0 - begin - exec (@sql) - fetch next from curSession into @sql - end - close curSession - deallocate curSession - - go - " - - if ($true -eq $returnVariable) - { - Write-LogDebug "Returned variable without creating file, this maybe due to use of GUI to filter out some of the xevents" - - $content = $content -split "`r`n" - return $content - } - - if (-Not (Test-Path $fileName)) - { - Set-Content -Path $fileName -Value $content - } else - { - Write-LogDebug "$filName already exists, could be from GUI" - } - - #check if command was successful, then add the file to the list for cleanup AND return collector name - if ($true -eq $?) - { - $global:tblInternalSQLFiles += $collectorName - return $collectorName - } - - Write-LogDebug "Failed to build SQL File " - Write-LogDebug $fileName - - #return false if we reach here. - return $false - - } - - diff --git a/SQL LogScout/Bin/SQLScript_MiscDiagInfo.psm1 b/SQL LogScout/Bin/SQLScript_MiscDiagInfo.psm1 index 0669e8d..9d5a8e0 100644 --- a/SQL LogScout/Bin/SQLScript_MiscDiagInfo.psm1 +++ b/SQL LogScout/Bin/SQLScript_MiscDiagInfo.psm1 @@ -321,6 +321,35 @@ PRINT '' + PRINT '-- sys.servers --' + SELECT [server_id] + ,[name] + ,[product] + ,[provider] + ,CONVERT(VARCHAR(512),[data_source]) AS [data_source] + ,CONVERT(VARCHAR(512),[location]) AS [location] + ,CONVERT(VARCHAR(512),[provider_string]) AS [provider_string] + ,[catalog] + ,[connect_timeout] + ,[query_timeout] + ,[is_linked] + ,[is_remote_login_enabled] + ,[is_rpc_out_enabled] + ,[is_data_access_enabled] + ,[is_collation_compatible] + ,[uses_remote_collation] + ,[collation_name] + ,[lazy_schema_validation] + ,[is_system] + ,[is_publisher] + ,[is_subscriber] + ,[is_distributor] + ,[is_nonsql_subscriber] + ,[is_remote_proc_transaction_promotion_enabled] + ,[modify_date] + FROM [master].[sys].[servers] + PRINT '' + --this proc is only present in SQL Server 2019 and later but seems not present in early builds IF OBJECT_ID('sys.sp_certificate_issuers') IS NOT NULL BEGIN @@ -472,6 +501,355 @@ DROP TABLE #dbcc_loginfo_cur_db DROP TABLE #loginfo_all_dbs + PRINT '' + + PRINT '-- sql_agent_jobs_information --'; +WITH LastExecution AS ( + SELECT ROW_NUMBER() OVER (PARTITION BY job_id ORDER BY run_date DESC, run_time DESC) as id, + job_id, + run_date, + run_time, + run_status + FROM msdb.dbo.sysjobhistory + WHERE step_id = 0 + ) + SELECT sj.name AS JobName, + CASE sj.enabled + WHEN 1 THEN 'Yes' + ELSE 'No' + END AS IsEnabled, + CASE ss.enabled + WHEN 1 THEN 'Yes' + ELSE 'No' + END AS ScheduleEnabled, + CASE ss.freq_type + WHEN 1 THEN 'Once' + WHEN 4 THEN 'Daily' + WHEN 8 THEN 'Weekly' + WHEN 16 THEN 'Monthly' + WHEN 32 THEN 'Monthly - Interval Related' + WHEN 64 THEN 'When Agent Starts' + WHEN 128 THEN 'When Computer is Idle' + END AS Frequency, + CASE ss.freq_subday_type + WHEN 0 THEN 'N/A' + WHEN 1 THEN 'Specific Time' + WHEN 2 THEN 'Seconds' + WHEN 4 THEN 'Minutes' + WHEN 8 THEN 'Hours' + END AS IntervalType, + CASE + WHEN ss.freq_subday_type = 1 THEN LEFT(STUFF(STUFF(STUFF(CONVERT(VARCHAR(6), active_start_time), 1, 0, + REPLICATE('0', 6 - LEN(CONVERT(VARCHAR(6), active_start_time)))), 3, 0, ':'), 6, 0, ':'), 12) + ELSE 'N/A' + END AS ExecutionTime, + CASE + WHEN ss.freq_type = 1 THEN 'N/A' + WHEN ss.freq_type = 64 THEN 'N/A' + WHEN ss.freq_type = 16 THEN 'N/A' + WHEN ss.freq_type = 4 THEN 'Every ' + CONVERT(VARCHAR(10), ss.freq_relative_interval) + ' day(s)' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 1 THEN 'Sunday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 2 THEN 'Monday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 4 THEN 'Tuesday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 8 THEN 'Wednesday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 16 THEN 'Thursday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 32 THEN 'Friday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 62 THEN 'Monday to Saturday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 64 THEN 'Saturday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 65 THEN 'Saturday, Sunday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 124 THEN 'Tuesday to Sunday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 126 THEN 'Monday to Sunday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 127 THEN 'Monday to Sunday (All days)' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 9 THEN 'Wednesday, Sunday' + WHEN ss.freq_type = 8 AND ss.freq_relative_interval = 95 THEN 'Monday, Tuesday, Wednesday, Thursday, Saturday, Sunday' + WHEN ss.freq_type = 8 THEN 'Every ' + CONVERT(VARCHAR(20), ss.freq_recurrence_factor) + ' Week' + WHEN ss.freq_type = 16 THEN 'Every ' + CONVERT(VARCHAR(20), ss.freq_recurrence_factor) + ' Month' + WHEN ss.freq_type = 32 THEN 'Every ' + CONVERT(VARCHAR(20), ss.freq_recurrence_factor) + ' Month' + ELSE 'N/A' + END AS Interval, + CASE + WHEN ss.freq_subday_type = 1 THEN 'N/A' + WHEN ss.freq_subday_type = 2 THEN 'Every ' + CONVERT(VARCHAR(20), ss.freq_subday_interval) + ' second(s)' + WHEN ss.freq_subday_type = 4 THEN 'Every ' + CONVERT(VARCHAR(20), ss.freq_subday_interval) + ' minute(s)' + WHEN ss.freq_subday_type = 8 THEN 'Every ' + CONVERT(VARCHAR(20), ss.freq_subday_interval) + ' hour(s)' + ELSE 'N/A' + END AS DayInterval, + CASE + WHEN ss.freq_type = 16 THEN CONVERT(VARCHAR(2), ss.freq_relative_interval) + WHEN ss.freq_type = 32 AND ss.freq_interval = 1 AND ss.freq_relative_interval = 1 THEN 'First Sunday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 2 AND ss.freq_relative_interval = 1 THEN 'First Monday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 3 AND ss.freq_relative_interval = 1 THEN 'First Tuesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 4 AND ss.freq_relative_interval = 1 THEN 'First Wednesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 5 AND ss.freq_relative_interval = 1 THEN 'First Thursday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 6 AND ss.freq_relative_interval = 1 THEN 'First Friday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 7 AND ss.freq_relative_interval = 1 THEN 'First Saturday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 8 AND ss.freq_relative_interval = 1 THEN 'First day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 9 AND ss.freq_relative_interval = 1 THEN 'First weekday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 10 AND ss.freq_relative_interval = 1 THEN 'First weekend day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 1 AND ss.freq_relative_interval = 2 THEN 'Second Sunday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 2 AND ss.freq_relative_interval = 2 THEN 'Second Monday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 3 AND ss.freq_relative_interval = 2 THEN 'Second Tuesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 4 AND ss.freq_relative_interval = 2 THEN 'Second Wednesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 5 AND ss.freq_relative_interval = 2 THEN 'Second Thursday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 6 AND ss.freq_relative_interval = 2 THEN 'Second Friday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 7 AND ss.freq_relative_interval = 2 THEN 'Second Saturday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 8 AND ss.freq_relative_interval = 2 THEN 'Second day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 9 AND ss.freq_relative_interval = 2 THEN 'Second weekday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 10 AND ss.freq_relative_interval = 2 THEN 'Second weekend day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 1 AND ss.freq_relative_interval = 4 THEN 'Third Sunday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 2 AND ss.freq_relative_interval = 4 THEN 'Third Monday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 3 AND ss.freq_relative_interval = 4 THEN 'Third Tuesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 4 AND ss.freq_relative_interval = 4 THEN 'Third Wednesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 5 AND ss.freq_relative_interval = 4 THEN 'Third Thursday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 6 AND ss.freq_relative_interval = 4 THEN 'Third Friday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 7 AND ss.freq_relative_interval = 4 THEN 'Third Saturday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 8 AND ss.freq_relative_interval = 4 THEN 'Third day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 9 AND ss.freq_relative_interval = 4 THEN 'Third weekday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 10 AND ss.freq_relative_interval = 4 THEN 'Third weekend day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 1 AND ss.freq_relative_interval = 8 THEN 'Fourth Sunday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 2 AND ss.freq_relative_interval = 8 THEN 'Fourth Monday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 3 AND ss.freq_relative_interval = 8 THEN 'Fourth Tuesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 4 AND ss.freq_relative_interval = 8 THEN 'Fourth Wednesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 5 AND ss.freq_relative_interval = 8 THEN 'Fourth Thursday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 6 AND ss.freq_relative_interval = 8 THEN 'Fourth Friday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 7 AND ss.freq_relative_interval = 8 THEN 'Fourth Saturday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 8 AND ss.freq_relative_interval = 8 THEN 'Fourth day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 9 AND ss.freq_relative_interval = 8 THEN 'Fourth weekday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 10 AND ss.freq_relative_interval = 8 THEN 'Fourth weekend day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 1 AND ss.freq_relative_interval = 16 THEN 'Last Sunday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 2 AND ss.freq_relative_interval = 16 THEN 'Last Monday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 3 AND ss.freq_relative_interval = 16 THEN 'Last Tuesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 4 AND ss.freq_relative_interval = 16 THEN 'Last Wednesday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 5 AND ss.freq_relative_interval = 16 THEN 'Last Thursday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 6 AND ss.freq_relative_interval = 16 THEN 'Last Friday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 7 AND ss.freq_relative_interval = 16 THEN 'Last Saturday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 8 AND ss.freq_relative_interval = 16 THEN 'Last day of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 9 AND ss.freq_relative_interval = 16 THEN 'Last weekday of every month' + WHEN ss.freq_type = 32 AND ss.freq_interval = 10 AND ss.freq_relative_interval = 16 THEN 'Last weekend day of every month' + ELSE 'N/A' + END AS MonthDay, + CONVERT(VARCHAR(10), CONVERT(DATETIME, CONVERT(VARCHAR(10), active_start_date)), 126) AS StartDate, + CONVERT(VARCHAR(10), CONVERT(DATETIME, CONVERT(VARCHAR(10), active_end_date)), 126) AS EndDate, + LEFT(STUFF(STUFF(STUFF(CONVERT(VARCHAR(6), active_start_time), 1, 0, REPLICATE('0', 6 - LEN(CONVERT(VARCHAR(6), active_start_time)))), 3, 0, ':'), 6, 0, ':'), 12) AS StartTime, + LEFT(STUFF(STUFF(STUFF(CONVERT(VARCHAR(6), active_end_time), 1, 0, REPLICATE('0', 6 - LEN(CONVERT(VARCHAR(6), active_end_time)))), 3, 0, ':'), 6, 0, ':'), 12) AS EndTime, + CASE le.run_status + WHEN 0 THEN 'Failed' + WHEN 1 THEN 'Succeeded' + WHEN 2 THEN 'Retry' + WHEN 3 THEN 'Canceled' + WHEN 4 THEN 'In Progress' + ELSE 'Unknown' + END as LastExecutionStatus, + CONVERT(date, CONVERT(varchar(10), le.run_date)) AS LastExecutionDate, + STUFF(STUFF(RIGHT('000000' + CAST(le.run_time AS VARCHAR(6)), 6), 5, 0, ':'), 3, 0, ':') AS LastExecutionTime + FROM msdb..sysjobs sj + LEFT OUTER JOIN msdb..sysjobschedules sjs + ON (sj.job_id = sjs.job_id) + LEFT OUTER JOIN msdb..sysschedules ss + ON (sjs.schedule_id = ss.schedule_id) + LEFT OUTER JOIN LastExecution le + ON sj.job_id = le.job_id AND + le.id = 1 + ORDER BY sj.name + OPTION (MAX_GRANT_PERCENT = 3, MAXDOP 1); + + PRINT '' + PRINT '-- sql_agent_job_history --' + SELECT + j.name AS job_name, + h.job_id, + h.step_id, + h.step_name, + h.sql_message_id, + h.sql_severity, + h.message, + h.run_status, + h.run_date, + h.run_time, + h.run_duration, + h.operator_id_emailed, + h.operator_id_netsent, + h.operator_id_paged, + h.retries_attempted, + h.server, + h.instance_id + FROM ( + SELECT TOP 1000 * + FROM ( + SELECT *, + ROW_NUMBER() OVER (PARTITION BY job_id ORDER BY run_date DESC, run_time DESC) AS rn + FROM msdb.dbo.sysjobhistory + ) AS JobHistory + WHERE rn <= 100 + ) AS h + JOIN msdb.dbo.sysjobs AS j + ON h.job_id = j.job_id + ORDER BY h.run_date DESC, h.run_time DESC; + + PRINT '' + PRINT '-- sys.dm_clr_appdomains --' + SELECT TOP 1000 + appdomain_address, + appdomain_id, + LEFT(appdomain_name, 80) AS appdomain_name, + creation_time, + db_id, + user_id, + LEFT(state, 48) AS state, + strong_refcount, + weak_refcount, + cost, + value, + compatibility_level, + total_processor_time_ms, + total_allocated_memory_kb, + survived_memory_kb + FROM sys.dm_clr_appdomains + IF @@ROWCOUNT >= 1000 PRINT '<<<<< LIMIT OF 1000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' + PRINT '' + + PRINT '-- sys.dm_clr_loaded_assemblies --' + SELECT TOP 1000 + assembly_id, + appdomain_address, + load_time + FROM sys.dm_clr_loaded_assemblies + IF @@rowcount >= 1000 PRINT '<<<<< LIMIT OF 1000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' + PRINT '' + + + PRINT '-- sys.dm_clr_tasks --' + SELECT TOP 1000 + task_address, + sos_task_address, + appdomain_address, + LEFT(state,64) AS state, + LEFT(abort_state,64) AS abort_state, + LEFT(type,64) AS type, + affinity_count, + forced_yield_count + FROM sys.dm_clr_tasks + IF @@rowcount >= 1000 PRINT '<<<<< LIMIT OF 1000 ROWS EXCEEDED, SOME RESULTS NOT SHOWN >>>>>' + PRINT '' + + -- Create temporary tables to store the results for sys.assemblies, sys.assembly_modules, and sys.assembly_types + CREATE TABLE #assemblies ( + database_name NVARCHAR(128), + name SYSNAME NULL, + assembly_id INT, + principal_id INT, + clr_name NVARCHAR(512) NULL, + permission_set TINYINT NULL, + permission_set_desc NVARCHAR(128) NULL, + is_visible BIT, + create_date DATETIME, + modify_date DATETIME, + is_user_defined BIT NULL + ); + + CREATE TABLE #assembly_modules ( + database_name NVARCHAR(128), + object_id INT, + assembly_id INT, + assembly_class NVARCHAR(256) NULL, + assembly_method NVARCHAR(256) NULL, + null_on_null_input BIT NULL, + execute_as_principal_id INT NULL + ); + + CREATE TABLE #assembly_types ( + database_name NVARCHAR(128), + name SYSNAME, + system_type_id TINYINT, + user_type_id INT, + schema_id INT, + principal_id INT NULL, + max_length SMALLINT, + precision TINYINT, + scale TINYINT, + collation_name SYSNAME NULL, + is_nullable BIT NULL, + is_user_defined BIT, + is_assembly_type BIT, + default_object_id INT, + rule_object_id INT, + assembly_id INT, + assembly_class NVARCHAR(256) NULL, + is_binary_ordered BIT NULL, + is_fixed_length BIT NULL, + prog_id NVARCHAR(80) NULL, + assembly_qualified_name NVARCHAR(512) NULL, + is_table_type BIT + ); + + -- Declare a variable to store the database name + DECLARE @database_name NVARCHAR(128); + + -- Declare a table variable to store the list of databases + DECLARE @databases TABLE (database_name NVARCHAR(128)); + + -- Insert the list of databases into the table variable + INSERT INTO @databases (database_name) + SELECT name + FROM sys.databases + WHERE state_desc = 'ONLINE' AND name NOT IN ('master', 'tempdb', 'model', 'msdb'); + + -- Loop through each database and insert the assemblies, assembly modules, and assembly types into the temporary tables + WHILE EXISTS (SELECT 1 FROM @databases) + BEGIN + -- Get the next database name + SELECT TOP 1 @database_name = database_name + FROM @databases; + + -- Construct the dynamic SQL to insert the assemblies into the temporary table + DECLARE @SQLTxt NVARCHAR(MAX) = ' + INSERT INTO #assemblies (database_name, assembly_id, name, principal_id, clr_name, permission_set, permission_set_desc, is_visible, create_date, modify_date, is_user_defined) + SELECT ''' + @database_name + ''', assembly_id, name, principal_id, clr_name, permission_set, permission_set_desc, is_visible, create_date, modify_date, is_user_defined + FROM ' + QUOTENAME(@database_name) + '.sys.assemblies + WHERE assembly_id <> 1'; + + EXEC sp_executesql @SQLTxt; + + -- Construct the dynamic SQL to insert the assembly modules into the temporary table + SET @SQLTxt = ' + INSERT INTO #assembly_modules (database_name, object_id, assembly_id, assembly_class, assembly_method, null_on_null_input, execute_as_principal_id) + SELECT ''' + @database_name + ''', object_id, assembly_id, assembly_class, assembly_method, null_on_null_input, execute_as_principal_id + FROM ' + QUOTENAME(@database_name) + '.sys.assembly_modules'; + + EXEC sp_executesql @SQLTxt; + + -- Construct the dynamic SQL to insert the assembly types into the temporary table + SET @SQLTxt = ' + INSERT INTO #assembly_types (database_name, name, system_type_id, user_type_id, schema_id, principal_id, max_length, precision, scale, collation_name, is_nullable, is_user_defined, is_assembly_type, default_object_id, rule_object_id, assembly_id, assembly_class, is_binary_ordered, is_fixed_length, prog_id, assembly_qualified_name, is_table_type) + SELECT ''' + @database_name + ''', name, system_type_id, user_type_id, schema_id, principal_id, max_length, precision, scale, collation_name, is_nullable, is_user_defined, is_assembly_type, default_object_id, rule_object_id, assembly_id, assembly_class, is_binary_ordered, is_fixed_length, prog_id, assembly_qualified_name, is_table_type + FROM ' + QUOTENAME(@database_name) + '.sys.assembly_types + WHERE schema_id <> SCHEMA_ID(''sys'')'; + + EXEC sp_executesql @SQLTxt; + + -- Remove the processed database from the table variable + DELETE FROM @databases + WHERE database_name = @database_name; + END; + + -- Select the results from the temporary tables + PRINT '-- sys.assemblies --' + SELECT * FROM #assemblies; + PRINT '' + + PRINT '-- sys.assembly_modules --' + SELECT * FROM #assembly_modules; + PRINT '' + + PRINT '-- sys.assembly_types --' + SELECT * FROM #assembly_types; + PRINT '' + + -- Drop the temporary tables + DROP TABLE #assemblies; + DROP TABLE #assembly_modules; + DROP TABLE #assembly_types; + PRINT '' " diff --git a/SQL LogScout/Bin/SQLScript_NeverEndingQuery_perfstats.psm1 b/SQL LogScout/Bin/SQLScript_NeverEndingQuery_perfstats.psm1 index 062531e..028861a 100644 --- a/SQL LogScout/Bin/SQLScript_NeverEndingQuery_perfstats.psm1 +++ b/SQL LogScout/Bin/SQLScript_NeverEndingQuery_perfstats.psm1 @@ -19,77 +19,73 @@ SET NOCOUNT ON DECLARE @cpu_threshold_ms int = 60000 -BEGIN - DECLARE @msg varchar(100) - - IF EXISTS (SELECT * FROM sys.dm_exec_requests req left outer join sys.dm_exec_sessions sess - on req.session_id = sess.session_id - WHERE req.session_id <> @@SPID AND ISNULL (sess.host_name, '') != @appname and sess.is_user_process = 1 AND req.cpu_time > @cpu_threshold_ms) - - BEGIN - - DECLARE @runtime datetime = GETDATE(), @runtime_utc datetime = GETUTCDATE() - --SET @msg = 'Start time: ' + CONVERT (varchar(30), @runtime, 126) - RAISERROR (@msg, 0, 1) WITH NOWAIT - - - PRINT '' - RAISERROR ('-- neverending_query --', 0, 1) WITH NOWAIT - - --query the DMV in a loop to compare the - SELECT CONVERT (varchar(30), @runtime, 126) as runtime, - CONVERT (varchar(30), @runtime_utc, 126) as runtime_utc, - qp.session_id, - convert(nvarchar(48), qp.physical_operator_name) as physical_operator_name, - qp.row_count, - qp.estimate_row_count, - qp.node_id, - req.cpu_time, - req.total_elapsed_time, - substring - (REPLACE - (REPLACE - (SUBSTRING - (SQLText.text - , (req.statement_start_offset/2) + 1 - , ( - (CASE statement_END_offset - WHEN -1 - THEN DATALENGTH(SQLText.text) - ELSE req.statement_END_offset - END - - req.statement_start_offset)/2) + 1) - , CHAR(10), ' '), CHAR(13), ' '), 1, 512) AS active_statement_text, - qp.rewind_count, - qp.rebind_count, - qp.end_of_scan_count, - replace(replace(substring(ISNULL(SQLText.text, ''),1,150),CHAR(10), ' '),CHAR(13), ' ') as batch_text - FROM sys.dm_exec_query_profiles qp - RIGHT OUTER JOIN sys.dm_exec_requests req - ON qp.session_id = req.session_id - LEFT OUTER JOIN sys.dm_exec_sessions sess - on req.session_id = sess.session_id - LEFT OUTER JOIN sys.dm_exec_connections conn - on conn.session_id = req.session_id - and conn.net_transport <> 'session' - OUTER APPLY sys.dm_exec_sql_text (ISNULL (req.sql_handle, conn.most_recent_sql_handle)) as SQLText - WHERE req.session_id <> @@SPID - AND ISNULL (sess.host_name, '') != @appname - AND sess.is_user_process = 1 - AND req.cpu_time > @cpu_threshold_ms - ORDER BY qp.session_id, qp.node_id - --this is to prevent massive grants - OPTION (max_grant_percent = 3, MAXDOP 1) - - --flush results to client - RAISERROR (' ', 0, 1) WITH NOWAIT - +BEGIN TRY + + DECLARE @msg varchar(100) + + IF EXISTS (SELECT * FROM sys.dm_exec_requests req left outer join sys.dm_exec_sessions sess + on req.session_id = sess.session_id + WHERE req.session_id <> @@SPID AND ISNULL (sess.host_name, '') != @appname and sess.is_user_process = 1 AND req.cpu_time > @cpu_threshold_ms) + + BEGIN + + DECLARE @runtime datetime = GETDATE(), @runtime_utc datetime = GETUTCDATE() + --SET @msg = 'Start time: ' + CONVERT (varchar(30), @runtime, 126) + RAISERROR (@msg, 0, 1) WITH NOWAIT + + + PRINT '' + RAISERROR ('-- neverending_query --', 0, 1) WITH NOWAIT + + --query the DMV in a loop to compare the + SELECT CONVERT(VARCHAR(30), @runtime, 126) AS runtime, + CONVERT(VARCHAR(30), @runtime_utc, 126) AS runtime_utc, + qp.session_id, + convert(NVARCHAR(48), qp.physical_operator_name) AS physical_operator_name, + qp.row_count, + qp.estimate_row_count, + qp.node_id, + req.cpu_time, + req.total_elapsed_time, + SUBSTRING(REPLACE(REPLACE(SUBSTRING(SQLText.text, (req.statement_start_offset / 2) + 1, ( + ( + CASE statement_END_offset + WHEN - 1 + THEN DATALENGTH(SQLText.text) + ELSE req.statement_END_offset + END - req.statement_start_offset + ) / 2 + ) + 1), CHAR(10), ' '), CHAR(13), ' '), 1, 512) AS active_statement_text, + qp.rewind_count, + qp.rebind_count, + qp.end_of_scan_count, + replace(replace(substring(ISNULL(SQLText.text, ''), 1, 150), CHAR(10), ' '), CHAR(13), ' ') AS batch_text + FROM sys.dm_exec_query_profiles qp + RIGHT OUTER JOIN sys.dm_exec_requests req ON qp.session_id = req.session_id + LEFT OUTER JOIN sys.dm_exec_sessions sess ON req.session_id = sess.session_id + LEFT OUTER JOIN sys.dm_exec_connections conn ON conn.session_id = req.session_id + AND conn.net_transport <> 'session' + OUTER APPLY sys.dm_exec_sql_text(ISNULL(req.sql_handle, conn.most_recent_sql_handle)) AS SQLText + WHERE req.session_id <> @@SPID + AND ISNULL(sess.host_name, '') != @appname + AND sess.is_user_process = 1 + AND req.cpu_time > @cpu_threshold_ms + ORDER BY qp.session_id, + qp.node_id + --this is to prevent massive grants + OPTION (max_grant_percent = 3,MAXDOP 1) + + --flush results to client + RAISERROR (' ', 0, 1) WITH NOWAIT + END -END +END TRY +BEGIN CATCH + PRINT 'Exception occured in: `"' + OBJECT_NAME(@@PROCID) + '`"' + PRINT 'Msg ' + isnull(cast(Error_Number() as nvarchar(50)), '') + ', Level ' + isnull(cast(Error_Severity() as nvarchar(50)),'') + ', State ' + isnull(cast(Error_State() as nvarchar(50)),'') + ', Server ' + @@servername + ', Line ' + isnull(cast(Error_Line() as nvarchar(50)),'') + char(10) + Error_Message() + char(10); +END CATCH GO - - IF OBJECT_ID ('dbo.sp_Run_NeverEndingQuery_Stats','P') IS NOT NULL DROP PROCEDURE dbo.sp_Run_NeverEndingQuery_Stats GO @@ -99,9 +95,9 @@ as SET NOCOUNT ON PRINT 'starting query never seems to complete perf stats script...' -set language us_english +SET language us_english PRINT '-- script source --' -select 'query never completes stats script' as script_name +SELECT 'query never completes stats script' as script_name PRINT '' PRINT '-- script and environment details --' PRINT 'name value' @@ -122,36 +118,32 @@ PRINT '@@spid ' + ltrim(str(@@spid)) DECLARE @servermajorversion int SET @servermajorversion = CONVERT (INT, (REPLACE (LEFT (CONVERT (nvarchar, SERVERPROPERTY ('ProductVersion')), 2), '.', ''))) -if (@servermajorversion < 12) -begin +IF (@servermajorversion < 12) +BEGIN RAISERROR ('Lightweight Profiling SQL Server version is less than 2014. No additional data can be collected', 0, 1) WITH NOWAIT PRINT '' - return -end + RETURN +END -declare @serverbuild int +DECLARE @serverbuild INT SET @serverbuild = CONVERT (int, SERVERPROPERTY ('ProductBuild')) - - --minimum build 12.0.5000.0 , see https://docs.microsoft.com/en-us/sql/relational-databases/performance/query-profiling-infrastructure?view=sql-server-ver15 -if (@servermajorversion <= 12 and @serverbuild < 5000) -begin +IF (@servermajorversion <= 12 and @serverbuild < 5000) +BEGIN RAISERROR ('Lightweight Profiling Your SQL Sever version does not support collecting real-time perf stats on long-running query', 0, 1) WITH NOWAIT PRINT '' -end +END --13.0.4001.0 (SP1) -else if ((@servermajorversion = '13' and @serverbuild <4001) or (@servermajorversion = 12 and @serverbuild >= 5000)) -begin +ELSE IF ((@servermajorversion = '13' and @serverbuild <4001) or (@servermajorversion = 12 and @serverbuild >= 5000)) +BEGIN RAISERROR ('Lightweight Profiling Using Lightweight Profiling Ver1 requires that you enable SET STATISTICS PROFILE ON in the same session where the query runs', 0, 1) WITH NOWAIT PRINT '' PRINT 'See https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-query-profiles-transact-sql#examples for more information' PRINT '' - - -end -else if ((@servermajorversion = '13' and @serverbuild >=4001) or @servermajorversion = '14') -begin +END +ELSE IF ((@servermajorversion = '13' and @serverbuild >=4001) or @servermajorversion = '14') +BEGIN RAISERROR ('Lightweight Profiling SQL 2016 SP1+ or 2017. Using Lightweight Profiling Ver2', 0, 1) WITH NOWAIT PRINT '' PRINT 'Enabling TF 7412' @@ -164,27 +156,37 @@ begin WHILE (1=1) BEGIN + BEGIN TRY --query the DMV in a loop to compare the EXEC dbo.sp_perf_never_ending_query_snapshots @appname = 'SqlLogScout' WAITFOR DELAY '00:00:10' + END TRY + BEGIN CATCH + PRINT 'Exception occured in: `"' + OBJECT_NAME(@@PROCID) + '`"' + PRINT 'Msg ' + isnull(cast(Error_Number() as nvarchar(50)), '') + ', Level ' + isnull(cast(Error_Severity() as nvarchar(50)),'') + ', State ' + isnull(cast(Error_State() as nvarchar(50)),'') + ', Server ' + @@servername + ', Line ' + isnull(cast(Error_Line() as nvarchar(50)),'') + char(10) + Error_Message() + char(10); + END CATCH END - -end -else if (@servermajorversion >= '15') -begin +END +ELSE IF (@servermajorversion >= '15') +BEGIN RAISERROR ('Lightweight Profiling SQL 2019. Using Lightweight Profiling Ver3 (enabled by default)', 0, 1) WITH NOWAIT PRINT '' WHILE (1=1) BEGIN + BEGIN TRY --query the DMV in a loop to compare the EXEC dbo.sp_perf_never_ending_query_snapshots @appname = 'SqlLogScout' WAITFOR DELAY '00:00:20' + END TRY + BEGIN CATCH + PRINT 'Exception occured in: `"' + OBJECT_NAME(@@PROCID) + '`"' + PRINT 'Msg ' + isnull(cast(Error_Number() as nvarchar(50)), '') + ', Level ' + isnull(cast(Error_Severity() as nvarchar(50)),'') + ', State ' + isnull(cast(Error_State() as nvarchar(50)),'') + ', Server ' + @@servername + ', Line ' + isnull(cast(Error_Line() as nvarchar(50)),'') + char(10) + Error_Message() + char(10); + END CATCH END -end - +END go -exec dbo.sp_Run_NeverEndingQuery_Stats +EXEC dbo.sp_Run_NeverEndingQuery_Stats " if ($true -eq $returnVariable) diff --git a/SQL LogScout/Bin/SQLScript_Repl_Metadata_Collector.psm1 b/SQL LogScout/Bin/SQLScript_Repl_Metadata_Collector.psm1 index cde0952..f740d8e 100644 --- a/SQL LogScout/Bin/SQLScript_Repl_Metadata_Collector.psm1 +++ b/SQL LogScout/Bin/SQLScript_Repl_Metadata_Collector.psm1 @@ -48,7 +48,7 @@ PRINT '-- repl_msdb_jobhistory --' IF HAS_PERMS_BY_NAME('msdb.dbo.sysjobhistory', 'object', 'SELECT') = 1 SELECT TOP (4999) sj.job_id,sj.name,jh.instance_id,jh.step_id,jh.step_name,jh.sql_message_id,jh.sql_severity,CAST(jh.message as nvarchar(256))[message],jh.run_status,jh.run_date,jh.run_time,jh.run_duration,jh.retries_attempted,jh.server FROM [msdb].[dbo].[sysjobs] sj WITH(NOLOCK) - INNER JOIN [msdb].[dbo].[sysjobhistory] jh WITH(NOLOCK) ON sj.[job_id] = sj.[job_id] + INNER JOIN [msdb].[dbo].[sysjobhistory] jh WITH(NOLOCK) ON sj.[job_id] = jh.[job_id] WHERE category_id <> 0 ORDER BY jh.run_date desc, jh.run_time desc, jh.job_id asc, jh.step_id desc ELSE @@ -155,6 +155,8 @@ PRINT 'Logging: Creating Table Variable to Store Distribution Database Records' agent_id,runstatus,start_time,time,duration,comments,xact_seqno,current_delivery_rate,current_delivery_latency,delivered_transactions,delivered_commands, average_commands,delivery_rate,delivery_latency,total_delivered_commands,error_id,updateable_row,timestamp FROM MSdistribution_history WITH (NOLOCK) + /* limit to last 3 days of exeuction as a precaution if the distribution cleanup job is having issues */ + WHERE time >= DATEADD(DAY, -3, GETDATE()) END' ) RAISERROR('',0,1) WITH NOWAIT @@ -182,6 +184,8 @@ PRINT 'Logging: Creating Table Variable to Store Distribution Database Records' agent_id,runstatus,start_time,time,duration,comments,xact_seqno,delivery_time,delivered_transactions,delivered_commands,average_commands,delivery_rate,delivery_latency, error_id,timestamp,updateable_row FROM MSlogreader_history WITH (NOLOCK) + /* limit to last 3 days of exeuction as a precaution if the distribution cleanup job is having issues */ + WHERE time >= DATEADD(DAY, -3, GETDATE()) END' ) RAISERROR('',0,1) WITH NOWAIT @@ -222,6 +226,8 @@ PRINT 'Logging: Creating Table Variable to Store Distribution Database Records' SELECT distribution_dbname = '''+@DistribName+''''+', session_id,agent_id,comments,error_id,timestamp,updateable_row,time FROM MSmerge_history WITH (NOLOCK) + /* limit to last 3 days of exeuction as a precaution if the distribution cleanup job is having issues */ + WHERE time >= DATEADD(DAY, -3, GETDATE()) END' ) RAISERROR('',0,1) WITH NOWAIT @@ -344,6 +350,8 @@ PRINT 'Logging: Creating Table Variable to Store Distribution Database Records' agent_id,publication_id,runstatus,start_time,time,duration,comments,transaction_id,transaction_status,transactions_processed,commands_processed, delivery_rate,transaction_rate,subscriber,subscriberdb,error_id,timestamp FROM MSqreader_history WITH (NOLOCK) + /* limit to last 3 days of exeuction as a precaution if the distribution cleanup job is having issues */ + WHERE time >= DATEADD(DAY, -3, GETDATE()) END' ) RAISERROR('',0,1) WITH NOWAIT @@ -507,6 +515,8 @@ PRINT 'Logging: Creating Table Variable to Store Distribution Database Records' SELECT distribution_dbname = '''+@DistribName+''''+', agent_id,runstatus,start_time,time,duration,comments,delivered_transactions,delivered_commands,delivery_rate,error_id,timestamp FROM MSsnapshot_history WITH (NOLOCK) + /* limit to last 3 days of exeuction as a precaution if the distribution cleanup job is having issues */ + WHERE time >= DATEADD(DAY, -3, GETDATE()) END' ) RAISERROR('',0,1) WITH NOWAIT diff --git a/SQL LogScout/Bin/SQLScript_SQL_Server_Mem_Stats.psm1 b/SQL LogScout/Bin/SQLScript_SQL_Server_Mem_Stats.psm1 index f1ee77c..236e179 100644 --- a/SQL LogScout/Bin/SQLScript_SQL_Server_Mem_Stats.psm1 +++ b/SQL LogScout/Bin/SQLScript_SQL_Server_Mem_Stats.psm1 @@ -36,90 +36,80 @@ AS BEGIN TRY print '-- query execution memory mem_script--' - SELECT CONVERT (varchar(30), @runtime, 121) as runtime, - r.session_id - , r.blocking_session_id - , r.cpu_time - , r.total_elapsed_time - , r.reads - , r.writes - , r.logical_reads - , r.row_count - , wait_time - , wait_type - , r.command - , ltrim(rtrim(replace(replace (substring (SUBSTRING(q.text,r.statement_start_offset/2 +1, (CASE WHEN r.statement_end_offset = -1 THEN LEN(CONVERT(nvarchar(max), q.text)) * 2 ELSE r.statement_end_offset end - r.statement_start_offset )/2 ) , 1, 1000), char(10), ' '), char(13), ' '))) [text] - --, ltrim(rtrim(replace(replace (substring (q.text, 1, 1000), char(10), ' '), char(13), ' '))) [text] - --, REPLACE (REPLACE (SUBSTRING (q.[text] COLLATE Latin1_General_BIN, CHARINDEX (''CREATE '', SUBSTRING (q.[text] COLLATE Latin1_General_BIN, 1, 1000)), 50), CHAR(10), '' ''), CHAR(13), '' '') - --, q.TEXT --Full SQL Text - , s.login_time - , d.name - , s.login_name - , s.host_name - , s.nt_domain - , s.nt_user_name - , s.status - , c.client_net_address - , s.program_name - , s.client_interface_name - -- , s.total_elapsed_time - , s.last_request_start_time - , s.last_request_end_time - , c.connect_time - , c.last_read - , c.last_write - , mg.dop --Degree of parallelism - , mg.request_time --Date and time when this query requested the memory grant. - , mg.grant_time --NULL means memory has not been granted - , mg.requested_memory_kb - / 1024 requested_memory_mb --Total requested amount of memory in megabytes - , mg.granted_memory_kb - / 1024 AS granted_memory_mb --Total amount of memory actually granted in megabytes. NULL if not granted - , mg.required_memory_kb - / 1024 AS required_memory_mb--Minimum memory required to run this query in megabytes. - , max_used_memory_kb - / 1024 AS max_used_memory_mb - , mg.query_cost --Estimated query cost. - , mg.timeout_sec --Time-out in seconds before this query gives up the memory grant request. - , mg.resource_semaphore_id --Nonunique ID of the resource semaphore on which this query is waiting. - , mg.wait_time_ms --Wait time in milliseconds. NULL if the memory is already granted. - , CASE mg.is_next_candidate --Is this process the next candidate for a memory grant - WHEN 1 THEN 'Yes' - WHEN 0 THEN 'No' - ELSE 'Memory has been granted' - END AS 'Next Candidate for Memory Grant' - , rs.target_memory_kb - / 1024 AS server_target_memory_mb --Grant usage target in megabytes. - , rs.max_target_memory_kb - / 1024 AS server_max_target_memory_mb --Maximum potential target in megabytes. NULL for the small-query resource semaphore. - , rs.total_memory_kb - / 1024 AS server_total_memory_mb --Memory held by the resource semaphore in megabytes. - , rs.available_memory_kb - / 1024 AS server_available_memory_mb --Memory available for a new grant in megabytes. - , rs.granted_memory_kb - / 1024 AS server_granted_memory_mb --Total granted memory in megabytes. - , rs.used_memory_kb - / 1024 AS server_used_memory_mb --Physically used part of granted memory in megabytes. - , rs.grantee_count --Number of active queries that have their grants satisfied. - , rs.waiter_count --Number of queries waiting for grants to be satisfied. - , rs.timeout_error_count --Total number of time-out errors since server startup. NULL for the small-query resource semaphore. - , rs.forced_grant_count --Total number of forced minimum-memory grants since server startup. NULL for the small-query resource semaphore. - , object_name (q.objectid, q.dbid) 'Object_Name' - FROM sys.dm_exec_requests r - JOIN sys.dm_exec_connections c - ON r.connection_id = c.connection_id - AND c.net_transport <> 'session' - JOIN sys.dm_exec_sessions s - ON c.session_id = s.session_id - JOIN sys.databases d - ON r.database_id = d.database_id - JOIN sys.dm_exec_query_memory_grants mg - ON s.session_id = mg.session_id - INNER JOIN sys.dm_exec_query_resource_semaphores rs - ON mg.resource_semaphore_id = rs.resource_semaphore_id - CROSS APPLY sys.dm_exec_sql_text (r.sql_handle ) AS q - ORDER BY wait_time DESC - OPTION (max_grant_percent = 3, MAXDOP 1) + SELECT CONVERT (varchar(30), @runtime, 121) as runtime, + r.session_id + , r.blocking_session_id + , r.cpu_time + , r.total_elapsed_time + , r.reads + , r.writes + , r.logical_reads + , r.row_count + , wait_time + , wait_type + , r.command + , LTRIM(RTRIM(REPLACE(REPLACE (SUBSTRING (SUBSTRING(q.text,r.statement_start_offset/2 +1, (CASE WHEN r.statement_end_offset = -1 THEN LEN(CONVERT(nvarchar(max), q.text)) * 2 ELSE r.statement_end_offset end - r.statement_start_offset )/2 ) , 1, 1000), char(10), ' '), char(13), ' '))) [text] + , s.login_time + , DB_NAME(r.database_id) AS name + , s.login_name + , s.host_name + , s.nt_domain + , s.nt_user_name + , s.status + , c.client_net_address + , s.program_name + , s.client_interface_name + , s.last_request_start_time + , s.last_request_end_time + , c.connect_time + , c.last_read + , c.last_write + , mg.dop --Degree of parallelism + , mg.request_time --Date and time when this query requested the memory grant. + , mg.grant_time --NULL means memory has not been granted + , mg.requested_memory_kb / 1024 AS requested_memory_mb --Total requested amount of memory in megabytes + , mg.granted_memory_kb / 1024 AS granted_memory_mb --Total amount of memory actually granted in megabytes. NULL if not granted + , mg.required_memory_kb / 1024 AS required_memory_mb--Minimum memory required to run this query in megabytes. + , max_used_memory_kb / 1024 AS max_used_memory_mb + , mg.query_cost --Estimated query cost. + , mg.timeout_sec --Time-out in seconds before this query gives up the memory grant request. + , mg.resource_semaphore_id --Nonunique ID of the resource semaphore on which this query is waiting. + , mg.wait_time_ms --Wait time in milliseconds. NULL if the memory is already granted. + , CASE mg.is_next_candidate --Is this process the next candidate for a memory grant + WHEN 1 THEN 'Yes' + WHEN 0 THEN 'No' + ELSE 'Memory has been granted' + END AS 'Next Candidate for Memory Grant' + , rs.target_memory_kb + / 1024 AS server_target_memory_mb --Grant usage target in megabytes. + , rs.max_target_memory_kb + / 1024 AS server_max_target_memory_mb --Maximum potential target in megabytes. NULL for the small-query resource semaphore. + , rs.total_memory_kb + / 1024 AS server_total_memory_mb --Memory held by the resource semaphore in megabytes. + , rs.available_memory_kb + / 1024 AS server_available_memory_mb --Memory available for a new grant in megabytes. + , rs.granted_memory_kb + / 1024 AS server_granted_memory_mb --Total granted memory in megabytes. + , rs.used_memory_kb + / 1024 AS server_used_memory_mb --Physically used part of granted memory in megabytes. + , rs.grantee_count --Number of active queries that have their grants satisfied. + , rs.waiter_count --Number of queries waiting for grants to be satisfied. + , rs.timeout_error_count --Total number of time-out errors since server startup. NULL for the small-query resource semaphore. + , rs.forced_grant_count --Total number of forced minimum-memory grants since server startup. NULL for the small-query resource semaphore. + , OBJECT_NAME (q.objectid, q.dbid) AS 'Object_Name' +FROM sys.dm_exec_requests r + JOIN sys.dm_exec_connections c + ON r.connection_id = c.connection_id + AND c.net_transport <> 'session' + JOIN sys.dm_exec_sessions s + ON c.session_id = s.session_id + JOIN sys.dm_exec_query_memory_grants mg + ON s.session_id = mg.session_id + INNER JOIN sys.dm_exec_query_resource_semaphores rs + ON mg.resource_semaphore_id = rs.resource_semaphore_id AND mg.pool_id = rs.pool_id + OUTER APPLY sys.dm_exec_sql_text (r.sql_handle ) AS q +ORDER BY wait_time DESC +OPTION (max_grant_percent = 3, MAXDOP 1, LOOP JOIN, FORCE ORDER) RAISERROR ('', 0, 1) WITH NOWAIT END TRY diff --git a/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats.psm1 b/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats.psm1 index e249147..a3fca7e 100644 --- a/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats.psm1 +++ b/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats.psm1 @@ -31,7 +31,7 @@ IF OBJECT_ID ('#sp_perf_stats','P') IS NOT NULL GO CREATE PROCEDURE #sp_perf_stats @appname sysname='sqllogscout', @runtime datetime, @prevruntime datetime, @IsLite bit=0 AS - SET NOCOUNT ON + SET NOCOUNT ON DECLARE @msg varchar(100) DECLARE @querystarttime datetime DECLARE @queryduration int @@ -706,24 +706,74 @@ CREATE PROCEDURE #sp_perf_stats_infrequent @runtime datetime, @prevruntime datet SELECT /*qry8*/ CONVERT (varchar(30), @runtime, 126) AS 'runtime', * from sys.dm_exec_query_resource_semaphores - /* Resultset #9: dm_exec_query_memory_grants - ** Query sometimes causes follow message: - ** Warning: The join order has been enforced because a local join hint is used.*/ - PRINT '' - RAISERROR ('-- dm_exec_query_memory_grants --', 0, 1) WITH NOWAIT; - SELECT /*qry9*/ CONVERT (varchar(30), @runtime, 126) AS 'runtime', session_id, request_id, scheduler_id, dop, request_time, grant_time, requested_memory_kb, - granted_memory_kb, required_memory_kb, used_memory_kb, max_used_memory_kb, query_cost, timeout_sec, resource_semaphore_id, queue_id, wait_order, is_next_candidate, - wait_time_ms, group_id, pool_id, is_small ideal_memory_kb, plan_handle, [sql_handle], - convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1)) as [database_id], - case when substring(plan_handle,1,1) = 0x05 then convert(int, substring(plan_handle,8,1) + substring(plan_handle,7,1) + substring(plan_handle,6,1) + substring(plan_handle,5,1)) - else NULL end as [object_id], - case when substring(plan_handle,1,1) = 0x05 then - '[' + DB_NAME(convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1))) - + '].[' + object_schema_name(convert(int, substring(plan_handle,8,1) + substring(plan_handle,7,1) + substring(plan_handle,6,1) + substring(plan_handle,5,1)),convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1))) - + '].['+ object_name(convert(int, substring(plan_handle,8,1) + substring(plan_handle,7,1) + substring(plan_handle,6,1) + substring(plan_handle,5,1)),convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1))) + ']' - else 'ad-hoc query, see notableactivequeries for text' end as 'full_object_name' - FROM sys.dm_exec_query_memory_grants - OPTION (MAX_GRANT_PERCENT = 3, MAXDOP 1) + /* Resultset #9: dm_exec_requests, dm_exec_connections, dm_exec_sessions, dm_exec_query_memory_grants*/ + PRINT '' + PRINT '-- query execution memory --' + SELECT CONVERT (varchar(30), @runtime, 121) as runtime, + r.session_id + , r.blocking_session_id + , r.cpu_time + , r.total_elapsed_time + , r.reads + , r.writes + , r.logical_reads + , r.row_count + , wait_time + , wait_type + , r.command + ,LTRIM(RTRIM(REPLACE(REPLACE (SUBSTRING (SUBSTRING(q.text,r.statement_start_offset/2 +1, (CASE WHEN r.statement_end_offset = -1 THEN LEN(CONVERT(nvarchar(max), q.text)) * 2 ELSE r.statement_end_offset end - r.statement_start_offset )/2 ) , 1, 1000), CHAR(10), ' '), CHAR(13), ' '))) [text] + , s.login_time + , DB_NAME(r.database_id) AS name + , s.login_name + , s.host_name + , s.nt_domain + , s.nt_user_name + , s.status + , c.client_net_address + , s.program_name + , s.client_interface_name + , s.last_request_start_time + , s.last_request_end_time + , c.connect_time + , c.last_read + , c.last_write + , mg.dop --Degree of parallelism + , mg.request_time --Date and time when this query requested the memory grant. + , mg.grant_time --NULL means memory has not been granted + , mg.requested_memory_kb / 1024 AS requested_memory_mb --Total requested amount of memory in megabytes + , mg.granted_memory_kb / 1024 AS granted_memory_mb --Total amount of memory actually granted in megabytes. NULL if not granted + , mg.required_memory_kb / 1024 AS required_memory_mb--Minimum memory required to run this query in megabytes. + , max_used_memory_kb / 1024 AS max_used_memory_mb + , mg.query_cost --Estimated query cost. + , mg.timeout_sec --Time-out in seconds before this query gives up the memory grant request. + , mg.resource_semaphore_id --Nonunique ID of the resource semaphore on which this query is waiting. + , mg.wait_time_ms --Wait time in milliseconds. NULL if the memory is already granted. + , CASE mg.is_next_candidate --Is this process the next candidate for a memory grant + WHEN 1 THEN 'Yes' + WHEN 0 THEN 'No' + ELSE 'Memory has been granted' + END AS 'Next Candidate for Memory Grant' + , rs.target_memory_kb / 1024 AS server_target_memory_mb --Grant usage target in megabytes. + , rs.max_target_memory_kb / 1024 AS server_max_target_memory_mb --Maximum potential target in megabytes. NULL for the small-query resource semaphore. + , rs.total_memory_kb / 1024 AS server_total_memory_mb --Memory held by the resource semaphore in megabytes. + , rs.available_memory_kb / 1024 AS server_available_memory_mb --Memory available for a new grant in megabytes. + , rs.granted_memory_kb / 1024 AS server_granted_memory_mb --Total granted memory in megabytes. + , rs.used_memory_kb / 1024 AS server_used_memory_mb --Physically used part of granted memory in megabytes. + , rs.grantee_count --Number of active queries that have their grants satisfied. + , rs.waiter_count --Number of queries waiting for grants to be satisfied. + , rs.timeout_error_count --Total number of time-out errors since server startup. NULL for the small-query resource semaphore. + , rs.forced_grant_count --Total number of forced minimum-memory grants since server startup. NULL for the small-query resource semaphore. + , OBJECT_NAME(q.objectid, q.dbid) AS 'Object_Name' + FROM sys.dm_exec_requests r + JOIN sys.dm_exec_connections c ON r.connection_id = c.connection_id + AND c.net_transport <> 'session' + JOIN sys.dm_exec_sessions s ON c.session_id = s.session_id + JOIN sys.dm_exec_query_memory_grants mg ON s.session_id = mg.session_id + INNER JOIN sys.dm_exec_query_resource_semaphores rs ON mg.resource_semaphore_id = rs.resource_semaphore_id AND mg.pool_id = rs.pool_id + OUTER APPLY sys.dm_exec_sql_text (r.sql_handle ) AS q + ORDER BY wait_time DESC + OPTION (max_grant_percent = 3, MAXDOP 1, LOOP JOIN, FORCE ORDER) + /* Resultset #10: dm_os_memory_brokers */ PRINT '' @@ -903,70 +953,25 @@ GO CREATE PROCEDURE #sp_mem_stats_grants @runtime datetime , @lastruntime datetime =null as BEGIN TRY - print '-- query execution memory --' - SELECT CONVERT (varchar(30), @runtime, 121) as runtime, - r.session_id - , r.blocking_session_id - , r.cpu_time - , r.total_elapsed_time - , r.reads - , r.writes - , r.logical_reads - , r.row_count - , wait_time - , wait_type - , r.command - , LTRIM(RTRIM(REPLACE(REPLACE (SUBSTRING (q.text, 1, 1000), char(10), ' '), char(13), ' '))) [text] - , s.login_time - , d.name - , s.login_name - , s.host_name - , s.nt_domain - , s.nt_user_name - , s.status - , c.client_net_address - , s.program_name - , s.client_interface_name - , s.last_request_start_time - , s.last_request_end_time - , c.connect_time - , c.last_read - , c.last_write - , mg.dop --Degree of parallelism - , mg.request_time --Date and time when this query requested the memory grant. - , mg.grant_time --NULL means memory has not been granted - , mg.requested_memory_kb / 1024 AS requested_memory_mb --Total requested amount of memory in megabytes - , mg.granted_memory_kb / 1024 AS granted_memory_mb --Total amount of memory actually granted in megabytes. NULL if not granted - , mg.required_memory_kb / 1024 AS required_memory_mb--Minimum memory required to run this query in megabytes. - , max_used_memory_kb / 1024 AS max_used_memory_mb - , mg.query_cost --Estimated query cost. - , mg.timeout_sec --Time-out in seconds before this query gives up the memory grant request. - , mg.resource_semaphore_id --Nonunique ID of the resource semaphore on which this query is waiting. - , mg.wait_time_ms --Wait time in milliseconds. NULL if the memory is already granted. - , CASE mg.is_next_candidate --Is this process the next candidate for a memory grant - WHEN 1 THEN 'Yes' - WHEN 0 THEN 'No' - ELSE 'Memory has been granted' - END AS 'Next Candidate for Memory Grant' - , rs.target_memory_kb / 1024 AS server_target_memory_mb --Grant usage target in megabytes. - , rs.max_target_memory_kb / 1024 AS server_max_target_memory_mb --Maximum potential target in megabytes. NULL for the small-query resource semaphore. - , rs.total_memory_kb / 1024 AS server_total_memory_mb --Memory held by the resource semaphore in megabytes. - , rs.available_memory_kb / 1024 AS server_available_memory_mb --Memory available for a new grant in megabytes. - , rs.granted_memory_kb / 1024 AS server_granted_memory_mb --Total granted memory in megabytes. - , rs.used_memory_kb / 1024 AS server_used_memory_mb --Physically used part of granted memory in megabytes. - , rs.grantee_count --Number of active queries that have their grants satisfied. - , rs.waiter_count --Number of queries waiting for grants to be satisfied. - , rs.timeout_error_count --Total number of time-out errors since server startup. NULL for the small-query resource semaphore. - , rs.forced_grant_count --Total number of forced minimum-memory grants since server startup. NULL for the small-query resource semaphore. - FROM sys.dm_exec_requests r - JOIN sys.dm_exec_connections c ON r.connection_id = c.connection_id - AND c.net_transport <> 'session' - JOIN sys.dm_exec_sessions s ON c.session_id = s.session_id - JOIN sys.databases d ON r.database_id = d.database_id - JOIN sys.dm_exec_query_memory_grants mg ON s.session_id = mg.session_id - INNER JOIN sys.dm_exec_query_resource_semaphores rs ON mg.resource_semaphore_id = rs.resource_semaphore_id AND mg.pool_id = rs.pool_id - OUTER APPLY sys.dm_exec_sql_text (r.sql_handle ) AS q - OPTION (MAXDOP 1, LOOP JOIN, FORCE ORDER) + + /* Resultset #9: dm_exec_query_memory_grants + ** Query sometimes causes follow message: + ** Warning: The join order has been enforced because a local join hint is used.*/ + PRINT '' + RAISERROR ('-- dm_exec_query_memory_grants --', 0, 1) WITH NOWAIT; + SELECT /*qry9*/ CONVERT (varchar(30), @runtime, 126) AS 'runtime', session_id, request_id, scheduler_id, dop, request_time, grant_time, requested_memory_kb, + granted_memory_kb, required_memory_kb, used_memory_kb, max_used_memory_kb, query_cost, timeout_sec, resource_semaphore_id, queue_id, wait_order, is_next_candidate, + wait_time_ms, group_id, pool_id, is_small ideal_memory_kb, plan_handle, [sql_handle], + convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1)) as [database_id], + case when substring(plan_handle,1,1) = 0x05 then convert(int, substring(plan_handle,8,1) + substring(plan_handle,7,1) + substring(plan_handle,6,1) + substring(plan_handle,5,1)) + else NULL end as [object_id], + case when substring(plan_handle,1,1) = 0x05 then + '[' + DB_NAME(convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1))) + + '].[' + object_schema_name(convert(int, substring(plan_handle,8,1) + substring(plan_handle,7,1) + substring(plan_handle,6,1) + substring(plan_handle,5,1)),convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1))) + + '].['+ object_name(convert(int, substring(plan_handle,8,1) + substring(plan_handle,7,1) + substring(plan_handle,6,1) + substring(plan_handle,5,1)),convert(smallint, substring(plan_handle,4,1) + substring(plan_handle,3,1))) + ']' + else 'ad-hoc query, see notableactivequeries for text' end as 'full_object_name' + FROM sys.dm_exec_query_memory_grants + OPTION (MAX_GRANT_PERCENT = 3, MAXDOP 1) RAISERROR ('', 0, 1) WITH NOWAIT END TRY @@ -1274,21 +1279,21 @@ AS EXEC @#sp_perf_stats_ver 'sqllogscout', @runtime = @runtime, @prevruntime = @prevruntime, @IsLite=@IsLite -- Collect #sp_perf_stats_infrequent approximately every minute - if DATEDIFF(SECOND, @previnfreqruntime,GETDATE()) > 59 + IF DATEDIFF(SECOND, @previnfreqruntime,GETDATE()) > 59 BEGIN EXEC @#sp_perf_stats_infrequent_ver @runtime = @runtime, @prevruntime = @previnfreqruntime, @lastmsticks = @lastmsticks output, @firstrun = @firstrun, @IsLite=@IsLite SET @previnfreqruntime = @runtime END -- Collect #sp_perf_stats_reallyinfrequent approximately every 5 minutes - if DATEDIFF(SECOND, @prevreallyinfreqruntime,GETDATE()) > 299 + IF DATEDIFF(SECOND, @prevreallyinfreqruntime,GETDATE()) > 299 BEGIN EXEC @#sp_perf_stats_reallyinfrequent_ver @runtime = @runtime, @firstrun = @firstrun, @IsLite=@IsLite SET @firstrun = 0 SET @prevreallyinfreqruntime = @runtime END - SET @prevruntime = @runtime - WAITFOR DELAY '0:0:10' + SET @prevruntime = @runtime + WAITFOR DELAY '0:0:10' END TRY BEGIN CATCH PRINT 'Exception occured in: `"' + OBJECT_NAME(@@PROCID) + '`"' diff --git a/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats_Snapshot.psm1 b/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats_Snapshot.psm1 index 1581d87..db3716b 100644 --- a/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats_Snapshot.psm1 +++ b/SQL LogScout/Bin/SQLScript_SQL_Server_PerfStats_Snapshot.psm1 @@ -122,7 +122,7 @@ begin PRINT '-- Missing Indexes --' SELECT CONVERT (varchar(30), @runtime, 126) AS runtime, mig.index_group_handle, mid.index_handle, - CONVERT (decimal (28,1), migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) AS improvement_measure, + CONVERT (bigint, migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) AS improvement_measure, 'CREATE INDEX missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) + ' ON ' + mid.statement + ' (' + ISNULL (mid.equality_columns,'') @@ -133,8 +133,8 @@ begin FROM sys.dm_db_missing_index_groups mig INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle - WHERE CONVERT (decimal (28,1), migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) > 10 - ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC + WHERE CONVERT (bigint, migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans)) > 10 + ORDER BY improvement_measure DESC OPTION (MAX_GRANT_PERCENT = 3, MAXDOP 1) PRINT '' @@ -821,7 +821,7 @@ BEGIN SELECT object_id, OBJECT_NAME(object_id) [object_name], index_id, name [index_name], sql_text,last_max_dop_used, partition_number, state, state_desc, start_time, last_pause_time, total_execution_time, percent_complete, page_count - FROM sys.index_resumable_operations + FROM sys.index_resumable_operations WITH (NOLOCK) PRINT '' RAISERROR ('', 0, 1) WITH NOWAIT diff --git a/SQL LogScout/Bin/SQLScript_SSB_DbMail_Diag.psm1 b/SQL LogScout/Bin/SQLScript_SSB_DbMail_Diag.psm1 index 1606a79..a62468a 100644 --- a/SQL LogScout/Bin/SQLScript_SSB_DbMail_Diag.psm1 +++ b/SQL LogScout/Bin/SQLScript_SSB_DbMail_Diag.psm1 @@ -264,7 +264,7 @@ PRINT '-- sysmail_event_log_sysmail_faileditems --' SELECT er.log_id, er.event_type, er.log_date, - er.description, + er.description, er.process_id, er.mailitem_id, er.account_id, @@ -273,8 +273,7 @@ SELECT er.log_id, fi.send_request_user, fi.send_request_date, fi.recipients, - fi.subject, - fi.body + fi.subject FROM msdb.dbo.sysmail_event_log er LEFT JOIN msdb.dbo.sysmail_faileditems fi ON er.mailitem_id = fi.mailitem_id @@ -289,7 +288,6 @@ SELECT mailitem_id, blind_copy_recipients, subject, from_address, - body, body_format, importance, sensitivity, @@ -348,7 +346,7 @@ SELECT log_id , event_type , log_date , - description , + description, process_id , mailitem_id , account_id , diff --git a/SQL LogScout/Bin/SQLScript_TempDB_and_Tran_Analysis.psm1 b/SQL LogScout/Bin/SQLScript_TempDB_and_Tran_Analysis.psm1 index 7ac0328..3dfb4c1 100644 --- a/SQL LogScout/Bin/SQLScript_TempDB_and_Tran_Analysis.psm1 +++ b/SQL LogScout/Bin/SQLScript_TempDB_and_Tran_Analysis.psm1 @@ -17,520 +17,528 @@ SELECT @sql_major_version = (CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion' WHILE 1=1 BEGIN - IF OBJECT_ID('tempdb..#dbtable') IS NOT NULL - DROP TABLE #dbtable; + BEGIN TRY + IF OBJECT_ID('tempdb..#dbtable') IS NOT NULL + DROP TABLE #dbtable; + + IF OBJECT_ID('tempdb..#db_inmemory') IS NOT NULL + DROP TABLE #db_inmemory; - IF OBJECT_ID('tempdb..#db_inmemory') IS NOT NULL - DROP TABLE #db_inmemory; - - IF OBJECT_ID('tempdb..#tmp_dm_db_xtp_transactions ') IS NOT NULL - DROP TABLE #tmp_dm_db_xtp_transactions; + IF OBJECT_ID('tempdb..#tmp_dm_db_xtp_transactions ') IS NOT NULL + DROP TABLE #tmp_dm_db_xtp_transactions; + + PRINT '-- Current time' + SELECT getdate() + PRINT '' - PRINT '-- Current time' - SELECT getdate() - PRINT '' - - DECLARE @runtime datetime - SET @runtime = CONVERT (varchar(30), GETDATE(), 121) - - PRINT '-- sys.dm_db_file_space_usage --' - SELECT @runtime AS runtime, - DB_NAME() AS dbname, - SUM (user_object_reserved_page_count)*8 AS usr_obj_kb, - SUM (internal_object_reserved_page_count)*8 AS internal_obj_kb, - SUM (version_store_reserved_page_count)*8 AS version_store_kb, - SUM (unallocated_extent_page_count)*8 AS freespace_kb, - SUM (mixed_extent_page_count)*8 AS mixedextent_kb - FROM sys.dm_db_file_space_usage - OPTION (max_grant_percent = 3, MAXDOP 2) - PRINT '' - - PRINT '-- tempdb_space_usage_by_file --' - SELECT @runtime AS runtime, - SUBSTRING(name, 0, 32) AS filename, - physical_name, - CONVERT(decimal(10,3),size/128.0) AS currentsize_mb, - CONVERT(decimal(10,3),size/128.0 - FILEPROPERTY(name, 'SpaceUsed')/128.0) AS freespace_mb - FROM tempdb.sys.database_files f - PRINT '' - - - PRINT '-- transaction_perfmon_counters --' + DECLARE @runtime datetime + SET @runtime = CONVERT (varchar(30), GETDATE(), 121) - SELECT @runtime AS runtime, - CONVERT(VARCHAR(16), DB_NAME ()) AS dbname, - SUBSTRING(object_name,0,28) as object_name, - SUBSTRING(counter_name,0,42) as counter_name, - cntr_value AS counter_value - FROM sys.dm_os_performance_counters - WHERE Object_Name LIKE '%:Transactions%' - RAISERROR ('', 0, 1) WITH NOWAIT - PRINT '' - - PRINT '-- sys.dm_db_session_space_usage --' - SELECT TOP 10 @runtime AS runtime, - su.session_id, - su.database_id, - su.internal_objects_alloc_page_count, - su.internal_objects_dealloc_page_count, - su.user_objects_alloc_page_count, - su.user_objects_dealloc_page_count, - su.user_objects_deferred_dealloc_page_count, - s.open_transaction_count, - s.last_request_end_time, - SUBSTRING(s.host_name, 0, 48) host_name, - SUBSTRING(s.program_name,0,48) program_name, - LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, 0,256), CHAR(10), ' '), CHAR(13), ' '))) AS most_recent_query - FROM sys.dm_db_session_space_usage su - LEFT OUTER JOIN sys.dm_exec_sessions s - ON su.session_id = s.session_id - LEFT OUTER JOIN sys.dm_exec_connections c - on su.session_id = c.session_id - AND c.net_transport <> 'session' - OUTER APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) as t - WHERE (internal_objects_alloc_page_count + internal_objects_dealloc_page_count + user_objects_alloc_page_count + user_objects_dealloc_page_count + su.user_objects_deferred_dealloc_page_count) !=0 + PRINT '-- sys.dm_db_file_space_usage --' + SELECT @runtime AS runtime, + DB_NAME() AS dbname, + SUM (user_object_reserved_page_count)*8 AS usr_obj_kb, + SUM (internal_object_reserved_page_count)*8 AS internal_obj_kb, + SUM (version_store_reserved_page_count)*8 AS version_store_kb, + SUM (unallocated_extent_page_count)*8 AS freespace_kb, + SUM (mixed_extent_page_count)*8 AS mixedextent_kb + FROM sys.dm_db_file_space_usage + OPTION (max_grant_percent = 3, MAXDOP 2) + PRINT '' + + PRINT '-- tempdb_space_usage_by_file --' + SELECT @runtime AS runtime, + SUBSTRING(name, 0, 32) AS filename, + physical_name, + CONVERT(decimal(10,3),size/128.0) AS currentsize_mb, + CONVERT(decimal(10,3),size/128.0 - FILEPROPERTY(name, 'SpaceUsed')/128.0) AS freespace_mb + FROM tempdb.sys.database_files f + PRINT '' + + + PRINT '-- transaction_perfmon_counters --' + + SELECT @runtime AS runtime, + CONVERT(VARCHAR(16), DB_NAME ()) AS dbname, + SUBSTRING(object_name,0,28) as object_name, + SUBSTRING(counter_name,0,42) as counter_name, + cntr_value AS counter_value + FROM sys.dm_os_performance_counters + WHERE Object_Name LIKE '%:Transactions%' + RAISERROR ('', 0, 1) WITH NOWAIT + PRINT '' + + PRINT '-- sys.dm_db_session_space_usage --' + SELECT TOP 10 @runtime AS runtime, + su.session_id, + su.database_id, + su.internal_objects_alloc_page_count, + su.internal_objects_dealloc_page_count, + su.user_objects_alloc_page_count, + su.user_objects_dealloc_page_count, + su.user_objects_deferred_dealloc_page_count, + s.open_transaction_count, + s.last_request_end_time, + SUBSTRING(s.host_name, 0, 48) host_name, + SUBSTRING(s.program_name,0,48) program_name, + LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, 0,256), CHAR(10), ' '), CHAR(13), ' '))) AS most_recent_query + FROM sys.dm_db_session_space_usage su + LEFT OUTER JOIN sys.dm_exec_sessions s + ON su.session_id = s.session_id + LEFT OUTER JOIN sys.dm_exec_connections c + on su.session_id = c.session_id + AND c.net_transport <> 'session' + OUTER APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) as t + WHERE (internal_objects_alloc_page_count + internal_objects_dealloc_page_count + user_objects_alloc_page_count + user_objects_dealloc_page_count + su.user_objects_deferred_dealloc_page_count) !=0 + ORDER BY (user_objects_alloc_page_count + internal_objects_alloc_page_count) DESC + OPTION (max_grant_percent = 3, MAXDOP 2) + PRINT '' + + + PRINT '-- sys.dm_db_task_space_usage --' + SELECT TOP 10 @runtime AS runtime, + tsu.session_id, + tsu.database_id, + tsu.internal_objects_alloc_page_count, + tsu.internal_objects_dealloc_page_count, + tsu.user_objects_alloc_page_count, + tsu.user_objects_dealloc_page_count, + tsu.exec_context_id, + r.status, + r.wait_type, + r.wait_time, + r.cpu_time, + LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, (r.statement_start_offset/2)+1, + ((CASE r.statement_end_offset + WHEN -1 THEN DATALENGTH(t.text) + ELSE r.statement_end_offset + END - r.statement_start_offset)/2) + 1), CHAR(10), ' '), CHAR(13), ' '))) AS statement_text, + LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, 0,256), CHAR(10), ' '), CHAR(13), ' '))) AS batch_text + FROM sys.dm_db_task_space_usage tsu + LEFT JOIN sys.dm_exec_requests r + ON tsu.session_id = r.session_id + CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t + WHERE (internal_objects_alloc_page_count + internal_objects_dealloc_page_count + user_objects_alloc_page_count + user_objects_dealloc_page_count) !=0 ORDER BY (user_objects_alloc_page_count + internal_objects_alloc_page_count) DESC OPTION (max_grant_percent = 3, MAXDOP 2) PRINT '' - - - PRINT '-- sys.dm_db_task_space_usage --' - SELECT TOP 10 @runtime AS runtime, - tsu.session_id, - tsu.database_id, - tsu.internal_objects_alloc_page_count, - tsu.internal_objects_dealloc_page_count, - tsu.user_objects_alloc_page_count, - tsu.user_objects_dealloc_page_count, - tsu.exec_context_id, - r.status, - r.wait_type, - r.wait_time, - r.cpu_time, - LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, (r.statement_start_offset/2)+1, - ((CASE r.statement_end_offset - WHEN -1 THEN DATALENGTH(t.text) - ELSE r.statement_end_offset - END - r.statement_start_offset)/2) + 1), CHAR(10), ' '), CHAR(13), ' '))) AS statement_text, - LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, 0,256), CHAR(10), ' '), CHAR(13), ' '))) AS batch_text - FROM sys.dm_db_task_space_usage tsu - LEFT JOIN sys.dm_exec_requests r - ON tsu.session_id = r.session_id - CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t - WHERE (internal_objects_alloc_page_count + internal_objects_dealloc_page_count + user_objects_alloc_page_count + user_objects_dealloc_page_count) !=0 - ORDER BY (user_objects_alloc_page_count + internal_objects_alloc_page_count) DESC - OPTION (max_grant_percent = 3, MAXDOP 2) - PRINT '' - - PRINT '-- version store transactions --' - SELECT @runtime AS runtime, - ast.transaction_id, - ast.transaction_sequence_num, - ast.commit_sequence_num, - ast.elapsed_time_seconds, - ast.average_version_chain_traversed, - ast.max_version_chain_traversed, - ast.first_snapshot_sequence_num, - ast.is_snapshot, - ast.session_id, - r.blocking_session_id, - r.status, - r.wait_type, - r.wait_time, - r.cpu_time, - r.total_elapsed_time, - r.granted_query_memory, - r.open_transaction_count, - r.transaction_isolation_level, - LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, (r.statement_start_offset/2)+1, - ((CASE r.statement_end_offset - WHEN -1 THEN DATALENGTH(t.text) - ELSE r.statement_end_offset - END - r.statement_start_offset)/2) + 1), CHAR(10), ' '), CHAR(13), ' '))) AS statement_text - FROM sys.dm_tran_active_snapshot_database_transactions ast - LEFT JOIN sys.dm_exec_requests r - ON ast.session_id = r.session_id - CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) as t - RAISERROR ('', 0, 1) WITH NOWAIT - PRINT '' - - PRINT '-- open transactions --' - SELECT @runtime AS runtime, - s_tdt.transaction_id, - s_tdt.database_transaction_state, - s_tdt.database_transaction_type, - s_tdt.database_transaction_log_record_count, - s_tdt.database_transaction_begin_lsn, - s_tdt.database_transaction_last_lsn, - s_tdt.database_transaction_begin_time, - s_tdt.database_transaction_log_bytes_used, - s_tdt.database_transaction_log_bytes_reserved, - s_tdt.database_transaction_log_bytes_reserved_system, - s_tdt.database_transaction_log_bytes_used_system, - s_tst.session_id, - s_tst.is_local, - s_es.login_time, - s_es.last_request_end_time, - CONVERT(VARCHAR(36), DB_NAME (s_tdt.database_id)) AS dbname, - con.most_recent_session_id, - s_es.open_transaction_count, - s_es.status, - SUBSTRING(s_es.host_name, 0, 48) host_name, - SUBSTRING(s_es.program_name,0,48) program_name, - s_es.is_user_process, - s_es.host_process_id, - SUBSTRING(s_es.login_name, 0,48) login_name, - con.client_net_address, - con.net_transport - FROM sys.dm_tran_database_transactions s_tdt - JOIN sys.dm_tran_session_transactions s_tst - ON s_tst.transaction_id = s_tdt.transaction_id - JOIN sys.dm_exec_sessions AS s_es - ON s_es.session_id = s_tst.session_id - LEFT OUTER JOIN sys.dm_exec_requests s_er - ON s_er.session_id = s_tst.session_id - LEFT OUTER JOIN sys.dm_exec_connections con - ON con.session_id = s_tst.session_id - AND con.net_transport <> 'session' + + PRINT '-- version store transactions --' + SELECT @runtime AS runtime, + ast.transaction_id, + ast.transaction_sequence_num, + ast.commit_sequence_num, + ast.elapsed_time_seconds, + ast.average_version_chain_traversed, + ast.max_version_chain_traversed, + ast.first_snapshot_sequence_num, + ast.is_snapshot, + ast.session_id, + r.blocking_session_id, + r.status, + r.wait_type, + r.wait_time, + r.cpu_time, + r.total_elapsed_time, + r.granted_query_memory, + r.open_transaction_count, + r.transaction_isolation_level, + LTRIM(RTRIM(REPLACE(REPLACE(SUBSTRING(t.text, (r.statement_start_offset/2)+1, + ((CASE r.statement_end_offset + WHEN -1 THEN DATALENGTH(t.text) + ELSE r.statement_end_offset + END - r.statement_start_offset)/2) + 1), CHAR(10), ' '), CHAR(13), ' '))) AS statement_text + FROM sys.dm_tran_active_snapshot_database_transactions ast + LEFT JOIN sys.dm_exec_requests r + ON ast.session_id = r.session_id + OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) as t + RAISERROR ('', 0, 1) WITH NOWAIT + PRINT '' + + PRINT '-- open transactions --' + SELECT @runtime AS runtime, + s_tdt.transaction_id, + s_tdt.database_transaction_state, + s_tdt.database_transaction_type, + s_tdt.database_transaction_log_record_count, + s_tdt.database_transaction_begin_lsn, + s_tdt.database_transaction_last_lsn, + ISNULL(s_tdt.database_transaction_begin_time,s_tat.transaction_begin_time) as transaction_begin_time, + DATEDIFF(second, ISNULL(s_tdt.database_transaction_begin_time,s_tat.transaction_begin_time), getdate()) as elapsed_time_seconds, + s_tdt.database_transaction_log_bytes_used, + s_tdt.database_transaction_log_bytes_reserved, + s_tdt.database_transaction_log_bytes_reserved_system, + s_tdt.database_transaction_log_bytes_used_system, + s_tst.session_id, + s_tst.is_local, + s_es.login_time, + s_es.last_request_end_time, + CONVERT(VARCHAR(36), DB_NAME (s_tdt.database_id)) AS dbname, + con.most_recent_session_id, + s_es.open_transaction_count, + s_es.status, + SUBSTRING(s_es.host_name, 0, 48) host_name, + SUBSTRING(s_es.program_name,0,48) program_name, + s_es.is_user_process, + s_es.host_process_id, + SUBSTRING(s_es.login_name, 0,48) login_name, + con.client_net_address, + con.net_transport + FROM sys.dm_tran_database_transactions s_tdt + INNER JOIN sys.dm_tran_session_transactions s_tst + ON s_tst.transaction_id = s_tdt.transaction_id + INNER JOIN sys.dm_tran_active_transactions s_tat + ON (s_tdt.transaction_id = s_tat.transaction_id) + INNER JOIN sys.dm_exec_sessions AS s_es + ON s_es.session_id = s_tst.session_id + LEFT JOIN sys.dm_exec_requests s_er + ON s_er.session_id = s_tst.session_id + LEFT JOIN sys.dm_exec_connections con + ON con.session_id = s_tst.session_id + AND con.net_transport <> 'session' OUTER APPLY sys.dm_exec_sql_text(con.most_recent_sql_handle) T - ORDER BY database_transaction_begin_time ASC - OPTION (max_grant_percent = 3, MAXDOP 2) - - RAISERROR ('', 0, 1) WITH NOWAIT - PRINT '' + ORDER BY database_transaction_begin_time ASC + OPTION (max_grant_percent = 3, MAXDOP 2) - PRINT '-- tempdb usage by objects --' - SELECT TOP 10 - @runtime AS runtime, - CONVERT(VARCHAR(16), DB_NAME ()) AS dbname, - DB_ID() AS database_id, - _Objects.schema_id AS schema_id, - Schema_Name(_Objects.schema_id) AS schema_name, - _Objects.object_id AS object_id, - RTrim(_Objects.name) AS table_name, - (~(Cast(_Partitions.index_id AS Bit))) AS is_heap, - SUM(_Partitions.used_page_count) * 8192/1024 used_pages_kb, - SUM(_Partitions.reserved_page_count) * 8192/1024 reserved_pages_kb - FROM sys.objects AS _Objects - INNER JOIN sys.dm_db_partition_stats AS _Partitions - ON (_Objects.object_id = _Partitions.object_id) - WHERE (_Partitions.index_id IN (0, 1)) - GROUP BY _Objects.schema_id, - _Objects.object_id, - _Objects.name, - _Partitions.index_id - ORDER BY used_pages_kb DESC - OPTION (max_grant_percent = 3, MAXDOP 2) - PRINT '' - - - PRINT '-- waits-in-tempdb --' - SELECT @runtime AS runtime, - session_id, - start_time, - status, - command, - CONVERT(VARCHAR(36), DB_NAME (database_id)) AS dbname, - blocking_session_id, - wait_type, - wait_time, - last_wait_type, - wait_resource, - open_transaction_count, - cpu_time, - total_elapsed_time, - logical_reads - FROM sys.dm_exec_requests - WHERE wait_resource like '% 2:%' - OPTION (max_grant_percent = 3, MAXDOP 2) - PRINT '' - - IF @sql_major_version >= 15 - BEGIN - PRINT '-- dm_tran_aborted_transactions --' - SELECT @runtime AS runtime, - transaction_id, - database_id, - begin_xact_lsn, - end_xact_lsn, - begin_time, - nest_aborted - FROM sys.dm_tran_aborted_transactions - END - - RAISERROR ('', 0, 1) WITH NOWAIT - PRINT '' + RAISERROR ('', 0, 1) WITH NOWAIT + PRINT '' - PRINT '-- sys.dm_tran_active_transactions --' - SELECT [transaction_id], - [name], - [transaction_begin_time], - [transaction_type], - [transaction_uow], - [transaction_state], - [transaction_status], - [transaction_status2], - [dtc_state], - [dtc_status], - [dtc_isolation_level], - [filestream_transaction_id] - FROM sys.dm_tran_active_transactions - RAISERROR ('', 0, 1) WITH NOWAIT - PRINT '' - - --in-memory related - - IF (@sql_major_version > 11) - BEGIN - - DECLARE @database_id INT - DECLARE @dbname SYSNAME - DECLARE @count INT - DECLARE @maxcount INT - DECLARE @sql NVARCHAR(MAX) - - CREATE TABLE #dbtable ( - id INT IDENTITY (1,1) PRIMARY KEY, - database_id INT, - dbname SYSNAME - ) - - --database level in-memory dmvs - - SELECT IDENTITY(INT,1,1) AS id, - @database_id as database_id , - @dbname as dbname - INTO #db_inmemory - FROM sys.databases - WHERE 1=0 + PRINT '-- tempdb usage by objects --' + SELECT TOP 10 + @runtime AS runtime, + CONVERT(VARCHAR(16), DB_NAME ()) AS dbname, + DB_ID() AS database_id, + _Objects.schema_id AS schema_id, + Schema_Name(_Objects.schema_id) AS schema_name, + _Objects.object_id AS object_id, + RTrim(_Objects.name) AS table_name, + (~(Cast(_Partitions.index_id AS Bit))) AS is_heap, + SUM(_Partitions.used_page_count) * 8192/1024 used_pages_kb, + SUM(_Partitions.reserved_page_count) * 8192/1024 reserved_pages_kb + FROM sys.objects AS _Objects WITH (NOLOCK) + INNER JOIN sys.dm_db_partition_stats AS _Partitions WITH (NOLOCK) + ON (_Objects.object_id = _Partitions.object_id) + WHERE (_Partitions.index_id IN (0, 1)) + GROUP BY _Objects.schema_id, + _Objects.object_id, + _Objects.name, + _Partitions.index_id + ORDER BY used_pages_kb DESC + OPTION (max_grant_percent = 3, MAXDOP 2) + PRINT '' + + + PRINT '-- waits-in-tempdb --' + SELECT @runtime AS runtime, + session_id, + start_time, + status, + command, + CONVERT(VARCHAR(36), DB_NAME (database_id)) AS dbname, + blocking_session_id, + wait_type, + wait_time, + last_wait_type, + wait_resource, + open_transaction_count, + cpu_time, + total_elapsed_time, + logical_reads + FROM sys.dm_exec_requests + WHERE wait_resource like '% 2:%' + OPTION (max_grant_percent = 3, MAXDOP 2) + PRINT '' + + IF @sql_major_version >= 15 + BEGIN + PRINT '-- dm_tran_aborted_transactions --' + SELECT @runtime AS runtime, + transaction_id, + database_id, + begin_xact_lsn, + end_xact_lsn, + begin_time, + nest_aborted + FROM sys.dm_tran_aborted_transactions + END + + RAISERROR ('', 0, 1) WITH NOWAIT + PRINT '' - INSERT INTO #dbtable - SELECT database_id, name FROM sys.databases WHERE state_desc='ONLINE' - - SET @count = 1 - SET @maxcount = (SELECT MAX(id) FROM #dbtable) - - WHILE (@count<=@maxcount) + PRINT '-- sys.dm_tran_active_transactions --' + SELECT [transaction_id], + [name], + [transaction_begin_time], + [transaction_type], + [transaction_uow], + [transaction_state], + [transaction_status], + [transaction_status2], + [dtc_state], + [dtc_status], + [dtc_isolation_level], + [filestream_transaction_id] + FROM sys.dm_tran_active_transactions + RAISERROR ('', 0, 1) WITH NOWAIT + PRINT '' + + --in-memory related + + IF (@sql_major_version > 11) BEGIN - SELECT @database_id = database_id, - @dbname = dbname - FROM #dbtable - WHERE id = @count - - SET @sql = N'USE [' + @dbname + ']; - IF EXISTS(SELECT type_desc FROM sys.data_spaces WHERE type_desc = ''MEMORY_OPTIMIZED_DATA_FILEGROUP'') - BEGIN - INSERT INTO #db_inmemory VALUES (' + CONVERT(NVARCHAR(50),@database_id) + ',''' + @dbname +'''); - END' - --print @sql - EXEC (@sql) - SET @count = @count + 1 - - END - - PRINT '-- sys.dm_db_xtp_transactions --' + + DECLARE @database_id INT + DECLARE @dbname SYSNAME + DECLARE @count INT + DECLARE @maxcount INT + DECLARE @sql NVARCHAR(MAX) - CREATE TABLE #tmp_dm_db_xtp_transactions ( - [dbname] SYSNAME NULL, - [node_id] SMALLINT NULL, - [xtp_transaction_id] BIGINT NULL, - [transaction_id] BIGINT NULL, - [session_id] SMALLINT NULL, - [begin_tsn] BIGINT NULL, - [end_tsn] BIGINT NULL, - [state] INT NULL, - [state_desc] NVARCHAR(16) NULL, - [result] INT NULL, - [result_desc] NVARCHAR(24) NULL, - [xtp_parent_transaction_node_id] SMALLINT NULL, - [xtp_parent_transaction_id] BIGINT NULL, - [last_error]INT NULL, - [is_speculative] BIT NULL, - [is_prepared] BIT NULL, - [is_delayed_durability] BIT NULL , - [memory_address] VARBINARY(8) NULL, - [database_address] VARBINARY(8) NULL, - [thread_id] INT NULL, - [read_set_row_count] INT NULL, - [write_set_row_count] INT NULL, - [scan_set_count] INT NULL, - [savepoint_garbage_count] INT NULL, - [log_bytes_required]BIGINT NULL, - [count_of_allocations] INT NULL, - [allocated_bytes] INT NULL, - [reserved_bytes] INT NULL, - [commit_dependency_count] INT NULL, - [commit_dependency_total_attempt_count] INT NULL, - [scan_area] INT NULL, - [scan_area_desc] NVARCHAR(16) NULL, - [scan_location] INT NULL, - [dependent_1_address] VARBINARY(8) NULL, - [dependent_2_address] VARBINARY(8) NULL, - [dependent_3_address] VARBINARY(8) NULL, - [dependent_4_address] VARBINARY(8) NULL, - [dependent_5_address] VARBINARY(8) NULL, - [dependent_6_address] VARBINARY(8) NULL, - [dependent_7_address] VARBINARY(8) NULL, - [dependent_8_address] VARBINARY(8) NULL - ) + CREATE TABLE #dbtable ( + id INT IDENTITY (1,1) PRIMARY KEY, + database_id INT, + dbname SYSNAME + ) - SET @count = 1 - SET @maxcount = (SELECT MAX(id) FROM #db_inmemory) + --database level in-memory dmvs - WHILE (@count<=@maxcount) - BEGIN + SELECT IDENTITY(INT,1,1) AS id, + @database_id as database_id , + @dbname as dbname + INTO #db_inmemory + FROM sys.databases + WHERE 1=0 + + INSERT INTO #dbtable + SELECT database_id, name FROM sys.databases WHERE state_desc='ONLINE' - SELECT @database_id = database_id, - @dbname = dbname - FROM #db_inmemory - WHERE id = @count - - IF (@sql_major_version >=13 ) + SET @count = 1 + SET @maxcount = (SELECT MAX(id) FROM #dbtable) + + WHILE (@count<=@maxcount) BEGIN + SELECT @database_id = database_id, + @dbname = dbname + FROM #dbtable + WHERE id = @count + SET @sql = N'USE [' + @dbname + ']; - INSERT INTO #tmp_dm_db_xtp_transactions - SELECT '''+@dbname+''', - [node_id], - [xtp_transaction_id], - [transaction_id], - [session_id], - [begin_tsn], - [end_tsn], - [state], - [state_desc], - [result], - [result_desc], - [xtp_parent_transaction_node_id], - [xtp_parent_transaction_id], - [last_error], - [is_speculative], - [is_prepared], - [is_delayed_durability], - [memory_address], - [database_address], - [thread_id], - [read_set_row_count], - [write_set_row_count], - [scan_set_count], - [savepoint_garbage_count], - [log_bytes_required], - [count_of_allocations], - [allocated_bytes], - [reserved_bytes], - [commit_dependency_count], - [commit_dependency_total_attempt_count], - [scan_area], - [scan_area_desc], - [scan_location], - [dependent_1_address], - [dependent_2_address], - [dependent_3_address], - [dependent_4_address], - [dependent_5_address], - [dependent_6_address], - [dependent_7_address], - [dependent_8_address] - FROM sys.dm_db_xtp_transactions;' + IF EXISTS(SELECT type_desc FROM sys.data_spaces WHERE type_desc = ''MEMORY_OPTIMIZED_DATA_FILEGROUP'') + BEGIN + INSERT INTO #db_inmemory VALUES (' + CONVERT(NVARCHAR(50),@database_id) + ',''' + @dbname +'''); + END' + --print @sql + EXEC (@sql) + SET @count = @count + 1 + END - ELSE + + PRINT '-- sys.dm_db_xtp_transactions --' + + CREATE TABLE #tmp_dm_db_xtp_transactions ( + [dbname] SYSNAME NULL, + [node_id] SMALLINT NULL, + [xtp_transaction_id] BIGINT NULL, + [transaction_id] BIGINT NULL, + [session_id] SMALLINT NULL, + [begin_tsn] BIGINT NULL, + [end_tsn] BIGINT NULL, + [state] INT NULL, + [state_desc] NVARCHAR(16) NULL, + [result] INT NULL, + [result_desc] NVARCHAR(24) NULL, + [xtp_parent_transaction_node_id] SMALLINT NULL, + [xtp_parent_transaction_id] BIGINT NULL, + [last_error]INT NULL, + [is_speculative] BIT NULL, + [is_prepared] BIT NULL, + [is_delayed_durability] BIT NULL , + [memory_address] VARBINARY(8) NULL, + [database_address] VARBINARY(8) NULL, + [thread_id] INT NULL, + [read_set_row_count] INT NULL, + [write_set_row_count] INT NULL, + [scan_set_count] INT NULL, + [savepoint_garbage_count] INT NULL, + [log_bytes_required]BIGINT NULL, + [count_of_allocations] INT NULL, + [allocated_bytes] INT NULL, + [reserved_bytes] INT NULL, + [commit_dependency_count] INT NULL, + [commit_dependency_total_attempt_count] INT NULL, + [scan_area] INT NULL, + [scan_area_desc] NVARCHAR(16) NULL, + [scan_location] INT NULL, + [dependent_1_address] VARBINARY(8) NULL, + [dependent_2_address] VARBINARY(8) NULL, + [dependent_3_address] VARBINARY(8) NULL, + [dependent_4_address] VARBINARY(8) NULL, + [dependent_5_address] VARBINARY(8) NULL, + [dependent_6_address] VARBINARY(8) NULL, + [dependent_7_address] VARBINARY(8) NULL, + [dependent_8_address] VARBINARY(8) NULL + ) + + SET @count = 1 + SET @maxcount = (SELECT MAX(id) FROM #db_inmemory) + + WHILE (@count<=@maxcount) BEGIN - SET @sql = N'USE [' + @dbname + ']; - INSERT INTO #tmp_dm_db_xtp_transactions - SELECT '''+@dbname+''', - NULL, --[node_id], - [xtp_transaction_id], - [transaction_id], - [session_id], - [begin_tsn], - [end_tsn], - [state], - [state_desc], - [result], - [result_desc], - NULL, --[xtp_parent_transaction_node_id], - NULL, --[xtp_parent_transaction_id], - [last_error], - [is_speculative], - [is_prepared], - [is_delayed_durability], - [memory_address], - [database_address], - [thread_id], - [read_set_row_count], - [write_set_row_count], - [scan_set_count], - [savepoint_garbage_count], - [log_bytes_required], - [count_of_allocations], - [allocated_bytes], - [reserved_bytes], - [commit_dependency_count], - [commit_dependency_total_attempt_count], - [scan_area], - [scan_area_desc], - [scan_location], - [dependent_1_address], - [dependent_2_address], - [dependent_3_address], - [dependent_4_address], - [dependent_5_address], - [dependent_6_address], - [dependent_7_address], - [dependent_8_address] - FROM sys.dm_db_xtp_transactions;' + + SELECT @database_id = database_id, + @dbname = dbname + FROM #db_inmemory + WHERE id = @count + + IF (@sql_major_version >=13 ) + BEGIN + SET @sql = N'USE [' + @dbname + ']; + INSERT INTO #tmp_dm_db_xtp_transactions + SELECT '''+@dbname+''', + [node_id], + [xtp_transaction_id], + [transaction_id], + [session_id], + [begin_tsn], + [end_tsn], + [state], + [state_desc], + [result], + [result_desc], + [xtp_parent_transaction_node_id], + [xtp_parent_transaction_id], + [last_error], + [is_speculative], + [is_prepared], + [is_delayed_durability], + [memory_address], + [database_address], + [thread_id], + [read_set_row_count], + [write_set_row_count], + [scan_set_count], + [savepoint_garbage_count], + [log_bytes_required], + [count_of_allocations], + [allocated_bytes], + [reserved_bytes], + [commit_dependency_count], + [commit_dependency_total_attempt_count], + [scan_area], + [scan_area_desc], + [scan_location], + [dependent_1_address], + [dependent_2_address], + [dependent_3_address], + [dependent_4_address], + [dependent_5_address], + [dependent_6_address], + [dependent_7_address], + [dependent_8_address] + FROM sys.dm_db_xtp_transactions;' + END + ELSE + BEGIN + SET @sql = N'USE [' + @dbname + ']; + INSERT INTO #tmp_dm_db_xtp_transactions + SELECT '''+@dbname+''', + NULL, --[node_id], + [xtp_transaction_id], + [transaction_id], + [session_id], + [begin_tsn], + [end_tsn], + [state], + [state_desc], + [result], + [result_desc], + NULL, --[xtp_parent_transaction_node_id], + NULL, --[xtp_parent_transaction_id], + [last_error], + [is_speculative], + [is_prepared], + [is_delayed_durability], + [memory_address], + [database_address], + [thread_id], + [read_set_row_count], + [write_set_row_count], + [scan_set_count], + [savepoint_garbage_count], + [log_bytes_required], + [count_of_allocations], + [allocated_bytes], + [reserved_bytes], + [commit_dependency_count], + [commit_dependency_total_attempt_count], + [scan_area], + [scan_area_desc], + [scan_location], + [dependent_1_address], + [dependent_2_address], + [dependent_3_address], + [dependent_4_address], + [dependent_5_address], + [dependent_6_address], + [dependent_7_address], + [dependent_8_address] + FROM sys.dm_db_xtp_transactions;' + END + + --print @sql + EXEC (@sql) + SET @count = @count + 1 END - - --print @sql + + SELECT CONVERT (varchar(30), @runtime, 121) as runtime, * FROM #tmp_dm_db_xtp_transactions + RAISERROR ('', 0, 1) WITH NOWAIT + + PRINT '-- sys.dm_xtp_transaction_stats --' + SET @sql = N'SELECT [total_count] + ,[read_only_count] + ,[total_aborts] + ,[system_aborts] + ,[validation_failures] + ,[dependencies_taken] + ,[dependencies_failed] + ,[savepoint_create] + ,[savepoint_rollbacks] + ,[savepoint_refreshes] + ,[log_bytes_written] + ,[log_IO_count] + ,[phantom_scans_started] + ,[phantom_scans_retries] + ,[phantom_rows_touched] + ,[phantom_rows_expiring] + ,[phantom_rows_expired] + ,[phantom_rows_expired_removed] + ,[scans_started] + ,[scans_retried] + ,[rows_returned] + ,[rows_touched] + ,[rows_expiring] + ,[rows_expired] + ,[rows_expired_removed] + ,[row_insert_attempts] + ,[row_update_attempts] + ,[row_delete_attempts] + ,[write_conflicts] + ,[unique_constraint_violations]' + IF (@sql_major_version >= 13) + BEGIN + SET @sql = @sql + N',[drop_table_memory_attempts] + ,[drop_table_memory_failures]' + END + + SET @sql = @sql + N'FROM sys.dm_xtp_transaction_stats; + RAISERROR ('''', 0, 1) WITH NOWAIT;' EXEC (@sql) - SET @count = @count + 1 END - - SELECT CONVERT (varchar(30), @runtime, 121) as runtime, * FROM #tmp_dm_db_xtp_transactions - RAISERROR ('', 0, 1) WITH NOWAIT - - PRINT '-- sys.dm_xtp_transaction_stats --' - SET @sql = N'SELECT [total_count] - ,[read_only_count] - ,[total_aborts] - ,[system_aborts] - ,[validation_failures] - ,[dependencies_taken] - ,[dependencies_failed] - ,[savepoint_create] - ,[savepoint_rollbacks] - ,[savepoint_refreshes] - ,[log_bytes_written] - ,[log_IO_count] - ,[phantom_scans_started] - ,[phantom_scans_retries] - ,[phantom_rows_touched] - ,[phantom_rows_expiring] - ,[phantom_rows_expired] - ,[phantom_rows_expired_removed] - ,[scans_started] - ,[scans_retried] - ,[rows_returned] - ,[rows_touched] - ,[rows_expiring] - ,[rows_expired] - ,[rows_expired_removed] - ,[row_insert_attempts] - ,[row_update_attempts] - ,[row_delete_attempts] - ,[write_conflicts] - ,[unique_constraint_violations]' - IF (@sql_major_version >= 13) - BEGIN - SET @sql = @sql + N',[drop_table_memory_attempts] - ,[drop_table_memory_failures]' - END - SET @sql = @sql + N'FROM sys.dm_xtp_transaction_stats; - RAISERROR ('''', 0, 1) WITH NOWAIT;' - EXEC (@sql) - END - - WAITFOR DELAY '00:01:00' + WAITFOR DELAY '00:01:00' + END TRY + BEGIN CATCH + PRINT 'Msg ' + isnull(cast(Error_Number() as nvarchar(50)), '') + ', Level ' + isnull(cast(Error_Severity() as nvarchar(50)),'') + ', State ' + isnull(cast(Error_State() as nvarchar(50)),'') + ', Server ' + @@servername + ', Line ' + isnull(cast(Error_Line() as nvarchar(50)),'') + char(10) + Error_Message() + char(10); + END CATCH END GO " diff --git a/SQL LogScout/Bin/SQLScript_xevent_detailed.psm1 b/SQL LogScout/Bin/SQLScript_xevent_detailed.psm1 index a5e44e0..4071081 100644 --- a/SQL LogScout/Bin/SQLScript_xevent_detailed.psm1 +++ b/SQL LogScout/Bin/SQLScript_xevent_detailed.psm1 @@ -136,7 +136,7 @@ ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sp_stat ) GO IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 -ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sp_statement_starting ( ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) +ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sp_statement_starting ( ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.query_hash_signed, sqlserver.query_plan_hash_signed, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) ) GO @@ -151,7 +151,7 @@ ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sql_sta ) GO IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 -ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sql_statement_starting ( ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) +ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sql_statement_starting ( ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.query_hash_signed, sqlserver.query_plan_hash_signed, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) ) GO @@ -185,7 +185,43 @@ ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.sql_tra WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) ) GO - " + +DECLARE @sql_major_version INT, @sql_major_build INT, @sql NVARCHAR(max), @sql_minor_version INT +SELECT @sql_major_version = (CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(20)), 4) AS INT)), + @sql_major_build = (CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(20)), 2) AS INT)) , + @sql_minor_version = (CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(20)), 3) AS INT)) + +-- ParsName is used to extract MajorVersion , MinorVersion and Build from ProductVersion e.g. 16.0.1105.1 will comeback AS 16000001105 +DECLARE @SQLVERSION BIGINT = PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(20)), 4) + + RIGHT(REPLICATE ('0', 3) + PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(20)), 3), 3) + + RIGHT (replicate ('0', 6) + PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR(20)), 2) , 6) + +IF (@SQLVERSION>=16000001000) +BEGIN + + IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 + ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.memory_grant_feedback_loop_disabled (ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) + WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) + ) + + IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 + ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.memory_grant_feedback_percentile_grant (ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) + WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) + ) + + IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 + ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.memory_grant_feedback_persistence_invalid (ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) + WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) + ) + + IF HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY EVENT SESSION') = 1 + ALTER EVENT SESSION [xevent_SQLLogScout] ON SERVER ADD EVENT sqlserver.memory_grant_feedback_persistence_update (ACTION (package0.event_sequence, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.client_pid, sqlserver.database_id, sqlserver.database_name, sqlserver.is_system, sqlserver.nt_username, sqlserver.query_hash, sqlserver.request_id, sqlserver.server_principal_name, sqlserver.session_server_principal_name, sqlserver.session_id, sqlserver.session_nt_username, sqlserver.sql_text, sqlserver.transaction_id, sqlserver.username) + WHERE (([sqlserver].[client_hostname]<>N'sqllogscout') AND ([sqlserver].[client_hostname]<>N'sqllogscout_stop') AND ([sqlserver].[client_hostname]<>N'sqllogscout_cleanup')) + ) + +END + + " if ($true -eq $returnVariable) { diff --git a/SQL LogScout/Bin/ScheduleSQLLogScoutAsTask.ps1 b/SQL LogScout/Bin/ScheduleSQLLogScoutAsTask.ps1 index 236763f..46e1013 100644 --- a/SQL LogScout/Bin/ScheduleSQLLogScoutAsTask.ps1 +++ b/SQL LogScout/Bin/ScheduleSQLLogScoutAsTask.ps1 @@ -122,7 +122,7 @@ function ScheduledTaskHandleCatchBlock ([string] $function_name, [System.Managem function Initialize-ScheduledTaskLog ( - [string]$LogFilePath = $env:TEMP, + [string]$LogFilePath, [string]$LogFileName = "##SQLLogScout_ScheduledTask" ) { @@ -134,11 +134,15 @@ function Initialize-ScheduledTaskLog #> try { + #Create log file in temp directory using full path. The temp var can come back as 8.3 format and so ensure we have the full path. + $shortEnvTempPath = $env:TEMP + $LogFilePath = (Get-Item $shortEnvTempPath).FullName + #Cache LogFileName withotu date so we can delete old records properly $LogFileNameStringToDelete = $LogFileName #update file with date - $LogFileName = ($LogFileName -replace "##SQLLogScout_ScheduledTask", ("##SQLLogScout_ScheduledTask_" + @(Get-Date -Format "yyyyMMddTHHmmssffff") + ".log")) + $LogFileName = $LogFileName + (Get-Date -Format "yyyyMMddTHHmmssffff") + ".log" $global:ScheduledTaskLog = $LogFilePath + '\' + $LogFileName New-Item -ItemType "file" -Path $global:ScheduledTaskLog -Force | Out-Null $CurrentTime = (Get-Date -Format("yyyy-MM-dd HH:MM:ss.ms")) diff --git a/SQL LogScout/Bin/SqlVersionsTable.psm1 b/SQL LogScout/Bin/SqlVersionsTable.psm1 index cd73ea9..777c579 100644 --- a/SQL LogScout/Bin/SqlVersionsTable.psm1 +++ b/SQL LogScout/Bin/SqlVersionsTable.psm1 @@ -1,5 +1,10 @@ function getSQLVersionsTBL { return @{ + "2022RTMCU18"=16000004185; + "2022RTMCU17"=16000004175; + "2022RTMCU16"=16000004165; + "2022RTMCU15"=16000004145; + "2022RTMCU14"=16000004135; "2022RTMCU13"=16000004125; "2022RTMCU12"=16000004115 "2022RTMCU11"=16000004105; @@ -14,6 +19,11 @@ function getSQLVersionsTBL { "2022RTMCU2"=16000004015; "2022RTMCU1"=16000004003; "2022RTM"=16000001000; + "2019RTMCU32"=15000004430; + "2019RTMCU31"=15000004420; + "2019RTMCU30"=15000004415; + "2019RTMCU29"=15000004405; + "2019RTMCU28"=15000004385; "2019RTMCU27"=15000004375; "2019RTMCU26"=15000004365; "2019RTMCU25"=15000004355; diff --git a/SQL LogScout/Bin/TestingInfrastructure/ConsistentQualityTests.ps1 b/SQL LogScout/Bin/TestingInfrastructure/ConsistentQualityTests.ps1 index c0a6d67..ece9661 100644 --- a/SQL LogScout/Bin/TestingInfrastructure/ConsistentQualityTests.ps1 +++ b/SQL LogScout/Bin/TestingInfrastructure/ConsistentQualityTests.ps1 @@ -47,6 +47,93 @@ function Get-LogScoutRootFolder return $root_folder } +function GetPortFromInstance { + param ( + [string]$server + ) + + Write-Host "Testing GetPortFromInstance function with server: $server" + + try + { + # Extract the instance name from the server string + $instanceName = if ($server -match '\\') { + $server.Split('\')[1] + } else { + 'MSSQLSERVER' # Default instance name + } + + # Get all the registry keys where an instance name is present using "MSSQL" and Property like "(default)" to check TCP/IP Sockets + $InstancesInReg = Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server' -ErrorAction SilentlyContinue | + Where-Object {$_.Name -like '*MSSQL*' -and $_.Property -like "(default)"} | + Select-Object -ExpandProperty PSChildName + + if (-not $InstancesInReg) + { + Write-Host "No SQL Server instances found in the registry." + return $null + } + + Write-Host "Found these instances in the registry: $InstancesInReg" + + # Go through each instance in the registry + foreach ($InstKey in $InstancesInReg) + { + # Extract the instance name from the reg key (e.g. get the part after the . in "MSSQL14.MYSQL2017") + $RegInstanceName = $InstKey.Substring($InstKey.IndexOf(".") + 1) + + # Check if the instance name matches the one we are looking for + if ($RegInstanceName -eq $instanceName) + { + # Build the reg key in the form HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstKey\MSSQLServer\SuperSocketNetLib\Tcp + $tcpKey = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$InstKey\MSSQLServer\SuperSocketNetLib\Tcp" + + Write-Host "TCP key for instance '$instanceName' is $tcpKey" + + # Check if the TCP key exists + if (Test-Path -Path $tcpKey) + { + # Check if TCP/IP Sockets is enabled + $tcpEnabled = Get-ItemProperty -Path $tcpKey -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Enabled + + # If enabled, go through ports + if ($tcpEnabled -eq "1") + { + $Ports = Get-ItemProperty -Path "$tcpKey\IP*" -ErrorAction SilentlyContinue | Select-Object TcpPort, TcpDynamicPorts + foreach ($port in $Ports) + { + # Skip if the port is not set (0 or null) + if (-not [string]::IsNullOrWhiteSpace($port.TcpDynamicPorts) -and $port.TcpDynamicPorts -gt 0) + { + Write-Host "Port found: $($port.TcpDynamicPorts)" + return $port.TcpDynamicPorts + } + elseif (-not [string]::IsNullOrWhiteSpace($port.TcpPort) -and $port.TcpPort -gt 0) { + Write-Host "Port found: $($port.TcpPort)" + return $port.TcpPort + } + } + } + else + { + Write-Host "TCP/IP Sockets is not enabled for instance $instanceName" + return $null + } + } + } + } + + Write-Host "No matching instance found for server: $server" + return $null + } + catch + { + Write-Host "Test failed with error: $_" + } +} + + +# Main entry point try { @@ -97,6 +184,25 @@ try $TestCount++ } + if ($Scenarios -in ("Basic", "All")) + { + # Get the port number for the instance and use it as a connection string to test the Basic scenario and GetSQLInstanceNameByPortNo() + $port = GetPortFromInstance -server $ServerName + + # If the port is found, run the Basic scenario with the port number. Else, skip the test + if ($port) + { + $temp_return_val = .\Scenarios_Test.ps1 -ServerName ("127.0.0.1,"+$port) -Scenarios "Basic" -SummaryOutputFile $SummaryOutputFilename -SqlNexusPath $SqlNexusPath -SqlNexusDb $SqlNexusDb -LogScoutOutputFolder $LogScoutOutputFolder -RootFolder $root_folder -RunDuration $RunDuration + + #due to PS pipeline, Scenario_Test returns many things in an array. + #We need to get the last element of the array - the return value which is sent out last + $return_val+=$temp_return_val[$temp_return_val.Count-1] + + $TestCount++ + } + + } + if ($Scenarios -in ("GeneralPerf", "All")) { $temp_return_val = .\Scenarios_Test.ps1 -ServerName $ServerName -Scenarios "GeneralPerf" -SummaryOutputFile $SummaryOutputFilename -SqlNexusPath $SqlNexusPath -SqlNexusDb $SqlNexusDb -LogScoutOutputFolder $LogScoutOutputFolder -RootFolder $root_folder -RunTSQLLoad $true -RunDuration $RunDuration @@ -199,7 +305,8 @@ try } if ($Scenarios -in ("GeneralPerf+NoBasic", "All")) { - $temp_return_val =.\Scenarios_Test.ps1 -ServerName $ServerName -Scenarios "GeneralPerf+NoBasic" -SummaryOutputFile $SummaryOutputFilename -RootFolder $root_folder -RunTSQLLoad $true -RunDuration $RunDuration + #Run this scenario with a logscout.stop file to test that functionality -UseStopFile $true + $temp_return_val =.\Scenarios_Test.ps1 -ServerName $ServerName -Scenarios "GeneralPerf+NoBasic" -SummaryOutputFile $SummaryOutputFilename -RootFolder $root_folder -RunTSQLLoad $true -RunDuration $RunDuration -UseStopFile $true $return_val+=$temp_return_val[$temp_return_val.Count-1] $TestCount++ } diff --git a/SQL LogScout/Bin/TestingInfrastructure/FilecountandtypeValidation.ps1 b/SQL LogScout/Bin/TestingInfrastructure/FilecountandtypeValidation.ps1 index f10eea2..7424134 100644 --- a/SQL LogScout/Bin/TestingInfrastructure/FilecountandtypeValidation.ps1 +++ b/SQL LogScout/Bin/TestingInfrastructure/FilecountandtypeValidation.ps1 @@ -151,16 +151,20 @@ function BuildBasicFileArray([bool]$IsNoBasic) 'NetTCPandUDPConnections.out', 'SQL_AzureVM_Information.out', 'Environment_Variables.out', - 'azcmagent-logs' + 'azcmagent-logs', + 'AllMemoryDumps_List.out', + 'exception.log', + 'SQLDUMPER_ERRORLOG.log', + 'DotNetVersions.out' ) # inclusions and exclusions to the array - ModifyArray -ActionType "Add" -TextToFind "This is a Windows Cluster for sure!" -ArrayToEdit $global:BasicFiles -ReferencedLog "_SQLDIAG" + ModifyArray -ActionType "Add" -TextToFind "Getting MSSQLSERVER_SQLDIAG*.xel files" -ArrayToEdit $global:BasicFiles -ReferencedLog "_SQLDIAG" ModifyArray -ActionType "Remove" -TextToFind "Azcmagent not found" -ArrayToEdit $global:BasicFiles -ReferencedLog "azcmagent-logs" ModifyArray -ActionType "Remove" -TextToFind "Will not collect SQLAssessmentAPI" -ArrayToEdit $global:BasicFiles -ReferencedLog "SQLAssessmentAPI" ModifyArray -ActionType "Remove" -TextToFind "No SQLAgent log files found" -ArrayToEdit $global:BasicFiles -ReferencedLog "SQLAGENT" ModifyArray -ActionType "Remove" -TextToFind "SQL_AzureVM_Information will not be collected" -ArrayToEdit $global:BasicFiles -ReferencedLog "SQL_AzureVM_Information.out" - ModifyArray -ActionType "Add" -TextToFind "memory dumps \(max count limit of 20\), from the past 2 months, of size < 100 MB" -ArrayToEdit $global:BasicFiles -ReferencedLog ".mdmp" + ModifyArray -ActionType "Add" -TextToFind "memory dumps \(max count limit of 20\), from the past 2 months, of size < 100 MB" -ArrayToEdit $global:BasicFiles -ReferencedLog "PATTERN:.*\.(mdmp|dmp)$" ModifyArray -ActionType "Add" -TextToFind "memory dumps \(max count limit of 20\), from the past 2 months, of size < 100 MB" -ArrayToEdit $global:BasicFiles -ReferencedLog "SQLDUMPER_ERRORLOG.log" ModifyArray -ActionType "Add" -TextToFind "HADR /AG is enabled on this system" -ArrayToEdit $global:BasicFiles -ReferencedLog "AlwaysOnDiagScript.out" ModifyArray -ActionType "Add" -TextToFind "Found AlwaysOn_health files" -ArrayToEdit $global:BasicFiles -ReferencedLog "AlwaysOn_health" @@ -170,7 +174,10 @@ function BuildBasicFileArray([bool]$IsNoBasic) ModifyArray -ActionType "Add" -TextToFind "FullText is installed on this SQL instance" -ArrayToEdit $global:BasicFiles -ReferencedLog "FDLAUNCHERRORLOG" ModifyArray -ActionType "Add" -TextToFind "FullText is installed on this SQL instance" -ArrayToEdit $global:BasicFiles -ReferencedLog "_FD" ModifyArray -ActionType "Add" -TextToFind "FulText-Search Log file *SQLFT* copied." -ArrayToEdit $global:BasicFiles -ReferencedLog "SQLFT" + ModifyArray -ActionType "Remove" -TextToFind "Not capturing exception.log. File not found in the" -ArrayToEdit $global:BasicFiles -ReferencedLog "exception.log" + ModifyArray -ActionType "Remove" -TextToFind "Not capturing SQL Dumper Error Log. File not found in the" -ArrayToEdit $global:BasicFiles -ReferencedLog "SQLDUMPER_ERRORLOG.log" + #calculate count of expected files $ExpectedFiles = $global:BasicFiles return $ExpectedFiles @@ -425,7 +432,8 @@ function BuildSetupFileArray([bool]$IsNoBasic) '_HKLM_CurVer_Uninstall.txt', '_HKLM_MicrosoftSQLServer.txt', '_MissingMsiMsp_Detailed.txt', - '_MissingMsiMsp_Summary.txt' + '_MissingMsiMsp_Summary.txt', + '_InstalledPrograms.out' ) @@ -884,10 +892,23 @@ function FileCountAndFileTypeValidation([string]$scenario_string, [bool]$IsNoBas #loop through array of actual files found foreach ($actFile in $LogsCollected) { - # if a file is found , set the flag - if ($actFile.Name -like ("*" + $expFile + "*")) + # if a file is found , set the flag to $true + # for PATTERN: files, use -match instead of -like. These are custom cases where we may need an OR search for multiple files for example + if ($expFile.StartsWith("PATTERN:")) + { + # remove the PATTERN: from the string and trim spaces + $pattern = ($expFile -replace "PATTERN:", "").Trim() + if($actFile.Name -match $pattern) + { + $file_found = $true + } + } + else { - $file_found = $true + if($actFile.Name -like ("*" + $expFile + "*")) + { + $file_found = $true + } } } diff --git a/SQL LogScout/Bin/TestingInfrastructure/Scenarios_Test.ps1 b/SQL LogScout/Bin/TestingInfrastructure/Scenarios_Test.ps1 index 95191c0..a8491c7 100644 --- a/SQL LogScout/Bin/TestingInfrastructure/Scenarios_Test.ps1 +++ b/SQL LogScout/Bin/TestingInfrastructure/Scenarios_Test.ps1 @@ -32,7 +32,10 @@ param [int] $RepeatCollections = 0, [Parameter(Position=10)] - [double] $RunDuration = 3 + [double] $RunDuration = 3, + + [Parameter(Position=11)] + $UseStopFile = $false ) @@ -129,6 +132,29 @@ try } + #if UseStopFile is set, start a job which will create a stop file after the specified time in seconds (RunDuration *60 * 0.60) + if ($UseStopFile -eq $true) + { + Write-Host "Creating stop file for LogScout to stop in $($RunDuration*60*0.60) seconds" + $StopFile = $RootFolder + "\output\internal\logscout.stop" + $StopDuration = ($RunDuration * 60) * 0.60 # 60% of the run duration in seconds + $stop_job = Start-Job -Name "CreateStopFileJob" -ScriptBlock { + param($StopFile, $StopDuration) + Start-Sleep -Seconds $StopDuration; + Set-Content -Value "stop please" -Path $StopFile -Force; + + if (Test-Path -Path $StopFile) + { + Microsoft.PowerShell.Utility\Write-Host "The stop file $StopFile was created successfully." + } + else + { + Microsoft.PowerShell.Utility\Write-Host "The stop file $StopFile was not created successfully." + } + #no need to remove the file as it will be deleted when a new test is run + } -ArgumentList $StopFile, $StopDuration + } + ##execute a regular SQL LogScout data collection from root folder Write-Host "Starting LogScout" @@ -153,6 +179,21 @@ try TSQLLoadCheckWorkloadExited } + #if UseStopFile is set, wait for the job to complete and print the output + if ($UseStopFile -eq $true) + { + # Wait for the job to complete + Wait-Job -Job $stop_job | Out-Null + + # Retrieve and display the job output + $jobOutput = Receive-Job -Job $stop_job + Microsoft.PowerShell.Utility\Write-Host $jobOutput + + # Remove the job + Remove-Job -Job $stop_job + } + + #run file validation test $script_ret = ./FileCountAndTypeValidation.ps1 -SummaryOutputFile $SummaryOutputFile 2> .\##TestFailures.LOG diff --git a/SQL LogScout/Bin/TestingInfrastructure/azuredevops-pipelines.yml b/SQL LogScout/Bin/TestingInfrastructure/azuredevops-pipelines.yml index 6adfcdc..333a146 100644 --- a/SQL LogScout/Bin/TestingInfrastructure/azuredevops-pipelines.yml +++ b/SQL LogScout/Bin/TestingInfrastructure/azuredevops-pipelines.yml @@ -228,52 +228,53 @@ extends: displayName: Run LogScout Test Suite inputs: script: | + @echo off time /t sqlcmd -S.\sqlexpress -Q "set nocount on; SELECT @@version; SELECT @@servername; SELECT * FROM sys.databases" echo NexusDir: $(NexusDir) - + set RunDuration=2.7 echo ======================================================================================== echo Starting SQL LogScout test... date /t & time /t cd .\Bin\TestingInfrastructure - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Basic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Basic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 timeout /T 5 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "GeneralPerf" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "GeneralPerf" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "DetailedPerf+NoBasic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "DetailedPerf+NoBasic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "LightPerf" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "LightPerf" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Memory" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Memory" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - # powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "AlwaysOn" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + # powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "AlwaysOn" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% # IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "NetworkTrace+NoBasic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "NetworkTrace+NoBasic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "IO" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "IO" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "BackupRestore+NoBasic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "BackupRestore+NoBasic" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Replication" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Replication" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Setup" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "Setup" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "ServiceBrokerDBMail" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "ServiceBrokerDBMail" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 - powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "NeverEndingQuery" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration 2.5 + powershell -File .\ConsistentQualityTests.ps1 -ServerName ".\sqlexpress" -Scenarios "NeverEndingQuery" -SqlNexusPath $(NexusDir) -SqlNexusDb "SqlNexusDB" -RunDuration %RunDuration% IF %ERRORLEVEL% GTR 0 echo ##[error]Test failed with errorlevel %ERRORLEVEL% && exit 1 \ No newline at end of file diff --git a/SQL LogScout/Bin/TestingInfrastructure/sqlnexus_tablecheck_proc.sql b/SQL LogScout/Bin/TestingInfrastructure/sqlnexus_tablecheck_proc.sql index 45a89cd..1739ce2 100644 --- a/SQL LogScout/Bin/TestingInfrastructure/sqlnexus_tablecheck_proc.sql +++ b/SQL LogScout/Bin/TestingInfrastructure/sqlnexus_tablecheck_proc.sql @@ -336,7 +336,6 @@ BEGIN ('dbo','tbl_SYSPERFINFO') , ('dbo','tbl_SQL_CPU_HEALTH') , ('dbo','tbl_FILE_STATS') , - ('dbo','tbl_SYSINFO') , ('dbo','tbl_PERF_STATS_SCRIPT_RUNTIMES') , ('dbo','tbl_BLOCKING_CHAINS') , ('dbo','tbl_Reports') , @@ -350,7 +349,15 @@ BEGIN ('dbo','CounterDetails'), ('dbo','CounterData'), ('dbo', 'tbl_SystemInformation'), - ('dbo', 'tbl_environment_variables') + ('dbo', 'tbl_environment_variables'), + ('dbo', 'tbl_sys_servers'), + ('dbo', 'tbl_dotnet_versions'), + ('dbo', 'tbl_sys_assembly_types'), + ('dbo', 'tbl_sys_assembly_modules'), + ('dbo', 'tbl_sys_assemblies'), + ('dbo', 'tbl_clr_loaded_assemblies'), + ('dbo', 'tbl_clr_appdomains'), + ('dbo','tbl_sqlagent_jobs') --create the list of Basic scenario tables for reuse in other scenarios IF OBJECT_ID('tempdb..#tablelist_LightPerfScenario') IS NOT NULL @@ -518,7 +525,8 @@ BEGIN BEGIN -- insert the tables for Setup scenario INSERT INTO #temptablelist_sqlnexus (SchemaName,TableName) VALUES - ('dbo','tbl_setup_missing_msi_msp_packages') + ('dbo','tbl_setup_missing_msi_msp_packages'), + ('dbo','tbl_installed_programs') --insert the tables for Basic scenario INSERT INTO #temptablelist_sqlnexus (SchemaName,TableName) @@ -672,12 +680,10 @@ BEGIN INSERT INTO #temptablelist_sqlnexus (SchemaName,TableName) VALUES ('dbo','tbl_sysmail_profileaccount'), ('dbo','tbl_sysmail_profile'), - ('dbo','tbl_sysmail_log'), ('dbo','tbl_sysmail_configuration'), ('dbo','tbl_sysmail_account'), ('dbo','tbl_sysmail_mailitems'), - ('dbo','tbl_sysmail_event_log_sysmail_faileditems'), - ('dbo','tbl_sysmail_server') + ('dbo','tbl_sysmail_server') --add the basic scenario tables INSERT INTO #temptablelist_sqlnexus (SchemaName,TableName) diff --git a/SQL LogScout/SQL_LogScout.ps1 b/SQL LogScout/SQL_LogScout.ps1 index 7d783c1..58abdec 100644 --- a/SQL LogScout/SQL_LogScout.ps1 +++ b/SQL LogScout/SQL_LogScout.ps1 @@ -93,9 +93,16 @@ function Test-PowerShellVersionAndHost() } } + +# get the full but by default short path of the temp folder and convert it to full path. Then store it in a global variable +$shortEnvTempPath = $env:TEMP +$global:EnvTempVarFullPath = (Get-Item $shortEnvTempPath).FullName + # create a temporary log file to store the output of the repeated executions -$script:temp_output_sqllogscout = $env:temp + "\SQL_LogScout_Repeated_Execution_" + (Get-Date).ToString('yyyyMMddhhmmss') + ".txt" -$script:search_pattern = $env:temp + "\SQL_LogScout_Repeated_Execution_*.txt" +# the file will be created in the temp folder and will be deleted at the end of the script + +$script:temp_output_sqllogscout = $global:EnvTempVarFullPath + "\SQL_LogScout_Repeated_Execution_" + (Get-Date).ToString('yyyyMMddhhmmss') + ".txt" +$script:search_pattern = $global:EnvTempVarFullPath+ "\SQL_LogScout_Repeated_Execution_*.txt" function Write-SQLLogScoutTempLog() { From fe381d23089f4b3966ac356614081918663ac952 Mon Sep 17 00:00:00 2001 From: JosephPilov-MSFT <23519517+PiJoCoder@users.noreply.github.com> Date: Thu, 1 May 2025 18:15:37 -0500 Subject: [PATCH 2/2] Update Readme.md at the root folder --- README.md | 469 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 319 insertions(+), 150 deletions(-) diff --git a/README.md b/README.md index 41a2083..37607a1 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,14 @@ - [Examples](#examples) 1. [Scenarios](#scenarios) 1. [Output folders](#output-folders) +1. [SQL LogScout as a scheduled task in Windows Task Scheduler](#schedule-sql-logscout-as-a-task-to-automate-execution) 1. [Logging](#logging) -1. [Permissions](#permissions) 1. [Targeted SQL instances](#targeted-sql-instances) 1. [Security](#security) 1. [Sample output](#sample-output) 1. [Test Suite](#test-suite) 1. [Script to cleanup an incomplete shutdown of SQL LogScout](#script-to-cleanup-an-incomplete-shutdown-of-sql-logscout) -1. [SQL LogScout as a scheduled task in Windows Task Scheduler](#schedule-sql-logscout-as-a-task-to-automate-execution) +1. [How to connect to and collect data from Windows Internal Database (WID)](#how-to-connect-to-and-collect-data-from-windows-internal-database-wid) # Introduction @@ -111,10 +111,17 @@ There are 3 possible ways to run and interact with SQL LogScout: 1. Run the following PS script by itself or by using [parameters](#parameters). For example: ```powershell - PS > .\SQL_LogScout.ps1 -Scenario "Basic" -ServerName "Win2022machine\inst2022" + .\SQL_LogScout.ps1 -Scenario "Basic" -ServerName "Win2022machine\inst2022" ``` -**Note:** Using the PowerShell script `SQL_LogScout.ps1` is the recommended way to run SQL LogScout, but `SQL_LogScout.cmd` is supported for backwards compatibility. The introduction of `SQL_LogScount.ps1` was brought about for several reasons: +### Accept to run signed files for first time + +You may be prompted to accept to run the digitally-signed PowerShell scripts for the very first time. See [Prompt to accept usage of digitally-signed files](#prompt-to-accept-usage-of-digitally-signed-files) + + +### Recommendation to use SQL_LogScout.ps1 script + +Using the PowerShell script `SQL_LogScout.ps1` is the recommended way to run SQL LogScout, but `SQL_LogScout.cmd` is supported for backwards compatibility. The introduction of `SQL_LogScount.ps1` was brought about for several reasons: 1. The ability to invoke SQL LogScout with named parameters in any order and with the option to omit parameters that aren't required. The .CMD file has been inflexible in this respect. 1. The introduction of a new feature RepeatCollections or continuous mode and the ability to retain a certain number of output folders when run with continuous mode. @@ -128,7 +135,7 @@ There are 3 possible ways to run and interact with SQL LogScout: |:---------------------------| | Please make sure that the SQL Server startup account has **write** permissions to the folder you selected. Typically folders like %USERPROFILE%\Downloads, %USERPROFILE%\Documents AND %USERPROFILE%\Desktop folders are **not** write-accessible by the SQL Server service account by default.| -1. Open a PowerShell prompot or a Command Prompt as an Administrator and change to the folder where SQL LogScout files reside. For example: +1. Open a PowerShell prompt as an Administrator and change to the folder where SQL LogScout files reside. For example: ```console cd d:\sqllogscout @@ -137,7 +144,7 @@ There are 3 possible ways to run and interact with SQL LogScout: 1. Start the tool via `SQL_LogScout.ps1` before or while the issue is occurring and follow the menus ```console - SQL_LogScout.ps1 + .\SQL_LogScout.ps1 ``` 1. When prompted `Would you like to use GUI mode ?> (Y/N):` type 'y' and you will be presented with a GUI @@ -203,6 +210,71 @@ If the need arises, you can interrupt the execution of SQL LogScout by pressing |:---------------------------| | Do **not** close the Command Prompt window where SQL LogScout is running because this may leave a data collector running on your system. You can safely do so when SQL LogScout completes.| +## Stop execution automatically by using a .stop file + +In some cases the user may not be present to type 'STOP' and terminate the SQL LogScout collection. You may need to have an event trigger an automatic stop. To do so, you can create a blank or non-blank file named `logscout.stop` in the **\internal** folder. The file can be created either manually or programmatically. SQL LogScout detects the file within 5 seconds and initiates a graceful stop. A message is printed on teh screen and in the log that states this "Stop file detected. Shutting down the collector". + +Here are examples of how to create a logscout.stop file programmatically + +In PowerShell: + +```powershell +Set-Content -Value "stop please" -Path "G:\SQLLogScout\output\internal\logscout.stop" +``` + +In a batch file or from Command Prompt + +```bash +ECHO abc > F:\SQLLogScout\output_20240919T114819\internal\logscout.stop +``` + +There are two situations where this action is possible: + +- Manually choose to wait for a stop file to be created +- Create a stop file while SQL LogScout is waiting for an end time (DiagStopTime) to expire + +### Manually choose to wait for a stop file to be created + +You can set up SQL LogScout to stop only when a .stop file is created. If you manually start SQL LogScout and follow the prompts, you are asked whether you'd like to type 'STOP' or 'STOPEVENT'. If you type 'STOPEVENT', SQL LogScout continues to collect logs until a .stop file is created. The user experience looks like this: + +```bash +2025-03-28 14:49:16.302 INFO Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue. +2025-03-28 14:49:16.302 INFO You can type 'STOPEVENT' and wait for a stop file to automatically end the diagnostics collection. +>: stopevent +2025-03-28 14:49:25.809 INFO StopCollection Console input: stopevent +2025-03-28 14:49:25.821 INFO Waiting for stop file to be created... +2025-03-28 14:49:35.839 INFO Stop file detected. Shutting down the collector +2025-03-28 14:49:35.884 INFO Executing Collector: Xevents_Stop +2025-03-28 14:49:36.000 INFO Executing Collector: PerfmonStop +2025-03-28 14:49:39.126 INFO Executing Collector: KillActiveLogscoutSessions +2025-03-28 14:49:40.234 INFO Collecting logs for 'Basic' scenario +2025-03-28 14:49:40.266 INFO Executing Collector: TaskListVerbose +2025-03-28 14:49:45.465 INFO Executing Collector: TaskListServices +2025-03-28 14:49:48.582 INFO Executing Collector: FLTMC_Filters +``` + +### Create a stop file while waiting for an end time to expire + +If you have configured SQL LogScout to run until a predefined time using the -DiagStopTime parameter, then it waits for that time to be reached and automatically stop. However, if you decide to stop collection before that end time is reached, you can create a stop file in the \internal folder and SQL LogScout stops. The user experience looks like this (note that 14:48 is not reached because a stop file is created at 14:46): + +```bash +2025-03-28 14:46:18.245 INFO Executing Collector: HighCPU_perfstats +2025-03-28 14:46:18.322 INFO Executing Collector: PerfStats +2025-03-28 14:46:20.455 INFO Executing Collector: PerfStatsSnapshotStartup +2025-03-28 14:46:20.541 INFO Executing Collector: QueryStore +2025-03-28 14:46:22.649 INFO Executing Collector: TempDB_and_Tran_Analysis +2025-03-28 14:46:22.728 INFO Executing Collector: linked_server_config +2025-03-28 14:46:22.966 WARN Waiting until the specified stop time '2025-Mar-28 14:48:00' is reached...(CTRL+C to stop - wait for response) +2025-03-28 14:46:41.108 INFO Stop file detected. Shutting down the collector +2025-03-28 14:46:41.116 INFO Checking for errors in collector logs +2025-03-28 14:46:41.140 INFO Shutting down automatically. No user interaction to stop collectors +2025-03-28 14:46:41.145 INFO Waiting 10-15 seconds to capture a few snapshots of Perfmon before shutting down. +2025-03-28 14:46:53.152 INFO Shutting down the collector +2025-03-28 14:46:53.179 INFO Executing Collector: Xevents_Stop +2025-03-28 14:46:53.303 INFO Executing Collector: PerfmonStop +2025-03-28 14:46:56.415 INFO Executing Collector: KillActiveLogscoutSessions +``` + ## Parameters `SQL_LogScout.ps1` and `SQL_LogScout.cmd` accepts several optional parameters. If you are using the PS1 PowerShell script, you can pass named parameters and omit most of them or specify them in any order. However, if you are using `SQL_LogScout.cmd` because this is a batch file, you have to specify all the parameters in the sequence listed below and cannot omit parameters. For example if you would like to specify the server instance (3rd parameter), you must specify the Scenario parameter before it. @@ -225,6 +297,7 @@ Possible values are: - IO - LightPerf - ProcessMonitor + - ServiceBrokerDBMail - NeverEndingQuery - MenuChoice - this directs SQL LogScout to present an interactive menu with Scenario choices. The option is available in cases where multiple parameters are used with SQL_LogScout.cmd. Combining MenuChoice with another scenario choice, causes SQL LogScout to ignore MenuChoice and pick the selected scenario(s). For more information on what data each scenario collects, see [Scenarios](#scenarios) - NoBasic - this instructs SQL LogScout to skip the collection of basic logs, when Basic scenario is part of another scenario by default. For example if you use GeneralPerf+NoBasic, only the performance logs will be collected and static logs (Basic) will be skipped. If NoBasic+Basic is specified by mistake, the assumption is you intend to collect data; therefore Basic is enabled and NoBasic flag is disabled. Similarly, if NoBasic+Basic+A_VALID_SCENARIO is selected, again the assumption is that data collection is intended. In this case, Basic is enabled, NoBasic is disabled and A_VALID_SCENARIO will collect Basic logs. @@ -302,7 +375,7 @@ If you do not select any option in the GUI (e.g. scenario or server name) and cl This is the most common method to execute SQL LogScout which allows you to pick your choices from a menu of options ```powershell -SQL_LogScout.ps1 +.\SQL_LogScout.ps1 ``` ### B. Execute SQL LogScout using a specific scenario @@ -310,7 +383,7 @@ SQL_LogScout.ps1 This command starts the diagnostic collection specifying the GeneralPerf scenario. ```powershell -SQL_LogScout.ps1 -Scenario "GeneralPerf" +.\SQL_LogScout.ps1 -Scenario "GeneralPerf" ``` ### C. Execute SQL LogScout by specifying folder creation option @@ -318,7 +391,7 @@ SQL_LogScout.ps1 -Scenario "GeneralPerf" Execute SQL LogScout using the DetailedPerf Scenario, specifies the Server name, use the present directory and folder option to delete the default \output folder if present ```powershell -SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" +.\SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" ``` ### D. Execute SQL LogScout with start and stop times (absolute values) @@ -326,7 +399,7 @@ SQL_LogScout.ps1 -Scenario "DetailedPerf" -ServerName "DbSrv\SQL2019" -CustomOut The following example collects the AlwaysOn scenario against the "DbSrv" default instance, prompts user to choose a custom path and a new custom subfolder, and sets the stop time to some time in the future, while setting the start time in the past to ensure the collectors start without delay. ```powershell -SQL_LogScout.ps1 -Scenario AlwaysOn -ServerName "DbSrv" -CustomOutputPath "PromptForCustomDir" -DeleteExistingOrCreateNew "NewCustomFolder" -DiagStartTime "2000-01-01 19:26:00" -DiagStopTime "2020-10-29 13:55:00" +.\SQL_LogScout.ps1 -Scenario AlwaysOn -ServerName "DbSrv" -CustomOutputPath "PromptForCustomDir" -DeleteExistingOrCreateNew "NewCustomFolder" -DiagStartTime "2000-01-01 19:26:00" -DiagStopTime "2020-10-29 13:55:00" ``` This is how you would do the same using the .CMD file. @@ -340,7 +413,7 @@ SQL_LogScout.cmd AlwaysOn "DbSrv" PromptForCustomDir NewCustomFolder "2000-01-01 The following example collects the Replication and LightPerf scenarios without getting Basic logs against the "DbSrv\SQL2022" named instance, uses the current directory as root and overwrites the \output subfolder. Then uses relative time from current time to set the start time 3 minutes from now and stop time to seven minutes from now. ```powershell -SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQL2022" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "+00:03:00" -DiagStopTime "+00:07:00" +.\SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQL2022" -CustomOutputPath "UsePresentDir" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "+00:03:00" -DiagStopTime "+00:07:00" ``` **Note:** If you are using SQL_LogScout.cmd, all parameters are required when you need to specify the last parameter. For example, if you need to specify stop time, the 5 prior parameters have to be passed. @@ -350,7 +423,7 @@ SQL_LogScout.ps1 -Scenario "Replication+LightPerf+NoBasic" -ServerName "DbSrv\SQ The example collects data for GeneralPerf, AlwaysOn, and BackupRestore scenarios against the "DbSrv" default instance, re-uses the default output folder but creates it in the D:\Log custom path, and sets the stop time to some time in the future, while setting the start time in the past to ensure the collectors start without delay. It also automatically accepts the prompts by using Quiet mode and helps a full automation with no interaction. ```powershell -SQL_LogScout.ps1 -Scenario "GeneralPerf+AlwaysOn+BackupRestore" -ServerName "DbSrv" -CustomOutputPath "d:\log" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "01-01-2000" -DiagStopTime "04-01-2021 17:00" -InteractivePrompts "Quiet" +.\SQL_LogScout.ps1 -Scenario "GeneralPerf+AlwaysOn+BackupRestore" -ServerName "DbSrv" -CustomOutputPath "d:\log" -DeleteExistingOrCreateNew "DeleteDefaultFolder" -DiagStartTime "01-01-2000" -DiagStopTime "04-01-2021 17:00" -InteractivePrompts "Quiet" ``` When you use SQL_LogScout.cmd (available for backwards compatibility), pass the parameters in order @@ -390,9 +463,10 @@ Collects snapshot or static logs. It captures information on: - Installed Windows Hotfixes - OS disk information - Running filter drivers +- .NET Framework and .NET Core versions - Event logs (system and application in both .CSV and .TXT formats) - Full-Text Search Log files and output file with Full-Text metadata -- SQL Server dumps found in the errorlog directory. We collect up to 20 dumps if they were created in the last 2 months and are less than 100 MB in size. +- SQL Server dumps found in the errorlog directory. SQL LogScout collects up to 20 dumps if they were created in the last 2 months and are less than 200 MB in size. - Memory dump .txt files (most recent 200 files) - IPConfig, DNSClientInfo, and TCP and UDP endpoints - SQL Errorlogs @@ -486,7 +560,7 @@ Allows you to collect a [Windows Performance Recorder](https://docs.microsoft.co | :warning: WARNING | |:---------------------------| -| WPR traces collect system-wide diagnostic data. Thus a large set of trace data may be collected and it may take several minutes to stop the trace. Therefore the WPR trace is limited to 45 seconds of data collection. You can specify a custom value between 3 and 45 seconds.| +| WPR traces collect system-wide diagnostic data. Thus a large set of trace data may be collected and it may take several minutes to stop the trace. Therefore the WPR trace is limited to 45 seconds of data collection. You can specify a custom value between 3 and 45 seconds. Since the WPR scenario is run for a very short time and can be impactful to systems, this scenario is not designed to be run as a scheduled task and requires the user's interaction with SQL LogScout to run it.| ## 9. Setup scenario @@ -494,7 +568,9 @@ Collects Setup logs and allows analysis of installation issues of SQL Server com - Basic scenario logs - All SQL Setup logs from the SQL Server \Setup Bootstrap\ folders on the system. +- Registry keys of the installed programs on the system - Missing MSI/MSP output files showing what installation packages may be missing. The summary file shows the only missing and potentially corrupt packages and the detailed one provides details on each SQL Server MSI/MSP and if it's in place, missing, or corrupt and what actions can be taken. +- A list of installed programs on the system ## 10. BackupRestore scenario @@ -557,7 +633,7 @@ SQL LogScout can be scheduled as a task in Windows Task Scheduler. This allows y - **-LogScoutPath** - this is the executable path to the `SQL_LogScout.cmd` file. It defaults to the current path you are running the script from. - **-Scenario** - you can input the scenario (s) you want to collect data for. Examples include "Basic", "GeneralPerf" or "Basic+Replication". For more information see [Scenarios](#scenarios) -- **-SQLInstance** - this is the name of the SQL Server instance to connect to. Please provide correct name (for example: "MACHINE1\SQLINST1") +- **-SQLInstance** - this is the name of the SQL Server instance to connect to. Please provide correct name. For example you would use "MACHINE1\SQLINST1" for a named instance or "MACHINE2" for a default instance. For SQL Server failover clustered instances use a virtual network name: for example "SQL01FCIVNN" for a default instance or "SQL01FCIVNN\SQLINST2" for a named instance. - **-OutputPath** - you specify whether you want a custom output path by providing the path itself, or specify 'UsePresentDir' to use the current folder as a base under which an output folder will be created. This corresponds to `CustomOutputPath` in SQL LogScout [Parameters](#parameters). Do NOT use `PromptForCustomDir` for a scheduled task, because you have to present to accept this on the screen. - **-CmdTaskName** - this is the name of the task as it appears in Windows Task Scheduler. This is an optional parameter that allows you to create multiple scheduled tasks. If you pass a value which already exists, you will be prompted to overwrite or keep original task. Default value is "SQL LogScout Task". - **-DeleteFolderOrNew** - this controls the sub-folder name where the output data goes. For more information see, `DeleteExistingOrCreateNew` in [Parameters](#parameters). Options for it are: @@ -578,32 +654,43 @@ SQL LogScout can be scheduled as a task in Windows Task Scheduler. This allows y Examples: 1. Run SQL_LogScout one time for the GeneralPerf scenario, starting at 05/06/2024 at 2:18 PM ending after 10 minutes (2:28 PM). The Output folder is overwritten (if it exists already). User will be logged in during execution. + ```powershell -.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstanceName" -StartTime "2024-05-06 14:18" -EndTime "+00:10:00" -Once -DeleteFolderOrNew "DeleteDefaultFolder" -LogonType "S4U" +.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstance01" -StartTime "2024-05-06 14:18" -EndTime "+00:10:00" -Once -DeleteFolderOrNew "DeleteDefaultFolder" -LogonType "S4U" ``` -2. Run SQL_LogScout starting 6 hours from now, running continously for 48 executions recycling the logs every 30 minutes. The total run time would be 24 hours (48 runs * 30 minutes). A new folder is created for each execution and the user isn't to be logged in during runtime. + +1. Run SQL_LogScout starting 6 hours from now, running continously for 48 executions recycling the logs every 30 minutes. The total run time would be 24 hours (48 runs * 30 minutes). A new folder is created for each execution and the user isn't to be logged in during runtime. + ```powershell -.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance ".\SQLInstanceName" -StartTime "+06:00:00" -EndTime "+00:30:00" -Continuous -DeleteFolderOrNew "NewCustomFolder" -LogonType "Interactive" -RepeatCollections 47 +.\ScheduleSQLLogScoutAsTask.ps1 -Scenario "GeneralPerf" -SQLInstance "SQLPRODMACHINE" -StartTime "+06:00:00" -EndTime "+00:30:00" -Continuous -DeleteFolderOrNew "NewCustomFolder" -LogonType "Interactive" -RepeatCollections 47 ``` # Logging +There are several logs generated by SQL LogScout based on the activities used. + ### ##SQLLOGSCOUT.LOG file + SQL LogScout logs the flow of activity in two files ##SQLLOGSCOUT.LOG and ##SQLLOGSCOUT_DEBUG.LOG. The activity flow on the console is logged in ##SQLLOGSCOUT.LOG. The design goal is to match what the user sees on the screen with what is written in the log file so that a post-mortem analysis can be performed. This file can be found in the **\Internal** folder ### ##STDERR.LOG file + If SQL LogScout main script generates any runtime errors that were not caught, those will be written to the ##STDERR.LOG file and the contents of that file is displayed in the console after the main script completes execution. The ##STDERR.LOG file is stored in the root directory where SQL LogScout runs because any failures that occur early before the creation of an output folder may be logged in this file. This file can be found together with the scripts (**\Bin** folder). ### ##SQLLOGSCOUT_DEBUG.LOG file + This file contains everything the ##SQLLOGSCOUT.LOG contains, but also adds many debug-level, detailed messages. These can be used to investigate any issues with SQL LogScout and examine the flow of execution in detail. This file can be found in the **\Internal** folder. In addition, the %temp% folder stores copies of ##SQLLOGSCOUT_DEBUG.LOG from the last 10 executions. ### SQL_LogScout_Repeated_Execution_yyyyMMddhhmmss.txt + This file is created when repeated collections (continuous mode) is used. It logs the number of repetitions, the number of folders to be preserved, the names of output folders created by the repeated mode. It is created in the Windows **%temp%** folder (commonly C:\Users\\\AppData\Local\Temp). ### ##SQLLogScout_ScheduledTask_yyyyMMddhhmmss.log + This file is created when the functionality to automate the SQL_LogScout collection task through Windows Task Scheduler is used. This file can be found in the user's **%temp%** folder where you can find copies of the latest 10 executions of the task scheduling script `ScheduleSQLLogScoutAsTask.ps1`. ### ##SQLLogScout_CleanupIncompleteShutdown_yyyyMMddhhmmss.log + This file is created when the functionality to cleanup an incomplete shutdown of SQL_LogScout is used. The last 10 instances of this file can be found in the user's **%temp%** folder. @@ -625,6 +712,37 @@ The following is security-related information: SQL LogScout is released with digitally-signed Powershell files. For other files, SQL LogScout calculates a SHA512 hash and compares it to the expected value of each file. If the stored hash does not match the calculated hash on disk, then SQL LogScout will not run. +### Prompt to accept usage of digitally-signed files + +When you download and run a new version of SQL LogScout on your system for the first time, you will be prompted to confim and accept running these scripts if your PowerShell execution policy requires signed files. In order to successfully run SQL LogScout, read the message on screen that shows that Microsoft has signed these files and accept to run. You may see messages similar to these: + +```powershell + +Do you want to run software from this untrusted publisher? +File C:\Temp\SQL_LogScout.ps1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, +S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers. +[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"): a +Launching SQL LogScout... + + + +Do you want to run software from this untrusted publisher? +File C:\Temp\Bin\CommonFunctions.psm1 is published by CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US and is not trusted on your system. Only run scripts from trusted publishers. +[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is "D"): a +Copyright (c) 2022 Microsoft Corporation. All rights reserved. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +... + +``` + +### Validate digital signatures of Powershell scripts To manually validate script signature, you may execute the following: ```bash @@ -669,7 +787,7 @@ SignerCertificate : [Subject] ## Encrypted connection to SQL Server -SQL LogScout negotiates connection encryption with the SQL Server it collects data from. It does so by using "Encrypt=True;TrustServerCertificate=true;" and "sqlcmd -C -N" values. +SQL LogScout negotiates connection encryption with the SQL Server it collects data from. It does so by using "Encrypt=True;TrustServerCertificate=true;" and "sqlcmd -C -N" values. In cases where encryption isn't supported by the back-end SQL Server (for example WID), SQL LogScout will attempt to use an unencrypted connection via the classic SQL Server ODBC driver. # Sample output @@ -695,138 +813,139 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -2021-09-10 11:03:32.148 INFO Initializing log C:\temp\log scout\Test 2\output\internal\##SQLLOGSCOUT.LOG -2021-09-10 11:03:26.230 INFO SQL LogScout version: 4.5.33 -2021-09-10 11:03:26.302 INFO The Present folder for this collection is C:\temp\log scout\Test 2 -2021-09-10 11:03:30.479 INFO Prompt CustomDir Console Input: n -2021-09-10 11:03:30.551 INFO -2021-09-10 11:03:30.560 WARN It appears that output folder 'C:\temp\log scout\Test 2\output\' has been used before. -2021-09-10 11:03:30.562 WARN You can choose to: -2021-09-10 11:03:30.562 WARN - Delete (D) the \output folder contents and recreate it -2021-09-10 11:03:30.572 WARN - Create a new (N) folder using \Output_ddMMyyhhmmss format. -2021-09-10 11:03:30.572 WARN You can delete the new folder manually in the future -2021-09-10 11:03:31.954 INFO Output folder Console input: d -2021-09-10 11:03:32.118 WARN Deleted C:\temp\log scout\Test 2\output\ and its contents -2021-09-10 11:03:32.126 INFO Output path: C:\temp\log scout\Test 2\output\ -2021-09-10 11:03:32.126 INFO Error path is C:\temp\log scout\Test 2\output\internal\ -2021-09-10 11:03:32.168 INFO Validating attributes for non-Powershell script files -2021-09-10 11:03:32.648 INFO -2021-09-10 11:03:32.656 INFO Initiating diagnostics collection... -2021-09-10 11:03:32.659 INFO Please select one of the following scenarios: +2025-03-10 11:03:32.148 INFO Initializing log C:\temp\log scout\Test 2\output\internal\##SQLLOGSCOUT.LOG +2025-03-10 11:03:26.230 INFO SQL LogScout version: 4.5.33 +2025-03-10 11:03:26.302 INFO The Present folder for this collection is C:\temp\log scout\Test 2 +2025-03-10 11:03:30.479 INFO Prompt CustomDir Console Input: n +2025-03-10 11:03:30.551 INFO +2025-03-10 11:03:30.560 WARN It appears that output folder 'C:\temp\log scout\Test 2\output\' has been used before. +2025-03-10 11:03:30.562 WARN You can choose to: +2025-03-10 11:03:30.562 WARN - Delete (D) the \output folder contents and recreate it +2025-03-10 11:03:30.572 WARN - Create a new (N) folder using \Output_ddMMyyhhmmss format. +2025-03-10 11:03:30.572 WARN You can delete the new folder manually in the future +2025-03-10 11:03:31.954 INFO Output folder Console input: d +2025-03-10 11:03:32.118 WARN Deleted C:\temp\log scout\Test 2\output\ and its contents +2025-03-10 11:03:32.126 INFO Output path: C:\temp\log scout\Test 2\output\ +2025-03-10 11:03:32.126 INFO Error path is C:\temp\log scout\Test 2\output\internal\ +2025-03-10 11:03:32.168 INFO Validating attributes for non-Powershell script files +2025-03-10 11:03:32.648 INFO +2025-03-10 11:03:32.656 INFO Initiating diagnostics collection... +2025-03-10 11:03:32.659 INFO Please select one of the following scenarios: -2021-09-10 11:03:32.659 INFO -2021-09-10 11:03:32.669 INFO ID Scenario -2021-09-10 11:03:32.669 INFO -- --------------- -2021-09-10 11:03:32.677 INFO 0 Basic -2021-09-10 11:03:32.679 INFO 1 GeneralPerf -2021-09-10 11:03:32.679 INFO 2 DetailedPerf -2021-09-10 11:03:32.687 INFO 3 Replication -2021-09-10 11:03:32.689 INFO 4 AlwaysOn -2021-09-10 11:03:32.689 INFO 5 NetworkTrace -2021-09-10 11:03:32.689 INFO 6 Memory -2021-09-10 11:03:32.689 INFO 7 DumpMemory -2021-09-10 11:03:32.697 INFO 8 WPR -2021-09-10 11:03:32.699 INFO 9 Setup -2021-09-10 11:03:32.699 INFO 10 BackupRestore -2021-09-10 11:03:32.699 INFO 11 IO -2021-09-10 11:03:32.699 INFO 12 LightPerf -2021-09-10 11:03:32.709 INFO -2021-09-10 11:03:32.709 WARN Type one or more Scenario IDs (separated by '+') for which you want to collect diagnostic data. Then press Enter -2021-09-10 11:04:02.077 INFO Scenario Console input: 1+4+10 -2021-09-10 11:04:02.208 INFO The scenarios selected are: 'GeneralPerf AlwaysOn BackupRestore Basic' -2021-09-10 11:04:02.665 INFO Discovered the following SQL Server instance(s) +2025-03-10 11:03:32.659 INFO +2025-03-10 11:03:32.669 INFO ID Scenario +2025-03-10 11:03:32.669 INFO -- --------------- +2025-03-10 11:03:32.677 INFO 0 Basic +2025-03-10 11:03:32.679 INFO 1 GeneralPerf +2025-03-10 11:03:32.679 INFO 2 DetailedPerf +2025-03-10 11:03:32.687 INFO 3 Replication +2025-03-10 11:03:32.689 INFO 4 AlwaysOn +2025-03-10 11:03:32.689 INFO 5 NetworkTrace +2025-03-10 11:03:32.689 INFO 6 Memory +2025-03-10 11:03:32.689 INFO 7 DumpMemory +2025-03-10 11:03:32.697 INFO 8 WPR +2025-03-10 11:03:32.699 INFO 9 Setup +2025-03-10 11:03:32.699 INFO 10 BackupRestore +2025-03-10 11:03:32.699 INFO 11 IO +2025-03-10 11:03:32.699 INFO 12 LightPerf +2025-03-10 11:03:32.709 INFO +2025-03-10 11:03:32.709 WARN Type one or more Scenario IDs (separated by '+') for which you want to collect diagnostic data. Then press Enter +2025-03-10 11:04:02.077 INFO Scenario Console input: 1+4+10 +2025-03-10 11:04:02.208 INFO The scenarios selected are: 'GeneralPerf AlwaysOn BackupRestore Basic' +2025-03-10 11:04:02.665 INFO Discovered the following SQL Server instance(s) -2021-09-10 11:04:02.665 INFO -2021-09-10 11:04:02.676 INFO ID SQL Instance Name -2021-09-10 11:04:02.678 INFO -- ---------------- -2021-09-10 11:04:02.679 INFO 0 DbServerMachine -2021-09-10 11:04:02.679 INFO 1 DbServerMachine\SQL2014 -2021-09-10 11:04:02.686 INFO 2 DbServerMachine\SQL2017 -2021-09-10 11:04:02.686 INFO 3 DbServerMachine\SQL2019 -2021-09-10 11:04:02.686 INFO -2021-09-10 11:04:02.686 WARN Enter the ID of the SQL instance for which you want to collect diagnostic data. Then press Enter -2021-09-10 11:04:11.899 INFO SQL Instance Console input: 3 -2021-09-10 11:04:11.911 INFO You selected instance 'DbServerMachine\SQL2019' to collect diagnostic data. -2021-09-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has VIEW SERVER STATE on SQL Server Instance 'DbServerMachine\SQL2019' -2021-09-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has ALTER ANY EVENT SESSION on SQL Server Instance 'DbServerMachine\SQL2019' -2021-09-10 11:04:12.735 WARN At least one of the selected 'GeneralPerf AlwaysOn BackupRestore Basic' scenarios collects Xevent traces -2021-09-10 11:04:12.751 WARN The service account 'NT Service\MSSQL$SQL2019' for SQL Server instance 'DbServerMachine\SQL2019' must have write/modify permissions on the 'C:\temp\log scout\Test 2\output\' folder -2021-09-10 11:04:12.751 WARN The easiest way to validate write permissions on the folder is to test-run SQL LogScout for 1-2 minutes and ensure an *.XEL file exists that you can open and read in SSMS -2021-09-10 11:04:15.822 INFO Access verification Console input: y -2021-09-10 11:04:15.841 INFO LogmanConfig.txt copied to C:\temp\log scout\Test 2\output\internal\LogmanConfig.txt -2021-09-10 11:04:15.922 INFO Basic collectors will execute on shutdown -2021-09-10 11:04:15.934 INFO Collecting logs for 'GeneralPerf' scenario -2021-09-10 11:04:15.964 INFO Executing Collector: Perfmon -2021-09-10 11:04:17.055 INFO Executing Collector: Xevent_Core_AddSession -2021-09-10 11:04:17.088 INFO Executing Collector: Xevent_General_AddSession -2021-09-10 11:04:19.130 INFO Executing Collector: Xevent_General_Target -2021-09-10 11:04:19.152 INFO Executing Collector: Xevent_General_Start -2021-09-10 11:04:19.214 INFO Executing Collector: ExistingProfilerXeventTraces -2021-09-10 11:04:21.313 INFO Executing Collector: HighCPU_perfstats -2021-09-10 11:04:21.364 INFO Executing Collector: SQLServerPerfStats -2021-09-10 11:04:23.441 INFO Executing Collector: SQLServerPerfStatsSnapshotStartup -2021-09-10 11:04:23.492 INFO Executing Collector: QueryStore -2021-09-10 11:04:25.552 INFO Executing Collector: TempDBAnalysis -2021-09-10 11:04:25.601 INFO Executing Collector: linked_server_config -2021-09-10 11:04:25.708 INFO Collecting logs for 'AlwaysOn' scenario -2021-09-10 11:04:25.740 INFO Executing Collector: AlwaysOnDiagScript -2021-09-10 11:04:25.788 INFO Executing Collector: Xevent_CoreAddSesion -2021-09-10 11:04:25.809 INFO Executing Collector: Xevent_AlwaysOn_Data_Movement -2021-09-10 11:04:27.853 INFO Executing Collector: AlwaysOn_Data_Movement_target -2021-09-10 11:04:27.881 INFO Executing Collector: AlwaysOn_Data_Movement_Start -2021-09-10 11:04:27.922 INFO Executing Collector: AlwaysOnHealthXevent -2021-09-10 11:04:28.007 INFO Collecting logs for 'BackupRestore' scenario -2021-09-10 11:04:28.023 INFO Executing Collector: Xevent_BackupRestore_AddSession -2021-09-10 11:04:30.070 INFO Executing Collector: EnableTraceFlag -2021-09-10 11:04:30.088 INFO Executing collector: SetVerboseSQLVSSWriterLog -2021-09-10 11:04:30.159 WARN To enable SQL VSS VERBOSE loggging, the SQL VSS Writer service must be restarted now and when shutting down data collection. This is a very quick process. -2021-09-10 11:04:36.697 INFO Console Input: n -2021-09-10 11:04:36.705 INFO You have chosen not to restart SQLWriter Service. No verbose logging will be collected for SQL VSS Writer (2019 or later) -2021-09-10 11:04:36.737 INFO Executing Collector: VSSAdmin_Providers -2021-09-10 11:04:36.778 INFO Executing Collector: VSSAdmin_Shadows -2021-09-10 11:04:37.832 INFO Executing Collector: VSSAdmin_Shadowstorage -2021-09-10 11:04:37.873 INFO Executing Collector: VSSAdmin_Writers -2021-09-10 11:04:37.924 INFO Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue -2021-09-10 11:04:43.012 INFO StopCollection Console input: stop -2021-09-10 11:04:43.014 INFO Shutting down the collector -2021-09-10 11:04:43.032 INFO Executing shutdown command: Xevents_Stop -2021-09-10 11:04:43.073 INFO Executing shutdown command: Xevents_Alwayson_Data_Movement_Stop -2021-09-10 11:04:43.098 INFO Executing shutdown command: Disable_BackupRestore_Trace_Flags -2021-09-10 11:04:43.145 INFO Executing shutdown command: PerfmonStop -2021-09-10 11:04:46.228 INFO Executing shutdown command: KillActiveLogscoutSessions -2021-09-10 11:04:47.277 INFO Collecting logs for 'Basic' scenario -2021-09-10 11:04:47.298 INFO Executing Collector: TaskListVerbose -2021-09-10 11:04:47.339 INFO Executing Collector: TaskListServices -2021-09-10 11:04:47.407 INFO Executing Collector: FLTMC_Filters -2021-09-10 11:04:47.464 INFO Executing Collector: FLTMC_Instances -2021-09-10 11:04:47.533 INFO Executing Collector: SystemInfo_Summary -2021-09-10 11:04:47.618 INFO Executing Collector: MiscDiagInfo -2021-09-10 11:04:47.681 INFO Executing Collector: SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel -2021-09-10 11:04:50.501 INFO Executing Collector: PolybaseLogs -2021-09-10 11:04:50.533 INFO Executing Collector: SQLAssessmentAPI -2021-09-10 11:05:09.554 INFO Executing Collector: UserRights -2021-09-10 11:05:12.266 INFO Executing Collector: RunningDrivers -2021-09-10 11:05:14.217 INFO Executing Collector: PowerPlan -2021-09-10 11:05:14.308 INFO Executing Collector: WindowsHotfixes -2021-09-10 11:05:16.694 INFO Executing Collector: GetEventLogs -2021-09-10 11:05:16.707 INFO Gathering Application EventLog in TXT and CSV format -2021-09-10 11:05:23.218 INFO Produced 10000 records in the EventLog -2021-09-10 11:05:29.011 INFO Produced 20000 records in the EventLog -2021-09-10 11:05:35.914 INFO Produced 30000 records in the EventLog -2021-09-10 11:05:41.975 INFO Produced 39129 records in the EventLog -2021-09-10 11:05:41.975 INFO Application EventLog in TXT and CSV format completed! -2021-09-10 11:05:41.975 INFO Gathering System EventLog in TXT and CSV format -2021-09-10 11:05:50.913 INFO Produced 10000 records in the EventLog -2021-09-10 11:05:59.494 INFO Produced 20000 records in the EventLog -2021-09-10 11:06:04.839 INFO Produced 26007 records in the EventLog -2021-09-10 11:06:04.842 INFO System EventLog in TXT and CSV format completed! -2021-09-10 11:06:04.879 INFO Executing Collector: PerfStatsSnapshotShutdown -2021-09-10 11:06:04.888 INFO Executing collector: GetSQLVSSWriterLog -2021-09-10 11:06:04.900 INFO SQLWriter Service has been restarted -2021-09-10 11:06:04.917 INFO Waiting 3 seconds to ensure files are written to and closed by any program including anti-virus... -2021-09-10 11:06:08.518 INFO Ending data collection -2021-09-10 11:06:08.533 WARN Launching cleanup and exit routine... please wait -2021-09-10 11:06:13.780 INFO Thank you for using SQL LogScout! +2025-03-10 11:04:02.665 INFO +2025-03-10 11:04:02.676 INFO ID SQL Instance Name +2025-03-10 11:04:02.678 INFO -- ---------------- +2025-03-10 11:04:02.679 INFO 0 DbServerMachine +2025-03-10 11:04:02.679 INFO 1 DbServerMachine\SQL2014 +2025-03-10 11:04:02.686 INFO 2 DbServerMachine\SQL2017 +2025-03-10 11:04:02.686 INFO 3 DbServerMachine\SQL2019 +2025-03-10 11:04:02.686 INFO +2025-03-10 11:04:02.686 WARN Enter the ID of the SQL instance for which you want to collect diagnostic data. Then press Enter +2025-03-10 11:04:11.899 INFO SQL Instance Console input: 3 +2025-03-10 11:04:11.911 INFO You selected instance 'DbServerMachine\SQL2019' to collect diagnostic data. +2025-03-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has VIEW SERVER STATE on SQL Server Instance 'DbServerMachine\SQL2019' +2025-03-10 11:04:12.022 INFO Confirmed that MYDOMAIN\Joseph has ALTER ANY EVENT SESSION on SQL Server Instance 'DbServerMachine\SQL2019' +2025-03-10 11:04:12.735 WARN At least one of the selected 'GeneralPerf AlwaysOn BackupRestore Basic' scenarios collects Xevent traces +2025-03-10 11:04:12.751 WARN The service account 'NT Service\MSSQL$SQL2019' for SQL Server instance 'DbServerMachine\SQL2019' must have write/modify permissions on the 'C:\temp\log scout\Test 2\output\' folder +2025-03-10 11:04:12.751 WARN The easiest way to validate write permissions on the folder is to test-run SQL LogScout for 1-2 minutes and ensure an *.XEL file exists that you can open and read in SSMS +2025-03-10 11:04:15.822 INFO Access verification Console input: y +2025-03-10 11:04:15.841 INFO LogmanConfig.txt copied to C:\temp\log scout\Test 2\output\internal\LogmanConfig.txt +2025-03-10 11:04:15.922 INFO Basic collectors will execute on shutdown +2025-03-10 11:04:15.934 INFO Collecting logs for 'GeneralPerf' scenario +2025-03-10 11:04:15.964 INFO Executing Collector: Perfmon +2025-03-10 11:04:17.055 INFO Executing Collector: Xevent_Core_AddSession +2025-03-10 11:04:17.088 INFO Executing Collector: Xevent_General_AddSession +2025-03-10 11:04:19.130 INFO Executing Collector: Xevent_General_Target +2025-03-10 11:04:19.152 INFO Executing Collector: Xevent_General_Start +2025-03-10 11:04:19.214 INFO Executing Collector: ExistingProfilerXeventTraces +2025-03-10 11:04:21.313 INFO Executing Collector: HighCPU_perfstats +2025-03-10 11:04:21.364 INFO Executing Collector: SQLServerPerfStats +2025-03-10 11:04:23.441 INFO Executing Collector: SQLServerPerfStatsSnapshotStartup +2025-03-10 11:04:23.492 INFO Executing Collector: QueryStore +2025-03-10 11:04:25.552 INFO Executing Collector: TempDBAnalysis +2025-03-10 11:04:25.601 INFO Executing Collector: linked_server_config +2025-03-10 11:04:25.708 INFO Collecting logs for 'AlwaysOn' scenario +2025-03-10 11:04:25.740 INFO Executing Collector: AlwaysOnDiagScript +2025-03-10 11:04:25.788 INFO Executing Collector: Xevent_CoreAddSesion +2025-03-10 11:04:25.809 INFO Executing Collector: Xevent_AlwaysOn_Data_Movement +2025-03-10 11:04:27.853 INFO Executing Collector: AlwaysOn_Data_Movement_target +2025-03-10 11:04:27.881 INFO Executing Collector: AlwaysOn_Data_Movement_Start +2025-03-10 11:04:27.922 INFO Executing Collector: AlwaysOnHealthXevent +2025-03-10 11:04:28.007 INFO Collecting logs for 'BackupRestore' scenario +2025-03-10 11:04:28.023 INFO Executing Collector: Xevent_BackupRestore_AddSession +2025-03-10 11:04:30.070 INFO Executing Collector: EnableTraceFlag +2025-03-10 11:04:30.088 INFO Executing collector: SetVerboseSQLVSSWriterLog +2025-03-10 11:04:30.159 WARN To enable SQL VSS VERBOSE loggging, the SQL VSS Writer service must be restarted now and when shutting down data collection. This is a very quick process. +2025-03-10 11:04:36.697 INFO Console Input: n +2025-03-10 11:04:36.705 INFO You have chosen not to restart SQLWriter Service. No verbose logging will be collected for SQL VSS Writer (2019 or later) +2025-03-10 11:04:36.737 INFO Executing Collector: VSSAdmin_Providers +2025-03-10 11:04:36.778 INFO Executing Collector: VSSAdmin_Shadows +2025-03-10 11:04:37.832 INFO Executing Collector: VSSAdmin_Shadowstorage +2025-03-10 11:04:37.873 INFO Executing Collector: VSSAdmin_Writers +2025-03-10 11:04:37.924 INFO Please type 'STOP' to terminate the diagnostics collection when you finished capturing the issue. +2025-03-10 11:04:37.924 INFO You can type 'StopFile' and wait for the presence of a '\internal\logscout.stop' file to automatically end the diagnostics collection. +2025-03-10 11:04:43.012 INFO StopCollection Console input: stop +2025-03-10 11:04:43.014 INFO Shutting down the collector +2025-03-10 11:04:43.032 INFO Executing shutdown command: Xevents_Stop +2025-03-10 11:04:43.073 INFO Executing shutdown command: Xevents_Alwayson_Data_Movement_Stop +2025-03-10 11:04:43.098 INFO Executing shutdown command: Disable_BackupRestore_Trace_Flags +2025-03-10 11:04:43.145 INFO Executing shutdown command: PerfmonStop +2025-03-10 11:04:46.228 INFO Executing shutdown command: KillActiveLogscoutSessions +2025-03-10 11:04:47.277 INFO Collecting logs for 'Basic' scenario +2025-03-10 11:04:47.298 INFO Executing Collector: TaskListVerbose +2025-03-10 11:04:47.339 INFO Executing Collector: TaskListServices +2025-03-10 11:04:47.407 INFO Executing Collector: FLTMC_Filters +2025-03-10 11:04:47.464 INFO Executing Collector: FLTMC_Instances +2025-03-10 11:04:47.533 INFO Executing Collector: SystemInfo_Summary +2025-03-10 11:04:47.618 INFO Executing Collector: MiscDiagInfo +2025-03-10 11:04:47.681 INFO Executing Collector: SQLErrorLogs_AgentLogs_SystemHealth_MemDumps_FciXel +2025-03-10 11:04:50.501 INFO Executing Collector: PolybaseLogs +2025-03-10 11:04:50.533 INFO Executing Collector: SQLAssessmentAPI +2025-03-10 11:05:09.554 INFO Executing Collector: UserRights +2025-03-10 11:05:12.266 INFO Executing Collector: RunningDrivers +2025-03-10 11:05:14.217 INFO Executing Collector: PowerPlan +2025-03-10 11:05:14.308 INFO Executing Collector: WindowsHotfixes +2025-03-10 11:05:16.694 INFO Executing Collector: GetEventLogs +2025-03-10 11:05:16.707 INFO Gathering Application EventLog in TXT and CSV format +2025-03-10 11:05:23.218 INFO Produced 10000 records in the EventLog +2025-03-10 11:05:29.011 INFO Produced 20000 records in the EventLog +2025-03-10 11:05:35.914 INFO Produced 30000 records in the EventLog +2025-03-10 11:05:41.975 INFO Produced 39129 records in the EventLog +2025-03-10 11:05:41.975 INFO Application EventLog in TXT and CSV format completed! +2025-03-10 11:05:41.975 INFO Gathering System EventLog in TXT and CSV format +2025-03-10 11:05:50.913 INFO Produced 10000 records in the EventLog +2025-03-10 11:05:59.494 INFO Produced 20000 records in the EventLog +2025-03-10 11:06:04.839 INFO Produced 26007 records in the EventLog +2025-03-10 11:06:04.842 INFO System EventLog in TXT and CSV format completed! +2025-03-10 11:06:04.879 INFO Executing Collector: PerfStatsSnapshotShutdown +2025-03-10 11:06:04.888 INFO Executing collector: GetSQLVSSWriterLog +2025-03-10 11:06:04.900 INFO SQLWriter Service has been restarted +2025-03-10 11:06:04.917 INFO Waiting 3 seconds to ensure files are written to and closed by any program including anti-virus... +2025-03-10 11:06:08.518 INFO Ending data collection +2025-03-10 11:06:08.533 WARN Launching cleanup and exit routine... please wait +2025-03-10 11:06:13.780 INFO Thank you for using SQL LogScout! Checking for console execution errors logged into .\##STDERR.LOG... Removed .\##STDERR.LOG which was 0 bytes @@ -948,4 +1067,54 @@ xecuting 'PerfmonStop'. It will stop Perfmon started by SQL LogScout in case it Executing 'NetworkTraceStop'. It will stop network tracing initiated by SQLLogScout in case it was found to be running... Cleanup script execution completed. PS C:\SQL LogScout\Bin> -``` \ No newline at end of file +``` + +# How to connect to and collect data from Windows Internal Database (WID) + +WID uses a modified version of SQL Server and has some limitations or behaves differently. SQL LogScout has been adapted to support WID with some lmitations: + +1. Doesn't connect with encryption because WID doesn't support encryption (less of a concern since connection is local). You will get an error message initially that a connection fails, but it would eventually succeed to connect. +1. Cannot use the SQL LogScout GUI because an client alias must be created. You can use command line only with ServerName specified explicitly. +1. Might not collect WID errorlogs unless you create a specific connection alias (see the [steps](#steps-to-collect-data-with-sql-logscout-on-wid) below) + +## Steps to collect data with SQL LogScout on WID + +1. Open Services app (services.msc) on Windows and find the **Windows Internal Database** service +1. Under the General tab, find the **Path to executable** and copy the WID instance name that appears after the -S parameter. Most commonly it is **MSWIN8.SQLWID** +1. Close Serivces app +1. Open SQL Client Network Utility (cliconfg.exe) and define an alias to the custom WID named pipe `np:\\.\pipe\MICROSOFT##WID\tsql\query`. Use the WiD instance you found, as a name in **Server alias**. For example use `MSWIN8.SQLWID` + + - Start->Run->Cliconfg.exe + - Click Add to create a new alias. + - In the Server alias field, enter the instance name you discovered in prior steps: `MSWIN8.SQLWID`. + - In the Network libraries section, select Named Pipes. + - In the Pipe Name section, enter `\\.\pipe\MICROSOFT##WID\tsql\query` + +1. Alternatively, you can use [SQL Server Configuration Manager](https://learn.microsoft.com/sql/relational-databases/sql-server-configuration-manager) to create an alias. For more information, see [Create or delete a server alias for use by a client](https://learn.microsoft.com/sql/database-engine/configure-windows/create-or-delete-a-server-alias-for-use-by-a-client) and [Aliases - Named Pipes connections](https://learn.microsoft.com/sql/tools/configuration-manager/aliases-sql-server-configuration-manager#named-pipes-connections) + +1. Then run SQL LogScout with that alias. For example + + ```PowerShell + .\SQL_LogScout.ps1 -ServerName "MSWIN8.SQLWID" -Scenario "GeneralPerf" + ``` + +1. You will get connection errors when trying to connect with a ODBC driver using encryption, but after a few attempts, an unencrypted connection succeeds. The output may look like this: + + ```output + 2025-01-08 00:14:31.229 WARN Could not connect to SQL Server + 2025-01-08 00:14:31.229 ERROR Function 'getSQLConnection' failed with error: Exception calling "Open" with "0" argument(s): "ERROR [08001] [Microsoft][ODBC Driver 17 for SQL Server]Encryption not supported on SQL Server. + ERROR [08001] [Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection + ERROR [01S00] [Microsoft][ODBC Driver 17 for SQL Server]Invalid connection string attribute" (line: 628, offset: 13, file: C:\Tools\SQLLogScout\Bin\CommonFunctions.psm1) + 2025-01-08 00:14:31.276 WARN Could not connect to SQL Server + 2025-01-08 00:14:31.276 ERROR Function 'getSQLConnection' failed with error: Exception calling "Open" with "0" argument(s): "ERROR [08001] [Microsoft][SQL Server Native Client 11.0]Encryption not supported on SQL Server. + ERROR [08001] [Microsoft][SQL Server Native Client 11.0]Client unable to establish connection + ERROR [01S00] [Microsoft][SQL Server Native Client 11.0]Invalid connection string attribute" (line: 628, offset: 13, file: C:\Tools\SQLLogScout\Bin\CommonFunctions.psm1) + 2025-01-08 00:14:31.307 WARN ********************************************************************** + 2025-01-08 00:14:31.323 WARN * SQL LogScout is switching to the classic SQL Server ODBC driver. + 2025-01-08 00:14:31.323 WARN * Thus, this local connection is unencrypted to ensure it is successful + 2025-01-08 00:14:31.323 WARN * To exit without collecting LogScout press Ctrl+C + 2025-01-08 00:14:31.323 WARN ********************************************************************** + 2025-01-08 00:14:37.489 INFO Confirmed that WIN2022SQL1\Administrator has VIEW SERVER STATE on SQL Server Instance 'MSWIN8.SQLWID' + 2025-01-08 00:14:37.489 INFO Confirmed that WIN2022SQL1\Administrator has ALTER ANY EVENT SESSION on SQL Server Instance 'MSWIN8.SQLWID' + 2025-01-08 00:14:37.489 INFO Confirmed that SQL Server Instance WIDAlias can write Extended Event Session Target at C:\Tools\SQLLogScout\output\WIDAlias_20250108T0014373961_xevent_LogScout_target_test.xel + ```