event-management について
ServiceNow の Event Management を扱うスキルです。イベントの集約、アラートの相関、対応可能な項目への変換を説明し、イベントルールや指標イベントも扱います。
主な機能
- 01イベント作成とイベントルール処理
- 02アラートライフサイクルの管理
- 03アラート管理・相関ルールの設定
- 04指標イベントの生成と重大度の割り当て
- 05ES5 によるスクリプト作成
活用シーン
- 01監視システムからのイベント受信
- 02関連アラートを相関してノイズを低減
- 03重大アラートからインシデントや変更を作成
MCP 対応
イベント、アラート、ルールの検索、関連アーティファクトの特定、スクリプトのテスト、システムイベントの発生に使う MCP ツールを記載しています。
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ serac-labs/ serac --skill event-managementインストール後、Claude Code で/event-managementを入力して読み込まれたか確認します。
詳細
ServiceNow のイベント管理
イベント管理は、監視ツールからのイベントを集約して相関付けし、対処可能なアラートを作成します。
イベントフロー
Monitoring Tools (Nagios, SCOM, etc.)
↓
Events (em_event)
↓ Event Rules
Alerts (em_alert)
↓ Alert Management Rules
Incidents/Changes
主なテーブル
| テーブル | 目的 |
|---|---|
em_event | ソースからの生イベント |
em_alert | 処理済みアラート |
em_event_rule | イベント処理ルール |
em_alert_correlation_rule | アラートの相関付け |
em_connector | イベントソースのコネクター |
イベント(ES5)
プログラムによるイベントの作成
// Create event (ES5 ONLY!)
var event = new GlideRecord("em_event")
event.initialize()
// Required fields
event.setValue("source", "Custom Monitor")
event.setValue("node", "server01.example.com")
event.setValue("type", "CPU High")
event.setValue("severity", 3) // 1=Critical, 2=Major, 3=Minor, 4=Warning, 5=OK
// Event key for deduplication
event.setValue("event_class", "performance")
event.setValue("message_key", "cpu_high_server01")
// Description
event.setValue("description", "CPU usage exceeded 90% threshold")
event.setValue(
"additional_info",
JSON.stringify({
cpu_percent: 95,
process: "java",
duration: "5 minutes",
}),
)
// CI binding
event.setValue("cmdb_ci", getCISysId("server01"))
// Resource and metric
event.setValue("resource", "CPU")
event.setValue("metric_name", "cpu_usage")
event.insert()
REST API 経由のイベント
// Push event via REST (External script - ES5 ONLY!)
var request = {
records: [
{
source: "External Monitor",
node: "app-server-01",
type: "Application Error",
severity: "2",
message_key: "app_error_" + Date.now(),
description: "Application threw critical exception",
additional_info: '{"error_code": "E500", "module": "payment"}',
},
],
}
// POST to: /api/global/em/jsonv2
イベントルール(ES5)
イベント処理ルール
// Create event rule (ES5 ONLY!)
var rule = new GlideRecord("em_event_rule")
rule.initialize()
// Rule identification
rule.setValue("name", "High CPU Alert")
rule.setValue("description", "Create alert for high CPU events")
rule.setValue("order", 100)
rule.setValue("active", true)
// Event filter (which events to process)
rule.setValue("filter", "type=CPU High^severity<=3")
// Actions
rule.setValue("create_alert", true)
rule.setValue("alert_severity", 3)
// Transform settings
rule.setValue("transform_type", true)
rule.setValue("new_type", "Performance - CPU")
// CI binding
rule.setValue("ci_binding_type", "node")
rule.insert()
イベントルールスクリプト(ES5)
// Event rule advanced script (ES5 ONLY!)
// Table: em_event_rule, field: script
;(function runRule(event, rule) {
// Get additional info
var addInfo = {}
try {
addInfo = JSON.parse(event.additional_info)
} catch (e) {
addInfo = {}
}
// Set severity based on CPU percentage
var cpuPercent = parseFloat(addInfo.cpu_percent) || 0
if (cpuPercent >= 95) {
event.severity = 1 // Critical
} else if (cpuPercent >= 90) {
event.severity = 2 // Major
} else if (cpuPercent >= 80) {
event.severity = 3 // Minor
}
// Enrich description
event.description = event.description + " (Current: " + cpuPercent + "%)"
// Set time to clear (auto-close if OK event not received)
event.u_time_to_clear = 900 // 15 minutes
return true // Continue processing
})(event, rule)
アラート(ES5)
アラートのライフサイクル
Open
↓ Acknowledge
Acknowledged
↓ Investigate
In Progress
↓ Resolution
Resolved
↓ Close
Closed
Flapping ← Multiple severity changes
アラート管理ルール
// Create alert management rule (ES5 ONLY!)
var amRule = new GlideRecord("em_alert_management_rule")
amRule.initialize()
amRule.setValue("name", "Auto-create Incident for Critical Alerts")
amRule.setValue("description", "Create P1 incident for critical alerts on production CIs")
amRule.setValue("order", 100)
amRule.setValue("active", true)
// Alert filter
amRule.setValue("filter", "severity=1^cmdb_ci.u_environment=production")
// Action: Create incident
amRule.setValue("create_incident", true)
amRule.setValue("incident_priority", 1)
amRule.setValue("incident_assignment_group", getGroupSysId("NOC"))
amRule.insert()
手動によるアラート処理(ES5)
// Process alert manually (ES5 ONLY!)
function acknowledgeAlert(alertSysId, notes) {
var alert = new GlideRecord("em_alert")
if (!alert.get(alertSysId)) {
return { success: false, message: "Alert not found" }
}
// Validate state
if (alert.getValue("state") !== "Open") {
return { success: false, message: "Alert is not in Open state" }
}
// Acknowledge
alert.setValue("state", "Acknowledged")
alert.setValue("acknowledged_by", gs.getUserID())
alert.setValue("acknowledged_at", new GlideDateTime())
// Add notes
if (notes) {
alert.work_notes = "Acknowledged: " + notes
}
alert.update()
return { success: true, number: alert.getValue("number") }
}
アラートの相関付け(ES5)
相関ルール
// Create correlation rule (ES5 ONLY!)
var corrRule = new GlideRecord("em_alert_correlation_rule")
corrRule.initialize()
corrRule.setValue("name", "Server Down Correlation")
corrRule.setValue("description", "Correlate all alerts when a server goes down")
corrRule.setValue("active", true)
// Parent alert filter
corrRule.setValue("parent_filter", "type=Server Down^severity=1")
// Child alert filter
corrRule.setValue("child_filter", "cmdb_ci.u_hosted_on=javascript:parent.cmdb_ci")
// Correlation window
corrRule.setValue("time_window", 300) // 5 minutes
// Action
corrRule.setValue("set_child_severity", true)
corrRule.setValue("new_child_severity", 4) // Warning
corrRule.insert()
カスタム相関スクリプト(ES5)
// Alert correlation script (ES5 ONLY!)
// Correlate database alerts with application alerts
var AlertCorrelation = Class.create()
AlertCorrelation.prototype = {
initialize: function () {},
/**
* Find related alerts for correlation
*/
findRelatedAlerts: function (parentAlertSysId) {
var parent = new GlideRecord("em_alert")
if (!parent.get(parentAlertSysId)) {
return []
}
var relatedAlerts = []
var parentCI = parent.getValue("cmdb_ci")
var parentTime = new GlideDateTime(parent.getValue("sys_created_on"))
// Time window: 5 minutes before/after parent
var windowStart = new GlideDateTime(parentTime)
windowStart.addSeconds(-300)
var windowEnd = new GlideDateTime(parentTime)
windowEnd.addSeconds(300)
// Find alerts on dependent CIs
var dependents = this._getDependentCIs(parentCI)
var alert = new GlideRecord("em_alert")
alert.addQuery("cmdb_ci", "IN", dependents.join(","))
alert.addQuery("sys_created_on", ">=", windowStart)
alert.addQuery("sys_created_on", "<=", windowEnd)
alert.addQuery("sys_id", "!=", parentAlertSysId)
alert.addQuery("parent_alert", "") // Not already correlated
alert.query()
while (alert.next()) {
relatedAlerts.push({
sys_id: alert.getUniqueValue(),
number: alert.getValue("number"),
cmdb_ci: alert.cmdb_ci.getDisplayValue(),
severity: alert.getValue("severity"),
})
}
return relatedAlerts
},
_getDependentCIs: function (parentCISysId) {
var dependents = []
var rel = new GlideRecord("cmdb_rel_ci")
rel.addQuery("parent", parentCISysId)
rel.addQuery("type.name", "Depends on::Used by")
rel.query()
while (rel.next()) {
dependents.push(rel.getValue("child"))
}
return dependents
},
/**
* Correlate alerts under parent
*/
correlate: function (parentAlertSysId, childAlertSysIds) {
for (var i = 0; i < childAlertSysIds.length; i++) {
var child = new GlideRecord("em_alert")
if (child.get(childAlertSysIds[i])) {
child.setValue("parent_alert", parentAlertSysId)
child.work_notes = "Correlated with parent alert"
child.update()
}
}
},
type: "AlertCorrelation",
}
メトリクス(ES5)
メトリックイベントの作成
// Create metric event for threshold monitoring (ES5 ONLY!)
function createMetricEvent(ciSysId, metricName, value, thresholds) {
var severity = 5 // OK by default
// Determine severity based on thresholds
if (value >= thresholds.critical) {
severity = 1
} else if (value >= thresholds.major) {
severity = 2
} else if (value >= thresholds.minor) {
severity = 3
} else if (value >= thresholds.warning) {
severity = 4
}
// Only create event if not OK
if (severity < 5) {
var event = new GlideRecord("em_event")
event.initialize()
event.setValue("source", "Metric Monitor")
event.setValue("cmdb_ci", ciSysId)
event.setValue("type", metricName + " Threshold")
event.setValue("severity", severity)
event.setValue("metric_name", metricName)
event.setValue("message_key", metricName + "_" + ciSysId)
event.setValue("description", metricName + " is at " + value + " (Threshold: " + getThresholdName(severity) + ")")
event.insert()
}
return severity
}
function getThresholdName(severity) {
var names = { 1: "Critical", 2: "Major", 3: "Minor", 4: "Warning", 5: "OK" }
return names[severity]
}
MCP ツールの統合
利用可能なツール
| ツール | 目的 |
|---|---|
snow_query_table | イベント、アラート、イベントルールのクエリ |
snow_artifact_manage | 関連アーティファクトの検索(action='find') |
snow_execute_script | イベントスクリプトのテスト |
snow_create_event | システムイベントのトリガー |
ワークフローの例
// 1. Query open alerts
await snow_query_table({
table: "em_alert",
query: "state=Open^severity<=2",
fields: "number,description,cmdb_ci,severity,source",
})
// 2. Find unprocessed events
await snow_query_table({
table: "em_event",
query: "state=Ready",
fields: "source,node,type,severity,description",
})
// 3. Create test event
await snow_execute_script({
script: `
var event = new GlideRecord('em_event');
event.initialize();
event.source = 'Test';
event.type = 'Test Event';
event.severity = 4;
event.node = 'test-server';
gs.info('Created: ' + event.insert());
`,
})
ベストプラクティス
- イベントの重複排除 - message_key を適切に使用します
- CI の紐付け - 影響を把握できるよう、イベントを CI に紐付けます
- 重要度のマッピング - 重要度レベルに一貫性を持たせます
- 相関付け - アラートのノイズを減らします
- 時間枠 - 適切な時間枠を設定します
- 自動クローズ - 一時的な問題には time-to-clear を設定します
- 監視 - イベント処理の健全性を追跡します
- ES5 のみ - 最新の JavaScript 構文は使用しません
コメント
Markdown 対応