You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

227 lines
6.3 KiB

var Class = require('./Class');
var Trace = require('./Trace');
var perfNow = require('./perfNow');
var extend = require('./extend');
var isNode = require('./isNode');
var Stack = require('./Stack');
var map = require('./map');
var trim = require('./trim');
var isEmpty = require('./isEmpty');
var intersect = require('./intersect');
var convertBase = require('./convertBase');
var defPid = 0;
var defTid = 0;
var id = 0;
if (isNode) {
defPid = process.pid;
try {
defTid = eval('require')('worker_threads').threadId;
} catch (e) {}
}
exports = Class({
initialize: function Tracing() {
var _ref =
arguments.length > 0 && arguments[0] !== undefined
? arguments[0]
: {},
_ref$pid = _ref.pid,
pid = _ref$pid === void 0 ? defPid : _ref$pid,
_ref$tid = _ref.tid,
tid = _ref$tid === void 0 ? defTid : _ref$tid,
_ref$processName = _ref.processName,
processName =
_ref$processName === void 0 ? 'Process' : _ref$processName,
_ref$threadName = _ref.threadName,
threadName =
_ref$threadName === void 0 ? 'Thread' : _ref$threadName;
this._pid = pid;
this._tid = tid;
this._processName = processName;
this._threadName = threadName;
},
start: function() {
var cat =
arguments.length > 0 && arguments[0] !== undefined
? arguments[0]
: '';
this._targetCat = processCat(cat);
if (!isEmpty(this._targetCat)) {
this._targetCat.push('__metadata');
}
this._traceEventStack = new Stack();
this._asyncEventMap = {};
this._trace = new Trace();
this.metadata(
'process_name',
{
name: this._processName
},
{
tid: 0,
ts: 0
}
);
this.metadata(
'thread_name',
{
name: this._threadName
},
{
ts: 0
}
);
},
stop: function() {
var trace = this._trace;
if (!trace) {
throw Error('Need to call start first');
}
delete this._targetCat;
delete this._traceEventStack;
delete this._asyncEventMap;
delete this._trace;
return trace.toJSON();
},
metadata: function(name, args, extra) {
this._addEvent('__metadata', name, Phase.Metadata, args, extra);
},
begin: function(cat, name) {
var args =
arguments.length > 2 && arguments[2] !== undefined
? arguments[2]
: {};
if (!this._traceEventStack) {
return;
}
this._traceEventStack.push({
cat: cat,
name: name,
args: args,
ts: this._getCurTs()
});
},
end: function(args) {
if (!this._traceEventStack) {
return;
}
var beginEvent = this._traceEventStack.pop();
if (!beginEvent) {
throw Error('Need to call begin first');
}
var cat = beginEvent.cat,
name = beginEvent.name,
ts = beginEvent.ts;
args = extend(beginEvent.args, args);
this._addEvent(cat, name, Phase.Complete, args, {
dur: this._getCurTs() - ts,
ts: ts
});
},
asyncBegin: function(cat, name) {
var id =
arguments.length > 2 && arguments[2] !== undefined
? arguments[2]
: this.id();
var args =
arguments.length > 3 && arguments[3] !== undefined
? arguments[3]
: {};
if (!this._asyncEventMap) {
return id;
}
this._asyncEventMap[id] = {
cat: cat,
name: name
};
this._addEvent(cat, name, Phase.NestableAsyncBegin, args, {
id: id
});
return id;
},
asyncEnd: function(id) {
var args =
arguments.length > 1 && arguments[1] !== undefined
? arguments[1]
: {};
if (!this._asyncEventMap) {
return;
}
var asyncBeginEvent = this._asyncEventMap[id];
if (!asyncBeginEvent) {
throw Error('Need to call async begin first');
}
var cat = asyncBeginEvent.cat,
name = asyncBeginEvent.name;
delete this._asyncEventMap[id];
this._addEvent(cat, name, Phase.NestableAsyncEnd, args, {
id: id
});
},
instant: function(cat, name) {
var scope =
arguments.length > 2 && arguments[2] !== undefined
? arguments[2]
: 't';
var args = arguments.length > 3 ? arguments[3] : undefined;
this._addEvent(cat, name, Phase.Instant, args, {
s: scope
});
},
id: function() {
return '0x' + convertBase(id++, 10, 16);
},
_addEvent: function(cat, name, ph) {
var args =
arguments.length > 3 && arguments[3] !== undefined
? arguments[3]
: {};
var extra =
arguments.length > 4 && arguments[4] !== undefined
? arguments[4]
: {};
if (!this._trace) {
return;
}
var targetCat = this._targetCat;
if (!isEmpty(targetCat)) {
var catArr = processCat(cat);
if (isEmpty(intersect(catArr, targetCat))) {
return;
}
}
var event = extend(
{
name: name,
cat: cat,
ph: ph,
ts: this._getCurTs(),
pid: this._pid,
tid: this._tid,
args: args
},
extra
);
this._trace.addEvent(event);
},
_getCurTs: function() {
return Math.round(perfNow() * 1000);
}
});
var Phase = {
Begin: 'B',
End: 'E',
Complete: 'X',
Instant: 'I',
NestableAsyncBegin: 'b',
NestableAsyncEnd: 'e',
Metadata: 'M'
};
function processCat(cat) {
cat = trim(cat);
if (cat === '') {
return [];
}
return map(cat.split(','), trim);
}
module.exports = exports;