Microsoft 365 Servis Sağlığı İzleme Rehberi
Microsoft 365 servislerinde yaşanan her kesinti, kurum içi ağdan veya kullanıcı cihazından kaynaklanmaz. Exchange Online, Microsoft Teams, SharePoint Online ya da Microsoft Entra ID tarafındaki bir servis olayı; son kullanıcıya e-posta gecikmesi, oturum açma problemi veya toplantıya katılamama şeklinde yansıyabilir. Böyle bir durumda ilk yapılması gerekenlerden biri Microsoft 365 servis sağlığını kontrol etmektir.
Microsoft 365 yönetim merkezindeki Health > Service health ekranı bu bilgiyi sunar. Ancak operasyon ekiplerinin sürekli yönetim merkezini kontrol etmesi sürdürülebilir değildir. Microsoft Graph Service Communications API ve PowerShell kullanılarak servis sağlığı otomatik olarak sorgulanabilir, yalnız yeni veya kapanan olaylar için bildirim üretilebilir ve sonuçlar merkezi bir HTML raporunda tutulabilir.
Bu makalede, Microsoft 365 servis sağlığını PowerShell ile temel seviyede izlemenin mimarisini, gerekli Entra uygulamasını, yetkileri, sertifika tabanlı kimlik doğrulamayı, örnek sorguları, durum takibini ve görev zamanlayıcı yapılandırmasını ele alacağız.

Neden özel bir izleme betiğine ihtiyaç duyulur?
Microsoft 365 servis sağlığını otomatik izleyen basit bir çözüm şu ihtiyaçları karşılayabilir:
- Kullanılan Microsoft 365 servislerinin sağlık durumunu düzenli kontrol etmek
- Yalnız yeni açılan veya kapanan olaylarda bildirim göndermek
- Aynı olay için her çalışmada tekrar e-posta gönderilmesini önlemek
- Olay kimliği, etkilenen servis, sınıflandırma, başlangıç zamanı ve durum gibi bilgileri raporlamak
- Sonuçları HTML dosyasına ve günlük kayıtlarına yazmak
- ServiceNow, Jira, Teams veya başka bir olay yönetim platformuna entegrasyon için başlangıç noktası oluşturmak
Bu yöntem tam kapsamlı bir izleme platformunun yerine geçmez. Bununla birlikte, ayrı bir izleme ürünü bulunmayan veya Microsoft 365 servis durumunu mevcut operasyon süreçlerine eklemek isteyen kurumlar için düşük maliyetli ve geliştirilebilir bir temel sağlar.
Çözüm mimarisi
İşleyiş aşağıdaki adımlardan oluşur:
- PowerShell betiği, sertifika kullanarak Entra ID üzerinde kayıtlı uygulama kimliğiyle oturum açar.
- Uygulama, Microsoft Graph üzerinden tenant’a ait servis sağlık özetlerini ve aktif olayları sorgular.
- Sonuçlar yalnız kurumda kullanılan servisleri içerecek şekilde filtrelenir.
- Önceki çalışmanın durumu yerel bir JSON dosyasından okunur.
- Yeni açılan veya kapanan olaylar belirlenir.
- HTML raporu ve günlük dosyası güncellenir.
- Değişiklik varsa SMTP ya da Microsoft Graph üzerinden bildirim gönderilir.
- Betik Windows Task Scheduler, Azure Automation veya benzeri bir otomasyon platformunda belirli aralıklarla çalıştırılır.
Ön Koşullar
- Microsoft 365 tenant’ında uygulama kaydı oluşturabilecek yetki
- API izinlerine yönetici onayı verebilecek bir yönetici hesabı
- PowerShell 7.x önerilir; mevcut yapı gerekiyorsa Windows PowerShell 5.1 de kullanılabilir
- Uygulama kimlik doğrulaması için özel anahtar içeren bir X.509 sertifikası
- Betiğin çalışacağı sistemde Microsoft Graph PowerShell Authentication modülü
- Çıktı, günlük ve durum dosyalarının yazılabileceği güvenli bir dizin
- E-posta gönderilecekse bir bildirim posta kutusu ve uygun Exchange Online yetkilendirmesi
Entra ID uygulama kaydının oluşturulması
Bu uygulama aşağıdaki Microsoft Entra tenant bilgileri üzerinden yapılandırılacaktır:

