www.SAMURAJ-cz.com 

14.12.2017 Lýdie Translate to English by Google     VÍTEJTE V MÉM SVĚTĚ

Články

Exchange server a statistiky posílání zpráv

Sobota, 19.10.2013 15:18 | Samuraj - Petr Bouška |
Myslím, že Exchange serveru chybí jedna zásadní věc, a to jsou různé statistiky o provozu. U konkurenčních produktů je běžné zobrazení řady informací, které Exchange přímo neobsahuje. Například hodinové, denní, týdenní a měsíční statistiky o odeslaných a přijatých emailech, jak interně tak z internetu. Statistiky pro různé konektory. Údaje o nedoručitelnosti, nejčastější příjemci a odesílatelé, populární domény. A když už mluvíme o různých informacích, tak by také mohl Exchange přehledně informovat o svém zdraví. Tento článek je malým navedením, jak některé informace získat.

Pozn.: Popisované informace byly otestovány na Exchange Serveru 2010 SP3.

Co jsou to Message Tracking Logs

Jediné, co na Exchange serveru máme k dispozici, jsou Message Tracking Logs. Do těch zapisuje role Hub Transport, Edge Transport a Mailbox server všechny aktivity o přenosu zpráv. Logy jsou textové soubory, které se ukládají na serveru. Defaultně se uchovávají po dobu 30 dní a nachází se v cestě C:\Program Files\Microsoft\Exchange Server\V14\TransportRoles\Logs\MessageTracking. Na aktuální nastavení se můžeme podívat pomocí Exchange Management Shell (EMS, tedy PowerShellu).

Get-MailboxServer SERVER | FL Message*
Get-TransportServer SERVER | FL Message*

Pokud bychom chtěli nějakou hodnotu změnit, tak opět využijeme PowerShell. Detailní popis je u Microsoftu v Configure Message Tracking.

Jak s logy pracovat

S logy můžeme pracovat několika způsoby. V Exchange Management Console (EMC) se pod Toolbox nachází Tracking Log Explorer. Můžeme využít další nástroj Microsoftu, což je Log Parser Studio. Nebo můžeme použít EMS, kde máme k dispozici cmdlet Get-MessageTrackingLog.

Příklady procházení tracking logu

Následující příklady slouží pouze k nastínění syntaxe cmdletu Get-MessageTrackingLog. Na začátku si definujeme časový interval jednoho dne.

$Start = (Get-Date).AddDays(-1)
$End = (Get-Date)

Najdeme všechny zprávy (a události) odeslané z adresy jmeno@firma.cz a k nim zobrazíme vyjmenované informace.

Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Where-Object { $_.Sender -eq "jmeno@firma.cz" } | FT Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,TotalBytes,RecipientCount,MessageId -AutoSize 

Najdeme všechny události k jedné zprávě s daným MessageId.

Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Where-Object { $_.MessageId -eq "<928D4983D1BD6A4790DB8323A23E8A8B4AB386AF@server.firma.local>" }| FT EventId,Sender,Recipients,MessageSubject -AutoSize 

Zobrazíme všechny události daných typů RECEIVE, SEND, DELIVER.

Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Where-Object { $_.EventId -eq "RECEIVE" -or $_.EventId -eq "SEND" -or $_.EventId -eq "DELIVER" } | FT EventId,Sender,Recipients -AutoSize 

Jiný způsob zápisů pro vyhledání událostí jednoho typu RECEIVE (stejně můžeme provést i hledání odesílatele pomocí parametru Sender, atd).

Get-MessageTrackingLog -Start $Start -End $End -EventID "RECEIVE" -ResultSize Unlimited | FT Sender, Recipients, TotalBytes -AutoSize 

Informace v logu

Do logů se ukládá velké množství událostí různých typů (EventID). Hlavní události, které nás asi budou zajímat, jsou RECEIVE, SUBMIT, SEND a DELIVER. Související údaj je zdroj události (Source), kde hlavní je SMTP a STOREDRIVER.

