PowerShellでCPUとメモリの使用率をログに出力する方法は「Get-CounterでCPU percentとAvailable MBytesを同じsample時刻に取得し、上限付きのCSVへ記録します。memory使用率が必要ならtotal memoryとavailableを同じ単位で計算し、単発値ではなく時系列で判定します。」と理解すると迷いません。Windows performance counter名は表示language差があり、sample間隔・件数・保存容量を上限付きで設計する点が適用条件です。
実機のcounter setから利用可能pathを選ぶ
CPU・メモリーログでは、採取するカウンターパス、サンプル間隔、最大サンプル数、保存先を先に決めます。Get-CounterのTimestampとCookedValueを数件確認し、Totalとプロセス別インスタンスを混同しないようにします。CSVは別名で作成し、予定行数と時刻範囲を検証してから長時間採取へ移行します。
- Get-Counter -ListSetでcounter setとlocal名を確認する
- Get-CimInstance Win32_OperatingSystemでTotalVisibleMemorySizeを確認する
- sample interval、MaxSamples、log path、保持容量を決める
- service accountのwrite権限とtimezoneを確認する
sample間隔と最大回数を先に決める
Processor Timeはsampling windowにおけるcounter値で、Get-Process CPUの累積秒とは別です。Available MBytesは使用中memory percentではありません。cacheの扱いやcommit pressureも別counterで確認します。瞬間spike、一時的なGC、継続高負荷を区別するにはsample間隔と期間をworkloadへ合わせます。
CounterSamplesをlong形式へ展開する
- Get-Process CPUを瞬間率とする
- Available MBytesをmemory使用率と表示する
- 無限loopでAdd-Contentする
- counter名のlanguage差を無視する
- CSVを同じ名前へ無期限appendする
Available MBytesと使用率を分けて計算する
counterを一回取得
Get-Counter '\Processor(_Total)\% Processor Time','\Memory\Available MBytes' |
Select-Object -ExpandProperty CounterSamples | Select-Object Path,CookedValue,Timestamp
local OS languageでcounter pathが違う場合があります。実機ListSetから選びます。
CPUとmemoryを十二回sample
$samples=Get-Counter '\Processor(_Total)\% Processor Time','\Memory\Available MBytes' -SampleInterval 5 -MaxSamples 12
一分だけのtestです。無限loopにせず実行時間を見積もります。
long format CSVへ変換
$samples.CounterSamples | Select-Object Timestamp,Path,InstanceName,CookedValue |
Export-Csv -LiteralPath '.\perf-20260717.csv' -NoTypeInformation -Encoding utf8
counterごと一行のlong formatは後からpivotしやすく、列追加にも耐えます。
memory使用率を計算
$os=Get-CimInstance Win32_OperatingSystem
$totalMB=$os.TotalVisibleMemorySize/1024
$availableMB=$os.FreePhysicalMemory/1024
[pscustomobject]@{TotalMB=$totalMB;AvailableMB=$availableMB;UsedPercent=(($totalMB-$availableMB)/$totalMB*100)}
CIM値はKiB単位です。Get-Counterと取得時刻がずれる点を記録します。
CSVを読み戻す
Import-Csv '.\perf-20260717.csv' | Measure-Object
Import-Csv '.\perf-20260717.csv' | Select-Object -First 4
列、件数、decimal表現、文字化けを確認します。
CSVの列・encoding・保存先を固定する
monitoringは読み取りですが、短間隔・多数counter・無期限保存は負荷とdisk枯渇を招きます。MaxSamples、timeout、file size上限、rotation、ACLを設定し、credentialやprocess command lineを必要なく収集しません。log pathが満杯になったらsecurity log等を削除せず、この監視の新規出力を停止し、古い監視dataを保持policyに従って整理します。
localized path・NaN・書込失敗を検出する
Task ManagerまたはPerformance Monitorと同じ時間帯・単位で傾向を照合し、sample件数がMaxSamplesとcounter数に合うか確認します。CPU idle/load、memory allocation testを限定環境で行い、欠測、counter unavailable、disk不足を別statusへ記録します。
予定行数・Status・読み戻しでlogを検収する
Get-CounterのCounterSamplesをTimestamp、Path、InstanceName、CookedValueのlong形式へ保存します。CPU % Processor Timeはinterval値、Available MBytesは空き容量で単位が異なるため、同じpercent列へ押し込みません。
三回のCPU・memory sampleをCSVへ保存する
$samples=Get-Counter '\Processor(_Total)\% Processor Time','\Memory\Available MBytes' -SampleInterval 2 -MaxSamples 3 -ErrorAction Stop
$rows=@($samples.CounterSamples | Select-Object Timestamp,Path,InstanceName,CookedValue)
$rows | Export-Csv '.\perf-sample.csv' -NoTypeInformation -Encoding utf8
[pscustomobject]@{Rows=$rows.Count;Errors=@($samples.CounterSamples | Where-Object { $_.Status -ne 0 }).Count}
sample欠損をStatusと予定行数で検出する
- 全counter sample取得:MaxSamples×counter instance相当の行を取得し、CookedValueが数値でTimestamp順になる
- counter未提供:指定counterなしは0行成功にせず、localized counter setの候補をListSetで確認する
- 採取・CSV error:PDH error、NaN、sample欠落、CSV書込errorは取得/保存別のerror件数へ分ける
Get-Process CPUの累積秒をCPU使用率として混ぜません。counter名はOS languageで変わり得るため、対象hostのGet-Counter -ListSetで確認します。同名CSVへの無制限appendを避け、rotationと容量上限を持たせます。
localized名・blank値・途中cancelを試す
$read=@(Import-Csv '.\perf-sample.csv')
[pscustomobject]@{Rows=$read.Count;BlankValues=@($read|Where-Object CookedValue -eq '').Count;First=$read[0].Timestamp;Last=$read[-1].Timestamp}
idle/load、counter不存在、localized名、disk不足、途中cancelをtestします。予定/実sample数、Path別件数、NaN/blank、CSV byte数、開始終了時刻を照合します。
二つのcounterを三回取得するfixtureなら、正常時は六行が基準です。CounterSamplesのStatus、CSV行数、blank値を読み戻し、counter pathがlocalizedされる端末ではListSetの実名へ置き換えます。

コメント