Giter Club home page Giter Club logo

longjohn's Introduction

longjohn

Long stack traces for node.js with configurable call trace length

Inspiration

I wrote this while trying to add long-stack-traces to my server and realizing that there were issues with support of EventEmitter::removeListener. The node HTTP Server will begin to leak callbacks and any of your own code that relies on removing listeners would not work as anticipated.

So what to do... I stole the code and rewrote it. I've added support for removeListener along with the ability to cut off the number of async calls the library will trace. I hope you like it!

Please thank tlrobinson for the initial implementation!

Production Use

Longjohn collects a large amount of data in order to provide useful stack traces. While it is very helpful in development and testing environments, it is not recommended to use longjohn in production. The data collection puts a lot of strain on V8's garbage collector and can greatly slow down heavily-loaded applications.

Installation

Just npm install it!

$ npm install longjohn

Usage

To use longjohn, require it in your code (probably in some initialization code). That's all!

if (process.env.NODE_ENV !== 'production'){
  require('longjohn');
}

// ... your code

Options

Limit traced async calls

longjohn.async_trace_limit = 5;   // defaults to 10
longjohn.async_trace_limit = -1;  // unlimited

Change callback frame text

longjohn.empty_frame = 'ASYNC CALLBACK';  // defaults to '---------------------------------------------'

Use with Source Maps

As of version 0.2.9 longjonn supports source maps. Just compile your code down to javascript with source map support and run like normal.

For coffee-script, this would look like:

$ coffee --map --compile script.coffee

longjohn's People

Contributors

alloy avatar caleyd avatar carter-thaxton avatar drauggres avatar mattinsler avatar mbertoglio avatar pdehaan avatar ssafejava avatar trindaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

longjohn's Issues

Original call to async.series cannot be traced

longjohn is awesome, but for some reason, it can't quite finish the job of tracing from one of the various steps in an async.series call (using the well-known async npm module) all the way back up to the place where async.series was invoked.

I have put together a simple test showing that the trace reaches a line of code in async.series itself, where it invokes async.mapSeries, but never rises above that to the application code that actually invoked async.series.

I am scratching my head here because I don't see where anything fancy is happening up to that point in the async.series code that would make it tough to retain the rest of the stack trace above that point.

I would love some insight as to what keeps longjohn from reporting the whole story.

Thanks!

https://github.com/boutell/longjohn-async-test

res.json(err) causes "Converting circular structure to JSON"

In my app I am json-sending errors to the client for some development environments so that these become visible on the browser.

I understand that longjohn is adding circular stuff to the default error instances. And so, Express' res.json cannot deal with these error instances anymore.

So, do you have any tricks or an advice for that?

Huge CPU usage

I have used Node.js (0.10.33) quite long time with 'longjohn' in the clustered application. No any bad affect of 'longjohn' was detected there. The application worked stable and used about 20% of CPU time.
Recently I have updated my Nodejs engine up to latest version (0.12.5) and correspondingly did update for all dependencies. The 'longjonh' was updated to 0.2.7 version. But, unfortunately, after restart my application began to eat up to 95-100% of CPU time. The commenting of 'var longjohn = require('longjohn');' fixed the situation and now it's using no more than 20% of CPU time.
Can you please explain what is happening? Is it my fault? Or there is some bug?

Broken on v0.11.0

Getting an error at the end of a program when using longjohn (0.2.0):

require( 'longjohn' );

console.log( 'Start' );
setTimeout(function(){
    console.log( 'Timeout' );
}, 1000);
corey@corey-mac:~/git/lj$ node test.js
Start
Timeout

/Users/corey/git/lj/node_modules/longjohn/dist/longjohn.js:181
        throw e;
              ^
TypeError: Function.prototype.apply: Arguments list has wrong type
    at Function.prepareStackTrace (/Users/corey/git/lj/node_modules/longjohn/dist/longjohn.js:123:48)
    at new Error (<anonymous>)
    at wrap_callback (/Users/corey/git/lj/node_modules/longjohn/dist/longjohn.js:167:19)
    at process.nextTick (/Users/corey/git/lj/node_modules/longjohn/dist/longjohn.js:257:15)
    at onwrite (_stream_writable.js:249:15)
    at WritableState.onwrite (_stream_writable.js:92:5)
    at WriteStream.Socket._write (net.js:634:5)
    at doWrite (_stream_writable.js:211:10)
    at writeOrBuffer (_stream_writable.js:201:5)
    at WriteStream.Writable.write (_stream_writable.js:172:11)

