Showing posts with label performance data. Show all posts
Showing posts with label performance data. Show all posts

Thursday, June 2, 2016

OpsMgr (SCOM) - Management Servers Services Status and System Consumption

Some Operations Manager installations just go off the marks when it comes to memory and processor utilization by SCOM services (omsdk, healthservice and cshost).
So, it might be useful to know what's going on your servers, specially when you apply a new MP, or change any other configuration.
In my particular case i just found out that a bunch of gateway servers went to it's limit in Unix/Linux monitoring.
So, i made this Powershell script that retrieves me :
Management Server | Service Name | Service Status | Service PID | CPU Time | Private Bytes

Basically i just make some WMI queries to each MS i've got and put all the info i retrieve in a fancy HTML table.

Well, the output :

And the most important, the code:
 Import-Module OperationsManager  
 New-SCOMManagementGroupConnection -ComputerName $env:computername  
 $managementServers = (Get-SCOMManagementServer).DisplayName  
 $Head = "<style>"  
 $Head +="BODY{background-color:White;font-family:Verdana,sans-serif; font-size: x-small;}"  
 $Head +="TABLE{font-family: verdana,arial,sans-serif; font-size:9px; color:#333333; border-width: 1px; border-color: #666666; border-collapse: collapse;}"  
 $Head +="TH{border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #dedede;}"  
 $Head +="TD{border-width: 1px; padding: 8px; border-style: solid;}"  
 $Head +="</style>"  
 $myStatus = "<br><br>"  
 # Your logo (if any) goes here :)  
 $myStatus += "<img src='.\images\logo' height='12%' width='12%'>"  
 $myStatus += "<center><h1 style=color:#999999>.: (OpsMgr) Management Servers - Services Status :.</center>"  
 $myStatus += "<table>"  
 $myStatus += "<tr>"  
 $myStatus += "<td>Management Server</td>"  
 $myStatus += "<td>Service</td>"  
 $myStatus += "<td>Status</td>"  
 $myStatus += "<td>PID</td>"  
 $myStatus += "<td>Processor Time</td>"  
 $myStatus += "<td>Private Bytes (in MB)</td>"  
 $myStatus += "</tr>"  
 foreach ( $ms in $managementServers ) {  
   $perflist = (get-wmiobject Win32_PerfFormattedData_PerfProc_Process -ComputerName $ms)   
   $services = @("HealthService","OMSDK","cshost")  
   foreach ($service in $services) {   
     $mypid = Get-WmiObject win32_service -ComputerName $ms | ?{$_.Name -like "$service" } | select -ExpandProperty ProcessId  
     $procStatus = (Get-Service -ComputerName $ms -Name $service).Status  
     $cpuCon = ($perflist | ? {$_.IDProcess -eq "$mypid" }).PercentProcessorTime  
     $privBytes = [math]::Round((($perflist | ? {$_.IDProcess -eq "$mypid" }).PrivateBytes / 1MB))  
     $myStatus += "<tr>"  
     $myStatus += "<td>$ms</td>"  
     $myStatus += "<td>$service</td>"  
     $myStatus += "<td>$procStatus</td>"  
     $myStatus += "<td>$mypid</td>"  
     $myStatus += "<td>$cpuCon</td>"  
     $myStatus += "<td>$privBytes</td>"  
     $myStatus += "</tr>"  
   }  
 }  
 $myStatus += "</table>"  
 $HTML = ConvertTo-Html -Head $head -Body $myStatus  
 $HTML > 1.html  

Cheers,

Tuesday, April 12, 2016

OpsMgr (SCOM) - Visual Studio Report (System Drive Available Space)

Challanged by a local PFE friend to start using Visual Studio to create my reports, and keeping in mind i'm no SQL expert, and no Report-Builder greatest fan, i tried to make a costumers request on specific report they wanted (C: Drive available Space)!

