Windows Sunucu Performansını İzleme: Temel Araçlar

Üretim ortamında bir Windows sunucusu aniden yavaşlamaya başladığında, ilk birkaç dakika gerçekten kritiktir. Kullanıcılar şikayet ediyor, telefon çalıyor ve siz ekranın başında “acaba ne oldu?” diye düşünüyorsunuz. İşte tam bu anlarda doğru araçları bilmek, saatlerce uğraşmak ile sorunu 10 dakikada çözmek arasındaki farkı yaratır. Bu yazıda Windows sunucu performansını izlemek için kullandığım temel araçları, gerçek senaryolarla birlikte anlatacağım.

Temel Performans İzleme Araçlarına Genel Bakış

Windows, performans izleme konusunda aslında oldukça zengin bir araç setine sahip. Sorun şu ki, bu araçların büyük bir kısmı göz önünde değil. Çoğu sistem yöneticisi Task Manager’ı açıp “CPU %95’te, tamam sorun var” deyip geçiyor. Oysa asıl hikaye çok daha derinlerde yatıyor.

Kullanacağımız araçları üç kategoriye ayırabiliriz:

  • Yerleşik GUI Araçları: Task Manager, Performance Monitor (PerfMon), Resource Monitor
  • Komut Satırı Araçları: PowerShell cmdlet’leri, WMI sorguları, typeperf
  • Üçüncü Parti Araçlar: Process Hacker, PAL (Performance Analysis of Logs)

Sırasıyla hepsini ele alacağız ama asıl ağırlığı komut satırı tarafına vereceğim, çünkü gerçek izleme otomasyonu oradan geliyor.

Task Manager: Hızlı Bakış Aracı

Task Manager’ı küçümsemek yanlış olur. Doğru kullanıldığında çok hızlı bilgi verir. Ctrl+Shift+Esc ile açın ve direkt “Performance” sekmesine gidin.

Burada dikkat etmeniz gereken birkaç nokta var. CPU grafiğinin altındaki “Open Resource Monitor” linkine tıklayın. Task Manager size genel resmi gösterir, Resource Monitor size “hangi process tam olarak ne yapıyor” sorusunu yanıtlar.

Ancak Task Manager’ın bir sınırı var: anlık veri gösterir, trend görmez. Bir sunucunun her gece 02:00-03:00 arasında yavaşladığını Task Manager ile tespit edemezsiniz.

Performance Monitor (PerfMon): Gerçek Güç Buradan

PerfMon, Windows’un en underrated aracıdır diyebilirim. perfmon.msc ile açılır ve başlangıçta biraz ürkütücü görünür. Ama birkaç temel kavramı anladıktan sonra vazgeçilmez olur.

Temel Sayaçlar ve Anlamları

PerfMon’da izlemeniz gereken kritik sayaçlar şunlar:

Processor kategorisi:

  • % Processor Time: Toplam CPU kullanımı. Sürekli %80 üzerindeyse sorun var
  • % Privileged Time: Kernel mode CPU kullanımı. Bu yüksekse driver veya donanım sorunu olabilir
  • Processor Queue Length: Bekleyen thread sayısı. Çekirdek başına 2’den fazlaysa CPU darboğazı var demektir

Memory kategorisi:

  • Available MBytes: Kullanılabilir fiziksel bellek
  • Pages/sec: Saniyedeki sayfa hatası sayısı. 20’nin üzerinde olmamalı
  • Page Faults/sec: Bellek baskısının göstergesi

PhysicalDisk kategorisi:

  • Avg. Disk Queue Length: Disk kuyruğu uzunluğu. Disk başına 2’den fazlaysa disk darboğazı var
  • % Disk Time: Disk meşguliyet yüzdesi
  • Avg. Disk sec/Transfer: Transfer başına geçen süre. 20ms üzeri sorunlu

Bu sayaçları manuel eklemek yerine, bir Data Collector Set oluşturup veri toplamak çok daha akıllıca. Gece çalışan otomatik bir toplayıcı, sabah geldiğinizde geceyi analiz etmenizi sağlar.

PowerShell ile Performans İzleme

İşte asıl eğlence buradan başlıyor. PowerShell ile performans verisi toplamak hem güçlü hem de otomatize edilebilir.

Anlık Sistem Durumu Sorgulama

# CPU, bellek ve disk kullanımını tek seferde görmek için
Get-Counter 'Processor(_Total)% Processor Time', `
    'MemoryAvailable MBytes', `
    'PhysicalDisk(_Total)% Disk Time' | `
    Select-Object -ExpandProperty CounterSamples | `
    Format-Table Path, CookedValue -AutoSize

Bu komut size anlık bir snapshot verir. Ama ben bunu genellikle birkaç saniye arayla döngüde çalıştırmayı tercih ederim:

# 5 saniyede bir, 10 kez ölçüm al ve dosyaya kaydet
$outputFile = "C:Logsperf_$(Get-Date -Format 'yyyyMMdd_HHmm').csv"

1..10 | ForEach-Object {
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $cpu = (Get-Counter 'Processor(_Total)% Processor Time').CounterSamples.CookedValue
    $memMB = (Get-Counter 'MemoryAvailable MBytes').CounterSamples.CookedValue
    $diskTime = (Get-Counter 'PhysicalDisk(_Total)% Disk Time').CounterSamples.CookedValue
    
    "$timestamp,$([math]::Round($cpu,2)),$([math]::Round($memMB,0)),$([math]::Round($diskTime,2))" | 
        Out-File -Append -FilePath $outputFile
    
    Start-Sleep -Seconds 5
}

Write-Host "Veriler $outputFile dosyasina kaydedildi."

WMI ile Detaylı Süreç Analizi

Hangi process ne kadar CPU yiyor, bellekte ne kadar yer kaplıyor, bunu programatik olarak çekmek için WMI sorgularını kullanıyorum:

# En çok CPU kullanan 10 process'i listele
Get-WmiObject Win32_PerfFormattedData_PerfProc_Process |
    Where-Object { $_.Name -ne "_Total" -and $_.Name -ne "Idle" } |
    Sort-Object PercentProcessorTime -Descending |
    Select-Object -First 10 Name, PercentProcessorTime, WorkingSet |
    Format-Table -AutoSize

Bir keresinde bir müşteri sunucusunda CPU sürekli %90 üzerindeydi. Task Manager’a bakınca birden fazla svchost.exe process’i vardı ve hangisinin sorun çıkardığını anlayamıyorduk. Aşağıdaki sorgu işi çözdü:

# Hangi servisler hangi svchost altında çalışıyor
$svchostProcesses = Get-WmiObject Win32_Process -Filter "Name = 'svchost.exe'" |
    Select-Object ProcessId, @{
        Name = 'Services'
        Expression = {
            (Get-WmiObject Win32_Service -Filter "ProcessId = $($_.ProcessId)").Name -join ', '
        }
    }, @{
        Name = 'CPU_Percent'
        Expression = {
            $pid = $_.ProcessId
            (Get-WmiObject Win32_PerfFormattedData_PerfProc_Process -Filter "IDProcess = $pid").PercentProcessorTime
        }
    }

$svchostProcesses | Sort-Object CPU_Percent -Descending | Format-Table -AutoSize

Sonuç? Windows Update servisi güncelleme taraması yapıyordu ve CPU’yu bitiriyordu. Klasik senaryo.

Resource Monitor: Process Düzeyinde Derinlik

Resource Monitor (resmon.exe) Task Manager’ın gelişmiş kardeşidir. Özellikle şu senaryolarda kullanıyorum:

Disk I/O sorunlarında: “Disk Activity” sekmesi, hangi process’in hangi dosyaya ne kadar okuma/yazma yaptığını gösterir. Yavaş bir SQL Server’da log dosyasının dolu olup olmadığını buradan saniyeler içinde anlayabilirsiniz.

Ağ sorunlarında: “Network” sekmesindeki “Network Activity” ve “TCP Connections” kısımları, hangi process’in hangi IP’ye bağlandığını gösterir. Şüpheli bir outbound connection’ı buradan yakaladım birkaç kez.

Bellek sorunlarında: “Memory” sekmesindeki “Physical Memory” grafiği, Standby/Free/Modified bellek dağılımını gösterir. Standby bellek aslında kullanılabilir bellektir, bunu bilmeyenler gereksiz bellek alarmı verebiliyor.

Typeperf: Komut Satırından Sürekli İzleme

typeperf komutu, PerfMon sayaçlarını doğrudan komut satırından izlemenizi sağlar. Otomatik script’lerde ve zamanlanmış görevlerde çok kullanışlıdır.

# CPU kullanımını 5 saniyede bir, 60 saniye boyunca CSV'ye kaydet
typeperf "Processor(_Total)% Processor Time" "MemoryAvailable MBytes" -si 5 -sc 12 -f CSV -o C:Logsperflog.csv

Bir başka sık kullandığım senaryo: Sunucu yeniden başlatıldıktan sonra sistemin stabilize olma sürecini izlemek. Bazen servisler ayağa kalktıkça kaynak tüketimi dalgalanır ve bunu kayıt altına almak ileride analiz için değerli olur.

# Sistem restart sonrası ilk 10 dakikayı kaydet (120 x 5 saniye)
$logPath = "C:Logsrestart_monitor_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
typeperf "Processor(_Total)% Processor Time" `
         "MemoryAvailable MBytes" `
         "PhysicalDisk(0 C:)Avg. Disk sec/Read" `
         "PhysicalDisk(0 C:)Avg. Disk sec/Write" `
         -si 5 -sc 120 -f CSV -o $logPath

Write-Host "Izleme tamamlandi. Log: $logPath"

Olay Günlükleri ile Korelasyon

Performans sorunu yaşandığında, sadece sayaçlara bakmak yeterli değildir. Windows Event Log ile korelasyon kurmak şart. Bir sunucunun her Pazartesi sabahı yavaşladığını düşünün. Event Log’a bakınca Pazartesi 08:00’de başlayan bir grup policy işlemi veya antivirüs taraması görebilirsiniz.

# Son 24 saatte kritik ve hata seviyesindeki sistem olaylarını çek
$startTime = (Get-Date).AddHours(-24)

Get-WinEvent -FilterHashtable @{
    LogName = 'System'
    Level = 1,2  # 1=Critical, 2=Error
    StartTime = $startTime
} -ErrorAction SilentlyContinue |
    Select-Object TimeCreated, Id, LevelDisplayName, Message |
    Sort-Object TimeCreated -Descending |
    Select-Object -First 20 |
    Format-List

Performance sorununu Application log ile de ilişkilendirmek gerekir:

# Uygulama logunda son 2 saatteki uyarı ve hataları göster
Get-WinEvent -FilterHashtable @{
    LogName = 'Application'
    Level = 2,3  # 2=Error, 3=Warning
    StartTime = (Get-Date).AddHours(-2)
} -ErrorAction SilentlyContinue |
    Select-Object TimeCreated, ProviderName, LevelDisplayName, Message |
    Sort-Object TimeCreated -Descending |
    Format-Table -Wrap

Ağ Performansı İzleme

Sunucu izleme denince akla önce CPU ve bellek gelir, ama ağ performansı da en az bunlar kadar kritiktir. Özellikle terminal server veya dosya sunucularında ağ darboğazı çok sık karşılaşılan bir sorundur.

# Ağ arayüzü istatistiklerini göster
Get-Counter 'Network Interface(*)Bytes Total/sec', 
            'Network Interface(*)Packets/sec',
            'Network Interface(*)Output Queue Length' |
    Select-Object -ExpandProperty CounterSamples |
    Where-Object { $_.InstanceName -notmatch "isatap|loopback" } |
    Format-Table Path, CookedValue -AutoSize

Output Queue Length değeri sürekli 2’nin üzerindeyse ağ kartı darboğazı yaşıyorsunuzdur. Bu değeri gördüğünüzde NIC driver’ını, duplex ayarlarını ve switch portunu kontrol edin.

Otomatik Uyarı Scripti: Pratik Senaryo

Şimdi her şeyi bir araya getirip pratik bir senaryo kuralım. Aşağıdaki script, belirlediğiniz eşikleri aşan durumlarda e-posta gönderir ve log dosyasına yazar:

# Performans uyari scripti - Windows Task Scheduler ile calistirin
param(
    [int]$CpuThreshold = 85,
    [int]$MemThresholdMB = 512,
    [int]$DiskQueueThreshold = 3
)

$logFile = "C:LogsPerfAlert_$(Get-Date -Format 'yyyyMMdd').log"
$alertMessages = @()
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

# CPU kontrolu (3 olcum ortalaması al)
$cpuSamples = 1..3 | ForEach-Object {
    (Get-Counter 'Processor(_Total)% Processor Time').CounterSamples.CookedValue
    Start-Sleep -Seconds 2
}
$avgCpu = ($cpuSamples | Measure-Object -Average).Average

if ($avgCpu -gt $CpuThreshold) {
    $msg = "[$timestamp] UYARI: Ortalama CPU kullanimi %$([math]::Round($avgCpu,1)) - Esik: %$CpuThreshold"
    $alertMessages += $msg
    Add-Content -Path $logFile -Value $msg
}

# Bellek kontrolu
$availMem = (Get-Counter 'MemoryAvailable MBytes').CounterSamples.CookedValue
if ($availMem -lt $MemThresholdMB) {
    $msg = "[$timestamp] UYARI: Kullanilabilir bellek $([math]::Round($availMem,0)) MB - Esik: $MemThresholdMB MB"
    $alertMessages += $msg
    Add-Content -Path $logFile -Value $msg
}

# Disk kuyrugu kontrolu
$diskQueue = (Get-Counter 'PhysicalDisk(_Total)Avg. Disk Queue Length').CounterSamples.CookedValue
if ($diskQueue -gt $DiskQueueThreshold) {
    $msg = "[$timestamp] UYARI: Disk kuyrugu uzunlugu $([math]::Round($diskQueue,2)) - Esik: $DiskQueueThreshold"
    $alertMessages += $msg
    Add-Content -Path $logFile -Value $msg
}

# Uyari varsa e-posta gonder
if ($alertMessages.Count -gt 0) {
    $emailParams = @{
        From = "[email protected]"
        To = "[email protected]"
        Subject = "[$env:COMPUTERNAME] Performans Uyarisi - $(Get-Date -Format 'HH:mm')"
        Body = $alertMessages -join "`n"
        SmtpServer = "mail.sirket.com"
    }
    Send-MailMessage @emailParams -ErrorAction SilentlyContinue
    Write-Host "Uyarilar gonderildi ve loglandı: $logFile"
} else {
    Add-Content -Path $logFile -Value "[$timestamp] Sistem normal - CPU:%$([math]::Round($avgCpu,1)) Bellek:$([math]::Round($availMem,0))MB DiskQueue:$([math]::Round($diskQueue,2))"
}

Bu scripti Task Scheduler’da her 15 dakikada bir çalışacak şekilde ayarlayın. Üretimde bunu kullanıyoruz ve çok büyük kolaylık sağlıyor.

Process Hacker: Derinlemesine Analiz

Üçüncü parti araçlar konusunda şunu söyleyeyim: Process Hacker (artık System Informer adıyla da biliniyor) Task Manager’ın çok ötesinde bir araçtır. Ücretsizdir, portable çalışır ve kurumsal ortamlarda güvenle kullanılabilir.

