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 Slide

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

    View Slide

  3. Web is Evolving

    View Slide

  4. So Code Breaks

    View Slide

  5. And when it breaks

    View Slide

  6. View Slide

  7. Case Study

    View Slide

  8. So how to debug ?

    View Slide

  9. window.onerror

    View Slide

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

    View Slide

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

    View Slide

  12. View Slide

  13. try catch

    View Slide

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

    View Slide

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

    View Slide

  16. View Slide

  17. 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 Slide

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

    View Slide

  19. 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 Slide

  20. window.console

    View Slide

  21. 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 Slide

  22. View Slide

  23. 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 Slide

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

    View Slide

  25. View Slide

  26. report errors

    View Slide

  27. 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 Slide

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

    View Slide

  29. async functions

    View Slide

  30. 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 Slide

  31. instrument functions

    View Slide

  32. 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 Slide

  33. 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 Slide

  34. debug frameworks

    View Slide

  35. 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 Slide

  36. Ember.onerror = reportEx;
    Emberjs

    View Slide

  37. View Slide

  38. Q & A

    View Slide

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

    View Slide

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

    View Slide