简体   繁体   English

如何调试 Google Apps 脚本(也就是 Logger.log 记录到哪里?)

[英]How to debug Google Apps Script (aka where does Logger.log log to?)

In Google Sheets, you can add some scripting functionality.在 Google 表格中,您可以添加一些脚本功能。 I'm adding something for the onEdit event, but I can't tell if it's working.我正在为onEdit事件添加一些内容,但我无法判断它是否有效。 As far as I can tell, you can't debug a live event from Google Sheets, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor .据我所知,您无法从 Google 表格调试实时事件,因此您必须从调试器进行调试,这是没有意义的,因为如果我运行,传递给我的onEdit() function 的事件参数将始终未定义它来自Script Editor

So, I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor .因此,每当调用onEdit function 时,我都尝试使用Logger.log方法记录一些数据,但这似乎也只有在从Script Editor运行时才有效。 When I run it from the Script Editor , I can view the logs by going to View->Logs...当我从Script Editor运行它时,我可以通过转到View->Logs...查看日志

I was hoping I'd be able to see the logs from when the event actually gets executed, but I can't figure it out.我希望我能够看到事件实际执行时的日志,但我无法弄清楚。

How do I debug this stuff?我该如何调试这些东西?

UPDATE:更新:

As written in this answer,正如这个答案中所写,


Logger.log will either send you an email (eventually) of errors that have happened in your scripts, or, if you are running things from the Script Editor , you can view the log from the last run function by going to View->Logs (still in script editor). Logger.log会(最终)向您发送一封电子邮件,告知您脚本中发生的错误,或者,如果您正在从Script Editor运行内容,您可以通过转到查看View->Logs (仍在脚本编辑器中)。 Again, that will only show you anything that was logged from the last function you ran from inside Script Editor .同样,这只会向您显示您Script Editor中运行的最后一个函数记录的任何内容。

The script I was trying to get working had to do with spreadsheets - I made a spreadsheet todo-checklist type thing that sorted items by priorities and such.我试图开始工作的脚本与电子表格有关——我制作了一个电子表格待办事项清单类型的东西,它按优先级等对项目进行排序。

The only triggers I installed for that script were the onOpen and onEdit triggers.我为该脚本安装的唯一触发器是 onOpen 和 onEdit 触发器。 Debugging the onEdit trigger was the hardest one to figure out, because I kept thinking that if I set a breakpoint in my onEdit function, opened the spreadsheet, edited a cell, that my breakpoint would be triggered.调试 onEdit 触发器是最难搞清楚的,因为我一直在想,如果我在我的 onEdit 函数中设置一个断点,打开电子表格,编辑一个单元格,我的断点就会被触发。 This is not the case.不是这种情况。

To simulate having edited a cell, I did end up having to do something in the actual spreadsheet though.为了模拟编辑一个单元格,最终不得不在实际的电子表格中做一些事情。 All I did was make sure the cell that I wanted it to treat as "edited" was selected, then in Script Editor , I would go to Run->onEdit .我所做的只是确保选中我希望它视为“已编辑”的单元格,然后在Script Editor中,我将转到Run->onEdit Then my breakpoint would be hit.然后我的断点就会被击中。

However, I did have to stop using the event argument that gets passed into the onEdit function - you can't simulate that by doing Run->onEdit .但是,我确实不得不停止使用传递给 onEdit 函数的事件参数——你不能通过执行Run->onEdit来模拟它。 Any info I needed from the spreadsheet, like which cell was selected, etc, I had to figure out manually.我需要从电子表格中获得的任何信息,例如选择了哪个单元格等,我都必须手动弄清楚。

Anyways, long answer, but I figured it out eventually.无论如何,答案很长,但我最终想通了。


EDIT :编辑

If you want to see the todo checklist I made, you can check it out here如果你想看我做的待办事项清单,你可以在这里查看

(yes, I know anybody can edit it - that's the point of sharing it!) (是的,我知道任何人都可以编辑它——这就是分享它的意义所在!)

I was hoping it'd let you see the script as well.我希望它也能让你看到剧本。 Since you can't see it there, here it is:由于您在那里看不到它,因此它是:

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();
};

As far as I can tell, you can't debug a live event from google docs, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.据我所知,您无法从 google docs 调试实时事件,因此您必须从调试器进行调试,这是没有意义的,因为如果我运行,传递给我的 onEdit() 函数的事件参数将始终未定义它来自脚本编辑器。