Určitý popis událostí a dalších hodnot nalezneme v článku Understanding Message Tracking, Message Tracking (Exchange Server 2013) a Search Message Tracking Logs. Bohužel nikde není graf nebo popis posloupnosti jednotlivých událostí při nějaké akci (například odeslání emailu mimo firmu). Něco popisuje článek Exchange 2013 Mail Flow (Part 3), ale není to vše, co by bylo třeba znát a více informací jsem nenalezl.

Další důležitou hodnotou v logu je MessageId, což je jednoznačný identifikátor, který určuje jednu zprávu kolující v naší organizaci. Můžeme pak vyfiltrovat unikátně všechny zprávy (vždy pouze jednu událost) za určité časové období (zde si je ukládáme do proměnné).

$log = Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Where-Object { $_.EventId -eq "RECEIVE" -or $_.EventId -eq "SEND" -or $_.EventId -eq "DELIVER" } | Sort-Object MessageID -Unique | Select-Object Sender,Recipients 

Následně si je vypsat (zde vracíme pouze odesílatele a příjemce) nebo spočítat jejich počet.

$log | FT * -AutoSize 
$log | Measure-Object 

Všechny vlastnosti, které cmdlet vrací, jsou Timestamp, ClientIp, ClientHostname, ServerIp, ServerHostname, SourceContext, ConnectorId, Source, EventId, InternalMessageId, MessageId, Recipients, RecipientStatus, TotalBytes, RecipientCount, RelatedRecipientAddress, Reference, MessageSubject, Sender, ReturnPath, MessageInfo, MessageLatency, MessageLatencyType, EventData.

Varianty posílání zpráv

V praxi nastává mnoho situací, které chceme zaznamenat a které generují různé zprávy do logu. Zprávy máme Inbound (příchozí), Outbound (odchozí), Local (lokální), Remote (vzdálené). Navíc se do procesu zapojuje více rolí Exchange serveru, které si zprávu předávají a také generují události. Role mohou být nainstalovány na jednom serveru, ale také každá samostatně, což způsobí jiné chování. Také můžeme mít více serverů se stejnou rolí (kvůli redundanci a rozložení zátěže, využívá se DAG, CAS Array, apod.), třeba i v různých Site.

Záleží pak na tom, ke kterému Client Access Server (CAS) je uživatel připojen a na kterém se nachází jeho mailbox databáze. V běžných případech v praxi nastává situace, že i když máme v síti více Exchange serverů, tak skoro každou zprávu si předávají mezi sebou dva z nich. Na obrázku níže můžeme nalézt všechny možné varianty, kdy si dva uživatelé posílají zprávu.

Varianty posílání zpráv

Mnoho návodů na internetu využívá příkaz Get-MessageTrackingLog a jednoduše filtruje události SEND pro odeslané zprávy a RECEIVE pro přijaté. To je, ale dle mého názoru, špatně. Když si vypíšeme události pro jednu zprávu, tak zjistíme, že třeba událost RECEIVE se zaloguje několikrát (protože si zprávu předávají ještě servery mezi sebou).

Počítání zpráv

Další důležitá věc na zamyšlení je, jaké zprávy chceme počítat jako odchozí a jaké jako příchozí. Já počítám zprávu mezi odeslané, pokud je odesílatel v mé Exchange organizaci. Stejně tak mezi přijaté, pokud je příjemce v mé organizaci. Pokud si posílají zprávu dva uživatelé organizace, tak se započítá mezi odeslané i přijaté. Otázka je, jak počítat zprávu, která je odeslána více příjemcům (to v tuto chvíli neřeším).

Abych shrnul výše uvedené informace, jedna zpráva (jedno jak poslána) vždy vygeneruje více než jednu událost v logu. V hodně případech se vygeneruje vícekrát událost RECEIVE (protože se zpráva posílá mezi interními servery) a někdy i SEND. Naopak jsou i situace, kdy se při odeslání zprávy vůbec událost SEND negeneruje.