0.2.5 Invalid array length

An example stack trace:

"RangeError: Invalid array length",
"    at onwrite (_stream_writable.js:265:15)",
"    at WritableState.onwrite (_stream_writable.js:96:5)",
"    at Socket._write (net.js:653:5)",
"    at doWrite (_stream_writable.js:225:10)",
"    at writeOrBuffer (_stream_writable.js:215:5)",
"    at Writable.write (_stream_writable.js:182:11)",
"    at Socket.write (net.js:615:40)",

But these came up from a few other places too. We solved the problem by reverting to 0.2.2

CHANGELOG

Hi,

Is there any changelog of this project? It would be awesome if we could read a changelog instead of git diffing or using github compare...
(just a suggestion of an enhancement).

longjohn is not compatible to other modules using a similar wrapping of EventEmitter

The way how longjohn wraps EventEmitter is incompatible with other modules doing a similar/same wrapping.
I tested by creating a clone of longjohn (incl. modifiny the 'longjohn' property of on()) and used it together with unmodified longjohn in following script:

require('longjohn');

var assert = require('assert');
var EventEmitter = require('events').EventEmitter;

function onListener() {}
function onceListener() {}

function test() {
    var emitter = new EventEmitter;
    emitter.on('xxx', onListener);
    emitter.once('xxx', onceListener);
    assert.equal(emitter.listenerCount('xxx'), 2);

    emitter.removeListener('xxx', onListener);
    // fails on second call as onListener was not removed
    assert.equal(emitter.listenerCount('xxx'), 1);

    emitter.removeListener('xxx', onceListener);
    assert.equal(emitter.listenerCount('xxx'), 0);
}

test();

require('longjohn-clone');

test();

Formatting lost on io.js

On io.js with longjohn, I see this output in my app:

Console.trace (console.js:80:17),/home/michael-heuberger/binarykitchen/code/videomail.io/src/server.js:130:25,LevelUP.<anonymous> (/home/michael-heuberger/binarykitchen/code/videomail.io/src/db/level/driver.js:29:23),emitNone (events.js:67:13),LevelUP.emit (events.js:163:7),/home/michael-heuberger/binarykitchen/code/videomail.io/node_modules/level/node_modules/level-packager/node_modules/levelup/lib/levelup.js:122:12

Line breaks are lost, gone.

Whenever I comment out longjohn, then all is formatted nicely:

Trace: [Error: ignore me]
    at /home/michael-heuberger/binarykitchen/code/videomail.io/src/server.js:130:25
    at LevelUP.<anonymous> (/home/michael-heuberger/binarykitchen/code/videomail.io/src/db/level/driver.js:29:23)
    at emitNone (events.js:67:13)
    at LevelUP.emit (events.js:163:7)
    at /home/michael-heuberger/binarykitchen/code/videomail.io/node_modules/level/node_modules/level-packager/node_modules/levelup/lib/levelup.js:122:12

No long stacktrace printed on ECONNRESET

^C
/home/michael.heuberger/binarykitchen/code/videomail.io/node_modules/longjohn/dist/longjohn.js:185
        throw e;
              ^
Error: read ECONNRESET
  at errnoException (net.js:904:11)
  at Pipe.onread (net.js:558:19)

Why isn't longjohn printing a long stack trace here with all the callbacks?

I placed require('longjohn'); on the top of my gulp file ...

util.isFunction not available in older versions of Node

Noticed that the latest release (0.2.10) is using util.isFunction in the code. Problem is that if you are running Node 0.10.x, this function is not available in the util package.

Seems like this latest version is not a backwards-compatible patch and should be a major version. Also, the node engine attribute in package.json should be bumped up to note that Longjohn will only work when running Node > 4.x. (I don't think util.isFunction was added until 4.x).

Not getting full stack trace

Hi,
I am using node-gcm module.
I have enable longjohn. But I am not getting full stack trace
Stacktrace look like

..................
[8] => at g (events.js:175:14)
[9] => at EventEmitter.emit (events.js:95:17)
[10] => at parserOnIncomingClient (http.js:1663:21)
[11] => at parserOnHeadersComplete (http.js:122:23)
[12] => at socketOnData (http.js:1556:20)
)

What could be the issue ?

