Exchange 2010 Powershell指令碼攻略(七)

ImSunkist發表於2011-07-12

CollectReplicationMetrics

param(

[string] $DagName,

[string[]] $DatabaseNames,

[string] $ReportAlias,

[string] $TemporaryDataPath,

[string] $ReportPath,

[TimeSpan] $Duration = [TimeSpan]::Parse("1.00:00:00"),

[TimeSpan] $Frequency = [TimeSpan]::FromSeconds(10),

[switch] $Verbose,

[switch] $ProcessOnly)

Set-StrictMode -Version 2.0

# Define all the script-wide variables

$LocalMachine = [environment]::MachineName

# Dag object for which perf info should be collected

$Dag = $null

#List of databases for which performance counter to be collected

$Databases = @()

# Hash table to servers to databases applicable for the servers

$ServerDatabaseHash = @{}

#

# Define all helper functions for Collect Replication Metrics script

#

function NonBoring-Sleep

{

param ([int] $Seconds)

if ($Verbose)

{

$crChar = [char]::ConvertFromUtf32(13)

$currentTime = [DateTime]::Now

$targetTime = $currentTime.AddSeconds($Seconds)

while ($currentTime -lt $targetTime)

{

$diff = $targetTime - $currentTime

$outputStr = [string]::Format("{0}Time remaining until next collection: {1:D2}:{2:D2}:{3:D2}", $crChar, $diff.Hours, $diff.Minutes, $diff.Seconds)

write-host $outputStr -ForegroundColor Yellow -NoNewline

start-sleep -Seconds 1

$currentTime = [DateTime]::Now

}

write-host "$crChar $crChar" -NoNewline

}

else

{

start-sleep -Seconds:$Seconds

}

}

function ShowError([string] $errorString)

{

write-error $errorString -ErrorAction:Stop

}

function LoadSnapin

{

$snapIn = Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue

if ($snapIn -eq $null)

{

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

}

}

# Function declarations

function Trace([string] $traceString)

{

if ($Verbose)

{

write-host $traceString

}

}

function FindLocalDagName

{

$dagName = $null

$mbxServer = Get-MailboxServer $LocalMachine -ErrorAction:SilentlyContinue

if ($mbxServer -ne $Null)

{

$dagId = $mbxServer.DatabaseAvailabilityGroup

if ($dagId -ne $Null)

{

$dagName = $dagId.Name

}

else

{

ShowError("$LocalMachine is a standalone exchange server. It is not part of any database availability group")

}

}

else

{

ShowError("$LocalMachine is not a mailbox server")

}

return $dagName

}

function FindDag

{

param([string] $DagName)

$dag = $null

if ($DagName)

{

$dag = Get-DatabaseAvailabilityGroup $DagName -ErrorAction:SilentlyContinue

}

if ($dag -eq $Null)

{

ShowError("Unable to find database availability group named $DagName")

}

return $dag

}

function DetermineServersAndDatabases

{

param ([string[]] $databaseNames, [ref] $databases, [ref] $serverDbTable)

$serverHash = @{}

$databaseHash = @{}

$filteredDatabaseHash = @{}

if ($databaseNames -ne $Null)

{

# If database is specified then find all the databases that match the wildcard

# that is specified in the argslist. Also make sure that a database appears

# only once in the list

foreach ($dbName in $databaseNames)

{

foreach ($db in get-mailboxdatabase $dbName -ErrorAction:SilentlyContinue)

{

if ($databaseHash[$db.Name] -eq $null)

{

$databaseHash[$db.Name] = $db

}

}

}

}

# Make sure that the matching databases are configured in the dag

foreach ($server in $dag.Servers)

{

$serverHash[$server.Name] = @()

foreach ($db in get-mailboxdatabase -Server:$server.Name -ErrorAction:SilentlyContinue)

{

if (($databaseNames -eq $null) -or ($databaseHash[$db.Name] -ne $null))

{

$filteredDatabaseHash[$db.Name] = $db

$serverHash[$server.Name] += $db

}

}

}

if ($filteredDatabaseHash.Count -eq 0)

{

ShowError("There are no databases to monitor for database availability group $(dag.Name)")

}

$databases.Value = $filteredDatabaseHash.Values

$serverDbTable.Value = $serverHash

}

function Write-CounterCsvHeader

{

param($outputFile)

$csvHeaderLine = "Iteration,SampleTime,Database,MountStatus,CopyStatus,CopyQueueLength,LogGenerationRate,LogReplayRate"

$csvHeaderLine > $outputFile

}

