Monitor Type For SPHARule

Microsoft.SharePoint.2016.MonitorType.SPHARule (UnitMonitorType)

Three state monitor type for SPHARule monitoring.

Element properties:

RunAsMicrosoft.SharePoint.Library.AdminAccount
AccessibilityInternal
Support Monitor RecalculateTrue

Member Modules:

ID Module Type TypeId RunAs 
DataSource DataSource Microsoft.SharePoint.2016.TimedScript.FilteredPropertyBagProvider Default
ErrorFilter ConditionDetection System.ExpressionFilter Default
SuccessFilter ConditionDetection System.ExpressionFilter Default
WarningFilter ConditionDetection System.ExpressionFilter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$IntervalSecondsThe frequency in seconds that this Monitor will be executed, it should be long enough to avoid Monitor failure by resource competing.
SyncTimestring$Config/SyncTime$SyncTimeSyncTime (start time) property of SPHARule Monitor Type. SyncTime is a string value in the format of "HH:mm". SyncTime, IntervalSeconds and Management Pack Import time together determines the exact run time of a given workflow. For example, if IntervalSeconds = 21600 (6 hours) and SyncTime = "01:15", the possible run time of the workflow is 1:15AM, 7:15AM, 1:15PM, 7:15PM; if the Management Pack is imported after 1:15AM but before 7:15AM, it will start at 7:15AM, if the Management Pack is imported after 1:15PM but before 7:15PM, it will start at 7:15PM. However, due to other factors such as network delay the actual start time may still vary.
TimeoutSecondsint$Config/TimeoutSeconds$TimeoutSecondsTimeout value in seconds for each monitoring run. The Timeout value should be long enough to finish required objects' Monitor status update, it should be less than IntervalSeconds.
DebugTracebool$Config/DebugTrace$DebugTraceDebugTrace property of SharePoint Health Analyzer (SPHA) Monitor. This module will write debug trace to Windows Event Log if this value is set to true.

Source Code:

<UnitMonitorType ID="Microsoft.SharePoint.2016.MonitorType.SPHARule" Accessibility="Internal" RunAs="MOSS!Microsoft.SharePoint.Library.AdminAccount">
<MonitorTypeStates>
<MonitorTypeState ID="Error" NoDetection="false"/>
<MonitorTypeState ID="Warning" NoDetection="false"/>
<MonitorTypeState ID="Success" NoDetection="false"/>
</MonitorTypeStates>
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="IntervalSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SyncTime" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="DebugTrace" type="xsd:boolean"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="FilterValue" type="xsd:string"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
<OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
<OverrideableParameter ID="DebugTrace" Selector="$Config/DebugTrace$" ParameterType="bool"/>
</OverrideableParameters>
<MonitorImplementation>
<MemberModules>
<DataSource ID="DataSource" TypeID="Microsoft.SharePoint.2016.TimedScript.FilteredPropertyBagProvider">
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<SyncTime>$Config/SyncTime$</SyncTime>
<ScriptName>MOSSBPAMonitor.ps1</ScriptName>
<Arguments/>
<ScriptBody><Script>$error.Clear()
$ErrorActionPreference = "SilentlyContinue"

$global:EventObject = New-Object Diagnostics.EventLog
$global:EventObject.Source = "Operations Manager"

function global:Write-Event ([string] $LogContent, $LogType = [Diagnostics.EventLogEntryType]::Information)
{
if ($error)
{
$error.Clear()
$LogType = [Diagnostics.EventLogEntryType]::Error
}

$EventObject.WriteEntry($LogContent, $LogType)
}

function global:LogScriptTime($InvocationObj)
{
$dtEnd = [DateTime]::Now

$msg = @"
[Debug] {0} ended.
Current User: {1}
Current PID: {2}
start time: {3}
stop time: {4}
time taken: {5}
"@ -f $InvocationObj.MyCommand,
[Environment]::UserName,
$pid,
$dtStart,
$dtEnd,
(New-TimeSpan $dtStart $dtEnd).TotalMilliseconds

Write-Event $msg
}

function global:GetDebugSetting($DebugTrace)
{

if ($DebugTrace.ToUpper() -eq "TRUE")
{
$global:Debug = $True;
}
else
{
$global:Debug = $False;
}

}

GetDebugSetting $Args[1]

function global:LogMessage($Message)
{

$Message = "[Debug] {0} `r`n{1}" -f $MyInvocation.ScriptName, $Message
Write-Event $Message
}

if ($global:Debug) {
$msg = "Powershell script {0} execution starting...`r`nArguments:{1} {2}" -f $MyInvocation.MyCommand, $args[0], $args[1]
LogMessage $msg

$dtStart = [DateTime]::Now
}

