All Projects → walmartlabs → costanza

walmartlabs / costanza

Licence: MIT License
Frontend error tracking toolkit: Own your own domain

Programming Languages

javascript
184084 projects - #8 most used programming language

NOTICE:

This repository has been archived and is not supported.

No Maintenance Intended


NOTICE: SUPPORT FOR THIS PROJECT HAS ENDED

This projected was owned and maintained by Walmart. This project has reached its end of life and Walmart no longer supports this project.

We will no longer be monitoring the issues for this project or reviewing pull requests. You are free to continue using this project under the license terms or forks of this project at your own risk. This project is no longer subject to Walmart's bug bounty program or other security monitoring.

Actions you can take

We recommend you take the following action:

  • Review any configuration files used for build automation and make appropriate updates to remove or replace this project
  • Notify other members of your team and/or organization of this change
  • Notify your security team to help you evaluate alternative options

Forking and transition of ownership

For security reasons, Walmart does not transfer the ownership of our primary repos on Github or other platforms to other individuals/organizations. Further, we do not transfer ownership of packages for public package management systems.

If you would like to fork this package and continue development, you should choose a new name for the project and create your own packages, build automation, etc.

Please review the licensing terms of this project, which continue to be in effect even after decommission.

Costanza

Build Status

Frontend error tracking toolkit: Own your own domain

Provides a Node.js domains inspired async error-tracking system for frontend clients. This allows for tracking errors with more than the Undefined is not an object level of detail that many implementations of generic window.onerror provide.

onerror:
  msg: Uncaught TypeError: 'undefined' is not an object
  url: http://localhost/home.js
  line: 1

But with Costanza the logged error is much more expressive:

Costanza error:
  type: javascript
  section: thorax-exception: home ;; DOM-event:click .js-big-red-button