function Write-ServerCsvHeader

{

param($outputFile)

$csvHeaderLine = "Iteration,SampleTime,IsReachable"

$csvHeaderLine > $outputFile

}

function Save-CounterInCsvFormat

{

param($iteration, $sampleTime, $dbName, $dbPerfMap, $outputFile)

$arrList = new-object System.Collections.ArrayList

# Iteration number of the collection

[void] $arrList.Add($iteration)

$strTime = Get-CustomDateString ($sampleTime)

# Time when the sample was collected

[void] $arrList.Add($strTime)

# Database name

[void] $arrList.Add($dbName)

# MountStatus => Mounted,Dismounted,Unavailable

$mountStatus = "Unavailable"

$copyStatus = new-object System.Collections.ArrayList

$entry = $dbMap[$dbName]

if ($entry)

{

if (Get-BooleanState ($entry.AmPerf) ("Database Mounted"))

{

$mountStatus = "Mounted"

}

else

{

$mountStatus = "Dismounted"

}

if ($entry.ReplPerf)

{

if (Get-BooleanState ($entry.ReplPerf) ("Initializing"))

{

[void] $copyStatus.Add("Initializing")

}

if (Get-BooleanState ($entry.ReplPerf) ("Suspended"))

{

[void] $copyStatus.Add("Suspended")

}

if (Get-BooleanState ($entry.ReplPerf) ("FailedSuspended"))

{

[void] $copyStatus.Add("FailedSuspended")

}

if (Get-BooleanState ($entry.ReplPerf) ("Resynchronizing"))

{

[void] $copyStatus.Add("Resynchronizing")

}

if (Get-BooleanState ($entry.ReplPerf) ("Disconnected"))

{

[void] $copyStatus.Add("Disconnected")

}

}

else

{

[void] $copyStatus.Add("Unavailable")

}

}

# Append mount status

[void] $arrList.Add($mountStatus)

# Append copy status

[void] $arrList.Add([string]::Join(":",$copyStatus.ToArray()))

if ($entry -and $entry.ReplPerf)

{

[void] $arrList.Add($entry.ReplPerf["CopyQueueLength"])

[void] $arrList.Add($entry.ReplPerf["log generation rate on source (generations/sec)"])

[void] $arrList.Add($entry.ReplPerf["log replay rate (generations/sec)"])

}

else

{

[void] $arrList.Add([string]::Empty)

[void] $arrList.Add([string]::Empty)

[void] $arrList.Add([string]::Empty)

}

$csvLine = [string]::Join(",",$arrList)

$csvLine >> $outputFile

}

function Create-EmptyServerRecord

{

param ([string] $serverName)

$record = new-object object

$emptyTs = new-object TimeSpan

add-member -inputobject $record -MemberType NoteProperty "Name" -Value $serverName

add-member -inputobject $record -MemberType NoteProperty "DurationMeasured" -Value $emptyTs

add-member -inputobject $record -MemberType NoteProperty "DurationUnavailable" -Value $emptyTs

add-member -inputobject $record -MemberType NoteProperty "AverageDurationMounted" -Value $emptyTs

add-member -inputobject $record -MemberType NoteProperty "AverageDurationDismounted" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "AverageLogReplayRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "PeakLogReplayRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "DbInfo" -Value @{}

add-member -InputObject $record -MemberType NoteProperty "ServerInfo" -Value $null

return $record

}

function Create-EmptyDatabaseRecord

{

param ([string] $databaseName)

$record = new-object object

$emptyTs = new-object TimeSpan

add-member -InputObject $record -MemberType NoteProperty "Name" -Value $databaseName

add-member -InputObject $record -MemberType NoteProperty "TotalEntriesProcessed" -Value ([int] 0)

add-member -InputObject $record -MemberType NoteProperty "DurationMountStatusMounted" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationMountStatusDismounted" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationMountStatusUnavailable" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusUnavailable" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusResynchronizing" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusFailed" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusSuspended" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusFailedSuspended" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusDisconnected" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "TotalLogGenerationRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "AverageLogGenerationRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "PeakLogGenerationRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "TotalLogReplayRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "AverageLogReplayRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "PeakLogReplayRate" -Value 0

add-member -InputObject $record -MemberType NoteProperty "DurationOutOfCriteria" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "AverageDurationOutOfCriteria" -Value $emptyTs

add-member -InputObject $record -MemberType NoteProperty "PrevPerfEntry" -Value $null

return $record

}

