iT邦幫忙

2024 iThome 鐵人賽

DAY 11
2

https://ithelp.ithome.com.tw/upload/images/20240925/20152073Oqf7u3l0r8.png

前言

在前端服務中如果要取得數據資料,勢必需要向後端服務發起 HTTP 請求,在 Grafana Scenes 中也是相同道理,而取得的資料即為 Datasource 的資料。在第三章中有說到,Datasource 的資料如果要提供給 Panel 使用需要透過 Query 和 Transform 的處理,然而在 Scenes 中不會讓開發者直接用 fetch 等 action 向 Grafana 後端請求,而是封裝了一些工具,讓開發者只需要設定相關的參數即可取得資料,這不僅更簡化了開發流程,也讓開發者可以更專注於數據的呈現和分析,而不必過多關注底層的資料獲取細節。

Scenes 資料取得的依賴

在 Scenes 中的 Scene Object 基本狀態有 $timeRange、$data、$variables 和 $behaviors,要讓 Scene Panel 取得資料可以依靠 $timeRange 和 $data 的設定,並調用特定的元件,元件會自行向 Grafana 後端請求,請求後也不需要做回傳資料的 setter,因為 Panel 或 Scene Object 會抓取本身的 $data 或是父層、祖先層的 $data 資料作為圖表呈現。而可以使用的元件有 $timeRange 的 SceneTimeRange 和 $data 的 SceneQueryRunner,以下逐一介紹:

時間範圍 ( Time Range)

const scene = new EmbeddedScene({
  $data: ...,
  $timeRange: new SceneTimeRange({ from: 'now-5m', to: 'now' }),
  body: ...,
  controls:[new SceneTimePicker({ isOnCanvas: true })]
})

Scene Object 中的 $timeRange 是管理所取資料時間範圍的屬性,而 SceneTimeRange 則是實現 $timeRange 功能的元件。還記得 Grafana 最初是將 time series 的資料作為視覺化工具,所以時間對於 Panel 而言是非常重要的設定。因此在介紹 SceneTimeRange 之前我們需要先了解在 Grafana 中 $timeRange 的資料格式。

$timeRange

$timeRange 接收的類型為 SceneTimeRangeLike,除了一些功能性的回調函數,最重要的是繼承了 SceneTimeRangeState 的類型,此類型也就是 timeRange 的格式,定義了時間範圍的具體屬性。其中包括了以下屬性:

  • from、to : 分別代表開始與結束的時間,直接以字串表示並支援相對時間表達式,例如:from: 'now-5m', to: 'now' ,代表『從5分鐘前到現在的時間範圍』,因此每次資料查詢時範圍都會自動調整為最近的5分鐘。
  • value: 實際的 TimeRange 物件,分別有 from、to 和 raw 屬性,但此處的 from 和 to 則是使用 DateTime 而非字串,所以可以進行更細膩的時間格式處理和計算,包括取得 timestemp 等資料。
  • timeZone: 時區設置,可以使用 UTC 時區 utc、瀏覽器時區 - browser、UTC 時區差 - UTC+8 或是 IANA 時區名稱 - Asia/Taipei。如果無設置預設為 browser。
  • fiscalYearStartMonth: 可讓使用者設定會計年度開始的月份。
  • weekStart: 每週的開始日,要注意 weekStart 會改變全域的日期區域設置,因此不支援同時有多個不同的 weekStart 值。

SceneTimeRange

了解了 $timeRange 的屬性後,我們同時也認識了 SceneTimeRange 可以設定的參數,並且元件回傳的值可以與 SceneQueryRunner 等 data 元件組合,重新進行資料查詢。

在 Dashboard 中,使用者也可以通過一些操作手動改變時間範圍或相關屬性。例如,在 controls 屬性中,可以設置 SceneTimePicker 元件。該元件是基於 @grafana/uiTimeRangePicker 元件進行封裝,並在選擇或改變時間範圍時,調用 $timeRange 所提供的 onTimeRangeChangeonTimeZoneChange 等回調函數來更新狀態。

https://ithelp.ithome.com.tw/upload/images/20240925/20152073IN9q4AVh33.png

數據資料 ( Data)

Scene Object 中的 $data 則是代表了視覺化中所需的數據資料,為了管理和處理這些資料,Scenes 提供了一個關鍵元件:SceneQueryRunner 。

雖然取得資料後 Panel 可以自行應用這些數據,但我們可以粗淺了解一下 $data 的資料格式。除了相關的回調函數,$data 的屬性只有一個型別為 PanelData 的 data,顧名思義是為 Panel 所設計的格式。其中有三個重要的必有屬性 state、series 及 timeRange:

  1. state - 為目前資料取得的加載狀態,分別有 NotStarted、Loading、Streaming、Done 以及 Error 五種狀態,可以藉由 LoadingState 的 enum 取得。目的是讓 UI 依據不同狀態呈現對應的內容。
  2. series - 實際的資料內容,以 DataFrame 陣列的形式呈現,而 DataFrame 是 Grafana 中標準的表格式資料格式,包含了定義每列內容的 fields、行數 - length 以及後端執行的相關資料 - meta。
  3. timeRange - 即為上個段落所表示的時間範圍資料,確保 Panel 上顯示的資料與選定的時一致。

