PowerShell¶
Scheduled tasks, RMM script blocks and ad-hoc admin scripts report runs with one function call. Install the module, or paste the inline version below when installing a module into an RMM's runner is more trouble than it is worth.
The module¶
Install-Module -Name LumaTrack -Scope CurrentUser
$env:LUMATRACK_KEY = 'lmt_your_ingest_key'
Reporting goes to https://lumatrack.io. Set $env:LUMATRACK_URL or pass
-Url only when you run LumaTrack on your own domain.
Windows PowerShell 5.1 and PowerShell 7 and later, with no dependencies. Create the key under Settings, API keys; ingest scope is enough for recording runs and cannot read your ledger back.
Report one run¶
Send-LumaTrackRun -Automation 'ad-account-cleanup' -Units 14 -DurationSeconds 42
Send-LumaTrackRun -Automation 'ad-account-cleanup' -Status failure -FailureReason 'auth/credential'
| Parameter | Notes |
|---|---|
-Automation |
The slug. Required |
-Status |
success, failure, skipped, cancelled. Default success |
-DurationSeconds |
Wall clock, rounded to a whole second |
-Units |
Records processed; drives per-unit valuation |
-ExternalId |
Your run id, which makes retries idempotent |
-FailureReason |
Root cause; powers the failure-reason Pareto |
-Metadata |
Hashtable kept with the run |
-Url, -ApiKey |
Default to $env:LUMATRACK_URL and $env:LUMATRACK_KEY; the URL falls back to https://lumatrack.io |
Wrap the work and let it report both ways¶
Invoke-LumaTrackTrackedCommand -Automation 'ad-account-cleanup' -ExternalId $TaskRunId -ScriptBlock {
Disable-StaleADAccounts
}
It times the block, records success when it returns and failure with the
exception message when it throws, then rethrows so your scheduler still sees
the job fail. Output passes straight through.
Reach for this over hand-written try/catch reporting. Hand-written reporting reliably grows the success call and never grows the failure call, and the resulting number is one nobody should present.
Reporting never breaks the job¶
Every failure path writes a warning and returns a result object. A bad key, a
timeout, an unreachable host or an unrecognised slug all let your script carry
on with its real exit status. Check $result.Ok when you care.
$result = Send-LumaTrackRun -Automation 'ad-account-cleanup'
$result.Ok # $true when it landed
$result.StatusCode # 201 recorded, 200 replay, 202 held over the plan cap
$result.Deduplicated # $true when this ExternalId was already recorded
Without installing anything¶
Paste this into a script or module where Install-Module is impractical:
function Send-LumaTrackRun {
param(
[Parameter(Mandatory)] [string] $Automation,
[ValidateSet("success", "failure", "skipped", "cancelled")] [string] $Status = "success",
[int] $DurationSeconds = -1,
[int] $Units = -1,
[string] $ExternalId,
[string] $FailureReason,
[string] $BaseUrl = $env:LUMATRACK_URL,
[string] $ApiKey = $env:LUMATRACK_KEY
)
$Body = @{ automation = $Automation; status = $Status; source = "powershell" }
if ($DurationSeconds -ge 0) { $Body.duration_seconds = $DurationSeconds }
if ($Units -ge 0) { $Body.units = $Units }
if ($ExternalId) { $Body.external_id = $ExternalId }
if ($FailureReason) { $Body.failure_reason = $FailureReason }
try {
Invoke-RestMethod -Method Post -Uri "$BaseUrl/api/v1/runs" `
-Headers @{ Authorization = "Bearer $ApiKey" } `
-ContentType "application/json" -Body ($Body | ConvertTo-Json) `
-TimeoutSec 15
} catch {
# Telemetry must never take down the job it measures.
Write-Warning "LumaTrack report failed: $($_.Exception.Message)"
}
}
And in the job:
$Timer = [System.Diagnostics.Stopwatch]::StartNew()
try {
$Disabled = Disable-StaleADAccounts # the actual work
Send-LumaTrackRun -Automation "ad-account-cleanup" `
-DurationSeconds $Timer.Elapsed.TotalSeconds `
-Units $Disabled.Count `
-ExternalId "$env:COMPUTERNAME-$(Get-Date -Format yyyyMMdd)"
} catch {
Send-LumaTrackRun -Automation "ad-account-cleanup" -Status failure `
-FailureReason $_.Exception.GetType().Name `
-ExternalId "$env:COMPUTERNAME-$(Get-Date -Format yyyyMMdd)"
throw
}
Notes, honestly:
- Report the failure path (the
catchabove). Success-only reporting produces a number nobody should present. ExternalIdmakes retries idempotent. Derive it from whatever your scheduler already has: task run id, ticket id, or a date stamp for daily jobs.Unitsfits batch jobs (accounts disabled, mailboxes archived); value those automations per unit so a 200-account sweep books more than a 3-account one.- Store the API key in your RMM's credential store or as a protected environment variable. Keep it out of the script body.
- Field reference: Recording runs.