Как отлаживать скрипт Google Apps (также как и куда входит Logger.log?)


129

В Google Таблицах вы можете добавить некоторые функции создания сценариев. Я добавляю что-то для onEditмероприятия, но не могу сказать, работает ли это. Насколько я могу судить, вы не можете отлаживать живое событие из Google Sheets, поэтому вам придется делать это из отладчика, что бессмысленно, поскольку аргумент события, переданный моей onEdit()функции, всегда будет неопределенным, если я запустил его из Script Editor,

Итак, я пытался использовать этот Logger.logметод для регистрации некоторых данных при каждом onEditвызове функции, но это тоже похоже на то, что он работает только при запуске из Script Editor. Когда я запускаю его из Script Editor, я могу просмотреть журналы, перейдя вView->Logs...

Я надеялся, что смогу увидеть журналы с момента фактического выполнения события, но я не мог этого понять.

Как мне отладить этот материал?


3
Здесь та же проблема - принятый ответ не отвечает на него, но дает много простой неправильной информации.
Hippyjim

Кажется, сейчас исправили. Пока вы открываете редактор сценариев из своей электронной таблицы, оставьте эту вкладку открытой при запуске материала в своей таблице. Затем вернитесь на вкладку скрипта, и в нем будет информация о регистрации.
phreakhead

2
tldr; копировать, вставлять и запускатьLogger.log('firstLog');MailApp.sendEmail({to:'yourEmailAddressHere@someone.com',subject: "subject here ^_^",body: Logger.getLog()});
Коти Эмбри

Маби, вы должны изменить принятый ответ или добавить примечание о том, что Stackdriver Logging доступен.
botenvouwer

Ответы:


83

ОБНОВИТЬ:

Как написано в этом ответе,


Logger.logлибо отправит вам электронное письмо (в конечном итоге) об ошибках, которые произошли в ваших скриптах, либо, если вы запускаете что-то из Script Editor, вы можете просмотреть журнал из последней функции запуска, перейдя в View->Logs(все еще в редакторе скриптов). Опять же, это покажет вам только то, что было зарегистрировано последней функцией, которую вы запускали изнутриScript Editor .

Сценарий, который я пытался заставить работать, был связан с электронными таблицами - я сделал что-то вроде списка дел, в котором элементы сортируются по приоритетам и так далее.

Единственными триггерами, которые я установил для этого сценария, были триггеры onOpen и onEdit. Отладка триггера onEdit была труднее всего, потому что я все думал, что если я установлю точку останова в своей функции onEdit, открою электронную таблицу, отредактирую ячейку, моя точка останова сработает. Это не вариант.

Чтобы смоделировать редактирование ячейки, мне все же пришлось что-то делать в реальной электронной таблице. Все , что я сделал , было убедитесь , что клетка, я хотел его рассматривать в качестве «отредактированы» был выбран, то в Script Editor, я пошел бы Run->onEdit. Тогда будет достигнута моя точка останова.

Однако мне пришлось прекратить использовать аргумент события, который передается в функцию onEdit - вы не можете смоделировать это, сделав это Run->onEdit. Любую информацию, которая мне была нужна из электронной таблицы, например, какая ячейка была выбрана, и т.д., мне приходилось выяснять вручную.

В любом случае, длинный ответ, но в конце концов я понял это.


ИЗМЕНИТЬ :

Если вы хотите увидеть список дел, который я составил, вы можете проверить его здесь

(да, я знаю, что кто угодно может его редактировать - в этом смысл делиться!)

Я надеялся, что это также позволит вам увидеть сценарий. Так как вы его не видите, вот оно:

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

Пфф, лог будет виден только в почте? Это делает все эти функции отладки и регистрации бесполезными, потому что мы не можем использовать реальные данные из электронной таблицы.
MrFox

Нет. Как сказал автор, ведение журнала доступно в журнале (редактор сценариев, просмотр, журнал или Ctrl-Enter)
rainabba

9
@rainabba Да, ведение журнала доступно в редакторе скриптов. Однако, когда сценарий зависит от аргумента события, а аргумент события недоступен в редакторе сценариев, это фактически означает, что разработчики сценариев этих типов не имеют доступа к журналам в реальном времени.
Джефф