TypeError: 'undefined' is not an object
    at bigRedButtonHandler (http://localhost/home.js:1:129)
    at http://localhost/base.js:1:2221
    at ret (http://localhost/base.js:1:9860)

Showing that the error occurred in the click .js-big-red-button event handler of the Thorax home view as well as providing the stack trace associated with that event.

Features

  • Automatically associating callbacks and events with the code group that created them
  • Tracking global javascript errors
  • Tracking resource load failures
  • Page unload tracking

Usage

Initialize the library using the Costanza.init method, passing a callback that will handle errors. This callback should send the error info to your centralized tracking server.

Costanza.init(function(info, rawError) {
  $.ajax({
    url: myAnalyticsServer,
    method: 'POST',
    data: info
  });
});

This is the minimum required to use the library, but the fidelity of the error tracking is greatly improved if code is associated with known sections. Sections allow for a unique name to be associated with a code execution path. Should an error occur within the section or one of its anonymous sections, this unique name will be included in the error result, easing debugging.

The easiest way to create a section is with the run method, which will immediately execute.

Costanza.run('unique-name', function() {
  // Do stuff that fails
});

Callbacks may also be created with sections for later execution:

var callback = Costanza.bind('another-unique-name', function() {
  // Bang!
});

Anonomyous sections may be created within other known sections. When these child sections execute, they will do so using the same identifier pased to the parent section. This is done automatically for callbacks passed to setTimeout, setInterval, and addEventListener by default.

Costanza.run('yet-another-unique-name', function() {
  setTimeout(function() {
    // A later bang!
  }, 1000);
});

Ideally new named sections are created for any logical entry point into the system from the event loop. Things like DOM event handlers and ajax callbacks are prime candidates for creating named sections. Plugins such as costanza-thorax allow for doing this in an automated fashion. (Don't see a plugin for your framework of choice? Send over a PR!)

Implementation Warning

This code hijacks majors portions of built-in prototype objects. This should be fail-safe but is not guaranteed to do so. Use only after considering the risks. Users who would like to avoid prototype extension may pass the safeMode option to avoid altering host objects. safeMode users will need to manually wrap callback functions to ensure that stack traces are available for methods that are executed on subsequent event loops.

Costanza.init(function(info, rawError) {
  $.ajax();
}, {safeMode: true});

Costanza.run('still-yet-another-unique-name', function() {
  setTimeout(Costanza.bind('still-yet-another-unique-name', function() {
    // A later bang!
  }), 1000);
});

API

#init(callback, options)

Initializes the library. In the event of an error callback(info, rawError) will be receive:

  • info: A stringifable object that may contain the following, in addition to custom fields for the case of emit.

    • type: The type of error that occurred. For execution errors this will be javascript. For errors loading external resources for a particular element this will be tag name of the element that failed to load.
    • section: Current section executing when the failure occured. global if there is no current section.
    • url: URL of the error, if available. For element load errors this will be the referenced external object.
    • line: The line number of the error, if available.
    • msg: The error message.
    • stack: The javascript stack trace of the error, if available.
  • rawError: The raw error object that generated the event, if available. This is not guaranteed to be JSON safe.

Enabled features may be controlled with the options parameter. These include:

  • safeMode: Disables native overrides
  • noGlobal: Disables global onerror and error event tracking

#run(name, [info, ] callback)

Creates a new named section and executes immediately. This allows for easy creation of new section scopes.

#bind([name, ][info, ] callback)

Creates a section which may be executed at a later time. If name is omitted then the section will execute under the current section name. This is useful for providing callbacks to methods that do not use one of the automaticly bound paths.

If an info object is provided, the data passed on error will be extended with any values defined on info. This may be used for passing arbitrary debugging data back to the tracking system.

#current()

Returns the name of the current section. If none is defined then the return is global.

#emit(info, error)

Emits a custom event to the error handler callback.

#cleanup()

Removes any overrides that may have been performed. Calling this method is unnecessary under most circumstances.

Platforms

Tested platforms include:

Desktop:

  • Chrome: Latest
  • Firefox: Latest
  • Safari: 7+
  • IE: 8+
  • Opera: 12+

Mobile:

  • iOS: 4.2+
  • Android: 2.3+
  • Windows Phone: 8+
  • Blackberry: 6.0+

Not all features are supported on all platforms and the log messages will vary by platform.

  • Support for error events for for loading vary greatly by browser. @yaypie has put together a good listing of supporting browsers for these events.
  • Android 2.x does not window.onerror generic handling.
  • Opera 12 does not appear to support tracking of SyntaxErrors via window.onerror

Hall of Shame

The following are exceptions seen in the wild that appear to be thrown by 3rd party extensions or proxy injected code. Don't let friends inject buggy code... or any for that matter.

  • TypeError: 'undefined' is not an object (evaluating 'document.getElementsByTagName('video')[0].src')
  • TypeError: 'undefined' is not an object (evaluating 'document.getElementsByTagName('video')[0].getElementsByTagName')
  • TypeError: 'undefined' is not an object (evaluating 'document.getElementsByTagName('video')[0].getAttribute')
  • Uncaught TypeError: Cannot call method 'Log' of undefined
  • Uncaught TypeError: Cannot call method 'setHTML' of undefined
  • Uncaught TypeError: Cannot call method 'setTitleDescription' of undefined
  • ReferenceError: Can't find variable: pc_scroll_view_will_begin_dragging
  • ReferenceError: Can't find variable: pc_scroll_view_will_begin_decelerating
  • ReferenceError: Can't find variable: pc_scroll_view_did_end_decelerating
  • ReferenceError: Can't find variable: atomicFindClose
  • Uncaught ReferenceError: MMSDK is not defined
  • Uncaught ReferenceError: measurePositions is not defined

Testing

Command line:

gulp

Interactive:

gulp watch

Costanza uses @karma, and will automatically load all locally installed browsers. If you want to access it manually or remotely, you can do so via http://localhost:9876

Why is this called Costanza?

George Costanza (of Seinfeld fame) was the master of his domain and we want you to be the master of yours.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].