Microsoft Entra yönetim merkezinde aşağıdaki adımlar uygulanır:
- Identity > Applications > App registrations > New registration bölümüne gidin.
- Uygulamaya örneğin M365-ServiceHealth-Monitor adını verin.
- Yalnız bu kuruluş dizinindeki hesapları seçin.
- Uygulama oluşturulduktan sonra Application (client) ID ve Directory (tenant) ID değerlerini kaydedin.
- Certificates & secrets > Certificates bölümünden sertifikanın yalnız açık anahtarını içeren .cer dosyasını yükleyin.

İzleme sunucusunda örnek bir sertifika oluşturmak için aşağıdaki komut kullanılabilir:
$cert = New-SelfSignedCertificate `
-Subject "CN=M365-ServiceHealth-Monitor" `
-CertStoreLocation "Cert:\LocalMachine\My" `
-KeySpec Signature `
-KeyExportPolicy NonExportable `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddYears(2)
Export-Certificate `
-Cert $cert `
-FilePath "C:\M365-ServiceHealth-Monitor.cer"
Oluşturulan .cer dosyası, uygulamanın Certificates & secrets > Certificates > Upload certificate bölümünden yüklenir. Burada yalnız açık anahtar yüklenir; özel anahtarı içeren sertifika dosyası portala aktarılmaz.

Zamanlanmış görev bir servis hesabıyla çalışacaksa, bu hesabın sertifikanın özel anahtarına okuma yetkisi bulunmalıdır. Özel anahtarın dışarı aktarılmasına izin vermemek güvenliği artırır. Sertifika süresi dolmadan önce yenileme ve uygulamaya yeni açık anahtar yükleme süreci ayrıca izlenmelidir.
Microsoft Graph API izinleri
Uygulamanın API permissions bölümünden Microsoft Graph için Application permissions seçilerek ihtiyaca göre şu izinler eklenir. Ardından Grant admin consent ile yönetici onayı verilmelidir.
| İzin | Kullanım amacı | Zorunluluk |
| ServiceHealth.Read.All | Servis sağlık özetlerini ve servis olaylarını okumak | Temel sağlık izleme için gerekli |
| ServiceMessage.Read.All | Microsoft 365 Message Center iletilerini okumak | Yalnız duyurular da izlenecekse gerekli |

Sertifika ile uygulama kimlik doğrulaması
Microsoft Graph PowerShell modülü kurulabilir:
Install-Module Microsoft.Graph.Authentication -Scope AllUsers
Uygulama kimliğiyle etkileşimsiz bağlantı örneği:
$TenantId = "8f7d093f-6d0d-4521-9cae-466d8**********"
$ClientId = "APPLICATION-CLIENT-ID"
$CertificateThumbprint = "CERTIFICATE-THUMBPRINT"
Connect-MgGraph `
-TenantId $TenantId `
-ClientId $ClientId `
-CertificateThumbprint $CertificateThumbprint `
-NoWelcome
Get-MgContext | Select-Object ClientId, TenantId, AuthType
AuthType değerinin AppOnly olması beklenir. Task Scheduler altında çalışan betiklerde CurrentUser yerine LocalMachine sertifika deposu genellikle daha yönetilebilir olur. Ancak özel anahtar erişimi yalnız betiği çalıştıran hesapla sınırlandırılmalıdır.
Servis sağlık verisinin sorgulanması
Tenant’taki servislerin genel durumunu almak için kullanılan uç nokta:
GET https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews
PowerShell ile örnek sorgu:
$healthUri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews"
$healthResult = Invoke-MgGraphRequest -Method GET -Uri $healthUri
$healthResult.value |
Select-Object service, status |
Sort-Object service |
Format-Table -AutoSize
Servis olayları ise aşağıdaki uç noktadan alınır:
GET https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues
$issuesUri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues"
$issuesResult = Invoke-MgGraphRequest -Method GET -Uri $issuesUri
$issuesResult.value |
Select-Object id, service, classification, status, startDateTime, endDateTime |
Sort-Object startDateTime -Descending
Sonuçlarda olay kimliği, etkilenen servis, olay türü, mevcut durum, başlangıç ve bitiş zamanı gibi alanlar bulunur. API yanıtındaki zaman bilgileri UTC olabilir; raporda Türkiye saati gösterilecekse saat dilimi dönüşümü açıkça yapılmalıdır.
Kullanılan servislerin izlenmesi
Tenant’ta görünen tüm servisler kurum tarafından aktif kullanılmıyor olabilir. Gereksiz alarm üretmemek için bir servis listesi tanımlanabilir:
$MonitoredServices = @(
"Exchange Online",
"Microsoft Teams",
"SharePoint Online",
"Microsoft 365 suite"
)
$monitoredIssues = $issuesResult.value | Where-Object {
$_.service -in $MonitoredServices
}
Servis adlarını elle yazmadan önce healthOverviews çıktısındaki gerçek service değerlerini kontrol edin. Görünen adlar zaman içinde değişebileceği için eşleşmeyen servisleri günlük kayıtlarında ayrıca raporlamak yararlı olur.
Yeni ve kapanan olayların belirlenmesi
Betiğin her 15 dakikada bir aynı aktif olay için e-posta göndermemesi gerekir. Bunun için önceki çalışmada görülen olaylar bir durum dosyasında saklanabilir.
$StateFile = "C:\M365Monitor\state.json"
$previousState = if (Test-Path $StateFile) {
Get-Content $StateFile -Raw | ConvertFrom-Json
} else {
@()
}
$currentState = @(
$monitoredIssues | ForEach-Object {
[pscustomobject]@{
Id = $_.id
Status = $_.status
Service = $_.service
}
}
)
$newIssues = $currentState | Where-Object {
$_.Id -notin @($previousState.Id)
}
$changedIssues = $currentState | Where-Object {
$current = $_
$old = $previousState | Where-Object Id -eq $current.Id | Select-Object -First 1
$old -and $old.Status -ne $current.Status
}
$closedIssues = $previousState | Where-Object {
$_.Id -notin @($currentState.Id)
}
$currentState |
ConvertTo-Json -Depth 5 |
Set-Content -Path $StateFile -Encoding UTF8
Bu basit yaklaşım başlangıç için yeterlidir; ancak üretim ortamında durum dosyasına yazma işlemi geçici dosya kullanılarak atomik yapılmalı, bozuk JSON ve eşzamanlı çalışma senaryoları ele alınmalıdır. Ayrıca API’den kaybolan her olayın mutlaka “resolved” olduğu varsayılmamalı; olayın son durumu mümkünse kimliği üzerinden yeniden doğrulanmalıdır.
HTML raporu oluşturma
Aktif olaylar kolay okunabilir bir HTML tabloya dönüştürülebilir:
$ReportPath = "C:\M365Monitor\M365-ServiceHealth.html"
$style = @"
<style>
body { font-family: Segoe UI, Arial; margin: 24px; color: #242424; }
table { border-collapse: collapse; width: 100%; }
th { background: #0078d4; color: white; text-align: left; }
th, td { border: 1px solid #d1d1d1; padding: 8px; }
tr:nth-child(even) { background: #f5f5f5; }
</style>
"@
$monitoredIssues |
Select-Object id, service, classification, status, startDateTime, endDateTime |
ConvertTo-Html `
-Title "Microsoft 365 Service Health" `
-Head $style `
-PreContent "<h1>Microsoft 365 Service Health</h1><p>Son güncelleme: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')</p>" |
Set-Content -Path $ReportPath -Encoding UTF8
HTML dosyası bir web sunucusunda salt okunur yayımlanabilir veya operasyon ekranında görüntülenebilir. Raporda hassas olay ayrıntıları bulunabileceğinden anonim erişime açılmamalıdır.

