PI Services

Le blog des collaborateurs de PI Services

SCOM – Créer un moniteur d’échantillons consécutifs de performance à 3 états – 1/2

Au cours de l’un ou l’autre des développements de Management Pack que j’ai été amené à réaliser, il est arrivé à plusieurs reprises que l’on me demande de mettre en place un moniteur de performances fonctionnant sur plusieurs mesures consécutives et ayant trois états (healthy/warning/critical), ou autrement dit deux seuils de déclenchement distincts.

Prises séparément, ces deux contraintes ne posent aucune difficulté particulière puisqu’il est possible de créer nativement via la console SCOM des moniteurs de performance de type « consecutive samples » (mesure d’échantillons consécutifs à deux états/un seul seuil) et « double thresholds » (trois états/deux seuils mais déclenchement sur une seule mesure).

Réunir ces deux besoins nécessite par contre d’en passer par un peu d’authoring, ce dont je profiterai pour présenter deux façons de procéder :

- Fusionner deux types de moniteurs natifs (cet article)

- Utiliser la Suppression, une propriété méconnue de l’expression filter natif

Comme vu dans l’introduction, il existe nativement dans SCOM deux types de moniteurs qui, s’ils pouvaient être assemblés, formeraient une solution évidente à notre problème.

Et il se trouve que SCOM permet ce genre de fantaisie assez facilement, bien que cela nécessite de mettre les mains dans le code…

Commençons par aller regarder la « définition » de ces deux types de moniteurs, à l’aide de l’indispensable systemcenter.wiki : ConsecutiveSamplesThreshold et DoubleThreshold

On remarque immédiatement qu’ils sont basés sur une construction très similaire : ils comportent tous les deux en point d’entrée une source de données (Data Source) qui leur permet de récupérer la valeur du compteur de performance qui nous intéressent :
clip_image001

Cette Data Source est suivie par un ensemble de conditions de détection (Condition Detection) qui leur permettent de déterminer quand l’un ou l’autre état du moniteur est atteint.

Pour comprendre leur fonctionnement, il faut imaginer que la valeur relevée par la DataSource passe successivement par chaque Condition Detection, qui, si les conditions qui les définissent sont réunies, vont renvoyer un property bag.

Dans le cas du Consecutive Sample, on trouve trois Condition Detections :

- La première, de type System.Performance.ConsecutiveSamplesCondition, permet de compter le nombre de fois où la valeur du compteur est passée au delà du seuil configuré. Elle n’agit pas directement sur l’état du moniteur.
clip_image002

- La seconde et la troisième, de type ExpressionFilter permettent quant à elles de déterminer deux états pour le moniteur, en fonction de la valeur renvoyée par la première (nombre d’échantillons au-delà du seuil suffisant ou non pour changer l’état).
clip_image004

Dans le cas du Double Threshold, on retrouve également trois Condition Detection, mais ici chacune des trois servent à déterminer l’état du moniteur directement en fonction de la valeur renvoyée par la Data Source (sous le premier seuil, entre les deux seuils ou au-dessus du second):

clip_image006

En se basant sur ces constations, on réalise que rien n’empêche d’écrire nous-même un Monitor Type qui contiendrait à la fois une Condition Detection de type ConsecutiveSamplesCondition pour compter le nombre d’échantillons au-dessus du seuil de détection, suivie de trois ExpressionFilter pour déterminer 3 états différents qui vérifieraient à la fois la valeur du compteur et le nombre de fois qu’il est passé au  delà du seuil!
Le filtre pour l’état « entre deux seuils » ressemblerait donc à cela :

clip_image007

On voit bien que pour que le moniteur prenne l’état « Warning », j’ai simplement créé une expression qui nécessite la réunion de 3 conditions : un nombre de mesures (NumSamples) au-delà du seuil défini et une valeur de ces mesures inférieure à un premier seuil et supérieure à un second.

