Extending Discovery Of Java Applications in SCOM 2012


The solution to monitoring JEE Application Servers and Applications in SCOM 2012 is a good starting point, but sometimes you may want to do more.  The good news is that the structure of theses MPs are extendable and this blog post will detail how to do that.

For instance, let’s suppose that I am a customer with my own Contoso (see http://blogs.technet.com/b/random_happy_dev_thoughts/archive/2012/03/26/sample-jee-application-contoso-order-service.aspx) application that I want to uniquely identify.  There is not a way to change the default JEE discovery exclude certain applications; however, what you can do is create a discovery to create your own extended version of the existing JEE objects.

For the example below I have written a custom discovery that targets the Microsoft.JEE.Application objects from the Microsoft.JEE.Library MP.  The discovery uses a simple condition detection module to filter on the name of the discovered application. The new class can be as simple as this:

<ClassType 
ID="Contoso.JEE.SampleApplication"
Abstract="false"
Accessibility="Public" Hosted="true"
Base="JEE!Microsoft.JEE.Application" />

 The filtering is done in this library module where the TargetApplicationName is the application name that I want to find and ApplicationName is the name as reported from the object found by the existing Microsoft.JEE management packs.  There is a discovery that has the hardcode name of the application I want:

 

 <Discovery ID="Contoso.JEE.CustomOrderService.Discovery" Target="JEE!Microsoft.JEE.Application"
Remotable="true" Enabled="true">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="Contoso.JEE.SampleApplication" />
</DiscoveryTypes>
<DataSource ID="DS" TypeID="Contoso.JEE.SampleApplication.Discovery.DataSource">
<ClassId>$MPElement[Name="Contoso.JEE.SampleApplication"]$</ClassId>
<TargetApplicationName>CustomOrderService</TargetApplicationName>
<ApplicationName>$Target/Property[Type="JEE!Microsoft.JEE.Application"]/ApplicationName$</ApplicationName>
<DisplayName>$Target/Property[Type="JEE!Microsoft.JEE.Application"]/ApplicationName$</DisplayName>
<ObjectName>$Target/Property[Type="JEE!Microsoft.JEE.Application"]/ObjectName$</ObjectName>
<PrincipalName>$Target/Host/Host/Property[Type="JEE!Microsoft.JEE.ApplicationServer.Instance"]/HostName$</PrincipalName>
<Id>$Target/Host/Host/Property[Type="JEE!Microsoft.JEE.ApplicationServer.Instance"]/Id$</Id>
<j2eeType>$Target/Property[Type="JEE!Microsoft.JEE.Application"]/j2eeType$</j2eeType>
<IntervalSeconds>14400</IntervalSeconds>
</DataSource>
</Discovery>

 

And the discovery call this module that does the dirty work of filtering.

 

 <DataSourceModuleType ID="Contoso.JEE.SampleApplication.Discovery.DataSource" Accessibility="Public">
<Configuration>
<IncludeSchemaTypes>
<SchemaType>System!System.ExpressionEvaluatorSchema</SchemaType>
</IncludeSchemaTypes>
<xsd:element name="ClassId" type="xsd:string" />
<xsd:element name="TargetApplicationName" type="xsd:string" />
<xsd:element name="ApplicationName" type="xsd:string" />
<xsd:element name="DisplayName" type="xsd:string" />
<xsd:element name="ObjectName" type="xsd:string" />
<xsd:element name="PrincipalName" type="xsd:string" />
<xsd:element name="Id" type="xsd:string" />
<xsd:element name="j2eeType" type="xsd:string" />
<xsd:element name="IntervalSeconds" type="xsd:integer" />
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
</OverrideableParameters>
<ModuleImplementation>
<Composite>
<MemberModules>
<DataSource TypeID="Contoso.SpecializedClass.Discovery.DataSource" ID="Specializer">
<ClassId>$Config/ClassId$</ClassId>
<IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
<Expression>
<RegExExpression>
<ValueExpression>
<Value>$Config/ApplicationName$</Value>
</ValueExpression>
<Operator>MatchesRegularExpression</Operator>
<Pattern>$Config/TargetApplicationName$</Pattern>
</RegExExpression>
</Expression>
<InstanceSettings>
<Settings>
<!-- These properties are for the Application Server Instance -->
<Setting>
<Name>$MPElement[Name="JEE!Microsoft.JEE.ApplicationServer.Instance"]/Id$</Name>
<Value>$Config/Id$</Value>
</Setting>
<Setting>
<Name>$MPElement[Name="JEE!Microsoft.JEE.ApplicationServer.Instance"]/HostName$</Name>
<Value>$Config/PrincipalName$</Value>
</Setting>
<!-- The following properties are defined for the Application-->
<Setting>
<Name>$MPElement[Name="JEE!Microsoft.JEE.Application"]/ApplicationName$</Name>
<Value>$Config/ApplicationName$</Value>
</Setting>
<Setting>
<Name>$MPElement[Name="JEE!Microsoft.JEE.Application"]/j2eeType$</Name>
<Value>$Config/j2eeType$</Value>
</Setting>
<Setting>
<Name>$MPElement[Name="JEE!Microsoft.JEE.Application"]/ObjectName$</Name>
<Value>$Config/ObjectName$</Value>
</Setting>
</Settings>
</InstanceSettings>
</DataSource>
</MemberModules>
<Composition>
<Node ID="Specializer" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.Discovery.Data</OutputType>
</DataSourceModuleType>

  

Now that there is a discovery for my specific application, I can write rules specific to my new class.  Since this order service that I have already exposes some metrics that I want to a MBean, I’ll just write my own rule that will capture this performance data and store it in the Perf Store.

 

 <Rule ID="Contoso.JEE.SampleApplication.PerformanceData.AverageTransactionTime" Target="Contoso.JEE.SampleApplication"
Enabled="true" Remotable="true">
<Category>PerformanceCollection</Category>

<DataSources>
<DataSource ID="DS" TypeID="JEE!Microsoft.JEE.Monitoring.UrlProbe.MBeans.DataSource">
<ComputerName>$Target/Host/Property[Type="JEE!Microsoft.JEE.ApplicationServer.Monitored.Instance"]/HostName$</ComputerName>
<Protocol>$Target/Host/Property[Type="JEE!Microsoft.JEE.ApplicationServer.Monitored.Instance"]/Protocol$</Protocol>
<Port>$Target/Host/Property[Type="JEE!Microsoft.JEE.ApplicationServer.Monitored.Instance"]/Port$</Port>
<BaseURL />
<JMXQuery>com.contoso:Name=CustomPerformance,*</JMXQuery>
<AdditionalArguments>&amp;MaxDepth=1</AdditionalArguments>
<IntervalSeconds>300</IntervalSeconds>
<TimeoutSeconds>100</TimeoutSeconds>
</DataSource>
</DataSources>

<ConditionDetection TypeID="Performance!System.Performance.DataGenericMapper" ID="PerfMapper">
<ObjectName>AverageTransactionTime</ObjectName>
<CounterName>AverageTransactionTime</CounterName>
<InstanceName />
<Value>$Data/MBeans/MBean[@Name='com.contoso.ws.CustomPerformance']/Properties/Property[@Name='AverageTransactionTime']$</Value>
</ConditionDetection>

<WriteActions>
<WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData"/>
<WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData"/>
</WriteActions>
</Rule>

 

Finally, this application will appear in the view with all of the rest of the (application server specific) applications (i.e. there is not a new view created for only the Contoso applications. Of course you could do this by simply defining a view that targets your new class.

CustomOrderServiceMonitor.xml

Comments (4)

  1. Anonymous says:

    It works perfectly. Thanks!

  2. Anonymous says:

    I see the TargetApplicationName is hardcoded. Unfortunately, our developers put the version-name in their application name.

    As I do not want my monitoring to stop when they release a new version, is it possible to put a wildcard here?

  3. Anonymous says:

    Yes it is.

    The datasource module type written uses regular expressions to match the application name.

    So try changing

    <TargetApplicationName>CustomOrderService</TargetApplicationName>

    to

    <TargetApplicationName>CustomOrderService.*</TargetApplicationName>

    See below for the relevant module section.

    (Excuse the formatting)

         <DataSourceModuleType ID="Contoso.JEE.SampleApplication.Discovery.DataSource" Accessibility="Public">

           <Configuration>

             <IncludeSchemaTypes>

               <SchemaType>System!System.ExpressionEvaluatorSchema</SchemaType>

             </IncludeSchemaTypes>

    ….

            <xsd:element name="TargetApplicationName" type="xsd:string" />

    ….

          </Configuration>

    ….

            <Composite>

               <MemberModules>

                 <DataSource TypeID="Contoso.SpecializedClass.Discovery.DataSource" ID="Specializer">

                   <ClassId>$Config/ClassId$</ClassId>

                   <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>

                   <Expression>

                     <RegExExpression>

                       <ValueExpression>

                         <Value>$Config/ApplicationName$</Value>

                       </ValueExpression>

                       <Operator>MatchesRegularExpression</Operator>

                       <Pattern>$Config/TargetApplicationName$</Pattern>

                     </RegExExpression>

                   </Expression>

  4. Dhawanmayur says:

    Hi,
    I have created one MP using the above sample. However unable to list theMbeans. How to debug the issue?