Skip to content
Zoos GlobalZoos GlobalZoos EngineeringHub

exl_systrack

README documentation for exl_systrack

stableRepositoryPythonprivate
13 min readUpdated Jul 24, 2026@integrations-teamClient Integrations
Edit source

Source: ZoosGlobal/exl_systrack Visibility: Private This page is automatically synchronized from the repository README. Do not edit this generated file directly.


EXL SysTrack → Datadog Windows Integration

Section titled “EXL SysTrack → Datadog Windows Integration”
Zoos Global

Pipeline data source: SysTrack by Lakeside Software


Python scripts → 73K+ endpoints → Datadog Logs → Dashboards & Alerts


EXL relies on SysTrack for endpoint health, performance, and stability telemetry across its desktop fleet, but that data was trapped inside the SysTrack console with no path into the team’s central observability platform:

  • Massive scale, zero centralized visibility — Across 77,000+ endpoints, health scores, reboot status, application crashes, and application faults all lived only in SysTrack’s own UI, with no way to view or correlate them alongside the rest of EXL’s infrastructure and application monitoring in Datadog.
  • Critical signals buried in a console, not surfaced as alerts — Application crashes are a small but high-severity signal (only a handful of hosts), yet without active alerting they could go unnoticed for hours inside a console nobody was watching in real time.
  • No SLA or failure tracking for the data pipeline itself — Even if a collection process existed, there was no record of whether it ran successfully, how long it took, or whether it silently failed — making it impossible to trust the data without manual spot-checks.
  • No historical trending at scale — With tens of thousands of hosts, understanding fleet-wide health trends, reboot patterns, or fault frequency over time required exporting and manually analyzing data — not something that scales operationally.
  • High data volume with no safe ingestion path — At ~1.1GB/day across four data types, naively pushing this into a monitoring platform risked uncontrolled disk growth, log bloat, or ingestion failures without careful log rotation and file-based handling.
  • Windows-only environment constraint — Like other EXL on-prem services, the collection had to run natively on Windows Server using SYSTEM-level scheduled execution, ruling out Linux-native or service-based collection patterns.

We built a stateless, Windows-native Python pipeline that pulls SysTrack data for all four key signal types and feeds it into Datadog through simple file-based log tailing — scaled to handle 77,000+ endpoints reliably every day.

SysTrack Console / API
Python Collectors (4 scripts, stateless)
Structured JSON Log Files (rotating, 500MB × 5 backups per script)
Datadog Agent (file-tail log collection, wildcard rotation tracking)
Datadog Logs → Dashboards → Alerts
C:\Scripts\exl_systrack\
├── config\
│ └── datadog\
│ └── systrack.d\
│ ├── conf.yaml # Datadog log collection config (must be named conf.yaml, not conf.yml)
│ └── sample.env # Reference env vars (documentation only -- see tools/systrack_dashboard.py's /help page)
├── schedulers\ # Task Scheduler entrypoints
│ ├── run_appcrash.ps1 # 15min CRITICAL
│ ├── run_appfault.ps1 # 30min (+5min offset)
│ ├── run_health.ps1 # 4 hours
│ └── run_reboot.ps1 # 30min
├── scripts\ # Python logic (stateless)
│ ├── sv_appcrash.py # 3 critical crashes
│ ├── sv_appfault.py # ~1.2K app faults
│ ├── sv_health_desktop.py # 67K hosts baseline
│ └── sv_reboot_health.py # 8.7K reboot issues
├── tools\ # Diagnostics & troubleshooting
│ ├── scripts\
│ │ ├── systrack_check.ps1 # Python + Datadog sanity
│ │ ├── systrack_dd_log_probe.ps1 # Log ingestion probe
│ │ ├── systrack_env_dump.ps1 # Environment snapshot
│ │ ├── systrack_paths_check.ps1 # PATH validation
│ │ └── systrack_permissions.ps1 # Permission checks
│ │
│ ├── output\ # Tool outputs (generated)
│ └── run_all_tools.ps1 # Master runner → ZIP flare
├── logs\ # Runtime output (auto-generated)
│ ├── apps\ # Main application logs (see section 8️⃣ --
│ │ │ # sv_process_queueLength.py is the one
│ │ │ # filename that intentionally doesn't
│ │ │ # match its script name -- frozen Datadog config)
│ │ ├── sv_appcrash.json.log
│ │ ├── sv_appfault.json.log
│ │ ├── sv_health_desktop.json.log
│ │ └── sv_reboot_health.json.log
│ ├── *_error.json.log # Error logs -- written directly under logs\
│ │ # (not a logs\errors\ subfolder), but as of
│ │ # 2026-07-15 not currently tailed by Datadog
│ │ # (no error-log glob in the live config; see 8️⃣)
│ └── history\ # Scheduler execution history
│ └── *_status.history.jsonl # (also not currently tailed by Datadog; see 8️⃣)
├── .gitignore # Excludes logs/, *.env, output/
└── README.md # This file

  • Windows Server 2019+ / Windows 10+
  • Python 3.14+ (SYSTEM-WIDE)
  • Datadog Agent (Logs enabled)
  • PowerShell 5.1+
  • Admin/SYSTEM privileges for Task Scheduler

