关于 debugging-techniques
面向 ServiceNow 开发者、管理员和支持工程师的调试指南,涵盖服务端与客户端脚本、日志及常见错误。它结合平台调试器、浏览器开发工具和 MCP 查询工具定位问题。
主要功能
- 01分析服务端日志和脚本执行记录
- 02使用 Script Debugger 逐步调试
- 03借助浏览器工具排查客户端脚本
- 04检查事务性能与慢查询
- 05诊断业务规则、工作流和流程
适用场景
- 01排查业务规则或脚本错误
- 02分析客户端请求和网络错误
- 03定位慢查询及流程执行问题
MCP 相关
该技能使用 ServiceNow MCP 服务的表查询、记录获取和后台脚本工具,检查日志、脚本与执行记录。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ happy-technologies-llc/ happy-platform-skills --skill debugging-techniques安装后在 Claude Code 中输入/debugging-techniques确认已加载。
详细介绍
ServiceNow 调试技巧
概述
掌握使用内置工具和技巧调试 ServiceNow 应用的方法。本技能涵盖服务器端调试、客户端调试、日志分析和常见错误排查。
- 解决什么问题? 识别并解决业务规则、脚本包含文件、客户端脚本、工作流和流程中的问题
- 谁应该使用此技能? ServiceNow 开发人员、管理员和支持工程师
- 预期结果是什么? 更快地识别问题、高效排查故障并编写更整洁的代码
先决条件
- 所需 ServiceNow 角色:使用 Script Debugger 需要
admin或script_write - 有权访问 System Logs(System Logs > All)
- 了解浏览器开发者工具(Chrome DevTools、Firefox Developer Tools)
- 了解 JavaScript 基础知识
流程
服务器端调试
日志记录函数
ServiceNow 为服务器端脚本提供了多个日志记录函数。请根据日志级别和可见性要求选择。
| 函数 | 日志级别 | 使用场景 |
|---|---|---|
gs.log(message, source) | 调试 | 开发/测试——旧版函数,建议使用 gs.debug |
gs.debug(message) | 调试 | 详细故障排查(需要启用调试) |
gs.info(message) | 信息 | 常规操作的提示性消息 |
gs.warn(message) | 警告 | 不会中止执行的潜在问题 |
gs.error(message) | 错误 | 需要处理的错误 |
最佳实践:日志消息中始终包含上下文:
// BAD - No context
gs.info('Record updated');
// GOOD - Full context
gs.info('[IncidentHandler] Incident ' + current.number + ' updated by ' + gs.getUserName() +
' - State changed from ' + current.state.getDisplayValue() + ' to ' + previous.state.getDisplayValue());
查询系统日志:
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: source=IncidentHandler^sys_created_onONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()
fields: sys_created_on,level,message,source
limit: 50
order_by: sys_created_on
order_by_desc: true
Script Debugger
Script Debugger 支持逐步执行服务器端脚本。
启用 Script Debugger:
- 转到 System Diagnostics > Script Debugger
- 点击 Enable Debugging,为当前会话启用调试
- 使用调试器 UI 在脚本中设置断点
- 触发脚本(例如,更新一条记录)
- 使用 F10(单步跳过)、F11(单步进入)、F5(继续)逐步执行代码
调试业务规则:
Tool: SN-Query-Table
Parameters:
table_name: sys_script
query: collection=incident^active=true
fields: name,order,when,script,condition
limit: 50
order_by: order
主要功能:
- 变量检查(将鼠标悬停在变量上)
- 调用堆栈可视化
- 监视表达式
- 条件断点
会话调试模块
在会话期间为特定组件启用详细日志记录。
常见会话调试模块:
| 模块 | 用途 | 启用路径 |
|---|---|---|
Session Debug | 调试所有会话 | System Diagnostics > Session Debug > All |
Business Rules | 记录 BR 执行情况 | System Diagnostics > Session Debug > Business Rules |
SQL | 记录数据库查询 | System Diagnostics > Session Debug > SQL |
Security | 调试 ACL | System Diagnostics > Session Debug > Security |
Client Scripts | 记录客户端脚本数据 | System Diagnostics > Session Debug > Client Scripts |
通过脚本启用:
// Enable business rule debugging for current session
gs.setProperty('glide.debugger.current.enabled', 'true');
脚本执行历史
跟踪脚本执行情况以排查问题。
Tool: SN-Query-Table
Parameters:
table_name: sys_script_execution_history
query: sys_created_onONLast 1 hour@javascript:gs.hoursAgo(1)@javascript:gs.nowDateTime()
fields: script,execution_time,status,error_message,sys_created_on
limit: 100
order_by: sys_created_on
order_by_desc: true
客户端调试
浏览器控制台方法
| 方法 | 用途 |
|---|---|
console.log() | 常规日志记录 |
console.info() | 提示性消息 |
console.warn() | 警告消息 |
console.error() | 错误消息 |
console.table() | 以表格形式显示数据 |
console.trace() | 显示调用堆栈 |
ServiceNow 专用方法:
// jslog - ServiceNow legacy logging (outputs to console when enabled)
jslog('Client script executed: ' + g_form.getValue('number'));
// Check if debug mode is enabled
if (window.NOW && NOW.debug) {
console.log('[DEBUG] Form loaded for: ' + g_form.getValue('sys_id'));
}
浏览器 DevTools 调试
Chrome DevTools 工作流:
- 打开 DevTools(F12 或 Cmd+Option+I)
- 转到 Sources 标签页
- 在
scripts.do?sysparm_type=下或页面源代码中查找客户端脚本 - 点击行号设置断点
- 使用 Watch 面板监视变量
- 使用 Scope 面板检查局部变量/闭包变量
实用 DevTools 命令:
// In Console - Inspect form field
g_form.getValue('short_description');
// Get all form values
g_form.serialize();
// Check if field is mandatory
g_form.isMandatory('priority');
// Inspect GlideAjax response
// Set breakpoint in callback function to inspect 'response' object
网络选项卡分析
监控 AJAX 调用和 API 请求:
- 打开 DevTools > Network 选项卡
- 按 XHR/Fetch 筛选
- 查找以下调用:
xmlhttp.do- GlideAjax 调用api/now/- REST API 调用sysparm_processor- 表单提交
常见网络问题:
- 401/403 错误 - 身份验证/ACL 问题
- 500 错误 - 服务端脚本错误
- 响应缓慢 - 在 Timing 选项卡中查看细分情况
事务日志
分析事务性能
Tool: SN-Query-Table
Parameters:
table_name: syslog_transaction
query: sys_created_onONLast 1 hour@javascript:gs.hoursAgo(1)@javascript:gs.nowDateTime()^urlLIKEincident
fields: url,response_time,user,sys_created_on,status
limit: 50
order_by: response_time
order_by_desc: true
检测慢查询
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: messageLIKEslow query^sys_created_onONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()
fields: sys_created_on,message,source
limit: 100
调试业务规则
了解业务规则的执行顺序
对于每项操作(插入、更新、删除),业务规则按以下顺序执行:
- before 规则(按顺序升序)- 在写入数据库之前执行
- after 规则(按顺序升序)- 在写入数据库之后执行
- async 规则 - 异步执行
关键:顺序很重要!
Tool: SN-Query-Table
Parameters:
table_name: sys_script
query: collection=incident^active=true^when=before
fields: name,order,when,condition,script
limit: 100
order_by: order
调试顺序问题:
// Add to each business rule to trace execution order
gs.info('[BR Debug] ' + current.sys_class_name + ' - ' +
'Name: ' + current.getTableName() + '_BR_Name - ' +
'Order: ' + 100 + ' - ' +
'When: before - ' +
'Record: ' + current.number);
常见业务规则调试模式
检查脚本是否正在运行:
(function executeRule(current, previous) {
gs.info('[BR_NAME] Script starting for: ' + current.getDisplayValue());
// Your logic here
gs.info('[BR_NAME] Script completed');
})(current, previous);
调试条件:
// Log condition evaluation
gs.info('[BR_NAME] Condition check - current.state: ' + current.state +
', previous.state: ' + previous.state +
', Result: ' + (current.state != previous.state));
检查当前值与之前的值:
// Log all changed fields
var changes = current.changesLog();
if (changes) {
gs.info('[BR_NAME] Changes: ' + changes);
}
调试工作流和流程
工作流调试
查询工作流上下文:
Tool: SN-Query-Table
Parameters:
table_name: wf_context
query: active=true
fields: name,state,started,ended,id,scratchpad
limit: 50
order_by: sys_created_on
order_by_desc: true
检查工作流历史记录:
Tool: SN-Query-Table
Parameters:
table_name: wf_history
query: context.active=false^sys_created_onONLast 7 days@javascript:gs.daysAgo(7)@javascript:gs.nowDateTime()
fields: activity,from_state,to_state,additional_info,sys_created_on
limit: 100
order_by: sys_created_on
order_by_desc: true
Flow Designer 调试
查询流程执行记录:
Tool: SN-Query-Table
Parameters:
table_name: sys_flow_context
query: state!=complete^ORstate=error
fields: name,state,started,ended,error_message
limit: 50
order_by: sys_created_on
order_by_desc: true
启用流程调试模式:
- 在 Flow Designer 中打开流程
- 点击 更多操作(三个点)> 调试
- 触发流程
- 在 Debug 面板中查看执行情况
常见错误消息及解决方案
“表中未找到记录”
原因: GlideRecord 查询未返回任何结果
解决方案:
var gr = new GlideRecord('incident');
gr.addQuery('number', 'INC0000001');
gr.query();
if (gr.next()) {
// Record found
} else {
gs.warn('Record not found: INC0000001');
}
“用户未获授权”
原因: ACL 阻止访问
解决方案:
- 启用 Session Debug > Security
- 检查 ACL 日志:System Logs > Security
- 查询 ACL:
Tool: SN-Query-Table
Parameters:
table_name: sys_security_acl
query: name=incident
fields: name,operation,condition,script,role
limit: 100
“脚本无效”或“脚本错误”
原因: JavaScript 语法错误或运行时异常
解决方案:
- 在 System Logs 中检查堆栈跟踪
- 使用 Script Debugger 逐步调试
- 使用浏览器控制台验证语法
“超过最大执行时间”
原因: 脚本运行时间过长(30 秒以上)
解决方案:
- 使用 GlideAggregate 进行计数,避免循环
- 使用 setLimit() 限制结果集
- 对于大型操作,改用 Scheduled Job
“违反互斥约束”
原因: 多个进程正在更新同一条记录
解决方案:
- 检查是否存在递归业务规则
- 添加条件以防止重复进入:
if (current.update_in_progress) return;
current.update_in_progress = true;
“超过嵌套调用限制”
原因: GlideRecord 操作嵌套过多或存在递归调用
解决方案:
- 重构以减少嵌套深度
- 使用 GlideAggregate 进行计数
- 拆分为单独的事务
工具使用
MCP 工具(Claude Code/Desktop)
| 工具 | 用途 |
|---|---|
SN-Query-Table | 查询 syslog、执行历史记录和脚本记录 |
SN-Execute-Background-Script | 在实例上运行诊断脚本 |
SN-Get-Record | 获取特定日志或脚本记录 |
REST API(ChatGPT/Other)
| 端点 | 方法 | 用途 |
|---|---|---|
/api/now/table/syslog | GET | 查询系统日志 |
/api/now/table/sys_script_execution_history | GET | 查询脚本执行历史记录 |
/api/now/table/syslog_transaction | GET | 查询事务日志 |
原生工具(Claude Code)
| 工具 | 用途 |
|---|---|
Bash | 执行 curl 命令以调用 REST API |
Read | 读取本地脚本文件以进行比较 |
最佳实践
- 始终包含上下文: 记录函数名称、记录标识符和操作类型
- 使用适当的日志级别: 开发时使用 Debug,生产环境追踪时使用 Info,遇到问题时使用 Error
- 清理调试代码: 部署到生产环境前,移除或禁用详细日志记录
- 使用条件日志记录: 将调试语句放在属性检查中
- 结构化日志记录: 使用一致的格式:
[Component] Action - Details - 在预生产环境中测试: 操作生产环境前,务必先在开发或测试环境中调试
故障排除
日志未显示
症状: gs.log/gs.info 语句未显示在 System Logs 中
原因: 日志级别已过滤或属性已禁用
解决方案:
- 检查 System Properties 中的
glide.log.level - 确保
glide.script.log.level允许相应的日志级别 - 使用始终会记录日志的
gs.error()
脚本调试器未触发
症状: 脚本执行时未触发断点 原因: 会话错误、脚本已缓存或条件未满足 解决方案:
- 确保为你自己的会话(而非其他管理员的会话)启用了调试
- 清除缓存:System Diagnostics > Cache Management > Flush Cache
- 验证脚本条件的结果为 true
业务规则未触发
症状: 业务规则已启用,但似乎未激活 原因: 条件未满足、表错误或筛选条件不匹配 解决方案:
Tool: SN-Query-Table
Parameters:
table_name: sys_script
query: name=YOUR_BUSINESS_RULE_NAME
fields: name,active,collection,when,order,condition,filter_condition,script
limit: 1
示例
示例 1:跟踪业务规则执行
// Add to business rule for debugging
(function executeRule(current, previous) {
var startTime = new Date().getTime();
var brName = 'Validate Incident Priority';
gs.info('[' + brName + '] START - Record: ' + current.number);
try {
// Original business rule logic
if (current.priority == 1 && !current.assignment_group) {
gs.info('[' + brName + '] Setting mandatory assignment group');
gs.addErrorMessage('Critical incidents require an assignment group');
current.setAbortAction(true);
}
} catch (e) {
gs.error('[' + brName + '] ERROR: ' + e.message + '\nStack: ' + e.stack);
}
var duration = new Date().getTime() - startTime;
gs.info('[' + brName + '] END - Duration: ' + duration + 'ms');
})(current, previous);
示例 2:查询近期错误
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: level=error^sys_created_onONLast 24 hours@javascript:gs.hoursAgo(24)@javascript:gs.nowDateTime()
fields: sys_created_on,source,message
limit: 100
order_by: sys_created_on
order_by_desc: true
示例 3:使用 GlideAjax 调试客户端脚本
// Client Script
function onLoad() {
console.log('[MyClientScript] Form loaded, fetching data...');
var ga = new GlideAjax('MyAjaxProcessor');
ga.addParam('sysparm_name', 'getData');
ga.addParam('sysparm_record_id', g_form.getUniqueValue());
ga.getXMLAnswer(function(response) {
console.log('[MyClientScript] Response received:', response);
if (!response) {
console.error('[MyClientScript] Empty response from server');
return;
}
try {
var data = JSON.parse(response);
console.table(data);
} catch (e) {
console.error('[MyClientScript] Failed to parse response:', e);
}
});
}
示例 4:用于日志分析的后台脚本
Tool: SN-Execute-Background-Script
Parameters:
script: |
// Find all errors in last hour with stack traces
var gr = new GlideRecord('syslog');
gr.addQuery('level', 'error');
gr.addQuery('sys_created_on', '>=', gs.hoursAgo(1));
gr.orderByDesc('sys_created_on');
gr.setLimit(20);
gr.query();
var results = [];
while (gr.next()) {
results.push({
time: gr.sys_created_on.getDisplayValue(),
source: gr.source.toString(),
message: gr.message.toString().substring(0, 200)
});
}
gs.info('=== Recent Errors ===\n' + JSON.stringify(results, null, 2));
description: Analyze recent error logs
相关技能
development/script-includes- 编写可复用的服务器端脚本development/business-rules- 业务规则开发与最佳实践development/client-scripts- 客户端脚本技术admin/script-execution- 系统日志配置与管理