Get-IncrementalCollectionEvaluationResults.ps1

<#PSScriptInfo
.DESCRIPTION
    Gets statistics for the most recent or currently running Incremental Evaluation Cycle (Express Evaluation) from the colleval.log in Configuration Manager
.VERSION
    1.0
.GUID
    7e205389-27ca-4eac-9662-6c129565ec61
.AUTHOR
    Trevor Jones
.TAGS
    ConfigMgr, SCCM, Configuration Manager, Collection Evaluation
#>


#requires -Version 2

 <#
.Synopsis
   Gets statistics for the most recent or currently running Incremental Evaluation Cycle (Express Evaluation) from the colleval.log in Configuration Manager
.DESCRIPTIONS
   Reads the colleval.log on a Configuration Manager Primary Site server to extract data and statistics from the Incremental Collection evaluation cycle.
 
   Since the log file may contain results from more than one cycle, you should limit the time period in which to search the log file using the -TimePeriodInMinutes parameter. This should
   be set to the same value (or less) as your Collection Membership Evaluation Cycle interval in Configuration Manager (default 5).
 
   As this log file is frequently updated and periodically rolled over, it's possible that incomplete results may be returned if the current log file itself does not contain all the log
   entries for the most recent cycle.
 
   If the cmdlet is run while an incremental evaluation cycle is currently in progress, incomplete results will also be returned until the cycle has finished.
 
   The cmdlet returns the list of collections evaluated as an array, so save the output to a variable to view them.
 
   PSRemoting is used so the cmdlet should not be run on the site server itself.
.EXAMPLE
   Get-IncrementalCollectionEvaluation -SiteServer SCCM-01
 
   Returns statistics for the most recent incremental evaluation cycle on the site server SCCM-01
.EXAMPLE
   Get-IncrementalCollectionEvaluation -SiteServer SCCM-01 -TimePeriodInMInutes 10
 
   Returns statistics for the most recent incremental evaluation cycle on the site server SCCM-01 with an extended time period
.EXAMPLE
   $Result = Get-IncrementalCollectionEvaluation -SiteServer SCCM-01
   $Result.'Collections Evaluated List'
 
   Returns the list of collections that were evaluated in the time period with the collection ID, how long the evaluation took and the time of the evaluation.
#>

  
    [CmdletBinding()]
    Param
    (
        # ConfigMgr Primary Site Server name
        [Parameter(Mandatory = $true)]
        [string]$SiteServer,
        
        # Number of minutes past to check the colleval.log
        [Parameter(Mandatory = $false)]
        [int]$TimePeriodInMinutes = 5
    )


###################
# Get the results #
###################

# Set the earliest date/time to return results for
[datetime]$CurrentTime = Get-Date
$EarliestTime = $CurrentTime.AddMinutes(-$TimePeriodInMinutes) | Get-Date

# Open a new PS remoting session to the site server
if ($env:COMPUTERNAME -eq $SiteServer)
    {
        Write-host 'This script uses PSRemoting to the site server and cannot be run on the site server itself.' -ForegroundColor Red
        continue
    }
$s = New-PSSession -ComputerName $SiteServer

# Get the current number of collections in the incremental evaluation graph
[array]$CollectionsFound = Invoke-Command -Session $s -ScriptBlock {
$CollectionsFound = @()
$string = Select-String -Path "$env:SMS_LOG_PATH\colleval.log" -Pattern 'collections in incremental evaluation graph'
$string | ForEach-Object -Process {
    $obj = '' | Select-Object -Property String, Date
    $obj.String = $_.Line.Split('$')[0]
    [datetime]$obj.Date = $_.Line.Split('<')[2] -replace ".{4}$"
    $CollectionsFound += $obj
    }
$CollectionsFound = $CollectionsFound | Where-Object -FilterScript {
$_.date -ge $using:EarliestTime
}
$CollectionsFound
} | Select-Object -Property String, Date

# Get the time the evaluation cycle started
[array]$EvaluationStarted = Invoke-Command -Session $s -ScriptBlock {
$EvaluationStarted = @()
$string = Select-String -Path "$env:SMS_LOG_PATH\colleval.log" -Pattern 'Express Evaluator] Starting'
$string | ForEach-Object -Process {
    $obj = '' | Select-Object -Property String, Date
    $obj.String = $_.Line.Split('$')[0]
    [datetime]$obj.Date = $_.Line.Split('<')[2] -replace ".{4}$"
    $EvaluationStarted += $obj
    }
$EvaluationStarted = $EvaluationStarted | Where-Object -FilterScript {
$_.date -ge $using:EarliestTime
}
$EvaluationStarted
} | Select-Object -Property String, Date

