Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V7: Breadcrumb refactor #650

Merged
merged 6 commits into from Nov 19, 2019
Merged

V7: Breadcrumb refactor #650

merged 6 commits into from Nov 19, 2019

Conversation

bengourley
Copy link
Contributor

  • Remove individual breadcrumb flags in favour of enabledBreadcrumbTypes option
    The *BreadcrumbsEnabled plugin-specfic options have been removed and breadcrumbs are now controlled by generic list in enabledBreadcrumbTypes.
  • Rename breadcrumb.{ name -> message, metaData -> metadata }
    These fields have been renamed. Note that metaData -> metadata will happen elsewhere in the codebase too but I limited the scope to just breadcrumbs for this PR
  • Update leaveBreadcrumb() type signature to be more explicit
    The metadata object is only allowed to be one level deep in breadcrumbs so the type signature now enforces that

@@ -1,19 +1,19 @@
const { isoDate } = require('./lib/es-utils')

class BugsnagBreadcrumb {
constructor (name = '[anonymous]', metaData = {}, type = 'manual', timestamp = isoDate()) {
constructor (message, metadata, type, timestamp = isoDate()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These default values have been removed in favour of the validation/default values being done in the client.leaveBreadcrumb() method rather than being split between there and here.

// if no name and no metaData, usefulness of this crumb is questionable at best so discard
if (typeof name !== 'string' && !metaData) return
// if no message, discard
if (!message) return
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The spec doesn't allow a breadcrumb without a message, so we are more strict about that now.

@@ -124,19 +124,21 @@ class BugsnagClient {
return this._sessionDelegate.startSession(this)
}

leaveBreadcrumb (name, metaData, type, timestamp) {
leaveBreadcrumb (message, metadata, type) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

timestamp is not in the public method signature according to the new spec

const crumb = new BugsnagBreadcrumb(message, metadata, type)

// check the breadcrumb is the list of enabled types
if (!this.config.enabledBreadcrumbTypes || !includes(this.config.enabledBreadcrumbTypes, crumb.type)) return
Copy link
Contributor Author

Choose a reason for hiding this comment

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

enabledBreadcrumbTypes is guaranteed by config to be either null or an array of valid types.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it worthwhile doing this check before instantiating a BugsnagBreadcrumb class instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah good point. We previously did it after because the default type="manual" was only populated after the instantiation, but now it's done inside this method we can do it earlier.

@bugsnagbot
Copy link
Collaborator

bugsnagbot commented Nov 18, 2019

@bugsnag/browser bundle size diff

Minified Minfied + Gzipped
Before 40.80 kB 12.19 kB
After 40.03 kB 12.16 kB
± -772 bytes -31 bytes

Generated by 🚫 dangerJS against b245c79

severity: event.severity
}, 'error')
}
BugsnagClient.prototype.leaveBreadcrumb.call(this, event.errorClass, {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Node's notifier monkey-patches the leaveBreadcrumb() method to log a warning that breadcrumbs aren't supported.

Calling the method via the prototype ensures "internal" calls to leaveBreadcrumb() don't trigger the log. I can explain more if this doesn't make sense!

public type: string;
public timestamp: string;
constructor(name: string, metaData?: object, type?: string, timestamp?: string);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Breadcrumb construction is not public, it can only be done via leaveBreadcrumb().

const explicitlyDisabled = client.config.consoleBreadcrumbsEnabled === false
const implicitlyDisabled = (client.config.autoBreadcrumbs === false || isDev) && client.config.consoleBreadcrumbsEnabled !== true
if (explicitlyDisabled || implicitlyDisabled) return
if (!client.config.enabledBreadcrumbTypes || !includes(client.config.enabledBreadcrumbTypes, 'log') || isDev) return
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 change has the known impact of meaning console log breadcrumbs can't be enabled in development.

const crumb = new BugsnagBreadcrumb(message, metadata, type)

// check the breadcrumb is the list of enabled types
if (!this.config.enabledBreadcrumbTypes || !includes(this.config.enabledBreadcrumbTypes, crumb.type)) return
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it worthwhile doing this check before instantiating a BugsnagBreadcrumb class instance?

Comment on lines 76 to 79
validate: value => value === null || (isArray(value) && reduce(BREADCRUMB_TYPES, (accum, maybeType) => {
if (accum === false) return accum
return includes(BREADCRUMB_TYPES, maybeType)
}, true))
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this validation logic is wrong. Consider the following failing test case:

  describe('schema', () => {
    ...

    describe('enabledBreadcrumbTypes', () => {
      describe('validation', () => {
        it('fails when a supplied value is not a valid breadcrumb type', () => {
	  const enabledBreadcrumbTypesValidator = config.schema.enabledBreadcrumbTypes.validate;
          expect(enabledBreadcrumbTypesValidator(['UNKNOWN_BREADCRUMB_TYPE'])).toBe(false)
        })
      })
    })
  })

Gives Expected true to be false.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the failing test case 🙌

I added it to the codebase and fixed the bug (I was iterating over BREADCRUMB_TYPES rather than values).

@bengourley bengourley merged commit 8917cbc into v7 Nov 19, 2019
@bengourley bengourley deleted the v7-breadcrumb-refactor branch November 19, 2019 17:14
@bengourley bengourley mentioned this pull request Apr 14, 2020
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants