forked from getsentry/raven-node
/
utils.js
146 lines (132 loc) · 4.92 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
var raven = require('./client'),
crypto = require('crypto'),
fs = require('fs'),
url = require('url'),
// this makes me feel dirty. :(
readInstalled = require(__dirname+'/../node_modules/npm/lib/utils/read-installed.js');
module.exports.constructChecksum = function constructChecksum(kwargs) {
var checksum = crypto.createHash('md5');
checksum.update(kwargs['message'] || '');
return checksum.digest('hex');
};
module.exports.getSignature = function getSignature(key, message, timestamp) {
var hmac = crypto.createHmac('sha1', key);
hmac.update(timestamp+' '+message);
return hmac.digest('hex');
};
module.exports.getAuthHeader = function getAuthHeader(signature, timestamp, api_key, project_id) {
var header = ['Sentry sentry_version=2.0'];
header.push('sentry_signature='+signature);
header.push('sentry_timestamp='+timestamp);
header.push('sentry_client=raven-node/'+raven.version);
header.push('sentry_key='+api_key);
header.push('project_id='+project_id);
return header.join(', ');
};
module.exports.parseDSN = function parseDSN(dsn) {
try {
var parsed = url.parse(dsn),
response = {
protocol: parsed.protocol.slice(0, -1),
public_key: parsed.auth.split(':')[0],
private_key: parsed.auth.split(':')[1],
host: parsed.host
};
var path = parsed.path.substr(1),
index = path.lastIndexOf('/');
response.path = path.substr(0, index);
response.project_id = ~~path.substr(index+1);
return response;
} catch(e) {
throw new Error('Invalid Sentry DSN: ' + dsn);
}
};
var module_cache = false;
module.exports.getModules = function getModules(callback) {
if(module_cache) {
return callback(module_cache);
}
readInstalled('.', function(err, list) {
if (err) {
// uh oh, ignore silently
return callback({});
}
module_cache = {};
for(var module in list.dependencies) {
var m = list.dependencies[module];
module_cache[m.name] = m.version;
}
cb(module_cache);
});
};
module.exports.getModules = function(){ return module_cache; };
var LINES_OF_CONTEXT = 7;
/*
* Testing out with a custom stack track.
* (Not done)
*/
module.exports.parseStackBetter = function parseStackBetter(err, callback) {
var orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack){ return stack; };
//Error.captureStackTrace(err);
var lines = err.stack;
Error.prepareStackTrace = orig;
lines.forEach(function(line, index){
var frame = {
function: line.getFunctionName(),
filename: line.getFileName(),
lineno: line.getLineNumber(),
typename: line.getTypeName()
};
if(line.getFunctionName() !== 'handle_request1') return;
console.log(line.getFunction().arguments);
if(line.fun && line.fun.arguments) {
frame.args = [];
for(var i=0, j=line.fun.arguments.length; i<j; i++) {
frame.args.push(line.fun.arguments[i]);
}
}
console.log(frame);
});
};
module.exports.parseStack = function parseStack(stack, callback) {
// grab all lines except the first
var lines = stack.split('\n').slice(1), callbacks=lines.length, frames=[], cache={};
lines.forEach(function(line, index) {
var data = line.match(/^\s*at (?:(.+?) )?\(?(.+?)(?::(\d+):(\d+))?\)?$/).slice(1),
frame = {
filename: data[1],
lineno: ~~data[2]
};
// only set the function key if it exists
if(data[0]) {
frame['function'] = data[0];
}
// internal Node files are not full path names. Ignore them.
if(frame.filename[0] === '/' || frame.filename[0] === '.') {
// check if it has been read in first
if(frame.filename in cache) {
parseLines(cache[frame.filename]);
if(--callbacks === 0) callback(null, frames);
} else {
fs.readFile(frame.filename, function(err, file) {
if(!err) {
file = file.toString().split('\n');
cache[frame.filename] = file;
parseLines(file);
}
frames[index] = frame;
if(--callbacks === 0) callback(null, frames);
});
}
} else {
frames[index] = frame;
if(--callbacks === 0) callback(null, frames);
}
function parseLines(lines) {
frame.pre_context = lines.slice(Math.max(0, frame.lineno-(LINES_OF_CONTEXT+1)), frame.lineno-1);
frame.context_line = lines[frame.lineno-1];
frame.post_context = lines.slice(frame.lineno, frame.lineno+LINES_OF_CONTEXT);
}
});
};