Bildirim iki yöntemle gönderilebilir:
Kurum içi SMTP relay
Yetkili ve yalnız belirli kaynak IP’lerden erişilebilen bir SMTP relay mevcutsa kullanılabilir. Eski Send-MailMessage cmdlet’i güncel kimlik doğrulama gereksinimleri açısından önerilen genel çözüm değildir. Üretim ortamında kurumun desteklediği SMTP istemcisi veya Graph tabanlı gönderim tercih edilmelidir.
Microsoft Graph ile gönderim
Graph üzerinden gönderim yapılacaksa uygulamaya posta gönderme yetkisi gerekir. Tenant genelinde sınırsız Mail.Send vermek yerine, Exchange Online RBAC for Applications kullanılarak Application Mail.Send rolü yalnız bildirim gönderecek posta kutusuyla sınırlandırılabilir.
Önemli nokta şudur: Entra ID üzerinde ayrıca tenant-geneli Mail.Send uygulama izni bırakılırsa, Exchange RBAC kapsamı beklenen sınırlamayı tek başına sağlamayabilir.
Kaynak kapsamlı yetki kullanılacaksa yetkilendirme tasarımı bütün olarak doğrulanmalı ve Test-ServicePrincipalAuthorization ile hedef posta kutusu üzerinde test edilmelidir.
Sık karşılaşılan hatalar
401 Unauthorized
Tenant ID, Client ID, sertifika thumbprint’i ve sertifikanın uygulama kaydına yüklenip yüklenmediği kontrol edilmelidir. Görevi çalıştıran hesabın özel anahtara erişimi de doğrulanmalıdır.
403 Forbidden
İzin türünün Application olarak eklendiğini ve yönetici onayı verildiğini kontrol edin. Servis sağlığı için ServiceHealth.Read.All, Message Center için ServiceMessage.Read.All gerekir.
Zamanlanmış Görev Elle Çalışıyor Ancak Belirlenen Saatlerde Otomatik Çalışmıyor
Sertifikanın yanlış kullanıcı deposunda bulunması, çalışma dizininin tanımlanmaması, görevin farklı hesapla çalışması veya PowerShell yürütülebilir dosya yolunun yanlış olması sık görülen nedenlerdir. Betikte tüm dosya yollarını mutlak olarak tanımlayın.
Aynı Servis Olayı İçin Her Çalıştırmada Tekrarlanan E-posta Bildirimi Gönderiliyor
Durum dosyasının kalıcı konumda olduğundan, olay kimliği ile durum bilgisinin birlikte karşılaştırıldığından ve API hatası sırasında dosyanın boş veriyle ezilmediğinden emin olun.
Sonuç
Microsoft Graph Service Communications API, Microsoft 365 servis sağlığını kurumun mevcut operasyon süreçlerine taşımak için güçlü bir arayüz sunar. PowerShell ile kurulacak temel bir çözüm; seçilen servisleri izleyebilir, yalnız yeni veya kapanan olaylarda bildirim oluşturabilir, HTML raporu üretebilir ve günlük kaydı tutabilir.
Üretim ortamındaki asıl değer yalnız API’den veri almak değil; tekrar eden alarmları önlemek, betiğin kendi sağlığını izlemek, yetkileri en az ayrıcalıkla sınırlamak ve sonuçları kurumun olay yönetim sürecine bağlamaktır. Bu temel yapı daha sonra Teams bildirimi, ServiceNow/Jira kaydı, merkezi log platformu veya Azure Monitor entegrasyonu ile geliştirilebilir.
Bu bilgilerin faydalı olması dileğiyle…










