pipeline-logging-functions.ps1 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. # Source for this file was taken from https://github.com/microsoft/azure-pipelines-task-lib/blob/11c9439d4af17e6475d9fe058e6b2e03914d17e6/powershell/VstsTaskSdk/LoggingCommandFunctions.ps1 and modified.
  2. # NOTE: You should not be calling these method directly as they are likely to change. Instead you should be calling the Write-Pipeline* functions defined in tools.ps1
  3. $script:loggingCommandPrefix = '##vso['
  4. $script:loggingCommandEscapeMappings = @( # TODO: WHAT ABOUT "="? WHAT ABOUT "%"?
  5. New-Object psobject -Property @{ Token = ';' ; Replacement = '%3B' }
  6. New-Object psobject -Property @{ Token = "`r" ; Replacement = '%0D' }
  7. New-Object psobject -Property @{ Token = "`n" ; Replacement = '%0A' }
  8. New-Object psobject -Property @{ Token = "]" ; Replacement = '%5D' }
  9. )
  10. # TODO: BUG: Escape % ???
  11. # TODO: Add test to verify don't need to escape "=".
  12. # Specify "-Force" to force pipeline formatted output even if "$ci" is false or not set
  13. function Write-PipelineTelemetryError {
  14. [CmdletBinding()]
  15. param(
  16. [Parameter(Mandatory = $true)]
  17. [string]$Category,
  18. [Parameter(Mandatory = $true)]
  19. [string]$Message,
  20. [Parameter(Mandatory = $false)]
  21. [string]$Type = 'error',
  22. [string]$ErrCode,
  23. [string]$SourcePath,
  24. [string]$LineNumber,
  25. [string]$ColumnNumber,
  26. [switch]$AsOutput,
  27. [switch]$Force)
  28. $PSBoundParameters.Remove('Category') | Out-Null
  29. if ($Force -Or ((Test-Path variable:ci) -And $ci)) {
  30. $Message = "(NETCORE_ENGINEERING_TELEMETRY=$Category) $Message"
  31. }
  32. $PSBoundParameters.Remove('Message') | Out-Null
  33. $PSBoundParameters.Add('Message', $Message)
  34. Write-PipelineTaskError @PSBoundParameters
  35. }
  36. # Specify "-Force" to force pipeline formatted output even if "$ci" is false or not set
  37. function Write-PipelineTaskError {
  38. [CmdletBinding()]
  39. param(
  40. [Parameter(Mandatory = $true)]
  41. [string]$Message,
  42. [Parameter(Mandatory = $false)]
  43. [string]$Type = 'error',
  44. [string]$ErrCode,
  45. [string]$SourcePath,
  46. [string]$LineNumber,
  47. [string]$ColumnNumber,
  48. [switch]$AsOutput,
  49. [switch]$Force
  50. )
  51. if (!$Force -And (-Not (Test-Path variable:ci) -Or !$ci)) {
  52. if ($Type -eq 'error') {
  53. Write-Host $Message -ForegroundColor Red
  54. return
  55. }
  56. elseif ($Type -eq 'warning') {
  57. Write-Host $Message -ForegroundColor Yellow
  58. return
  59. }
  60. }
  61. if (($Type -ne 'error') -and ($Type -ne 'warning')) {
  62. Write-Host $Message
  63. return
  64. }
  65. $PSBoundParameters.Remove('Force') | Out-Null
  66. if (-not $PSBoundParameters.ContainsKey('Type')) {
  67. $PSBoundParameters.Add('Type', 'error')
  68. }
  69. Write-LogIssue @PSBoundParameters
  70. }
  71. function Write-PipelineSetVariable {
  72. [CmdletBinding()]
  73. param(
  74. [Parameter(Mandatory = $true)]
  75. [string]$Name,
  76. [string]$Value,
  77. [switch]$Secret,
  78. [switch]$AsOutput,
  79. [bool]$IsMultiJobVariable = $true)
  80. if ((Test-Path variable:ci) -And $ci) {
  81. Write-LoggingCommand -Area 'task' -Event 'setvariable' -Data $Value -Properties @{
  82. 'variable' = $Name
  83. 'isSecret' = $Secret
  84. 'isOutput' = $IsMultiJobVariable
  85. } -AsOutput:$AsOutput
  86. }
  87. }
  88. function Write-PipelinePrependPath {
  89. [CmdletBinding()]
  90. param(
  91. [Parameter(Mandatory = $true)]
  92. [string]$Path,
  93. [switch]$AsOutput)
  94. if ((Test-Path variable:ci) -And $ci) {
  95. Write-LoggingCommand -Area 'task' -Event 'prependpath' -Data $Path -AsOutput:$AsOutput
  96. }
  97. }
  98. function Write-PipelineSetResult {
  99. [CmdletBinding()]
  100. param(
  101. [ValidateSet("Succeeded", "SucceededWithIssues", "Failed", "Cancelled", "Skipped")]
  102. [Parameter(Mandatory = $true)]
  103. [string]$Result,
  104. [string]$Message)
  105. if ((Test-Path variable:ci) -And $ci) {
  106. Write-LoggingCommand -Area 'task' -Event 'complete' -Data $Message -Properties @{
  107. 'result' = $Result
  108. }
  109. }
  110. }
  111. <########################################
  112. # Private functions.
  113. ########################################>
  114. function Format-LoggingCommandData {
  115. [CmdletBinding()]
  116. param([string]$Value, [switch]$Reverse)
  117. if (!$Value) {
  118. return ''
  119. }
  120. if (!$Reverse) {
  121. foreach ($mapping in $script:loggingCommandEscapeMappings) {
  122. $Value = $Value.Replace($mapping.Token, $mapping.Replacement)
  123. }
  124. }
  125. else {
  126. for ($i = $script:loggingCommandEscapeMappings.Length - 1 ; $i -ge 0 ; $i--) {
  127. $mapping = $script:loggingCommandEscapeMappings[$i]
  128. $Value = $Value.Replace($mapping.Replacement, $mapping.Token)
  129. }
  130. }
  131. return $Value
  132. }
  133. function Format-LoggingCommand {
  134. [CmdletBinding()]
  135. param(
  136. [Parameter(Mandatory = $true)]
  137. [string]$Area,
  138. [Parameter(Mandatory = $true)]
  139. [string]$Event,
  140. [string]$Data,
  141. [hashtable]$Properties)
  142. # Append the preamble.
  143. [System.Text.StringBuilder]$sb = New-Object -TypeName System.Text.StringBuilder
  144. $null = $sb.Append($script:loggingCommandPrefix).Append($Area).Append('.').Append($Event)
  145. # Append the properties.
  146. if ($Properties) {
  147. $first = $true
  148. foreach ($key in $Properties.Keys) {
  149. [string]$value = Format-LoggingCommandData $Properties[$key]
  150. if ($value) {
  151. if ($first) {
  152. $null = $sb.Append(' ')
  153. $first = $false
  154. }
  155. else {
  156. $null = $sb.Append(';')
  157. }
  158. $null = $sb.Append("$key=$value")
  159. }
  160. }
  161. }
  162. # Append the tail and output the value.
  163. $Data = Format-LoggingCommandData $Data
  164. $sb.Append(']').Append($Data).ToString()
  165. }
  166. function Write-LoggingCommand {
  167. [CmdletBinding(DefaultParameterSetName = 'Parameters')]
  168. param(
  169. [Parameter(Mandatory = $true, ParameterSetName = 'Parameters')]
  170. [string]$Area,
  171. [Parameter(Mandatory = $true, ParameterSetName = 'Parameters')]
  172. [string]$Event,
  173. [Parameter(ParameterSetName = 'Parameters')]
  174. [string]$Data,
  175. [Parameter(ParameterSetName = 'Parameters')]
  176. [hashtable]$Properties,
  177. [Parameter(Mandatory = $true, ParameterSetName = 'Object')]
  178. $Command,
  179. [switch]$AsOutput)
  180. if ($PSCmdlet.ParameterSetName -eq 'Object') {
  181. Write-LoggingCommand -Area $Command.Area -Event $Command.Event -Data $Command.Data -Properties $Command.Properties -AsOutput:$AsOutput
  182. return
  183. }
  184. $command = Format-LoggingCommand -Area $Area -Event $Event -Data $Data -Properties $Properties
  185. if ($AsOutput) {
  186. $command
  187. }
  188. else {
  189. Write-Host $command
  190. }
  191. }
  192. function Write-LogIssue {
  193. [CmdletBinding()]
  194. param(
  195. [ValidateSet('warning', 'error')]
  196. [Parameter(Mandatory = $true)]
  197. [string]$Type,
  198. [string]$Message,
  199. [string]$ErrCode,
  200. [string]$SourcePath,
  201. [string]$LineNumber,
  202. [string]$ColumnNumber,
  203. [switch]$AsOutput)
  204. $command = Format-LoggingCommand -Area 'task' -Event 'logissue' -Data $Message -Properties @{
  205. 'type' = $Type
  206. 'code' = $ErrCode
  207. 'sourcepath' = $SourcePath
  208. 'linenumber' = $LineNumber
  209. 'columnnumber' = $ColumnNumber
  210. }
  211. if ($AsOutput) {
  212. return $command
  213. }
  214. if ($Type -eq 'error') {
  215. $foregroundColor = $host.PrivateData.ErrorForegroundColor
  216. $backgroundColor = $host.PrivateData.ErrorBackgroundColor
  217. if ($foregroundColor -isnot [System.ConsoleColor] -or $backgroundColor -isnot [System.ConsoleColor]) {
  218. $foregroundColor = [System.ConsoleColor]::Red
  219. $backgroundColor = [System.ConsoleColor]::Black
  220. }
  221. }
  222. else {
  223. $foregroundColor = $host.PrivateData.WarningForegroundColor
  224. $backgroundColor = $host.PrivateData.WarningBackgroundColor
  225. if ($foregroundColor -isnot [System.ConsoleColor] -or $backgroundColor -isnot [System.ConsoleColor]) {
  226. $foregroundColor = [System.ConsoleColor]::Yellow
  227. $backgroundColor = [System.ConsoleColor]::Black
  228. }
  229. }
  230. Write-Host $command -ForegroundColor $foregroundColor -BackgroundColor $backgroundColor
  231. }