{"id":15721,"date":"2011-02-02T00:01:00","date_gmt":"2011-02-02T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/02\/02\/use-powershell-to-parse-saved-performance-counter-logs\/"},"modified":"2011-02-02T00:01:00","modified_gmt":"2011-02-02T00:01:00","slug":"use-powershell-to-parse-saved-performance-counter-logs","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-parse-saved-performance-counter-logs\/","title":{"rendered":"Use PowerShell to Parse Saved Performance Counter Logs"},"content":{"rendered":"<p><b>Summary<\/b>: Learn how to use the <b>Import-Counter<\/b> cmdlet in Windows PowerShell to parse saved performance counter log files.<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Question\" border=\"0\" title=\"Hey, Scripting Guy! Question\" \/><\/p>\n<p>Hey, Scripting Guy! We have configured a series of custom performance monitor logs that run as scheduled tasks and collect monitoring information. The problem is that I never seem to have time to run Performance Monitor to review these logs. Is there a way I can use Windows PowerShell to automate some of this?<\/p>\n<p>&mdash;CP<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Answer\" border=\"0\" title=\"Hey, Scripting Guy! Answer\" \/> Hello CP, <\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, here. It is still cold here in Charlotte, North Carolina in the United States. My trip to Florida for SQL Saturday in Tampa was a welcome respite from the cold weather. In addition to warming up from the cold, I was able to get a lot of work done during the ride as the Scripting Wife drove. I love working while traveling because there is a complete lack of distraction. At home, there is always my book case of technical books that beckon to me. <\/p>\n<p>CP, as I answer your email, I am sipping on a cup of English Breakfast Tea with a cinnamon stick for sweetener, and I am covered up with a blanket. I am beginning to wonder if I should wrap my teapot with an insulating blanket as well, but so far, the heavy ceramic seems to be doing just fine. The secret is to preheat the pot prior to adding the hot water and the tea. <\/p>\n<p>Just as the performance of a teapot is improved with a bit of judicious monitoring and tweaking, so too is the performance of a server or workstation. Personally, I love PerfMon (that is the executable name of Performance Monitor and my personal term of endearment) and at one point I thought about writing a book about it&mdash;instead, I wrote a book about VBScript and the rest, as they say, is history. Now with the performance counter cmdlets in Windows PowerShell, I get to combine two of my passions. <\/p>\n<p>The first thing I want to do is to create my own data collector set. The easiest way to do this is to open the Performance Monitor tool (Start\/All Programs\/Administrative Tools\/Performance Monitor, or type perfmon<i> <\/i>in the Start\/Search All Programs and Files text box). After Performance Monitor is running, select <b>Performance Monitor<\/b> from the left action pane. Now add the counters that you want to include in your Data Collector Sets. You add the counters by clicking the green plus (+) sign on the tool bar. After you click the green plus sign, you are able to select the counter category and drill down to individual counters. This technique is shown in the following screen shot.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/4062.HSG-2-2-11-01_7070FCA3.jpg\"><img decoding=\"async\" height=\"446\" width=\"604\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/6138.HSG-2-2-11-01_thumb_46CD0BA3.jpg\" alt=\"Image of AddCounters dialog box\" border=\"0\" title=\"Image of AddCounters dialog box\" style=\"border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px\" \/><\/a><\/p>\n<p>The nice thing about using the Performance Monitor tool to add counters is that it is easy to see the available instances of the counter. This means that you can add the __Total of all the instances, or you can add individual counter instances. The process is as easy as selecting the instance from the list, and clicking the <b>Add<\/b> button. This process is shown in the following screen shot.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/2806.HSG-2-2-11-02_2977B3D9.jpg\"><img decoding=\"async\" height=\"429\" width=\"604\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/5633.HSG-2-2-11-02_thumb_3D249D6D.jpg\" alt=\"Image of counter choices\" border=\"0\" title=\"Image of counter choices\" style=\"border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px\" \/><\/a><\/p>\n<p>After you have added the counters, look at the Performance Monitor chart, and examine each of the counters to see if they are returning the type of data that you wish to collect. I like to start at the top of the list of counters, and use the Control+H keyboard shortcut to highlight the selected counter. I can then use the Down arrow to view each of the counters in turn. If a counter shows a flat line, I may need to modify the default scale by choosing a different unit value. The Performance Monitor chart is shown in the following screen shot.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/8360.HSG-2-2-11-03_42930E11.jpg\"><img decoding=\"async\" height=\"422\" width=\"604\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/1016.HSG-2-2-11-03_thumb_6C26D944.jpg\" alt=\"Image of Performance Monitor chart\" border=\"0\" title=\"Image of Performance Monitor chart\" style=\"border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px\" \/><\/a><\/p>\n<p>When everything is working the way I like, I right-click the Performance Monitor tool from the <b>Action<\/b> menu in the left pane, and I select <b>New Data Collector Set<\/b>. The advantage of this is that I can give it a custom name, select a custom directory for storing the data (by default it saves in the %systemdrive%\\PerfLogs\\Admin\\ folder), I can also select the user account that will be used when the Data Collector Set runs (by default it runs using the System account). This is shown in the following screen shot.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/0830.HSG-2-2-11-04_43A7F730.jpg\"><img decoding=\"async\" height=\"449\" width=\"604\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/0841.HSG-2-2-11-04_thumb_08741B65.jpg\" alt=\"Image of Data Collector Set dialog box\" border=\"0\" title=\"Image of Data Collector Set dialog box\" style=\"border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px\" \/><\/a><\/p>\n<p>When all this is accomplished, the Data Collector Set appears in the User Defined Data Collector Sets portion of the Performance Monitor tool. This is shown in the following screen shot.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/2084.HSG-2-2-11-05_1495958C.jpg\"><img decoding=\"async\" height=\"422\" width=\"604\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/metablogapi\/1488.HSG-2-2-11-05_thumb_1350FCAD.jpg\" alt=\"Image of Performance Monitor menu\" border=\"0\" title=\"Image of Performance Monitor menu\" style=\"border-bottom: 0px;border-left: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px\" \/><\/a><\/p>\n<p>After I have run the Data Collector Set, I can import the performance information into a variable by using the <b>Import-Counter<\/b> Windows PowerShell cmdlet. I specify the variable to hold the data and the path to the saved Data Collector Set file. The command to do this is shown here.<\/p>\n<blockquote>\n<p>$data = Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217;<\/p>\n<\/blockquote>\n<p>After I have imported the counter set into a variable, I can use the techniques I discussed in <a target=\"_blank\" href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/01\/31\/use-powershell-to-simplify-collecting-performance-information.aspx\">Monday&rsquo;s Hey, Scripting Guy! Blog post<\/a> to parse the data.<\/p>\n<p>If I want to see what Performance Counter Sets are captured in the System Monitor Log file, I use the <b>ListSet<\/b> parameter as illustrated here. (This is a single logical command that I broke at the pipeline character (|) so that the command would fit the blog format.) <\/p>\n<blockquote>\n<p>PS C:\\&gt; Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; -ListSet * | <\/p>\n<\/blockquote>\n<blockquote>\n<p>Select-Object CounterSetName<\/p>\n<p>CounterSetName<\/p>\n<p>&#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n<p>Processor Information<\/p>\n<p>PhysicalDisk<\/p>\n<p>Network Interface<\/p>\n<p>Memory<\/p>\n<\/blockquote>\n<p>Although the previous command gives me an indication of the type of data that is recorded in the log file, it does not tell me specifically what the log contains. To do this, I pipe the results to the <b>Select-Object<\/b> cmdlet and expand the <b>Paths<\/b> property. This technique is shown here. (This is a single logical command that I broke at the pipeline character (|) so that the command would fit the blog format.)<\/p>\n<blockquote>\n<p>PS C:\\&gt; Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; -ListSet * | <\/p>\n<p>Select-Object paths -ExpandProperty paths<\/p>\n<p>\\\\MRED1\\Processor Information(*)\\% Processor Time<\/p>\n<p>\\\\MRED1\\PhysicalDisk(*)\\% Disk Time<\/p>\n<p>\\\\MRED1\\PhysicalDisk(*)\\Avg. Disk Queue Length<\/p>\n<p>\\\\MRED1\\PhysicalDisk(*)\\% Disk Read Time<\/p>\n<p>\\\\MRED1\\PhysicalDisk(*)\\% Disk Write Time<\/p>\n<p>\\\\MRED1\\Network Interface(*)\\Bytes Received\/sec<\/p>\n<p>\\\\MRED1\\Network Interface(*)\\Bytes Sent\/sec<\/p>\n<p>\\\\MRED1\\Network Interface(*)\\Bytes Total\/sec<\/p>\n<p>\\\\MRED1\\Network Interface(*)\\Current Bandwidth<\/p>\n<p>\\\\MRED1\\Memory\\% Committed Bytes In Use<\/p>\n<p>\\\\MRED1\\Memory\\Available MBytes<\/p>\n<\/blockquote>\n<p>After I see which counter instances are stored in the log file, I may decide that I only want to retrieve data from one of the counters. To do this, I use the counter paths that I obtained from the previous command. One thing that you may want to do is to specify the <b>ErrorAction<\/b><i> <\/i>preference for the command. This is because the <b>Import-Counter<\/b> cmdlet displays an error if a negative value is detected when importing the log. Personally, I find the error distracting, and I prefer to not see the message. The error message is shown here.<\/p>\n<blockquote>\n<p>Import-Counter: A counter with a negative denominator value was detected.<\/p>\n<\/blockquote>\n<blockquote>\n<p>At line:1 char:21<\/p>\n<p>+ $proc=Import-Counter &lt;&lt;&lt;&lt; -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; -counter &#8220;\\Processor Information(*)\\% Processor Time&#8221;<\/p>\n<p>+ CategoryInfo : InvalidResult: (:) [Import-Counter], Exception<\/p>\n<p>+ FullyQualifiedErrorId : CounterApiError,Microsoft.PowerShell.Commands.ImportCounterCommand<\/p>\n<\/blockquote>\n<p>The command I use to import only the percentage of processor time is shown here. <\/p>\n<blockquote>\n<p>PS C:\\&gt; $proc=Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; -counter &#8220;\\Process<\/p>\n<p>or Information(*)\\% Processor Time&#8221; -EA silentlycontinue<\/p>\n<p>PS C:\\&gt;<\/p>\n<\/blockquote>\n<p>The next thing I need to know is the time span of the log. To do this, I store the sorted results of the log in a variable. I then index into the array of data to retrieve the beginning and the ending time stamps. Because an array is zero-based, I need to use the <b>count-1<\/b> property. This technique is shown here. (This is a single logical command that I broke at the pipeline character (|) so that the command would fit the blog format.)<\/p>\n<blockquote>\n<p>PS C:\\&gt; $time = Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; | <\/p>\n<p>Sort-Object -Property timestamp<\/p>\n<p>PS C:\\&gt; $time[0].timestamp<\/p>\n<p>Monday, January 24, 2011 10:43:26 AM<\/p>\n<p>PS C:\\&gt; $time[$time.count-1].timestamp<\/p>\n<p>Monday, January 24, 2011 11:03:47 AM<\/p>\n<\/blockquote>\n<p>If the time span of the log is good, I can simply work with the data that I imported into the variable. On the other hand, if I wish to &ldquo;re-log&rdquo; the data and select a custom time range, I can do that by specifying values for the <b>starttime<\/b><i> <\/i>and<i> <\/i><b>endtime<\/b><i> <\/i>parameters that fall within the time range of the log. Because the <b>starttime<\/b><i> <\/i>and the <b>endtime<\/b><i> <\/i>parameters expect <b>System.DataTime<\/b> objects as parameter inputs, I only need to supply a string value that can be converted to a <b>DataTime<\/b> object. In addition, I do not need to specify seconds if I want to retrieve data from the beginning of each minute. This technique is shown here.<\/p>\n<blockquote>\n<p>PS C:\\&gt; $data = Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; -StartTime &#8220;1\/24<\/p>\n<p>\/11 10:44:00&#8243; -EndTime &#8220;1\/24\/11 10:44:03&#8221;<\/p>\n<p>PS C:\\&gt; $data | Format-Table -Property timestamp<\/p>\n<p>Timestamp<\/p>\n<p>&#8212;&#8212;&#8212;<\/p>\n<p>1\/24\/2011 10:44:00 AM<\/p>\n<p>1\/24\/2011 10:44:01 AM<\/p>\n<p>1\/24\/2011 10:44:02 AM<\/p>\n<p>1\/24\/2011 10:44:02 AM<\/p>\n<\/blockquote>\n<p>I may wish to view a specific number of counter sets. To do this, I can use the <b>maxsamples<\/b><i> <\/i>parameter and choose the number of sets to import. When I do this it imports the oldest counter sets first. The command that is shown here imports the three oldest counter sets and stores the results in the <b>$max3<\/b> variable.<\/p>\n<blockquote>\n<p>PS C:\\&gt; $max3 = Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217; -MaxSamples 3<\/p>\n<p>PS C:\\&gt; $max3.count<\/p>\n<p>3<\/p>\n<\/blockquote>\n<p>On the other hand, I might want to display the three newest counter sets. To do this, I can use the range operator as shown here. (This time, I display the timestamps to the Windows PowerShell console, instead of storing the results in a variable.)<\/p>\n<blockquote>\n<p>PS C:\\&gt; (Import-Counter -Path &#8216;C:\\fso\\System Monitor Log.blg&#8217;)[-1..-3] | Select-Objec<\/p>\n<p>t -Property timestamp -ExpandProperty timestamp<\/p>\n<p>Monday, January 24, 2011 11:03:47 AM<\/p>\n<p>Monday, January 24, 2011 11:03:46 AM<\/p>\n<p>Monday, January 24, 2011 11:03:45 AM<\/p>\n<\/blockquote>\n<p>CP, that is all there is to using the <b>Import-Counter<\/b> cmdlet. I hope you enjoyed my article today as much as I enjoyed writing it. The fun of Performance Week will continue tomorrow when I will talk about exporting performance counters. <\/p>\n<p>I invite you to follow me on <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to use the Import-Counter cmdlet in Windows PowerShell to parse saved performance counter log files. Hey, Scripting Guy! We have configured a series of custom performance monitor logs that run as scheduled tasks and collect monitoring information. The problem is that I never seem to have time to run Performance Monitor to [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,31,60,3,4,100],"class_list":["post-15721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-operating-system","tag-performance","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell-ise"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to use the Import-Counter cmdlet in Windows PowerShell to parse saved performance counter log files. Hey, Scripting Guy! We have configured a series of custom performance monitor logs that run as scheduled tasks and collect monitoring information. The problem is that I never seem to have time to run Performance Monitor to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/15721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=15721"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/15721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=15721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=15721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=15721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}