PowerShell LDAP response time monitor

I recently had some issues with a system not getting very response times to LDAP queries sent to various Active Directory domain controllers.

These were resolved via a combination of Windows Server 2003 Server Performance Advisor and the built in, better, equivalent in 2008 R2 (found via Performance Monitor/Server Manager – Diagnostics – Performance – Data Collector Sets – System – Active Directory Diagnostics). It turned out that a new system was running an expensive full directory tree query against a non-indexed attribute and this was using all the CPU. I have now got the attribute indexed, the query optimised to only look in certain OUs, and given the DC VM an extra CPU.

Anyway, in order to try and notice this kind of thing in the future I have written a script that tests all my DCs by running a simple (if non-optimal) query every ten seconds, and log the results to a CSV file for easy graphing/analysis in Excel. It also sends me an email if any of the DCs take longer than a specified number of milliseconds to return the results of the query. And it rolls the log file over when it reaches a specified size. The script can be run on multiple machines simultaneously so that you can test response times form different parts of your network and/or different PCs/servers. Create the log file folder before running the script for the first time.

Script is as follows:

# Specify DCs manually, or get all of them automatically
#$DCs = "dc03","dc04","dc05","dc06","dc07","dc08"
$DCs = (Get-ADDomainController -Filter *).Name
$LDAPUserToQuery = "tstd68"
$Logfile = "C:\Logs\LDAPTimes.csv"
$LogRollSize = 1024000 # size is in bytes
$SMTPServer = "smtp.rcmtech.co.uk"
$MailTo = "my.user@rcmtech.co.uk"

function Test-LDAPQuery($User,$DC){
    # assume that the DC is in the same domain as the user running the test
    $Root = [ADSI] ("LDAP://"+$DC+"."+$env:USERDNSDOMAIN)
	$Searcher = New-Object System.DirectoryServices.DirectorySearcher $Root
	$Searcher.Filter = "(cn=$User)"
    # run the query and time how long it takes in milliseconds
	$Milliseconds = (Measure-Command {$Container = $Searcher.FindAll()}).TotalMilliseconds
    # this script doesn't do anything with the results of the query
    return $Milliseconds
}

while($true){
    $ThisResult = New-Object System.Object
    $ThisResult | Add-Member -Type Noteproperty -Name DateTime -Value (Get-Date -Format G)
    foreach($DC in $DCs){
        $Milliseconds = Test-LDAPQuery -User $LDAPUserToQuery -DC $DC
        if($Milliseconds -gt 600){
            Send-MailMessage -From ("LDAPPerfTest@"+$env:COMPUTERNAME+"."+$env:USERDNSDOMAIN) -Subject ($DC+" took "+$Milliseconds+"ms") -Body "The log file can be found at $Logfile on the machine that sent this email" -To $MailTo -SmtpServer $SMTPServer
        }
        $ThisResult | Add-Member -Type Noteproperty -Name $DC -Value $Milliseconds
    }
    $ThisResult
    $ThisResult | Export-Csv -Path $Logfile -Append -NoTypeInformation
    $Log = Get-ChildItem -Path $Logfile
    if($Log.Length -ge $LogRollSize){
        Rename-Item -Path $Logfile -NewName ($Logfile.Replace($Log.Extension,"")+"_"+(Get-Date -Format s).Replace(":","-")+$Log.Extension)
    }
    Write-Host "Waiting..."
    Start-Sleep -Seconds 10
}
This entry was posted in Performance, PowerShell, Windows and tagged , , , , , , , , , , , , , . Bookmark the permalink.

3 Responses to PowerShell LDAP response time monitor

  1. rikkard says:

    thank you, works great!

    Like

  2. John Mohler says:

    We have a similar issue on Server 2012. Can you tell us how you got the query to index instead of loading everything every time?

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.