Public/Invoke-LMDataModelRunner.ps1
<# .SYNOPSIS Invokes Submit-LMDataModel for an array of models .DESCRIPTION Based on the specified ModelPath, all discovered models are submitted to Submit-LMDataModel. ModelPath should contain a subfolder called Models which contains the generated model JSON files and additionally a Scipts folder with an pre processing scripts you want executed priot to model submission. .PARAMETER BearerToken Logic Monitor bearer token for connecting to the targeted portal .PARAMETER AccountName LogicMontior Portal to submit models to .PARAMETER ModelPath File path where models are located .PARAMETER LogSourceName Submitted Logs will have a log source name appended as metadata, defaults to PMv1 if not set .PARAMETER LogFileName File name to use for transcript files, defaults to Runner.txt if not set .PARAMETER LogResult Switch to enable logging of submission results to LogicMonitor. If not set no logs will be generated. .PARAMETER LogResourceId Hashtable containing the required mapping info for lm logs. .PARAMETER ConcurrencyLimit Number of models to process in parallel, defaults to 5. Running too many concurrently can result in 429 errors. .PARAMETER RunPreFlightScripts Switch to enable the procesing of scripts included in the module directory under the script folder. .EXAMPLE Invoke-LMDataModelRunner -BearerToken XXXXXXX -AccountName portal_name -ModelPath C:\LogicMonitor\<ModelDir> -LogSourceName "DL-PMv1" -LogFileName Runner.txt -LogResult -LogResourceId @{"system.deviceId"="123"} .INPUTS None. You cannot pipe objects to this command. .LINK Module repo: https://github.com/stevevillardi/Logic.Monitor.SE .LINK PSGallery: https://www.powershellgallery.com/packages/Logic.Monitor.SE #> Function Invoke-LMDataModelRunner { [CmdletBinding()] Param ( [Parameter(Mandatory)] [String]$BearerToken, [Parameter(Mandatory)] [String]$AccountName, [Parameter(Mandatory)] [String]$ModelPath, [Parameter(ParameterSetName = 'LogResult')] [String]$LogSourceName = "PMv1", [String]$DatasourceSuffix = "_PMv1", [Parameter(ParameterSetName = 'LogResult')] [String]$LogFileName = "RunnerLog.txt", [Parameter(ParameterSetName = 'LogResult')] [Switch]$LogResult, [Parameter(ParameterSetName = 'LogResult')] [Hashtable]$LogResourceId, [Parameter(ParameterSetName = 'LogResult')] [Hashtable]$LogAdditionalMetadata, [Int]$ConcurrencyLimit = 5, [Switch]$MultiThreadDatasourceSubmission, [Switch]$RunPreFlightScripts ) #Load models $Models = (Get-ChildItem "$ModelPath\Models" -Filter *.json).FullName | ForEach-Object {Get-Content $_ -Raw | ConvertFrom-Json -Depth 10} #Load any model specific scripts/funcitons If($RunPreFlightScripts){ $AdditionalScripts = @( Get-ChildItem -Path $ModelPath\Scripts\*.ps1 -ErrorAction SilentlyContinue -Recurse) #Dot source the files Foreach ($import in @($AdditionalScripts)) { Try { #Run preflight scripts pass our models and connection details for usage . $import.fullname -Models $Models -BearerToken $BearerToken -AccountName $AccountName } Catch { Write-Error -Message "Failed to import function $($import.fullname): $_" } } } $TotalResults = Measure-Command { #Run models $Models | ForEach-Object -Parallel { #Manually load modules since running as a job they are not automatically loaded Import-Module Microsoft.PowerShell.SecretStore -ErrorAction SilentlyContinue Import-Module Microsoft.PowerShell.SecretManagement -ErrorAction SilentlyContinue Import-Module Logic.Monitor -ErrorAction SilentlyContinue Import-Module Logic.Monitor.SE -ErrorAction SilentlyContinue #Dev module import for testing, not needed for production Import-Module /Users/stevenvillardi/Documents/GitHub/Logic.Monitor/Dev.Logic.Monitor.psd1 -Force -ErrorAction SilentlyContinue Import-Module /Users/stevenvillardi/Documents/GitHub/Logic.Monitor.SE/Dev.Logic.Monitor.SE.psd1 -Force -ErrorAction SilentlyContinue #Start last run log $RunnerTranscriptPath = "$using:ModelPath\$($_.DisplayName)-$using:LogFileName" If($using:LogResult){Start-Transcript -Path $RunnerTranscriptPath -UseMinimalHeader -ErrorAction SilentlyContinue} If($using:MultiThreadDatasourceSubmission){ #Call Submit-LMDataModelConcurrent to run DS processing in parallel $ModelResult = Measure-Command {Submit-LMDataModelConcurrent -ModelObject $_ -BearerToken $using:BearerToken -AccountName $using:AccountName -DatasourceSuffix $using:DatasourceSuffix -ConcurrencyLimit $using:ConcurrencyLimit} } Else{ #Connect to portal Connect-LMAccount -BearerToken $using:BearerToken -AccountName $using:AccountName -SkipVersionCheck -DisableConsoleLogging -SkipCredValidation $ModelResult = Measure-Command {Submit-LMDataModel -ModelObject $_ -DatasourceSuffix $using:DatasourceSuffix} } $ModelTime = [Math]::Round(($ModelResult).TotalMinutes,2) #End last run log If($using:LogResult){Stop-Transcript -ErrorAction SilentlyContinue} $LastRunLog = Get-Content $RunnerTranscriptPath -Raw -ErrorAction SilentlyContinue #Send Log Message with Result If($using:LogResult){ If($using:MultiThreadDatasourceSubmission){ Connect-LMAccount -BearerToken $using:BearerToken -AccountName $using:AccountName -SkipVersionCheck -DisableConsoleLogging -SkipCredValidation } $DSList = $_.Datasources.DatasourceName -join "," Send-LMLogMessage -Message $LastRunLog -resourceMapping $using:LogResourceId -Metadata $($using:LogAdditionalMetadata + @{"modelSimulationType"=$_.SimulationType;"modelDatasourceList"=$DSList;"modelRuntimeInMin"=$ModelTime;"modelLogSource"=$using:LogSourceName;"modelDeviceDisplayName"=$_.DisplayName}) } #Disconnect from portal Disconnect-LMAccount } -ThrottleLimit $ConcurrencyLimit } return $TotalResults.TotalMinutes } |