|
| 1 | +<# |
| 2 | +.SYNOPSIS |
| 3 | +Sends webhook events to LogicMonitor. |
| 4 | +
|
| 5 | +.DESCRIPTION |
| 6 | +The Send-LMWebhookMessage function submits webhook messages to LogicMonitor for ingestion via the Webhook LogSource endpoint. Provide an array of events to transmit; each entry is converted into a JSON payload. Optional common properties can be merged into every event to support downstream parsing in LogicMonitor. |
| 7 | +
|
| 8 | +.PARAMETER SourceName |
| 9 | +Specifies the LogicMonitor LogSource identifier used in the ingest URL. This typically matches the sourceName configured in LogicMonitor. |
| 10 | +
|
| 11 | +.PARAMETER Events |
| 12 | +Specifies the collection of events to send. Each item may be a hashtable, PSCustomObject, or simple value. Simple values are wrapped in a payload under the `message` property. |
| 13 | +
|
| 14 | +.PARAMETER Properties |
| 15 | +Specifies additional key/value pairs that are merged into every event payload before sending. |
| 16 | +
|
| 17 | +.EXAMPLE |
| 18 | +Send-LMWebhookMessage -SourceName "Meraki_CustomerA" -Events $Messages -Properties @{ accountId = '12345' } |
| 19 | +Sends each event in `$Messages` to the Meraki webhook LogSource, appending the `accountId` property to every payload. |
| 20 | +
|
| 21 | +.OUTPUTS |
| 22 | +Outputs a confirmation message for each accepted webhook event, or an error message if the request fails. When -PassThru is specified, returns PSCustomObject entries containing status, payload, and optional error details for each attempted message. |
| 23 | +#> |
| 24 | +function Send-LMWebhookMessage { |
| 25 | + |
| 26 | + [CmdletBinding()] |
| 27 | + param ( |
| 28 | + |
| 29 | + [Parameter(Mandatory)] |
| 30 | + [String]$SourceName, |
| 31 | + |
| 32 | + [Parameter(Mandatory)] |
| 33 | + [Object[]]$Messages, |
| 34 | + |
| 35 | + [Hashtable]$Properties, |
| 36 | + |
| 37 | + [Switch]$PassThru |
| 38 | + ) |
| 39 | + |
| 40 | + begin { |
| 41 | + if (-not $Properties) { |
| 42 | + $Properties = @{} |
| 43 | + } |
| 44 | + |
| 45 | + if ($PassThru) { |
| 46 | + $SentPayloads = New-Object System.Collections.Generic.List[pscustomobject] |
| 47 | + } |
| 48 | + } |
| 49 | + process { |
| 50 | + if (-not $Script:LMAuth.Valid) { |
| 51 | + Write-Error "Please ensure you are logged in before running any commands, use Connect-LMAccount to login and try again." |
| 52 | + return |
| 53 | + } |
| 54 | + |
| 55 | + if ($Script:LMAuth.Type -ne "Bearer") { |
| 56 | + Write-Error "This cmdlet does not support LMv1 or SessionSync auth. Use Connect-LMAccount to login with the correct auth type and try again" |
| 57 | + return |
| 58 | + } |
| 59 | + |
| 60 | + $encodedSource = [System.Uri]::EscapeDataString($SourceName) |
| 61 | + $resourcePath = "/api/v1/webhook/ingest/$encodedSource" |
| 62 | + $uri = "https://$($Script:LMAuth.Portal).logicmonitor.com/rest" + $resourcePath |
| 63 | + |
| 64 | + foreach ($message in $Messages) { |
| 65 | + $payload = [ordered]@{} |
| 66 | + |
| 67 | + if ($message -is [System.Collections.IDictionary]) { |
| 68 | + foreach ($key in $message.Keys) { |
| 69 | + $payload[$key] = $message[$key] |
| 70 | + } |
| 71 | + } |
| 72 | + elseif ($message -is [PSCustomObject]) { |
| 73 | + foreach ($property in $message.PSObject.Properties) { |
| 74 | + $payload[$property.Name] = $property.Value |
| 75 | + } |
| 76 | + } |
| 77 | + else { |
| 78 | + $payload["message"] = [String]$message |
| 79 | + } |
| 80 | + |
| 81 | + foreach ($propertyKey in $Properties.Keys) { |
| 82 | + $payload[$propertyKey] = $Properties[$propertyKey] |
| 83 | + } |
| 84 | + |
| 85 | + foreach ($key in @($payload.Keys)) { |
| 86 | + if ($null -eq $payload[$key]) { |
| 87 | + $payload.Remove($key) |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + $body = ConvertTo-Json -InputObject $payload -Depth 10 |
| 92 | + |
| 93 | + $headers = New-LMHeader -Auth $Script:LMAuth -Method "POST" -ResourcePath $resourcePath -Data $body |
| 94 | + |
| 95 | + Resolve-LMDebugInfo -Url $uri -Headers $headers[0] -Command $MyInvocation -Payload $body |
| 96 | + |
| 97 | + $response = Invoke-LMRestMethod -CallerPSCmdlet $PSCmdlet -Uri $uri -Method "POST" -Headers $headers[0] -WebSession $headers[1] -Body $body |
| 98 | + $isAccepted = ($response -eq "Accepted") |
| 99 | + |
| 100 | + if ($isAccepted) { |
| 101 | + if ($PassThru) { |
| 102 | + $SentPayloads.Add([pscustomobject]$payload) |
| 103 | + } |
| 104 | + else { |
| 105 | + Write-Output "Webhook message accepted successfully." |
| 106 | + } |
| 107 | + continue |
| 108 | + } |
| 109 | + |
| 110 | + $statusMessage = "Error" |
| 111 | + if ($PassThru) { |
| 112 | + $SentPayloads.Add([pscustomobject]@{ |
| 113 | + status = $statusMessage |
| 114 | + payload = [pscustomobject]$payload |
| 115 | + error = [pscustomobject]@{ |
| 116 | + code = $response.errors.code |
| 117 | + error = $response.errors.error |
| 118 | + } |
| 119 | + }) |
| 120 | + } |
| 121 | + |
| 122 | + Write-Error -Message "$($response.errors.code): $($response.errors.error)" |
| 123 | + } |
| 124 | + } |
| 125 | + end { |
| 126 | + if ($PassThru -and $SentPayloads -and $SentPayloads.Count -gt 0) { |
| 127 | + foreach ($result in $SentPayloads) { |
| 128 | + if (-not ($result.PSObject.Properties.Name -contains 'status')) { |
| 129 | + $SentPayloads[$SentPayloads.IndexOf($result)] = [pscustomobject]@{ |
| 130 | + status = "Accepted" |
| 131 | + payload = $result |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | + $SentPayloads.ToArray() |
| 136 | + } |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | + |
0 commit comments