Skip to content

Commit d9b35df

Browse files
author
Guilherme Oenning
committed
finished pg provider and some other fixes
1 parent 61b1766 commit d9b35df

File tree

16 files changed

+336
-90
lines changed

16 files changed

+336
-90
lines changed

lib/miniprofiler.js

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ var popupRenderPosition = 'left';
2727

2828
// EXPORTS
2929
exports.configure = configure;
30+
configure();
3031

3132
for (let framework of ['koa', 'express', 'hapi']) {
3233
let func = require(`./middlewares/${framework}.js`);
@@ -174,8 +175,6 @@ function results(req, res, lastPathSegment, done) {
174175
var body = '';
175176
req.on('data', function(data) {
176177
body += data;
177-
if (body.length > 1e6)
178-
req.connection.destroy();
179178
});
180179

181180
req.on('end', function() {
@@ -222,13 +221,12 @@ function include(id) {
222221
*/
223222
function configure(options){
224223
options = options || {};
225-
if(options) {
226-
storage = options.storage || storage;
227-
ignoredPaths = options.ignoredPaths || ignoredPaths;
228-
trivialDurationThresholdMilliseconds = options.trivialDurationThresholdMilliseconds || trivialDurationThresholdMilliseconds;
229-
popupShowTimeWithChildren = options.popupShowTimeWithChildren || popupShowTimeWithChildren;
230-
popupRenderPosition = options.popupRenderPosition || popupRenderPosition;
231-
}
224+
225+
storage = options.storage || storage;
226+
ignoredPaths = options.ignoredPaths || ignoredPaths;
227+
trivialDurationThresholdMilliseconds = options.trivialDurationThresholdMilliseconds || trivialDurationThresholdMilliseconds;
228+
popupShowTimeWithChildren = options.popupShowTimeWithChildren || popupShowTimeWithChildren;
229+
popupRenderPosition = options.popupRenderPosition || popupRenderPosition;
232230
}
233231

234232
/*
@@ -249,6 +247,7 @@ function startProfiling(request, enabled) {
249247
currentRequestExtension.customTimings = {};
250248
debug(`Profiling started for ${path} with id ${currentRequestExtension.id}`);
251249
}
250+
252251
currentRequestExtension.timeQuery = function() {
253252
var args = Array.prototype.slice.call(arguments, enabled ? 0 : 3);
254253
if (enabled) {
@@ -258,6 +257,15 @@ function startProfiling(request, enabled) {
258257
arguments[2].apply(this, args);
259258
}
260259
};
260+
261+
currentRequestExtension.startTimeQuery = function(type, query) {
262+
return startTimeQuery.call(this, currentRequestExtension, type, query);
263+
};
264+
265+
currentRequestExtension.stopTimeQuery = function(timing) {
266+
return stopTimeQuery.call(this, timing);
267+
};
268+
261269
currentRequestExtension.step = function(name, call) {
262270
//var args = Array.prototype.slice.call(arguments, enabled ? 0 : 2);
263271
if (enabled) {
@@ -266,6 +274,7 @@ function startProfiling(request, enabled) {
266274
call();
267275
}
268276
};
277+
269278
currentRequestExtension.include = function() {
270279
return enabled ? include(currentRequestExtension.id) : '';
271280
};
@@ -283,9 +292,14 @@ function stopProfiling(request){
283292
var extension = request.miniprofiler;
284293
var time = process.hrtime();
285294
debug(`Profiling stopped for ${path} with id ${extension.id}`);
286-
if(extension.stepGraph.parent != null){
287-
throw new Error('profiling ended while still in a function, was left in ['+extension.stepGraph.name+']');
288-
}
295+
296+
/*
297+
* Do we still need this?
298+
*
299+
if(extension.stepGraph.parent != null){
300+
throw new Error('profiling ended while still in a function, was left in ['+extension.stepGraph.name+']');
301+
}
302+
*/
289303

290304
extension.stopTime = time;
291305
extension.stepGraph.stopTime = time;
@@ -340,13 +354,35 @@ function step(name, request, call) {
340354
* to have ended the query.
341355
*/
342356
function timeQuery(extension, type, query, executeFunction) {
343-
debug(`Started timed query "${type}" with command "${query}"`);
357+
var timing = startTimeQuery(extension, type, query);
358+
var params = Array.prototype.slice.call(arguments, 4);
359+
360+
for(var i = 0; i < params.length; i++){
361+
if(_.isFunction(params[i])){
362+
var param = params[i];
363+
params[i] = function() {
364+
debug(`Stopped timed query "${type}" with command "${query}"`);
365+
extension.stopTimeQuery(timing);
366+
var ret = param.apply(this, arguments);
367+
return ret;
368+
};
369+
}
370+
}
371+
372+
var ret = executeFunction.apply(this, params);
373+
return ret;
374+
}
375+
376+
function stopTimeQuery(timing) {
377+
timing.stopTime = process.hrtime();
378+
}
379+
380+
function startTimeQuery(extension, type, query) {
381+
debug(`Started timed query "${type}" with command "${query}"`);
344382

345383
var time = process.hrtime();
346384
var startDate = Date.now();
347385

348-
var params = Array.prototype.slice.call(arguments, 4);
349-
350386
extension.stepGraph.customTimings[type] = extension.stepGraph.customTimings[type] || [];
351387

352388
var customTiming = {
@@ -360,31 +396,21 @@ function timeQuery(extension, type, query, executeFunction) {
360396

361397
extension.stepGraph.customTimings[type].push(customTiming);
362398

363-
for(var i = 0; i < params.length; i++){
364-
if(_.isFunction(params[i])){
365-
var param = params[i];
366-
params[i] = function() {
367-
debug(`Stopped timed query "${type}" with command "${query}"`);
368-
customTiming.stopTime = process.hrtime();
369-
var ret = param.apply(this, arguments);
370-
return ret;
371-
};
372-
}
373-
}
374-
375-
var ret = executeFunction.apply(this, params);
376-
377-
return ret;
399+
return customTiming;
378400
}
379401

380402
function unstep(name, request) {
381403
var time = process.hrtime();
382404

383405
var extension = request.miniprofiler;
384406

385-
if(extension.stepGraph.name != name){
386-
throw new Error('profiling stepped out of the wrong function, found ['+name+'] expected ['+extension.stepGraph.name+']');
387-
}
407+
/*
408+
* Do we still need this?
409+
*
410+
if(extension.stepGraph.name != name){
411+
throw new Error('profiling stepped out of the wrong function, found ['+name+'] expected ['+extension.stepGraph.name+']');
412+
}
413+
*/
388414

389415
extension.stepGraph.stopTime = time;
390416

@@ -407,10 +433,14 @@ function describePerformance(root, request) {
407433
}
408434

409435
function diff(start, stop){
436+
/*
437+
* Do we still need this?
438+
*
410439
if (!stop) {
411440
stop = process.hrtime();
412441
debug('missing stop, using', stop);
413442
}
443+
*/
414444
var deltaSecs = stop[0] - start[0];
415445
var deltaNanoSecs = stop[1] - start[1];
416446

lib/providers/miniprofiler.pg.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,17 @@ module.exports = function(pg) {
77
name: 'pg',
88
handler: function(req, res, next) {
99

10-
pg.Client.prototype.query = !req.miniprofiler.enabled ? pgQuery : function(config, values, callback) {
11-
req.miniprofiler.timeQuery('sql', config.toString(), pgQuery.bind(this), config, values, callback);
10+
pg.Client.prototype.query = !req.miniprofiler || !req.miniprofiler.enabled ? pgQuery : function(config, values, callback) {
11+
if (callback) {
12+
req.miniprofiler.timeQuery('sql', config.toString(), pgQuery.bind(this), config, values, callback);
13+
} else {
14+
var timing = req.miniprofiler.startTimeQuery('sql', config.toString());
15+
var query = pgQuery.call(this, config, values, callback);
16+
query.on('end', function() {
17+
req.miniprofiler.stopTimeQuery(timing);
18+
});
19+
return query;
20+
}
1221
};
1322

1423
next();

lib/providers/miniprofiler.redis.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = function(redis) {
88
name: 'redis',
99
handler: function(req, res, next) {
1010

11-
redis.RedisClient.prototype.internal_send_command = !req.miniprofiler.enabled ? redisSendCommand : function(command, args, callback) {
11+
redis.RedisClient.prototype.internal_send_command = !req.miniprofiler || !req.miniprofiler.enabled ? redisSendCommand : function(command, args, callback) {
1212
var query = `${command} ${args.join(', ')}`.trim();
1313
if (this.ready && blacklist.indexOf(command) == -1)
1414
req.miniprofiler.timeQuery('redis', query, redisSendCommand.bind(this), command, args, callback);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
"mocha": "mocha tests/ -c",
1313
"mocha-coverage": "istanbul cover ./node_modules/mocha/bin/_mocha -- tests/ -R spec",
14-
"check-coverage": "istanbul check-coverage --statements 80 --branches 80 --functions 80 --lines 80",
14+
"check-coverage": "istanbul check-coverage --statements 95 --branches 95 --functions 95 --lines 95",
1515
"update-coveralls": "cat coverage/lcov.info | sed s/.usr.src.miniprofiler/./ | node ./node_modules/coveralls/bin/coveralls.js"
1616
},
1717
"repository": {

tests/basic-test.js

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,5 @@ module.exports = function(server) {
2222
});
2323
});
2424

25-
it('Custom timed query should be profiled', function(done) {
26-
server.get('/js-sleep', (err, response) => {
27-
var ids = JSON.parse(response.headers['x-miniprofiler-ids']);
28-
expect(ids).to.have.lengthOf(1);
29-
30-
server.post('/mini-profiler-resources/results/', { id: ids[0], popup: 1 }, (err, response, body) => {
31-
var result = JSON.parse(body);
32-
expect(result.Id).to.equal(ids[0]);
33-
expect(result.Name).to.equal('/js-sleep');
34-
expect(result.DurationMilliseconds).to.be.above(40);
35-
expect(result.Root.Children).to.be.empty;
36-
expect(result.Root.CustomTimings).to.have.property('custom');
37-
expect(result.Root.CustomTimings.custom).to.have.lengthOf(1);
38-
39-
expect(result.Root.CustomTimings.custom[0].ExecuteType).to.be.equal('custom');
40-
expect(result.Root.CustomTimings.custom[0].CommandString).to.be.equal('Sleeping...');
41-
expect(result.Root.CustomTimings.custom[0].DurationMilliseconds).to.be.below(result.DurationMilliseconds);
42-
done();
43-
});
44-
});
45-
46-
});
47-
4825
});
4926
};

tests/provider-pg-test.js

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,30 @@ module.exports = function(server) {
55
before(server.setUp.bind(null, 'default'));
66
after(server.tearDown);
77

8-
it('Should profile postgres SELECT command', function(done) {
9-
server.get('/pg-select', (err, response) => {
10-
var ids = JSON.parse(response.headers['x-miniprofiler-ids']);
11-
expect(ids).to.have.lengthOf(1);
8+
for (let url of ['/pg-select', '/pg-select-event']) {
129

13-
server.post('/mini-profiler-resources/results/', { id: ids[0], popup: 1 }, (err, response, body) => {
14-
var result = JSON.parse(body);
10+
it(`Should profile postgres SELECT command for url '${url}'`, function(done) {
11+
server.get(url, (err, response) => {
12+
var ids = JSON.parse(response.headers['x-miniprofiler-ids']);
13+
expect(ids).to.have.lengthOf(1);
1514

16-
expect(result.Id).to.equal(ids[0]);
17-
expect(result.Name).to.equal('/pg-select');
18-
expect(result.Root.Children).to.be.empty;
19-
expect(result.Root.CustomTimings).to.have.property('sql');
20-
expect(result.Root.CustomTimings.sql).to.have.lengthOf(1);
15+
server.post('/mini-profiler-resources/results/', { id: ids[0], popup: 1 }, (err, response, body) => {
16+
var result = JSON.parse(body);
2117

22-
expect(result.Root.CustomTimings.sql[0].ExecuteType).to.be.equal('sql');
23-
expect(result.Root.CustomTimings.sql[0].CommandString).to.be.equal('SELECT $1::int AS number');
24-
expect(result.Root.CustomTimings.sql[0].DurationMilliseconds).to.be.below(result.DurationMilliseconds);
25-
done();
18+
expect(result.Id).to.equal(ids[0]);
19+
expect(result.Name).to.equal(url);
20+
expect(result.Root.Children).to.be.empty;
21+
expect(result.Root.CustomTimings).to.have.property('sql');
22+
expect(result.Root.CustomTimings.sql).to.have.lengthOf(1);
23+
24+
expect(result.Root.CustomTimings.sql[0].ExecuteType).to.be.equal('sql');
25+
expect(result.Root.CustomTimings.sql[0].CommandString).to.be.equal('SELECT $1::int AS number');
26+
expect(result.Root.CustomTimings.sql[0].DurationMilliseconds).to.be.below(result.DurationMilliseconds);
27+
done();
28+
});
2629
});
2730
});
2831

29-
});
30-
32+
}
3133
});
3234
};

tests/servers/express/default.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,31 @@ app.get('/step-two', (req, res) => {
2929
});
3030
});
3131

32+
app.get('/step-parallel', (req, res) => {
33+
var count = 0;
34+
var finish = () => {
35+
if (++count == 2)
36+
res.send(req.miniprofiler.include());
37+
};
38+
39+
req.miniprofiler.step('Step 1', finish);
40+
req.miniprofiler.step('Step 2', finish);
41+
});
42+
3243
app.get('/js-sleep', function(req, res) {
3344
req.miniprofiler.timeQuery('custom', 'Sleeping...', setTimeout, function() {
3445
res.send(req.miniprofiler.include());
3546
}, 50);
3647
});
3748

49+
app.get('/js-sleep-start-stop', function(req, res) {
50+
var timing = req.miniprofiler.startTimeQuery('custom', 'Sleeping...');
51+
setTimeout(function() {
52+
req.miniprofiler.stopTimeQuery(timing);
53+
res.send(req.miniprofiler.include());
54+
}, 50);
55+
});
56+
3857
app.get('/redis-set-key', function(req, res) {
3958
client.set('key', 'Awesome!', () => {
4059
res.send(req.miniprofiler.include());
@@ -57,4 +76,13 @@ app.get('/pg-select', function(req, res) {
5776
});
5877
});
5978

79+
app.get('/pg-select-event', function(req, res) {
80+
pg.connect(connString, function(err, pgClient, done) {
81+
var query = pgClient.query('SELECT $1::int AS number', ['1']);
82+
query.on('end', function() {
83+
res.send(req.miniprofiler.include());
84+
});
85+
});
86+
});
87+
6088
module.exports = app;

tests/servers/express/unprofiled.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
var miniprofiler = require('../../../lib/miniprofiler.js');
22
var express = require('express');
3+
var redis = require('redis');
4+
var pg = require('pg');
5+
var connString = `postgres://docker:docker@${process.env.PG_PORT_5432_TCP_ADDR}/docker`;
36

47
var app = express();
8+
var client = redis.createClient(6379, process.env.REDIS_PORT_6379_TCP_ADDR);
59

610
var disableMiniProfiler = (req) => {
711
return false;
@@ -17,4 +21,18 @@ app.get('/', (req, res) => {
1721
}, 50);
1822
});
1923

24+
app.get('/pg', (req, res) => {
25+
pg.connect(connString, function(err, pgClient, done) {
26+
pgClient.query('SELECT $1::int AS number', ['1'], function(err, result) {
27+
res.send(req.miniprofiler.include());
28+
});
29+
});
30+
});
31+
32+
app.get('/redis', (req, res) => {
33+
client.set('key', 'Awesome!', () => {
34+
res.send(req.miniprofiler.include());
35+
});
36+
});
37+
2038
module.exports = app;

0 commit comments

Comments
 (0)