var _ = require('./utility'); var traverse = require('./utility/traverse'); function raw(payload, jsonBackup) { return [payload, _.stringify(payload, jsonBackup)]; } function selectFrames(frames, range) { var len = frames.length; if (len > range * 2) { return frames.slice(0, range).concat(frames.slice(len - range)); } return frames; } function truncateFrames(payload, jsonBackup, range) { range = (typeof range === 'undefined') ? 30 : range; var body = payload.data.body; var frames; if (body.trace_chain) { var chain = body.trace_chain; for (var i = 0; i < chain.length; i++) { frames = chain[i].frames; frames = selectFrames(frames, range); chain[i].frames = frames; } } else if (body.trace) { frames = body.trace.frames; frames = selectFrames(frames, range); body.trace.frames = frames; } return [payload, _.stringify(payload, jsonBackup)]; } function maybeTruncateValue(len, val) { if (!val) { return val; } if (val.length > len) { return val.slice(0, len - 3).concat('...'); } return val; } function truncateStrings(len, payload, jsonBackup) { function truncator(k, v, seen) { switch (_.typeName(v)) { case 'string': return maybeTruncateValue(len, v); case 'object': case 'array': return traverse(v, truncator, seen); default: return v; } } payload = traverse(payload, truncator); return [payload, _.stringify(payload, jsonBackup)]; } function truncateTraceData(traceData) { if (traceData.exception) { delete traceData.exception.description; traceData.exception.message = maybeTruncateValue(255, traceData.exception.message); } traceData.frames = selectFrames(traceData.frames, 1); return traceData; } function minBody(payload, jsonBackup) { var body = payload.data.body; if (body.trace_chain) { var chain = body.trace_chain; for (var i = 0; i < chain.length; i++) { chain[i] = truncateTraceData(chain[i]); } } else if (body.trace) { body.trace = truncateTraceData(body.trace); } return [payload, _.stringify(payload, jsonBackup)]; } function needsTruncation(payload, maxSize) { return _.maxByteSize(payload) > maxSize; } function truncate(payload, jsonBackup, maxSize) { maxSize = (typeof maxSize === 'undefined') ? (512 * 1024) : maxSize; var strategies = [ raw, truncateFrames, truncateStrings.bind(null, 1024), truncateStrings.bind(null, 512), truncateStrings.bind(null, 256), minBody ]; var strategy, results, result; while ((strategy = strategies.shift())) { results = strategy(payload, jsonBackup); payload = results[0]; result = results[1]; if (result.error || !needsTruncation(result.value, maxSize)) { return result; } } return result; } module.exports = { truncate: truncate, /* for testing */ raw: raw, truncateFrames: truncateFrames, truncateStrings: truncateStrings, maybeTruncateValue: maybeTruncateValue };