One of the powerful authoring capabilities of Visual Studio Authoring Extensions, is the use of “Snippets” to create lots of monitoring workflows with minimal effort. Snippets can be input manually, or they can use a CSV file with the input data already prepared.
I had a request from a customer who needed an MP to monitor a Windows Server Role, but the only Management Pack available was an ancient MOM 2005 conversion MP. So, I decided to create a new management pack that is native for SCOM for the server role. One of the challenges, is that I needed to create about 140 event log rules. This would be very time consuming.
Snippets solve that challenge. Lets have a look.
Open Visual Studio with VSAE installed. New project. Give your project a name. Choose Operations Manager 2007R2 management pack since we wont be doing anything special that could not be used in either version.
First, we should add some references which will be needed for certain types of workflows. Right click “References” in Solution Explorer (at the right) and add references to the appropriate version of the Microsoft.SystemCenter.DataWarehouse.Library and the System.Performance.Library. These should be located on your SCOM 2007 R2 media/management servers, or whatever version of SCOM you are writing the MP’s for.
Next, right click your solution name, add, new Item.
Scroll down to the bottom, and choose “Snippet Template”. Give your template a name, and click OK.
This will add the template to your project in Solution Explorer on the right, and it will throw a bunch of code up. Our default sample is a performance collection rule.
The snippet template will accept a data input variable such as “#text(‘Rule Id’)#” in place of any fixed data that you would find in XML. We want to use these tags to replace the things that would change in a rule, such as the Rule ID, the Perf Counter, Object, Instance, frequency, etc. Review the examples. You have items like #text, #choice, and #alias.
#text we already covered, it will replace that text with whatever we feed it from another source (later). #choice lets you present a comma delimited list of options to the user executing the snippet with snippet data. #alias simply will resolve your references and ensure the correct reference alias is chosen. If you already know what aliases you are using in your manifest section of the XML, you can just hard code these.
Without changing any of the XML – just to show how these work, we will use the Perf Collection rule example. Now, right click the Project again, Add, New Item. Choose “Snippet Data”. Give it a name and click Add. This will bring up a box to select snippet type:
Click that, and it will show all snippet templates in the project.
Choose your snippet template name you created earlier, and click OK.
That’s it! At this point, you can start adding new rules quickly and easily, by supplying the required data, OR you can import a huge list from a CSV you have pre-prepared using Excel.
To demo the “add new item” select that. You can see you are prompted to input the Rule ID, Counter, Object, Instance, and frequency. For each item you add, you are generating lots of new XML.
Fill in a few lines with dummy data.
When complete, click “Save”
Once you save it – you will see a .mpx file under your snippet object in Solution Explorer. Right click it – choose Open. This will show you the XML you just generated that will become simple perf collection rules when you Build the MP.
The example above is a simple one – for Perf Collection. However, I want to use an alert generating rule, so what I will do is open the XML of some sample MP I already have with a good Alert generating Event rule, and copy/replace the perf collection XML sample with my own.
The snippet template will accept a data input variable such as “#text(‘Rule Id’)#” in place of any fixed data that you would find in XML. We want to use these tags to replace the things that would change in an event log rule, such as the Rule ID, the event ID, the alert name, and any display name data for each in the display strings.
So – I Add a New Item, Snippet Template, and name it DemoEventRules.templatesnippet and click Add.
Now, I replace the XML with a rule I have already written from a previous MP. This includes the section under <Rules> and <Presentation> and <DisplayStrings>. Here is my initial sample MP Fragment:
<ManagementPackFragment SchemaVersion="1.0"> <Monitoring> <Rules> <Rule ID="ruletest.testrulename" Enabled="true" Target="Windows!Microsoft.Windows.Server.OperatingSystem" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100"> <Category>Alert</Category> <DataSources> <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.EventProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName> <LogName>System</LogName> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="UnsignedInteger">EventDisplayNumber</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="UnsignedInteger">4000</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">PublisherName</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">MyEventSource</Value> </ValueExpression> </SimpleExpression> </Expression> </And> </Expression> </DataSource> </DataSources> <WriteActions> <WriteAction ID="Alert" TypeID="Health!System.Health.GenerateAlert"> <Priority>1</Priority> <Severity>1</Severity> <AlertName /> <AlertDescription /> <AlertOwner /> <AlertMessageId>$MPElement[Name="ruletest.testrulename.AlertMessage"]$</AlertMessageId> <AlertParameters> <AlertParameter1>$Data/EventDescription$</AlertParameter1> </AlertParameters> <Suppression> <SuppressionValue>$Data/EventDisplayNumber$</SuppressionValue> <SuppressionValue>$Data/PublisherName$</SuppressionValue> <SuppressionValue>$Data/LoggingComputer$</SuppressionValue> </Suppression> <Custom1 /> <Custom2 /> <Custom3 /> <Custom4 /> <Custom5 /> <Custom6 /> <Custom7 /> <Custom8 /> <Custom9 /> <Custom10 /> </WriteAction> </WriteActions> </Rule> </Rules> </Monitoring> <Presentation> <StringResources> <StringResource ID="ruletest.testrulename.AlertMessage" /> </StringResources> </Presentation> <LanguagePacks> <LanguagePack ID="ENU" IsDefault="true"> <DisplayStrings> <DisplayString ElementID="ruletest.testrulename"> <Name>Test Rule Display Name</Name> </DisplayString> <DisplayString ElementID="ruletest.testrulename.AlertMessage"> <Name>Custom Alert Name Here</Name> <Description>Event Description: {0}</Description> </DisplayString> </DisplayStrings> </LanguagePack> </LanguagePacks> </ManagementPackFragment>
Now I will proceed to add in the variable input tags. You can reuse the same tag in multiple places and only provide a single input for that as your CSV.
When I am done with all my tag edits, my MP fragment looks like this:
<ManagementPackFragment SchemaVersion="1.0"> <Monitoring> <Rules> <Rule ID="#text('RuleId')#" Enabled="#text('Enabled')#" Target="Windows!Microsoft.Windows.Server.OperatingSystem" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100"> <Category>Alert</Category> <DataSources> <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.EventProvider"> <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName> <LogName>#text('LogName')#</LogName> <Expression> <And> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="UnsignedInteger">EventDisplayNumber</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="UnsignedInteger">#text('EventId')#</Value> </ValueExpression> </SimpleExpression> </Expression> <Expression> <SimpleExpression> <ValueExpression> <XPathQuery Type="String">PublisherName</XPathQuery> </ValueExpression> <Operator>Equal</Operator> <ValueExpression> <Value Type="String">#text('EventSource')#</Value> </ValueExpression> </SimpleExpression> </Expression> </And> </Expression> </DataSource> </DataSources> <WriteActions> <WriteAction ID="Alert" TypeID="Health!System.Health.GenerateAlert"> <Priority>1</Priority> <Severity>#text('Severity')#</Severity> <AlertName /> <AlertDescription /> <AlertOwner /> <AlertMessageId>$MPElement[Name="#text('RuleId')#.AlertMessage"]$</AlertMessageId> <AlertParameters> <AlertParameter1>$Data/EventDescription$</AlertParameter1> </AlertParameters> <Suppression> <SuppressionValue>$Data/EventDisplayNumber$</SuppressionValue> <SuppressionValue>$Data/PublisherName$</SuppressionValue> <SuppressionValue>$Data/LoggingComputer$</SuppressionValue> </Suppression> <Custom1 /> <Custom2 /> <Custom3 /> <Custom4 /> <Custom5 /> <Custom6 /> <Custom7 /> <Custom8 /> <Custom9 /> <Custom10 /> </WriteAction> </WriteActions> </Rule> </Rules> </Monitoring> <Presentation> <StringResources> <StringResource ID="#text('RuleId')#.AlertMessage" /> </StringResources> </Presentation> <LanguagePacks> <LanguagePack ID="ENU" IsDefault="true"> <DisplayStrings> <DisplayString ElementID="#text('RuleId')#"> <Name>#text('RuleDisplayName')#</Name> </DisplayString> <DisplayString ElementID="#text('RuleId')#.AlertMessage"> <Name>#text('RuleAlertName')#</Name> <Description>Event Description: {0}</Description> </DisplayString> </DisplayStrings> </LanguagePack> </LanguagePacks> </ManagementPackFragment>
Once I am happy, save the DemoEventRules.templatesnippet.
Now, add a new item, Snippet Data, and provide a name like DemoEventRulesData.mpsd and click Add. Choose our new snippet template from the list:
This time, in the upper right corner, choose “Import from CSV” and browse to a prepared CSV file. Your CSV will need to be in the order of tags in your XML, which is visible in the rows in the Snippet Data:
I will choose a CSV that I have prepped for this, which is a bunch of event rules for WINS in the System Event log. Here in an excerpt:
I select the CSV and click Open. I can now review all the input data:
If I am happy – click “Save” icon at the top.
Now I can review the XML generated, by opening the .mpx file under my Snippet Data MPSD file in Solution Explorer. If it took correctly, then you will see LOTS of XML. If it didn’t, look at the bottom “Error List” and review any issues. One thing I notices is that Excel likes to auto case “TRUE” and “FALSE” in all caps. This must be lower case for XML.
When done, you can click “Build” and “Build Solution” at the top, and it will generate your XML. This will be located at C:\Users\username\Documents\Visual Studio 2013\Projects\DemoSnippets\DemoSnippets\bin\Debug\ by default.
As you can see, using snippets and XML MP fragments is a great way to generate a lot of data, quite quickly.
I will attach my CSV file and MP XML in a zip file below, for your reference.