Azure OpInsights: Collecting Text Log Files with a custom PowerShell Script

This post demonstrates a way to collect text log files to Microsoft Azure Operational Insights (OpInsights) using a PowerShell-based collection rule or workflow in OpsMgr. This post was inspired by Daniele’s recent post on how to collect text log files to Azure Operational Insights using System Center Operations Manager.

Here is an example of how a custom Error event detected in a text log file, converted and collected by the PowerShell-based rule to OpInsights would look like in the OpInsights Portal.
With a custom PowerShell script, any other machine data related to the event detected can also be collected, like Total % Processor Time, Available Memory or current Log File size in KB etc.

image

With the above custom events collected and stored into OpInsights from OpsMgr, the data can then be analysed with OpInsights’ real-time drill-down + slicing & dicing capabilities, and displayed on a summary dashboard on the Overview page.

image

 

Here are the key elements to create a PowerShell script based workflow to collect text log files to OpInsights:

First, include a reference to the Microsoft.IntelligencePacks.Types library to access the write action to send to OpInsights:

<Reference Alias="IPTypes">
  <ID>
Microsoft.IntelligencePacks.Types</ID>
  <Version>7.0.9802.0</Version>
  < PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
< /Reference>

I created a library management pack back in 2012 that contains a data source module that will allow any PowerShell script to be included in a custom rule’s workflow. Here is the post.
So, I included another reference to that library management pack – Take.A.Wei.MP.Demo.Library as well to access the PowerShell-based data source module:

<Reference Alias="TAWMDL">
  <ID>
Take.A.Wei.MP.Demo.Library</ID>
  <Version>1.0.0.5</Version>
  < PublicKeyToken>5e477fbc309e3f65</PublicKeyToken>
< /Reference>

After that, just replace the data source module in a normal eventlog collection rule with the Powershell.PropertyBag.DataSource data source module from the Take.A.Wei.MP.Demo.Library .
Then, add the PowerShell script name and script into the data source module’s <ScriptName> and <ScriptBody> parameters as follows:
 

< Rule ID="MomUIGeneratedRule2e12ff5e85f748a595bfab827f86204c" Enabled="true" Target="Windows!Microsoft.Windows.Server.Computer" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
< Category>EventCollection</Category>
< DataSources>
<DataSource ID="PSLogDS" TypeID="TAWMDL!Take.A.Wei.MP.Demo.Library.Powershell.PropertyBag.DataSource">
<ScriptName>MyTestEVP.ps1</ScriptName>
< ScriptBody>

$API          = new-object -comObject "MOM.ScriptAPI"
$PropertyBag  = $API.CreatePropertyBag()

$fileName = "C:\testfolder\weioutthereFile.log"

if(Test-Path $fileName)
{
$file = Get-Item $fileName
$fileSizeinKB = $file.Length/1024
$findErrorKeyword = select-string -Pattern "error" -Path $fileName

If($findErrorKeyword.length -gt 0)
{
$cpu = (Get-Counter ("\Processor Information(_Total)\% Processor Time")).CounterSamples[0].CookedValue
$memory = (Get-Counter ("\Memory\Available MBytes")).CounterSamples[0].CookedValue

$Description = "Error keyword found in log file. Total % Processor Time at " + [math]::round($cpu,2) + "% ; Available Memory at " + [math]::round($memory,2) + "MB ; File Size at " + [math]::round($fileSizeinKB,2) + "KB."
$EventLevel = 2
$logcontent = Get-Content -Path $fileName  | Out-String
$Description = $Description + "LogFile Contents: " + $logcontent
}
else 

$Description = "No Error keyword found in log file. File size currently at " + [math]::round($fileSizeinKB,2) + "KB."
$EventLevel = 3
$logcontent = Get-Content -Path $fileName  | Out-String
$Description = $Description + "LogFile Contents: " + $logcontent
}
}
else
{
$Description = "No log file found."
$EventLevel = 4
}

$PropertyBag.AddValue("MyParam1",$EventLevel)
$PropertyBag.AddValue("MyParam2", $Description)
$PropertyBag.AddValue("MyParam3","12134")
$PropertyBag.AddValue("MyParam4", "WOTCustomLog")
$PropertyBag.AddValue("MyParam5", $fileName)

$PropertyBag
< /ScriptBody>
<Parameters />
<TimeoutSeconds>300</TimeoutSeconds>
<IntervalSeconds>3600</IntervalSeconds>
</DataSource>
</DataSources>


Note:
The PowerShell script used in the data source module looks for an error keyword in the weioutthereFile.log file under the C:\testfolder\ path across all Windows Server computers under a specific management group. If an error keyword is detected, additional data on CPU, Memory and the log file size are collected and a Warning Event (EventLevel = 2) is logged. Otherwise, if the file is not found, an Informational Event (EventLevel = 4) is logged.
If the log file is found but there are no error events detected, an EventLevel =3 is logged.
The script runs every hour and is configurable with the <IntervalSeconds> parameter. (Please be mindful of the interval setting to not over collect.)             
Notice that the collected data is added into the property bag and assigned to variables MyParam1 – 5.

Next, just pop the property pag data variables into the corresponding parameters in the “Mapper” condition detection module next in the collection workflow.

<ConditionDetection ID="Mapper" TypeID="System!System.Event.GenericDataMapper">
< EventOriginId>$Target/Id$</EventOriginId>
< PublisherId>$MPElement$</PublisherId>
<PublisherName>$Data/Property[@Name=’MyParam4′]$</PublisherName>
<Channel>$Data/Property[@Name=’MyParam5′]$</Channel>

< LoggingComputer>$Target/Property[Type=’Windows!Microsoft.Windows.Computer’]/PrincipalName$</LoggingComputer>
<EventNumber>$Data/Property[@Name=’MyParam3′]$</EventNumber>
< EventCategory>3</EventCategory>
<EventLevel>$Data/Property[@Name=’MyParam1′]$</EventLevel>
< UserName></UserName>
<Description>$Data/Property[@Name=’MyParam2′]$</Description>
< Params />
</ConditionDetection>

Its interesting to note that the Mapper module’s parameter maps to the event data fields in OpInsights in the following manner:
PublisherName parameter maps to Source field in OpInsights
Channel parameter maps to EventLog field in OpInsights
EventNumber parameter maps to EventID field in OpInsights
EventLevel parameter maps to EventLevel and EventLevelName field in OpInsights
Description parameter maps to Message field in OpInsights

image

Lastly, add the write action module at the end of the workflow to send this data to the cloud:

<WriteActions>
<WriteAction ID="HttpWA" TypeID="IPTypes!Microsoft.SystemCenter.CollectCloudGenericEvent" />
< /WriteActions>

</Rule>

And that’s it ! Once the rule starts running, you will receive the custom event data in OpInsights within 20 minutes.          
         
image

Clicking into (2.) will drill down into all events related to the text log file collected:

image


Drill down further by selecting a specific Event Level:

image


Exporting to an excel spreadsheet from OpInsights:

image


Saving the Search Query, configuring summary dashboard tile and notification when threshold is breached:

image

image

image


The sample MP with the PoweShell script based text log file event collection rule and the Take.A.Wei.MP.Demo.Library pack is now available for download at the TechNet Gallery !

 

Thank you for your support !             


Disclaimer:
All information on this blog is provided on an as-is basis with no warranties and for informational purposes only. Use at your own risk. The opinions and views expressed in this blog are those of the author and do not necessarily state or reflect those of my employer.