internal/Write-AppInsightsException.ps1
<# .SYNOPSIS Write Exception to Application Insights. .EXAMPLE PS C:\>Write-AppInsightsEvent $exception Write Exception to Application Insights. .INPUTS System.Exception #> function Write-AppInsightsException { [CmdletBinding()] [Alias('Write-AIException')] param ( # Exception [Parameter(Mandatory = $true)] [Exception[]] $Exceptions, # Severity Level [Parameter(Mandatory = $false)] [ValidateSet('Verbose', 'Information', 'Warning', 'Error', 'Critical')] [string] $SeverityLevel, # Custom Properties [Parameter(Mandatory = $false)] [hashtable] $Properties, # Instrumentation Key [Parameter(Mandatory = $false)] [string] $InstrumentationKey = $script:ModuleConfig.'ai.instrumentationKey', # Ingestion Endpoint [Parameter(Mandatory = $false)] [string] $IngestionEndpoint = $script:ModuleConfig.'ai.ingestionEndpoint' ) begin { ## Return Immediately when Telemetry is Disabled if ($script:ModuleConfig.'ai.disabled') { return } ## Application Insights Exception Helper Functions # https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/Extensibility/Implementation/ExceptionConverter.cs#L9 Set-Variable MaxParsedStackLength -Value 32768 -Option Constant <# .SYNOPSIS Convert Exceptions Tree to ExceptionDetails .LINK https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/DataContracts/ExceptionTelemetry.cs#L386 #> function ConvertExceptionTree ([Exception] $exception, [hashtable] $parentExceptionDetails, [System.Collections.Generic.List[hashtable]] $exceptions) { if ($null -eq $exception) { $exception = New-Object Exception -ArgumentList 'n/a' } [hashtable] $exceptionDetails = ConvertToExceptionDetails $exception $parentExceptionDetails ## For upper level exception see if Message was provided and do not use exceptiom.message in that case #if ($null -eq $parentExceptionDetails -and ![string]::IsNullOrWhiteSpace($this.Message)) { # $exceptionDetails.message = $this.Message #} $exceptions.Add($exceptionDetails) [AggregateException] $aggregate = $exception -as [AggregateException] if ($null -ne $aggregate) { foreach ($inner in $aggregate.InnerExceptions) { ConvertExceptionTree $inner $exceptionDetails $exceptions } } elseif ($null -ne $exception.InnerException) { ConvertExceptionTree $exception.InnerException $exceptionDetails $exceptions } } <# .SYNOPSIS Converts a Exception to a Microsoft.ApplicationInsights.Extensibility.Implementation.TelemetryTypes.ExceptionDetails. .LINK https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/Extensibility/Implementation/ExceptionConverter.cs#L14 #> function ConvertToExceptionDetails ([Exception]$exception, [hashtable]$parentExceptionDetails) { [hashtable] $exceptionDetails = CreateWithoutStackInfo $exception $parentExceptionDetails $stack = New-Object System.Diagnostics.StackTrace -ArgumentList $Exception, $true $frames = $stack.GetFrames() $sanitizedTuple = SanitizeStackFrame $frames $exceptionDetails['parsedStack'] = $sanitizedTuple[0] $exceptionDetails['hasFullStack'] = $sanitizedTuple[1] return $exceptionDetails } <# .SYNOPSIS Creates a new instance of ExceptionDetails from a Exception and a parent ExceptionDetails. .LINK https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/Extensibility/Implementation/External/ExceptionDetailsImplementation.cs#L13 #> function CreateWithoutStackInfo ([Exception]$exception, [hashtable]$parentExceptionDetails) { if ($null -eq $exception) { throw (New-Object ArgumentNullException -ArgumentList $exception.GetType().Name) } [hashtable] $exceptionDetails = [ordered]@{ id = $exception.GetHashCode() typeName = $exception.GetType().FullName message = $exception.Message } if ($null -ne $parentExceptionDetails) { $exceptionDetails.outerId = $parentExceptionDetails.id } return $exceptionDetails } <# .SYNOPSIS Sanitizing stack to 32k while selecting the initial and end stack trace. .LINK https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/Extensibility/Implementation/ExceptionConverter.cs#L93 #> function SanitizeStackFrame ([System.Diagnostics.StackFrame[]]$inputList) { [System.Collections.Generic.List[hashtable]] $orderedStackTrace = New-Object System.Collections.Generic.List[hashtable] [bool] $hasFullStack = $true if ($null -ne $inputList -and $inputList.Count -gt 0) { [int] $currentParsedStackLength = 0 for ($level = 0; $level -lt $inputList.Count; $level++) { ## Skip middle part of the stack [int] $current = if ($level % 2 -eq 0) { ($inputList.Count - 1 - ($level / 2)) } else { ($level / 2) } [hashtable] $convertedStackFrame = GetStackFrame $inputList[$current] $current $currentParsedStackLength += GetStackFrameLength $convertedStackFrame if ($currentParsedStackLength -gt $MaxParsedStackLength) { $hasFullStack = $false break } $orderedStackTrace.Insert($orderedStackTrace.Count / 2, $convertedStackFrame) } } return $orderedStackTrace, $hasFullStack } <# .SYNOPSIS Converts a System.Diagnostics.StackFrame to a Microsoft.ApplicationInsights.Extensibility.Implementation.TelemetryTypes.StackFrame. .LINK https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/Extensibility/Implementation/ExceptionConverter.cs#L36 #> function GetStackFrame ([System.Diagnostics.StackFrame]$stackFrame, [int]$frameId) { [hashtable] $convertedStackFrame = [ordered]@{ level = $frameId } $methodInfo = $stackFrame.GetMethod() [string] $fullName = $null [string] $assemblyName = $null if ($null -eq $methodInfo) { $fullName = "unknown" $assemblyName = "unknown" } else { $assemblyName = $methodInfo.Module.Assembly.FullName if ($null -ne $methodInfo.DeclaringType) { $fullName = $methodInfo.DeclaringType.FullName + "." + $methodInfo.Name } else { $fullName = $methodInfo.Name } } $convertedStackFrame['method'] = $fullName $convertedStackFrame['assembly'] = $assemblyName $convertedStackFrame['fileName'] = $stackFrame.GetFileName() ## 0 means it is unavailable [int] $line = $stackFrame.GetFileLineNumber() if ($line -ne 0) { $convertedStackFrame['line'] = $line } return $convertedStackFrame } <# .SYNOPSIS Gets the stack frame length for only the strings in the stack frame. .LINK https://github.com/microsoft/ApplicationInsights-dotnet/blob/81288f26921df1e8e713d31e7e9c2187ac9e6590/BASE/src/Microsoft.ApplicationInsights/Extensibility/Implementation/ExceptionConverter.cs#L82 #> function GetStackFrameLength ([hashtable]$stackFrame) { [int] $stackFrameLength = if ($null -eq $stackFrame.method) { 0 } else { $stackFrame.method.Length } $stackFrameLength += if ($null -eq $stackFrame.assembly) { 0 } else { $stackFrame.assembly.Length } $stackFrameLength += if ($null -eq $stackFrame.fileName) { 0 } else { $stackFrame.fileName.Length } return $stackFrameLength } } process { ## Return Immediately when Telemetry is Disabled if ($script:ModuleConfig.'ai.disabled') { return } foreach ($Exception in $Exceptions) { ## Get New Telemetry Entry $AppInsightsTelemetry = New-AppInsightsTelemetry 'AppExceptions' -InstrumentationKey $InstrumentationKey ## Get Exception Details [System.Collections.Generic.List[hashtable]] $exceptions = New-Object System.Collections.Generic.List[hashtable] ConvertExceptionTree $Exception $null $exceptions ## Update Telemetry Data $AppInsightsTelemetry.data.baseData['exceptions'] = $exceptions if ($SeverityLevel) { $AppInsightsTelemetry.data.baseData['severityLevel'] = $SeverityLevel } if ($Properties) { $AppInsightsTelemetry.data.baseData['properties'] += $Properties } ## Write Data to Application Insights Write-Debug (([PSCustomObject]$AppInsightsTelemetry) | ConvertTo-Json -Depth 6) try { $result = Invoke-RestMethod -UseBasicParsing -Method Post -Uri $IngestionEndpoint -ContentType 'application/json' -Body ($AppInsightsTelemetry | ConvertTo-Json -Depth 6 -Compress) -Verbose:$false -ErrorAction SilentlyContinue } catch {} } } } # SIG # Begin signature block # MIInlgYJKoZIhvcNAQcCoIInhzCCJ4MCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCC93Un1eZ6zWh3W # FMjnWEmfzsapiw30oApdccCbksE5o6CCDXYwggX0MIID3KADAgECAhMzAAACURR2 # zMWFg24LAAAAAAJRMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDBIpXR3b1IYAMunV9ZYBVYsaA7S64mqacKy/OJUf0Lr/LW/tWlJDzJH9nFAhs0 # zzSdQQcLhShOSTUxtlwZD9dnfIcx4pZgu0VHkqQw2dVc8Ob21GBo5sVrXgEAQxZo # rlEuAl20KpSIFLUBwoZFGFSQNSMcqPudXOw+Mhvn6rXYv/pjXIjgBntn6p1f+0+C # 2NXuFrIwjJIJd0erGefwMg//VqUTcRaj6SiCXSY6kjO1J9P8oaRQBHIOFEfLlXQ3 # a1ATlM7evCUvg3iBprpL+j1JMAUVv+87NRApprPyV75U/FKLlO2ioDbb69e3S725 # XQLW+/nJM4ihVQ0BHadh74/lAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUMLgM7NX5EnpPfK5uU6FPvn2g/Ekw # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzQ2NzU5NjAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAIVJlff+Fp0ylEJhmvap # NVv1bYLSWf58OqRRIDnXbHQ+FobsOwL83/ncPC3xl8ySR5uK/af4ZDy7DcDw0yEd # mKbRLzHIfcztZVSrlsg0GKwZuaB2MEI1VizNCoZlN+HlFZa4DNm3J0LhTWrZjVR0 # M6V57cFW0GsV4NlqmtelT9JFEae7PomwgAV9xOScz8HzvbZeERcoSRp9eRsQwOw7 # 8XeCLeglqjUnz9gFM7RliCYP58Fgphtkht9LNEcErLOVW17m6/Dj75zg/IS+//6G # FEK2oXnw5EIIWZraFHqSaee+NMgOw/R6bwB8qLv5ClOJEpGKA3XPJvS9YgOpF920 # Vu4Afqa5Rv5UJKrsxA7HOiuH4TwpkP3XQ801YLMp4LavXnvqNkX5lhFcITvb01GQ # lcC5h+XfCv0L4hUum/QrFLavQXJ/vtirCnte5Bediqmjx3lswaTRbr/j+KX833A1 # l9NIJmdGFcVLXp1en3IWG/fjLIuP7BqPPaN7A1tzhWxL+xx9yw5vQiT1Yn14YGmw # OzBYYLX0H9dKRLWMxMXGvo0PWEuXzYyrdDQExPf66Fq/EiRpZv2EYl2gbl9fxc3s # qoIkyNlL1BCrvmzunkwt4cwvqWremUtqTJ2B53MbBHlf4RfvKz9NVuh5KHdr82AS # MMjU4C8KNTqzgisqQdCy8unTMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGXYwghlyAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAJRFHbMxYWDbgsAAAAAAlEwDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIIkJL3ReVeysW58JJVlGYxO+ # +Gv5h/e8qOxKpoX+X3FrMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEANQCUBjtWyp28kPvvRWt1IxIzqqzyzDK8+AUs0R9BtCqdgeKfSyVHSURw # Y+afZ9o3JPu0RcJnJ8gBXODSzR7/0sKNg5WEx1CG8bke7J6n/fJYiu46BBGhuQNU # lXw8cepqWDADTAtztpBAKsSNM14qmok4uleiQxzjWlsjdcgjxIvlXQxvBlnM7R8d # UBL9/nUV4P5aS6qiMB0KMyZflgVJoccdY0DMaELE6fiiZdsTmXIBaYi5FqtD5v5z # cEutphhFAe8Bjo5Ncc9d7gfNE5vt0qM27rpTr1uCgE2I9bWgnW+I/v51ZNj9el4t # yd307VpdO4ymnGVU+XevdzTY8iWcQ6GCFwAwghb8BgorBgEEAYI3AwMBMYIW7DCC # FugGCSqGSIb3DQEHAqCCFtkwghbVAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFRBgsq # hkiG9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCA56J8wwapUYYkqwtNul3T6U+wGKyMabQghOmHLfIgbRAIGYoIxuRg7 # GBMyMDIyMDYxNTE3MzczNS42MjlaMASAAgH0oIHQpIHNMIHKMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l # cmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpERDhDLUUz # MzctMkZBRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCC # EVcwggcMMIIE9KADAgECAhMzAAABnA+mTWHSnksoAAEAAAGcMA0GCSqGSIb3DQEB # CwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTIxMTIwMjE5MDUx # OVoXDTIzMDIyODE5MDUxOVowgcoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMx # JjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkREOEMtRTMzNy0yRkFFMSUwIwYDVQQD # ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEA21IqDBldSRY/rOtdrNNpirttyj1DbO9Tow3iRrcZExfa # 0lk4rgPF4GJAAIv+fthX+wpOyXCkPR/1w9TisINf2x9xNajtc/F0ctD5aRoZsopY # BOyrDr1vDyGQn9uNynZXYDq8ay/ByokKHTsErck+ZS1mKTLLk9nx/JPKIoY3uE5a # VohT2gii5xQ2gAdAnMuryHbR42AdSHt4jmT4rKri/rzXQse4DoQfIok5k3bFPDkl # KQvLQU3kyGD85oWsUGXeJqDZOqngicou34luH8l3R62d6LZoMcWuaV8+aVFK/nBI # 1fnMCGATJGmOZBzPXOnRBpIB59GQyb3bf+eBTnUhutVsB4ePnr1IcL12geCwjGSH # QreWnDnzb7Q41dwh8hTqeQFP6oAMBn7R1PW67+BFMHLrXhACh+OjbnxNtJf1o5TV # Ie4AL7dsyjIzuM10cQlE4f6awUMFyYlGXhUqxF4jn5Lr0pQZ4sgGGGaeZDp2sXwi # nRmI76+ECwPd70CeqdjsdyB7znQj2gq/C7ClXBacqfDBIYSUzPtS8KhyahQxeTtW # fZo22L5t0fbz4ZBvkQyyqE6a+5k4JGk5Y3fcb5veDm6fAQ/R5OJj4udZrYC4rjfP # +mmVRElWV7b0rjZA+Q5yCUHqyMuY2kSlv1tqwnvZ4DQyWnUu0fehhkZeyCBN+5cC # AwEAAaOCATYwggEyMB0GA1UdDgQWBBS7aQlnU12OXbXXZLKcvqMYwgP6sjAfBgNV # HSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5o # dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBU # aW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwG # CCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRz # L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNV # HRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IC # AQCnACqmIxhHM01jLPc9Ju2KNt7IKlRdy8iuoDjM+0whwCTfhb272ZEOd1ZL62VH # dbBOmvU6BpXXCZzpgXOoroQZab3TdQSwUTvEEkw9eN91U4+FwkHe9+8DQ9fnqiht # wXY682w5LBMHxuL+ez4Kzf0+7Oz5BI1Bl3yIBUEJK/E0Ivvx2WfZEZTXHIHgAqpX # 2+Lhj8Z+bHYUD6MXTL5gt6hvQzjSeVLEvSrTvm3svqIVEw2vS7xE6HOEM8uX7h49 # h9SbJgmihu/J16X1qcASwcWWEqX5pdvaJzfI3Buyg/Jxkkv++jw5W9hjELL7/kWt # CYC+hbRkRoGJhwqTOs1a3+Ff2vkqB3AvrXHRmJNmilOSjpb/nxRN59NuFfs+eLQw # Ckfc+/K3o3QgVqn78uXAVEPXOft7pxw9PARKe6j9q4KaA/OerzQ4BMDu+5+xFk++ # p5fyMq2ytpI2xy81DKYRaVyp1dX2FiSNvhP9Cx71xRhqheDrzAUcW6yVZ9N09g8u # XW+rOU8yc0mkLwq12KgOByr7LUFpKpKbwR01/DNPfv78kW1Vzcaz3Xl8OqA9kOA5 # LMpAhX5/Ddo9i3YsRPcBuYopb+vXc7LxyDf4PQPfrYZAEAlW/Q1Ejk2jCBoLDqg2 # BY4U+s3vZZIRxxr/xBCJMY/ZekuIalEMlnqxZGlFg13J2TCCB3EwggVZoAMCAQIC # EzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS # b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoX # DTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC # 0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VG # Iwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP # 2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/P # XfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361 # VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwB # Sru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9 # X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269e # wvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDw # wvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr # 9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+e # FnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAj # BgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+n # FV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEw # PwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9j # cy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3 # FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAf # BgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBH # hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNS # b29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF # BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl # ckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4Swf # ZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTC # j/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu # 2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/ # GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3D # YXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbO # xnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqO # Cb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I # 6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0 # zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaM # mdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNT # TY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggLOMIICNwIBATCB+KGB0KSBzTCByjEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWlj # cm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBF # U046REQ4Qy1FMzM3LTJGQUUxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w # IFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVAM3Zaerd8LP25xK25vXNDPvXb1NAoIGD # MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEF # BQACBQDmVDvKMCIYDzIwMjIwNjE1MTkwNjUwWhgPMjAyMjA2MTYxOTA2NTBaMHcw # PQYKKwYBBAGEWQoEATEvMC0wCgIFAOZUO8oCAQAwCgIBAAICIeMCAf8wBwIBAAIC # EVMwCgIFAOZVjUoCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAK # MAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQUFAAOBgQBV5SurpyZy # B/K+jcOkzj+KiPCSolyMEf4xnYL8ObDbOS0jfa+K5bwffmXXrHxC+VQ+JFNSh6Qk # OhOrbd/zhEaxHJzZkK+WA5QYeC3BujMw4ND3UsaAEjwprHQW899J7yKX6ebXWfBv # 2ViE6P2q5WM5f6YwLpf3Iox+CQX88rmaYzGCBA0wggQJAgEBMIGTMHwxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABnA+mTWHSnksoAAEAAAGcMA0GCWCG # SAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZI # hvcNAQkEMSIEINosMIi7kZDreLarWbc9i94ikBhNeBP6+HLb1yLNzt4QMIH6Bgsq # hkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgNw9FhSCNLMo6EXf13hCBtFlCCs87suj+ # oTka29J6prwwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAIT # MwAAAZwPpk1h0p5LKAABAAABnDAiBCCXc6n0V9LyYy2+aY0U0Gk2Kxa7iRHNomw2 # LWpRZ+r22TANBgkqhkiG9w0BAQsFAASCAgA6F4m8Q7jVdvr7vZL5PeEXho/x0iNt # YFLhm/Uf64huZjIo/9m3qak4gAAOUTREh7uRSzDH8CWlmP8uTVuHBaFO4GdCc8Zz # oT2HXG17vKUNeu5AvlNN5wCqK7A85kuEhve5OrrFtdhPYpnSNUAlVfX9ZPjcv0OH # A1SDZzZpkpU1Mmg/lvvIzy4zjqdPGTNjo18eu5JtRd2kMUf2IQPNiQG2Vd8u1tja # KCSIl42w0qvLGDjVbwHscW5Svcfbj9d2rMjCjExJS9YY7SXtBG2Un8QrOSocS2g1 # ELcSpFyor0u+U+gfN4s0LlCrKdj6dwdAqoWgg1TeWzQVbiiCRW4mydzN3KIE78r0 # Yd3+bH5oL7TFZkQ8qEuYwMSvNx+/sQGXuFYyCnR8FQvccxOQW0SPpTS8xAFh8qb8 # 7+nFFJ3OmniGILU63uhwTgFgIJ1KGicsQwsLspQjXG/GtOSD6zMppZB6ces+v6FO # LKNcMbsCcG1hm+THMtPPsnjH5NUbD1Izou2kN47ZZngu+YLixh1aXvFbagRpXo9c # OpNlrcpkov6cbu+3hcPQpCidT7ZzSxeHSTktIOGA8tFP4yzoh+Hhy6tGKhtv2HEj # gX3V1C9FyFTiXaG/wBJuxYg2rhTGd1JMfVhiBTb/qkF6uBOgBpuhRqJ9LUBCiMCH # qonvMy0iefM84Q== # SIG # End signature block |