function Populate-ServerADInfo

{

param ($svrRecord)

$svrRecord.ServerInfo = get-mailboxserver $svrRecord.Name

}

function Get-ElsapedTimeBetweenIterations

{

param ($prevTimeStr, $currentTimeStr)

if ($prevTimeStr -match "(d+)/(d+)/(d+)-(d+):(d+):(d+)")

{

$prevSampleTime = new-object datetime $matches[1],$matches[2],$matches[3],$matches[4],$matches[5],$matches[6]

}

if ($currentTimeStr -match "(d+)/(d+)/(d+)-(d+):(d+):(d+)")

{

$newSampleTime = new-object datetime $matches[1],$matches[2],$matches[3],$matches[4],$matches[5],$matches[6]

}

$duration = $newSampleTime - $prevSampleTime

return $duration

}

function Update-CopystatusDurations

{

param ($dbRecord, $newPerfEntry, $duration)

foreach ($cpStatusName in $newPerfEntry.CopyStatus.Split(","))

{

if ($cpStatusName)

{

$memberName = "DurationCopyStatus" + $cpStatusName

$dbRecord.$memberName += $duration

}

}

}

function Update-MountStatusDurations

{

param ($dbRecord, $newPerfEntry, $duration)

foreach ($mountStatusName in $newPerfEntry.MountStatus.Split(","))

{

$memberName = "DurationMountStatus" + $mountStatusName

$dbRecord.$memberName += $duration

}

}

function PredictTime-ByTransition

{

param($prevData, $currentData, $perfMemberName)

[int] $predictedMs = 0

if ($currentData.$perfMemberName -gt 0)

{

if (($prevData -eq $null) -or ($prevData.$perfMemberName -eq 0))

{

$predictedMs += ($Frequency.TotalMilliseconds)/2

}

else

{

$predictedMs += $Frequency.TotalMilliseconds

}

}

else

{

if (($prevData -eq $null) -or ($prevData.$perfMemberName -gt 0))

{

$predictedMs += ($Frequency.TotalMilliseconds)/2

}

}

return $predictedMs

}

function Parse-Counter

{

param ($sample)

$counterDetails = $null

if ($sample.Path -imatch "+(.*?)+(.*?)((.*))+(.*)")

{

$counterDetails = new-object object

Add-Member -InputObject $counterDetails -MemberType NoteProperty "MachineName" -Value $matches[1]

Add-Member -InputObject $counterDetails -MemberType NoteProperty "Category" -Value $matches[2]

Add-Member -InputObject $counterDetails -MemberType NoteProperty "InstanceName" -Value $matches[3]

Add-Member -InputObject $counterDetails -MemberType NoteProperty "CounterName" -Value $matches[4]

Add-Member -InputObject $counterDetails -MemberType NoteProperty "CounterValue" -Value ([int] $sample.CookedValue)

}

return $counterDetails

}

function Convert-CountersToMap

{

param($instanceMap, $categoryMemberName, $counterInfo)

if ($counterInfo)

{

foreach ($sample in $counterInfo.CounterSamples)

{

$counterDetails = Parse-Counter ($sample)

if ($counterDetails)

{

$instanceName = $counterDetails.InstanceName

$counterCategory = $counterDetails.Category

$counterName = $counterDetails.CounterName

$counterValue = $counterDetails.CounterValue

$pairMember = $instanceMap[$instanceName]

if ($pairMember -ne $null)

{

$pairMember.$($categoryMemberName)[$counterName] = $counterValue

}

}

}

}

}

function Get-BooleanState

{

param($perfMap, $counterName)

$isFound = $false

if (($perfMap -ne $null) -and ($perfMap[$counterName] -gt 0))

{

return $true

}

return $false

}

function Get-CustomDateString

{

param($sampleTime)

$str = $sampleTime.ToString("yyyy/MM/dd-hh:mm:ss")

return $str

}

function Get-TempDbOutputFile

{

param($serverName)

$outputFile = "$($TemporaryDataPath)$($serverName)_DatabaseInfo.csv"

return $outputFile

}

function Get-TempServerOutputFile

{

param($serverName)

$outputFile = "$($TemporaryDataPath)$($serverName)_ServerInfo.csv"

return $outputFile

}

# Load the exchange snapin so that we can use the exchange cmdlets in this script

LoadSnapin

$scriptStartTime = get-date