True - so define the event argument yourself for debugging.是的 - 所以自己定义事件参数以进行调试。 See How can I test a trigger function in GAS?请参阅如何在 GAS 中测试触发功能?

I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor.每当调用 onEdit 函数时,我都尝试使用 Logger.log 方法记录一些数据,但这似乎也只有在从脚本编辑器运行时才有效。 When I run it from the Script Editor, I can view the logs by going to View->Logs...当我从脚本编辑器运行它时,我可以通过转到“查看”->“日志...”来查看日志。

True again, but there is help.再次正确,但有帮助。 Peter Hermann's BetterLog library will redirect all logs to a spreadsheet, enabling logging even from code that is not attached to an instance of the editor / debugger. Peter Hermann 的BetterLog 库会将所有日志重定向到电子表格,甚至可以从未附加到编辑器/调试器实例的代码中进行日志记录。

If you're coding in a spreadsheet-contained script, for example, you can add just this one line to the top of your script file, and all logs will go to a "Logs" sheet in the spreadsheet.例如,如果您在包含电子表格的脚本中进行编码,则可以仅将这一行添加到脚本文件的顶部,所有日志都将转到电子表格中的“日志”表。 No other code necessary, just use Logger.log() as you usually would:不需要其他代码,只需像往常一样使用Logger.log()

Logger = BetterLog.useSpreadsheet();

2017 Update: Stackdriver Logging is now available for Google Apps Script. 2017 年更新: Stackdriver Logging现在可用于 Google Apps 脚本。 From the menu bar in the script editor, goto: View > Stackdriver Logging to view or stream the logs.在脚本编辑器的菜单栏中,转到: View > Stackdriver Logging以查看或流式传输日志。

console.log() will write DEBUG level messages console.log()将写入DEBUG级别的消息

Example onEdit() logging: onEdit()日志记录示例:

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});
}

Then check the logs in the Stackdriver UI labeled onEdit() Event Object to see the output然后检查标记为onEdit() Event Object的 Stackdriver UI中的日志以查看输出

I've gone through these posts and somehow ended up finding a simple answer, which I'm posting here for those how want short and sweet solutions:我浏览了这些帖子,最终以某种方式找到了一个简单的答案,我将其发布在这里,以供那些想要简短而贴心的解决方案的人使用:

  1. Use console.log("Hello World") in your script.在脚本中使用console.log("Hello World")
  2. Go to https://script.google.com/home/my and select your add-on.转到https://script.google.com/home/my并选择您的附加组件。
  3. Click on the ellipsis menu on Project Details, select Executions.单击项目详细信息上的省略号菜单,选择执行。

在此处输入图像描述

  1. Click on the header of the latest execution and read the log.单击最新执行的标题并阅读日志。

在此处输入图像描述

A little hacky, but I created an array called "console", and anytime I wanted to output to console I pushed to the array.有点 hacky,但我创建了一个名为“console”的数组,每当我想输出到控制台时,我都会将其推送到该数组。 Then whenever I wanted to see the actual output, I just returned console instead of whatever I was returning before.然后,每当我想查看实际输出时,我只返回console ,而不是之前返回的任何内容。

    //return 'console' //uncomment to output console
    return "actual output";
}

If you have the script editor open you will see the logs under View->Logs.如果您打开了脚本编辑器,您将在“查看”->“日志”下看到日志。 If your script has an onedit trigger, make a change to the spreadsheet which should trigger the function with the script editor opened in a second tab.如果您的脚本有 onedit 触发器,请使用在第二个选项卡中打开的脚本编辑器对应该触发该功能的电子表格进行更改。 Then go to the script editor tab and open the log.然后转到脚本编辑器选项卡并打开日志。 You will see whatever your function passes to the logger.您将看到您的函数传递给记录器的任何内容。

Basically as long as the script editor is open, the event will write to the log and show it for you.基本上只要打开脚本编辑器,事件就会写入日志并显示给您。 It will not show if someone else is in the file elsewhere.它不会显示其他人是否在其他地方的文件中。

I am having the same problem, I found the below on the web somewhere....我有同样的问题,我在网上的某个地方找到了下面的......

