Skip to content

Testing & debugging

The portal’s custom-driver editor is the fastest feedback loop:

  1. Open the device, then the Custom Drivers tab.
  2. Click the driver to edit.
  3. Use the Test button to execute the driver against the device on demand, without waiting for the scheduler.
  4. Pick which entry point to run — validate or get_status (or backup for configuration-management drivers).
  5. 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.
  6. The log panel shows the driver’s console.debug / info / warn / error output from that run, plus the final D.success / D.failure outcome.

Iterate here first — it’s the shortest path from edit to outcome.

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.

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.

SymptomLikely causeFix
Driver marked as failed, no log linesDriver never called D.success / D.failure on a code pathAdd an else / early return — every branch must terminate
Driver timeout-kills every tickUsing a synchronous blocking pattern inside an async callbackReturn from the callback with one of the terminal calls
Variables appear then vanishUID changing across runsMake the UID stable — don’t use Date.now() or random
Self-signed HTTPS works in curl but not in driverrejectUnauthorized default is strictSet rejectUnauthorized: false in options
SSH says auth failed but creds are rightOld KEX or cipherOverride algorithms.kex / algorithms.cipher — see the SSH guide
JSON.parse throws on valid JSONResponse has a BOM or leading whitespaceTrim before parse — JSON.parse(body.trim().replace(/^/, ''))