$scriptStartTimeStr = $scriptStartTime.ToString("yyy_MM_dd_hh_mm_ss")

if ($DagName)

{

# If DatabaseAvailabilityGroup is specified, then use that. Otherwise default

# to the database availability group which has the local node as a member

$Dag = FindDag -DagName:$DagName

}

else

{

$DagName = FindLocalDagName

$Dag = FindDag -DagName:$DagName

}

# If Database (array) is specified, then use that. Otherwise default to all

# the databases in the current dag

DetermineServersAndDatabases $DatabaseNames ([ref] $Databases) ([ref] $ServerDatabaseHash)

# If temp path is not specified, then assume a default one

if ([string]::IsNullOrEmpty($TemporaryDataPath))

{

$TemporaryDataPath = "$env:SystemDriveTempCollectReplicationMetrics$($scriptStartTime.ToString('yyy_MM_dd_hh_mm_ss'))"

}

# If report path is not specified in the command line then produce the results in the current directory

if (!$ReportPath)

{

$ReportPath = "."

}

# Keep the final report in the following directory

$DatabaseReportFile = $ReportPath+"DB_CollectReplicationMetrics_$($dag)_$scriptStartTimeStr.csv"

$ServerReportFile = $ReportPath+"SERVER_CollectReplicationMetrics_$($dag)_$scriptStartTimeStr.csv"

# Create temp directory if it doesn't exist already

if (!(Test-Path $TemporaryDataPath))

{

$dummy = new-item -ItemType Directory -Path:$TemporaryDataPath

}

if (!$ProcessOnly)

{

$currentTime = [DateTime]::Now

$endTime = $currentTime + $Duration

$iteration = 0

foreach ($serverName in $ServerDatabaseHash.Keys)

{

$outputFile = "$($TemporaryDataPath)$($serverName)_DatabaseInfo.csv"

$serverOutputFile = "$($TemporaryDataPath)$($serverName)_ServerInfo.csv"

Write-CounterCsvHeader $outputFile

Write-ServerCsvHeader $serverOutputFile

}

# Now start perfmon collection for the requested duration

while ($currentTime -lt $endTime)

{

write-host "Collecting samples at $currentTime"

$iteration++

$collectionInitiatedTime = [DateTime]::Now

foreach ($serverName in $ServerDatabaseHash.Keys)

{

Trace("Retrieving performance counters from $serverName")

$outputFile = Get-TempDbOutputFile $serverName

$serverOutputFile = Get-TempServerOutputFile $serverName

$sampleTime = [DateTime]::Now

$amCounterInfo = $null

$replCounterInfo = $null

$isServerReachable = 0

# Get core counter to find if machine is accessible

$procCounterInfo = get-counter "processor(_total)% processor time" -ComputerName:$serverName -MaxSamples:1 -ErrorAction:SilentlyContinue

if ($procCounterInfo)

{

$isServerReachable = 1

# Get AM counters for all the databases to optimize multiple trips for each database

$amCounterInfo = get-counter "MSExchange Active Manager(*)*" -ComputerName:$serverName -MaxSamples:1 -ErrorAction:SilentlyContinue

$replCounterInfo= get-counter "MSExchange Replication(*)*" -ComputerName:$serverName -MaxSamples:1 -ErrorAction:SilentlyContinue

}

$strTime = Get-CustomDateString ($sampleTime)

"$iteration,$strTime,$isServerReachable" >> $serverOutputFile

# Initialize db map with perf counter categories

$dbMap = @{}

foreach ($dbObj in $Databases)

{

$obj = new-object object

add-member -InputObject $obj -MemberType NoteProperty "AmPerf" -Value @{}

add-member -InputObject $obj -MemberType NoteProperty "ReplPerf" -Value @{}

$dbMap[$dbObj.Name] = $obj

}

# Convert retrieved counters to a convenient map

Convert-CountersToMap ($dbMap) ("AmPerf") ($amCounterInfo)

Convert-CountersToMap ($dbMap) ("ReplPerf") ($replCounterInfo)

foreach ($db in $ServerDatabaseHash[$serverName])

{

Save-CounterInCsvFormat ($iteration) ($sampleTime) ($db.Name) ($dbMap) ($outputFile)

}

}

$collectionCompletedTime = [DateTime]::Now

$elaspedCollectionDuration = $collectionCompletedTime - $collectionInitiatedTime

$durationToSleep = 0

if ($elaspedCollectionDuration -lt $Frequency)

{

$durationToSleep = ($Frequency - $elaspedCollectionDuration).TotalSeconds

}

if ($durationToSleep)

{

# Just make the sleep little bit interesting by providing some text mode fun

NonBoring-Sleep -Seconds $durationToSleep

}

$currentTime = [DateTime]::Now

}

write-host ""

}

