Enterprise Application Availability Monitoring PowerShell script DataSource

SquaredUp.EAM.Library.DataSource.AvailabilityMonitoring.PowerShellScript (DataSourceModuleType)

Executes the given PowerShell script using and returns the results and response time.

Element properties:

TypeDataSourceModuleType
IsolationAny
AccessibilityInternal
RunAsDefault
OutputTypeSystem.PropertyBagData

Member Modules:

ID Module Type TypeId RunAs 
Scheduler DataSource System.Scheduler Default
PA ProbeAction Microsoft.Windows.PowerShellPropertyBagTriggerOnlyProbe Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
IntervalSecondsint$Config/IntervalSeconds$Interval (Seconds)The number of seconds between script executions.
SyncTimestring$Config/SyncTime$Sync Time (hh:mm)The time around which executions should be synchronised.
TimeoutSecondsint$Config/TimeoutSeconds$Timeout (Seconds)The number of seconds after which the script will be terminated.
ConfigurationJsonstring$Config/ConfigurationJson$Configuration JSONA JSON blob containing configuration data for the provided script.
Scriptstring$Config/Script$ScriptThe script to execute. Should either return an object with a Success and Description property, or throw an exception if the test fails.
ResponseTimeThresholddouble$Config/ResponseTimeThreshold$Response Time Threshold (ms)The number of milliseconds that the given script should complete in.

Source Code:

<DataSourceModuleType ID="SquaredUp.EAM.Library.DataSource.AvailabilityMonitoring.PowerShellScript" Accessibility="Internal" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" type="xsd:integer" name="IntervalSeconds"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" type="xsd:string" name="SyncTime"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" type="xsd:integer" name="TimeoutSeconds"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" type="xsd:string" name="ConfigurationJson"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" type="xsd:string" name="Script"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" type="xsd:double" name="ResponseTimeThreshold"/>
</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="ConfigurationJson" Selector="$Config/ConfigurationJson$" ParameterType="string"/>
<OverrideableParameter ID="Script" Selector="$Config/Script$" ParameterType="string"/>
<OverrideableParameter ID="ResponseTimeThreshold" Selector="$Config/ResponseTimeThreshold$" ParameterType="double"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<DataSource ID="Scheduler" TypeID="System!System.Scheduler">
<Scheduler>
<SimpleReccuringSchedule>
<Interval Unit="Seconds">$Config/IntervalSeconds$</Interval>
<SyncTime>$Config/SyncTime$</SyncTime>
</SimpleReccuringSchedule>
<ExcludeDates/>
</Scheduler>
</DataSource>
<ProbeAction ID="PA" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagTriggerOnlyProbe">
<ScriptName>SquaredUp.EAM.AvailabilityMonitoring.Web.Basic.Monitor.DataSource.ps1</ScriptName>
<ScriptBody><Script>[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")]
param(
$ConfigurationJson,
$Script,
$ResponseTimeThreshold,
$Username,
$Password
)

#=================================================================================
# Squared Up Enterprise Application Monitoring
# Custom PowerShell availability monitor
#
# This script wraps a simple PowerShell script and interprets the results
#
# Copyright (c) Squared Up Ltd
#=================================================================================


# Constants
#=================================================================================
$ScriptName = "SquaredUp.EAM.AvailabilityMonitoring.Web.Basic.Monitor.DataSource.ps1"
$EventID = "8001"
#=================================================================================


# Start
#=================================================================================
$whoami = whoami
$momapi = New-Object -comObject MOM.ScriptAPI
$bag = $momapi.CreatePropertyBag()
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script is starting. `n Running as ($whoami). `n Config: $ConfigurationJson")
#=================================================================================

# Functions
#=================================================================================

function ExecuteScript {
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "credentials")]
param($script, $config, $credentials)
return Invoke-Expression $script
}

#=================================================================================


# Main
#=================================================================================

# Convert the JSON to an object to be used by the script
#
$configuration = $null
if ($ConfigurationJson -ne $null) {
$configuration = ConvertFrom-Json $ConfigurationJson
}

# Construct credentials object which can be used by the script
#
$SecureString = $null
$PSCreds = $null
if (-not [string]::IsNullOrEmpty($Password)) {
$SecureString = ConvertTo-SecureString -AsPlainText $Password -Force
$PSCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username,$SecureString
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Credentials provided from EAM Parameter Run As profile: ($username).")
}