Můžeme si vypsat nějakou část logu seřazenou dle času, pro přesnost včetně milisekund, a analyzovat jaké události se při jaké příležitosti používají.

Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Sort-Object Timestamp | FT @{label=’Timestamp [ms]’;Expression={"{0:dd.MM.yyyy HH:mm:ss.fff}" -f $_.Timestamp}}, EventId, Source, ClientHostname, ServerHostname, Sender, Recipients, MessageId

Chtěl jsem dát dohromady tabulku všech situací odeslání a příjmu zprávy, jaké se při ní generují události a v jakém pořadí. Po analýze většího množství praktických situací, jsem zjistil, že pořadí v logu patrně neodpovídá skutečnosti. Několikrát mám u zprávy z internetu dříve zalogované přijetí (receive) na druhém poštovním serveru, než na tom, který přijímá zprávy z internetu. Protože pracujeme s milisekundami, tak patrně hraje roli i nepatrný rozdíl v čase mezi servery.

Takže alespoň události, které se nejčastěji logují pro hlavní situace. Zkratky: I - internet, E1 - první Exchange server přijímá z internetu, E2 - druhý Exchange server.

komunikace počítaná situace události v logu
I - E1 - E2 1x receive RECEIVE - RECEIVE - DELIVER - SEND
E2 - E1 - I 1x send SUBMIT - RECEIVE - SEND
E1 - E2 1x receive, 1x send RECEIVE - SUBMIT - SEND (ne vždy) - RECEIVE - DELIVER

Jak je vidět, tak nemůžeme jednoduše počítat události RECEIVE a SEND. V prvním případě, kdy se má započítat pouze jednou příjem zprávy, by se započítal dvakrát příjem a jednou odeslání. Takže pro určení odeslaných a přijatých zpráv musíme použít něco jiného.

Výpis událostí dle operace

Jedna věc, která nám může pomoci je, že si můžeme vyfiltrovat zprávy odeslané nebo přijaté z firemních adres (domén), případně poslané mezi firemními adresami. Zde si nejprve připravíme proměnné, které budeme používat i dále. Definujeme časový interval 10 minut. Vytvoříme seznam serverů, které generují logy, a seznam všech událostí z těchto serverů za časový interval uložíme do proměnné $log.

$Start = (Get-Date).AddMinutes(-10)
$End = (Get-Date)
$hubs = Get-ExchangeServer | where {$_.isHubTransportServer -eq $true -or $_.isMailboxServer -eq $true} 
$log = $hubs | Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Select-Object Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,TotalBytes,RecipientCount,MessageId

Dále již budeme pouze filtrovat údaje v proměnné $log. Zobrazíme záznamy, kde je adresa odesílatele nebo příjemce ukončena názvem naší domény.

$log | Where-Object { $_.Sender -like "*firma.cz" } | FT Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,MessageId
$log | Where-Object { $_.Recipients -like "*firma.cz*" } | FT Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,MessageId
$log | Where-Object { $_.Sender -like "*firma.cz" -and $_.Recipients -like "*firma.cz*" } | FT Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,MessageId

Pro naši situaci výhodnější je jiná možnost, kdy využijeme komunikující servery. Příchozí zprávy do firmy by měli mít právě jednu událost RECEIVE, kde je jako ClientHostname adresa jiná než firemní poštovní servery. Mohou zde být firemní aplikační servery (které můžeme také odfiltrovat, většinou dle domény). Pokud máme nějaký předřazený server (třeba jako Antispam GW), přes který chodí veškerá příchozí pošta, tak můžeme využít jeho adresu.

$log | Where-Object { $_.EventId -eq "RECEIVE" -and $_.ClientHostname -notlike "mailfirma*" } | Sort-Object Timestamp | FT Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,MessageId 

