2019/1/13

使用chart.js 畫系統監控圖表

專案有個需求是可以觀察server 上資源的使用情形。本來習慣使用 hichart,但後來發現他的使用是要錢的,於是改用chart.js。
繪製動態圖表需要準備幾件事情:
一、取得資料來源:目前多用ajax取得資料。
二、資料有無依照時間序列變化:資料可能是依照時間變化跑的,或者只是依類別顯示。
三、要幫資料歸類出x軸(資料點的名稱)與y軸(數值變動)。

我們的專案是利用power shell 或 vbs 將伺服器監控的數據寫到SQL Server,再用Asp.net 網站讓管理人員查閱資料。作一隻簡單的泛型處理函式(ashx)將資料轉為json,讓chart.js讀取。

我們當初在紀錄資料時,每筆紀錄就包含日期、CPU使用率跟可用記憶體。很明顯這是隨時間序列變化的資料。搭配EF大概是這樣寫:

 using ( xxxxxxxEntitiesdbm = new xxxxxxxEntities()) {
                string vid="OOOp_WEB";

                /*抓兩天以內的資料*/
                DateTime lastdate = DateTime.Now.AddDays(-2);

                var query1 = dbm.monitor_record
                    .Where(o => o.Server_id == vid && o.Recdate >= lastdate)
                    .Select  ( o=> new{
                       x = o.Recdate,
                       y = o.CPU_Useage,
                       z = o.Available_Memory
                    }
                    ) .ToList();
                string vv = JsonConvert.SerializeObject(query1);
                context.Response.Write(vv);         
            }

然後 chart.js的範例是參考Line (point data)的做法:
https://www.chartjs.org/samples/latest/scales/time/line-point-data.html

網頁須載入以下的js元件跟jquery。
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
<script src="https://www.chartjs.org/dist/2.7.3/Chart.js"></script>
<script src="https://www.chartjs.org/samples/latest/utils.js"></script>


不過問題來了,我希望從ajax抓取資料,這點跟範例不同。由於ajax預設為非同步,相關事件是包在success的區塊內,因此修改成有結果再把資料傳給另一個函數繼續顯示。

/*以下的 javascript是放在載入頁面中*/

window.onload = function() {
    $.ajax({
        url: "../WebAPI/Hardware.ashx",
        type: "POST",
        data: {
            ENCODED: "1",
        },
        dataType: "json",
        success: function (Xresponse) {
            DrawChart(Xresponse);
        },
        error: function () {
            alert("無法載入。");
        }
    });
};


我的原始資料雖然能順利取得json,而且也帶有類別標籤x跟y,但直接帶到範例內的datasets ,無論怎樣都無法直接顯示。




看看原來範例,x是日期而y是數值,我並沒有搞錯啊?看來可能是解讀json的問題。不論陣列轉 json (array/object to json ) 的 JSON.stringify() 或 json轉陣列的 JSON.parse()都是過了,chart.js還是認不到資料。


後來爬文的結果,應該利用foreach 將資料拆開成三個陣列:

陣列一存資料標籤
陣列二存第一條線的數值
陣列二存第二條線的數值

利用javascript中陣列 push 新增元素的方式實作出來
   var labelsx = [], dataCPU = [], dataMEMORY = [];
        for (var rr in results) {
            labelsx.push(results[rr].x);
            dataCPU.push(parseFloat(results[rr].y));
            dataMEMORY.push(parseFloat(results[rr].z));
        }

接下來就能將資料以標準陣列的方式餵給chart.js



然後這個圖表包含cpu使用率跟記憶體,兩個y軸的數據差距很大,所以需要左右兩邊不同刻度的y軸。

大功告成,這樣圖表就會顯示出來了。