How to monitor DFS replication on several servers/sites?


Modified and extended version for DFS monitoring

One of the challenges with DFS is to monitor the DFS replication backlog. There are various scripts out there to accomplish this. Unfortunately I found nothing I really liked and giving me the simple insight I wanted.

The goal was simple – a script that will monitor the backlog between two systems in both directions – meaning Server-A to Server-B and Server-B to Server-A. For both directions I wanted to see the amount of files as well as the size of those files. I did not care about what DFS groups and or DFS folders are affected in detail – this is because the amount of groups might change, the amount of folders will likely change rather frequently, meaning it would be a challenge to monitor it per group or even on a folder level very efficient. Monitoring the amounts of groups and folders alone has no really advantage, cause this would have been changed by an administrator.

Below you will find the script that actually expects three parameter – the two server names and a limit integer value. The limit will not influence the XML response of the script, you could add the <text>$Response</text> and <text>$Response2</text> tags in lines 77 and 79 after the </unit> and before the </result> tag if you want, I removed them currently.


Create the following script in C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML and make sure you have the C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Dfsr\ and the C:\Windows\SysWow64\WindowsPowerShell\v1.0\Modules\Dfsr\ folders – you might need to copy them over. If you miss them at all, you might need to add the needed Windows Roles/Features or install the RSAT (Remote Server Administration Tools) on your system.

Script: Get-DFS-Backlog-For-Servers.ps1

Param(
$SourceComputer=$args[0],
$DestinationComputer=$args[1],
$MaxBackLog=$args[2]
)

Import-Module Dfsr
#Import-Module -FullyQualifiedName "C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Dfsr\DfsrPowerShell.dll"
#Module needs to be in System32 and SysWow64 directory - make sure the path exists in both cases

$Count=-1
$TotalSize=0
$Count2=-1
$TotalSize2=0
$Response="-1:Script did not execute right"
$Response2="-1:Script did not execute right"

$err = $null
$BackLog = Get-DfsrBacklog -SourceComputerName "$SourceComputer" -DestinationComputerName "$DestinationComputer" -ea SilentlyContinue -ev err;
If ($err -ne $null)
{
$Response="-2:Script error with GET-DFSRBACKLOG"
}
Else
{
$Response = "-3:Error getting count"
$Count = $BackLog.Count
If ($Count -gt $MaxBackLog)
{
$Response = "Alarm - Backlog is over defined maximum of $MaxBackLog"
}
Else
{
$Response = "OK"
}
ForEach($Item in $BackLog)
{
$file = $Item.FullPathName
$file = $file -replace ":", "$"
$file = "\\$SourceComputer\$file"
If (Test-Path $file)
{
$TotalSize += (Get-Item $file).Length
}
}
}
$err = $null
$BackLog2 = Get-DfsrBacklog -DestinationComputerName "$SourceComputer" -SourceComputerName "$DestinationComputer" -ea SilentlyContinue -ev err;
If ($err -ne $null)
{
$Response2="-2:Script error with GET-DFSRBACKLOG"
}
Else
{
$Response2 = "-3:Error getting count"
$Count2 = $BackLog2.Count
If ($Count2 -gt $MaxBackLog)
{
$Response2 = "Alarm - Backlog is over defined maximum of $MaxBackLog"
}
Else
{
$Response2 = "OK"
}
ForEach($Item in $BackLog2)
{
$file = $Item.FullPathName
$file = $file -replace ":", "$"
$file = "\\$DestinationComputer\$file"
If (Test-Path $file)
{
$TotalSize2 += (Get-Item $file).Length
}
}
}
$XML = "<prtg>"
$XML += "<result><channel>BackLog count 1</channel><value>$Count</value><unit>Count</unit></result>"
$XML += "<result><channel>BackLog size 1</channel><value>$TotalSize</value><unit>BytesFile</unit></result>"
$XML += "<result><channel>BackLog count 2</channel><value>$Count2</value><unit>Count</unit></result>"
$XML += "<result><channel>BackLog size 2</channel><value>$TotalSize2</value><unit>BytesFile</unit></result>"
$XML += "</prtg>"

Function WriteXmlToScreen ([xml]$xml)
{
$StringWriter = New-Object System.IO.StringWriter;
$XmlWriter = New-Object System.Xml.XmlTextWriter $StringWriter;
$XmlWriter.Formatting = "indented";
$xml.WriteTo($XmlWriter);
$XmlWriter.Flush();
$StringWriter.Flush();
Write-Output $StringWriter.ToString();
}

WriteXmlToScreen $XML

This whole article can also be found on my personal blog-page where I posted more useful scripts - partly for PRTG as well https://www.it-admins.com/monitor-dfs-replication-backlog-between-servers-in-prtg


While looking at at way to monitor DFS replication stumbled upon the DFS Backlog By monitoring the DFS Backlog on each server we get a good and solid view to the state of our DFS replication. As DFS replication are known to take it's time to come around its replication we allow quite some time before changing status to failed.


Implementation:


The script was saved under "Custom Sensors/EXE" with the name "Get-DFS-Backlog-For-Server.ps1"

Param(
$hosttransfere=$args[0]
)

import-module Dfsr

$computername = [System.Net.Dns]::GetHostByAddress($hosttransfere).hostname
$computername = $computername.Replace(".domainname.com","")
$testDFSBacklog = Get-DfsrBacklog -computername $computername

$count = -1
ForEach($Item in $testDFSBacklog)
{
If($count -eq -1){$count = 0}
$count += $Item.Backlog
}

Write-host $count,":OK"

Monitoring:


The sensor was then added to a server running DFS as a "EXE/Script" sensor.

  • Tag: DFS
  • EXE/Scripts: Get-DFS-Backlog-For-Server-ps1
  • Parameters:'%host'
  • Timeout (Sec.): 600
  • EXE Result: " Write EXE result to disk in case of error"
  • Scanning Interval: 1 hour

When a Sensor Reports an Error: Set sensor to warning for 5 intervals, then set to "down"


Finally the Channel was altered to have:

  • "Upper Error Limit (#)" of 50.000 (this is to be adjusted according to your number of files in DFS)
  • "Lower Error Limit (#)" 0 (as the script starts at -1 until contact with the server is in place this will tell you if the servers was available at the time)

The sensor was added to several servers and displayed in a Custom map Object build on the "Top 10 list container" The Object was saved under "webroot/mapobjects" with the name "Top10 Count-DFS.htm"

Sorting and columns can be altered as you wish to see them.

<!--Custom Collection: DFS-->

<div class="map_object map_table" id="<@itemid>" objectid="<@objectid>" subid="<@subid>" style="overflow:auto;<#mapobject type="coordinates" subid="<@subid>" mode="<@editmode>">">
<#mapobject type="objectgrip" mode="<@editmode>">
<#mapobject type="htmlbefore" subid="<@subid>">
<#checkobjecttype objecttype="probenode,group,device" nicemessage="true" id="<@objectid>">

<div class="top10listcontainer" style="overflow:hidden">
<#lang default="DFS (@@@@)" var="tabletitle">
<#table tableid="sensortable"
content="sensors"
columns="lastvalue,sensor"
sortby="sensor"
_subid='2'
sortable="false"
refreshable="false"
infoheader="false"
links="false"
filter_tags="@tag(DFS)"
count="15"
varexpand="tabletitle"
tabletitle="DFS Backlog (1 hour update)"
id="<@objectid>">
</div>


<#mapobject type="htmlafter" subid="<@subid>">
</div>

I hope this can help some of you - It has given us a big help in our daily monitoring :)


Disclaimer:
The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.