Stejně tak odchozí zprávy do internetu by měli mít právě jednu událost SEND, kde je ServerHostname nějaká adresa serveru v internetu (ne náš poštovní server).

$log | Where-Object { $_.EventId -eq "SEND" -and $_.ServerHostname -notlike "mailfirma*" } | Sort-Object Timestamp | FT Timestamp,EventId,Source,ClientHostname,ServerHostname,Sender,Recipients,MessageId 

Pomocí výše popsaných úvah můžeme spočítat různé statistické údaje. Ze všech zpráv můžeme získat informaci o velikosti největšího emailu, průměrné velikosti a celkovém objemu zpráv.

$mail_all_stats = $log | Sort-Object MessageID -Unique | Measure-Object -Property TotalBytes -Sum -Maximum -Average 

Spočítáme počet přijatých zpráv z internetu, z aplikačních serverů a odeslaných zpráv do internetu. Když tyto hodnoty odečteme od celkového počtu zpráv, tak by nám měl vyjít počet zpráv zaslaných lokálně (to znamená, že je počítáme jako odeslané i jako přijaté). Chybu nám tu budou zavádět zprávy odeslané více příjemcům a zvlášť pokud část příjemců je interní a část mimo firmu. Tyto zprávy se většinou započítají jako jedna (buď interní, nebo externí).

Nejčastější příjemci a odesilatelé

Další zajímavý údaj může být, jaký odesílatel odeslal nejvíce zpráv a jaký příjemce jich nejvíce obdržel. Někoho to může zajímat pouze z pohledu odeslaných zpráv z firmy, mne ale zajímá údaj ze všech zpráv. Pro seznam dvaceti nejčastějších odesílatelů vyfiltrujeme události, kde je vyplněn odesílatel, dle MessageID získáme unikátní události (tedy jednotlivé zprávy), ty seskupíme dle odesílatele, tím získáme i počty (Count). Pak již pouze seřadíme od největšího a vypíšeme požadovaný počet hodnot.

$log | Where-Object { $_.Sender } | Sort-Object MessageID -Unique | Group-Object Sender | Sort-Object Count -Descending | Select -First 20 | FT Count, Name -AutoSize 

Seznam nejčastějších příjemců získáme obdobně.

$log | Where-Object { $_.Recipients } | Sort-Object MessageID -Unique | Group-Object Recipients | Sort-Object Count -Descending | Select -First 20 | FT Count, Values -AutoSize 

Dlouhodobé údaje

To, co jsme si popsali v předchozích kapitolách, můžeme využít třeba ve skriptu, který spustíme každý den v noci a výsledek si necháme zaslat na email. Skript můžeme spustit i za delší období (maximálně takové, jak dlouho se nám ukládají logy), ale to nemusí být praktické. Jiná možnost je, při pravidelném denním spouštění, ukládat denní statistiky do CSV textového souboru. Poté můžeme, třeba v Excelu, získávat dlouhodobější statistiky a grafy.

Komplexní skript

Výše jsem popsal svoje úvahy, které vedly k sestavení následujícího skriptu, který při denním spouštění přináší určité statistické údaje o mailové komunikaci. Hodnoty nejsou stoprocentně přesné a část skriptu vychází z praktického pozorování chování určitého prostředí, takže v jiné konfiguraci může být trochu jiné. Rozhodně je potřeba upravit podmínky v řádcích, kde se počítají hodnoty $mail_receive_inet, $mail_receive_app, $mail_send_inet, tak jak bylo popsáno výše.

Když se skript spustí na poštovním serveru, tak vytvoří textový soubor c:\Skripty\Mail-statistics.txt, který následně odešle jako email (zde jsou další hodnoty, které je třeba upravit dle vašeho prostředí). Potom je dobré připravit soubor c:\Skripty\mail-statistics.csv, do kterého se vloží jeden řádek hlavičky CSV souboru:

