Google Sheets и Apps Script: как использовать Logger для отладки?

Отладка является неотъемлемой частью разработки любого программного обеспечения, и скрипты Google Apps Script не исключение. Встроенный инструмент Logger предоставляет простой, но мощный механизм для логирования информации во время выполнения скрипта, что значительно упрощает процесс поиска и исправления ошибок.

Что такое Logger и зачем он нужен?

Logger — это глобальный объект в Google Apps Script, предоставляющий базовые возможности логирования. Он позволяет разработчикам выводить текстовые сообщения, значения переменных и содержимое объектов в специальную консоль логов в редакторе скриптов. Основное назначение Logger — предоставить разработчику информацию о состоянии скрипта и значениях данных в различных точках его выполнения без прерывания работы самого скрипта, в отличие от точек останова (breakpoints) в отладчике.

Основные принципы отладки в Google Apps Script

Отладка в Apps Script включает несколько подходов:

Использование Logger: Вывод промежуточных значений и сообщений о ходе выполнения.

Использование встроенного отладчика: Пошаговое выполнение кода, установка точек останова и просмотр значений переменных в реальном времени.

Обработка исключений: Использование блоков try...catch для перехвата и анализа ошибок во время выполнения.

Logger особенно полезен для отладки триггеров (например, onEdit, onOpen), веб-приложений или скриптов, выполняющихся длительное время, где использование интерактивного отладчика может быть затруднительным или невозможным.

Преимущества использования Logger для отладки скриптов Google Sheets

При работе с Google Sheets Logger предлагает несколько преимуществ:

Неинтрузивность: Логирование не изменяет данные в таблице и не прерывает выполнение скрипта для пользователя.

Простота: Не требует сложной настройки, в отличие от полноценных систем логирования.

Отладка сложных сценариев: Помогает понять логику работы скриптов, взаимодействующих с большими объемами данных, внешними API или сложными формулами.

Асинхронный анализ: Логи можно просмотреть после завершения выполнения скрипта, что удобно для анализа длительных операций.

Основы работы с Logger в Apps Script

Работа с Logger интуитивно понятна и требует знания всего нескольких методов.

Синтаксис и методы Logger: log(), logAll(), getLog()

Основные методы объекта Logger:

Logger.log(data): Записывает переданное значение data (строку, число, объект) в лог. Если передан нестроковый тип, Apps Script попытается преобразовать его в строку.

Logger.log(format, ...values): Позволяет форматировать строку вывода, используя спецификаторы формата, аналогичные Utilities.formatString() (например, %s для строк, %d для чисел).

Logger.clear(): Очищает текущий лог. Примечание: Доступность этого метода может зависеть от контекста выполнения.

Logger.getLog(): Возвращает весь накопленный лог в виде одной строки. Это полезно для программной обработки логов, например, отправки их по электронной почте или сохранения в ячейку таблицы.

Простой пример использования Logger для записи данных

/**
 * Простая функция для демонстрации Logger.log()
 */
function logSimpleMessage(): void {
  const campaignName: string = 'Summer Sale 2024';
  const budget: number = 500.50;

  Logger.log('Запуск обработки кампании...');
  Logger.log('Название кампании: ' + campaignName);
  Logger.log('Бюджет: ' + budget);

  // Пример форматированного вывода
  Logger.log('Обработка кампании %s с бюджетом %.2f завершена.', campaignName, budget);
}

Чтобы просмотреть вывод, запустите функцию logSimpleMessage в редакторе скриптов и затем выберите в меню View > Logs (или нажмите Ctrl+Enter / Cmd+Enter).

Вывод переменных различных типов: строки, числа, массивы, объекты

Logger может выводить переменные различных типов, автоматически преобразуя их в строковое представление.

/**
 * Демонстрация вывода различных типов данных с помощью Logger.
 */
function logDataTypes(): void {
  const clicks: number = 150;
  const ctr: number = 0.025;
  const isActive: boolean = true;
  const keywords: string[] = ['google sheets', 'apps script', 'logger'];
  const campaignData: { name: string; clicks: number; conversions: number | null } = {
    name: 'Lead Generation Q3',
    clicks: clicks,
    conversions: 25
  };
  const emptyValue: null = null;

  Logger.log('Clicks: ' + clicks); // Число
  Logger.log('CTR: %s', ctr); // Число (форматированное)
  Logger.log('Is Active: ' + isActive); // Булево
  Logger.log('Keywords: ' + keywords); // Массив (преобразуется в строку 'google sheets,apps script,logger')
  Logger.log('Campaign Data: ' + JSON.stringify(campaignData, null, 2)); // Объект (используем JSON.stringify для читаемости)
  Logger.log('Conversions: ' + campaignData.conversions);
  Logger.log('Empty Value: ' + emptyValue); // Null
}

Обратите внимание, что для объектов и массивов стандартный вывод Logger.log() может быть не всегда информативным. Использование JSON.stringify() часто предпочтительнее для сложных структур данных.

Реклама

Продвинутые техники отладки с использованием Logger

Помимо базового вывода, Logger можно использовать для более сложных сценариев отладки.

Условный вывод в Logger: отладка только при определенных условиях