So, since i'm kind new to Visual Studio, and to this scenario in general, i decided to make this how to, and obviously, share it here.

So! Let's open Visual Studio and click NEW!

And then :



You'll have a blank report, so we need to add a datasource (from where you'll get your data from!)
(Since we're using OpsMgrDW database...)



Then, add a dataset (it's a query!) :)

This one i used!

 SELECT DISTINCT VME.Path AS Agente, DISKs.SystemDiskUsed AS FreePercentage, DISKs.SystemDiskFreeMB AS FreeMB  
 FROM Perf.vPerfDaily AS PERF   
 INNER JOIN vManagedEntity AS VME ON PERF.ManagedEntityRowId = VME.ManagedEntityRowId   
 INNER JOIN vPerformanceRuleInstance AS PRI ON PRI.PerformanceRuleInstanceRowId = PERF.PerformanceRuleInstanceRowId   
 INNER JOIN vPerformanceRule AS PR ON PR.RuleRowId = PRI.RuleRowId   
 LEFT OUTER JOIN  
 (  
     SELECT ME.Path AS Computer,  
     AVG(CASE WHEN PR.CounterName = '% Free Space' THEN PERF.AverageValue END) AS SystemDiskUsed,   
     AVG(CASE WHEN PR.CounterName = 'Free Megabytes' THEN PERF.AverageValue END) AS SystemDiskFreeMB  
     FROM Perf.vPerfDaily AS PERF   
     INNER JOIN vPerformanceRuleInstance AS PRI ON PRI.PerformanceRuleInstanceRowId = PERF.PerformanceRuleInstanceRowId  
     INNER JOIN vPerformanceRule AS PR ON PR.RuleRowId = PRI.RuleRowId  
     INNER JOIN vManagedEntity AS ME ON PERF.ManagedEntityRowId = ME.ManagedEntityRowId  
     WHERE (PERF.DateTime > DATEADD(Day, - 7, GETDATE()))   
     AND (PR.CounterName = '% Free Space'   
     OR PR.CounterName = 'Free Megabytes') AND (PRI.InstanceName = 'C:')  
     GROUP BY ME.Path, PRI.InstanceName  
 ) AS DISKs ON VME.Path = DISKs.Computer  
 WHERE (PERF.DateTime > GETUTCDATE() - 2)   
 AND (PR.CounterName LIKE '% Free Space')  
 AND (PRI.InstanceName LIKE 'C:')  
 ORDER BY FreeMB  

















Then, add a matrix, with that dataset.



Add a logo you may want (Company logo perhaps!):


Change the expression value for the FreeMB (Just a tweak to look better!)


So, now, let's add some colour to it with a new row with a 'progress bar'.
First, add the row:


Then, insert the 'Data Bar'



For the 'progress bar' you added, change the values of its expression like : 


And the values of the series fill propreties, just to make it RED when is bellow a threshold you define.


As you did for the FreeMB field, do the same for the Free% :


Run the preview and you'll get :


And that's it! :)
Save the project, copy the RDL file into your Reporting Services server and schedule it!

In the future i'll make other posts like this, now that i'm a Visual Studio rookie :)

Cheers :)

Thursday, April 7, 2016

OpsMgr (SCOM) - Create Performance Charts in Powershell

It might be usefull for people who don't have Datazen or just want to create and manage their own costumized HTML views, or perhaps, for fun!

Powershell is one of the things i like the most while exploring everything that SCOM (and other System Center tools) can give to you, it just makes everything you want, a way or another.

So.

What about creating this in a Powershell script ?











This is the script that does all the magic :

!!NOTE!! : For the most problematic servers in specific groups i've i retrieve memory, cpu, and disk usage performance data, but, you change this logic as well as the performance counters.