Install Python for all users and add to SYSTEM PATH.

https://www.python.org/downloads/windows/
✅ Check "Add Python to PATH"
✅ Check "Install for all users"
C:\Program Files\Python314\python.exe
Terminal window
where python
python --version
pip --version

Expected Output:

C:\Program Files\Python314\python.exe
Python 3.14.x
pip 24.x from C:\Program Files\Python314\Lib\site-packages\pip (python 3.14)

⚠️ Install as Administrator, using the full Python path with --no-user (see python-update.md for why: without it, packages install to your user profile, which the SYSTEM account running Task Scheduler cannot see).

Terminal window
"C:\Program Files\Python314\python.exe" -m pip install requests pandas openpyxl --no-user

Verify:

Terminal window
"C:\Program Files\Python314\python.exe" -c "import requests, pandas, openpyxl; print('requests', requests.__version__); print('pandas', pandas.__version__); print('openpyxl', openpyxl.__version__)"

Expected: requests 2.32+, pandas 2.3+, openpyxl 3.1+ (see offline_packages/requirements.txt for the full pinned list, including transitive dependencies like numpy)

5️⃣ Manual Script Validation (MANDATORY)

Section titled “5️⃣ Manual Script Validation (MANDATORY)”

Before enabling schedulers, test each script manually:

Terminal window
cd C:\Scripts\exl_systrack\scripts
python sv_health_desktop.py
python sv_reboot_health.py
python sv_appcrash.py
python sv_appfault.py
Terminal window
dir ..\logs\apps\

(all app logs now use *.json.log except sv_process_queueLenth.json.log, whose filename intentionally keeps a typo – see section 8️⃣ for why)

Expected:

sv_health_desktop.json.log ~80MB (67K hosts)
sv_reboot_health.json.log ~8MB (8.7K hosts)
sv_appcrash.json.log ~50KB (3 hosts)
sv_appfault.json.log ~5MB (~1.2K hosts)

Check for Errors:

Terminal window
dir ..\logs\*_error.json.log

(directly under logs\, not a logs\errors\ subfolder – these are written locally but not currently tailed by Datadog; see section 8️⃣)

Should be empty or contain only API-related errors (401, timeout, etc.)


Each scheduler runs only PowerShell, never Python directly.

Script Interval Priority Offset Daily Runs
run_health.ps1 4 hours (240 min) Medium 00:00 6
run_reboot.ps1 30 minutes High 00:00 48
run_appcrash.ps1 15 minutes CRITICAL 00:00 96
run_appfault.ps1 30 minutes High 00:05 48
Terminal window
:: Health - Every 4 hours (240 minutes)
schtasks /create /tn "SysTrack-Health" /sc minute /mo 240 /st 00:00 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_health.ps1" /ru SYSTEM /rl HIGHEST /f
:: Reboot - Every 30 minutes
schtasks /create /tn "SysTrack-Reboot" /sc minute /mo 30 /st 00:00 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_reboot.ps1" /ru SYSTEM /rl HIGHEST /f
:: AppCrash - Every 15 minutes (CRITICAL)
schtasks /create /tn "SysTrack-AppCrash" /sc minute /mo 15 /st 00:00 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_appcrash.ps1" /ru SYSTEM /rl HIGHEST /f
:: AppFault - Every 30 minutes (staggered +5min)
schtasks /create /tn "SysTrack-AppFault" /sc minute /mo 30 /st 00:05 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_appfault.ps1" /ru SYSTEM /rl HIGHEST /f
Terminal window
schtasks /query /tn "SysTrack-*" /fo LIST /v

