callsite-record
Advanced tools
Comparing version 2.0.2 to 3.0.0
141
lib/index.js
@@ -1,7 +0,8 @@ | ||
var fs = require('fs'); | ||
var Promise = require('pinkie-promise'); | ||
var callsite = require('callsite'); | ||
var padStart = require('lodash/string').padStart; | ||
var defatuls = require('defaults'); | ||
var highlight = require('highlight-es'); | ||
var fs = require('fs'); | ||
var Promise = require('pinkie-promise'); | ||
var callsite = require('callsite'); | ||
var stackParser = require('error-stack-parser'); | ||
var padStart = require('lodash/string').padStart; | ||
var defatuls = require('defaults'); | ||
var highlight = require('highlight-es'); | ||
@@ -27,29 +28,9 @@ var renderers = { | ||
// NOTE: The following code was partially adopted from the V8 code | ||
// (see: https://github.com/v8/v8/blob/3c3d7e7be80f45eeea0dc74a71d7552e2afc2985/src/js/messages.js#L647) | ||
function getFrameLocation (frame) { | ||
if (frame.isNative()) | ||
return 'native'; | ||
var location = frame.getFileName(); | ||
var lineNum = frame.getLineNumber(); | ||
var colNum = frame.getColumnNumber(); | ||
if (!location) { | ||
location = frame.isEval() ? frame.getEvalOrigin() + ', ' : ''; | ||
location += '<anonymous>'; | ||
} | ||
if (lineNum) { | ||
location += ':' + lineNum; | ||
if (colNum) | ||
location += ':' + colNum; | ||
} | ||
return location; | ||
function isV8StackFrame (frame) { | ||
return /CallSite/.test(frame.constructor); | ||
} | ||
function getFrameMethodName (frame, funcName) { | ||
// NOTE: Code was partially adopted from the V8 code | ||
// (see: https://github.com/v8/v8/blob/3c3d7e7be80f45eeea0dc74a71d7552e2afc2985/src/js/messages.js#L647) | ||
var typeName = frame.getTypeName(); | ||
@@ -78,4 +59,20 @@ var methodName = frame.getMethodName(); | ||
function getFrameName (frame) { | ||
// CallsiteRecord | ||
var CallsiteRecord = function (filename, lineNum, callsiteFrameIdx, stackFrames) { | ||
this.filename = filename; | ||
this.lineNum = lineNum; | ||
this.callsiteFrameIdx = callsiteFrameIdx; | ||
this.stackFrames = stackFrames; | ||
this.isV8Frames = isV8StackFrame(this.stackFrames[0]); | ||
}; | ||
CallsiteRecord.prototype._getFrameName = function (frame) { | ||
// NOTE: Code was partially adopted from the V8 code | ||
// (see: https://github.com/v8/v8/blob/3c3d7e7be80f45eeea0dc74a71d7552e2afc2985/src/js/messages.js#L647) | ||
var funcName = frame.getFunctionName(); | ||
if (!this.isV8Frames) | ||
return funcName || '<anonymous>'; | ||
var isCtor = frame.isConstructor(); | ||
@@ -90,10 +87,27 @@ var isMethod = !frame.isToplevel() && !isCtor; | ||
return isCtor ? 'new ' + funcName : funcName; | ||
} | ||
}; | ||
// CallsiteRecord | ||
var CallsiteRecord = function (filename, lineNum, callsiteFrameIdx, stackFrames) { | ||
this.filename = filename; | ||
this.lineNum = lineNum; | ||
this.callsiteFrameIdx = callsiteFrameIdx; | ||
this.stackFrames = stackFrames; | ||
CallsiteRecord.prototype._getFrameLocation = function (frame) { | ||
// NOTE: Code was partially adopted from the V8 code | ||
// (see: https://github.com/v8/v8/blob/3c3d7e7be80f45eeea0dc74a71d7552e2afc2985/src/js/messages.js#L647) | ||
if (this.isV8Frames && frame.isNative()) | ||
return 'native'; | ||
var location = frame.getFileName(); | ||
var lineNum = frame.getLineNumber(); | ||
var colNum = frame.getColumnNumber(); | ||
if (this.isV8Frames && !location) { | ||
location = frame.isEval() ? frame.getEvalOrigin() + ', ' : ''; | ||
location += '<anonymous>'; | ||
} | ||
if (lineNum) { | ||
location += ':' + lineNum; | ||
if (colNum) | ||
location += ':' + colNum; | ||
} | ||
return location; | ||
}; | ||
@@ -146,6 +160,10 @@ | ||
CallsiteRecord.prototype._renderStack = function (renderer, stackFilter) { | ||
var record = this; | ||
var entries = this.stackFrames.slice(this.callsiteFrameIdx); | ||
if (stackFilter) | ||
entries = entries.filter(stackFilter); | ||
if (stackFilter) { | ||
entries = entries.filter(function (frame, idx) { | ||
return stackFilter(frame, idx, record.isV8Frames); | ||
}); | ||
} | ||
@@ -156,4 +174,4 @@ var lastIdx = entries.length - 1; | ||
var isLast = idx === lastIdx; | ||
var name = getFrameName(frame); | ||
var location = getFrameLocation(frame); | ||
var name = record._getFrameName(frame); | ||
var location = record._getFrameLocation(frame); | ||
@@ -199,9 +217,4 @@ return str + renderer.stackLine(name, location, isLast); | ||
// API | ||
module.exports = function createCallsiteRecord (fnName, typeName) { | ||
var stackFrames = callsite(); | ||
// NOTE: remove API call | ||
stackFrames.shift(); | ||
// Static | ||
CallsiteRecord.fromStackFrames = function (stackFrames, fnName, typeName) { | ||
if (typeName && fnName === 'constructor') | ||
@@ -232,2 +245,32 @@ fnName = typeName; | ||
CallsiteRecord.fromError = function (error) { | ||
var stackFrames = stackParser.parse(error); | ||
if (stackFrames.length) { | ||
var filename = stackFrames[0].getFileName(); | ||
var lineNum = stackFrames[0].getLineNumber() - 1; | ||
return new CallsiteRecord(filename, lineNum, 0, stackFrames); | ||
} | ||
return null; | ||
}; | ||
// API | ||
module.exports = function createCallsiteRecord (/* err || fnName, typeName */) { | ||
if (arguments[0] instanceof Error) | ||
return CallsiteRecord.fromError(arguments[0]); | ||
else if (typeof arguments[0] === 'string') { | ||
var stackFrames = callsite(); | ||
// NOTE: remove API call | ||
stackFrames.shift(); | ||
return CallsiteRecord.fromStackFrames(stackFrames, arguments[0], arguments[1]); | ||
} | ||
return null; | ||
}; | ||
module.exports.renderers = renderers; |
{ | ||
"name": "callsite-record", | ||
"version": "2.0.2", | ||
"description": "Create fancy call site records for any function up in the stack for the logging purposes.", | ||
"version": "3.0.0", | ||
"description": "Create fancy log entries for errors and function call sites.", | ||
"main": "lib/index.js", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"files": [ | ||
@@ -42,2 +39,3 @@ "lib" | ||
"defaults": "^1.0.3", | ||
"error-stack-parser": "^1.3.3", | ||
"escape-html": "^1.0.3", | ||
@@ -44,0 +42,0 @@ "highlight-es": "^1.0.0", |
# callsite-record | ||
[![Build Status](https://api.travis-ci.org/inikulin/callsite-record.svg)](https://travis-ci.org/inikulin/callsite-record) | ||
*Create fancy call site records for any function up in the stack for the logging purposes.* | ||
*Create fancy log entries for errors and function call sites.* | ||
**For Error:** | ||
```js | ||
@@ -11,13 +12,35 @@ 'use strict'; | ||
let record = null; | ||
function myFunc() { | ||
throw new Error('Yo!'); | ||
} | ||
function func1 () { | ||
record = createCallsiteRecord('func1'); | ||
try { | ||
myFunc(); | ||
} | ||
catch(err) { | ||
console.log(createCallsiteRecord(err).renderSync()); | ||
} | ||
(function func2(){ | ||
func1(); | ||
})(); | ||
``` | ||
console.log(record.renderSync()); | ||
⬇ | ||
![example](https://raw.githubusercontent.com/inikulin/callsite-record/master/media/example1.png) | ||
**For function call up in the stack:** | ||
```js | ||
'use strict'; | ||
const createCallsiteRecord = require('callsite-record'); | ||
function func2 () { | ||
(function func1 () { | ||
console.log(createCallsiteRecord('func2').renderSync()); | ||
})(); | ||
} | ||
func2(); | ||
``` | ||
@@ -27,4 +50,8 @@ | ||
![example](https://raw.githubusercontent.com/inikulin/callsite-record/master/media/example.png) | ||
![example](https://raw.githubusercontent.com/inikulin/callsite-record/master/media/example2.png) | ||
**Additional goodies:** | ||
- Use [renderers](#renderoptionsrenderer) for different output formats, e.g. to produce output in HTML. | ||
- Use [stack filter](#renderoptionsstackfilter) to produce clean and beautiful stacks, e.g. removing Node lib internal calls. | ||
## Install | ||
@@ -88,4 +115,6 @@ ``` | ||
Function that will be used to filter stack frames. Function accepts 2 arguments: | ||
- `stackFrame` - V8 [CallSite](https://github.com/v8/v8/wiki/Stack-Trace-API#customizing-stack-traces) object. | ||
- `stackFrame` - stack entry. | ||
- `idx` - index of the frame. | ||
- `isV8StackFrame` - if `true` then `stackFrame` is a V8 [CallSite](https://github.com/v8/v8/wiki/Stack-Trace-API#customizing-stack-traces) object. | ||
Otherwise it's a [StackFrame](https://github.com/stacktracejs/stackframe) object. | ||
@@ -92,0 +121,0 @@ **Default:** `null`. |
18084
283
170
10
+ Addederror-stack-parser@^1.3.3
+ Addederror-stack-parser@1.3.6(transitive)
+ Addedstackframe@0.3.1(transitive)