debugging-techniques について
ServiceNow の開発者、管理者、サポートエンジニア向けのデバッグガイドです。サーバー側・クライアント側のスクリプト、ログ、一般的なエラーを扱い、プラットフォームとブラウザーのツール、MCP 検索で問題を調べます。
主な機能
- 01サーバーログと実行履歴の確認
- 02Script 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());
System Logs の検索:
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 | ビジネスルールの実行を記録 | 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
ビジネスルールのデバッグ
ビジネスルールの実行順序を理解する
ビジネスルールは各操作(insert、update、delete)で、次の順序で実行されます。
- 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 でフローを開きます
- More Actions(3 つのドット)> Debug をクリックします
- フローを実行します
- Debug パネルで実行内容を確認します
よくあるエラーメッセージと解決策
「Record not found in table」
原因: GlideRecord クエリで結果が返されませんでした 解決策:
var gr = new GlideRecord('incident');
gr.addQuery('number', 'INC0000001');
gr.query();
if (gr.next()) {
// Record found
} else {
gs.warn('Record not found: INC0000001');
}
「User not authorized」
原因: 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
「Invalid script」または「Script error」
原因: JavaScript の構文エラーまたは実行時例外です 解決策:
- System Logs でスタックトレースを確認します
- Script Debugger を使用してステップ実行します
- ブラウザーのコンソールで構文を検証します
「Maximum execution time exceeded」
原因: スクリプトの実行時間が長すぎます(30 秒以上) 解決策:
- ループの代わりに GlideAggregate を追加してカウントします
- setLimit() を使用して結果セットを制限します
- 大規模な処理は Scheduled Job に移します
「Mutual exclusion violation」
原因: 同じレコードが複数のプロセスによって更新されています 解決策:
- 再帰的なビジネスルールがないか確認します
- 再実行を防ぐ条件を追加します。
if (current.update_in_progress) return;
current.update_in_progress = true;
「Nested call limit exceeded」
原因: 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 | REST API 用の curl コマンドを実行します |
Read | 比較のためにローカルのスクリプトファイルを読み込みます |
ベストプラクティス
- 常にコンテキストを含める: 関数名、レコード識別子、操作の種類を記録します
- 適切なログレベルを使用する: 開発時は Debug、本番環境のトレースには Info、問題には Error を使用します
- デバッグコードを整理する: 本番環境に移行する前に、詳細なログ記録を削除するか無効にします
- 条件付きログを使用する: デバッグステートメントをプロパティチェックで囲みます
- 構造化ログ: 一貫した形式を使用します:
[Component] Action - Details - 本番前の環境でテストする: 本番環境に触れる前に、必ず開発環境またはテスト環境でデバッグします
トラブルシューティング
ログが表示されない
症状: gs.log/gs.info ステートメントがシステムログに表示されない
原因: ログレベルがフィルタリングされているか、プロパティが無効になっています
解決策:
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- システムログの設定と管理