Expected Output:

TaskName: \SysTrack-Health
Run As User: NT AUTHORITY\SYSTEM
Task To Run: powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_health.ps1
Schedule: Every 240 minutes
Next Run Time: <valid timestamp>
Click to expand PowerShell method
Terminal window
# 1. Health - Every 4 hours
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -File "C:\Scripts\exl_systrack\schedulers\run_health.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At '00:00' -RepetitionInterval (New-TimeSpan -Hours 4) -RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledTask -TaskName "SysTrack-Health" -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest -Force
# 2. Reboot - Every 30 minutes
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -File "C:\Scripts\exl_systrack\schedulers\run_reboot.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At '00:00' -RepetitionInterval (New-TimeSpan -Minutes 30) -RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledTask -TaskName "SysTrack-Reboot" -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest -Force
# 3. AppCrash - Every 15 minutes (CRITICAL)
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -File "C:\Scripts\exl_systrack\schedulers\run_appcrash.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At '00:00' -RepetitionInterval (New-TimeSpan -Minutes 15) -RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledTask -TaskName "SysTrack-AppCrash" -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest -Force
# 4. AppFault - Every 30 minutes (staggered +5min)
$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -File "C:\Scripts\exl_systrack\schedulers\run_appfault.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At '00:05' -RepetitionInterval (New-TimeSpan -Minutes 30) -RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledTask -TaskName "SysTrack-AppFault" -Action $action -Trigger $trigger -User "SYSTEM" -RunLevel Highest -Force

00:00 → Health (4h) + Reboot (30m) + AppCrash (15m)
00:05 → AppFault (30m)
00:15 → AppCrash
00:30 → Reboot + AppCrash
00:35 → AppFault
00:45 → AppCrash
01:00 → Reboot + AppCrash
01:05 → AppFault
01:15 → AppCrash
01:30 → Reboot + AppCrash
...
04:00 → Health (4h) + Reboot + AppCrash
...
Daily Totals:
- Health: 6 runs (00:00, 04:00, 08:00, 12:00, 16:00, 20:00)
- Reboot: 48 runs (every 30 minutes)
- AppCrash: 96 runs (every 15 minutes)
- AppFault: 48 runs (every 30 minutes, +5min offset)

C:\ProgramData\Datadog\conf.d\systrack.d\conf.yaml

⚠️ Must be named exactly conf.yaml (not conf.yml). The Datadog Agent’s config loader only recognizes conf.yaml / conf.yaml.example inside a check’s .d\ folder – a file named conf.yml is silently ignored, and none of these logs would ever reach Datadog even though everything else works.

⚠️ This file is FROZEN in production. The live copy at the path above already has dashboards and monitors built on top of its exact paths, and it must never be edited to “fix” it – any change risks silently breaking those dashboards. The repo’s tracked copy at config\datadog\systrack.d\conf.yaml is a verbatim mirror of that live file (not an idealized/cleaned-up version), kept in version control for visibility only. It covers all 13 scripts.

Updated 2026-07-15 to match the current live file – production was corrected since the previous mirror, so the old lowercase/typo’d filenames below no longer apply. Two intentional quirks remain (not bugs to “fix”):

  • sv_health_desktop.json.log ships with source: sv_health (the short form, not the full script name) – cosmetic Datadog tag only.
  • sv_process_queueLenth.json.log / source: sv_process_queueLenth keeps the “Lenth” typo (missing “g”) even though the script itself is spelled correctly (sv_process_queueLength.py).

sv_appcrash and sv_appfault also use sources without the sv_ prefix (appcrash, appfault) – also cosmetic, no script-side impact.

There is currently no error-log glob and no history-log glob in the live file – error and history logs are written locally by scripts\*.py as before, but are not currently shipped to Datadog.