Please attempt to the comments in-line so you can understand the logic :)
 [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")  
 Import-Module OperationsManager  
 New-SCOMManagementGroupConnection -ComputerName "opsmgr.server.local" #Change here :)  
 $script:scriptpath = "C:\PS\OpsMgr_PerfCharts\images"  
   
 # Foreach Group above list the most problematic agents   
   
 $MyGroups = @()  
 $MyGroups += Get-SCOMGroup -DisplayName 'UNIX/Linux Computer Group'  
 $MyGroups += Get-SCOMGroup -DisplayName 'All Windows Computers'  
 $newTime = (Get-Date).AddHours(-24)  
 $Criteria = New-Object Microsoft.EnterpriseManagement.Monitoring.MonitoringAlertCriteria("TimeRaised > `'$newTime`'")  
 $TransversalDepth = [Microsoft.EnterpriseManagement.Common.TraversalDepth]::Recursive  
 $TopAgents = @()  
 Foreach ( $Group in $MyGroups ) {  
   $TopObjAlerts = ($Group.GetMonitoringAlerts($Criteria , $TransversalDepth) | Group-Object MonitoringObjectPath | Sort-Object count -descending | select -first 5 Values).Values  
   Foreach ($i in $TopObjAlerts) {  
     $TopAgents += ($i -split ";")[0]  
   }  
   $TopAgents = $TopAgents.Split(";",[System.StringSplitOptions]::RemoveEmptyEntries)  
 }  
 $Count = 0  
 $Query = ""  
 Foreach ($Agent in $TopAgents) {  
   If ($TopAgents.Count -eq $Count ) {  
     $Query += "'" + $agent + "'" + ","  
   } Else { $Query += "'" + $agent + "'" }  
   $Count++  
 }  
   
 # Create SQL Query with the most problematic agents criteria   
   
 $Query = $Query -replace "''","','"  
   
 $SqlQuery = "  
 SELECT          
     Path,  
     DateTime,  
     CASE   
     WHEN vpr.ObjectName = 'Processor Information' THEN 'Processor'  
     WHEN vpr.ObjectName = 'LogicalDisk' THEN 'Logical Disk' ELSE vpr.ObjectName END as ObjectName,  
 CASE   
     WHEN vpr.CounterName = 'PercentMemoryUsed' OR vpr.CounterName = '% Available Memory' THEN '% Used Memory'   
     WHEN vpr.CounterName = '% Free Space' THEN '% Used Space'  
     ELSE vpr.CounterName END as CounterName,  
 CASE   
     WHEN len(vpri.InstanceName) < 1 THEN '_Total' ELSE vpri.InstanceName END as InstanceName,  
 CASE   
     WHEN vpr.CounterName = '% Available Memory' or vpr.CounterName = '% Free Space' THEN 100 - pvpr.AverageValue ELSE pvpr.AverageValue END as AverageValue,  
 100.00 as ComparisonValue  
 FROM   
     Perf.vPerfDaily pvpr WITH (NOLOCK)   
     inner join vManagedEntity vme WITH (NOLOCK) on pvpr.ManagedEntityRowId = vme.ManagedEntityRowId   
     inner join vPerformanceRuleInstance vpri WITH (NOLOCK) on pvpr.PerformanceRuleInstanceRowId = vpri.PerformanceRuleInstanceRowId   
     inner join vPerformanceRule vpr WITH (NOLOCK) on vpr.RuleRowId = vpri.RuleRowId   
 WHERE  
     Path in (  
         select   
             unix.DisplayName  
         from   
             vManagedEntity unix WITH (NOLOCK)   
             join vManagedEntityManagementGroup unixMG WITH (NOLOCK) ON unix.ManagedEntityRowId = unixMG.ManagedEntityRowId  
             join vManagedEntityType unixType WITH (NOLOCK) on unix.ManagedEntityTypeRowId = unixType.ManagedEntityTypeRowId  
         where   
             unixMG.ToDateTime Is Null   
             and (unixType.ManagedEntityTypeSystemName = 'Microsoft.Unix.Computer'   
             or unixType.ManagedEntityTypeSystemName = 'Microsoft.Windows.Computer' )  
             AND vpr.ObjectName <> 'Process'  
             AND unix.DisplayName IN ( $Query )  
     )  
 AND vpr.CounterName in ('% Processor Time','PercentMemoryUsed','% Available Memory','% Free Space')  
 AND vpri.InstanceName in ('_Total','C:','/','')  
 AND DATEDIFF(DAY, pvpr.DateTime, GETDATE()) < 8  
 "  
   
 $SqlQuery > $env:TEMP\query.sql  
   
 $SqlQuery = Get-Content $env:TEMP\query.sql  
   
 # Create connection to SCOMDW Database   
   
 $script:SQLServer = "SCOMDBSERVER\SCOMDW"  
 $script:SQLDBName = "OperationsManagerDW"  
 $script:connString = "Data Source=$SQLServer;Initial Catalog=$SQLDBName;Integrated Security = True"  
 $script:connection = New-Object System.Data.SqlClient.SqlConnection($connString)  
 $connection.Open()  
 $sqlcmd = $connection.CreateCommand()  
 $sqlcmd.CommandText = $SqlQuery  
 $results = $sqlcmd.ExecuteReader()  
 $script:table = new-object “System.Data.DataTable”  
 $script:table.Load($results)  
   
 # Lets GRAPH!  
   
 $Servers = ($table | Select -Unique Path).Path  
 # 1 Graph foreach Agent   
 Foreach ( $Server in $Servers ) {  
   $Server = ($Server -split '\.')[0]  
   $GraphName = $Server  
   # Create CHART   
   $GraphName = New-object System.Windows.Forms.DataVisualization.Charting.Chart  
   $GraphName.Width = 900  
   $GraphName.Height = 300  
   $GraphName.BackColor = [System.Drawing.Color]::White  
   # CHART Title  
   [void]$GraphName.Titles.Add("$Server - Performance Data")  
   $GraphName.Titles[0].Font = "Arial,10pt"  
   $GraphName.Titles[0].Alignment = "MiddleCenter"  
   # CHART Area and X/Y sizes   
   $chartarea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea  
   $chartarea.Name = "ChartArea"  
   $chartarea.AxisY.Title = "$CounterName"  
   $chartarea.AxisX.Title = "Time"  
   $chartarea.AxisY.Maximum = 100  
   $chartarea.AxisY.Interval = 10  
   $chartarea.AxisX.Interval = 1  
   $GraphName.ChartAreas.Add($chartarea)  
   # CHART Legend  
   $legend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend  
   $legend.name = "Legend"  
   $GraphName.Legends.Add($legend)  
     # Line Colors  
     $num = 0  
   $LineColours = ('DarkBlue','Brown','DarkMagenta')  
   # Create 'n' SERIES (lines) for each COUNTER  
   Foreach ($Counter in $Counters) {  
     $LineColor = $LineColours[$num]  
     [void]$GraphName.Series.Add("$Counter")  
     $GraphName.Series["$Counter"].ChartType = "Line"  
     $GraphName.Series["$Counter"].BorderWidth = 2  
     $GraphName.Series["$Counter"].IsVisibleInLegend = $true  
     $GraphName.Series["$Counter"].chartarea = "ChartArea"  
     $GraphName.Series["$Counter"].Legend = "Legend"  
     $GraphName.Series["$Counter"].color = "$LineColor"  
     ForEach ($i in ($table | ? { $_.ObjectName -eq $Counter -and $_.Path -like "$Server*" }) ) {   
       $GraphName.Series["$Counter"].Points.addxy( ($i.DateTime -split ' ')[0] , $i.AverageValue )   
     }  
     $num++ # Next Color :)  
   }  
   $GraphName.SaveImage("$scriptpath\$Server.png","png") # Save the GRAPH as PNG  
 }  

Have fun! :)