メインコンテンツへスキップ

【完全版】Splunk Classic オリジナルチャート作成ガイド


    インデックスデータで自由自在にカスタムビジュアライゼーション! 🚀


    📚 目次

    1️⃣ オリジナルチャートとは?
    2️⃣ 基本テンプレート(コピペOK)
    3️⃣ チャートパターン集
    4️⃣ 実践例:カスタムチャート
    5️⃣ カスタマイズ方法
    6️⃣ トラブルシューティング
    

    🎯 1️⃣ オリジナルチャートとは?

    Splunk標準チャート vs オリジナルチャート

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      【比較】
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    ┌────────────────────────────────────────────────────┐
    │ 📊 Splunk標準チャート                              │
    ├────────────────────────────────────────────────────┤
    │ ✅ 簡単に作れる(クリックだけ)                    │
    │ ❌ デザインの自由度が低い                          │
    │ ❌ 複雑な表現ができない                            │
    │                                                    │
    │ 例: Line Chart, Bar Chart, Pie Chart              │
    └────────────────────────────────────────────────────┘
    
    ┌────────────────────────────────────────────────────┐
    │ 🎨 オリジナルチャート                              │
    ├────────────────────────────────────────────────────┤
    │ ✅ デザイン完全自由                                │
    │ ✅ アニメーション追加可能                          │
    │ ✅ インタラクティブな表現                          │
    │ ✅ 独自のUIコンポーネント                          │
    │ ❌ HTML/CSS/JSの知識が必要                         │
    │                                                    │
    │ 例: カスタムゲージ, 3Dグラフ, リアルタイム表示    │
    └────────────────────────────────────────────────────┘
    
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    

    オリジナルチャートで何ができる?

    ✅ カスタムメーター(速度計風)
    ✅ プログレスバー(進捗表示)
    ✅ カスタムカード(情報表示)
    ✅ ヒートマップ
    ✅ ネットワークダイアグラム
    ✅ 3Dグラフ
    ✅ リアルタイムアニメーション
    ✅ インタラクティブダッシュボード
    

    📝 2️⃣ 基本テンプレート

    テンプレート1: シンプルカスタムチャート

    <dashboard version="1.1">
      <label>🎨 オリジナルチャート - 基本</label>
      
      <row>
        <panel>
          <title>カスタムチャート例</title>
          <html>
            <style>
              .custom-chart {
                background: linear-gradient(135deg, #667eea  0%, #764ba2  100%);
                border-radius: 15px;
                padding: 30px;
                color: white;
                text-align: center;
                margin: 20px;
              }
              .chart-value {
                font-size: 72px;
                font-weight: bold;
                margin: 20px 0;
              }
              .chart-label {
                font-size: 24px;
                opacity: 0.9;
              }
            </style>
            
            <div class="custom-chart">
              <div class="chart-label">エラー件数</div>
              <div class="chart-value" id="errorValue">0</div>
              <div class="chart-label">件</div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var searchManager = new SearchManager({
                  id: 'custom_search',
                  search: 'index=excel_monitoring earliest=-5m (status="NG" OR status="CRITICAL") | stats count',
                  earliest_time: '-5m',
                  latest_time: 'now',
                  autostart: true
                });
                
                var results = searchManager.data('results');
                
                results.on('data', function() {
                  var data = results.data();
                  if (data && data.results && data.results.length > 0) {
                    var count = data.results[0].count || 0;
                    document.getElementById('errorValue').textContent = count;
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
    </dashboard>
    

    🎨 3️⃣ チャートパターン集

    パターン1: カスタムゲージメーター

    <dashboard version="1.1">
      <label>⚡ カスタムゲージメーター</label>
      
      <row>
        <panel>
          <title>CPU使用率ゲージ</title>
          <html>
            <style>
              .gauge-container {
                width: 300px;
                height: 300px;
                margin: 40px auto;
                position: relative;
              }
              
              .gauge-background {
                width: 100%;
                height: 100%;
                border-radius: 50%;
                background: conic-gradient(
                  #65A637  0deg 108deg,
                  #F7BC38  108deg 252deg,
                  #D93F3C  252deg 360deg
                );
                position: relative;
              }
              
              .gauge-inner {
                position: absolute;
                width: 80%;
                height: 80%;
                background: white;
                border-radius: 50%;
                top: 10%;
                left: 10%;
                display: flex;
                align-items: center;
                justify-content: center;
                flex-direction: column;
              }
              
              .gauge-value {
                font-size: 64px;
                font-weight: bold;
                color: #333 ;
              }
              
              .gauge-label {
                font-size: 18px;
                color: #666 ;
                margin-top: 10px;
              }
              
              .gauge-needle {
                position: absolute;
                width: 4px;
                height: 45%;
                background: #333 ;
                bottom: 50%;
                left: 50%;
                transform-origin: bottom center;
                transform: translateX(-50%) rotate(0deg);
                transition: transform 1s ease;
                border-radius: 4px 4px 0 0;
              }
              
              .gauge-center {
                position: absolute;
                width: 20px;
                height: 20px;
                background: #333 ;
                border-radius: 50%;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                z-index: 10;
              }
            </style>
            
            <div class="gauge-container">
              <div class="gauge-background">
                <div class="gauge-needle" id="gaugeNeedle"></div>
                <div class="gauge-center"></div>
                <div class="gauge-inner">
                  <div class="gauge-value" id="gaugeValue">0</div>
                  <div class="gauge-label">%</div>
                </div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var searchManager = new SearchManager({
                  id: 'gauge_search',
                  search: 'index=excel_monitoring earliest=-5m | stats avg(cpu_usage) as avg_cpu',
                  autostart: true
                });
                
                var results = searchManager.data('results');
                
                results.on('data', function() {
                  var data = results.data();
                  if (data && data.results && data.results.length > 0) {
                    var cpu = parseFloat(data.results[0].avg_cpu) || 0;
                    
                    // 値を表示
                    document.getElementById('gaugeValue').textContent = Math.round(cpu);
                    
                    // 針の角度を計算(0-100% を -90deg から 90deg にマッピング)
                    var angle = (cpu / 100) * 180 - 90;
                    document.getElementById('gaugeNeedle').style.transform = 
                      'translateX(-50%) rotate(' + angle + 'deg)';
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
    </dashboard>
    

    パターン2: プログレスバー

    <dashboard version="1.1">
      <label>📊 プログレスバー チャート</label>
      
      <row>
        <panel>
          <title>システム別レスポンスタイム</title>
          <html>
            <style>
              .progress-container {
                padding: 30px;
              }
              
              .progress-item {
                margin: 20px 0;
              }
              
              .progress-label {
                display: flex;
                justify-content: space-between;
                margin-bottom: 8px;
                font-size: 16px;
                font-weight: bold;
              }
              
              .progress-bar-bg {
                width: 100%;
                height: 40px;
                background: #e0e0e0 ;
                border-radius: 20px;
                overflow: hidden;
                position: relative;
              }
              
              .progress-bar-fill {
                height: 100%;
                background: linear-gradient(90deg, #4CAF50  0%, #8BC34A  100%);
                border-radius: 20px;
                transition: width 1s ease;
                display: flex;
                align-items: center;
                justify-content: flex-end;
                padding-right: 15px;
                color: white;
                font-weight: bold;
                box-shadow: 0 2px 10px rgba(76, 175, 80, 0.4);
              }
              
              .progress-bar-fill.warning {
                background: linear-gradient(90deg, #FF9800  0%, #FFC107  100%);
                box-shadow: 0 2px 10px rgba(255, 152, 0, 0.4);
              }
              
              .progress-bar-fill.error {
                background: linear-gradient(90deg, #F44336  0%, #E91E63  100%);
                box-shadow: 0 2px 10px rgba(244, 67, 54, 0.4);
              }
            </style>
            
            <div class="progress-container">
              <div class="progress-item">
                <div class="progress-label">
                  <span>🌐 WebServer01</span>
                  <span id="web-value">0 ms</span>
                </div>
                <div class="progress-bar-bg">
                  <div class="progress-bar-fill" id="web-bar" style="width: 0%;">
                    <span id="web-percent">0%</span>
                  </div>
                </div>
              </div>
              
              <div class="progress-item">
                <div class="progress-label">
                  <span>🗄️ DBServer01</span>
                  <span id="db-value">0 ms</span>
                </div>
                <div class="progress-bar-bg">
                  <div class="progress-bar-fill" id="db-bar" style="width: 0%;">
                    <span id="db-percent">0%</span>
                  </div>
                </div>
              </div>
              
              <div class="progress-item">
                <div class="progress-label">
                  <span>⚙️ APIGateway01</span>
                  <span id="api-value">0 ms</span>
                </div>
                <div class="progress-bar-bg">
                  <div class="progress-bar-fill" id="api-bar" style="width: 0%;">
                    <span id="api-percent">0%</span>
                  </div>
                </div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var searchManager = new SearchManager({
                  id: 'progress_search',
                  search: 'index=excel_monitoring earliest=-5m | stats avg(response_time) as avg_rt by system_name',
                  autostart: true
                });
                
                var results = searchManager.data('results');
                var maxValue = 1000; // 最大値(ms)
                
                results.on('data', function() {
                  var data = results.data();
                  if (data && data.results) {
                    data.results.forEach(function(row) {
                      var systemName = row.system_name;
                      var rt = parseFloat(row.avg_rt) || 0;
                      var percent = Math.min((rt / maxValue) * 100, 100);
                      
                      var id = '';
                      if (systemName === 'WebServer01') id = 'web';
                      else if (systemName === 'DBServer01') id = 'db';
                      else if (systemName === 'APIGateway01') id = 'api';
                      
                      if (id) {
                        var bar = document.getElementById(id + '-bar');
                        var valueElem = document.getElementById(id + '-value');
                        var percentElem = document.getElementById(id + '-percent');
                        
                        if (bar && valueElem && percentElem) {
                          bar.style.width = percent + '%';
                          valueElem.textContent = Math.round(rt) + ' ms';
                          percentElem.textContent = Math.round(percent) + '%';
                          
                          // 色を変更
                          bar.className = 'progress-bar-fill';
                          if (rt >= 500) bar.classList.add('error');
                          else if (rt >= 200) bar.classList.add('warning');
                        }
                      }
                    });
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
    </dashboard>
    

    パターン3: カスタムカード

    <dashboard version="1.1">
      <label>🃏 カスタムカード ダッシュボード</label>
      
      <row>
        <panel>
          <html>
            <style>
              .cards-grid {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
                gap: 20px;
                padding: 20px;
              }
              
              .metric-card {
                background: white;
                border-radius: 20px;
                padding: 30px;
                box-shadow: 0 10px 40px rgba(0,0,0,0.1);
                transition: all 0.3s ease;
                position: relative;
                overflow: hidden;
              }
              
              .metric-card:hover {
                transform: translateY(-5px);
                box-shadow: 0 15px 50px rgba(0,0,0,0.15);
              }
              
              .metric-card::before {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 5px;
                background: linear-gradient(90deg, #667eea  0%, #764ba2  100%);
              }
              
              .card-icon {
                font-size: 48px;
                margin-bottom: 15px;
              }
              
              .card-title {
                font-size: 18px;
                color: #666 ;
                margin-bottom: 10px;
                font-weight: 500;
              }
              
              .card-value {
                font-size: 56px;
                font-weight: bold;
                color: #333 ;
                margin: 15px 0;
              }
              
              .card-trend {
                display: inline-flex;
                align-items: center;
                gap: 5px;
                padding: 5px 12px;
                border-radius: 20px;
                font-size: 14px;
                font-weight: bold;
                margin-top: 10px;
              }
              
              .card-trend.up {
                background: #FFE6E6 ;
                color: #D93F3C ;
              }
              
              .card-trend.down {
                background: #E6F7E6 ;
                color: #65A637 ;
              }
              
              .card-subtitle {
                font-size: 14px;
                color: #999 ;
                margin-top: 10px;
              }
            </style>
            
            <div class="cards-grid">
              <!-- カード1: エラー件数 -->
              <div class="metric-card">
                <div class="card-icon">🔴</div>
                <div class="card-title">エラー件数</div>
                <div class="card-value" id="card1-value">0</div>
                <div class="card-trend up" id="card1-trend">
                  <span>↑</span>
                  <span id="card1-change">0%</span>
                </div>
                <div class="card-subtitle">直近5分</div>
              </div>
              
              <!-- カード2: 平均レスポンスタイム -->
              <div class="metric-card">
                <div class="card-icon">⚡</div>
                <div class="card-title">平均レスポンスタイム</div>
                <div class="card-value" id="card2-value">0<span style="font-size: 24px;">ms</span></div>
                <div class="card-trend down" id="card2-trend">
                  <span>↓</span>
                  <span id="card2-change">0%</span>
                </div>
                <div class="card-subtitle">全システム平均</div>
              </div>
              
              <!-- カード3: CPU使用率 -->
              <div class="metric-card">
                <div class="card-icon">💻</div>
                <div class="card-title">平均CPU使用率</div>
                <div class="card-value" id="card3-value">0<span style="font-size: 24px;">%</span></div>
                <div class="card-trend up" id="card3-trend">
                  <span>↑</span>
                  <span id="card3-change">0%</span>
                </div>
                <div class="card-subtitle">全サーバー平均</div>
              </div>
              
              <!-- カード4: アクティブシステム -->
              <div class="metric-card">
                <div class="card-icon">🟢</div>
                <div class="card-title">稼働中システム</div>
                <div class="card-value" id="card4-value">0<span style="font-size: 24px;">/4</span></div>
                <div class="card-trend down" id="card4-trend">
                  <span>✓</span>
                  <span id="card4-change">正常</span>
                </div>
                <div class="card-subtitle">稼働状況</div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                // カード1: エラー件数
                var search1 = new SearchManager({
                  id: 'card1_search',
                  search: 'index=excel_monitoring earliest=-5m (status="NG" OR status="CRITICAL") | stats count',
                  autostart: true
                });
                
                search1.data('results').on('data', function() {
                  var data = search1.data('results').data();
                  if (data && data.results && data.results.length > 0) {
                    var count = data.results[0].count || 0;
                    document.getElementById('card1-value').innerHTML = count;
                  }
                });
                
                // カード2: レスポンスタイム
                var search2 = new SearchManager({
                  id: 'card2_search',
                  search: 'index=excel_monitoring earliest=-5m | stats avg(response_time) as avg_rt',
                  autostart: true
                });
                
                search2.data('results').on('data', function() {
                  var data = search2.data('results').data();
                  if (data && data.results && data.results.length > 0) {
                    var rt = Math.round(data.results[0].avg_rt || 0);
                    document.getElementById('card2-value').innerHTML = rt + '<span style="font-size: 24px;">ms</span>';
                  }
                });
                
                // カード3: CPU
                var search3 = new SearchManager({
                  id: 'card3_search',
                  search: 'index=excel_monitoring earliest=-5m | stats avg(cpu_usage) as avg_cpu',
                  autostart: true
                });
                
                search3.data('results').on('data', function() {
                  var data = search3.data('results').data();
                  if (data && data.results && data.results.length > 0) {
                    var cpu = parseFloat(data.results[0].avg_cpu || 0).toFixed(1);
                    document.getElementById('card3-value').innerHTML = cpu + '<span style="font-size: 24px;">%</span>';
                  }
                });
                
                // カード4: 稼働システム
                var search4 = new SearchManager({
                  id: 'card4_search',
                  search: 'index=excel_monitoring earliest=-5m | stats dc(system_name) as active_systems',
                  autostart: true
                });
                
                search4.data('results').on('data', function() {
                  var data = search4.data('results').data();
                  if (data && data.results && data.results.length > 0) {
                    var active = data.results[0].active_systems || 0;
                    document.getElementById('card4-value').innerHTML = active + '<span style="font-size: 24px;">/4</span>';
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
    </dashboard>
    

    パターン4: ヒートマップ

    <dashboard version="1.1">
      <label>🔥 ヒートマップ チャート</label>
      
      <row>
        <panel>
          <title>時間帯別システム負荷ヒートマップ</title>
          <html>
            <style>
              .heatmap-container {
                padding: 30px;
                overflow-x: auto;
              }
              
              .heatmap-table {
                border-collapse: collapse;
                margin: 0 auto;
                box-shadow: 0 5px 20px rgba(0,0,0,0.1);
              }
              
              .heatmap-table th {
                background: #f5f5f5 ;
                padding: 15px 20px;
                text-align: center;
                font-weight: bold;
                border: 1px solid #ddd ;
              }
              
              .heatmap-table td {
                padding: 20px 30px;
                text-align: center;
                border: 1px solid #ddd ;
                transition: all 0.3s ease;
                cursor: pointer;
                font-weight: bold;
                font-size: 16px;
              }
              
              .heatmap-table td:hover {
                transform: scale(1.1);
                z-index: 10;
                box-shadow: 0 5px 15px rgba(0,0,0,0.2);
              }
              
              .heat-level-0 { background: #E8F5E9 ; color: #2E7D32 ; }
              .heat-level-1 { background: #C8E6C9 ; color: #1B5E20 ; }
              .heat-level-2 { background: #FFF9C4 ; color: #F57F17 ; }
              .heat-level-3 { background: #FFE082 ; color: #E65100 ; }
              .heat-level-4 { background: #FFAB91 ; color: #BF360C ; }
              .heat-level-5 { background: #EF5350 ; color: white; }
              
              .heatmap-legend {
                display: flex;
                justify-content: center;
                gap: 10px;
                margin-top: 30px;
                flex-wrap: wrap;
              }
              
              .legend-item {
                display: flex;
                align-items: center;
                gap: 8px;
              }
              
              .legend-color {
                width: 30px;
                height: 30px;
                border-radius: 5px;
                border: 1px solid #ddd ;
              }
            </style>
            
            <div class="heatmap-container">
              <table class="heatmap-table">
                <thead>
                  <tr>
                    <th>System / Hour</th>
                    <th>10:00</th>
                    <th>11:00</th>
                    <th>12:00</th>
                    <th>13:00</th>
                    <th>14:00</th>
                  </tr>
                </thead>
                <tbody id="heatmapBody">
                  <tr>
                    <th>WebServer01</th>
                    <td class="heat-level-0" id="web-10">0</td>
                    <td class="heat-level-0" id="web-11">0</td>
                    <td class="heat-level-0" id="web-12">0</td>
                    <td class="heat-level-0" id="web-13">0</td>
                    <td class="heat-level-0" id="web-14">0</td>
                  </tr>
                  <tr>
                    <th>DBServer01</th>
                    <td class="heat-level-0" id="db-10">0</td>
                    <td class="heat-level-0" id="db-11">0</td>
                    <td class="heat-level-0" id="db-12">0</td>
                    <td class="heat-level-0" id="db-13">0</td>
                    <td class="heat-level-0" id="db-14">0</td>
                  </tr>
                  <tr>
                    <th>APIGateway01</th>
                    <td class="heat-level-0" id="api-10">0</td>
                    <td class="heat-level-0" id="api-11">0</td>
                    <td class="heat-level-0" id="api-12">0</td>
                    <td class="heat-level-0" id="api-13">0</td>
                    <td class="heat-level-0" id="api-14">0</td>
                  </tr>
                </tbody>
              </table>
              
              <div class="heatmap-legend">
                <div class="legend-item">
                  <div class="legend-color heat-level-0"></div>
                  <span>0-20%</span>
                </div>
                <div class="legend-item">
                  <div class="legend-color heat-level-1"></div>
                  <span>20-40%</span>
                </div>
                <div class="legend-item">
                  <div class="legend-color heat-level-2"></div>
                  <span>40-60%</span>
                </div>
                <div class="legend-item">
                  <div class="legend-color heat-level-3"></div>
                  <span>60-80%</span>
                </div>
                <div class="legend-item">
                  <div class="legend-color heat-level-4"></div>
                  <span>80-90%</span>
                </div>
                <div class="legend-item">
                  <div class="legend-color heat-level-5"></div>
                  <span>90-100%</span>
                </div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var searchManager = new SearchManager({
                  id: 'heatmap_search',
                  search: 'index=excel_monitoring | eval hour = strftime(_time, "%H") | stats avg(cpu_usage) as avg_cpu by system_name, hour',
                  autostart: true
                });
                
                var results = searchManager.data('results');
                
                function getHeatLevel(value) {
                  if (value < 20) return 0;
                  if (value < 40) return 1;
                  if (value < 60) return 2;
                  if (value < 80) return 3;
                  if (value < 90) return 4;
                  return 5;
                }
                
                results.on('data', function() {
                  var data = results.data();
                  if (data && data.results) {
                    data.results.forEach(function(row) {
                      var system = row.system_name;
                      var hour = row.hour;
                      var cpu = parseFloat(row.avg_cpu) || 0;
                      
                      var id = '';
                      if (system === 'WebServer01') id = 'web-' + hour;
                      else if (system === 'DBServer01') id = 'db-' + hour;
                      else if (system === 'APIGateway01') id = 'api-' + hour;
                      
                      var cell = document.getElementById(id);
                      if (cell) {
                        cell.textContent = Math.round(cpu) + '%';
                        cell.className = 'heat-level-' + getHeatLevel(cpu);
                      }
                    });
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
    </dashboard>
    

    🎯 4️⃣ 実践例:総合ダッシュボード

    全部入り!カスタムダッシュボード

    <dashboard version="1.1">
      <label>🎨 オリジナルチャート総合ダッシュボード</label>
      <description>インデックスデータで作るカスタムビジュアライゼーション</description>
      
      <!-- Row 1: カスタムカード -->
      <row>
        <panel>
          <html>
            <style>
              .mini-cards {
                display: grid;
                grid-template-columns: repeat(4, 1fr);
                gap: 15px;
                padding: 15px;
              }
              
              .mini-card {
                background: white;
                border-radius: 12px;
                padding: 20px;
                text-align: center;
                box-shadow: 0 5px 20px rgba(0,0,0,0.08);
                border-left: 4px solid;
              }
              
              .mini-card.success { border-left-color: #4CAF50 ; }
              .mini-card.warning { border-left-color: #FF9800 ; }
              .mini-card.error { border-left-color: #F44336 ; }
              .mini-card.info { border-left-color: #2196F3 ; }
              
              .mini-icon {
                font-size: 32px;
                margin-bottom: 10px;
              }
              
              .mini-value {
                font-size: 36px;
                font-weight: bold;
                margin: 10px 0;
              }
              
              .mini-label {
                font-size: 14px;
                color: #666 ;
              }
            </style>
            
            <div class="mini-cards">
              <div class="mini-card success">
                <div class="mini-icon">✅</div>
                <div class="mini-value" id="ok-count">0</div>
                <div class="mini-label">正常</div>
              </div>
              
              <div class="mini-card warning">
                <div class="mini-icon">⚠️</div>
                <div class="mini-value" id="warning-count">0</div>
                <div class="mini-label">警告</div>
              </div>
              
              <div class="mini-card error">
                <div class="mini-icon">🔴</div>
                <div class="mini-value" id="error-count">0</div>
                <div class="mini-label">エラー</div>
              </div>
              
              <div class="mini-card info">
                <div class="mini-icon">📊</div>
                <div class="mini-value" id="total-count">0</div>
                <div class="mini-label">総イベント</div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var search = new SearchManager({
                  id: 'status_search',
                  search: 'index=excel_monitoring earliest=-5m | stats count by status',
                  autostart: true
                });
                
                search.data('results').on('data', function() {
                  var data = search.data('results').data();
                  if (data && data.results) {
                    var ok = 0, warning = 0, error = 0, total = 0;
                    
                    data.results.forEach(function(row) {
                      var count = parseInt(row.count) || 0;
                      total += count;
                      
                      if (row.status === 'OK') ok = count;
                      else if (row.status === 'WARNING') warning = count;
                      else if (row.status === 'NG' || row.status === 'CRITICAL') error += count;
                    });
                    
                    document.getElementById('ok-count').textContent = ok;
                    document.getElementById('warning-count').textContent = warning;
                    document.getElementById('error-count').textContent = error;
                    document.getElementById('total-count').textContent = total;
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
      
      <!-- Row 2: ゲージとプログレスバー -->
      <row>
        <panel>
          <title>⚡ CPU使用率ゲージ</title>
          <html>
            <style>
              .small-gauge {
                width: 200px;
                height: 200px;
                margin: 20px auto;
                position: relative;
              }
              
              .small-gauge-bg {
                width: 100%;
                height: 100%;
                border-radius: 50%;
                background: conic-gradient(
                  #65A637  0deg 108deg,
                  #F7BC38  108deg 252deg,
                  #D93F3C  252deg 360deg
                );
              }
              
              .small-gauge-inner {
                position: absolute;
                width: 75%;
                height: 75%;
                background: white;
                border-radius: 50%;
                top: 12.5%;
                left: 12.5%;
                display: flex;
                align-items: center;
                justify-content: center;
                flex-direction: column;
              }
              
              .small-value {
                font-size: 48px;
                font-weight: bold;
              }
            </style>
            
            <div class="small-gauge">
              <div class="small-gauge-bg">
                <div class="small-gauge-inner">
                  <div class="small-value" id="cpu-gauge">0</div>
                  <div style="font-size: 14px; color: #666 ;">%</div>
                </div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var search = new SearchManager({
                  id: 'cpu_gauge_search',
                  search: 'index=excel_monitoring earliest=-5m | stats avg(cpu_usage) as cpu',
                  autostart: true
                });
                
                search.data('results').on('data', function() {
                  var data = search.data('results').data();
                  if (data && data.results && data.results.length > 0) {
                    var cpu = Math.round(data.results[0].cpu || 0);
                    document.getElementById('cpu-gauge').textContent = cpu;
                  }
                });
              });
            </script>
          </html>
        </panel>
        
        <panel>
          <title>📊 システム別負荷</title>
          <html>
            <style>
              .compact-progress {
                padding: 20px;
              }
              
              .compact-item {
                margin: 15px 0;
              }
              
              .compact-label {
                font-size: 14px;
                margin-bottom: 5px;
                display: flex;
                justify-content: space-between;
              }
              
              .compact-bar-bg {
                width: 100%;
                height: 25px;
                background: #e0e0e0 ;
                border-radius: 12px;
                overflow: hidden;
              }
              
              .compact-bar {
                height: 100%;
                background: linear-gradient(90deg, #2196F3 , #21CBF3 );
                border-radius: 12px;
                transition: width 0.8s ease;
              }
            </style>
            
            <div class="compact-progress">
              <div class="compact-item">
                <div class="compact-label">
                  <span>WebServer01</span>
                  <span id="web-cpu">0%</span>
                </div>
                <div class="compact-bar-bg">
                  <div class="compact-bar" id="web-bar" style="width: 0%"></div>
                </div>
              </div>
              
              <div class="compact-item">
                <div class="compact-label">
                  <span>DBServer01</span>
                  <span id="db-cpu">0%</span>
                </div>
                <div class="compact-bar-bg">
                  <div class="compact-bar" id="db-bar" style="width: 0%"></div>
                </div>
              </div>
              
              <div class="compact-item">
                <div class="compact-label">
                  <span>APIGateway01</span>
                  <span id="api-cpu">0%</span>
                </div>
                <div class="compact-bar-bg">
                  <div class="compact-bar" id="api-bar" style="width: 0%"></div>
                </div>
              </div>
            </div>
            
            <script>
              require([
                'splunkjs/mvc',
                'splunkjs/mvc/searchmanager',
                'splunkjs/mvc/simplexml/ready!'
              ], function(mvc, SearchManager) {
                
                var search = new SearchManager({
                  id: 'system_cpu_search',
                  search: 'index=excel_monitoring earliest=-5m | stats avg(cpu_usage) as cpu by system_name',
                  autostart: true
                });
                
                search.data('results').on('data', function() {
                  var data = search.data('results').data();
                  if (data && data.results) {
                    data.results.forEach(function(row) {
                      var cpu = parseFloat(row.cpu) || 0;
                      var id = '';
                      
                      if (row.system_name === 'WebServer01') id = 'web';
                      else if (row.system_name === 'DBServer01') id = 'db';
                      else if (row.system_name === 'APIGateway01') id = 'api';
                      
                      if (id) {
                        document.getElementById(id + '-cpu').textContent = cpu.toFixed(1) + '%';
                        document.getElementById(id + '-bar').style.width = cpu + '%';
                      }
                    });
                  }
                });
              });
            </script>
          </html>
        </panel>
      </row>
      
      <!-- Row 3: Splunk標準チャート -->
      <row>
        <panel>
          <title>📈 時系列グラフ(標準チャート)</title>
          <chart>
            <search>
              <query>
    index=excel_monitoring earliest=-1h
    | timechart span=5m avg(response_time) as "Avg RT" by system_name
              </query>
            </search>
            <option name="charting.chart">line</option>
            <option name="charting.legend.placement">bottom</option>
          </chart>
        </panel>
      </row>
    </dashboard>
    

    🛠️ 5️⃣ カスタマイズ方法

    カスタマイズポイント

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      【カスタマイズできる要素】
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    1. 色
       ├─ background: #色コード 
       ├─ color: #色コード 
       └─ border-color: #色コード 
    
    2. サイズ
       ├─ width: 300px
       ├─ height: 200px
       ├─ font-size: 24px
       └─ padding: 20px
    
    3. アニメーション
       ├─ transition: all 0.3s ease
       ├─ @keyframes で独自アニメーション
       └─ transform: scale(1.1)
    
    4. レイアウト
       ├─ display: grid
       ├─ flex
       └─ position: absolute
    
    5. データ取得元
       └─ search: 'index=〇〇 | ...'
    
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    

    色変更例

    /* 緑系 → 青系に変更 */
    
    /* 変更前 */
    background: linear-gradient(90deg, #4CAF50  0%, #8BC34A  100%);
    
    /* 変更後 */
    background: linear-gradient(90deg, #2196F3  0%, #03A9F4  100%);
    

    サイズ変更例

    /* 小さくする */
    .gauge-container {
      width: 200px;  /* 300px → 200px */
      height: 200px; /* 300px → 200px */
    }
    
    .gauge-value {
      font-size: 48px; /* 64px → 48px */
    }
    

    データ取得クエリ変更例

    // 変更前: CPU使用率
    search: 'index=excel_monitoring | stats avg(cpu_usage) as cpu'
    
    // 変更後: メモリ使用率
    search: 'index=excel_monitoring | stats avg(memory_usage) as memory'
    

    🔧 6️⃣ トラブルシューティング

    問題1: チャートが表示されない

    【原因】
    ├─ HTMLの構文エラー
    ├─ JavaScriptのエラー
    └─ CSSの記述ミス
    
    【確認方法】
    1. ブラウザでF12キーを押す
    2. Consoleタブを確認
    3. 赤いエラーメッセージを確認
    
    【対処法】
    1. XMLの<html>タグが正しく閉じているか
    2. <script>タグが正しく閉じているか
    3. シングルクォート/ダブルクォートの対応
    

    問題2: データが更新されない

    【原因】
    ├─ search id が間違っている
    ├─ インデックス名が間違っている
    └─ フィールド名が間違っている
    
    【確認】
    1. Search画面でクエリを直接実行
    2. 結果が返ってくるか確認
    3. フィールド名が一致しているか確認
    

    問題3: スタイルが適用されない

    【原因】
    CSSセレクタが間違っている
    
    【確認】
    <div class="my-class"> ← クラス名
    ↓
    .my-class { ... } ← CSS(ドット付き)
    
    <div id="my-id"> ← ID名
    ↓ #my -id { ... } ← CSS(シャープ付き)
    

    📚 まとめ

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      【オリジナルチャート作成の流れ】
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    1. ダッシュボード作成
       ↓
    2. <html>パネル追加
       ↓
    3. <style> で見た目を作る
       ↓
    4. HTML要素を配置
       ↓
    5. <script> でデータ取得
       ↓
    6. 値を表示
       ↓
    7. 完成!
    
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
      【重要ポイント】
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    ✅ HTML/CSS/JSの基礎知識があればOK
    ✅ テンプレートをコピペして改造
    ✅ 色・サイズは自由に変更可能
    ✅ インデックスデータから自動取得
    ✅ リアルタイム更新可能
    
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    

    これでオリジナルチャートが作れますね! 🎉

    テンプレートをコピペして、色やサイズを変更するだけで 自分だけのカスタムダッシュボードが完成します! 💪

    どのチャートを作りたいか教えてください! 一緒にカスタマイズしましょう! 🚀

    あなたへのおすすめ