scripts\sv_process_queueLength.py has the one remaining DATADOG_LOG_FILENAME override (for the typo above). Run tools\systrack_conf_check.py any time either side changes to confirm scripts and conf.yaml still agree.

init_config:
instances:
logs:
- path: C:\Scripts\exl_systrack\logs\apps\sv_health_desktop.json.log
service: systrack
source: sv_health
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_reboot_health.json.log
service: systrack
source: desktopreboothealth
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_appcrash.json.log
service: systrack
source: appcrash
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_appfault.json.log
service: systrack
source: appfault
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_realTime_disk.json.log
service: systrack
source: realTime_disk
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_realTime_cpu.json.log
service: systrack
source: realTime_cpu
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_realTime_memory.json.log
service: systrack
source: realTime_memory
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_realTime_latency.json.log
service: systrack
source: realTime_latency
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_realTime_event.json.log
service: systrack
source: realTime_event
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_interruptRate.json.log
service: systrack
source: sv_interruptRate
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_memoryLeak.json.log
service: systrack
source: sv_memoryLeak
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_packetRate.json.log
service: systrack
source: sv_packetRate
type: file
- path: C:\Scripts\exl_systrack\logs\apps\sv_process_queueLenth.json.log
service: systrack
source: sv_process_queueLenth
type: file
Terminal window
net stop datadogagent && net start datadogagent
Terminal window
"C:\Program Files\Datadog\Datadog Agent\bin\agent.exe" status

Expected Output:

Logs Agent
==========
Type: file
Path: C:\Scripts\exl_systrack\logs\apps\sv_health_desktop.json.log
Status: OK
Type: file
Path: C:\Scripts\exl_systrack\logs\apps\sv_reboot_health.json.log
Status: OK
Type: file
Path: C:\Scripts\exl_systrack\logs\apps\sv_appcrash.json.log
Status: OK
Type: file
Path: C:\Scripts\exl_systrack\logs\apps\sv_appfault.json.log
Status: OK

Note: as of 2026-07-15 the live config has no error-log or history-log glob, so *_error.json.log and *.history.jsonl entries no longer appear in agent status output – those logs are written locally but not shipped to Datadog.


Terminal window
cd C:\Scripts\exl_systrack\tools
.\run_all_tools.ps1

What it does:

  1. Runs all 5 diagnostic scripts
  2. Saves outputs to tools\output\
  3. Creates ZIP bundle: systrack-flare-YYYYMMDD-HHMMSS.zip

👉 Share this ZIP with support/Datadog/SRE for troubleshooting

Tool Purpose Usage
systrack_check.ps1 Python + Datadog sanity .\scripts\systrack_check.ps1
systrack_env_dump.ps1 Environment snapshot .\scripts\systrack_env_dump.ps1
systrack_paths_check.ps1 PATH + file validation .\scripts\systrack_paths_check.ps1
systrack_dd_log_probe.ps1 Log ingestion test .\scripts\systrack_dd_log_probe.ps1
systrack_permissions.ps1 Permission checks .\scripts\systrack_permissions.ps1

Each scheduler run appends JSON to:

logs\history\*_status.history.jsonl

Example:

{
"timestamp": "2025-12-14T16:42:11Z",
"script": "sv_appcrash",
"status": "SUCCESS",
"exit_code": 0,
"duration_ms": 287,
"scheduler": "run_appcrash.ps1"
}

Use for:

  • SLA tracking
  • Silent failure detection
  • Performance monitoring
count(@host.status) by {source:sv_health_desktop}
@host.status:Green by {source:sv_health_desktop}
@host.status:Red by {source:sv_health_desktop} > 100 | alert
avg(@host.quality) by {source:sv_health_desktop} | timeseries
count(@reboot.status) by {source:sv_reboot_health}
@reboot.onlinestatus:SystemOn by {source:sv_reboot_health}
count(@host.fqdn) by {source:sv_appcrash}
@host.status:* by {source:sv_appcrash} | alert immediately
count(@appfault.status) by {source:sv_appfault}
@appfault.status:Online by {source:sv_appfault}
count(*) by {source:systrack_error,script}
@level:ERROR by {source:systrack_error} | alert
count(@status) by {source:systrack_scheduler,script}
@status:FAILURE by {source:systrack_scheduler} | alert
avg(@duration_ms) by {source:systrack_scheduler,script} | timeseries