$credentials = [PSCustomObject]@{
"Username" =$Username
"Password" =$Password
"BasicAuth" = [convert]::ToBase64String([system.text.encoding]::ASCII.Getbytes("$($username):$password"))
"SecureString" = $SecureString
"PSCredential" = $PSCreds
}

# Measure total time taken
#
$timeTaken = Measure-Command -Expression {

Try {

# Execute the custom script
$result = ExecuteScript $Script $configuration $credentials

}
Catch {
# Treat exceptions as failures
$result = New-Object &#x2013;TypeName PSObject &#x2013;Prop (@{'Success'=$false;'Description'=$_.Exception.Message})
}

}

# $result values:
# [bool] (success)
# OR
# $result.Success = [bool]
# $result.Level = [string] "warning" | "error"
# $result.ResponseTime = [double]

# If no result, assume ok
#
if( $null -eq $result) {
$result = New-Object -TypeName PSObject -Property (@{'Success'=$true; 'Description'=''})
}

# Is result a simple boolean?
#
if( $result.GetType().FullName -eq "System.Boolean" ) {
$boolResult = $result
$result = New-Object -TypeName PSObject -Property (@{'Success'=$boolResult; 'Description'=''})
}

# If no Success property, assume ok
#
if ( -not( [bool]($result.PSobject.Properties.name -match "Success") ) ) {
$result | Add-Member &#x2013;MemberType NoteProperty &#x2013;Name Success &#x2013;Value $true
}

# If no Description property, add one so alert paramter replacement works
#
if ( -not ([bool]($result.PSobject.Properties.name -match "Description"))) {
$result | Add-Member -MemberType NoteProperty -Name 'Description' -Value ''
}

# If no ResponseTime, set to measured time taken
#
if ( -not( [bool]($result.PSobject.Properties.name -match "ResponseTime") ) -or (($result.ResponseTime -as [double]) -eq $null ) ) {
$result | Add-Member &#x2013;MemberType NoteProperty &#x2013;Name ResponseTime &#x2013;Value $timeTaken.TotalMilliseconds
}

# If ResponseTimeThreshold and success measure time
#
if ( $result.Success -and ($ResponseTimeThreshold -as [double]) -gt 0.0) {
$underThreshold = $result.ResponseTime -lt [double]$ResponseTimeThreshold
$result.Success = $underThreshold

if (-not $underThreshold -and [string]::IsNullOrEmpty($result.Description)) {
$result.Description = "Test did not complete in under $ResponseTimeThreshold ms (took $($result.ResponseTime))"
}
}

# If no Level property, assume error
#
if ( -not( [bool]($result.PSobject.Properties.name -match "Level") ) -and -not $result.Success ) {
$result | Add-Member &#x2013;MemberType NoteProperty &#x2013;Name Level &#x2013;Value "error"
}

# Save result into property bag
#
$result.PSObject.Properties | ForEach-Object {
$bag.AddValue( $_.Name, $_.Value )
}

#=================================================================================


# End
#=================================================================================
#Log an event for script ending and total execution time.
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script Completed. `n Script result: `n $(ConvertTo-Json $result)")
# Return property bag
$bag
#=================================================================================
</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>ConfigurationJson</Name>
<Value>$Config/ConfigurationJson$</Value>
</Parameter>
<Parameter>
<Name>Script</Name>
<Value>$Config/Script$</Value>
</Parameter>
<Parameter>
<Name>ResponseTimeThreshold</Name>
<Value>$Config/ResponseTimeThreshold$</Value>
</Parameter>
<Parameter>
<Name>Username</Name>
<Value>$RunAs[Name='SquaredUp.EAM.Library.SecureReference.AvailabilityMonitoring.Custom.Parameter']/UserName$</Value>
</Parameter>
<Parameter>
<Name>Password</Name>
<Value>$RunAs[Name='SquaredUp.EAM.Library.SecureReference.AvailabilityMonitoring.Custom.Parameter']/Password$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="PA">
<Node ID="Scheduler"/>
</Node>
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
</DataSourceModuleType>