Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The NetSuite Pro

The NetSuite Pro Logo The NetSuite Pro Logo

The NetSuite Pro Navigation

  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • Advanced PDF Templates in NetSuite
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask A Question
  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • Advanced PDF Templates in NetSuite
  • Blog
  • Contact Us
Home/ NetSuite Scripting/Debugging & Logging Strategies (SuiteScript 2.1)

Debugging & Logging Strategies (SuiteScript 2.1)

🔹 Why this matters

Good logging makes bugs reproducible, fixable, and rare. In NetSuite, you’ll triage via Execution Logs (server-side) and the browser console (client-side). This guide shows:

  • What to log (and what not to)
  • How to structure logs for fast filtering
  • Patterns for server, client, Scheduled, and Map/Reduce scripts
  • Safe logging (no secrets) and governance-aware timing

🔹 The logging toolbox (quick reference)

Server-side (UE, Scheduled, M/R, Suitelet, RESTlet)

  • log.debug(title, details) – verbose info (default filtered in Prod)
  • log.audit(title, details) – noteworthy events/state changes
  • log.error(title, details) – failures you must see
  • log.emergency(title, details) – critical outages (rare)

Tips

  • details can be objects → wrap with JSON.stringify(details) when needed.
  • Avoid dumping entire records or big payloads; redact and truncate.

Client-side (Client Script)

  • console.log/info/warn/error(...) – view in browser devtools
  • debugger; – sets a breakpoint if devtools are open
  • Avoid alert() except for UX prompts

🔹 Make logs filterable: include a request/run “Correlation ID”

Add a lightweight correlation ID per execution. Put it in every log so you can grep a failing run.

function makeCorrelationId(prefix='RUN') {
  // e.g., RUN-1732549012345-7f3a
  return `${prefix}-${Date.now()}-${Math.random().toString(16).slice(2,6)}`;
}

Use it in every log line:

const cid = makeCorrelationId('CUSTSYNC');
log.debug('Start', JSON.stringify({ cid, deployment: runtime.getCurrentScript().deploymentId }));

🔹 Safe logging helper (redact & truncate)

Never log secrets or PII in plain text.

function redact(value) {
  if (!value) return value;
  const s = String(value);
  if (/^Bearer\s+/i.test(s)) return 'Bearer ***';
  if (s.length > 1200) return s.slice(0, 1200) + '…[truncated]';
  return s.replace(/([A-Za-z0-9]{4})([A-Za-z0-9]+)([A-Za-z0-9]{4})/g, '$1***$3'); // coarse mask
}

function safe(obj) {
  try { return JSON.stringify(obj, (k, v) => (k.match(/key|secret|token|password/i) ? '***' : v)); }
  catch (_) { return '[unserializable]'; }
}

🔹 Pattern: Try–catch with context-rich logs

Wrap critical sections; include record IDs, counts, and the correlation ID.

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */
define(['N/runtime'], (runtime) => {
  const beforeSubmit = (context) => {
    const cid = makeCorrelationId('UE');
    try {
      const rec = context.newRecord;
      log.audit('UE:beforeSubmit:start', safe({ cid, type: rec.type, id: rec.id, mode: context.type }));
      // … your logic …
      log.debug('UE:beforeSubmit:end', safe({ cid }));
    } catch (e) {
      log.error('UE:beforeSubmit:error', redact(e && (e.stack || e.message || e)));
      throw e; // block save when validation fails
    }
  };
  return { beforeSubmit };
});

🔹 Toggle verbosity via Deployment “Log Level”

In the Script Deployment record:

  • Dev/Sandbox: Debug
  • Production: Audit (bump to Error for noisy scripts)

You can also add a script parameter custscript_log_level and gate your log.debug calls.

function shouldDebug(runtime) {
  const lvl = (runtime.getCurrentScript().getParameter({ name: 'custscript_log_level' }) || '').toLowerCase();
  return lvl === 'debug';
}
// usage: if (shouldDebug(runtime)) log.debug('Detail', safe({...}));

🔹 Time and governance checkpoints

Measure performance and avoid usage surprises.

define(['N/runtime'], (runtime) => {
  function timer() { const t0 = Date.now(); return (label) => log.audit('TIMER', `${label} ms=${Date.now()-t0}`); }

  const execute = () => {
    const tic = timer();
    const script = runtime.getCurrentScript();

    // … step 1 …
    tic('after step 1');

    // log remaining governance units
    log.debug('Gov', `remaining=${script.getRemainingUsage()}`);

    // … step 2 …
    tic('after step 2');
  };

  return { execute };
});

🔹 Map/Reduce: summarize ALL the things

Use summarize to dump errors and metrics in one place.

const summarize = (summary) => {
  try {
    log.audit('MR:summary', safe({ usage: summary.usage, yields: summary.yields }));

    if (summary.inputSummary.error) {
      log.error('MR:input:error', redact(summary.inputSummary.error));
    }

    summary.mapSummary.errors.iterator().each((key, err) => {
      log.error('MR:map:error', safe({ key, err: redact(err) }));
      return true;
    });

    summary.reduceSummary.errors.iterator().each((key, err) => {
      log.error('MR:reduce:error', safe({ key, err: redact(err) }));
      return true;
    });
  } catch (e) {
    log.error('MR:summary:fail', redact(e && (e.stack || e.message || e)));
  }
};

