Як налагодити сценарій Google Apps Script (він же записує журнал Logger.log?)


129

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

Отже, я намагався використовувати Logger.logметод для реєстрації деяких даних щоразу, коли onEditфункція викликається, але це теж здається, що вона працює лише під час запуску з Script Editor. Коли я запускаю його з Script Editor, я можу переглянути журнали, перейшовши доView->Logs...

Я сподівався, що зможу побачити журнали, коли подія насправді виконується, але я не можу це зрозуміти.

Як налагодити цей матеріал?


3
Тут же питання - прийнята відповідь не відповідає на це, але дає багато простої неправильної інформації.
Hippyjim

Схоже, вони зараз це виправили. Поки ви відкриваєте редактор сценаріїв із своєї таблиці, залишайте цю вкладку відкритою, коли ви запускаєте матеріали у своєму аркуші. Потім поверніться до вкладки сценарію, і в ній буде інформація про журнал.
фрікхед

2
tldr; Скопіюйте, вставте та запустітьLogger.log('firstLog');MailApp.sendEmail({to:'yourEmailAddressHere@someone.com',subject: "subject here ^_^",body: Logger.getLog()});
Coty Embry

Maby, вам слід змінити прийняту відповідь або додати примітку про те, що журнал Stackdriver доступний.
botenvouwer

Відповіді:


83

ОНОВЛЕННЯ:

Як написано у цій відповіді,

  • В даний час кращим методом ведення журналів є Stackdriver Logging .

  • Використовуйте console.log()для входу в Stackdriver.


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

Сценарій, над яким я намагався налагодити роботу, стосувався електронних таблиць - я створив реквізит типу "todo-контрольний список", який сортував елементи за пріоритетами та ін.

Єдині тригери, які я встановив для цього сценарію, були тригерами onOpen та onEdit. Налагодження тригера onEdit було найскладнішим для розуміння, тому що я думав, що якщо я встановлю точку перерви у своїй функції onEdit, відкрию електронну таблицю, відредагую комірку, що моя точка перерви буде запущена. Це не так.

Щоб імітувати, відредагувавши клітинку, мені все- таки довелося щось робити у фактичній таблиці. Все, що я робив, це переконатися, що клітина, яку я хочу, щоб вона трактувалась як "відредагована", була обрана, тоді Script Editorя б перейшов Run->onEdit. Тоді мій точку розриву вдарив би.

Однак мені довелося перестати використовувати аргумент події, який передається у функцію onEdit - ви не можете імітувати це, виконуючи Run->onEdit. Будь-яку інформацію, потрібну мені з електронної таблиці, наприклад, яку клітинку було вибрано тощо, я повинен був розібрати вручну.

У будь-якому випадку, довга відповідь, але я зрозумів це врешті-решт.


Редагувати :

Якщо ви хочете побачити контрольний список todo, який я зробив, ви можете переглянути його тут

(так, я знаю, що хтось може редагувати це - у цьому сенс ділитися ним!)

Я сподівався, що це також дозволить вам побачити сценарій. Оскільки ви його там не бачите, ось він:

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

Pff, журнал буде видно лише в пошті? Це свого роду робить усі ці функції налагодження та ведення журналу марними, оскільки ефективно ми не можемо використовувати реальні дані з електронної таблиці.
MrFox

Ні. Як сказав автор, журнал доступний у журналі (Редактор сценаріїв, Перегляд, Журнал або Ctrl-Enter)
rainabba

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

1
Раніше я не міг коментувати, тому надав відповідь нижче, але якщо у вас відкритий редактор сценаріїв і ви викликаєте подію у відкритій таблиці, ви можете повернутися до екземпляра браузера редактора сценаріїв і переглянути інформацію в журналах . Це добре працює, доки вам не доведеться тестувати щось у користувача, який не може відкрити скрипт, або того, до якого ви не можете ввійти як.
Karl_S

1
Ця відповідь застаріла, і її не слід розглядати як прийняту відповідь. Запис журналів Stackdriver доступний і працює як принадність. Подивіться на відповідь випадкових частин!
botenvouwer

34

Наскільки я можу сказати, ви не можете налагоджувати живу подію з google docs, тому вам доведеться робити це з налагоджувача, що безглуздо, оскільки аргумент події, переданий моїй функції onEdit (), завжди буде невизначений, якщо я запускаю це від редактора сценаріїв.

Правда - значить, самі визначте аргумент події для налагодження. Див. Як я можу перевірити функцію запуску в GAS?

Я намагався використовувати метод Logger.log для реєстрації деяких даних, коли викликається функція onEdit, але це теж здається, що це працює лише під час запуску з редактора сценаріїв. Коли я запускаю його з редактора сценаріїв, я можу переглянути журнали, перейшовши до меню Перегляд-> Журнали ...

Щоправда знову, але допомога є. Бібліотека BetterLog Пітера Германна буде перенаправляти всі журнали до електронної таблиці, що дозволяє вести журнал навіть з коду, який не приєднаний до екземпляра редактора / налагоджувача.