Часто нет необходимости логировать информацию при каждом запуске. Можно использовать условные операторы if для вывода логов только при выполнении определенных условий, например, при обработке конкретной кампании или при возникновении ошибки.

/**
 * Обрабатывает данные рекламной кампании, логируя только при низком CTR.
 * @param {string} campaignName Имя кампании.
 * @param {number} clicks Количество кликов.
 * @param {number} impressions Количество показов.
 */
function processCampaignData(campaignName: string, clicks: number, impressions: number): void {
  if (impressions === 0) {
    Logger.log('Предупреждение: Количество показов равно нулю для кампании %s.', campaignName);
    return;
  }

  const ctr: number = clicks / impressions;
  const threshold: number = 0.01; // Порог CTR

  // Логируем только если CTR ниже порога
  if (ctr < threshold) {
    Logger.log('Низкий CTR для кампании %s: %.4f (Клики: %d, Показы: %d)', 
               campaignName, ctr, clicks, impressions);
  }

  // ... остальная логика обработки ...
}

// Пример вызова
processCampaignData('Low Performer Campaign', 5, 1000); // Этот вызов попадет в лог
processCampaignData('High Performer Campaign', 50, 1000); // Этот вызов не попадет в лог

Использование Logger для трассировки выполнения кода

Чтобы понять последовательность вызовов функций или выполнение циклов, можно размещать Logger.log() в начале и конце функций или внутри итераций цикла.

/**
 * Основная функция, вызывающая вспомогательные.
 */
function mainProcessingFunction(): void {
  Logger.log('Старт mainProcessingFunction');
  const data: string[][] = fetchDataFromSheet();
  processData(data);
  Logger.log('Финиш mainProcessingFunction');
}

/**
 * Условная функция получения данных.
 * @returns {string[][]} Массив данных.
 */
function fetchDataFromSheet(): string[][] {
  Logger.log('--> Старт fetchDataFromSheet');
  // ... логика получения данных ...
  const sampleData: string[][] = [['ID', 'Value'], ['1', 'A'], ['2', 'B']];
  Logger.log('--> Финиш fetchDataFromSheet');
  return sampleData;
}

/**
 * Условная функция обработки данных.
 * @param {string[][]} data Массив данных для обработки.
 */
function processData(data: string[][]): void {
  Logger.log('----> Старт processData');
  for (let i = 0; i  Обработка строки %d: %s', i, data[i].join(', '));
    // ... логика обработки строки ...
  }
  Logger.log('----> Финиш processData');
}

Отладка ошибок: запись сообщений об ошибках в Logger

Блоки try...catch идеально подходят для перехвата ошибок выполнения. В блоке catch можно использовать Logger.log() для записи детальной информации об ошибке, включая сообщение и, при необходимости, стек вызовов.

/**
 * Пример функции с обработкой ошибок и логированием.
 */
function processWithPotentialError(): void {
  try {
    Logger.log('Попытка выполнить операцию...');
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('NonExistentSheet');
    // Эта строка вызовет ошибку, если лист не существует
    const value = sheet.getRange('A1').getValue(); 
    Logger.log('Операция успешна, значение: ' + value);
  } catch (error) {
    Logger.log('Произошла ошибка!');
    // Логируем само сообщение об ошибке
    Logger.log('Сообщение: ' + error.message);
    // Логируем стек вызовов (может быть полезно для сложных скриптов)
    Logger.log('Стек: ' + error.stack);
    // Логируем весь объект ошибки для детального анализа
    Logger.log('Объект ошибки: ' + JSON.stringify(error, null, 2));
  }
}

Форматирование вывода Logger для лучшей читаемости

Для улучшения читаемости логов можно использовать:

Отступы: Как показано в примере трассировки, отступы помогают визуально отделить уровни вложенности вызовов.

Префиксы: Добавляйте префиксы (INFO:, WARN:, ERROR:, DEBUG:) для классификации сообщений.

Разделители: Используйте строки типа --- или === для разделения логических блоков в логе.

JSON.stringify(): Для структурированного вывода объектов и массивов.

/**
 * Пример форматированного вывода.
 */
function formattedLogging(): void {
  const userId: number = 123;
  const userAction: string = 'updateProfile';

  Logger.log('INFO: Начало операции для пользователя %d', userId);
  Logger.log('DEBUG: Параметры действия: %s', userAction);
  Logger.log('====================================');

  // Имитация какой-то работы
  const result: { status: string; data: any } = { status: 'success', data: { userId: userId, timestamp: new Date().toISOString() } };

  Logger.log('DEBUG: Результат операции: %s', JSON.stringify(result, null, 2));
  Logger.log('INFO: Операция для пользователя %d завершена успешно.', userId);
}

Практические примеры использования Logger в Google Sheets

Рассмотрим сценарии применения Logger при работе с Google Sheets.

Отладка скрипта, который читает данные из Google Sheets

При чтении данных важно убедиться, что скрипт получает ожидаемый диапазон и корректные значения.

/**
 * Читает данные о расходах из листа 'Expenses' и логирует их.
 */
function logExpenseData(): void {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('Expenses');

  if (!sheet) {
    Logger.log('ERROR: Лист

Добавить комментарий