sv_health_desktop: 80MB (67K hosts)
sv_reboot_health: 8MB (8.7K hosts)
sv_appcrash: 50KB (3 hosts)
sv_appfault: 5MB (~1.2K hosts)
Health: 6 runs × 80MB = ~480MB/day
Reboot: 48 runs × 8MB = ~384MB/day
AppCrash: 96 runs × 50KB = ~5MB/day
AppFault: 48 runs × 5MB = ~240MB/day
-------------------------------------------
TOTAL: ~1.1GB/day → Datadog
Each script: 500MB max + 5 backups = 2.5GB per script
Total storage: 4 scripts × 2.5GB = 10GB maximum
Datadog auto-tracks: *.log, *.log.1, *.log.2, ... *.log.5

Script Hosts Interval Priority Daily Runs Data/Day
sv_health_desktop 67,204 4 hours (240 min) Medium 6 480MB
sv_reboot_health 8,774 30 minutes High 48 384MB
sv_appcrash 3 15 minutes CRITICAL 96 5MB
sv_appfault ~1,200 30 minutes (+5min) High 48 240MB
TOTAL 77,181 - - 198 ~1.1GB

Feature Status
System-wide Python
SYSTEM scheduler execution
Rotating logs (500MB×5)
Error logs (logs\*_error.json.log)
History audit trail (history/)
One-click diagnostics
Datadog wildcard tailing
Safe type conversions
Per-host error handling
Cookie authentication
24-hour lookback
UTC timestamps (ISO-8601)

  • Python 3.14+ installed system-wide
  • requests, pandas, openpyxl (and dependencies) installed system-wide with --no-user
  • Repository cloned to C:\Scripts\exl_systrack\
  • SYSTRACK_API_KEY set as a machine-level (System) environment variable – see tools/systrack_dashboard.py’s /help page
  • All 13 scripts tested manually (no errors)
  • Task Scheduler tasks created (SYSTEM user)
  • Datadog Agent conf.yaml configured (all 13 scripts + errors + history – see config\datadog\systrack.d\conf.yaml)
  • Agent restarted and verified
  • Logs appearing in Datadog UI
  • Dashboards created
  • Monitors/alerts configured
  • Diagnostic tools validated
  • ZIP flare generation tested

If starting cautiously, use:

Terminal window
:: Health - Every 6 hours (360 minutes)
schtasks /create /tn "SysTrack-Health" /sc minute /mo 360 /st 00:00 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_health.ps1" /ru SYSTEM /rl HIGHEST /f
:: Reboot - Every 1 hour (60 minutes)
schtasks /create /tn "SysTrack-Reboot" /sc minute /mo 60 /st 00:00 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_reboot.ps1" /ru SYSTEM /rl HIGHEST /f
:: AppCrash - Every 30 minutes
schtasks /create /tn "SysTrack-AppCrash" /sc minute /mo 30 /st 00:00 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_appcrash.ps1" /ru SYSTEM /rl HIGHEST /f
:: AppFault - Every 1 hour (60 minutes, +5min offset)
schtasks /create /tn "SysTrack-AppFault" /sc minute /mo 60 /st 00:05 /tr "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\exl_systrack\schedulers\run_appfault.ps1" /ru SYSTEM /rl HIGHEST /f

Then increase frequency after 1-2 weeks of stable operation.


✅ DEPLOY READY — VERIFIED END-TO-END
Scheduler → Python → Logs → Datadog → Dashboards 🚀
77,181 endpoints monitored
198 executions/day
~1.1GB daily ingestion
Zero data loss
Production hardened

Powered by Zoos Global | EXL Service


  1. Run tools\run_all_tools.ps1
  2. Share generated ZIP: tools\systrack-flare-*.zip
  3. Check Task Scheduler history: taskschd.msc
  4. Review error logs: logs\*_error.json.log

📌 This README is production-ready and complete.

Version: 1.0.0
Last Updated: December 14, 2025