[question] Advantages over `Error.stackTraceLimit`

Hi, simple question—what does this library do that setting Error.stackTraceLimit= <number greater than 10, the default> does not?

A cursory Internet search suggests that Longjohn collects async stack traces whereas Error.stackTraceLimit does not, but here is an example of Error.stackTraceLimit theoretically collecting stack traces across fiber calls, which are asynchronous.

Also do you know if perhaps Error.stackTraceLimit is more suitable for production use than longjohn? (Since we use fibers, so if Error.stackTraceLimit works for that, that would be good even if it didn't work in other circumstances where longjohn did work.)

Doesn't work with promises

All I get is:

    at Promise.resolve.then (/usr/src/app/lib/promises/index.js:61:15)
    at process._tickDomainCallback (internal/process/next_tick.js:129:7)

Is this project still alive?

Throwing exception 'e'

Was getting the below error --

/node_modules/longjohn/dist/longjohn.js:185
throw e;
^
Fixed it by commenting out line 185 and add a console.log

// throw e;
console.log(e.stack);

Doesn't work with node 0.12.

Test script:

var longjohn = require('longjohn');
longjohn.async_trace_limit = -1;

function timeoutHandler() {
  console.log('timeout fired!');
  throw new Error('EXPLODE');
}

function createTimeout() {
  setTimeout(timeoutHandler, 1000);
}

createTimeout();

Results:

image

image

Original removeListener is not executed

In this code:

var longjohn = require('longjohn');
var EventEmitter = require('events').EventEmitter;

var ee = new EventEmitter();

ee.on('removeListener', function(event, listener) {
    console.log('removeListener: ' + event);
});

ee.on('data', function() {
});

ee.removeAllListeners('data');

The removeListener is never executed, while without longjohn it is. Is it expected or a bug?

Thanks!

EventEmitter.listeners() returns different results in case longlohn is used

For events registered via once() the listener() API returns different result if longjohn is used or not.

Reproducer:

var assert = require('assert');
var EventEmitter = require('events').EventEmitter;

function onListener() {}
function onceListener() {}

function test() {
    var eventEmitter = new EventEmitter();

    eventEmitter.on('TheEvent', onListener);
    eventEmitter.once('TheEvent', onceListener);

    var listeners = eventEmitter.listeners('TheEvent');
    assert.equal(listeners[0], onListener);
    assert.equal(listeners[1].listener, onceListener);
    // the following assert passes for longlohn case
    //assert.equal(listeners[1], onceListener); 
}

test();

require('longjohn');

test();

Looks like the longlohn implementation unwraps one level too much in listen() for once listeners.

.once only working if there is an .on call for the same event type

Seeing an issue where .once( 'data' ... ) on a stream will only be hit if there is an .on( 'data'... ) call somewhere on the same eventemitter object.

I've spent an hour or so in the code trying to figure out the issue, but I am stumped. Could you give me any guidance on why a .once() would not be hit unless there's a .on() for the same event type?

Specifically I am seeing this using the node-postgres module with longjohn included. In their connection module, I tracked it down to this:

  // without this, .once below seems inconsistent
  this.stream.on( 'data', function() {
    var nop = 1;
  });

  this.stream.once('data', function(buffer) {
    var responseCode = buffer.toString('utf8');
    if(responseCode != 'S') {
      return self.emit('error', new Error('The server does not support SSL connections'));
    }
    var tls = require('tls');
    self.stream = tls.connect({
      socket: self.stream,
      servername: host,
      rejectUnauthorized: self.ssl.rejectUnauthorized,
      ca: self.ssl.ca,
      pfx: self.ssl.pfx,
      key: self.ssl.key,
      passphrase: self.ssl.passphrase,
      cert: self.ssl.cert,
      NPNProtocols: self.ssl.NPNProtocols
    });
    self.attachListeners(self.stream);
    self.emit('sslconnect');

    self.stream.on('error', function(error){
      self.emit('error', error);
    });
  });

If I don't add the .on( 'data'...) the .once( 'data'... will never be hit while longjohn is loaded.

errors with Timer error

hello,

when i run my script with longjohn, i receive the following

TypeError: Cannot read property 'apply' of undefined
    at Timer.listOnTimeout (timers.js:92:15)
---------------------------------------------
    at JavascriptComputation.computationRegistry._doAdd.local.remote.fn (/Users/cdieringer/node/coinstac-common/test/models/pipeline/runner/pool/.test-pool-utils.js:187:41)
    at JavascriptComputation.run (/Users/cdieringer/node/coinstac-common/src/models/computation/javascript-computation.js:29:10)
    at /Users/cdieringer/node/coinstac-common/src/models/pipeline/pipeline.js:51:26
    at Pipeline.run.Pipeline._handleRunComplete.Pipeline.tryNext.cb [as tryNext] (/Users/cdieringer/node/coinstac-common/src/models/pipeline/pipeline.js:126:32)
    at Pipeline.run.cb.tryNext [as run] (/Users/cdieringer/node/coinstac-common/src/models/pipeline/pipeline.js:48:10)
    at RemotePipelineRunner.run.async.parallel.userResults.RemotePipelineRunner._run.cb [as _run] (/Users/cdieringer/node/coinstac-common/src/models/pipeline/runner/remote-pipeline-runner.js:81:19)
    at /Users/cdieringer/node/coinstac-common/src/models/pipeline/runner/remote-pipeline-runner.js:59:14
    at /Users/cdieringer/node/coinstac-common/node_modules/async/lib/async.js:726:13
    at /Users/cdieringer/node/coinstac-common/node_modules/async/lib/async.js:52:16
    at done (/Users/cdieringer/node/coinstac-common/node_modules/async/lib/async.js:246:17)
    at /Users/cdieringer/node/coinstac-common/node_modules/async/lib/async.js:44:16
    at /Users/cdieringer/node/coinstac-common/node_modules/async/lib/async.js:723:17
    at /Users/cdieringer/node/coinstac-common/node_modules/async/lib/async.js:167:37
    at /Users/cdieringer/node/coinstac-common/src/models/pipeline/runner/pipeline-runner.js:70:19
    at process._tickCallback (node.js:406:9)

i think it's a nodejs internal error? any clue?

thx!

Streaming objects from Mongoose is very slow, and sometimes runs out of memory

Detailed reproduction instructions here:

https://gist.github.com/jwalton/6575901

But basically, if longjohn is present, then trying to stream 40K records from Mongoose will run well, but as you get close to 12K objects (YMMV) things start slowing way, way , way down, and then you start getting objects one or two every ten seconds, and the memory footprint of node on my mac jumps up to 1.5G. In a real production app, I've seen the node VM run out of memory and die.

If you take longjohn out of the equation, then things run a lot faster (including creating objects), everything finishes OK, and the memory footprint never gets up much above 75MB.

Interestingly, if you modify this app like this:

# Line X
cursor = B.collection.collection.find()

and this:

# Line Y
object = new B object

then the program completes successfully regardless of whether you have longjohn enabled or not, which is weird, since you're effectively doing the same thing. There must be something specific about the way Mongoose streams objects that makes this happen.

Memory leak when using longjohn and mongodb with replica sets

I'm trying to use longjohn with (mongodb)[https://github.com/mongodb/node-mongodb-native], but it seems that if you have replica sets configured, and you use the "ping strategy", then node.js will very slowly leak memory if you have longjohn enabled.

I used (memwatch)[https://github.com/lloyd/node-memwatch] to print out the top 10 object types that were growing every 60 seconds. Rather consistently, I was seeing results like this:

15327 - Interval - Top 10 growing heap objects:
  Interval -   Array - 157.3 kb - 842
  Interval -   Closure - 55.97 kb - 796
  Interval -   Object - 6.73 kb - 205
  Interval -   Error - 3.09 kb - 132
  Interval -   Number - 1.02 kb - 65
  Interval -   String - 2.66 kb - 63
  Interval -   Date - 5.16 kb - 55
  Interval -   exports.DbCommand - 4.73 kb - 55
  Interval -   Code - 9.25 kb - 37
  Interval -   PingStrategy._pingServer.pingFunction - 528 bytes - 22
  Interval -   Timer - 288 bytes - 9

DbCommand and PingStrategy are both from mongodb. Using (node-webkit-agent)[https://github.com/c4milo/node-webkit-agent] to poke about in the heap, it seems the pingFunction functions are all referenced, indirectly, from Error objects. The Error object in question (and most of the tens of thousands of Error objects sticking around in memory) all have a "location" member, which points to longjohn created Errors.

If I remove longjohn from my configuration, then my memory leak seems to go away.

If you want to look at the code responsible on the mongodb side, (this is the file)[https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/connection/strategies/ping_strategy.js] that's causing all the trouble.

-Jason

Doesn't work on node v0.9.x/v0.10.x

It most likely has something to do with a V8 API change...

Note that it works with v0.8.21, but both v0.9.9 and v0.9.10 have strange, different results:

☮ ~/cloudup-local (add/unlink-page) ∴ n use 0.8.20 t

timers.js:103
            if (!process.listeners('uncaughtException').length) throw e;
                                                                      ^
Error: uncaught
    at Object.c (/Users/nrajlich/cloudup-local/t.js:15:9)
    at Timer.list.ontimeout [as ontimeout] (timers.js:101:19)
---------------------------------------------
    at Object.b (/Users/nrajlich/cloudup-local/t.js:11:3)
    at Timer.list.ontimeout [as ontimeout] (timers.js:101:19)
---------------------------------------------
    at Object.a (/Users/nrajlich/cloudup-local/t.js:7:3)
    at Timer.list.ontimeout [as ontimeout] (timers.js:101:19)
---------------------------------------------
    at Object.<anonymous> (/Users/nrajlich/cloudup-local/t.js:4:1)
    at Module.Module._compile [as _compile] (module.js:449:26)
    at Object.Module._extensions..js [as .js] (module.js:467:10)
    at Module.Module.load [as load] (module.js:356:32)
    at Function.Module._load [as _load] (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback [as _tickCallback] (node.js:244:9)

☮ ~/cloudup-local (add/unlink-page) ∴ n use 0.9.10 t

Array.filter (native)

☮ ~/cloudup-local (add/unlink-page) ∴ n use 0.9.9 t

CallSiteGetFileName (native),Array.filter (native)

Can LongJohn be disabled after having been required?

I'm writing some tests where I want longjohn on and others when it should be off. I could just run the non long john tests first, but it'd be nice to just be able to turn it on and off depending on the sub test suite.

Is there a way?

Thanks in advance,
Francois

wrong stacktrace

I am getting a wrong stacktrace with the following code. It is showing setTimeout getting called from the firstfunction, but in real the program is crashing before firstfunction is getting executed.

 var longjohn = require("longjohn");

setTimeout(function () {
    throw new Error();
}, 10);


setTimeout(function () {
    firstfunction();
}, 10000);


var firstfunction = function () {
    setTimeout(function () {
        console.log("First function");
    }, 10);
}

Stacktrace

/home/jeevan/node_js/node_modules/longjohn/dist/longjohn.js:181
        throw e;
              ^
Error
    at firstfunction (/home/jeevan/node_js/longjohn.js:11:11)
    at listOnTimeout (timers.js:110:15)
---------------------------------------------
    at Object.<anonymous> (/home/jeevan/node_js/longjohn.js:10:1)
    at Module._compile (module.js:456:26)
    at Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Module._load (module.js:312:12)
    at Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3

Mongo database connection timeout with 0.2.10

Hi,

with longjohn 0.2.10, this code doesn't work anymore, i.e the callback is never called. Works fine with 0.2.9.

var mongo = require('mongodb');
var longjohn = require('longjohn');

console.log("Connecting...");
mongo.connect("mongodb://127.0.0.1:27017/dev", function (err, db) {
  if (err) {
    console.log(err);
  }
  console.log("We are connected");
});

Environment:

  • Mac OSX El capitan,
  • Node 4.1.1 (also reproduced with 4.2.2)
  • "mongodb": "^1.4.39"
  • Mongo 3.0.3 (also reproduced with 2.06)

thanks,

Longjohn breaking jasmine tests (possibly because of changed exception handling?)

We had some problems with our jasmine tests. When we called a failing test, that thrown an exception from inside a promise, Jasmine reported No specs found and exited (note that the specs were found and already running at this time). After we removed longjohn from the tests, they started running just fine, reporting the correct results.

Invalid Array length error with 0.2.6

We have a series of node modules that depend on latest version of longjohn (which currently points to 0.2.6). Our node modules are distributed to our customers and [email protected] errors out with

RangeError: Invalid array length
at onwrite (_stream_writable.js:266:15)
at WritableState.onwrite (_stream_writable.js:97:5)
at Socket._write (net.js:654:5)
at doWrite (_stream_writable.js:226:10)
at writeOrBuffer (_stream_writable.js:216:5)
at Writable.write (_stream_writable.js:183:11)
at Socket.write (net.js:616:40)
at Console.log (console.js:54:16)

We narrowed down the problem with [email protected] module, and published PR. It would be great if you can include the fix for this and publish a new version.

Interoperability with Traceur call stacks

Example: https://gist.github.com/OliverJAsh/fd98c53b62eaa32f5e56

Without longjohn:

❯ node traceur-runner.js main.js

/Users/Oliver/Development/tmp/traceur-longjohn/<compileSource>:5
var bar = () => { throw new Error('foo'); };
                        ^
Error: foo
    at bar (/Users/Oliver/Development/tmp/traceur-longjohn/<compileSource>:5:25)
    at [object Object].foo [as _onTimeout] (/Users/Oliver/Development/tmp/traceur-longjohn/<compileSource>:7:67)
    at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)

With longjohn:

❯ node traceur-runner.js main.js
Error: foo
    at bar (/Users/Oliver/Development/tmp/traceur-longjohn/main.js:5:9)
    at foo (/Users/Oliver/Development/tmp/traceur-longjohn/main.js:10:22)
    at listOnTimeout (timers.js:112:15)
---------------------------------------------
    at foo (/Users/Oliver/Development/tmp/traceur-longjohn/main.js:9:12)
    at new Promise (eval at eval at <anonymous> (/Users/Oliver/Development/tmp/traceur-longjohn/node_modules/traceur/src/node/traceur.js:24:17))
    at foo (/Users/Oliver/Development/tmp/traceur-longjohn/main.js:8:10)
    at Object.<anonymous> (/Users/Oliver/Development/tmp/traceur-longjohn/main.js:14:1)
    at Module._compile (module.js:456:26)
    at Module._extensions..js (/Users/Oliver/Development/tmp/traceur-longjohn/node_modules/traceur/src/node/require.js:65:21)
    at Module.load (module.js:356:32)
    at Module._load (module.js:312:12)

When longjohn is enabled, the generated call stack does not respect Traceur’s call stack, which is resolved against the source maps using by traceur-source-maps. Notice how the first few lines of the longjohn call stack do not match the mappings of the original.

What is the happy path to using longjohn with Traceur? Is this something we can fix?

Longjohn causes TLS error handler to be triggered

I have found a strange issue when using longjohn with TLS. Normally, when I kill the server, the error handler on the client TLS is not fired. If I require longjohn in the client code, killing the server does cause the error handler to be fired.

Here is an example:

client.js

'use strict';

var longjohn = require('longjohn');

var tls = require('tls');

var tlsConnection = tls.connect({
  host: 'localhost',
  port: 8099,
  rejectUnauthorized: false
});

tlsConnection.on('error', function(error) {
  console.log('there was an error');
  console.log(error.stack);
});

tlsConnection.on('data', function(data) {
  console.log('we got some data');
  console.log(data.toString('utf8'));
});

and server.js (this is almost an exact copy of the example at https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener)

'use strict';

var tls = require('tls');
var fs = require('fs');

var tlsOptions = {
  key: fs.readFileSync('/path/to/key'),
  cert: fs.readFileSync('/path/to/cert')
};

var server = tls.createServer(tlsOptions, function(socket) {
  socket.write('hello world');
  socket.setEncoding('utf8');
  socket.pipe(socket);
});

server.listen(8099, function() {
  console.log('server bound');
});

first I start the server

$ node ./server.js
    server bound

then start the client

$ node client.js
    we got some data
    hello world

Then I kill the server with ctrl-c, and the client logs out

there was an error
Error: socket hang up
    at TLSSocket.onHangUp (_tls_wrap.js:1032:19)
    at TLSSocket.g (events.js:260:16)
    at emitNone (events.js:72:20)
    at TLSSocket.emit (events.js:166:7)
    at endReadableNT (_stream_readable.js:903:12)
    at doNTCallback2 (node.js:439:9)
    at process._tickCallback (node.js:353:17)
---------------------------------------------
    at TLSSocket.Readable.on (_stream_readable.js:665:33)
    at Object.<anonymous> (/home/gabe/workspace/longjohnTest/client.js:13:15)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:134:18)
    at node.js:961:3

If I go back and comment out the

var longjohn = require('longjohn');

line in the client code, the error handler never gets fired when I kill the server.

I have tested this on node v0.12.1 and v4.2.0

Using with TypeScript?

I'm using TypeScript and would like to use longjohn conditionally just in dev mode. Documentation suggests using conditional require:

if (process.env.NODE_ENV !== 'production'){
  require('longjohn');
}

However, TypeScript imports are restricted to top-level, making it impossible to do such conditional check without falling back to commonJS-style require.

There is also a related issue: #61 - having the ability to disable longjohn after require would be a sufficient fix.

Getting at the raw trace

Is there an easy way to get to the raw stack trace with longjohn? I have a generic exception handler that when called performs a new Error() to get to the trace. It would be nice if it didn't report itself in the results. Also as I'm recording these to a MongoDB I would rather write the JSONified trace than the stringified trace.

It would be even better if longjohn had some type of currentStack instead of having to do a new Error every time you need the trace details.

Even a starting point on what to modify/change would be great. I'd gladly do the pull request.

Thanks,

  • Jeremy

Stack Overflow with mongoose only when using Longjohn

I get a stack_overflow error when using longjohn when performing a save with mongoose.
If I don't require longjohn everything is working as expected.

Any idea how to work around or fix it?

Ignore this issue... It was caused by something else...

Issues with gunzip

Hello,

At work we are using longjohn together with our own async library, which works wonders,
only recently we began parsing gzipped files.

The issue is that when using longjohn that the gunzip of the zlib core module virtually stops responding.
We have tested and it responds after a few hours.

I will include the code that will give this issue:

var zlib = require('zlib'),
    request = require('request'),
    longjohn = require('longjohn');

request({ url: 'http://www.jaap.nl/sitemaps/sitemap1.xml.gz', encoding: null }, function(error, response, body) {
  if(response.statusCode === 200) {
    zlib.gunzip(body, function (err, data) {
      console.log(data); // This callback is never executed.
    });
  }
});

When removing the require of longjohn the callback is called without any issue.

I hope this issue can be fixed.

Kind regards and Thanks in advance,

Jasper van Rijbroek

warn when NODE_ENV=production

we were using this module in production, we thought the tradeoff would be reasonable but it causes v8's GC to go nuts and use ~50-60% cpu when a realistic load is applied, without longjohn we use around 3-4%. Warning will probably save a lot of people the same trouble in the future

Use Hookit

Currently there is a memory leak in longjohn because it does not properly shim EventEmitter.removeListener[1]. (See the issues linked in this long-stack-traces issue[2] and also this longjohn issue[3]). Instead of the many libraries like trycatch, longjohn and long-stack-traces implementing their shim layers separately, we should all work together on a common shimming layer.

hookit[4] allows us to share these fixes and benefit together.

[1] https://github.com/CrabDude/trycatch/blob/master/test/event-emitter.test.js#L80-L95
[2] tlrobinson/long-stack-traces#9 (comment)
[3] #3
[4] https://github.com/CrabDude/hookit

Cassé on io.js 1.0.X

Longjohn stopped working on io.js 1.0.X, couldn't investigate any further right now, but we removed longjohn from the dev environment for the time being.

**/node_modules/longjohn/dist/longjohn.js:185
        throw e;
              ^
ChildProcess.emit (events.js:101:17),
maybeClose (child_process.js:979:16),
Socket.<anonymous> (child_process.js:1147:11),
Socket.emit (events.js:98:17),
Pipe.close (net.js:456:12)

Any idea?

Asynchronously / lazily accessed err.stack is wrong

Since stack trace generation is tied to Error.prepareStackTrace, lazily (asynchronously) accessing err.stack causes it be wrong and include both an additional (shouldn't be there) and out of order stack:

require('longjohn')

setTimeout(function() {
  setTimeout(function() {
    var err =new Error('asdf')
    setTimeout(function() {
      console.log(err.stack)
    })
  })
})
Error: asdf
    at [object Object].<anonymous> (/private/tmp/index.js:5:14)
    at listOnTimeout (timers.js:89:15)
---------------------------------------------
    at [object Object].<anonymous> (/private/tmp/index.js:6:5)
    at listOnTimeout (timers.js:89:15)
---------------------------------------------
    at [object Object].<anonymous> (/private/tmp/index.js:4:3)
    at listOnTimeout (timers.js:89:15)
---------------------------------------------
    at Object.<anonymous> (/private/tmp/index.js:3:1)
    at Module._compile (module.js:430:26)
    at Module._extensions..js (module.js:448:10)
    at Module.load (module.js:355:32)
    at Module._load (module.js:310:12)
    at Module.runMain (module.js:471:10)
    at startup (node.js:117:18)
    at node.js:951:3

Note /private/tmp/index.js:6:5 and the line after it, should not be included.

Strange behavior when loaded twice

Say you have project A, which has a require('longjohn') line in it,
and you also have a project B which is unit tests for A and some other things, and also requires longjohn. The two do not interact well (see stack trace below).

Workarounds:

  • Comment out one or the other's use of longjohn
  • Make one's node_modules/longjohn a symlink to the other's

but neither will work in the case that it's a dependency of a third-party dependency.

Error: TypeError: Cannot call method 'emit' of null
TypeError: Cannot call method 'emit' of null
at Socket.onServerResponseClose (http.js:906:21)
at Socket.new_callback (/home/tim/work/abcd/incubator/xyzserver/node_modules/longjohn/index.js:107:16)
at Socket.EventEmitter.emit (events.js:115:20)
at Socket.vows.describe.options.Emitter.emit as emit
at Socket._destroy.destroyed (net.js:358:10)
at new_callback (/home/tim/work/abcd/incubator/xyzserver/node_modules/longjohn/index.js:107:16)
at process.startup.processNextTick.process._tickCallback as _tickCallback

at process.startup.processMakeCallback.process._makeCallback as _makeCallback

at ServerResponse.ServerResponse.assignSocket [as assignSocket] (http.js:912:10)
at HTTPParser.parser.onIncoming (http.js:1748:11)
at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:111:23)
at Socket.socket.ondata (http.js:1682:22)
at TCP.onread (net.js:404:27)
at process.startup.processMakeCallback.process._makeCallback [as _makeCallback] (node.js:238:20)

No limit on serialization of error

Every so often, we'll run into an error that longjohn tries to serialize, and in attempting to do so will peg the CPU and gobble up RAM (like 1+GB).

It seems like it attempts to serialize our entire application in a single Object graph...

uncaughtException: { [Error: Invalid timestamp. Please provide timezone as fallback]
  __cached_trace__: 
   [ { receiver: 
        { localTime: [Function],
          humanizeDuration: [Function] },
       fun: [Function],
       pos: 401 },
     { receiver: undefined,
       fun: [Function: grouper],
       pos: 4432 },
     { receiver: 
        { ArrayBuffer: [Function: ArrayBuffer],
          Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
          Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
          Uint8ClampedArray: { [Function: Uint8ClampedArray] BYTES_PER_ELEMENT: 1 },
          Int16Array: { [Function: Int16Array] BYTES_PER_ELEMENT: 2 },
          Uint16Array: { [Function: Uint16Array] BYTES_PER_ELEMENT: 2 },
          Int32Array: { [Function: Int32Array] BYTES_PER_ELEMENT: 4 },
          Uint32Array: { [Function: Uint32Array] BYTES_PER_ELEMENT: 4 },
          Float32Array: { [Function: Float32Array] BYTES_PER_ELEMENT: 4 },
          Float64Array: { [Function: Float64Array] BYTES_PER_ELEMENT: 8 },
          DataView: [Function: DataView],
          global: [Circular],
          process: 
           { title: 'node',
             version: 'v0.8.21',
             moduleLoadList: 
              [ 'Binding evals',
                'Binding natives',
                'NativeModule events',
                'NativeModule buffer',
                'Binding buffer',
                'NativeModule assert',
                // several thousands of additional lines omitted ...

It might be worth using util's inspect to mitigate this.

Q seems to truncate the stack trace

The call stack ends with Q - anything that called the promise doesn't appear in the call stack.

    at callback (/server/node_modules/q/q.js:1398:37)
    at makePromise.makePromise.fapply (/server/node_modules/q/q.js:745:27)
    at makePromise.promise.promiseSend [as promiseSend] (/server/node_modules/q/q.js:546:41)
    at exports.dispatcher (/server/node_modules/q/q.js:1036:28)

Does not remove listener from event emitter instance when using `once` to bind it

The following will throw

var EventEmitter = require('events').EventEmitter;
require('longjohn');


var ee = new EventEmitter();

function listener() {
  throw new Error('should not be called');
}

ee.once('foo', listener);
ee.removeListener('foo', listener);
ee.emit('foo');

console.log('success!');

Changing ee.once() to ee.on() works.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.