Skip to content

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 catch above). Success-only reporting produces a number nobody should present.
  • ExternalId makes retries idempotent. Derive it from whatever your scheduler already has: task run id, ticket id, or a date stamp for daily jobs.
  • Units fits 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.