Özellikle şu senaryolarda vazgeçilmez:

  • Bir process’in açık dosya handle’larını görmek istediğinizde (hangi dosyayı kilitlediğini bulmak için)
  • DLL injection veya şüpheli thread aktivitesi araştırırken
  • Servis dependency’lerini görsel olarak incelemek istediğinizde
  • Memory leak analizi yaparken (Working Set vs Private Bytes farkını görmek için)

Kurumsal ortamda antivirüs false positive üretebilir, bu yüzden whitelist’e almanız gerekebilir.

PAL (Performance Analysis of Logs): Toplu Analiz

PerfMon’dan topladığınız veriyi analiz etmek için PAL (Performance Analysis of Logs) aracını öneririm. Microsoft’un desteklediği, ücretsiz bir araçtır. BLG veya CSV formatındaki PerfMon çıktılarını alır, belirlediğiniz eşiklerle karşılaştırır ve HTML rapor üretir.

Özellikle şu durumlarda kullanışlıdır:

  • Kapasite planlama çalışması yaparken
  • Müşteriye veya yönetime rapor sunarken
  • Birden fazla sunucunun verilerini karşılaştırırken
  • Değişiklik öncesi ve sonrası performans karşılaştırması yaparken

PAL’ı Windows Server, Exchange, SQL Server, IIS gibi roller için hazır şablonlarla kullanabilirsiniz. Bu şablonlar Microsoft’un belirlediği best practice eşiklerini içerir.

Gerçek Dünya Tüyoları

Yıllar içinde öğrendiğim birkaç pratik ipucu:

Baseline önce, sorun sonra: Sisteminiz sağlıklıyken bir hafta boyunca performans verisi toplayın. Bu baseline olmadan “normal” nedir bilemezsiniz. Kış ayında %40 CPU normal olabilir, yaz ayında aynı sistem %40 CPU’da çalışıyorken müşteri sayısı iki katına çıkmış olabilir.

Syslog yetersizliği: Windows Event Log retention süresi varsayılan olarak çok kısadır. Özellikle Security log’u dolunca üzerine yazmaya başlar. Log boyutlarını artırın ve uzak log sunucusuna gönderin.

Scheduled Task çakışmaları: Gece çalışan backup, antivirus tarama, Windows Update, disk defrag işlemlerinin saatlerini birbirinden ayırın. Hepsi aynı anda çalışıyorsa sabah geldiğinizde log analizinde kördüğüm olur.

Sanallaştırma farkı: VMware veya Hyper-V üzerindeki Windows sunucularında % Processor Time yanıltıcı olabilir. Hypervisor seviyesinde CPU ready/co-stop değerlerine de bakmanız gerekir. Guest OS’un gördüğü CPU ile fiziksel CPU kullanımı farklı olabilir.

Sonuç

Windows sunucu performansını izlemek, tek bir aracı iyi bilmekten çok, birden fazla aracı doğru senaryoda kullanmayı bilmekten geçiyor. Task Manager hızlı bakış için, Resource Monitor process detayı için, PerfMon trend analizi için, PowerShell ise her şeyi otomatize etmek için kullanılıyor.

Benim önerim şu: önce PowerShell ile temel sayaçları toplamayı öğrenin, PerfMon Data Collector Set’lerini kurun, bir baseline alın. Ardından bu yazıdaki uyarı scriptini kendi ortamınıza uyarlayın. Sorun çıkmadan önce elinizde veri olsun. Çünkü üretim ortamında sorun çıktıktan sonra veri toplamaya başlamak, hasta hastaneye kaldırıldıktan sonra tansiyon ölçmeye başlamak gibi.

Sorularınız veya farklı senaryolarınız varsa yorumlara yazabilirsiniz. Özellikle SQL Server veya IIS performans izleme konusunda daha spesifik araçları başka bir yazıda ele alabiliriz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir