Cómo obtener Llamadas a Funciones Javascript / Seguimiento en Tiempo de ejecución


Al interactuar con mi aplicación basada en AJAX en TIEMPO DE EJECUCIÓN Me gustaría que la consola escupiera todas las funciones que está llamando. (así que no hay seguimiento de pila, o puntos de interrupción, o perfiles o nada)

Por ejemplo, digamos que presioné un botón en la página. Me gustaría que devolviera todas las funciones pasó cuando eso sucedió:

Así que veía en la consola algo como (cuando presionaba un botón):

1. button1Clicked();
2.     calculating();
3.          printingResults();

Lo que básicamente significa que button1Clicked() called calculating () que llamó a printingResults ()

¿Hay alguna utilidad, o plugin, navegador, o tal vez alguna forma en el idioma para hacer esto? Estoy usando Google Chrome, por cierto.

P. s y NO No quiero ir a través de cada función y añadir un "console.log("inside function X")" b/c que es demasiado trabajo

P. P. s como un bono adicional Me gustaría ver los argumentos pasados a las funciones también, pero tal vez eso es empujarlo. :>

Author: foreyez, 2012-08-08

6 answers

No puedo pensar en una gran manera de interceptar todas las llamadas a funciones a nivel mundial para insertar el registro (aunque hay una solución decente en la sección de actualización a continuación).

En su lugar, ¿qué tal si solo agregas registros a funciones en un espacio de nombres determinado que te importa? Puede hacer esto con el siguiente código de configuración:

var functionLogger = {};

functionLogger.log = true;//Set this to false to disable logging 

/**
 * Gets a function that when called will log information about itself if logging is turned on.
 *
 * @param func The function to add logging to.
 * @param name The name of the function.
 *
 * @return A function that will perform logging and then call the function. 
 */
functionLogger.getLoggableFunction = function(func, name) {
    return function() {
        if (functionLogger.log) {
            var logText = name + '(';

            for (var i = 0; i < arguments.length; i++) {
                if (i > 0) {
                    logText += ', ';
                }
                logText += arguments[i];
            }
            logText += ');';

            console.log(logText);
        }

        return func.apply(this, arguments);
    }
};

/**
 * After this is called, all direct children of the provided namespace object that are 
 * functions will log their name as well as the values of the parameters passed in.
 *
 * @param namespaceObject The object whose child functions you'd like to add logging to.
 */
functionLogger.addLoggingToNamespace = function(namespaceObject){
    for(var name in namespaceObject){
        var potentialFunction = namespaceObject[name];

        if(Object.prototype.toString.call(potentialFunction) === '[object Function]'){
            namespaceObject[name] = functionLogger.getLoggableFunction(potentialFunction, name);
        }
    }
};

Luego, para cualquier objeto de espacio de nombres al que desee agregar el registro, simplemente llame a:

functionLogger.addLoggingToNamespace(yourNamespaceObject);

Aquí hay un violín para verlo en acto.

UPDATE
Tenga en cuenta que puede llamar a functionLogger.addLoggingToNamespace(window); para agregar registros a todas las funciones globales en el momento de la llamada. Además, si realmente lo desea, puede recorrer el árbol para encontrar cualquier función y actualizarlas en consecuencia. La única falla de este método es que solo funciona en funciones que existen en ese momento. Por lo tanto, todavía no es la mejor solución, pero es mucho menos trabajo que agregar declaraciones de registro a mano:)

 32
Author: Briguy37,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-13 13:02:27

Esto se llama perfilado y Chrome y Firebug lo tienen incorporado. En Chrome developer Tools, ve a la pestaña perfiles y haz clic en el botón grabar (círculo). Realice su ajax y después de su respuesta, haga clic en el botón grabar de nuevo para detenerse. Los resultados del perfil aparecerán en el panel derecho.