Event handlers in Docs are a little tricky though. Docs 中的事件处理程序虽然有点棘手。 Because docs can handle multiple simultaneous edits by multiple users, the event handlers are handled server-side.因为文档可以处理多个用户同时进行的多个编辑,所以事件处理程序是在服务器端处理的。 The major issue with this structure is that when an event trigger script fails, it fails on the server.这种结构的主要问题是,当事件触发脚本失败时,它会在服务器上失败。 If you want to see the debug info you'll need to setup an explicit trigger under the triggers menu that emails you the debug info when the event fails or else it will fail silently.如果您想查看调试信息,您需要在触发器菜单下设置一个显式触发器,当事件失败时通过电子邮件向您发送调试信息,否则它会静默失败。

It's far from elegant, but while debugging, I often log to the Logger, and then use getLog() to fetch its contents.它远非优雅,但在调试时,我经常登录到 Logger,然后使用getLog()获取其内容。 Then, I either:然后,我要么:

  • save the results to a variable (which can be inspected in the Google Scripts debugger—this works around cases where I can't set a breakpoint in some code, but I can set one in code that gets executed later)将结果保存到一个变量(可以在 Google Scripts 调试器中检查——这适用于我无法在某些代码中设置断点,但我可以在稍后执行的代码中设置断点的情况)
  • write it to some temporary DOM element将其写入某个临时 DOM 元素
  • display it in an alert警报中显示

Essentially, it just becomes a JavaScript output issue.本质上,它只是一个JavaScript 输出问题。

It grossly lacks the functionality of modern console.log() implementations, but the Logger does still help debug Google Scripts.它严重缺乏现代console.log()实现的功能,但 Logger 仍然有助于调试 Google 脚本。

Just as a notice.就像一个通知。 I made a test function for my spreadsheet.我为我的电子表格做了一个测试函数。 I use the variable google throws in the onEdit(e) function (I called it e).我在 onEdit(e) 函数中使用变量 google throws(我称之为 e)。 Then I made a test function like this:然后我做了一个这样的测试函数:

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())
}

Calling this test function makes all the code run as you had an event in the spreadsheet.调用此测试函数会使所有代码都像电子表格中的事件一样运行。 I just put in the possision of the cell i edited whitch gave me an unexpected result, setting value as the value i put into the cell.我只是放入了我编辑的单元格,这给了我一个意想不到的结果,将值设置为我放入单元格的值。 OBS: for more variables googles gives to the function go here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events OBS:有关谷歌为函数提供的更多变量,请访问此处: https ://developers.google.com/apps-script/guides/triggers/events#google_sheets_events

Currently you are confined to the container bound nature of using scripts within docs.目前,您仅限于在文档中使用脚本的容器绑定特性。 If you create a new script inside outside of docs then you will be able to export information to a google spreadsheet and use it like a logging tool.如果您在文档之外的内部创建一个新脚本,那么您将能够将信息导出到谷歌电子表格并将其用作日志记录工具。

For example in your first code block例如在您的第一个代码块中

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);

When I'm working with GAS I have two monitors ( you can use two windows ) set up with one containing the GAS environment and the other containing the SS so I can write information to and log.当我使用 GAS 时,我有两个监视器(您可以使用两个窗口),其中一个包含 GAS 环境,另一个包含 SS,因此我可以将信息写入和记录。

The dev console will log errors thrown by the app script, so you can just throw an error to get it logged as a normal console.log.开发控制台将记录应用脚本抛出的错误,因此您只需抛出一个错误即可将其记录为普通的 console.log。 It will stop execution, but it might still be useful for step by step debugging.它会停止执行,但它可能仍然对逐步调试有用。

throw Error('hello world!');

will show up in the console similarly to console.log('hello world')将类似于console.log('hello world')显示在控制台中

For Apps Script projects that are tied to a single Sheet (or doc) — in 2022 — there is no View menu like other answers suggest.对于绑定到单个工作表(或文档)的 Apps 脚本项目——在 2022 年——没有其他答案建议的View菜单。 Instead you need to look in the Executions menu on the left sidebar to see the executions of your onSelectionChange function (or any other function), from there you can click REFRESH until your console.log messages appear.相反,您需要查看左侧边栏的Executions菜单以查看您的onSelectionChange function(或任何其他函数)的执行,您可以从那里单击REFRESH ,直到出现您的console.log消息。 在此处输入图像描述

just debug your spreadsheet code like this:只需像这样调试电子表格代码:

...
throw whatAmI;
...

shows like this:显示如下:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM