CPU Utilization Active Monitor (SNMP Polling)

' NAME: Average CPU Utilization

 ' AUTHOR: Jason Alberino, Ipswitch, Inc.

 ' DATE: 05/06/2015

 Option Explicit

 '*****Configuration*****

 Dim nThreshold : nThreshold = 95 'CPU Usage Percentage threshold

 Dim sCPULoadAttrib : sCPULoadAttrib = "CPULoad" 'Set the name of the CPU usage device attribute. Default is "CPULoad". This attribute is populated with the CPU usage information

 Dim nSNMPTimeout : nSNMPTimeout = 3000 'Set ms for SNMP timeouts

 Dim nSNMPRetry : nSNMPRetry = 2 'Set the number of SNMP retries

 '***End Configuration***

 'Get Device details

 Dim nDeviceID : nDeviceID = Context.GetProperty("DeviceID")

 Dim sAddress : sAddress = Context.GetProperty("Address")

 'Create SNMP object

 Dim oSnmp : Set oSnmp = CreateObject("CoreAsp.SnmpRqst")

 Dim nTimeout : nTimeout = oSnmp.SetTimeoutMs(nSNMPTimeout)

 Dim nRetries : nRetries = oSnmp.SetNumRetries(nSNMPRetry)

 'Create DB connection

 Dim oDb : Set oDb = Context.GetDB

 'Set script variables

 Dim bSNMPResult : bSNMPResult = 0

 Dim bFail : bFail = 0

 Dim bDown : bDown = 0

 Dim sErrorMsg : sErrorMsg = ""

 Dim sMsg : sMsg = ""

 Dim nCount : nCount = 0

 Dim sHRProcessorLoad : sHRProcessorLoad = "1.3.6.1.2.1.25.3.3.1.2" 'Type: Integer

 'Access: Read Only

 'Description: The average, over the last minute, of the percentage of time that this processor was not idle.

 'Label: iso.org.dod.internet.mgmt.mib-2.host.hrDevice.hrProcessorTable.hrProcessorEntry.hrProcessorLoad

 TestSNMP bFail, sErrorMsg, bSNMPResult

 SNMPLoop bFail, sErrorMsg, bSNMPResult, sHRProcessorLoad, sMsg, bDown

 SetResults bFail, sErrorMsg, bSNMPResult, bDown, sMsg

 Sub SNMPLoop(ByRef bFail, ByRef sErrorMsg, ByRef bSNMPResult, sOIDtoLoop, ByRef sMsg, ByRef bDown)

 Dim sSNMPValue, rc, sInstance, sOIDCore, aInstance, sValue, sFinalValue

 If bFail = 0 And bSNMPResult = 0 Then

 sValue = 0

 'Begin SNMP GetNext Loop

 Do

 Set rc = oSnmp.GetNext(sOIDtoLoop)

 If rc.Failed Then

 sErrorMsg = sErrorMsg & rc.GetErrorMsg

 bSNMPResult = 1

 Exit Do

 Else

 'Uncomment below to see what OIDs get returned

 'Context.Logmessage "OID: " & rc.GetOID

 sOIDtoLoop = rc.GetOID

 sInstance = rc.GetOIDInstance

 sOIDCore = rc.GetOIDCore

 End If

 If InStr(sOIDCore, "1.3.6.1.2.1.25.3.3.1.2") = 0 Then

 Exit Do

 Else

 sSNMPValue = GetSNMPVal(sOIDtoLoop, bFail, sErrorMsg)

 'Context.LogMessage "Instance:"&sInstance & " has a load of " & sSNMPValue & "%"

 nCount = nCount + 1

 sValue = sValue + sSNMPValue

 End If

 Loop Until InStr(sOIDCore, "1.3.6.1.2.1.25.3.3.1.2") = 0

 sFinalValue = CDbl(sValue/nCount)

 sFinalValue = Round(sFinalValue, 2)

 sMsg = sFinalValue & "%"

 PutDevAttr nDeviceID, sCPULoadAttrib, sMsg

 If sFinalValue => nThreshold Then bDown = 1

 End If

 End Sub

 Sub SetResults(ByRef bFail, ByRef sErrorMsg, ByRef bSNMPResult, ByRef bDown, ByRef sMsg)

 'Set result based on errors

 Dim bResultSet : bResultSet = 0

 If bSNMPResult = 1 Then

 bResultSet = 1

 Context.SetResult 1, "Error: " & sErrorMsg

 Else

 If bFail = 1 Then

 If sErrorMsg = "No Such object" Then

 bResultSet = 1

 Context.LogMessage "Down!"

 Context.SetResult 1, "Cannot find the SNMP object"

 ElseIf sErrorMsg = "Timeout" Then

 bResultSet = 1

 Context.LogMessage "Down!"

 Context.SetResult 1, "SNMP intilization timed out"

 ElseIf sErrorMsg <> "No Such object" And sErrorMsg <> "Timeout" Then

 bResultSet = 1

 Context.LogMessage "Down!"

 Context.SetResult 1, "There was a SNMP error" & vbCrLf & "Error: " & sErrorMsg

 End If

 Else

 End If

 End If

 'Set Up or Down

 If bResultSet = 0 Then

 If bDown = 1 Then

 Context.LogMessage "DOWN! " & sMsg

 Context.SetResult 1, sMsg & " is outside the threshold of " & nThreshold & "%"

 Else

 Context.LogMessage "UP! " & sMsg

 Context.SetResult 0, sMsg & " is within the threshold of " & nThreshold & "%"

 End If

 End If

 End Sub

 ' **************

 ' * TestSNMP *

 ' **************

 Sub TestSNMP(ByRef bFail, ByRef sErrorMsg, ByRef bSNMPResult)

 Dim rc, sOID

 'Initialize and Test SNMP Connection

 Set rc = oSnmp.Initialize(nDeviceID)

 If rc.Failed Then

 sErrorMsg = rc.GetErrorMsg

 bSNMPResult = 1

 bFail = 1

 Else

 Set rc = oSnmp.GetNext("1.3.6.1.2.1.25.1.1")

 If rc.Failed Then

 sErrorMsg = rc.GetErrorMsg

 bSNMPResult = 1

 bFail = 1

 Context.LogMessage "No value found under hrSystemUptime (1.3.6.1.2.1.25.1.1)"

 Else

 sOID = rc.GetValue

 Context.LogMessage "SNMP test successful!" & vbCrLf & "hrSystemUptime:" & sOID

 End If

 End If

 End Sub

 ' ****************

 ' * GetSNMPVal *

 ' ****************

 Function GetSNMPVal(sOID, ByRef bFail, ByRef sErrorMsg)

 GetSNMPVal = 0

 Dim rc

 Set rc = oSnmp.Get(sOID)

 If rc.Failed Then

 sErrorMsg = rc.GetErrorMsg

 bFail = bFail + 1

 Context.LogMessage "Failed to get value!"

 Else

 'Context.LogMessage rc.GetValue

 GetSNMPVal = rc.GetValue

 End If

 End Function

 ' **************

 ' * GetDevAttr *

 ' **************

 Function GetDevAttr(nDevID, sAttr)

 GetDevAttr = Null

 Dim sSql, sRet, sRS

 sSql = "Select max(svalue) from DeviceAttribute where nDeviceID = " & nDevID &_

 " and sName = '" & sAttr & "'"

 Set sRS = oDb.Execute(sSql)

 If Not sRS.EOF And Not sRS.BOF Then

 sRet = Trim(sRS.GetString)

 If Right(sRet,1) = vbCr Or Right(sRet,1) = vbLf Then

 sRet = Left(sRet,Len(sRet)-1)

 End If

 If Len(sRet) > 0 Then

 GetDevAttr = sRet

 End If

 End If

 End Function

 ' **************

 ' * PutDevAttr *

 ' **************

 Function PutDevAttr(nDevID,sAttr,sVal)

 PutDevAttr = Null

 Dim sPrev

 Dim sSql, sRet, sRS

 sPrev = GetDevAttr(nDevID,sAttr)

 If GetDevAttrID(nDevID,sAttr) = 0 Then

 ' Need to Insert

 sSql = "Insert into DeviceAttribute(nDeviceID,sName,sValue) " &_

 "Values (" & nDevID & ",'" & sAttr & "','" & sVal & "')"

 Set sRS = oDb.Execute(sSql)

 Else

 If sPrev = sVal Then

 ' No Need to do anything

 Else

 ' Need to update

 sSql = "Update DeviceAttribute set sValue = '" & sVal &_

 "' Where nDeviceID = " & nDevID &_

 " And sName = '" & sAttr & "'"

 Set sRS = oDb.Execute(sSql)

 End If

 End If

 PutDevAttr = 1

 End Function

 ' ****************

 ' * GetDevAttrID *

 ' ****************

 Function GetDevAttrID(nDevID,sAttr)

 GetDevAttrID = 0

 Dim sSql, sRet, sRS

 sSql = "Select nDeviceAttributeID from DeviceAttribute where nDeviceID = " & nDevID &_

 " and sName = '" & sAttr & "'"

 Set sRS = oDb.Execute(sSql)

 If Not sRS.EOF And Not sRS.BOF Then

 sRet = Trim(sRS.GetString)

 If Len(sRet) > 0 Then

 If Right(sRet,1) = vbCr Then

 sRet = Left(sRet,Len(sRet)-1)

 End If

 End If

 If IsNumeric(sRet) Then

 GetDevAttrID = CLng(sRet)

 End If

 End If

 End Function


  • You would need to modify the SQL query to grab only the threshold you care about: perhaps either by aspect name or the aspect ID? Something like this (this is not the exact query you need)
    "select sDisplayName, sAspectValue, PAA.sAlertDescription, sAspectName, sAlertName, ACI.dAlertTime, ACI.nAlertCenterItemsID from AlertCenterItems ACI " &amp;_

    "join ProActiveAlert PAA on PAA.nProActiveAlertID = ACI.nProActiveAlertID " &amp;_

    "where (bActive = 1 and nDeviceID = " &amp;nDeviceID &amp; " and sAspectName like '%Your Threshold%')"
  • Yes, but it would require some changes to the script itself. However I would suggest fixing your dependencies instead. As a best practice, dependencies should only be set on the ping monitor and not every monitor.
  • paul connor This does not provide an average, but rather currently utilized memory each time it polls. If you're looking for averages, simply use the built-in Memory Utilization performance monitor or rewrite the script to store values and then average them out after 5 polls.
  • paul connor Oh yes, sorry I typed memory above. But everything I said still applies. I have another script for alerting on Alert Center thresholds that may suite your needs better. Let me look up the link.
  • Is it possible to increase the time on this monitor? 1 minute does not give much time to work out an average. I was thinking more like 5 minutes.
    Thanks, Paul
  • Hi Jason, I thought this was for CPU? I could use the alert centre but it only alerts via Email or SMS and to automate this into our service desk application I need it via a file action, that is why I was leaning to active monitor to output to file. unfortunately due to some erratic CPU utilisation without an average over a longer timescale its messy with devices constantly showing up and down over and over again.
  • @Jason, this is working well for me but I have noticed a slight issue. we a device goes down (stops pinging) the alert threshold monitor is still up and therefore the device does not show as completely down, this has an impact on my dependencies.
    Is there a clever way to make this monitor only active (or Up) only if the ping monitor is Up?
    Many thanks,Paul.
    • Muzzammil Naqvi (Customer)

      Hi, were you ever able to find a solution to this problem?

      I'm going through the same issue and can't find out how to fix it.

10 of 12