1
Я не мог комментировать раньше, поэтому я предоставил ответ ниже, но: ЕСЛИ у вас открыт редактор сценариев и ВЫ запускаете событие в открытой электронной таблице, вы можете вернуться к экземпляру браузера редактора сценариев и просмотреть информацию в журналах , Он работает хорошо до тех пор, пока вам не нужно что-то тестировать под пользователем, который не может открыть скрипт или под которым вы не можете войти.
Karl_S

1
Этот ответ устарел, и его не следует рассматривать как принятый. Stackdriver Logging доступен и работает как шарм. Взгляните на ответ случайных частей!
botenvouwer

34

Насколько я могу судить, вы не можете отлаживать живое событие из документов Google, поэтому вам нужно делать это из отладчика, что бессмысленно, поскольку аргумент события, переданный моей функции onEdit (), всегда будет неопределенным, если я запустил это из редактора скриптов.

Верно - так что определите аргумент события самостоятельно для отладки. См. Как я могу проверить функцию триггера в GAS?

Я пытался использовать метод Logger.log для регистрации некоторых данных всякий раз, когда вызывается функция onEdit, но похоже, что он работает только при запуске из редактора сценариев. Когда я запускаю его из редактора скриптов, я могу просматривать журналы, перейдя в View-> Logs ...

Опять же, правда, но помощь есть. Библиотека BetterLog Питера Германа перенаправит все журналы в электронную таблицу, что позволит вести журнал даже из кода, который не прикреплен к экземпляру редактора / отладчика.

Если вы кодируете сценарий, содержащий электронную таблицу, например, вы можете добавить только эту одну строку в начало файла сценария, и все журналы перейдут на лист «Журналы» в электронной таблице. Никакого другого кода не требуется, просто используйте, Logger.log()как обычно:

Logger = BetterLog.useSpreadsheet();

1
Устаревшие. console.log()должен быть лучшим ответом сейчас
TheMaster 05

22

Обновление 2017 г .: Stackdriver Logging теперь доступно для скрипта Google Apps. В строке меню редактора сценария выберите: перейти View > Stackdriver Loggingк просмотру или потоковой передаче журналов.

console.log () будет писать DEBUGсообщения уровня

Пример 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});
}

Затем проверьте журналы в Stackdriver UI маркированы , onEdit() Event Objectчтобы увидеть результат


Исходный вопрос конкретно спрашивает о Logger.log. Чем это отличается от того, console.logчто вы используете? Я новичок в инструментах, поэтому просто пытаюсь понять, что все такое.
AnnanFay

5

Немного хакерский, но я создал массив под названием «console», и всякий раз, когда мне нужно было вывести на консоль, я вставлял его в массив. Затем всякий раз, когда я хотел увидеть фактический результат, я просто возвращал consoleвместо того, что возвращал раньше.

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

в js console.log('smth')работает отлично, а в ГАЗе?
Игорь Савинкин

1
console.log не будет работать просто потому, что GAS - это не сценарии, работающие на той же веб-странице, что и ваша электронная таблица, это сценарии, обрабатываемые движком приложений Google, поэтому вам нужно следовать их громоздкому отладчику Logger.log или использовать хак, подобный моему
woojoo666

как насчет вашей консоли массива? Когда I just returned consoleкак его выводить?
Игорь Савинкин

2
Извините, я не очень хорошо объяснил, но, по сути, функции электронных таблиц возвращают значение в ячейку, поэтому, если вы
вернете

5

Если у вас открыт редактор сценариев, вы увидите журналы в разделе «Просмотр»> «Журналы». Если в вашем сценарии есть триггер onedit, внесите изменения в электронную таблицу, которые должны запускать функцию с помощью редактора сценария, открытого на второй вкладке. Затем перейдите на вкладку редактора скриптов и откройте журнал. Вы увидите, что ваша функция передает регистратору.

Обычно, пока открыт редактор скриптов, событие будет записываться в журнал и показывать его вам. Он не будет показывать, есть ли кто-то еще в файле где-либо еще.


5

Я просмотрел эти сообщения и каким-то образом нашел простой ответ, который я публикую здесь для тех, кому нужны короткие и приятные решения:

  1. Используйте console.log("Hello World")в своем сценарии.
  2. Перейдите на страницу https://script.google.com/home/my и выберите свое дополнение.
  3. Нажмите на многоточие в меню «Сведения о проекте» и выберите «Выполнения».

