Google Apps Scriptでデバッグするイロハ集【GAS】
Google Apps Scriptでアプリを開発するには様々なメソッドを覚えることも重要ですが、何よりも「デバッグする」手法をきちんと身につけておく必要があります。通常のプログラミング言語と同様の手法が必ずしも出来るわけではないのと、割と最近まで原始的なデバッグ方法しか手もなかったというのもあります。
そこで今回は自分がGASでデバッグする際に利用してる手法をまとめてみました。エラートラップについては別のエントリーでまとめています。
目次
通常のデバッグ手法
ログ出力
V8対応の新対応前にはLogger.logしかなかったGoogle Apps Script。現在の新IDEになってからは通常使うデバッグ用のメソッドはconsole.logが主流になっています。原始的な手法ですが、変数の中身やエラーメッセージを取得して出力するという点では基礎の基礎なのがログ出力です。
現在のGASで使えるログ出力のメソッドパターンは以下の5種類です。console.log系はV8構文からはテンプレートリテラルなども使えるようになっています。
- Logger.log : 最も基礎的なログ出力。V8以前から現在も利用可能
- console.log : 現在最も普通に使われてるログ出力。引数で色々と指定が可能。以下は引数(フォーマット文字列)を取って変数を当て込む出力方法です。
//一般的なログ出力 var str = "してみました" console.log('文字列の出力 : %s', str) //出力結果 20:28:32 情報 文字列の出力 : してみました - console.info:エラーではないけれど情報出力として利用する
- console.warn:警告文を出す場合に使用する。オレンジ色出力で実行ログに出力されます。
- console.error : エラーとして出力する。赤色出力で実行ログに出力されます。
GASでは利用できないconsole出力のメソッドがあったりもするので、そこだけは注意です。
図:色々と使い分けが可能です。
JSONを整形してログ出力
console.logなのですが、JavaScriptの連想配列などのオブジェクトの中身を出力する場合、そのままだと非常に見にくい。REST APIなどでデータを取ってきたときに整形して表示するようにするとデバッグしやすくなります。
function seikeiman(){
let obj = {
name : "nyancat",
phone : "0120-222-222",
company : "nyannyan house"
}
//インデントで整形出力
console.log(JSON.stringify(obj, null, 2));
//タブで整形出力
console.log(JSON.stringify(obj, null, '\t'));
}
図:キレイに整形されるので見やすくなる
計測時間を出力する
自分のプログラムのベンチマークなどを取るために開始時刻と終了時刻を取ってログ出力したい場合があります。古いやり方だと以下のようなコードで差分を取って出力します。
function oldtimewatch(){
//現在時刻を取得する
let starttime = new Date();
Utilities.sleep(3000)
//終了時刻との差分を算出して、メッセージを表示
let endtime = new Date();
let diff = (endtime.getTime()-starttime.getTime()) / 1000;
console.log(diff + "ミリ秒掛かった");
}
Google Apps ScriptはV8からconsoleが拡張されていて、以下のような書き方も可能になっています。timeとtimeEndは同じ引数を取る必要があります。
function timewatch(){
var label = '経過時間調査';
console.time(label);
Utilities.sleep(3000)
console.timeEnd(label);
}
図:こんな具合にベンチが取れる
onEditをデバッグする
自作のユーザ定義関数や編集時イベントのシンプルトリガーであるonEditをデバッグするには引数のeを分解して表示するようにし、実行数次項の実行数から確認すると良いでしょう。
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});
}
図:onEditも引数を分解してデバッグ出来る
doGetをデバッグする
doGetについては新IDEになってからはparameterを普通に取得してデバッグ出力が可能になっています。doPostはこのままでは出来ないので、後述の高度なデバッグ手法を参照してください。左サイドバーの実行数から、doGetの中身を確認すれば取得が可能です。
function doGet(e) {
//受け取るパラメータを用意する
var filterparam = e.parameter.param1;
console.log(filterparam)
}
図:doGetはきちんと取得が可能
実行数から確認する
過去の実行ログ出力結果は、スクリプトエディタやダッシュボードの実行数から確認することが可能です。スクリプトエディタの場合、左サイドバーの実行数から開くことが可能です。
実行ログは直後のログは確認出来ますが、それ以前のログは実行数に蓄えられてるので、そちらで確認することになります。
図:実行数から過去のログ出力を確認
BetterLogを利用する
Google Apps ScriptのライブラリであるBetterLogを利用して、スプレッドシートにログを出力するという方法もあります。スクリプトIDをライブラリに追加してから以下のようなコードを実行すると、指定したスプレッドシートにLogというシートを作成して、そこにロギング内容を出力します。Logger.logを上書きして実行します。
function breakpoint(){
var point = 10
Logger = BetterLog.useSpreadsheet('スプレッドシートのIDをここに入れる');
for(var i = 0;i<10;i++){
var temppoint = point + i;
Logger.log(temppoint);
}
}
図:ログをスプレッドシートに出力するライブラリ
Google Formsの場合のデバッグ手法
Google Formsにスクリプトを記述して、送信されてきた値をデバッグしてコードを記述する。こういうシーンは多いですが、その度に毎回Formを開いて送信する内容を記述して・・・なんてやってたら日が暮れてしまいます。
そこでFormsで一回送信して於いて、デバッグする時はFormsに蓄積されてるデータを引っ張り出して検証するという手法がオススメです。通常は以下のようなコードを記述します
function sendForms(e){
//変数を宣言する
var user = ""; //メールアドレス格納用
var body =""; //本文用変数
//フォームデータを取得する
var formdata = e.response.getItemResponses();
//ループでメアド取得&入力値を本文に加える
for (var j = 0; j < formdata.length; j++){
//入力項目名を取得する
var title = formdata[j].getItem().getTitle();
//メールアドレスを取得する
if(title == "メールアドレス"){
user = formdata[j].getResponse();
}
//入力項目を入れる(タイトルと入力値)
body += "【"+formdata[j].getItem().getTitle()+"】<br>";
body += formdata[j].getResponse()+"<br><br>";
}
}
e.response.getItemResponsesが送られてきた中身を取得してくれるものですが、これだと毎回送信が必要なので、一回送信しておいて蓄積されてるデータでデバッグする場合にはe.responseの代わりに以下の内容に置き換える
function sendman(e){
var formdata = FormApp.getActiveForm().getResponses()[0].getItemResponses();
}
これで蓄積されてる0番目のデータの塊を取得出来るので、これを元にあとのコードをデバッグすればオッケー。本番運用時はこの部分を元のe.responseに置き換えておけば良い。
高度なデバッグ手法
ブレークポイントで変数を監視
Google Apps ScriptにもVBAのようにブレークポイントを設置して、そこで一時停止させて変数の中身を確認しつつ、ステップインで次の実行といったことが可能になっています。
コードの止めたい場所の左側に○を打てるので、クリックするとブレークポイントが設置されます。そして、通常のように関数を実行するのではなく、メニューにある「デバッグ」をクリックして実行するとブレークポイントで一時停止して、右サイドに変数の中身などが表示されて遷移を確認しながら、再開ボタンを押せば次のステップを実行できます。
またこの時、globalを展開するとグローバルオブジェクトも確認が可能になっています。
ログエクスプローラを使う
実はGoogle Apps Scriptでは以前はStackDriver Loggingという名称で高度なデバッギング環境を使うことが出来ました。現在はこれはログエクスプローラと改名されて、GCP側で高度なログ解析が出来るようになっています。Google Cloud FunctionsなどのNode.jsのデバッグ等でも利用されるもので、GASでdoPostの場合console.logでログ出力がされないものも、この機能だときっちりログを取得する事が可能になっています。
GASで使う場合には、以下の手順でプロジェクトとGCP側のプロジェクトを紐付けにする必要があります。
プロジェクトを移動する
図:プロジェクト変更画面
ログエクスプローラを開く
紐付けが完了し、doPostなどのログを見たいと思ったら、以下の手順でログエクスプローラで閲覧が可能です。
- ログエクスプローラを開く
- 全てのログが一箇所に集まってるので、時刻や日付などでフィルタしつつ使います。
- ログのフィールドのApps Script関数をクリックして絞り込みする
- 対象のログ出力を展開して中身を確認する
また、GAS側の実行数からCloudのログを開いても直接ジャンプして中身を確認出来ます。
図:ちょっと高度なので慣れが必要です。
Developer Toolを使う
Google Apps Scriptだけのプログラムならば不要ですが、実際にはウェブアプリケーションも作る機会は非常に多いです。しかし、HTML側のデバッグはGAS側で行わせるというのは難しい。ということはやはり、ChromeのDeveloper Toolを使っての変数の変化やElement内容の確認等が必要になります。通常のウェブ開発と同様にGASのウェブアプリも同様にデバッグが可能になっています。
また、GASのウェブアプリの場合のエラー出力はGAS側のエラーもデバッグコンソールに出力されたりするので、ちょっとだけやりやすいです。
GASのウェブアプリの主要なパーツの上で右クリック→検証で表示して要素の中身を見てみたり、F12キーで表示も可能。
図:Developer Toolでデバッグ中
AppSheet連携
AppSheetからスタンドアローンコンテナとして呼び出されるGoogle Apps Scriptのデバッグは簡単です。通常通りconsole.logでログ出しをすれば、実行数から確認することが可能です。
また、Apps ScriptからAppSheet側へReturnした時の値については、AppSheet側でMonitorを開き実行した時間を開くことで確認が可能です。
- Automationの対象のBotを開く
- 真ん中のパネル上部にある「Monitor」をクリックする
- AppSheet Monitoringという新しいウィンドウが開きます
- 右下のProcess>Steps>DetailにJSON形式で値が出ます。この中のTask Propertiesを見る
- ReturnValueに型とその値が入ってるのでこれで受け取った値を確認出来る
図:普通にログに残ります
図:Monitorから確認も可能