Tenga en cuenta que esto le dará todo así que si está utilizando una biblioteca como jQuery, la gran mayoría de las llamadas a funciones serán basura para usted. He probé esto un par de veces y me parece que es mucho más útil hacer la cosa console.log('inside <method>').

 12
Author: Jeff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-07 20:21:58

Tal vez puedas hacer que JavaScript haga parte del trabajo de agregar consola.registro para usted:

Añadir consola.registro de cada función automáticamente

También este blog de Paul Irish podría ayudar:

Http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog /

Incluye un enlace a algunos JavaScript dirigidos específicamente a los argumentos de registro:

Http://pastie.org/1033665

 2
Author: Jason Sperske,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:36

Pruebe diyism_trace_for_javascript.htm:

Https://code.google.com/p/diyism-trace/downloads/list

eval('window.c=function(){3+5;}');
declare_ticks_for(window);

function a(k, c) {
  return k + 2;
}

function b() {
  4 + 3;
  a(3, {'a':'c','b':'d'});
  c();
  return 5 + 4;
}

b();

Ver los registros en la pestaña consola de chrome o firefox

 2
Author: diyism,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-07 03:34:39

Una variación de la solución de Briguy37, escribí una que acepta una función para llamar antes de cada método. También funciona con clases ECMAScript 6, donde los métodos no son enumerados por for...in. Lo estoy usando para modificar prototipos de objetos, para agregar registros a todas las nuevas instancias de mi objeto.

function inject(obj, beforeFn) {
    for (let propName of Object.getOwnPropertyNames(obj)) {
        let prop = obj[propName];
        if (Object.prototype.toString.call(prop) === '[object Function]') {
            obj[propName] = (function(fnName) {
                return function() {
                    beforeFn.call(this, fnName, arguments);
                    return prop.apply(this, arguments);
                }
            })(propName);
        }
    }
}

function logFnCall(name, args) {
    let s = name + '(';
    for (let i = 0; i < args.length; i++) {
        if (i > 0)
            s += ', ';
        s += String(args[i]);
    }
    s += ')';
    console.log(s);
}

inject(Foo.prototype, logFnCall);
 2
Author: Peter Tseng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-26 05:01:25

He utilizado la solución de @Briguy37 con una mejora. En mi caso, no quería rastrear funciones de algunas bibliotecas, así que agregué algún código para excluirlas. Así es como se usa:

  • Primero, incluya la definición de las funciones que no desea rastrear;
  • excludeLoggingToNamespace para listar las funciones definidas hasta ahora y excluirlas;
  • Incluya la definición de las funciones que desea rastrear;
  • Llame a addLoggingToNamespace para agregar el registro capacidad para las funciones definidas en el paso anterior.

Ejemplo:

<script src="js/someLibrary.js"></script>
<script>
    functionLogger.excludeLoggingToNamespace(window);
</script>
<script src="js/codeIWantToTraceHere.js"></script>
<script>
    functionLogger.addLoggingToNamespace(window);
</script>

Aquí está el código que agregué a la solución de @Briguy37:

var excludedFunctions = {};

        functionLogger.excludeLoggingToNamespace = function(namespaceObject){
            for(var name in namespaceObject){
                var potentialFunction = namespaceObject[name];

                if(Object.prototype.toString.call(potentialFunction) === '[object Function]') {
                    excludedFunctions[name] = name;
                }
            }
        }; 

Y tuve que modificar el método addLoggingToNamespace de @Briguy37 para tener en cuenta el hash excludedFunctions:

functionLogger.addLoggingToNamespace = function(namespaceObject){
    for(var name in namespaceObject){
        var potentialFunction = namespaceObject[name];

        if(Object.prototype.toString.call(potentialFunction) === '[object Function]' && 
           !excludedFunctions[name]) {
            namespaceObject[name] = functionLogger.getLoggableFunction(potentialFunction, name);
        }
    }
};    
 0
Author: Jean-François Beauchamp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-01 16:05:14