function Handle-Errors([string] $ErrMsg = [String]::Empty, [bool] $IsExit = $true)
{
if (!$error)
{
return
}

$IsLog = $true

if ("" -eq $ErrMsg)
{
$IsLog = $false
}
else
{
$IsLog = $true
}

if ($IsLog)
{
$ErrorString = ""
if (!$IsExit)
{
$ErrorString = "{0} Monitoring script {1} continues under this error! " -f $MyInvocation.MyCommand, $ErrMsg
}
else
{
$ErrorString = "{0} Monitoring script {1} was terminated! " -f $MyInvocation.MyCommand, $ErrMsg
}

$Exception = $error[$error.Count - 1]
if ($Exception.InvocationInfo)
{
$ErrorString += @"
Current User: {0}
Current PID: {1}
InvocationInfo.MyCommand: {2}
InvocationInfo.ScriptLineNumber: {3}
InvocationInfo.OffsetInLine: {4}
InvocationInfo.ScriptName: {5}
InvocationInfo.Line: {6}
InvocationInfo.PositionMessage: {7}
InvocationInfo.InvocationName: {8}
InvocationInfo.PipelineLength: {9}
InvocationInfo.PipelinePosition: {10}
"@ -f [Environment]::UserName,
$pid,
$Exception.InvocationInfo.MyCommand,
$Exception.InvocationInfo.ScriptLineNumber,
$Exception.InvocationInfo.OffsetInLine,
$Exception.InvocationInfo.ScriptName,
$Exception.InvocationInfo.Line,
$Exception.InvocationInfo.PositionMessage,
$Exception.InvocationInfo.InvocationName,
$Exception.InvocationInfo.PipelineLength,
$Exception.InvocationInfo.PipelinePosition
}
if ($Exception.Exception)
{
$Exception = $Exception.Exception
}
if (!$Exception.InnerException)
{
$ErrType = "Error"
}
else
{
$ErrType = $Exception.InnerException.GetType().FullName
}

$EventObject.WriteEntry(("{0} `n{1}`n{2}" -f $ErrType, $ErrorString, $Exception.Message), [System.Diagnostics.EventLogEntryType]::Error)
}

if ($IsExit)
{
break
}

$error.Clear()
}

$oAPI = New-Object -comObject "MOM.ScriptAPI"
Handle-Errors "Error loading MOM.ScriptAPI COM object "

$MOSSAssembly = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
Handle-Errors ""
if (!$MOSSAssembly)
{
break
}

if ($MOSSAssembly.GetName().Version.Major -ne 16)
{
break
}

$RuleLocSeverities = @{}
$RuleLocSeverities["RuleExecutionFailure"] = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::GetLocalizedSeverity([Microsoft.SharePoint.Administration.Health.SPHealthCheckErrorLevel]::RuleExecutionFailure)
$RuleLocSeverities["Error"] = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::GetLocalizedSeverity([Microsoft.SharePoint.Administration.Health.SPHealthCheckErrorLevel]::Error)
$RuleLocSeverities["Warning"] = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::GetLocalizedSeverity([Microsoft.SharePoint.Administration.Health.SPHealthCheckErrorLevel]::Warning)
$RuleLocSeverities["Information"] = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::GetLocalizedSeverity([Microsoft.SharePoint.Administration.Health.SPHealthCheckErrorLevel]::Information)
$RuleLocSeverities["Success"] = [Microsoft.SharePoint.Administration.Health.SPHealthAnalyzer]::GetLocalizedSeverity([Microsoft.SharePoint.Administration.Health.SPHealthCheckErrorLevel]::Success)

$RuleStatesFromLocSeverities = @{}
$RuleStatesFromLocSeverities[$RuleLocSeverities["RuleExecutionFailure"]] = "WARNING"
$RuleStatesFromLocSeverities[$RuleLocSeverities["Error"]] = "ERROR"
$RuleStatesFromLocSeverities[$RuleLocSeverities["Warning"]] = "WARNING"
$RuleStatesFromLocSeverities[$RuleLocSeverities["Information"]] = "SUCCESS"
$RuleStatesFromLocSeverities[$RuleLocSeverities["Success"]] = "SUCCESS"

function global:GetSPHARuleState($ErrorLevel)
{
$RuleState = $RuleStatesFromLocSeverities[$ErrorLevel]

return $RuleState
}

$HealthReportQuery = new-object Microsoft.SharePoint.SPQuery
$HealthReportQuery.ViewFields = "&lt;FieldRef Name='HealthReportSeverity'/&gt;&lt;FieldRef Name='HealthRuleType'/&gt;&lt;FieldRef Name='Title'/&gt;&lt;FieldRef Name='HealthReportRemedy'/&gt;&lt;FieldRef Name='HealthReportExplanation'/&gt;&lt;FieldRef Name='HealthReportCategory'/&gt;&lt;FieldRef Name='HealthReportServers'/&gt;&lt;FieldRef Name='HealthReportServices'/&gt;&lt;FieldRef Name='HealthRuleReportLink'/&gt;"
$HealthReports = [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]::Local.HealthReports
if (!$HealthReports)
{
$ErrMsg = @"
Error in {0}:
Failed to get SharePoint Health Reports.
Make sure user {1} have enough permission or SharePoint is configured correctly and the database server is running.
Other issues might also cause this failure. Please see Microsoft SharePoint 2016 Management Pack Guide.docx for more information.
"@ -f $MyInvocation.MyCommand, [Environment]::UserName
$EventObject.WriteEntry($ErrMsg, [System.Diagnostics.EventLogEntryType]::Warning)
break;
}

