-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathServerHealthCheck_Grid2.ps1
185 lines (150 loc) · 5.85 KB
/
ServerHealthCheck_Grid2.ps1
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Clear-Host
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
[int]$numOfPerfmonCollections = 2
[int]$intervalOfCollections = 2
## Counters to collect ##
$physicalcounters = ("\Memory\Available MBytes") `
,("\PhysicalDisk(_Total)\Avg. Disk sec/Read")`
,("\PhysicalDisk(_Total)\Avg. Disk sec/Write") `
,("\Processor(_Total)\% Processor Time")
## SQL Counter template ([instancekey] is replaced with instance name in Get-SQLCounters Function)
$sqlCounterTemplate = ("\[instancekey]:SQL Statistics\Batch Requests/sec") `
,("\[instancekey]:Access Methods\Workfiles Created/sec")`
,("\[instancekey]:Buffer Manager\Page life expectancy")
# Creates an new array with a SQLInstance specific list of counters
# "\[instancekey]:Buffer Manager\Page life expectancy"
function Get-SQLCounters{
param([string] $SQLServerToMonitor, $counters)
$counterArray = @() # holds the instance specific counters array to pass into get-counter
# Generate a counter path friendly name (SQLServer (default instance) or MSSQL$InstanceName)
[int]$instPos = $SQLServerToMonitor.IndexOf("\");
if($instPos -gt 0){
$instPos += 1;
$instancekey = "MSSQL$" + $SQLServerToMonitor.Substring($instPos,($SQLServerToMonitor.Length - $instPos))
} else { # Default Instance
$instancekey = "SQLServer"
}
## Rebuilds Counter array with SQL Specific counters
foreach($cnter in $counters) {
$counterArray += $cnter.Replace("[instancekey]",$instancekey)
}
return $counterArray;
}
## Based on a Chad Miller script
function Invoke-Sqlcmd3
{
param(
[string]$ServerInstance,
[string]$Query
)
$QueryTimeout=30
$conn=new-object System.Data.SqlClient.SQLConnection
$constring = "Server=" + $ServerInstance + ";Integrated Security=True"
$conn.ConnectionString=$constring
$conn.Open()
if($conn){
$cmd=new-object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout=$QueryTimeout
$ds=New-Object system.Data.DataSet
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$conn.Close()
$ds.Tables[0]
}
}
### ********** ###
### Begin Code ###
$server = Read-Host -Prompt "Specify a server"
# Get a DateTime to use for filtering
[int]$hourThreshold = Read-Host -Prompt "Number of Hours to Check in Logs"
[datetime] $DatetoCheck = (Get-Date).AddHours(-1 * $hourThreshold)
[string]$sysprocessQuery = @"
SELECT spid,blocked,open_tran,waittime,lastwaittype,waitresource,dbid
,cpu,physical_io,memusage,hostname
FROM master..sysprocesses
WHERE blocked != 0
order by spid
"@
if(Test-Connection -ComputerName $server)
{
Write-Host "$server pinged successfully"
} else {
Write-Host "$server could not be pinged!"
break;
}
#Grab SQL Services
$SQLServices = Get-WmiObject -ComputerName $server win32_service |
Where-Object {$_.name -like "*SQL*" } |
Select-Object Name,StartMode,State,Status
if($SQLServices.Count -gt 0) {
$SQLServices | Out-GridView -Title "$server SQL Services Information"
}
# Grab OS counters and add to SQL Counter array for single grid output.
Write-Host "Reading OS Perf Counters...."
try{
$sqlCounters = Get-Counter -ComputerName $server -Counter $physicalcounters `
-MaxSamples $numOfPerfmonCollections -SampleInterval $intervalOfCollections
} catch {
Write-Host "Problem Reading Perf Counters" + $Error
}
# Check each SQL Service (not Agent, etc) gather information
Foreach($sqlService in $SQLServices |
Where-Object{$_.name -like "MSSQL$*" -or $_.name -eq "MSSQLSERVER"} |
Where-Object{$_.State -eq "Running" } )
{
[string]$sqlServerName = $sqlService.Name
$sqlServerName = $sqlServerName.Replace("MSSQL$","$server\")
$sqlServerName = $sqlServerName.Replace("MSSQLSERVER","$server")
Write-host "Checking $sqlServerName"
$sqlServer = New-Object("Microsoft.SqlServer.Management.Smo.Server") $sqlServerName
# Grab any blocking processes
try{
$tbl = Invoke-Sqlcmd3 -Query $sysprocessQuery -ServerInstance $sqlServerName |
Where-Object {$_.blocked -ne "0"} |
Out-GridView -Title "$sqlServerName Blocked Processes"
}
catch{
Write-Host "Problem Reading SysProcesses" + $Error
}
#
Write-Host "Reading SQL Log for $sqlServerName"
try{
$sqlServer.ReadErrorLog() | Where{$_.LogDate -is [datetime] } |
Where-Object{$_.LogDate -gt $DatetoCheck } |
Where-Object{$_.Text -like "*Error*" -or $_.Text -like "*Fail*"} |
Select-Object LogDate,Text |
Out-GridView -Title "$sqlServerName Log Errors"
} catch {
Write-Host "Error Reading $sqlServer.Name"
}
# Get SQL Instance specific counter array and build up array $sqlCounters to store for all instances
try{
$sqlInstanceCounters = Get-SQLCounters -SQLServerToMonitor $sqlServerName -counters $sqlCounterTemplate
} catch {
Write-Host "Error Building SQL Counter Template $_"
}
try{
$sqlCounters += Get-Counter -ComputerName $server -Counter $sqlInstanceCounters `
-MaxSamples $numOfPerfmonCollections -SampleInterval $intervalOfCollections
} catch {
Write-Host "Error getting SQL Counters $_"
}
} # end of SQL instances loop
# Push counters to grid
$sqlCounters | ForEach-Object{ $_.CounterSamples | Select-Object Path, CookedValue } |
Out-GridView -Title "$sqlServer Perfmon Counters"
try{
Write-Host "Reading Event Logs..."
# Check Server System and Application Event Logs
$systemLog = Get-EventLog -ComputerName $server `
-EntryType "Error" -LogName "System" -After $DatetoCheck |
Select-Object TimeGenerated,Source,Message
$appLog = Get-EventLog -ComputerName $server `
-EntryType "Error" -LogName "Application" -After $DatetoCheck |
Select-Object TimeGenerated,Source,Message
if($systemLog.Count -gt 0) {$serverLogs += $systemLog}
if($appLog.Count -gt 0) {$serverLogs += $appLog}
if($serverLogs.Count -gt 0) { $serverLogs | Out-GridView -Title "$server Event Logs" }
} catch {
Write-Host "Problem Reading Server Event Logs:" + $Error
}