Map/Reduce Script JavaScript Exception Error Tracking
I am super happy with NetSuite SuiteScript 2.0 introducing Map/Reduce Scripts:
There is the sheer performance, of course: Their multi-threading capabilities do make a massive difference in processing data, especially when calling the database.
The new and more generous Unit Governance concept allows me to create, load and edit thousands of NetSuite records in a single run. When it comes to querying data, still, I work with bulk searches with adequate SQL expressions and filter injections wherever possible.
While first feeling restricted with the requirement of working with practically just one object passed through the various stages, I have come to appreciate the clarity such an approach provides once you master those more complex JSONs. By now, across all my script types, I am working with a master object I generally call objInputData where I compile my data in tiered children, for example a transaction query by [{"accountingperiod":{"entity":{"project":{"glaccount":...}}}}] or an employee query by [{"workcalendar":{"employee":...}}], ready to convert it into a Map/Reduce script whenever and wherever possible. The approach even pays for input parameters, which I generally pack into an objInputParams with property keys such as objInputParams.startdate, objInputParams.accounttype, or objInputParams.numofmths, because once working with Map/Reduce, I can swiftly pump it into an N/cache object and call on it in later stages.
One tricky thing about Map/Reduce Scripting is tracking JavaScript exceptions, especially if you forget apostrophes in object property key declarations as frequently as I do.
Map/Reduce would not break and throw a JS_EXCEPTION error message in the Execution Logs, but either simply run through to the summarize() stage, in case you leave the checkbox “Submit all stages at once” ticked by default or break with no error message if you untick it.
In order to get the error messages, you need to “Submit all stages at once” and include the following code in your summarize() stage:
function summarize(context) { context.mapSummary.errors.iterator().each(function (key, error) { log.error('Map Error for key: ' + key, error); return true; }); context.reduceSummary.errors.iterator().each(function (key, error) { log.error('Reduce Error for key: ' + key, error); return true; }); }
You need the iterator. Code such as
log.error('objMapLog', JSON.stringify(context.mapSummary.errors)); log.error('objReduceLog', JSON.stringify(context.reduceSummary.errors));
will not work.
Further, it’s always cool to throw in some Unit Governance tracking with
var type = context.toString(); log.audit(type + ' Map Errors', context.mapSummary); log.audit(type + ' Reduce Errors', context.reduceSummary); log.audit(type + ' Usage Consumed', context.usage); log.audit(type + ' Concurrency Number ', context.concurrency); log.audit(type + ' Number of Yields', context.yields);
Comments