作為當前最流行的圖形化運維監控解決方案之一,Grafana 提供了一個靈活易用的界面,可以連接多種不同的數據源,包括時序數據庫(Time Series Database)、云服務、監控系統等,然后從這些數據源中提取數據并實時地將其可視化。為了給用戶打造更豐富的可視化方案,TDengine 在開源不久就提供了對 Grafana 的支持,此后也在不斷升級改造 TDengine Grafana 插件,還推出了基于 Grafana 的零依賴監控解決方案 TDinsight。本篇文章將以 tdengine-datasource 為例介紹 Grafana 插(cha)件(jian)開發(fa)。
實際上,tdengine-datasource 是 TDengine 為(wei) Grafana 打造的(de) datasource 插件,它能夠從 TDengine 讀取數據,并展示到 Grafana。

開發環境準備
- Grafana
- go
- Mage:
- nodejs
- yarn
Grafana 配置
首先下載(zai) Grafana 并(bing)解(jie)壓(ya),修改(gai) conf/default.ini 配置。
- 修改插件加載路徑。Grafana 插件會默認加載在 plugins = data/plugins,這里需要修改為自己插件的地址。這里通常改為插件項目下的 dist 目錄。
[paths]
plugins = /path/to/Grafana-plugins
- 修改 allow_loading_unsigned_plugins 配置,配置項的值為插件的名字,允許 Grafana 加載 unsigned 的插件。
allow_loading_unsigned_plugins = my_plugin_name
新建插件
使用 grafna-create-plugin 創(chuang)建插件(jian),然后根據提(ti)示新建插件(jian)。
$ npx @Grafana/create-plugin
? What is going to be the name of your plugin? my-plugin # 輸入插件名字
? What is the organization name of your plugin? taosdata # 輸入公司名字
? How would you describe your plugin? my testing plugin # 輸入插件描述
? What type of plugin would you like? datasource # 選擇插件類型 app or panel or datasource
? Do you want a backend part of your plugin? Yes # datasource 類型插件是否包含后端
? Do you want to add Github CI and Release workflows? Yes # 是否添加 github ci 和 release 工作流
? Do you want to add a Github workflow for automatically checking "Grafana API compatibility" on PRs? Yes # 是否添加 pr 工作流
之后(hou) grafna-create-plugin 會(hui)在(zai)目錄(lu)創建名為 taosdata-myplugin-datasource 的插件(jian)(jian)工程。進到(dao)(dao)該目錄(lu)之后(hou),執(zhi)行 yarn install && yarn build && go mod tidy && mage -v build 即可構建插件(jian)(jian)。啟(qi)動 Grafana,在(zai) datasource 配置頁面就可以搜到(dao)(dao)該插件(jian)(jian),插件(jian)(jian)的前(qian)端(duan)代碼(ma)(ma)在(zai) src 目錄(lu),后(hou)端(duan)代碼(ma)(ma)在(zai) pkg 目錄(lu)。
后端代碼
后端代(dai)碼需要實現 QueryDataHandler 接口(kou)(kou)和 CheckHealthHandler 接口(kou)(kou),分別(bie)用于查詢(xun)數據和 checkHealth。
頁面查詢(xun)數(shu)據時會(hui)調(diao)用 QueryData 方法(fa)(fa)。不同的數(shu)據源,QueryData 方法(fa)(fa)實現(xian)會(hui)有差(cha)異,歸根結底,該方法(fa)(fa)的作用是(shi)從(cong)數(shu)據源查詢(xun)數(shu)據,并將數(shu)據封裝成 Data Frame。
type QueryDataHandler interface {
QueryData(ctx context.Context, req *QueryDataRequest) (*QueryDataResponse, error)
}
Grafana 會(hui)定時調用 CheckHealth 方法,以(yi)檢測插件的健(jian)康狀態。數據源配置(zhi)頁面的 Save & Test 按鈕也會(hui)調用 CheckHealth 方法來檢測配置(zhi)是否正確。
type CheckHealthHandler interface {
CheckHealth(ctx context.Context, req *CheckHealthRequest) (*CheckHealthResult, error)
}
前端代碼
grafana datasource plugin 需要有一定的前(qian)端代碼開發量,包含 datasource、數據(ju)源配置頁面(mian)和數據(ju)查詢頁面(mian)。
datasource-with-backend 插件,datasource 的前端代碼需要實(shi)現(extends)DataSourceWithBackend 接(jie)口。由于通過后端接(jie)口進行數據查詢,所以(yi)前端頁(ye)面代碼比較簡(jian)單(dan)。
datasource-backend 插件(jian),datasource 的(de)前端代碼需要實(shi)現(xian)(extends)DataSourceApi 接口,并(bing)至少(shao)實(shi)現(xian) query、testDatasource 等方法。其中 query 方法用(yong)于(yu)數據查詢,testDatasource 方法用(yong)于(yu)測試(shi)數據源配置。
async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse>
async testDatasource()
數據(ju)(ju)(ju)源(yuan)插件(jian)需(xu)要配置數據(ju)(ju)(ju)源(yuan)地(di)址(zhi)、授(shou)權等(deng)信息,通常還(huan)需(xu)要配置數據(ju)(ju)(ju)查(cha)詢方式,因此需(xu)要數據(ju)(ju)(ju)源(yuan)配置頁面和數據(ju)(ju)(ju)查(cha)詢頁面。
plugin.json 和 module.ts
如果是通過 grafna-create-plugin 創建的插件(jian)項目,grafna-create-plugin 會在 src 目錄下生成 plugin.json 和 module.ts 文件(jian)。其中 plugin.json 包(bao)(bao)含(han)了(le)插件(jian)的信息,包(bao)(bao)括插件(jian)類型、插件(jian)名字、ID 等(deng)。而 module.ts 是 grafana 插件(jian)的入口。
Grafana 和 backend plugin 通訊協議
Grafana 和(he) backend-plugin 是兩個(ge)進程,plugin 是 Grafana 的子進程,二者通過(guo) gRpc 通信,plugin 作(zuo)為 server 端,Grafana 作(zuo)為 client 端。
其 gRpc 通信協議(yi)可參考 ,從(cong)協議(yi)上看,backend-plugin 提供了(le)如下 service:
//---------------------------------------------------------
// Resource service enables HTTP-style requests over gRPC.
//---------------------------------------------------------
service Resource {
rpc CallResource(CallResourceRequest) returns (stream CallResourceResponse);
}
//-----------------------------------------------
// Data
//-----------------------------------------------
service Data {
rpc QueryData(QueryDataRequest) returns (QueryDataResponse);
}
//-----------------------------------------------
// Diagnostics
//-----------------------------------------------
service Diagnostics {
rpc CheckHealth(CheckHealthRequest) returns (CheckHealthResponse);
rpc CollectMetrics(CollectMetricsRequest) returns (CollectMetricsResponse);
}
//-----------------------------------------------------------------
// Stream -- EXPERIMENTAL and is subject to change until 8.0
//-----------------------------------------------------------------
service Stream {
// SubscribeStream called when a user tries to subscribe to a plugin/datasource
// managed channel path – thus plugin can check subscribe permissions and communicate
// options with Grafana Core. When the first subscriber joins a channel, RunStream
// will be called.
rpc SubscribeStream(SubscribeStreamRequest) returns (SubscribeStreamResponse);
// RunStream will be initiated by Grafana to consume a stream. RunStream will be
// called once for the first client successfully subscribed to a channel path.
// When Grafana detects that there are no longer any subscribers inside a channel,
// the call will be terminated until next active subscriber appears. Call termination
// can happen with a delay.
rpc RunStream(RunStreamRequest) returns (stream StreamPacket);
// PublishStream called when a user tries to publish to a plugin/datasource
// managed channel path. Here plugin can check publish permissions and
// modify publication data if required.
rpc PublishStream(PublishStreamRequest) returns (PublishStreamResponse);
}
grafana backend-plugin 實現(xian)依賴 庫,go-plugin 是(shi)一(yi)個基(ji)于 gRpc 的golang 插件系統,由 HashiCorp 開(kai)發,并在業界廣(guang)泛使用,grafana backend plugin 就是(shi)基(ji)于 go-plugin 實現(xian)的。
tdengine-datasource
tdengine-datasource 是(shi) TDengine 的(de) grafana 數據源(yuan)插件。目(mu)前(qian),tdengine-datasource 不完全是(shi)一個 backend-plugin,TDinsight 或 dashboard 的(de)數據仍然(ran)是(shi)通過前(qian)端頁面直接查詢,只有(you)后端 alerting 的(de)查詢請求會經(jing)過后端。

ConfigEditor
在數(shu)據(ju)源配置頁面(mian)可以(yi)(yi)配置數(shu)據(ju)源的信息(xi)。添加數(shu)據(ju)源時,需要配置數(shu)據(ju)源的名字(默認為(wei) TDengine Datasource)、TDengine 的地址(zhi)、認證信息(xi),通過(guo) Save&test 按鈕(niu),可以(yi)(yi)校驗(yan) TDengine 的認證信息(xi)。

QueryEditor
在查詢(xun)配(pei)置頁面可以自定(ding)義數據查詢(xun),包含查詢(xun) sql、時間戳偏移配(pei)置、group by 配(pei)置等。

結語
現在你(ni)可以操作體驗(yan)了,希望本篇文章能帶給你(ni)一些幫助。更(geng)多示例(li)可參考:
- tdengine-datasource 代碼
- 更多 Grafana-plugin 示例
如果在使用 TDengine Grafana 插件的過程中遇到任何問題,或者有新的功能建議,也歡迎在 () 上和我們交流。或者添加小T vx:tdengine,和 TDengine 的技術研發人(ren)員(yuan)進行直(zhi)接溝通。


