$serverResults = @{}

# Crunch the data and prepare a datastructure that holds the

# required results

foreach ($serverName in $ServerDatabaseHash.Keys)

{

# Just create bunch of NoteProperties for convenience

$svrRecord = Create-EmptyServerRecord $serverName

# Fill svrrecord with the output of get-mailboxserver since we need

# some of these properties later

Populate-ServerADInfo $svrRecord

# Process all the databases on this server

$dbDataFile = Get-TempDbOutputFile $serverName

$serverDataFile = Get-TempServerOutputFile $serverName

foreach ($dbData in import-csv $dbDataFile)

{

# Create per db record if it doesn't exist already

$dbRecord = $svrRecord.DbInfo[$dbData.Database]

if ($dbRecord -eq $null)

{

$dbRecord = Create-EmptyDatabaseRecord $dbData.Database

$svrRecord.DbInfo[$dbData.Database] = $dbRecord

}

# Find out how much time elasped between the runs

$duration = $Frequency

if ($dbRecord.PrevPerfEntry -ne $null)

{

$duration = Get-ElsapedTimeBetweenIterations ($dbRecord.PrevPerfEntry.SampleTime) ($dbData.SampleTime)

}

Update-CopystatusDurations ($dbRecord) ($dbData) ($duration)

Update-MountStatusDurations ($dbRecord) ($dbData) ($duration)

$dbRecord.TotalLogGenerationRate += $dbData.LogGenerationRate

if ($dbData.LogGenerationRate -gt $dbRecord.PeakLogGenerationRate)

{

$dbRecord.PeakLogGenerationRate = $dbData.LogGenerationRate

}

$dbRecord.TotalLogGenerationRate += $dbData.LogGenerationRate

if ($dbData.LogReplayRate -gt $dbRecord.PeakLogReplayRate)

{

$dbRecord.PeakLogReplayRate = $dbData.LogReplayRate

}

if (($dbData.CopyQueueLength+1) -gt [int] $svrRecord.ServerInfo.AutoDatabaseMountDial)

{

$dbRecord.DurationOutOfCriteria += $duration

}

$dbRecord.TotalEntriesProcessed++

$dbRecord.PrevPerfEntry = $dbData

}

$totalPerServerMountedDuration = [TimeSpan]::FromSeconds(0)

$totalPerServerDismountedDuration = [TimeSpan]::FromSeconds(0)

$totalPerServerEntries = 0

$totalPerServerLogReplayRate = 0

$perServerPeakLogReplayRate = 0

# Calculate the per-db average info

foreach($dbName in $svrRecord.DbInfo.Keys)

{

$dbRecord = $svrRecord.DbInfo[$dbName]

$dbRecord.AverageLogGenerationRate = $dbRecord.TotalLogGenerationRate / $dbRecord.TotalEntriesProcessed

$dbRecord.AverageLogReplayRate = $dbRecord.TotalLogReplayRate / $dbRecord.TotalEntriesProcessed

$totalPerServerMountedDuration += $dbRecord.DurationMountStatusMounted

$totalPerServerDismountedDuration += $dbRecord.DurationMountStatusDismounted

$totalPerServerLogReplayRate += $dbRecord.TotalLogReplayRate

if ($dbRecord.PeakLogReplayRate -gt $perServerPeakLogReplayRate)

{

$perServerPeakLogReplayRate = $dbRecord.PeakLogReplayRate

}

$totalPerServerEntries += $dbRecord.TotalEntriesProcessed

}

# Calculate per-server average info

$svrRecord.AverageDurationMounted = [TimeSpan]::FromSeconds($totalPerServerMountedDuration.TotalSeconds / $totalPerServerEntries)

$svrRecord.AverageDurationDismounted = [TimeSpan]::FromSeconds($totalPerServerDismountedDuration.TotalSeconds / $totalPerServerEntries)

$svrRecord.AverageLogReplayRate = $totalPerServerLogReplayRate / $totalPerServerEntries

$svrRecord.PeakLogReplayRate = $perServerPeakLogReplayRate

$serverPrevEntry = $null

# Crunch the data from the per-server file

foreach($serverEntry in import-csv $serverDataFile)

{

$duration = $Frequency

if ($serverPrevEntry -ne $null)

{

$duration = Get-ElsapedTimeBetweenIterations ($serverPrevEntry.SampleTime) ($serverEntry.SampleTime)

}

$svrRecord.DurationMeasured += $duration

if (!$serverEntry.IsReachable)

{

$svrRecord.DurationUnavailable += $duration

}

$serverPrevEntry = $serverEntry

}

$serverResults[$serverName] = $svrRecord

}