SceneQueryRunner

SceneQueryRunner 是負責執行查詢和獲取原始數據的元件。元件在得到參數的初始化除了會針對 timeRange 狀態的改變與否進行監聽,更重要的就是對 Grafana 後端做資料請求。最核心的功能是 runWithTimeRange 的函數,會先整理請求的參數後調用由 @grafana/runtime 提供的 API 工具 - getDataSourceSrv() 顯取得需要哪一種 DataSource API 實例,再使用 getRunRequest 取得專門請求的函數 - runRequest,最後依據相對應的 DataSource 及參數執行請求。

流程圖

https://ithelp.ithome.com.tw/upload/images/20240925/20152073i7sHY23ED1.png

屬性

SceneQueryRunner 可以帶入的參數可以有 datasource、minInterval、maxDataPoints(限制回傳的最大資料點數量)、liveStreaming(是否啟用即時資料流)等功能,而最重要的參數是查詢參數 - queries,但每一種 Data source 都有自己的特定查詢語法,所以下方只以測試資料為範例。

而 datasource 屬性是告訴 SceneQueryRunner 以何種資料類型做查詢,可以傳入兩個參數:uid 和 type。

  • uid : 指定特定的資料源實例,可以在 Home > Connections > Data sources > 查詢的來源 中的 Name 取得。

    https://ithelp.ithome.com.tw/upload/images/20240925/20152073xUBP28avqC.png

  • type:該 Data source 所表示的類型,例如 testdata、prometheus、loki 等等。

Queries

queries 屬性會依據不同的 datasource 有不同的設定,但可以注意的是 queries 是一個陣列,所以可以針對第一層的 datasource 設定多種不同的 query 語法;同時也可以在同一個 Panel 中使用不同的 datasource 比較來自不同來源的數據或是複合查詢,Grafana 會分別處理每個查詢,再於前端將結果組合在一起。

範例一 - 同一 datasource 設定多種 query:

const multipleQueryRunner = new SceneQueryRunner({
  datasource: {
    uid: "gdev-testdata",
    type: "testdata",
  },
  queries: [
    {
      refId: "A",
      scenarioId: "random_walk",
      seriesCount: 5,
      alias: "__server_names",
      min: 30,
      max: 60,
    },
     {
      refId: "B",
      scenarioId: "random_walk",
      seriesCount: 5,
      alias: "__house_locations",
      min: 30,
      max: 60,
    },
  ],
  maxDataPoints: 100,
});

範例二 - 設定多種 datasource 的 query:

const multipleDsQueryRunner = new SceneQueryRunner({
  queries: [
    {
      refId: "A",
      datasource: {
        type: "prometheus",
        uid: "P1234",
      },
      expr: 'sum(rate(http_requests_total{job="api-server"}[5m]))',
      // 其他 Prometheus 特定的查詢參數...
    },
    {
      refId: "B",
      datasource: {
        type: "mysql",
        uid: "M5678",
      },
      rawSql: "SELECT * FROM users WHERE created_at > NOW() - INTERVAL 1 DAY",
      // 其他 MySQL 特定的查詢參數...
    },
  ],
  maxDataPoints: 100,
});

💡NOTICE
queries 中皆會有一個 refId 的屬性,作為 query 的唯一識別值,通常是字母(A, B, C...)可以作為 Panel 中引用特定 query 的結果,也可以依據這個屬性來做結果的後續處理,例如下方範例。另外在 Explore 頁面中每種 query 上方也會顯示 refId 方便使用者辨識。

https://ithelp.ithome.com.tw/upload/images/20240925/20152073vVmQa9kXA9.png

{
 refId: "C",
 expression: "$A + $B",
 type: "math",
 // ...
}

筆者語錄
透過本文的介紹,我們已經了解在 Grafana Scenes 中如何有效使用 $timeRange$data 來管理和取得資料,並透過 SceneTimeRangeSceneQueryRunner 元件簡化了開發流程,也帶讀者們認識這請求元件背後所執行的過程。這兩個功能的結合不僅提升開發效率,讓開發者專注於資料的視覺化與分析,減少在底層資料取得上的重複工作。當然還會有許多不同的請求情境與需求,因此 Scenes 也提供其他更複雜的資料請求工具,將會在後續的進階功能中向各位介紹!

參考資料

https://github.com/grafana/grafana/blob/40157111336615a85440f990dd584c93c42600b6/packages/grafana-runtime/src/services/dataSourceSrv.ts


上一篇
靠 Grafana 吃飯的第十天 - 當 Scenes 成為 Grafana 的切版工具
下一篇
靠 Grafana 吃飯的第十二天 - Grafana Scene 的 Variables 多重宇宙
系列文
論前端工程師如何靠 Grafana 吃飯:從 Grafana App 到前端可觀測性13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言