if ($HealthReports.Items.Count -eq 0)
{
$oBag = $oAPI.CreatePropertyBag()
$oBag.AddValue("FilterValue", "PlaceHolderPropertyBag")
$oBag.AddValue("Status", "Unknown")
$oAPI.AddItem($oBag)
}
else
{
$HealthReports = $HealthReports.GetItems($HealthReportQuery)
Handle-Errors "Error loading Microsoft SharePoint 2016 HealthReports "
if (!$HealthReports)
{
break
}

foreach ($HealthReport in $HealthReports)
{
$ErrorLevel = $HealthReport["HealthReportSeverity"]
Handle-Errors "Failed to get Health Report Severity" $false

$RuleState = GetSPHARuleState($ErrorLevel)

$HealthRuleType = $HealthReport["HealthRuleType"].SubString(0, $HealthReport["HealthRuleType"].IndexOf(","))
$oBag = $oAPI.CreatePropertyBag()
$oBag.AddValue("FilterValue", $HealthRuleType)
$oBag.AddValue("Status", $RuleState)
if ($RuleState.ToUpper() -ne "SUCCESS")
{
if ($HealthReport["HealthReportExplanation"])
{
$oBag.AddValue("Explanation", $HealthReport["HealthReportExplanation"])
}
else
{
$oBag.AddValue("Explanation", "")
}
if ($HealthReport["HealthReportRemedy"])
{
$oBag.AddValue("Remedy", $HealthReport["HealthReportRemedy"])
}
else
{
$oBag.AddValue("Remedy", "")
}
if ($HealthReport["HealthReportServers"])
{
$oBag.AddValue("FailingServers", $HealthReport["HealthReportServers"])
}
else
{
$oBag.AddValue("FailingServers", "")
}
if ($HealthReport["HealthReportServices"])
{
$oBag.AddValue("FailingServices", $HealthReport["HealthReportServices"])
}
else
{
$oBag.AddValue("FailingServices", "")
}

$oBag.AddValue("Link", $HealthReport["HealthRuleReportLink"])
}
$oAPI.AddItem($oBag)
Handle-Errors "Failed to get Health Report property" $false
}
}

$oAPI.ReturnItems()
Handle-Errors "Failed to submit PropertyBag data to SCOM Agent" $false

if ($global:Debug) {
$dtEnd = [DateTime]::Now

$msg = @"
Current User: {0}
Current PID: {1}
start time: {2}
stop time: {3}
time taken: {4}
Powershell script {5} execution ended.
"@ -f [Environment]::UserName,
$pid,
$dtStart,
$dtEnd,
(New-TimeSpan $dtStart $dtEnd).TotalMilliseconds,
$MyInvocation.MyCommand

LogMessage $msg
}</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
<DebugTrace>$Config/DebugTrace$</DebugTrace>
<FilterValue>$Config/FilterValue$</FilterValue>
</DataSource>
<ConditionDetection ID="ErrorFilter" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='Status']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">ERROR</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
<ConditionDetection ID="WarningFilter" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='Status']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">WARNING</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
<ConditionDetection ID="SuccessFilter" TypeID="System!System.ExpressionFilter">
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='Status']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">SUCCESS</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</ConditionDetection>
</MemberModules>
<RegularDetections>
<RegularDetection MonitorTypeStateID="Error">
<Node ID="ErrorFilter">
<Node ID="DataSource"/>
</Node>
</RegularDetection>
<RegularDetection MonitorTypeStateID="Warning">
<Node ID="WarningFilter">
<Node ID="DataSource"/>
</Node>
</RegularDetection>
<RegularDetection MonitorTypeStateID="Success">
<Node ID="SuccessFilter">
<Node ID="DataSource"/>
</Node>
</RegularDetection>
</RegularDetections>
<OnDemandDetections>
<OnDemandDetection MonitorTypeStateID="Error">
<Node ID="ErrorFilter">
<Node ID="DataSource"/>
</Node>
</OnDemandDetection>
<OnDemandDetection MonitorTypeStateID="Warning">
<Node ID="WarningFilter">
<Node ID="DataSource"/>
</Node>
</OnDemandDetection>
<OnDemandDetection MonitorTypeStateID="Success">
<Node ID="SuccessFilter">
<Node ID="DataSource"/>
</Node>
</OnDemandDetection>
</OnDemandDetections>
</MonitorImplementation>
</UnitMonitorType>