Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Debug the Web 101

Debug the Web 101

Useful Javascript Debugging Techniques in production environment.

Ankur Agarwal

March 31, 2013
Tweet

Other Decks in Programming

Transcript

  1. ANKUR AGARWAL
    DEBUG THE WEB 101

    View full-size slide

  2. Who do I do ?
    Twitter @Agarwal_Ankur
    Github @devilankur18

    View full-size slide

  3. Web is Evolving

    View full-size slide

  4. So Code Breaks

    View full-size slide

  5. And when it breaks

    View full-size slide

  6. So how to debug ?

    View full-size slide

  7. window.onerror

    View full-size slide

  8. 1. Error Message
    2. Line No
    3. Filename
    For the same origin only*
    * Some browsers provide information for cross origin as well
    Provides

    View full-size slide

  9. 1. Callstack missing
    2. Character no. missing
    3. Doesn't work for Cross origin
    scripts
    Challenges

    View full-size slide

  10. try {
    // Some code
    } catch (e) {
    // Character No
    // Stack Traces
    // Works for cross origin
    }
    Its simple to use

    View full-size slide

  11. Challenges
    1. Need to add extra code
    2. How to use with existing code
    and libraries ?
    3. Performance Tradeoff

    View full-size slide

  12. function wrap(func) {
    function wrapped() {
    try {
    return func.apply(this, arguments);
    } catch (e) {
    console.log(e.message);
    throw e;
    }
    }
    return wrapped;
    }
    A simple wrapper

    View full-size slide

  13. function track (object) {
    for (var fn in object) {
    if (typeof fn === "function") {
    object[fn] = wrap(fn);
    }
    }
    }
    A object wrapper

    View full-size slide

  14. var obj = {
    a : 1
    b : 2
    foo: {
    return "Hello World!"
    },
    bar: {
    throw new Error("Hello World!");
    }
    }
    track(obj);
    obj.foo(); // return "Hello World!"
    obj.bar(); // throws exception
    Example

    View full-size slide

  15. window.console

    View full-size slide

  16. Challenges
    1. Old IE doesn't have console
    2. Console object is unavailable
    until opened
    3. Don't want to throw logs in
    production

    View full-size slide

  17. if( (window && !window.console) || isProduction() ) {
    var apis = ['log','info','warn','error','assert','dir',
    'clear','profile','profileEnd'],
    g,
    api,
    container = window.console = {};
    for (g = 0; g < apis.length; g++) {
    api = apis[g];
    container[api] = function () {};
    }
    }
    function isProduction() {
    // Some logic
    return document.location.hostname !== "localhost";
    }
    A simple wrapper

    View full-size slide

  18. Challenges
    1. Collect the error logs in
    production
    2. Developers don't have access to
    users browsers

    View full-size slide

  19. report errors

    View full-size slide

  20. function report(message, url, linenumber) {
    if (window.XMLHttpRequest) {
    var xhr = new XMLHttpRequest();
    var scripturl = "http://yourdomain.example.com/report";
    var log = linenumber + message + url;
    xhr.open("POST", scripturl);
    xhr.setRequestHeader("Content-Type", "text/plain;
    charset=UTF-8");
    xhr.send(log);
    }
    }
    function reportEx(ex) {
    // Extract Info from exception
    var info = extract(ex);
    report(info.message, info.url, info.lineno);
    }
    Some Helpers

    View full-size slide

  21. window.onerror = report;
    // With try-catch
    try {
    // Some code
    } catch (e) {
    // Character No
    // Stack Traces
    // Works for cross origin
    reportEx(e);
    }
    Usage

    View full-size slide

  22. async functions

    View full-size slide

  23. function asyncTrack(fnName) {
    var originalFn = window[fnName];
    window[fnName] = function AsyncTrackingWrapper() {
    // Make a copy of the arguments
    var args = _slice.call(arguments);
    var originalCallback = args[0];
    if (typeof originalCallback === "function") {
    args[0] = wrap(originalCallback);
    }
    // IE < 9 Hack
    if (originalFn.apply) {
    return originalFn.apply(this, args);
    } else {
    return originalFn(args[0], args[1]);
    }
    };
    };
    asyncTrack('setTimeout');
    asyncTrack('setInterval');

    View full-size slide

  24. instrument functions

    View full-size slide

  25. Simple Helpers
    function instrumentFunction(context, functionName, callback)
    {
    context = context || window;
    var original = context[functionName];
    context[functionName] = function instrumented() {
    callback.apply(this, arguments);
    return context[functionName]._instrumented.apply(
    this, arguments);
    };
    context[functionName]._instrumented = original;
    }

    View full-size slide

  26. Simple Helpers
    function deinstrumentFunction(context, functionName) {
    if (context[functionName].constructor === Function &&
    context[functionName]._instrumented &&
    context[functionName]._instrumented.constructor ===
    Function) {
    context[functionName] = context[functionName].
    _instrumented;
    }
    }

    View full-size slide

  27. debug frameworks

    View full-size slide

  28. jQuery
    // All methods of jquery will be wrapped
    track(jQuery);
    // A simple helper to track ajax errors
    $(document).ajaxError(
    function(event, jqXHR, ajaxSettings, thrownError) {
    // Report this error
    report(thrownError, null, null);
    });

    View full-size slide

  29. Ember.onerror = reportEx;
    Emberjs

    View full-size slide

  30. And we are hiring
    Send your resume / github profiles to
    [email protected]
    Website: www.debuggify.net/career

    View full-size slide

  31. Thank you
    For More Tips & Tricks
    Follow us on Twitter @D3buggify
    Signup for debugging your production code
    www.debuggify.net/signup

    View full-size slide