6.1 ダッシュボード作成
効果的なデータ可視化と意思決定支援を実現するZabbixダッシュボードの包括的設計・構築手法
概要
ダッシュボード作成は、Zabbixで収集した膨大な監視データを視覚的に理解しやすい形で表現する重要な機能です。適切に設計されたダッシュボードにより、迅速な状況把握、効率的な問題発見、そして的確な意思決定を支援できます。
ダッシュボードの価値
要素 | 効果 | 適用場面 |
---|---|---|
即時可視化 | リアルタイム状況把握 | 運用監視・障害対応 |
統合ビュー | 複数データの一元表示 | 管理者向けレポート |
カスタマイズ | 用途別最適化 | 部門別・役割別表示 |
共有 | チーム間情報共有 | 会議・報告・引き継ぎ |
ドリルダウン | 詳細分析への導線 | 問題調査・原因究明 |
ダッシュボードの設計原則
ユーザー中心設計
対象ユーザー別ダッシュボード設計
yaml
# 経営陣向けダッシュボード
エグゼクティブダッシュボード:
目的: 全体的なIT状況の把握
表示項目:
- システム全体可用性
- 重大インシデント数
- SLA達成率
- 月次コスト動向
特徴:
- シンプルな表示
- 大きな数値とゲージ
- トレンド重視
- 色による状態表現
# 運用チーム向けダッシュボード
オペレーションダッシュボード:
目的: 日常運用における詳細監視
表示項目:
- 実行中の問題一覧
- リアルタイムメトリクス
- 最新イベント
- 対応待ちアラート
特徴:
- 詳細データ表示
- 高頻度更新
- インタラクティブ要素
- ドリルダウン機能
# 開発チーム向けダッシュボード
デベロッパーダッシュボード:
目的: アプリケーション性能の監視
表示項目:
- アプリケーションメトリクス
- レスポンス時間
- エラー率
- デプロイメント状況
特徴:
- 技術的詳細
- 時系列データ重視
- コード関連メトリクス
- パフォーマンス分析
情報階層の設計
ピラミッド型情報構造
yaml
# 情報階層レベル
Level 1 - 概要レベル:
- 全体ステータス
- KPI指標
- 重要アラート
- トレンド概要
Level 2 - 詳細レベル:
- システム別状況
- メトリクス詳細
- パフォーマンス指標
- 容量使用状況
Level 3 - 技術レベル:
- 生データ
- ログ詳細
- 設定情報
- 診断データ
レスポンシブデザイン
デバイス別最適化
yaml
# 画面サイズ別設計
大画面(1920x1080以上):
レイアウト: 4列構成
ウィジェットサイズ: 大
情報密度: 高
詳細表示: 有効
中画面(1366x768-1920x1080):
レイアウト: 3列構成
ウィジェットサイズ: 中
情報密度: 中
詳細表示: 選択的
小画面(1024x768以下):
レイアウト: 2列構成
ウィジェットサイズ: 小
情報密度: 低
詳細表示: 最小限
モバイル:
レイアウト: 1列構成
ウィジェットサイズ: モバイル最適
情報密度: 最低限
詳細表示: タップ展開
ウィジェットタイプと活用
基本ウィジェット
データ表示ウィジェット
yaml
# プレーンテキストウィジェット
プレーンテキスト:
用途: 単一値の表示
適用例:
- システム稼働時間
- CPU使用率
- メモリ使用率
- ディスク容量
設定例:
アイテム: system.uptime
表示形式: "稼働時間: {ITEM.LASTVALUE}"
更新間隔: 30秒
単位: 自動
小数点: 2桁
# ゲージウィジェット
ゲージ:
用途: 閾値に対する現在値の視覚化
適用例:
- CPU使用率(0-100%)
- ディスク使用率
- ネットワーク帯域使用率
- 温度監視
設定例:
アイテム: system.cpu.util
最小値: 0
最大値: 100
閾値:
- 緑: 0-70%
- 黄: 70-85%
- 赤: 85-100%
# グラフ(クラシック)ウィジェット
グラフ(クラシック):
用途: 時系列データの視覚化
適用例:
- パフォーマンストレンド
- リソース使用履歴
- ネットワークトラフィック
- レスポンス時間
設定例:
グラフ: "CPU utilization"
期間: 過去24時間
凡例: 表示
Y軸: 自動スケール
X軸: 時間軸
情報整理ウィジェット
yaml
# 問題ウィジェット
問題:
用途: アクティブな問題の一覧表示
適用例:
- 障害監視
- アラート管理
- 優先度別問題表示
- 問題対応状況
設定例:
ホストグループ: "Production servers"
深刻度: High以上
表示数: 20件
ソート: 時間降順
列表示:
- 時間
- ホスト
- 問題
- 深刻度
- 確認状況
# ホストアベイラビリティウィジェット
ホストアベイラビリティ:
用途: ホストの可用性状況表示
適用例:
- インフラ概要
- サービス稼働状況
- 接続性監視
- 全体ヘルス状況
設定例:
ホストグループ: "All servers"
インターフェースタイプ: "Zabbix agent"
レイアウト: "横配置"
表示項目:
- ホスト名
- 状態アイコン
- 最終確認時刻
# システム情報ウィジェット
システム情報:
用途: Zabbix自体の状況表示
適用例:
- システム監視
- パフォーマンス確認
- 容量管理
- 運用状況把握
設定項目:
- Zabbixサーバー状況
- キュー情報
- プロセス稼働状況
- データベース統計
高度なウィジェット
カスタムウィジェット
yaml
# Webページウィジェット
Webページ:
用途: 外部コンテンツの埋め込み
適用例:
- 外部監視システム
- ドキュメント表示
- 関連ツール連携
- カスタムアプリケーション
設定例:
URL: "https://monitoring.example.com/status"
更新間隔: 60秒
認証: Basic認証
セキュリティ: HTTPS必須
# 時計ウィジェット
時計:
用途: 時刻・タイムゾーン表示
適用例:
- グローバル運用
- タイムスタンプ参照
- 時差確認
- 運用時間管理
設定例:
タイムゾーン: "Asia/Tokyo"
形式: "YYYY-MM-DD HH:mm:ss"
表示サイズ: 大
# マップナビゲーションツリー
マップナビゲーションツリー:
用途: マップ階層の表示
適用例:
- 地理的構造
- 論理的階層
- システム構成
- ナビゲーション
設定例:
ルートマップ: "Global Infrastructure"
展開レベル: 2階層
アイコン表示: 有効
動的ダッシュボード
フィルタリング機能
動的フィルタ実装
yaml
# ホストグループフィルタ
ホストグループフィルタ:
実装方法:
- ダッシュボードレベルフィルタ
- ウィジェット継承設定
- 動的更新
設定例:
フィルタタイプ: "ホストグループ"
デフォルト値: "All servers"
選択肢:
- "Production servers"
- "Development servers"
- "Network devices"
- "Database servers"
# 時間範囲フィルタ
時間範囲フィルタ:
実装方法:
- グローバル時間設定
- ウィジェット同期
- カスタム範囲対応
設定例:
デフォルト: "過去1時間"
選択肢:
- "過去15分"
- "過去1時間"
- "過去6時間"
- "過去24時間"
- "過去7日"
- "カスタム範囲"
# 深刻度フィルタ
深刻度フィルタ:
実装方法:
- 問題ウィジェット連携
- 条件付き表示
- 複数選択対応
設定例:
フィルタタイプ: "チェックボックス"
選択肢:
- "災害" (チェック済み)
- "高" (チェック済み)
- "警告" (チェック済み)
- "情報" (未チェック)
- "未分類" (未チェック)
条件付き表示
状況適応型ダッシュボード
yaml
# 障害時緊急モード
緊急モードダッシュボード:
トリガー条件:
- 深刻度「災害」の問題発生
- 複数システム同時障害
- SLA閾値违反
表示変更:
- 背景色: 赤色系
- ウィジェット: 緊急対応用に切り替え
- 更新間隔: 10秒に短縮
- 音声アラート: 有効
# 夜間モード
夜間モードダッシュボード:
トリガー条件:
- 時間: 22:00-06:00
- 当番担当者ログイン
表示変更:
- テーマ: ダーク系
- 輝度: 50%に調整
- ウィジェット: 必須項目のみ
- 通知: サイレント
# メンテナンスモード
メンテナンスモードダッシュボード:
トリガー条件:
- 予定メンテナンス期間
- メンテナンスホスト存在
表示変更:
- メンテナンス情報表示
- 該当ホスト除外
- プログレス表示
- 完了予定時刻表示
ダッシュボード共有
権限管理
段階的アクセス制御
yaml
# 権限レベル設計
権限レベル:
Owner(所有者):
- 編集・削除
- 共有設定変更
- アクセス権管理
Editor(編集者):
- レイアウト変更
- ウィジェット設定
- フィルタ設定
- 複製作成
Viewer(閲覧者):
- 表示のみ
- フィルタ操作
- エクスポート
- 個人コピー作成
# 部門別共有設定
部門別アクセス:
"Executive Dashboard":
所有者: "C-Level"
編集者: "IT Manager"
閲覧者: "All managers"
"Infrastructure Dashboard":
所有者: "Infrastructure Team Lead"
編集者: "Infrastructure Team"
閲覧者: "Development Team"
"Application Dashboard":
所有者: "Application Team Lead"
編集者: "Application Team"
閲覧者: "QA Team"
バージョン管理
ダッシュボード履歴管理
yaml
# バージョン管理戦略
バージョニング:
命名規則: "DashboardName_v{major}.{minor}"
例: "Infrastructure_v2.1", "Application_v1.3"
変更分類:
Major変更:
- レイアウト大幅変更
- ウィジェット種類変更
- データソース変更
Minor変更:
- ウィジェット設定調整
- フィルタ追加
- 表示項目追加
# 変更履歴記録
変更ログ:
形式:
日時: "2024-01-15 10:30:00"
変更者: "admin.infrastructure"
変更内容: "CPU使用率ウィジェット閾値を85%に変更"
バージョン: "v2.1"
影響範囲: "Infrastructure Dashboard"
カスタムダッシュボード開発
API活用
プログラマティックダッシュボード作成
python
#!/usr/bin/env python3
"""Zabbix ダッシュボード自動生成スクリプト"""
import json
import requests
from typing import Dict, List, Any
class ZabbixDashboardBuilder:
def __init__(self, zabbix_url: str, auth_token: str):
self.zabbix_url = zabbix_url
self.auth_token = auth_token
self.session = requests.Session()
def create_dashboard_template(self, name: str, hostgroups: List[str]) -> Dict[str, Any]:
"""ダッシュボードテンプレート作成"""
dashboard_config = {
"name": name,
"display_period": 30,
"auto_start": 1,
"pages": [{
"name": "Overview",
"display_period": 0,
"widgets": []
}]
}
# 基本ウィジェット追加
widgets = []
# 1. システム情報ウィジェット
widgets.append({
"type": "systeminfo",
"name": "System Information",
"x": 0, "y": 0, "width": 6, "height": 3,
"fields": {
"rf_rate": 1
}
})
# 2. 問題ウィジェット
widgets.append({
"type": "problems",
"name": "Problems",
"x": 6, "y": 0, "width": 6, "height": 6,
"fields": {
"show_tags": 3,
"show_timeline": 1,
"sortfield": "clock",
"sortorder": "desc"
}
})
# 3. ホスト可用性ウィジェット
widgets.append({
"type": "hostavail",
"name": "Host Availability",
"x": 0, "y": 3, "width": 6, "height": 3,
"fields": {
"interface_type": 1,
"layout": 0
}
})
# ホストグループ別にCPU使用率ウィジェット追加
y_position = 6
for idx, hostgroup in enumerate(hostgroups):
widgets.append({
"type": "graph",
"name": f"CPU Utilization - {hostgroup}",
"x": (idx % 2) * 6,
"y": y_position + (idx // 2) * 4,
"width": 6,
"height": 4,
"fields": {
"graph_type": 0,
"source_type": 1,
"hostgroup": hostgroup,
"itempattern": "system.cpu.util"
}
})
dashboard_config["pages"][0]["widgets"] = widgets
return dashboard_config
def create_dashboard(self, dashboard_config: Dict[str, Any]) -> str:
"""ダッシュボード作成API呼び出し"""
data = {
"jsonrpc": "2.0",
"method": "dashboard.create",
"params": dashboard_config,
"auth": self.auth_token,
"id": 1
}
response = self.session.post(self.zabbix_url, json=data)
result = response.json()
if "result" in result:
return result["result"]["dashboardids"][0]
else:
raise Exception(f"Dashboard creation failed: {result}")
def update_widget_data_source(self, dashboard_id: str, widget_config: Dict[str, Any]):
"""ウィジェットデータソース更新"""
# ダッシュボード取得
get_data = {
"jsonrpc": "2.0",
"method": "dashboard.get",
"params": {
"dashboardids": [dashboard_id],
"selectPages": ["widgets"]
},
"auth": self.auth_token,
"id": 1
}
response = self.session.post(self.zabbix_url, json=get_data)
dashboard = response.json()["result"][0]
# ウィジェット更新
for page in dashboard["pages"]:
for widget in page["widgets"]:
if widget["name"] == widget_config["name"]:
widget["fields"].update(widget_config["fields"])
# ダッシュボード更新
update_data = {
"jsonrpc": "2.0",
"method": "dashboard.update",
"params": {
"dashboardid": dashboard_id,
"pages": dashboard["pages"]
},
"auth": self.auth_token,
"id": 1
}
response = self.session.post(self.zabbix_url, json=update_data)
return response.json()
# 使用例
def main():
builder = ZabbixDashboardBuilder(
zabbix_url="https://zabbix.example.com/api_jsonrpc.php",
auth_token="auth_token_here"
)
# ホストグループリスト
hostgroups = [
"Linux servers",
"Windows servers",
"Network devices",
"Database servers"
]
# ダッシュボード作成
dashboard_config = builder.create_dashboard_template(
name="Auto-Generated Infrastructure Dashboard",
hostgroups=hostgroups
)
dashboard_id = builder.create_dashboard(dashboard_config)
print(f"Created dashboard with ID: {dashboard_id}")
# カスタムウィジェット追加
custom_widget = {
"name": "System Information",
"fields": {
"rf_rate": 10, # 10秒更新
"show_header": 1
}
}
builder.update_widget_data_source(dashboard_id, custom_widget)
print("Updated widget configuration")
if __name__ == "__main__":
main()
Webhook統合
外部システム連携ダッシュボード
javascript
// Slack統合ダッシュボードウィジェット
class SlackIntegrationWidget {
constructor(slackWebhookUrl, channel) {
this.webhookUrl = slackWebhookUrl;
this.channel = channel;
this.updateInterval = 60000; // 1分
}
async fetchSlackMessages() {
try {
// Slack API呼び出し(実際の実装では適切な認証が必要)
const response = await fetch('/api/slack/messages', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + this.slackToken,
'Content-Type': 'application/json'
}
});
const messages = await response.json();
return messages.messages.filter(msg =>
msg.channel === this.channel &&
msg.text.includes('zabbix') || msg.text.includes('alert')
);
} catch (error) {
console.error('Slack API error:', error);
return [];
}
}
renderWidget(containerId) {
const container = document.getElementById(containerId);
this.fetchSlackMessages().then(messages => {
const html = `
<div class="slack-widget">
<h3>Recent Alerts in #${this.channel}</h3>
<div class="messages">
${messages.map(msg => `
<div class="message">
<span class="timestamp">${new Date(msg.ts * 1000).toLocaleString()}</span>
<span class="user">${msg.user}</span>
<div class="text">${msg.text}</div>
</div>
`).join('')}
</div>
</div>
`;
container.innerHTML = html;
});
// 定期更新
setInterval(() => this.renderWidget(containerId), this.updateInterval);
}
}
// GitLab CI/CD統合
class GitLabCIWidget {
constructor(gitlabUrl, projectId, accessToken) {
this.gitlabUrl = gitlabUrl;
this.projectId = projectId;
this.accessToken = accessToken;
}
async fetchPipelineStatus() {
const response = await fetch(
`${this.gitlabUrl}/api/v4/projects/${this.projectId}/pipelines`,
{
headers: {
'Authorization': `Bearer ${this.accessToken}`
}
}
);
const pipelines = await response.json();
return pipelines.slice(0, 10); // 最新10件
}
renderWidget(containerId) {
const container = document.getElementById(containerId);
this.fetchPipelineStatus().then(pipelines => {
const html = `
<div class="gitlab-widget">
<h3>Recent CI/CD Pipelines</h3>
<div class="pipelines">
${pipelines.map(pipeline => `
<div class="pipeline status-${pipeline.status}">
<span class="id">#${pipeline.id}</span>
<span class="branch">${pipeline.ref}</span>
<span class="status">${pipeline.status}</span>
<span class="duration">${pipeline.duration || 'N/A'}s</span>
</div>
`).join('')}
</div>
</div>
`;
container.innerHTML = html;
});
}
}
パフォーマンス最適化
レンダリング最適化
効率的なデータ取得
yaml
# データ取得最適化
最適化手法:
バッチ処理:
- 複数ウィジェットのデータを一括取得
- API呼び出し回数削減
- キャッシュ活用
差分更新:
- 変更されたデータのみ更新
- 増分更新実装
- 状態比較最適化
遅延読み込み:
- 表示領域外ウィジェット遅延
- スクロール時読み込み
- 優先度別読み込み
# 更新間隔最適化
更新戦略:
リアルタイム要求(10-30秒):
- 重要アラート
- システム稼働状況
- 緊急メトリクス
準リアルタイム(1-5分):
- パフォーマンス指標
- リソース使用率
- 一般メトリクス
定期更新(15-60分):
- 統計情報
- トレンドデータ
- レポートデータ
メモリ使用量最適化
ブラウザリソース管理
javascript
// ダッシュボードメモリ管理クラス
class DashboardMemoryManager {
constructor() {
this.widgetCache = new Map();
this.maxCacheSize = 100;
this.cleanupInterval = 300000; // 5分
// 定期クリーンアップ
setInterval(() => this.cleanup(), this.cleanupInterval);
}
cacheWidgetData(widgetId, data, ttl = 60000) {
const cacheEntry = {
data: data,
timestamp: Date.now(),
ttl: ttl
};
this.widgetCache.set(widgetId, cacheEntry);
// キャッシュサイズ制限
if (this.widgetCache.size > this.maxCacheSize) {
this.evictOldestCache();
}
}
getCachedData(widgetId) {
const cacheEntry = this.widgetCache.get(widgetId);
if (!cacheEntry) return null;
const isExpired = (Date.now() - cacheEntry.timestamp) > cacheEntry.ttl;
if (isExpired) {
this.widgetCache.delete(widgetId);
return null;
}
return cacheEntry.data;
}
cleanup() {
const now = Date.now();
for (const [widgetId, cacheEntry] of this.widgetCache.entries()) {
const isExpired = (now - cacheEntry.timestamp) > cacheEntry.ttl;
if (isExpired) {
this.widgetCache.delete(widgetId);
}
}
// ブラウザメモリ統計表示(開発環境)
if (performance.memory) {
console.log('Memory usage:', {
used: Math.round(performance.memory.usedJSHeapSize / 1024 / 1024) + 'MB',
total: Math.round(performance.memory.totalJSHeapSize / 1024 / 1024) + 'MB',
limit: Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024) + 'MB'
});
}
}
evictOldestCache() {
let oldestKey = null;
let oldestTime = Date.now();
for (const [widgetId, cacheEntry] of this.widgetCache.entries()) {
if (cacheEntry.timestamp < oldestTime) {
oldestTime = cacheEntry.timestamp;
oldestKey = widgetId;
}
}
if (oldestKey) {
this.widgetCache.delete(oldestKey);
}
}
}
// 使用例
const memoryManager = new DashboardMemoryManager();
// ウィジェットデータキャッシュ
memoryManager.cacheWidgetData('cpu_widget_1', cpuData, 30000); // 30秒TTL
// キャッシュからデータ取得
const cachedData = memoryManager.getCachedData('cpu_widget_1');
if (cachedData) {
updateWidget(cachedData);
} else {
fetchFreshData('cpu_widget_1');
}
ベストプラクティス
設計ガイドライン
ユーザビリティ原則
yaml
# 5秒ルール
即座に理解可能:
- 5秒以内に状況把握可能
- 直感的な色使い
- 明確な数値表示
- 適切なゲージ・チャート
# 情報密度バランス
適切な情報量:
- 画面サイズに応じた調整
- 重要度による優先順位
- 階層化された情報構造
- ドリルダウン機能
# 一貫性原則
統一されたデザイン:
- 色の意味統一(赤=危険、緑=正常)
- アイコンの統一
- レイアウトパターンの統一
- 操作方法の統一
運用考慮事項
継続的改善プロセス
yaml
# 利用状況分析
分析項目:
ダッシュボード使用頻度:
- アクセス回数
- 滞在時間
- ページビュー
- ユーザー別利用状況
ウィジェット有効性:
- クリック率
- 展開率
- エラー発生率
- データ更新頻度
# 改善サイクル
PDCAサイクル:
Plan(計画):
- ユーザーフィードバック収集
- 利用データ分析
- 改善案策定
Do(実行):
- テスト環境での実装
- 段階的ロールアウト
- ユーザートレーニング
Check(評価):
- 効果測定
- 満足度調査
- パフォーマンス測定
Act(改善):
- フィードバック反映
- 標準化
- 次期改善計画
まとめ
効果的なダッシュボード作成は、Zabbix監視データの価値を最大化する重要な要素です。
重要ポイント
- ユーザー中心設計: 対象ユーザーのニーズに合わせた設計
- 情報階層化: 概要から詳細へのスムーズな導線
- パフォーマンス重視: レスポンシブで高速なダッシュボード
- 継続的改善: 利用状況分析に基づく継続的な最適化
次のステップ
次章では、ダッシュボードで使用するグラフとチャートの詳細な作成・カスタマイズ手法について学習し、より効果的なデータ可視化技術を習得します。