sraposo

PowerShell approach to retrieve analysis run time statistics

Blog Post created by sraposo on Dec 18, 2019

"Is it possible to monitor the performance of specific analyses? Currently we use the PI Analysis Service performance counters which are great at providing an overview of the performance of the service, but not of specific analyses." 

 

"Can you retrieve the run time statistics of analyses using PowerShell? How can you gather the data in a useful manner? Do you have an example script that you can provide?" 

 

I've heard these questions quite a few times over the years, I figured I'd post here to answer them. Nitin Agarwal actually answered the first set of questions in his great blog post. To answer the second set of questions, I'll assume that the reader has read Nitin's blog post and is somewhat familiar with analysis statistics and very familiar with PowerShell and .NET programming. 

 

The answer is yes it is possible to retrieve the run time statistics of analyses using PowerShell in a useful manner. I've provided an example script at the end of this post to retrieve most of the statistic fields for all running analyses. As a suggestion, copy/paste the script into PowerShell's ISE to make it a little easier to read 

The output is a CSV file, the first column is the timestamp of when the statistics were retrieved, the other columns are fields for a single analysis. 

 

As is the script is probably not that helpful. This is intentional, as most have different use cases, some tweaking will need to be done. At a minimum though, the CSV can be opened and analyzed in Excel and provide some value.

 

Here are some examples on how this script / approach can be improved: 

  • The script could run periodically. You will need to modify how the output is generated. This could be done using: 
    • Task Scheduler to run the script on an interval
    • Infinite While loop with the Start-Sleep cmdlet to pause between executions. The script can be started with Task Scheduler when the machine starts up. If running on the machine running the PI AF Application or PI Analysis Service, there has to be a delay after startup. 
  • The CSV file can be parsed by the PI UFL connector and the data written to PI Points. You could then use any visualization tools to analyze the data (for example a PI Vision display!). 
  • Instead of outputting to a CSV, the script could monitor the statistics and generate Event Frames when a certain statistic is out of range. PI Notifications could then be used to notify PI Admins of an issue. 
  • Etc... with imagination and dedication anything is possible! 

 

I'm still learning PowerShell, if anything in this script isn't aligned with best practices, please let me know so I can learn more ! Hope this helps.... 

 

<# The below example is offered as is, for more
information refer to: Apache License, Version 2.0 
Questions in the comment section of the PI Square blog post
associated to this script are welcomed!#>

function Logger
{
param(
[Parameter(Mandatory=$true)]
[String] $logMsg
)

$logFilePath = "C:\PowerShellExamples\LogFile.txt"

try
{
(Get-Date).ToString() + " |ERROR| " + $logMsg | Out-File -FilePath $logFilePath -append
}
catch
{
Write-Error "Unable to write to Log File, does the user running this script have the right permissions? Log message that was meant to be written to log file is: $logMsg"
}

}

try
{
[Reflection.Assembly]::LoadWithPartialName("OSIsoft.AFSDK") | Out-Null
}
catch
{
Logger -logMsg "Couldn't load AF SDK. Is the AF Client installed on this machine?"

}

$afServerName = "myAFServer"
$outputCSVFilePath = "C:\PowerShellExamples\AnalysisStatistics.csv"

[OSIsoft.AF.PISystems] $afServers = new-object OSIsoft.AF.PISystems

[OSIsoft.AF.PISystem] $afServer = $AFServers[$AFServerName]

$query = "status:'Running' sortBy:'averageLag' sortOrder:'Desc'"
$fields = "ID path status statusDetail lastEvaluationStatus lastEvaluationStatusDetail lastLag averageLag lastElapsed averageElapsed lastTriggerTime averageTrigger successCount errorCount skipCount"

try
{
"TimeStamp," + $fields.Replace(" ", ",") | out-file -FilePath $outputCSVFilePath
}
catch
{
Logger -logMsg "Couldn't write to the output CSV file. Does the user running this PowerShell script have the proper permissions?"
}

try
{
$runTimeStatistics = $afServer.AnalysisService.QueryRuntimeInformation($query,$fields)
}
catch
{
Logger -logMsg "Couldn't retrieve the statistics from the PI Analysis Service. Are both the PI Analysis Service and PI AF Application service running?"
}


$timeStamp = get-date

foreach ($analysiStatistics in $runTimeStatistics)
{
[string] $outString = "$timeStamp,"

for($i=0;$i -lt $analysiStatistics.Count; $i++)
{

$outString = $outString + $analysiStatistics[$i] + ","

}

try
{
$outString.Substring(0,$outString.Length-1) | out-file -FilePath $outputCSVFilePath -append
}
catch
{
Logger -logMsg "Couldn't write to the output CSV file."
}


}

Outcomes