Et comme un bon exemple complet vaut mieux que tous les longs discours, voici ici le fragment intégral, implémenté pour le compteur « Logical Disk / Free Space % :

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <TypeDefinitions>
    <MonitorTypes>
  <UnitMonitorType ID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.MonitorType" Accessibility="Internal">
    <MonitorTypeStates>
      <MonitorTypeState ID="Healthy" NoDetection="false" />
      <MonitorTypeState ID="Warning" NoDetection="false" />
      <MonitorTypeState ID="Critical" NoDetection="false" />
    </MonitorTypeStates>
    <Configuration>
      <xsd:element name="Frequency" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="WarningThreshold" type="xsd:double" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="CriticalThreshold" type="xsd:double" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="NumSamples" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="Direction" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="ComputerName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="CounterName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="ObjectName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="InstanceName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
      <xsd:element name="AllInstances" type="xsd:boolean" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
    </Configuration>
    <OverrideableParameters>
      <OverrideableParameter ID="Frequency" Selector="$Config/Frequency$" ParameterType="int" />
      <OverrideableParameter ID="WarningThreshold" Selector="$Config/WarningThreshold$" ParameterType="double" />
      <OverrideableParameter ID="CriticalThreshold" Selector="$Config/CriticalThreshold$" ParameterType="double" />
      <OverrideableParameter ID="NumSamples" Selector="$Config/NumSamples$" ParameterType="int" />

    </OverrideableParameters>
    <MonitorImplementation>
      <MemberModules>
        <DataSource ID="DS" TypeID="Perf!System.Performance.DataProvider">
          <ComputerName>$Config/ComputerName$</ComputerName>
          <CounterName>$Config/CounterName$</CounterName>
          <ObjectName>$Config/ObjectName$</ObjectName>
          <InstanceName>$Config/InstanceName$</InstanceName>
          <AllInstances>$Config/AllInstances$</AllInstances>
          <Frequency>$Config/Frequency$</Frequency>
        </DataSource>
        <ConditionDetection ID="ConsecutiveSamples" TypeID="Perf!System.Performance.ConsecutiveSamplesCondition">
          <Threshold>$Config/WarningThreshold$</Threshold>
          <Direction>$Config/Direction$</Direction>
        </ConditionDetection>
        <ConditionDetection ID="HealthyCondition" TypeID="System!System.ExpressionFilter">
          <Expression>
            <And>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/WarningThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/CriticalThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </And>
          </Expression>
        </ConditionDetection>
        <ConditionDetection ID="WarningCondition" TypeID="System!System.ExpressionFilter">
          <Expression>
            <And>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Value</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Integer">$Config/NumSamples$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>LessEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/WarningThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>Greater</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/CriticalThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </And>
          </Expression>
        </ConditionDetection>
        <ConditionDetection ID="CriticalCondition" TypeID="System!System.ExpressionFilter">
          <Expression>
            <And>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Value</XPathQuery>
                  </ValueExpression>
                  <Operator>GreaterEqual</Operator>
                  <ValueExpression>
                    <Value Type="Integer">$Config/NumSamples$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Double">SampleValue</XPathQuery>
                  </ValueExpression>
                  <Operator>LessEqual</Operator>
                  <ValueExpression>
                    <Value Type="Double">$Config/CriticalThreshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </And>
          </Expression>
        </ConditionDetection>
      </MemberModules>
      <RegularDetections>
        <RegularDetection MonitorTypeStateID="Healthy">
          <Node ID="HealthyCondition">
            <Node ID="ConsecutiveSamples">
              <Node ID="DS" />
            </Node>
          </Node>
        </RegularDetection>
        <RegularDetection MonitorTypeStateID="Warning">
          <Node ID="WarningCondition">
            <Node ID="ConsecutiveSamples">
              <Node ID="DS" />
            </Node>
          </Node>
        </RegularDetection>
        <RegularDetection MonitorTypeStateID="Critical">
          <Node ID="CriticalCondition">
            <Node ID="ConsecutiveSamples">
              <Node ID="DS" />
            </Node>
          </Node>
        </RegularDetection>
      </RegularDetections>
    </MonitorImplementation>
  </UnitMonitorType>
  </MonitorTypes>
  </TypeDefinitions>
  <Monitoring>
    <Monitors>
      <UnitMonitor ID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" Accessibility="Public" Enabled="true" Target="MWSL!Microsoft.Windows.Server.6.2.LogicalDisk" ParentMonitorID="Health!System.Health.PerformanceState" Remotable="true" Priority="Normal" TypeID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.MonitorType" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <AlertSettings AlertMessage="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor.Alert.Message">
          <AlertOnState>Warning</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>MatchMonitorHealth</AlertSeverity>
          <AlertParameters>
            <AlertParameter1>$Data/Context/ObjectName$</AlertParameter1>
            <AlertParameter2>$Data/Context/CounterName$</AlertParameter2>
            <AlertParameter3>$Data/Context/InstanceName$</AlertParameter3>
            <AlertParameter4>$Data/Context/SampleValue$</AlertParameter4>
            <AlertParameter5>$Data/Context/TimeSampled$</AlertParameter5>
          </AlertParameters>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="Healthy" MonitorTypeStateID="Healthy" HealthState="Success" />
          <OperationalState ID="Warning" MonitorTypeStateID="Warning" HealthState="Warning" />
          <OperationalState ID="Critical" MonitorTypeStateID="Critical" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <Frequency>60</Frequency>
          <WarningThreshold>80</WarningThreshold>
          <CriticalThreshold>65</CriticalThreshold>
          <NumSamples>3</NumSamples>
          <Direction>Less</Direction>
          <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
          <CounterName>% Free Space</CounterName>
          <ObjectName>LogicalDisk</ObjectName>
          <InstanceName>$Target/Property[Type="Windows!Microsoft.Windows.LogicalDevice"]/DeviceID$</InstanceName>
          <AllInstances>false</AllInstances>
        </Configuration>
      </UnitMonitor>
    </Monitors>
  </Monitoring>
  <Presentation>
    <StringResources>
      <StringResource ID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor.Alert.Message" />
    </StringResources>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor">
          <Name>Test 3State Consecutive Free Disk Space Perf Monitor (Condition Detection)</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" SubElementID="Healthy">
          <Name>Healthy</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" SubElementID="Warning">
          <Name>Warning</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor" SubElementID="Critical">
          <Name>Critical</Name>
        </DisplayString>
        <DisplayString ElementID="Test.ThreeStateConsecutiveThreshold.ConditionDetection.Perf.Monitor.Alert.Message">
          <Name>Test 3 state consecutive counter has breached a threshold</Name>
          <Description>
            The monitor breached a threshold

            Object: {0}
            Counter {1}
            Instance {2}
            Has a value {3}
            At time {4}
          </Description>
        </DisplayString>
      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

 

Ajouter un commentaire

Loading