Cómo depurar Google Apps Script (también conocido como ¿dónde se registra Logger.log?)

129

En Hojas de cálculo de Google, puede agregar algunas funciones de secuencias de comandos. Estoy agregando algo para el onEditevento, pero no puedo decir si está funcionando. Por lo que puedo decir, no puede depurar un evento en vivo desde Google Sheets, por lo que debe hacerlo desde el depurador, lo cual no tiene sentido ya que el argumento del evento pasado a mi onEdit()función siempre estará indefinido si lo ejecuto desde el Script Editor.

Entonces, estaba tratando de usar el Logger.logmétodo para registrar algunos datos cada vez onEditque se llama a la función, pero también parece que solo funciona cuando se ejecuta desde Script Editor. Cuando lo ejecuto desde Script Editor, puedo ver los registros yendo aView->Logs...

Esperaba poder ver los registros de cuando el evento realmente se ejecuta, pero no puedo entenderlo.

¿Cómo depuro estas cosas?

d0c_s4vage
fuente
3
El mismo problema aquí: la respuesta aceptada no responde, pero proporciona mucha información errónea.
Hippyjim
Parece que arreglaron esto ahora. Siempre que abra el Editor de secuencias de comandos desde su hoja de cálculo, deje esa pestaña abierta cuando ejecute las cosas en su Hoja. Luego regrese a la pestaña de secuencia de comandos y tendrá la información de registro.
phreakhead
2
tldr; copiar, pegar y ejecutarLogger.log('firstLog');MailApp.sendEmail({to:'[email protected]',subject: "subject here ^_^",body: Logger.getLog()});
Coty Embry
Maby, debe cambiar la respuesta aceptada o agregar una nota de que Stackdriver Logging está disponible.
botenvouwer

Respuestas:

83

ACTUALIZAR:

Como está escrito en esta respuesta,


Logger.logle enviará un correo electrónico (eventualmente) de errores que ocurrieron en sus scripts o, si está ejecutando cosas desde el Script Editor, puede ver el registro desde la última función de ejecución yendo a View->Logs(todavía en el editor de scripts). Nuevamente, eso solo le mostrará cualquier cosa que haya sido registrada desde la última función que ejecutó desde adentroScript Editor .

El guión que estaba tratando de poner en funcionamiento tenía que ver con hojas de cálculo: hice una hoja de cálculo de tipo de lista de verificación que clasificaba los elementos por prioridades y demás.

Los únicos activadores que instalé para ese script fueron los activadores onOpen y onEdit. La depuración del desencadenador onEdit fue la más difícil de descifrar, porque seguía pensando que si establecía un punto de interrupción en mi función onEdit, abría la hoja de cálculo, editaba una celda, que mi punto de interrupción se dispararía. Este no es el caso.

Sin embargo , para simular haber editado una celda, terminé teniendo que hacer algo en la hoja de cálculo real. Todo lo que hice fue asegurarme de que la celda que quería que se tratara como "editada" estuviera seleccionada, luego Script Editor, iría a Run->onEdit. Entonces mi punto de ruptura sería golpeado.

Sin embargo, tuve que dejar de usar el argumento de evento que se pasa a la función onEdit; no puede simular eso haciendo Run->onEdit. Cualquier información que necesitaba de la hoja de cálculo, como qué celda se seleccionó, etc., tuve que averiguarla manualmente.

De todos modos, respuesta larga, pero finalmente lo descubrí.


EDITAR :

Si desea ver la lista de verificación de todo lo que hice, puede consultarla aquí

(sí, sé que cualquiera puede editarlo, ¡ese es el punto de compartirlo!)

Esperaba que también te dejara ver el guión. Como no puedes verlo allí, aquí está:

function onOpen() {
  setCheckboxes();
};

function setCheckboxes() {
  var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
  var checklist_data_range = checklist.getDataRange();
  var checklist_num_rows = checklist_data_range.getNumRows();
  Logger.log("checklist num rows: " + checklist_num_rows);

  var coredata = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
  var coredata_data_range = coredata.getDataRange();

  for(var i = 0 ; i < checklist_num_rows-1; i++) {
    var split = checklist_data_range.getCell(i+2, 3).getValue().split(" || ");
    var item_id = split[split.length - 1];
    if(item_id != "") {
      item_id = parseInt(item_id);
      Logger.log("setting value at ("+(i+2)+",2) to " + coredata_data_range.getCell(item_id+1, 3).getValue());
      checklist_data_range.getCell(i+2,2).setValue(coredata_data_range.getCell(item_id+1, 3).getValue());
    }
  }
}

function onEdit() {
  Logger.log("TESTING TESTING ON EDIT");
  var active_sheet = SpreadsheetApp.getActiveSheet();
  if(active_sheet.getName() == "checklist") {
    var active_range = SpreadsheetApp.getActiveSheet().getActiveRange();
    Logger.log("active_range: " + active_range);
    Logger.log("active range col: " + active_range.getColumn() + "active range row: " + active_range.getRow());
    Logger.log("active_range.value: " + active_range.getCell(1, 1).getValue());
    Logger.log("active_range. colidx: " + active_range.getColumnIndex());
    if(active_range.getCell(1,1).getValue() == "?" || active_range.getCell(1,1).getValue() == "?") {
      Logger.log("made it!");
      var next_cell = active_sheet.getRange(active_range.getRow(), active_range.getColumn()+1, 1, 1).getCell(1,1);
      var val = next_cell.getValue();
      Logger.log("val: " + val);
      var splits = val.split(" || ");
      var item_id = splits[splits.length-1];
      Logger.log("item_id: " + item_id);

      var core_data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
      var sheet_data_range = core_data.getDataRange();
      var num_rows = sheet_data_range.getNumRows();
      var sheet_values = sheet_data_range.getValues();
      Logger.log("num_rows: " + num_rows);

      for(var i = 0; i < num_rows; i++) {
        Logger.log("sheet_values[" + (i) + "][" + (8) + "] = " + sheet_values[i][8]);
        if(sheet_values[i][8] == item_id) {
          Logger.log("found it! tyring to set it...");
          sheet_data_range.getCell(i+1, 2+1).setValue(active_range.getCell(1,1).getValue());
        }
      }

    }
  }

  setCheckboxes();
};
d0c_s4vage
fuente
Pff, ¿el registro solo será visible en el correo? Eso hace que todas estas funciones de depuración y registro sean inútiles, porque efectivamente no podemos usar datos reales de la hoja de cálculo.
MrFox
No. Como dijo el autor, el registro está disponible en el registro (Script Editor, View, Log o Ctrl-Enter)
rainabba
9
@rainabba Sí, el registro está disponible en el Editor de secuencias de comandos. Sin embargo, cuando un script depende del argumento del evento y el argumento del evento no está disponible en el Editor de scripts, significa que los desarrolladores de este tipo de scripts no tienen una forma en tiempo real de acceder a los registros.
Jeff
1
No podía comentar antes, así que proporcioné una respuesta a continuación, pero: SI tiene abierto el editor de scripts y USTED activa un evento en la hoja de cálculo abierta, puede volver a la instancia del navegador del editor de scripts y ver la información en los Registros . Funciona bien siempre que no tenga que probar algo con un usuario que no puede abrir el script o con el que no puede iniciar sesión.
Karl_S
1
Esta respuesta está desactualizada y no debe verse como la respuesta aceptada. Stackdriver Logging está disponible y funciona de maravilla. Echa un vistazo a la respuesta de partes al azar!
botenvouwer
34

Por lo que puedo decir, no puede depurar un evento en vivo desde Google Docs, por lo que debe hacerlo desde el depurador, lo que no tiene sentido ya que el argumento del evento pasado a mi función onEdit () siempre estará indefinido si ejecuto desde el Editor de secuencias de comandos.

Verdadero: defina el argumento del evento usted mismo para la depuración. Consulte ¿Cómo puedo probar una función de activación en GAS?

Intenté usar el método Logger.log para registrar algunos datos cada vez que se llama a la función onEdit, pero también parece que solo funciona cuando se ejecuta desde el Editor de secuencias de comandos. Cuando lo ejecuto desde el Editor de secuencias de comandos, puedo ver los registros yendo a Ver-> Registros ...

Cierto otra vez, pero hay ayuda. La biblioteca BetterLog de Peter Hermann redirigirá todos los registros a una hoja de cálculo, permitiendo el registro incluso desde el código que no está adjunto a una instancia del editor / depurador.

Si está codificando en un script contenido en una hoja de cálculo, por ejemplo, puede agregar solo esta línea en la parte superior de su archivo de script, y todos los registros irán a una hoja "Registros" en la hoja de cálculo. No es necesario otro código, solo utilícelo Logger.log()como lo haría normalmente:

Logger = BetterLog.useSpreadsheet();
Mogsdad
fuente
1
Anticuado. console.log()debería ser la mejor respuesta ahora
TheMaster
22

Actualización de 2017: el registro de Stackdriver ahora está disponible para Google Apps Script. Desde la barra de menú en el editor de script, vaya a: View > Stackdriver Loggingpara ver o transmitir los registros.

console.log () escribirá DEBUGmensajes de nivel

Ejemplo de onEdit()registro:

function onEdit (e) {
  var debug_e = {
    authMode:  e.authMode,  
    range:  e.range.getA1Notation(),    
    source:  e.source.getId(),
    user:  e.user,   
    value:  e.value,
    oldValue: e. oldValue
  }

  console.log({message: 'onEdit() Event Object', eventObject: debug_e});
}

Luego verifique los registros en la IU de Stackdriver etiquetados onEdit() Event Objectpara ver la salida

partes aleatorias
fuente
La pregunta original pregunta específicamente sobre Logger.log. ¿Cómo es esto diferente de console.loglo que usas? Soy muy nuevo en las herramientas, así que solo trato de descubrir qué es todo.
AnnanFay
5

Un poco hacky, pero creé una matriz llamada "consola", y cada vez que quería salir a la consola empujé a la matriz. Luego, cada vez que quería ver la salida real, simplemente regresaba en consolelugar de lo que estaba regresando antes.

    //return 'console' //uncomment to output console
    return "actual output";
}
woojoo666
fuente
en js console.log('smth')funciona perfectamente, pero ¿qué tal en GAS?
Igor Savinkin
1
console.log no funcionará simplemente porque GAS no son scripts que se ejecutan en la misma página web que su hoja de cálculo, son scripts manejados por el motor de aplicaciones de Google, por lo que debe seguir su depurador Logger.log difícil de manejar o usar un truco como el mío
woojoo666
¿Qué hay de su matriz 'consola'? I just returned console¿ Cuándo cómo lo sacas?
Igor Savinkin
2
Lo siento, no lo expliqué muy bien, pero esencialmente las funciones de hoja de cálculo devuelven el valor a la celda, por lo que si devuelve su "consola" verá todo lo que registró dentro de su celda de hoja de cálculo
woojoo666
5

Si tiene abierto el editor de scripts, verá los registros en Ver-> Registros. Si su script tiene un activador de edición, realice un cambio en la hoja de cálculo que debería activar la función con el editor de script abierto en una segunda pestaña. Luego vaya a la pestaña del editor de scripts y abra el registro. Verá lo que su función pase al registrador.

Básicamente, siempre que el editor de scripts esté abierto, el evento escribirá en el registro y se lo mostrará. No se mostrará si alguien más está en el archivo en otro lugar.

Karl_S
fuente
5

Revisé estas publicaciones y de alguna manera terminé encontrando una respuesta simple, que estoy publicando aquí para aquellos que quieren soluciones cortas y dulces:

  1. Utilizar console.log("Hello World") en su guión.
  2. Vaya a https://script.google.com/home/my y seleccione su complemento.
  3. Haga clic en el menú de puntos suspensivos en Detalles del proyecto, seleccione Ejecuciones.

ingrese la descripción de la imagen aquí

  1. Haga clic en el encabezado de la última ejecución y lea el registro.

ingrese la descripción de la imagen aquí

Benjamín
fuente
Este es el "registro básico de Stackdriver" para las secuencias de comandos de Google Apps creadas después de abril de 2019 (que es cuando el acceso al Proyecto Google Cloud para proyectos "automáticos" detrás de las secuencias de comandos de aplicaciones se hizo imposible). Si cambia el GCP para un proyecto de Script de Apps, se aplicarán las respuestas de registro normales de Stackdriver.
Tehhowch
1
Aquí solo veo ejecuciones directas (es decir, aquellas para las que hice clic en "ejecutar" en el editor de scripts), pero no veo ejecuciones causadas por un cambio de datos en la hoja. ¿Cómo los depuro?
Cris70
No lo he probado, lo siento. Me imagino que si un cambio en la hoja activa una función y la función tiene un registro, el registro se mostrará junto. Los cambios siempre serían inducidos por el usuario, ¿verdad?
Benjamin
1
Sí, también me lo habría imaginado. Desafortunadamente, eso no es lo que sucede :-( Los cambios en los datos activan mi función, pero los mensajes de console.log () no se muestran en el registro de Stackdriver. Intenté agregar un activador de cambio, pero eso invoca mi función sin parámetros: - (
Cris70
4

Estoy teniendo el mismo problema, encontré lo siguiente en la web en alguna parte ...

Sin embargo, los controladores de eventos en Docs son un poco complicados. Debido a que los documentos pueden manejar múltiples ediciones simultáneas por parte de múltiples usuarios, los controladores de eventos se manejan del lado del servidor. El principal problema con esta estructura es que cuando falla un script de activación de eventos, falla en el servidor. Si desea ver la información de depuración, deberá configurar un activador explícito en el menú de activadores que le envíe por correo electrónico la información de depuración cuando el evento falle o de lo contrario fallará en silencio.

Angus Keenan
fuente
Hmm, sí, me encontré con esto: me envió un montón de errores de mis scripts a la mañana siguiente. Sin embargo
terminé
1

Está lejos de ser elegante, pero durante la depuración, a menudo me conecto al Logger, y luego uso getLog () para recuperar su contenido. Entonces, yo:

  • guardar los resultados en una variable (que se puede inspeccionar en el depurador de Google Scripts; esto funciona en casos en los que no puedo establecer un punto de interrupción en algún código, pero puedo establecer uno en el código que se ejecuta más adelante)
  • escribirlo en algún elemento DOM temporal
  • mostrarlo en una alerta

Básicamente, se convierte en un problema de salida de JavaScript .

Carece enormemente de la funcionalidad de las console.log()implementaciones modernas , pero el Logger todavía ayuda a depurar Google Scripts.

Michael Scheper
fuente
1

Solo como un aviso. Hice una función de prueba para mi hoja de cálculo. Utilizo la variable google throws en la función onEdit (e) (la llamé e). Luego hice una función de prueba como esta:

function test(){
var testRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,7)
var testObject = {
    range:testRange,
    value:"someValue"
}
onEdit(testObject)
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,6).setValue(Logger.getLog())
}

Al llamar a esta función de prueba, todo el código se ejecuta como si tuviera un evento en la hoja de cálculo. Acabo de poner en la posición de la celda que edité lo que me dio un resultado inesperado, estableciendo el valor como el valor que puse en la celda. OBS! Para obtener más variables, Google proporciona a la función ir aquí: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events

Meltinglava
fuente
0

Actualmente, está limitado a la naturaleza vinculada al contenedor de usar scripts dentro de los documentos. Si crea una nueva secuencia de comandos fuera de los documentos, podrá exportar información a una hoja de cálculo de Google y usarla como una herramienta de registro.

Por ejemplo en tu primer bloque de código

function setCheckboxes() {

    // Add your spreadsheet data
    var errorSheet = SpreadsheetApp.openById('EnterSpreadSheetIDHere').getSheetByName('EnterSheetNameHere');
    var cell = errorSheet.getRange('A1').offset(errorSheet.getLastRow(),0);

    // existing code
    var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
    var checklist_data_range = checklist.getDataRange();
    var checklist_num_rows = checklist_data_range.getNumRows();

    // existing logger
    Logger.log("checklist num rows: " + checklist_num_rows);

   //We can pass the information to the sheet using cell.setValue()
    cell.setValue(new Date() + "Checklist num rows: " + checklist_num_rows);

Cuando estoy trabajando con GAS, tengo dos monitores (puede usar dos ventanas) configurados con uno que contiene el entorno GAS y el otro que contiene el SS para que pueda escribir información e iniciar sesión.

JForgie
fuente
0

La consola de desarrollo registrará los errores generados por el script de la aplicación, por lo que puede lanzar un error para que se registre como un archivo console.log normal. Se detendrá la ejecución, pero aún puede ser útil para la depuración paso a paso.

throw Error('hello world!');

aparecerá en la consola de manera similar a console.log('hello world')

QWERTY
fuente
0

simplemente depure su código de hoja de cálculo de esta manera:

...
throw whatAmI;
...

muestra así:

ingrese la descripción de la imagen aquí

Toskan
fuente
Creo que debería mencionar que la imagen muestra cómo una función personalizada muestra un error, pero el OP menciona que está usando un disparador simple ( onEdit)
Rubén