Private/ConvertTo-HDTCmTraceLine.ps1
|
function ConvertTo-HDTCmTraceLine { <# .SYNOPSIS Renders one CMTrace line. .DESCRIPTION The second of the two formats every Write-HDTLog call emits. MDT administrators have CMTrace or OneTrace open already and know how to read it, so emitting the same format means their existing workflow, filtering and error highlighting work on day one - deliberately not a new thing to learn. The line, exactly: <![LOG[<message>]LOG]!><time="HH:mm:ss.fff+000" date="MM-dd-yyyy" component="<component>" context="" type="<1|2|3>" thread="<id>" file="<file>"> type maps 1 = Info and Debug, 2 = Warning, 3 = Error, which is what gives CMTrace its colour coding for free. ONE PHYSICAL LINE, ALWAYS. CMTrace's parser is line oriented, so a carriage return or a line feed inside the message would split one entry into two malformed ones. Both are replaced by a space. Every field is rendered in the INVARIANT culture. A German or Swedish machine would otherwise write a dotted date or a comma decimal separator into a format whose reader expects neither, and the engine ships to machines whose culture nobody chose. The function is pure: same arguments, same string, no clock, no filesystem, no state. .PARAMETER Message The message. Carriage returns and line feeds are replaced by spaces. .PARAMETER Component The component attribute - the subsystem the entry came from. .PARAMETER Severity Error, Warning, Info or Debug. .PARAMETER Timestamp The instant to render. Rendered as given, so the caller decides whether it is UTC. .PARAMETER ThreadId The thread attribute. .PARAMETER File The file attribute - the step type, the script name or Engine. .OUTPUTS System.String .EXAMPLE ConvertTo-HDTCmTraceLine -Message 'Applied index 1' -Component 'ImageService' ` -Severity Info -Timestamp $now -ThreadId 4820 -File 'ApplyImage' #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true, Position = 0)] [AllowEmptyString()] [string] $Message, [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $Component, [Parameter(Mandatory = $true)] [ValidateSet('Error', 'Warning', 'Info', 'Debug')] [string] $Severity, [Parameter(Mandatory = $true)] [datetime] $Timestamp, [Parameter(Mandatory = $true)] [int] $ThreadId, [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $File ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $invariant = [System.Globalization.CultureInfo]::InvariantCulture # CRLF first, so one line break becomes one space rather than two. $flat = $Message.Replace("`r`n", ' ').Replace("`r", ' ').Replace("`n", ' ') $type = '1' if ($Severity -eq 'Warning') { $type = '2' } if ($Severity -eq 'Error') { $type = '3' } return ('<![LOG[{0}]LOG]!><time="{1}+000" date="{2}" component="{3}" context="" type="{4}" thread="{5}" file="{6}">' -f $flat, $Timestamp.ToString('HH:mm:ss.fff', $invariant), $Timestamp.ToString('MM-dd-yyyy', $invariant), $Component, $type, $ThreadId.ToString($invariant), $File) } |