有没有办法阅读已发布的google apps脚本的日志?
目前,我可以在调试模式下使用Logger.log()
获取日志。
但是当我们在发布脚本时遇到某些问题时,就无法实现其原因。
答案 0 :(得分:2)
这是我用于记录和错误检查的调试对象。它总是写入Logger,但也写入一个名为" log"在链接的电子表格中。我已经从我正在处理的脚本(Flubaroo)中复制了这个内容,因此可能会遗漏一些外部函数。
// debug.gas.gs
// ============
//
// Development/debug functions.
// TODO_AJR - Add function name as first parameter of logging functions
// TODO_AJR - Generally, should there be some indication to the user that,
// there has been an error when debug is turned off? Couldn't we try and
// catch the errors further up rather than ignoring them in production and
// letting GAS catch them in debug.
// Unit Tests
// ==========
// testDebugClass()
// ----------------
//
// Unit tests for DebugClass(). Check log for results.
function testDebugClass()
{
Debug.info("testDebugClass() - PASS - info test call");
Debug.warning("testDebugClass() - PASS - warning test call");
Debug.assert_w(false, "testDebugClass() - PASS - assert_w test call");
// This will test Debug.error().
Debug.assert(true, "testDebugClass() - FAIL - Should not see this");
Debug.info("testDebugClass() - All tests PASSED");
return true;
} // testDebugClass()
// Debug Service
// =============
Debug = new DebugClass();
function DebugClass()
{
this.debugOn = DEBUG_ON;
this.loggingOn = LOGGING_ON;
this.log_sheet;
this.last_msg;
} // DebugClass()
// DebugClass.info()
// -----------------
//
// Output debug trace.
DebugClass.prototype.info = function(msg)
{
Logger.log(msg);
this.last_msg = msg;
if (!this.loggingOn)
{
return;
}
if (typeof this.log_sheet === 'undefined')
{
// Store log sheet name.
this.log_sheet = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(LOG_SHEET_NAME);
if (this.log_sheet === null)
{
// TODO_AJR - Could create it.
// TODO_AJR - use langStr.
Browser.msgBox(langstr("FLB_STR_NOTIFICATION"),
"You need to create a sheet called " +
LOG_SHEET_NAME +
" with logging enabled",
Browser.Buttons.OK);
this.error("DebugClass.info() - no 'log' sheet");
return;
}
}
if (this.log_sheet === null)
{
// Attempted, but failed, to find the log sheet on a
// previous call to info().
return;
}
// Add the trace message to the end of log sheet.
var row = this.log_sheet.getLastRow() + 1;
var range = this.log_sheet.getRange(row, 1, 1, 2);
var time = new Date();
range.setValues([[time, msg]]);
} // DebugClass.info()
// DebugClass.warning()
// --------------------
//
// Output warning.
DebugClass.prototype.warning = function(msg)
{
if (typeof msg !== "string")
{
this.error("DebugClass.warning() - incorrect parameter type");
}
this.info("WARNING - " + msg);
} // DebugClass.warning()
// DebugClass.error()
// ------------------
//
// Output error trace and throw an error (only this function
// should decide whether to throw the errors).
DebugClass.prototype.error = function(msg)
{
if (typeof msg !== "string")
{
msg = "DebugClass.error() - parameter must be a string";
this.info(msg);
if (this.debugOn)
{
throw(msg);
}
}
this.info("ERROR - " + msg);
if (this.debugOn)
{
throw(msg);
}
} // DebugClass.error()
// DebugClass.assert()
// -------------------
//
// Issue error if assertion false.
DebugClass.prototype.assert = function(assertion, msg)
{
if (typeof assertion !== "boolean")
{
assertion = false;
msg = "DebugClass.assert() - first parameter must be a boolean";
}
else if (typeof msg !== 'string')
{
assertion = false;
msg = "DebugClass.assert() - second parameter must be a string";
}
if (!assertion)
{
this.error(msg);
}
} // DebugClass.assert()
// assert_w()
// ----------
//
// Issue warning if assertion false.
DebugClass.prototype.assert_w = function(assertion, msg)
{
if (typeof assertion !== 'boolean')
{
assertion = false;
msg = "DebugClass.assert_w() - first parameter must be a boolean";
}
else if (typeof msg !== 'string')
{
assertion = false;
msg = "DebugClass.assert_w() - second parameter must be a string";
}
if (!assertion)
{
this.warning(msg);
}
} // DebugClass.assert_w()
// Event Handlers
// ==============
function debugMenu(menuEntries)
{
if (Debug.debugOn)
{
// Line break.
menuEntries.push(null);
menuEntries.push({name: "Debug: Reset", functionName: "resetFlubaroo"});
menuEntries.push({name: "Debug: Reinitialize", functionName: "reinitialize"});
if (UI.isOn())
{
menuEntries.push({name: "Debug: Skip UI", functionName: "skipUIMenu"});
}
else
{
menuEntries.push({name: "Debug: Display UI", functionName: "displayUIMenu"});
}
menuEntries.push({name: "Debug: Clear Log", functionName: "logClear"});
menuEntries.push({name: "Debug: Dump Config", functionName: "dumpConfig"});
menuEntries.push({name: "Debug: Trigger Autograde", functionName: "onAutogradeSubmission"});
menuEntries.push({name: "Debug: Run Tests", functionName: "runTests"});
menuEntries.push({name: "Debug: Delete Grades", functionName: "deleteGradesSheet"});
if (ScriptProperties.getProperty(SCRIPT_PROP_SKIP_EMAIL))
{
menuEntries.push({name: "Debug: Send Emails", functionName: "toggleEmailSending"});
}
else
{
menuEntries.push({name: "Debug: Skip Emailing", functionName: "toggleEmailSending"});
}
}
} // debugMenu()
// dumpConfig()
// ------------
function dumpConfig()
{
Debug.info("dumpConfig() - SCRIPT_PROP_NUM_GRADED_SUBM: " +
Number(ScriptProperties.getProperty(SCRIPT_PROP_NUM_GRADED_SUBM)));
Debug.info("dumpConfig() - SCRIPT_PROP_EMPTY_SUBM_ROW_PTR: " +
Number(ScriptProperties.getProperty(SCRIPT_PROP_EMPTY_SUBM_ROW_PTR)));
} // dumpConfig()
// logClear()
// ----------
function logClear()
{
Debug.info("logClear()");
var log_sheet = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(LOG_SHEET_NAME);
if (log_sheet)
{
log_sheet.deleteRows(1, log_sheet.getMaxRows() - 1);
log_sheet.insertRowsAfter(1, 5);
}
} // logClear()
// reinitialize()
// --------------
function reinitialize()
{
Debug.info("reinitialize()");
ScriptProperties.deleteAllProperties();
// Clear the triggers.
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++)
{
ScriptApp.deleteTrigger(triggers[i]);
}
// Simulate a re-installation.
onInstall();
} // reinitialize()
// resetFlubaroo()
// ---------------
function resetFlubaroo()
{
logClear();
reinitialize();
deleteGradesSheet();
} // resetFlubaroo()
// deleteGradesSheet()
// -------------------
function deleteGradesSheet()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = getSheetWithGrades(ss);
if (sheet)
{
ss.setActiveSheet(sheet);
ss.deleteActiveSheet();
// To avoid a bug in which 'Grades' get deleted, but appears to
// stick around, switch to another sheet after deleting it.
// TODO_AJR: bug still exists sometimes.
var switch_to_sheet = getSheetWithSubmissions(ss);
ss.setActiveSheet(switch_to_sheet);
}
} // deleteGradesSheet()
// toggleEmailSending()
// --------------------
function toggleEmailSending()
{
if (ScriptProperties.getProperty(SCRIPT_PROP_SKIP_EMAIL))
{
ScriptProperties.deleteProperty(SCRIPT_PROP_SKIP_EMAIL);
}
else
{
ScriptProperties.setProperty(SCRIPT_PROP_SKIP_EMAIL, 'true');
}
} // toggleEmailSending()
更新(2015年3月11日):我已经转移到使用BetterLog和我的own wrapper library for BetterLog自动将函数名称添加到调试跟踪(MqTFuiXcPtS5rVUZ_jC9Z4tnfWGfgtIUb)。
答案 1 :(得分:1)
不可能。根据它的执行方式,您最多可以访问上一次运行日志,它会在下一个脚本运行日志中丢失。 制作自己的记录器功能,例如在电子表格上执行appendRow。我做过一个甚至记录每个日志的完整堆栈跟踪,这比本机记录器更好。 这当然会让您记录罕见的事件,因为它会消耗更多的配额。 有关记录stacktrace等的示例代码,请参见此处(滚动到中间): http://plusfortrello.blogspot.com/2013/08/spent-for-trello-google-apps.html