Наприклад, якщо ви кодуєте скрипт, що містить електронну таблицю, ви можете додати лише цей один рядок у верхню частину файлу сценарію, і всі журнали перейдуть на аркуш "Журнали" у таблиці. Не потрібен інший код, просто використовуйте так, Logger.log()як зазвичай:

Logger = BetterLog.useSpreadsheet();

1
Застаріла. console.log()повинна бути найкращою відповіддю зараз
TheMaster

22

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

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 з міткою, onEdit() Event Objectщоб побачити вихід


Оригінальне запитання спеціально задається о Logger.log. Чим це відрізняється від того, console.logяким ви користуєтесь? Я дуже новачок у інструментах, тому просто намагаюся зрозуміти, що все таке.
AnnanFay

5

Трохи хакі, але я створив масив під назвою "консоль", і щоразу, коли мені захотілося вивести його на консоль, я натиснув на масив. Тоді, коли я хотів побачити фактичний результат, я просто повертався consoleзамість того, до чого я повертався раніше.

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

у js console.log('smth')працює відмінно, а як же в GAS?
Ігор Савінкін

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

як щодо масиву "консолі"? Коли I just returned consoleви виводите його?
Ігор Савінкін

2
Вибачте, що я не дуже добре пояснив, але по суті функції електронних таблиць повертають значення в клітинку, тому, якщо ви повернете свою "консоль", ви побачите все, що ви зафіксували у вашій комірці електронної таблиці
woojoo666

5

Якщо у вас відкритий редактор сценаріїв, ви побачите журнали в розділі Вид-> Журнали. Якщо ваш скрипт має тригер onedit, внесіть зміни в електронну таблицю, яка повинна запустити функцію, коли редактор сценаріїв відкриється на другій вкладці. Потім перейдіть на вкладку редактора сценаріїв і відкрийте журнал. Ви побачите, що ваша функція переходить до реєстратора.

В основному, поки редактор сценаріїв відкритий, подія запише в журнал і покаже його вам. Він не покаже, чи є хтось інший у файлі в іншому місці.


5

Я переглянув ці пости і якось знайшов просту відповідь, яку я розміщую тут для тих, наскільки хочуть коротких і солодких рішень:

  1. Використовуйте console.log("Hello World")у своєму сценарії.
  2. Перейдіть на сторінку https://script.google.com/home/my та виберіть свій додаток.
  3. Клацніть на меню еліпсису у деталях проекту, виберіть Виконання.

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

  1. Клацніть на заголовку останнього виконання та прочитайте журнал.

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


Це основний "журнал Stackdriver" для скриптів Google Apps, створених після квітня 2019 року (що при доступі до Google Cloud Project для "автоматичних" проектів за програмами Scripts стало неможливим). Якщо ви змінили GCP для проекту Script Script, тоді застосовуються звичайні відповіді на ведення журналу Stackdriver.
tehhowch

1
Тут я бачу лише прямі виконання (тобто ті, для яких я натиснув "запустити" в редакторі сценаріїв), але я не бачу виконання, спричинені зміною даних на аркуші. Як я налагоджую їх?
Cris70

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

1
Так, я б теж уявив це. На жаль, це не відбувається :-( Зміни в даних запускають мою функцію, але повідомлення console.log () не відображаються в журналі Stackdriver. Я намагався додати активатор змін, але це викликає мою функцію без параметрів: - (
Cris70

4

У мене є та сама проблема, я знайшов нижче в Інтернеті десь ....

Обробники подій у Документах хоч трохи складні. Оскільки документи можуть обробляти декілька одночасних редагувань кількома користувачами, обробниками подій обробляються на стороні сервера. Основна проблема цієї структури полягає в тому, що коли сценарій тригера події виходить з ладу, він не працює на сервері. Якщо ви хочете побачити інформацію про налагодження, вам потрібно встановити явний тригер під меню тригерів, який надсилатиме вам електронну пошту про інформацію про налагодження, коли подія виходить з ладу, інакше вона вийде з ладу.


Гм, так, я зіткнувся з цим - на наступний ранок мені надіслано цілу купу помилок із моїх сценаріїв. Я все-таки з'ясував це, хоча (розміщую власну відповідь зараз)
d0c_s4vage

1

Це далеко не елегантно, але під час налагодження я часто входжу до Logger, а потім використовую getLog (), щоб отримати його вміст. Тоді я або:

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

По суті, це просто стає проблемою виводу JavaScript .

Це вкрай не вистачає функціоналу сучасних console.log()реалізацій, але Logger все ще допомагає налагоджувати Google Scripts.


1

Тільки як повідомлення. Я зробив тестову функцію для своєї електронної таблиці. Я використовую зміни змінних google у функції 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())
}

Виклик цієї тестової функції змушує весь код виконуватись так, як у вас відбулася подія в електронній таблиці. Я просто помістив можливість осередку, і я відредагував, що дало мені несподіваний результат, встановивши значення як значення, яке я вклав у комірку. ЗАБУДОВА! для отримання додаткових змінних googles дає функцію перейти сюди: 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;
...

показує так:

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


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