date;total;processed;size[MB];receive;receive-inet;receive-app;receive-local;send;send-inet;send-local

Do tohoto souboru se budou doplňovat denní statistické údaje.

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010

$Start = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays(-1)
$End = (Get-Date -Hour 23 -Minute 9 -Second 59).AddDays(-1)

$hubs = Get-ExchangeServer | where {$_.isHubTransportServer -eq $true -or $_.isMailboxServer -eq $true}

$log = $hubs | Get-MessageTrackingLog -Start $Start -End $End -ResultSize Unlimited | Where-Object { $_.EventId -ne "NOTIFYMAPI" -and $_.EventId -ne "HAREDIRECT" } | Select-Object EventId,ClientHostname,ServerHostname,Sender,Recipients,TotalBytes,MessageId

$mail_all_stats = $log | Sort-Object MessageID -Unique | Measure-Object -Property TotalBytes -Sum -Maximum -Average
$mail_all_unique = $mail_all_stats.Count
$mail_receive_inet = ($log | Where-Object { $_.EventId -eq "RECEIVE" -and $_.ClientHostname -notlike "mailserver1" -and $_.ClientHostname -notlike "mailserver2" -and $_.ClientHostname -notlike "*firma.local" } | Measure-Object).Count
$mail_receive_app = ($log | Where-Object { $_.EventId -eq "RECEIVE" -and $_.ClientHostname -notlike " mailserver1" -and $_.ClientHostname -notlike " mailserver2" -and $_.ClientHostname -like "*firma.local" } | Measure-Object).Count
$mail_send_inet = ($log | Where-Object { $_.EventId -eq "SEND" -and $_.ServerHostname -notlike " mailserver1" -and $_.ServerHostname -notlike " mailserver2" } | Measure-Object).Count
$mail_local = $mail_all_unique - $mail_receive_inet - $mail_receive_app - $mail_send_inet
$mail_send = $mail_send_inet + $mail_local
$mail_receive = $mail_receive_inet + $mail_receive_app + $mail_local
$mail_all = $mail_send + $mail_receive

$str = "Mail servers statistics for date " + $Start.ToShortDateString() +"`r`n`r`n"
$str += "Servers:`r`n" + $hubs
$str += "`r`n`r`nTotal emails:`r`n"
$str += " count: " + "{0:N0}" -f $mail_all + "`r`n"
$str += " processed messages: " + "{0:N0}" -f $mail_all_unique + "`r`n"
$str += " size: " + "{0:N2}" -f ($mail_all_stats.Sum / (1024 * 1024)) + " MB `r`n"
$str += " biggest mail: " + "{0:N2}" -f ($mail_all_stats.Maximum / (1024 * 1024)) + " MB `r`n"
$str += " average size: " + "{0:N2}" -f ($mail_all_stats.Average / 1024) + " kB `r`n"
$str += "`r`n`r`nReceive emails:`r`n"
$str += " count: " + "{0:N0}" -f $mail_receive + "`r`n"
$str += " from internet: " + "{0:N0}" -f $mail_receive_inet + "`r`n"
$str += " from application servers: " + "{0:N0}" -f $mail_receive_app + "`r`n"
$str += " local: " + "{0:N0}" -f $mail_local + "`r`n"
$str += "`r`n`r`nSend emails:`r`n"
$str += " count: " + "{0:N0}" -f $mail_send + "`r`n"
$str += " to internet: " + "{0:N0}" -f $mail_send_inet + "`r`n"
$str += " local: " + "{0:N0}" -f $mail_local + "`r`n"
$str += "`r`n`r`nTop senders:"
$str += $log | Where-Object { $_.Sender } | Sort-Object MessageID -Unique | Group-Object Sender | Sort-Object Count -Descending | Select -First 20 | FT Count, Name -AutoSize | Out-String
$str += "Top recipients:"
$str += $log | Where-Object { $_.Recipients } | Sort-Object MessageID -Unique | Group-Object Recipients | Sort-Object Count -Descending | Select -First 20 | FT Count, Values -AutoSize | Out-String
$str | Out-File -FilePath "c:\Skripty\Mail-statistics.txt" -Width 300

Send-MailMessage -From "admin@firma.cz" -To "prijemce@firma.cz" -Subject "Statistiky z poštovních serverů" -SmtpServer "mailserver1.firma.local" -Attachments "c:\Skripty\Mail-statistics.txt" -Encoding ([System.Text.Encoding]::Unicode) -Body "Ahojda,`n`nStatistiky z posílání pošty za včerejší den.`n`nVáš administrátor ;-)`n`nPS: Vše naleznete v příloze`n"

#date;total;processed;size[MB];receive;receive-inet;receive-app;receive-local;send;send-inet;send-local 
$out = $Start.ToShortDateString() + ";" + $mail_all + ";" + $mail_all_unique + ";" + ($mail_all_stats.Sum / (1024 * 1024)) + ";" + $mail_receive + ";" + $mail_receive_inet + ";" + $mail_receive_app + ";" + $mail_local + ";" + $mail_send + ";" + $mail_send_inet + ";" + $mail_local
$out | Out-File c:\Skripty\mail-statistics.csv -Append -Encoding default
zobrazeno: 12656krát | Komentáře [4]

Autor:

Související články:

Microsoft Exchange

Jednou částí mé práce je administrace poštovního serveru od firmy Microsoft, tedy Exchange Serveru. Články začínají u verze 2003 a jak jde čas, tak pokračují dále.

Pokud se Vám článek líbil, tak mne potěšíte, když uložíte odkaz na některý server:

Pokud se chcete vyjádřit k tomuto článku, využijte komentáře níže. Pokud chcete poradit s nějakým problémem či diskutovat na nějaké téma, tak použijte fórum.

Komentáře

  1. [1] Jan

    Ahoj, velice povedený článek :)

    Nicméně měl bych dotaz, řešil jsi někdy nastavení správného času v logu? Ukazuje se mi tam o 2 hodiny méně, zřejmě je log nastaven dle GMT. Dá se to nějak změnit?

    Úterý, 01.04.2014 10:21 | odpovědět
  2. [2] Samuraj

    odpověď na [1]Jan: Neřešil, časy mám OK. Čekal bych, že záleží na nastavení serveru.

    Úterý, 01.04.2014 10:26 | odpovědět
  3. [3] Martin

    Zdravím, chci složit poklonu za vynikající článek. A rád bych položil jeden dotaz. Lze v rámci logování získávat informaci o IP adrese, na které se uživatel přihlásil do svého OWA účtu?

    Děkuji

    Pátek, 24.04.2015 13:48 | odpovědět
  4. [4] Samuraj

    odpověď na [3]Martin: Díky :-). To je trochu jiná oblast, než řešil tento článek. Nevím, jestli je na to nějaká jednoduchá možnost, ale připojení na OWA je klasicky služba IIS. To se loguje do W3SVC1 logů a z nich by to mohlo jít vytáhnout, i když je potřeba vymyslet nějaké inteligentní filtrování (je tam i ActiveSync a vůbec spousta informací).

    Pátek, 24.04.2015 14:06 | odpovědět
Přidat komentář

Vložit tag: strong em link

Vložit smajlík: :-) ;-) :-( :-O


Ochrana proti SPAMu, zdejte následující čtyři znaky image code

Nápověda:
  • maximální délka komentáře je 2000 znaků
  • HTML tagy nejsou povoleny (budou odstraněny), použít se mohou pouze speciální tagy (jsou uvedeny nad vstupním polem)
  • nový řádek (ENTER) ukončí odstavec a začne nový
  • pokud odpovídáte na jiný komentář, vložte na začátek odstavce (řádku) číslo komentáře v hranatých závorkách