# Get the list of collections that were evaluated
[array]$CollectionEvaluated = Invoke-Command -Session $s -ScriptBlock {
$CollectionEvaluated = @()
$string = Select-String -Path "$env:SMS_LOG_PATH\colleval.log" -Pattern 'Express Evaluator] successfully evaluated collection'
$string | ForEach-Object -Process {
    $obj = '' | Select-Object -Property CollectionID, SecondsToEvaluate, Date
    $obj.CollectionID = $_.Line.Split('$')[0].Split('[')[2].Split(']')[0]
    $obj.SecondsToEvaluate = $_.Line.Split('$')[0].Split()[9]
    [datetime]$obj.Date = $_.Line.Split('<')[2] -replace ".{4}$"
    $CollectionEvaluated += $obj
    }
$CollectionEvaluated = $CollectionEvaluated | Where-Object -FilterScript {
$_.date -ge $using:EarliestTime
}
$CollectionEvaluated
} | Select-Object -Property CollectionID, SecondsToEvaluate, Date

# Get the time the evaluation ended
[array]$EvaluationEnded = Invoke-Command -Session $s -ScriptBlock {
$EvaluationEnded = @()
$string = Select-String -Path "$env:SMS_LOG_PATH\colleval.log" -Pattern 'Express Evaluator] Exiting'
$string | ForEach-Object -Process {
    $obj = '' | Select-Object -Property String, Date
    $obj.String = $_.Line.Split('$')[0]
    [datetime]$obj.Date = $_.Line.Split('<')[2] -replace ".{4}$"
    $EvaluationEnded += $obj
    }
$EvaluationEnded = $EvaluationEnded | Where-Object -FilterScript {
$_.date -ge $using:EarliestTime
}
$EvaluationEnded
} | Select-Object -Property String, Date

# Close the remote session
Remove-PSSession $s


###############################
# Work the results for output #
###############################

# Collection count
if ($CollectionsFound -ne $null)
    {
        $CollectionCount = $CollectionsFound | Where-Object -FilterScript {
$_.String.Split(' ')[1] -gt 0
}
        $CollectionCount = $CollectionCount.String.Split(' ')[1]
    }
Else 
{
$CollectionCount = 'Not found'
}

# Evaluation Start Time
if ($EvaluationStarted -ne $null)
    {
[datetime]$EvaluationStartTime = $EvaluationStarted[0].Date
}

# Evaluation End Time
if ($EvaluationEnded -ne $null)
    {
[datetime]$EvaluationEndTime = $EvaluationEnded[0].Date
}

# Evaluation time taken
if ($EvaluationStartTime -and $EvaluationEndTime)
    {
        $TimeTaken = '' | Select-Object -Property Minutes, Seconds
        $TimeTaken.Minutes = ($EvaluationEndTime - $EvaluationStartTime).Minutes
        $TimeTaken.Seconds = ($EvaluationEndTime - $EvaluationStartTime).Seconds
    }
Else {$TimeTaken = 'N/A'}

# Collections Evaluated
$CollectionsEvaluatedCount = $CollectionEvaluated.Count
$measure = ($CollectionEvaluated.SecondsToEvaluate | Measure-Object -Sum -Average -Maximum -Minimum)
$CollectionsEvaluatedAverage = [math]::Round($measure.Average,2)
$CollectionsEvaluatedSum = [math]::Round(($measure.Sum / 60),2) # minutes
$CollectionsEvaluatedMaximum = [math]::Round($measure.Maximum,2)
$CollectionsEvaluatedMinimum = [math]::Round($measure.Minimum,2)


# Add the results to custom object
$Result = '' | Select-Object -Property 'Evaluation StartTime', 'Evaluation EndTime', 'Time Taken', `
    'Incremental Collections in graph', `
    'Collections Evaluated', 'Collection Eval TimeTaken (minutes)', 'Collection Eval Average Time (Seconds)', `
    'Longest Collection Eval (seconds)', 'Quickest Collection Eval (seconds)', 'Collections Evaluated List'
if ($EvaluationStarted)
    {
$Result.'Evaluation StartTime' = $EvaluationStartTime
}
Else 
{
$Result.'Evaluation StartTime' = 'Not found'
}
if ($EvaluationEnded)
    {
$Result.'Evaluation EndTime' = $EvaluationEndTime
}
Else 
{
$Result.'Evaluation EndTime' = 'Not found'
}
if ($EvaluationStarted -and $EvaluationEnded)
    {
$Result.'Time Taken' = "$($TimeTaken.Minutes) minutes $($TimeTaken.Seconds) seconds"
}
Else 
{
$Result.'Time Taken' = 'N/A'
}
$Result.'Incremental Collections in graph' = $CollectionCount
$Result.'Collections Evaluated' = $CollectionsEvaluatedCount
$Result.'Collection Eval TimeTaken (minutes)' = $CollectionsEvaluatedSum
$Result.'Collection Eval Average Time (Seconds)' = $CollectionsEvaluatedAverage
$Result.'Longest Collection Eval (seconds)' = $CollectionsEvaluatedMaximum
$Result.'Quickest Collection Eval (seconds)' = $CollectionsEvaluatedMinimum
$Result.'Collections Evaluated List' = $CollectionEvaluated

# Return the results
return $Result