Tip: Also count processed records and successes vs failures; include in audit.


🔹 Scheduled scripts: graceful stop + reschedule logs

When usage is low, log why you stop and reschedule.

define(['N/runtime','N/task'], (runtime, task) => {
  const execute = () => {
    const cid = makeCorrelationId('SCH');
    try {
      const rem = runtime.getCurrentScript().getRemainingUsage();
      if (rem < 150) {
        log.audit('SCH:reschedule', safe({ cid, reason: 'low usage', remaining: rem }));
        task.create({
          taskType: task.TaskType.SCHEDULED_SCRIPT,
          scriptId: runtime.getCurrentScript().id,
          deploymentId: runtime.getCurrentScript().deploymentId
        }).submit();
        return;
      }
      // … continue work …
      log.debug('SCH:done', safe({ cid }));
    } catch (e) {
      log.error('SCH:error', redact(e && (e.stack || e.message || e)));
    }
  };
  return { execute };
});

🔹 Client Script debugging (browser)

  • Open browser devtools (F12) on the NetSuite page.
  • Use console.log() with clear prefixes and IDs.
  • Use debugger; to break:
/**
 * @NApiVersion 2.1
 * @NScriptType ClientScript
 */
define(['N/currentRecord'], (currentRecord) => {
  const pageInit = () => {
    console.log('[CS] pageInit start');
    // debugger; // uncomment during development
    const rec = currentRecord.get();
    console.log('[CS] record type:', rec.type);
  };
  return { pageInit };
});

Note: log.debug does not exist in Client Scripts.


🔹 Persisting diagnostic breadcrumbs (optional)

For stubborn bugs, persist breadcrumbs to a custom record or a small File Cabinet text file—careful with volume and secrets.

// Write a small line to a text file for post-mortem (rotate or cap size in prod)
define(['N/file'], (file) => {
  function appendLine(name, text, folderId) {
    try {
      const f = file.create({ name, fileType: file.Type.PLAINTEXT, contents: text + '\n' });
      if (folderId) f.folder = folderId;
      return f.save();
    } catch (e) { log.error('appendLine error', e.message); }
  }
});

🔹 What NOT to log

  • Secrets: tokens, passwords, full Authorization headers
  • PII: full emails, phone numbers; mask if needed
  • Huge payloads: truncate or summarize counts/keys
  • Whole records: log only fields you need

🔹 Triage checklist (production issues)

  1. Get Correlation ID (or timestamp + deployment).
  2. Check Script Execution Logs (Script Deployment → Execution Log).
  3. Search for error/emergency first, then audit.
  4. Reproduce in Sandbox with Debug log level.
  5. Add timers around suspected hotspots.
  6. If data-dependent, log record IDs and search filters used.
  7. For external calls, log status code, duration, and a redacted body sample.

🔹 Copy-paste helpers (drop in /SuiteScripts/lib/logging.js)

export function makeCorrelationId(prefix='RUN') {
  return `${prefix}-${Date.now()}-${Math.random().toString(16).slice(2,6)}`;
}
export function safe(obj) {
  try { return JSON.stringify(obj, (k, v) => (k.match(/key|secret|token|password/i) ? '***' : v)); }
  catch (_) { return '[unserializable]'; }
}
export function redact(value) {
  if (!value) return value;
  const s = String(value);
  if (/^Bearer\s+/i.test(s)) return 'Bearer ***';
  if (s.length > 1200) return s.slice(0, 1200) + '…[truncated]';
  return s.replace(/([A-Za-z0-9]{4})([A-Za-z0-9]+)([A-Za-z0-9]{4})/g, '$1***$3');
}

✅ Key Takeaway

  • Structure logs with a correlation ID and consistent prefixes.
  • Log safely (redact, truncate), and at the right level (debug/audit/error).
  • Measure time and governance, and always summarize Map/Reduce errors.
  • For client issues, use the browser console and debugger;.
Share
  • Facebook

Sidebar

Ask A Question

Stats

  • Questions 6
  • Answers 6
  • Best Answers 0
  • Users 2
  • Popular
  • Answers
  • Rocky

    Issue in running a client script in NetSuite SuiteScript 2.0 ...

    • 1 Answer
  • admin

    How can I send an email with an attachment in ...

    • 1 Answer
  • admin

    How do I avoid SSS_USAGE_LIMIT_EXCEEDED in a Map/Reduce script?

    • 1 Answer
  • admin
    admin added an answer The issue is usually caused by following Wrong script file… September 14, 2025 at 10:33 pm
  • admin
    admin added an answer Steps to send an Invoice PDF by email: define(['N/email', 'N/render',… August 28, 2025 at 3:05 am
  • admin
    admin added an answer This error means your script hit NetSuite’s governance usage limit… August 28, 2025 at 3:02 am

Top Members

Rocky

Rocky

  • 1 Question
  • 21 Points
Begginer
admin

admin

  • 5 Questions
  • 2 Points

Trending Tags

clientscript netsuite scripting suitescript

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

© 2025 The NetSuite Pro. All Rights Reserved