введите описание изображения здесь

  1. Щелкните заголовок последнего выполнения и прочтите журнал.

введите описание изображения здесь


Это базовое «ведение журнала Stackdriver» для скриптов Google Apps, созданное после апреля 2019 г. (когда доступ к проекту Google Cloud для «автоматических» проектов, стоящих за скриптами приложений, стал невозможным). Если вы измените GCP для проекта Apps Script, будут применяться обычные ответы на ведение журнала Stackdriver.
tehhowch

1
Я вижу здесь только прямые исполнения (то есть те, для которых я щелкнул "запустить" в редакторе скриптов), но я не вижу выполнения, вызванные изменением данных в таблице. Как мне их отладить?
Cris70

Я не пробовал этого, извините. Я бы предположил, что если изменение в листе запускает функцию, и у функции есть журнал, журнал будет отображаться вместе. Изменения всегда будут инициированы пользователем, верно?
Бенджамин

1
Да, я тоже мог это представить. К сожалению, это не то, что происходит :-( Изменения данных действительно вызывают мою функцию, но сообщения console.log () не отображаются в журнале Stackdriver. Я попытался добавить активатор при изменении, но он вызывает мою функцию без параметров: - (
Cris70

4

У меня такая же проблема, я где-то нашел в Интернете следующее ....

Однако обработчики событий в Документах немного сложны. Поскольку документы могут обрабатывать несколько одновременных изменений, вносимых несколькими пользователями, обработчики событий обрабатываются на стороне сервера. Основная проблема с этой структурой заключается в том, что при сбое сценария триггера события происходит сбой на сервере. Если вы хотите увидеть информацию об отладке, вам необходимо настроить явный триггер в меню триггеров, который отправляет вам информацию об отладке по электронной почте, когда событие не удается, иначе оно не будет работать тихо.


Хм, да, я столкнулся с этим - на следующее утро он прислал мне по электронной почте целую кучу ошибок из моих скриптов. Тем не менее, я все же
понял

1

Это далеко не элегантно, но во время отладки я часто регистрируюсь в Logger, а затем использую getLog () для получения его содержимого. Тогда я либо:

  • сохранить результаты в переменную (которую можно проверить в отладчике Google Scripts - это работает в случаях, когда я не могу установить точку останова в некотором коде, но я могу установить ее в коде, который выполняется позже)
  • записать его во временный элемент DOM
  • отображать это в предупреждении

По сути, это просто проблема вывода JavaScript .

Ему явно не хватает функциональности современных console.log()реализаций, но Logger по-прежнему помогает отлаживать скрипты Google.


1

Просто в качестве примечания. Я сделал тестовую функцию для своей таблицы. Я использую переменную google throws в функции onEdit (e) (я назвал ее e). Затем я сделал такую ​​тестовую функцию:

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

Вызов этой тестовой функции запускает весь код, как если бы у вас было событие в электронной таблице. Я просто добавил возможность ячейки, которую я редактировал, что дало мне неожиданный результат, установив значение как значение, которое я ввел в ячейку. OBS! для дополнительных переменных, которые Google предоставляет функции, перейдите сюда: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events


0

В настоящее время вы ограничены природой, связанной с контейнером, при использовании скриптов в документах. Если вы создадите новый скрипт вне документации, вы сможете экспортировать информацию в электронную таблицу Google и использовать ее как инструмент для ведения журнала.

Например, в вашем первом блоке кода

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

Когда я работаю с GAS, у меня есть два монитора (вы можете использовать два окна), один из которых содержит среду GAS, а другой - SS, поэтому я могу записывать информацию и регистрировать.


0

Консоль разработчика будет регистрировать ошибки, вызванные сценарием приложения, поэтому вы можете просто выдать ошибку, чтобы она регистрировалась как обычный console.log. Он остановит выполнение, но может быть полезен для пошаговой отладки.

throw Error('hello world!');

будет отображаться в консоли аналогично console.log('hello world')


0

просто отлаживайте код своей электронной таблицы следующим образом:

...
throw whatAmI;
...

показывает так:

введите описание изображения здесь


Я думаю, вам следует упомянуть, что изображение показывает, как пользовательская функция показывает ошибку, но OP упоминает, что он использует простой триггер ( onEdit)
Рубен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.