' Parameters that should be passed to this script
' 0 CPU_PERCENTAGE_THRESHOLD
' 1 CPU_QUEUELEN_THRESHOLD
' 2 Computer (FQDN) that the Mount Point will be hosted on
Option Explicit
SetLocale("en-us")
'******************************************************************************
Sub CreateEvent(oAPI, lEventID, lEventType, strMessage)
'
' Purpose: To generate a MOM event
'
' Arguments: lEventID, the event code
' lEventType, the severity of the event
' strMessage, the message to include in the event
'
On Error Resume Next
oAPI.LogScriptEvent "Base OS Client", lEventID, lEventType, strMessage
End Sub
Dim TargetComputer
Call Main
Sub Main()
Dim CPU_PERCENTAGE_THRESHOLD, CPU_QUEUELEN_THRESHOLD, CPU_USAGE
Dim oAPI, oBag
Set oAPI = MOMCreateObject("MOM.ScriptAPI")
If Err.number <> 0 Or IsNull(oAPI) or IsEmpty(oAPI) Then
ThrowScriptError "Error While Creating ScriptAPI object", Err
Exit Sub
End If
'CreateEvent oAPI, 234, 1, "Just Before the Event Launch " & oArgs.Count
set oBag = oAPI.CreatePropertyBag()
If Err.number <> 0 Or IsNull(oBag) or IsEmpty(oBag) Then
ThrowScriptError "Error While Creating PropertyBag object", Err
Exit Sub
End If
Dim oArgs
Set oArgs = WScript.Arguments
if oArgs.Count <> 4 Then
Dim ArgIterCounter
Dim ArgumentsString
ArgumentsString = ""
For ArgIterCounter = 0 to oArgs.Count - 1
ArgumentsString = ArgumentsString & oArgs(ArgIterCounter)
Next
CreateEvent oAPI, 134, 1, " Wrong Number of Arguments " & oArgs.Count & "Argument String " & ArgumentsString
Quit()
End If
'CreateEvent oAPI, 144, 1, " Last Argument is " & oArgs.Count & "Argument String " & oArgs(3)
CPU_PERCENTAGE_THRESHOLD = oArgs(0)
CPU_QUEUELEN_THRESHOLD = oArgs(1)
TargetComputer = oArgs(2)
CPU_USAGE = oArgs(3)
Dim oWMI, lNumProcessors, nQueueLength
' Fetch number of processors on the box
Set oWMI = GetObject("winmgmts://" & TargetComputer)
lNumProcessors = GetNumProcessors()
If CDbl(CPU_USAGE) < 0 Or (CDbl(CPU_USAGE) - CDbl(CPU_PERCENTAGE_THRESHOLD)) < 0 Then
' Submit the state to be Green
oBag.AddValue "State", "GOOD"
oBag.AddValue "QueueLength", 0 & ""
oBag.AddValue "PctUsage", CPU_USAGE & ""
oAPI.AddItem oBag
oAPI.ReturnItems
Exit Sub
End If
'
' Sample the queue length. If we exceed threshold, then we will wait and sample agian
' to avoid sampling a cpu spike, both have exceeded, then we have a runaway cpu.
'
nQueueLength = GetCpuQueueLength(oWMI)
'WScript.echo "Queue Length is " & nQueueLength
If nQueueLength > CLng(CPU_QUEUELEN_THRESHOLD) * lNumProcessors Then
WScript.Sleep(500)
nQueueLength = GetCpuQueueLength(oWMI)
'WScript.echo "Queue Length is " & nQueueLength
If nQueueLength > CLng(CPU_QUEUELEN_THRESHOLD) * lNumProcessors Then
'WScript.echo "Queue Length is greter check pass "
If nQueueLength = 999 Then
' We need to throw a script error
ThrowScriptError "Nothing. Queue length was not available", Err
'WScript.echo "Queue Length is greter check pass "
Else
oBag.AddValue "State", "BAD"
oBag.AddValue "QueueLength", nQueueLength & ""
oBag.AddValue "PctUsage", CPU_USAGE & ""
oAPI.AddItem oBag
oAPI.ReturnItems
Exit Sub
End If
End If
End If
oBag.AddValue "State", "GOOD"
oBag.AddValue "QueueLength", nQueueLength & ""
oBag.AddValue "PctUsage", CPU_USAGE & ""
oAPI.AddItem oBag
oAPI.ReturnItems
'Exit Sub
End Sub
Function GetCPUUsage(oWMI)
Dim oSystem, oSystems
Set oSystems = oWMI.ExecQuery("SELECT * FROM Win32_PerfRawData_PerfOS_Processor where Name='_Total'")
Dim FirstSample
FirstSample = 0
Dim TimeStamp1
On Error Resume Next
For Each oSystem in oSystems
If oSystem.Name = "_Total" Then
FirstSample = oSystem.PercentProcessorTime
TimeStamp1 = oSystem.TimeStamp_Sys100NS
Exit For
End If
Next
If Err.Number <> 0 Or FirstSample = 0 Then
ThrowScriptError "Error While Fetching the Counter", Err
GetCPUUsage = 999
Err.Clear
Exit Function
End If
Wscript.Sleep(500)
Dim SecondSample, TimeStamp2
SecondSample = 0
Set oSystems = oWMI.ExecQuery("SELECT * FROM Win32_PerfRawData_PerfOS_Processor where Name='_Total'")
For Each oSystem in oSystems
If oSystem.Name = "_Total" Then
SecondSample = oSystem.PercentProcessorTime
TimeStamp2 = oSystem.TimeStamp_Sys100NS
Exit For
End If
Next
If Err.Number <> 0 Or SecondSample = 0 Then
ThrowScriptError "Error While Fetching the Counter", Err
GetCPUUsage = 999
Err.Clear
Exit Function
End If
GetCPUUsage = (1 - ((SecondSample - FirstSample)/(TimeStamp2 - TimeStamp1)))*100
On Error Goto 0
End Function
Function ListCriticalProcesses(oWMI, lNumProcessors)
' Work out which processes are using > 10% CPU at the moment by taking
' a snapshot of the rawdata PercentProcessorTimecounter, then wait
' a couple of seconds, and take another snapshot and working out what the
' difference is. Divide this by the period (calculated using the Timestamp_Sys100NS
' counter) and that gives the % CPU over the 2 second interval.
On Error Resume Next
End Function
Function GetCpuQueueLength(oWMI)
Dim oSystem, oSystems
Set oSystems = oWMI.ExecQuery("SELECT * FROM Win32_PerfRawData_PerfOS_System")
On Error Resume Next
For Each oSystem in oSystems
GetCpuQueueLength = oSystem.ProcessorQueueLength
Exit For
Next
If Err.Number <> 0 Then
'
' If an error occurs, ensure that we will check agian or alert
' by making sure the queue length exceeds the threshold. We
' already know that the CPU has exceed its threshold for
' the sampled interval (default: 5 min for 6 samples)
' so we will error on the side of caution.
'
GetCpuQueueLength = 999
End If
On Error Goto 0
End Function
' Number of CPUs Registry Key
Const HKEY_LOCAL_MACHINE = &h80000002
Const REGPATH_NUMBER_OF_CPUS = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment\"
Const REGKEY_NUMBER_OF_CPUS = "NUMBER_OF_PROCESSORS"
Function GetNumProcessors()
Dim oReg, sValue
Set oReg = WMIGetObject("winmgmts://" & TargetComputer & "/root/default:StdRegProv")
oReg.GetStringValue HKEY_LOCAL_MACHINE, REGPATH_NUMBER_OF_CPUS, REGKEY_NUMBER_OF_CPUS, sValue
GetNumProcessors = sValue
End Function
Function ThrowScriptErrorNoAbort(ByVal sMessage, ByVal oErr)
'
' ThrowScriptError :: Creates an event and sends it back to the mom server
'
'
Dim sErrDescription, sErrNumber
sErrDescription = oErr.Description
sErrNumber = oErr.Number
Wscript.echo "Error Message is " & sErrDescription & " Error number is " & sErrNumber
End Function
Function ThrowScriptError(Byval sMessage, ByVal oErr)
'
' ThrowScriptError :: Creates an event and sends it back to the mom server
'
'
On Error Resume Next
ThrowScriptErrorNoAbort sMessage, oErr
Quit()
End Function
Function WMIGetObject(ByVal sNamespace)
'
' WMIGetObject :: Returns the WMI object requested.
'
'
Dim oWMI
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
Set WMIGetObject = oWMI
End Function
Function WMIGetInstance(ByVal sNamespace, ByVal sInstance)
'
' WMIGetInstance :: Returns WMI Instance requested.
'
'
Dim oWMI, oInstance, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
On Error Resume Next
Set oInstance = oWMI.InstancesOf(sInstance)
e.Save
On Error Goto 0
If IsEmpty(oInstance) Or e.Number <> 0 Then
ThrowScriptError "The class name '" & sInstance & "' returned no instances. Please check to see if this is a valid WMI class name.", e
End If
'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oInstance.Count
e.Save
On Error Goto 0
If e.Number <> 0 Then
ThrowScriptError "The class name '" & sInstance & "' did not return any valid instances. Please check to see if this is a valid WMI class name.", e
End If
Set WMIGetInstance = oInstance
End Function
Function WMIExecQuery(ByVal sNamespace, ByVal sQuery)
'
' WMIExecQuery :: Executes the WMI query and returns the result set.
'
'
Dim oWMI, oQuery, nInstanceCount
Dim e
Set e = New Error
On Error Resume Next
Set oWMI = GetObject(sNamespace)
e.Save
On Error Goto 0
If IsEmpty(oWMI) Then
ThrowScriptError "Unable to open WMI Namespace '" & sNamespace & "'. Check to see if the WMI service is enabled and running, and ensure this WMI namespace exists.", e
End If
On Error Resume Next
Set oQuery = oWMI.ExecQuery(sQuery)
e.Save
On Error Goto 0
If IsEmpty(oQuery) Or e.Number <> 0 Then
ThrowScriptError "The Query '" & sQuery & "' returned an invalid result set. Please check to see if this is a valid WMI Query.", e
End If
'Determine if we queried a valid WMI class - Count will return 0 or empty
On Error Resume Next
nInstanceCount = oQuery.Count
e.Save
On Error Goto 0
If e.Number <> 0 Then
ThrowScriptError "The Query '" & sQuery & "' did not return any valid instances. Please check to see if this is a valid WMI Query.", e
End If
Set WMIExecQuery = oQuery
End Function
Function WMIGetInstanceNoAbort(ByVal sNamespace, ByVal sInstance)
'
' WMIGetInstanceNoAbort :: Returns WMI Instance requested.
'
'
Dim oWMI, oInstance, nInstanceCount
On Error Resume Next
Set oWMI = GetObject(sNamespace)
If Not IsEmpty(oWMI) Then
Set oInstance = oWMI.InstancesOf(sInstance)
If Not IsEmpty(oInstance) And Err.Number = 0 Then
'Determine if we queried a valid WMI class - Count will return 0 or empty
nInstanceCount = oInstance.Count
If Err.Number = 0 Then
Set WMIGetInstanceNoAbort = oInstance
Exit Function
End If
End If
End If
On Error Goto 0
Set WMIGetInstanceNoAbort = Nothing
End Function
Function GetWMIProperty(oWmi, sPropName, nCIMType, ErrAction)
Dim sValue, oWmiProp
If Not IsValidObject(oWmi) Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
ThrowScriptErrorNoAbort "Accessing property on invalid WMI object.", Err
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then _
Quit()
GetWMIProperty = ""
Exit Function
End If
On Error Resume Next
Set oWmiProp = oWmi.Properties_.Item(sPropName)
If Err.Number <> 0 Then
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" & sPropName & "'.", Err
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then _
Quit()
End If
On Error Goto 0
If IsValidObject(oWmiProp) Then
sValue = oWmiProp.Value
If IsNull(sValue) Then
'
' If value is null, return blank to avoid any issues
'
GetWMIProperty = ""
Else
Select Case (oWmiProp.CIMType)
Case wbemCimtypeString, wbemCimtypeSint16, wbemCimtypeSint32, wbemCimtypeReal32, wbemCimtypeReal64, wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeUint16, wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64:
If Not oWmiProp.IsArray Then
GetWMIProperty = Trim(CStr(sValue))
Else
GetWMIProperty = Join(sValue, ", ")
End If
Case wbemCimtypeBoolean:
If sValue = 1 Or UCase(sValue) = "TRUE" Then
GetWMIProperty = "True"
Else
GetWMIProperty = "False"
End If
Case wbemCimtypeDatetime:
Dim sTmpStrDate
'
' First attempt to convert the whole wmi date string
'
sTmpStrDate = Mid(sValue, 5, 2) & "/" & _
Mid(sValue, 7, 2) & "/" & _
Left(sValue, 4) & " " & _
Mid (sValue, 9, 2) & ":" & _
Mid(sValue, 11, 2) & ":" & _
Mid(sValue, 13, 2)
If IsDate(sTmpStrDate) Then
GetWMIProperty = CDate(sTmpStrDate)
Else
'
' Second, attempt just to convert the YYYYMMDD
'
sTmpStrDate = Mid(sValue, 5, 2) & "/" & _
Mid(sValue, 7, 2) & "/" & _
Left(sValue, 4)
If IsDate(sTmpStrDate) Then
GetWMIProperty = CDate(sTmpStrDate)
Else
'
' Nothing works - return passed in string
'
GetWMIProperty = sValue
End If
End If
Case Else:
GetWMIProperty = ""
End Select
End If
Else
If (ErrAction And ErrAction_ThrowError) = ErrAction_ThrowError Then _
ThrowScriptErrorNoAbort "An error occurred while accessing WMI property: '" & sPropName & "'.", Err
If (ErrAction And ErrAction_Abort) = ErrAction_Abort Then _
Quit()
GetWMIProperty = ""
End If
If (ErrAction And ErrAction_Trace) = ErrAction_Trace Then _
WScript.Echo " + " & sPropName & " :: '" & GetWMIProperty & "'"
End Function
Class Error
Private m_lNumber
Private m_sSource
Private m_sDescription
Private m_sHelpContext
Private m_sHelpFile
Public Sub Save()
m_lNumber = Err.number
m_sSource = Err.Source
m_sDescription = Err.Description
m_sHelpContext = Err.HelpContext
m_sHelpFile = Err.helpfile
End Sub
Public Sub Raise()
Err.Raise m_lNumber, m_sSource, m_sDescription, m_sHelpFile, m_sHelpContext
End Sub
Public Sub Clear()
m_lNumber = 0
m_sSource = ""
m_sDescription = ""
m_sHelpContext = ""
m_sHelpFile = ""
End Sub
Public Default Property Get Number()
Number = m_lNumber
End Property
Public Property Get Source()
Source = m_sSource
End Property
Public Property Get Description()
Description = m_sDescription
End Property
Public Property Get HelpContext()
HelpContext = m_sHelpContext
End Property
Public Property Get HelpFile()
HelpFile = m_sHelpFile
End Property
End Class
Function MomCreateObject(ByVal sProgramId)
Dim oError
Set oError = New Error
On Error Resume Next
Set MomCreateObject = CreateObject(sProgramId)
oError.Save
On Error Goto 0
If oError.Number <> 0 Then ThrowScriptError "Unable to create automation object '" & sProgramId & "'", oError
End Function
Function IsValidObject(ByVal oObject)
IsValidObject = False
If IsObject(oObject) Then
If Not oObject Is Nothing Then
IsValidObject = True
End If
End If
End Function </Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
<ConditionDetection ID="FilterOK" TypeID="System!System.ExpressionFilter">
<Expression>
<RegExExpression>
<ValueExpression>
<XPathQuery>Property[@Name='State']</XPathQuery>
</ValueExpression>
<Operator>ContainsSubstring</Operator>
<Pattern>GOOD</Pattern>
</RegExExpression>
</Expression>
</ConditionDetection>
<ConditionDetection ID="FilterNotOK" TypeID="System!System.ExpressionFilter">
<Expression>
<RegExExpression>
<ValueExpression>
<XPathQuery>Property[@Name='State']</XPathQuery>
</ValueExpression>
<Operator>ContainsSubstring</Operator>
<Pattern>BAD</Pattern>
</RegExExpression>
</Expression>
</ConditionDetection>
</MemberModules>
<RegularDetections>
<RegularDetection MonitorTypeStateID="CPUUtilizationNormal">
<Node ID="FilterOK">
<Node ID="ProbeActionDS">
<Node ID="DS1"/>
</Node>
</Node>
</RegularDetection>
<RegularDetection MonitorTypeStateID="CPUUtilizationHigh">
<Node ID="FilterNotOK">
<Node ID="ProbeActionDS">
<Node ID="DS1"/>
</Node>
</Node>
</RegularDetection>
</RegularDetections>
</MonitorImplementation>
</UnitMonitorType>