# Write headers for server report file

$serverHeader = new-object System.Collections.ArrayList

[void] $serverHeader.Add("ServerName")

[void] $serverHeader.Add("HoursMeasured")

[void] $serverHeader.Add("HoursUnavailable")

[void] $serverHeader.Add("AverageMountedMinutes")

[void] $serverHeader.Add("AverageLogReplayRate")

[void] $serverHeader.Add("PeakLogReplayRate")

[string]::Join(",",$serverHeader) > $ServerReportFile

# Write headers for database report file

$dbHeader = new-object System.Collections.ArrayList

[void] $dbHeader.Add("ServerName")

[void] $dbHeader.Add("DatabaseName")

[void] $dbHeader.Add("HoursMounted")

[void] $dbHeader.Add("MinutesUnavailabe")

[void] $dbHeader.Add("MinutesResynchronizing")

[void] $dbHeader.Add("MinutesFailed")

[void] $dbHeader.Add("MinutesSuspended")

[void] $dbHeader.Add("MinutesFailedSuspended")

[void] $dbHeader.Add("MinutesDisconnected")

[void] $dbHeader.Add("AverageLogGenerationRate")

[void] $dbHeader.Add("PeakLogGenerationRate")

[void] $dbHeader.Add("AverageLogReplayRate")

[void] $dbHeader.Add("PeakLogReplayRate")

[void] $dbHeader.Add("OutofCriteriaSeconds")

[void] $dbHeader.Add("AverageOutofCriteriaSeconds")

[string]::Join(",",$dbHeader) > $DatabaseReportFile

# Reports are now ready in-memory. Dump those into a csv file

foreach ($serverName in $serverResults.Keys)

{

$svrRec = $serverResults[$serverName]

$serverData = new-object System.Collections.ArrayList

[void] $serverData.Add($svrRec.Name)

[void] $serverData.Add([string]::Format("{0:0.###}", $svrRec.DurationMeasured.TotalHours))

[void] $serverData.Add([string]::Format("{0:0.###}", $svrRec.DurationUnavailable.TotalHours))

[void] $serverData.Add([string]::Format("{0:0.###}", $svrRec.AverageDurationMounted.TotalMinutes))

[void] $serverData.Add($svrRec.AverageLogReplayRate)

[void] $serverData.Add($svrRec.PeakLogReplayRate)

[string]::Join(",", $serverData) >> $ServerReportFile

$dbRecords = $svrRec.DbInfo

foreach ($dbName in $dbRecords.Keys)

{

$dbRec = $svrRec.DbInfo[$dbName]

$dbData = new-object System.Collections.ArrayList

[void] $dbData.Add($svrRec.Name)

[void] $dbData.Add($dbRec.Name)

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationMountStatusMounted.TotalHours))

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusUnavailable.TotalMinutes))

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusResynchronizing.TotalMinutes))

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusFailed.TotalMinutes))

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusSuspended.TotalMinutes))

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusFailedSuspended.TotalMinutes))

[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusDisconnected.TotalMinutes))

[void] $dbData.Add($dbRec.AverageLogGenerationRate)

[void] $dbData.Add($dbRec.PeakLogGenerationRate)

[void] $dbData.Add($dbRec.AverageLogReplayRate)

[void] $dbData.Add($dbRec.PeakLogReplayRate)

[void] $dbData.Add($dbRec.DurationOutOfCriteria.TotalSeconds)

[void] $dbData.Add($dbRec.AverageDurationOutOfCriteria.TotalSeconds)

[string]::Join(",", $dbData) >> $DatabaseReportFile

}

}

if ($Verbose)

{

write-host ""

write-host "Database report"

write-host "==============="

$dbReport = import-csv $DatabaseReportFile

$dbReport | ft

write-host "Server report"

write-host "============="

$serverReport = import-csv $ServerReportFile

$serverReport | ft

}

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23700676/viewspace-1052333/,如需轉載,請註明出處,否則將追究法律責任。

相關文章