Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Automatic breadcrumbs #240

Merged
merged 27 commits into from
Dec 13, 2016
Merged

Automatic breadcrumbs #240

merged 27 commits into from
Dec 13, 2016

Conversation

LewisJEllis
Copy link
Contributor

@LewisJEllis LewisJEllis commented Nov 28, 2016

Usage:

Raven.config(sentryDsn, {
  autoBreadcrumbs: {
    console: true,
    http: true,
    postgres: true
  }
}).install();

Todo:

  • Fix up configuration scheme
  • Become more sure that bad http requests won't explode/loop
  • Ensure that https requests are captured via http instrumentation
  • Don't capture breadcrumbs for our own requests
  • Don't capture breadcrumbs before instrumentation is finished
  • Tests (see Breadcrumb tests #244)

/cc @MaxBittker @benvinegar @mitsuhiko

Copy link
Contributor

@benvinegar benvinegar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Biggest change is that autoBreadcrumbs: true should be possible ("autobreadcrumb all the things"). Which means it needs to safely know what's available and what isn't without user hints.


function wrapPostgres(Raven) {
// Using fill helper here is hard because of `this` binding
var pg = require('pg');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if pg isn't available?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking here was "if you aren't using pg, don't do pg: true in the config", but I guess for the autoBreadcrumbs: true turn-it-all-on option we should just do a try/catch for all of the might-not-exist cases.

function wrapHttp(Raven) {
var http = require('http');
var OrigClientRequest = http.ClientRequest;
var ClientRequest = function (options, cb) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely need good test coverage on this.

registerRejectionHandler(this, cb);
}

if (opts.autoBreadcrumbs) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be able to work like this:

Raven.config('your-dsn', {
  autoBreadcrumbs: true // everything
});

Where in a future version, autoBreadcrumbs: true becomes the default.

@LewisJEllis
Copy link
Contributor Author

Okay, makes sense - I hadn't really thought forward to when "autoBreadcrumbs: true" will be default, but yea, might as well infer/be defensive instead of relying on user explicitness.

@LewisJEllis LewisJEllis force-pushed the breadcrumbs branch 3 times, most recently from c2c5431 to 5e04a30 Compare December 8, 2016 20:44
@LewisJEllis
Copy link
Contributor Author

@benvinegar I think this should be all ready to review; did some basic tests in a PR on top of this one #244.

Copy link
Contributor

@benvinegar benvinegar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fundamentally looks great. Just some quick comments that need addressing (does not necessarily mean code changes).

}
};

function instrument(key, Raven) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably have a test for this too.

},

captureBreadcrumb: function (breadcrumb) {
if (!this.installed) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does installed work like it does in raven-js? (Where you can choose not to "install" raven-js but that really just affects window.onerror and auto instrumentation.)

In other words – do we need this check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a spot where I thought about leaving a comment but didn't; I'll add one. The purpose here is to avoid capturing breadcrumbs halfway through instrumentation when we're not in a context yet. We do a consoleAlert for each instrumentation, so consider if console instrumentation happens first and then http instrumentation. Without this early exit condition we would try to capture a breadcrumb for the http instrumentation's consoleAlert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment.

var currCtx = this.getContext();
if (!currCtx.breadcrumbs) currCtx.breadcrumbs = [];
currCtx.breadcrumbs.push(breadcrumb);
if (currCtx.breadcrumbs.length > this.maxBreadcrumbs) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So maxBreadcrumbs is effectively per context? Is there a concern that someone could have a lot of contexts, and as a result breadcrumbs end up consuming a lot of memory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and in theory that could be a concern but I don't see it being a deal breaker in practice. If we have one context per simultaneous request/open connection, 10k connections, and 10k of breadcrumb data per context, that's still only 100MB, and I think these numbers are a pretty heavy case.

I do think it's worth making sure there's not an inadvertent memory leak, though; I want to make sure references aren't sticking around via any of the automagic stuff that goes on around domains. I'm going to put together a simple soak test of sorts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per our conversation, I'd probably err on recording, say, 30 breadcrumbs per context and allow users to increase it to the max if they really want to. Better safe than sorry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and I added a simple script to check for obvious memory leaks; seems okay.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

# /bin/sh
version=`node -v`
versionMinusV=`echo $version | cut -c 2-`
nodeRoot="node-$versionMinusV"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a Shell scripting style guide @mattrobenolt @JTCunning?

e.g. something like https://google.github.io/styleguide/shell.xml#Naming_Conventions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but this code looks ok to me.

If anything, I'd prefer the last command to be an exec, so:

exec node http.test.js $PWD/$nodeRoot

nodeRoot="node-$versionMinusV"

if [ ! -d $nodeRoot ]; then
url="https://codeload.github.com/nodejs/node/tar.gz/$version"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't really matter, but I don't think the double quotes are necessary here (or below).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true, they're not necessary, but I personally prefer them as well for readability when working with variables.

};
this.maxBreadcrumbs = Math.max(0, Math.min(options.maxBreadcrumbs || 100, 100));
this.autoBreadcrumbs = extend({}, autoBreadcrumbDefaults);
if (typeof options.autoBreadcrumbs !== 'undefined') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little confusing to grep at first glance. Maybe a quick comment:

// autoBreadcrumbs: true // enable all the breadcrumbs
// autoBreadcrumbs: {
//   http: true // enable a single breadcrumb
// }

(Looks good though.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment.

var knownFailures = [
'test-http-pipeline-flood.js',
'test-http-header-response-splitting.js'
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did they fail in all versions? Or just 0.12 and earlier?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pipeline-flood fails on all versions; it relies on argvs in a sort of one-off way to do a parent/child thing for server/client processes, so we're just not invoking it correctly. We could one-off special case it, but I'm not too worried. Response splitting just fails on 4.x. Various other tests fail on 0.10 and 0.12; I didn't try to list them all. The test setup on those older versions is a bit different.

@@ -0,0 +1,11 @@
# /bin/sh
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw bash is generally more widely used. Not a big deal, but you'll likely come across more docs pointing to bash code that may not work with sh.

@LewisJEllis LewisJEllis force-pushed the breadcrumbs branch 2 times, most recently from 401c9ac to e45f57e Compare December 13, 2016 02:07
Copy link
Contributor

@benvinegar benvinegar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the title to drop "WIP"

@LewisJEllis LewisJEllis changed the title Automatic breadcrumbs WIP Automatic breadcrumbs Dec 13, 2016
@LewisJEllis LewisJEllis merged commit 5c9c927 into master Dec 13, 2016
@LewisJEllis LewisJEllis deleted the breadcrumbs branch December 13, 2016 03:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants