Testing & debugging
In the portal
Section titled “In the portal”The portal’s custom-driver editor is the fastest feedback loop:
- Open the device, then the Custom Drivers tab.
- Click the driver to edit.
- Use the Test button to execute the driver against the device on demand, without waiting for the scheduler.
- Pick which entry point to run —
validateorget_status(orbackupfor configuration-management drivers). - The run is a dry run: published variables, metrics, tables, and backups are computed and shown in the UI but not persisted to the device’s history. Safe to re-run as many times as you like.
- The log panel shows the driver’s
console.debug/info/warn/erroroutput from that run, plus the finalD.success/D.failureoutcome.
Iterate here first — it’s the shortest path from edit to outcome.
Running against an arbitrary target
Section titled “Running against an arbitrary target”The driver does not have to run against the device it is currently attached to. If you want to point it at a different host — useful when you’re prototyping a driver against a test device you don’t want to manage — override the device inside the driver with D.createExternalDevice:
function validate() { var target = D.createExternalDevice('192.0.2.10', { username: 'admin', password: 'secret' }); target.sendSSHCommand({ command: 'uptime' }, function (out, error) { if (error) return D.failure(D.errorType.RESOURCE_UNAVAILABLE); D.success(); });}target exposes the same protocol methods as D.device — HTTP, SSH, SNMP, etc. Use this during iteration, then swap back to D.device.* before shipping.
Log levels
Section titled “Log levels”Inside a driver, use the console namespace:
console.debug('starting tick');console.info('got %d items', items.length);console.warn('missing field, defaulting to 0');console.error('HTTP %d from %s', response.statusCode, options.url);All four show up in the portal’s log panel when you use the Test button. Avoid dumping full payloads — big parses in every tick bloat logs and make the panel hard to read. Log what you need to diagnose a specific failure, nothing more.
Common failure modes
Section titled “Common failure modes”| Symptom | Likely cause | Fix |
|---|---|---|
| Driver marked as failed, no log lines | Driver never called D.success / D.failure on a code path | Add an else / early return — every branch must terminate |
| Driver timeout-kills every tick | Using a synchronous blocking pattern inside an async callback | Return from the callback with one of the terminal calls |
| Variables appear then vanish | UID changing across runs | Make the UID stable — don’t use Date.now() or random |
| Self-signed HTTPS works in curl but not in driver | rejectUnauthorized default is strict | Set rejectUnauthorized: false in options |
| SSH says auth failed but creds are right | Old KEX or cipher | Override algorithms.kex / algorithms.cipher — see the SSH guide |
| JSON.parse throws on valid JSON | Response has a BOM or leading whitespace | Trim before parse — JSON.parse(body.trim().replace(/^/, '')) |