OpenTSDB 开发指南之 查询数据
前面博主寫了一篇文章去介紹opentsdb的http接口的使用方法,但是某一些接口的使用還是比較復(fù)雜,這篇文章會(huì)通過example來詳細(xì)講述opentsdb的一些特性。
本文的舉的例子有這些:
一、基本的寫入和查詢
這個(gè)功能是最基本,也是最常用的。
寫數(shù)據(jù):寫入數(shù)據(jù)post接口為 /api/put?details,details表示會(huì)將寫入的詳細(xì)結(jié)果返回回來:
?
#請求體 [{"metric": "sys.cpu.nice","timestamp": 1346846402,"value": 18,"tags": {"host": "web01","dc": "lga"}} ] #寫入成功返回的內(nèi)容 {"success": 1,"failed": 0,"errors": [] }查數(shù)據(jù):寫入成功之后,當(dāng)然可以去查詢。查詢post接口為 /api/query:
?
#請求體 {"start": 1346846402,"end": 1346846403,#返回?cái)?shù)據(jù)對應(yīng)的tsUID"showTSUIDs":"true", "queries": [{"aggregator": "avg","metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"}}] } #返回?cái)?shù)據(jù) [{"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000001000002000002" #數(shù)據(jù)對應(yīng)的tsUID],"dps": {"1346846402": 18}} ]這里需要對tsUID進(jìn)行說明一下,opentsdb是由metric+tags來區(qū)分?jǐn)?shù)據(jù)的,當(dāng)metric和tags相同時(shí),其tsUID就會(huì)相同,代表著同一系列的數(shù)據(jù)。那么,假如我們想對這一系列數(shù)據(jù)進(jìn)行標(biāo)注和說明呢?見下一個(gè)example。
二、數(shù)據(jù)的注釋和說明
數(shù)據(jù)的注釋和說明是用到了 /api/annotation 接口,post方式是寫入annotation數(shù)據(jù),get是查詢annotation數(shù)據(jù)。
?
#post接口的請求body {"startTime":"1346846402",#和返回前面一個(gè)example返回tsUID相同,這樣時(shí)間序列數(shù)據(jù)就和annotation數(shù)據(jù)關(guān)聯(lián)了起來,可作為時(shí)間序列數(shù)據(jù)的注釋和說明"tsuid":"000001000001000001000002000002","description": "Testing Annotations","notes": "These would be details about the event, the description is just a summary","custom": {"owner": "jdoe","dept": "ops"} }當(dāng)寫入成功時(shí)間,再次運(yùn)行查詢example1中的 /api/query 請求,即可得到:
?
[{"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000001000002000002"],"annotations": [{"tsuid": "000001000001000001000002000002","description": "Testing Annotations","notes": "These would be details about the event, the description is just a summary","custom": {"owner": "jdoe","dept": "ops"},"startTime": 1346846402,"endTime": 0}],"dps": {"1346846402": 18}} ]可見,此次在返回?cái)?shù)據(jù)的清楚上,把相關(guān)聯(lián)的注釋(annotation數(shù)據(jù))也一起返回回來,注釋一般可以用來解釋和說明數(shù)據(jù)。
三、子查詢
在 /api/query 接口中,body中有一個(gè)參數(shù)是queries,它表示可以含有多個(gè)子查詢,所謂子查詢就是只要數(shù)據(jù)滿足其中的一個(gè)子查詢,數(shù)據(jù)就會(huì)返回回來。注意每次查詢至少需要一個(gè)子查詢。
在example1中寫入一條數(shù)據(jù)的前提下,這里再向tsdb中寫入一條數(shù)據(jù):
?
[{"metric": "sys.cpu.nice","timestamp": 1346846402,"value": 9,"tags": {"host": "web02","dc": "lga"}} ] # 通過 /api/query 接口我們可以查得該條數(shù)據(jù)的tsUID為000001000001000003000002000002下面查詢body就表示有兩個(gè)子查詢:
?
//請求體 {"start": 1346846401,"end": 1346846403,"showTSUIDs":"true","queries": [{ //第一個(gè)子查詢,查詢的是example1中寫入的數(shù)據(jù)"aggregator": "avg","metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"}},{ //第二個(gè)子查詢,查詢的是剛剛寫入的數(shù)據(jù)"aggregator": "avg","tsuids":["000001000001000003000002000002"]}] }//返回結(jié)果 [{ //第一個(gè)子查詢對應(yīng)的數(shù)據(jù)"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000001000002000002"],"annotations": [{"tsuid": "000001000001000001000002000002","description": "Testing Annotations","notes": "These would be details about the event, the description is just a summary","custom": {"owner": "jdoe","dept": "ops"},"startTime": 1346846402,"endTime": 0}],"dps": {"1346846402": 18}},{ //第二個(gè)子查詢對應(yīng)的數(shù)據(jù)"metric": "sys.cpu.nice","tags": {"host": "web02","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000003000002000002"],"dps": {"1346846402": 9}} ]在平常使用過程中我們可以使用單個(gè)或者多個(gè)子查詢,還有需要注意對于每個(gè)子查詢而言,主要有兩種類型:
四、查詢中的filters使用
從opentsdb2.2版本便支持filter,它其實(shí)是用于過濾tags的,可以作為tags查詢的替代者,并且比tags更加靈活。請求body如下:
?
{"start": 1346846401,"end": 1346846403,"showTSUIDs":"true","queries": [ {"aggregator": "avg","metric": "sys.cpu.nice","filters": [{ "type":"literal_or", "tagk":"host","filter":"web01|web02","groupBy":true}]}] }| type | 過濾器的類型,可以訪問 /api/config/filters 接口查看支持的所有類型,這里 literal_or 表示value是一個(gè)枚舉 |
| tagk | 指定過濾的key |
| filter | 和相type對應(yīng),這里表示對web01和web02都進(jìn)行匹配 |
| groupBy | 是否對匹配到的數(shù)據(jù)進(jìn)行分組 |
這里使用literal_or,filter里面的多個(gè)tagV以豎線相隔,這個(gè)過濾器的意思是對tagK為host進(jìn)行匹配,并且value為web01和web02都數(shù)據(jù)都會(huì)匹配成功。
返回結(jié)果:
?
[{"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000001000002000002"],"annotations": [{"tsuid": "000001000001000001000002000002","description": "Testing Annotations","notes": "These would be details about the event, the description is just a summary","custom": {"owner": "jdoe","dept": "ops"},"startTime": 1346846402,"endTime": 0}],"dps": {"1346846402": 18}},{"metric": "sys.cpu.nice","tags": {"host": "web02","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000003000002000002"],"dps": {"1346846402": 9}} ]可見本次filter查詢用一個(gè)子查詢的結(jié)果和example3中用了兩個(gè)子查詢的效果是一樣的。
五、查詢數(shù)據(jù)的rate(增長率)
在某些情況下,我們查詢的可能并不是數(shù)據(jù)的本身,而是它的增長率。恰巧opentsdb有幫我們提供這個(gè)功能:子查詢中的rate參數(shù)。
首先我們先寫入3條數(shù)據(jù),時(shí)間分別間隔兩秒,數(shù)據(jù)分別為0、64000和1000。
?
[{"metric": "sys.cpu.nice","timestamp": 1346846410,"value": 0,"tags": {"host": "web03","dc": "lga"}},{"metric": "sys.cpu.nice","timestamp": 1346846412,"value": 64000,"tags": {"host": "web03","dc": "lga"}},{"metric": "sys.cpu.nice","timestamp": 1346846414,"value": 1000,"tags": {"host": "web03","dc": "lga"}} ]查詢增長率的請求body如下:
?
{"start": 1346846409,"end": 1346846414,"showTSUIDs":"true","queries": [ {"aggregator": "avg","metric": "sys.cpu.nice","rate":true, # 查詢增長率"rateOptions":{"counter":false },"tags": {"host": "web03","dc": "lga"}}] }# 響應(yīng)結(jié)果 [{"metric": "sys.cpu.nice","tags": {"host": "web03","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000007000002000002"],"dps": {"1346846412": 32000,"1346846414": -31500}} ]3200=(6400-0)/2,-31500=(1000-6400)/2,可見增長率是以秒為單位。
六、直方圖中百分位數(shù)(percentiles)的查詢
opentsdb在2.4版本對直方圖(histogram進(jìn)行了支持),本個(gè)example中首先寫入直方圖數(shù)據(jù),然后根據(jù)數(shù)據(jù)對百分位數(shù)(percentile)進(jìn)行查詢。
寫入數(shù)據(jù)的body如下:buckets是直方圖數(shù)據(jù),意思為0到1.75區(qū)間的數(shù)值為12,1.75到3.5區(qū)間的數(shù)值為16.
?
{"metric": "sys.cpu.nice","timestamp": 1356998400,"overflow": 1,"underflow": 0,"buckets": { "0,1.75": 12,"1.75,3.5": 16},"tags": {"host": "web01","dc": "lga"} }關(guān)于百分位的定義可以自行查資料進(jìn)行詳細(xì)認(rèn)識(shí),本次查詢中percentiles列表里面就是需要查詢的百分位,需要注意的是列表里面的數(shù)字的取值區(qū)間是[0,100],并且可以不按照順序排列。查詢body如下:
?
{"start": 1356998400,"end": 1356998401,"showTSUIDs":"true","queries": [ {"aggregator": "sum","percentiles": [100,99,43,42,1],"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"}}] }請求的結(jié)果如下:
?
[{"metric": "sys.cpu.nice_pct_1.0","tags": {"host": "web01","dc": "lga"},"aggregateTags": [],"tsuids": ["000001000001000001000002000002"],"dps": {"1356998400": 0.875}},{"metric": "sys.cpu.nice_pct_42.0",···"dps": {"1356998400": 0.875}},{"metric": "sys.cpu.nice_pct_43.0",···"dps": {"1356998400": 2.625}},{"metric": "sys.cpu.nice_pct_99.0",···"dps": {"1356998400": 2.625}},{"metric": "sys.cpu.nice_pct_100.0",···"dps": {"1356998400": 2.625}} ]返回內(nèi)容如上:其中相同部分已經(jīng)省略,返回的metric由 原始metric_pct_number 組成,下面講述它們的計(jì)算方式:
第一個(gè)區(qū)間的數(shù)值為12,第二個(gè)區(qū)間的數(shù)值為16,12/(12+16)=0.428。
- 我們看到1和42的百分位的取值都是0.875,0.875=1.75/2,取的第一個(gè)區(qū)間的中點(diǎn)坐標(biāo),可以得到在0.428之前的百分位的數(shù)值都為0.875。
- 43、99、100百分位對應(yīng)的數(shù)值都為2.625,2.625=1.75+(3.5-1.75)/2,2.625的物理意義就是第二個(gè)區(qū)間中點(diǎn)的橫坐標(biāo),因此43到100之間的百分位取值都為2.525。
七、Downsampling(下采樣)
下采樣即讓濃密數(shù)據(jù)變稀疏的過程,首先寫入10條數(shù)據(jù),數(shù)值分別為0到9,相鄰數(shù)據(jù)的時(shí)間間隔為1s:
?
[{"timestamp": 1562068000,"value": 0,"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"}},······{"metric": "sys.cpu.nice","timestamp": 1562068009,"value": 9,"tags": {"host": "web01","dc": "lga"}} ]下采樣查詢如下,downsample字段是一個(gè)字符串,該字段由 interval-aggregate-fill policy 組成,分別表示時(shí)間間隔、聚合方法、缺少的值補(bǔ)齊的方法。本次查詢下采樣間隔為2s,聚合方法是取聚合區(qū)間的最小值,并且缺少的值用0補(bǔ)齊:
?
{"start": 1562068000,"end": 1562068009,"queries": [ {"aggregator": "avg","metric": "sys.cpu.nice","downsample":"2s-min-zero","tags": {"host": "web01","dc": "lga"}}] }返回結(jié)果如下,可見原本每秒一個(gè)數(shù)據(jù)在結(jié)果中是每兩秒返回一個(gè)數(shù)據(jù),并且在每個(gè)間隔中,都是取的最小值。
?
[{"metric": "sys.cpu.nice","tags": {"host": "web01","dc": "lga"},"aggregateTags": [],"dps": {"1562068000": 0,"1562068002": 2,"1562068004": 4,"1562068006": 6,"1562068008": 8}} ]八、query/exp 的使用(查詢中使用表達(dá)式)
這個(gè)接口允許使用表達(dá)式進(jìn)行查詢,可以對查詢的多個(gè)結(jié)果進(jìn)行操作。
在example7寫入數(shù)據(jù)的基礎(chǔ)上,再寫入如下數(shù)據(jù),相比example7的數(shù)據(jù)而言僅僅是metric發(fā)生了變化:
?
[{"timestamp": 1562068000,"value": 0,"metric": "sys.cpu.nice1","tags": {"host": "web01","dc": "lga"}},······{"metric": "sys.cpu.nice1","timestamp": 1562068009,"value": 9,"tags": {"host": "web01","dc": "lga"}} ]緊接著使用表達(dá)式進(jìn)行查詢,查詢body如下,
- time 定義了查詢的時(shí)間區(qū)間和聚合方式
- filters 定義了一個(gè)過濾器f1
- metric 中指定了對sys.cpu.nice和sys.cpu.nice1兩個(gè)metric進(jìn)行查詢,并且兩個(gè)metric都使用同一個(gè)filter:f1
- expressions 中是語法表達(dá)式,e就等于結(jié)果a加上結(jié)果b,e2就等于e乘以2
- outputs 指定需要輸出的表達(dá)式計(jì)算結(jié)果
?
{"time": {"start": "1562068000","end":"1562068009","aggregator":"sum"},"filters": [{ "tags": [{"type": "wildcard","tagk": "host","filter": "web*","groupBy": true}],"id": "f1"}],"metrics": [{"id": "a","metric": "sys.cpu.nice","filter": "f1","fillPolicy":{"policy":"nan"}},{"id": "b", "metric": "sys.cpu.nice1","filter": "f1","fillPolicy":{"policy":"nan"}}],"expressions": [{"id": "e","expr": "a + b"},{"id":"e2","expr": "e * 2"}],"outputs":[{"id":"e", "alias":"e"},{"id":"e2", "alias":"e2"}]}查詢結(jié)果如下,query是里面是關(guān)于查詢請求body的信息,為了節(jié)約空間這里省略。可以得知表達(dá)式計(jì)算是對同一個(gè)時(shí)間點(diǎn)進(jìn)行計(jì)算的。
- outputs中的e,時(shí)間點(diǎn)1562068001000對應(yīng)的值為2,sys.cpu.nice和sys.cpu.nice1在1562068001000對應(yīng)的數(shù)值都為1,便可和表達(dá)式中 e=a+b 對應(yīng)起來。
- e2中時(shí)間點(diǎn)1562068001000對應(yīng)的值為4,便可和表達(dá)式中 e2=ex2 對應(yīng)起來。
?
{"outputs": [{"id": "e","alias": "e","dps": [ [1562068000000,0],[1562068001000,2],[1562068002000,4],[ 1562068003000, 6],[1562068004000,8],[1562068005000,10],[1562068006000,12],[1562068007000,14],[1562068008000,16],[1562068009000,18] ],"dpsMeta": { "firstTimestamp": 1562068000000,"lastTimestamp": 1562068009000, "setCount": 10,"series": 1},"meta": [{"index":0,"metrics":["timestamp"]},{"index":1,"metrics":["sys.cpu.nice","sys.cpu.nice1"],"commonTags":{"host":"web01","dc":"lga"},"aggregatedTags":[]}]},{"id": "e2","alias": "e2","dps": [[1562068000000,0],[1562068001000,4],[1562068002000,8],[1562068003000,12],[1562068004000,16],[1562068005000,20],[1562068006000,24],[1562068007000,28],[1562068008000,32],[1562068009000,36]],"dpsMeta": { "firstTimestamp": 1562068000000,"lastTimestamp": 1562068009000,"setCount": 10,"series": 1},"meta": [{"index":0,"metrics":["timestamp"]},{"index":1,"metrics":["sys.cpu.nice","sys.cpu.nice1"],"commonTags":{"host":"web01","dc":"lga"},"aggregatedTags":[]}]}],"query": {······} }九、trees詳解
opentsdb2.0版本引入了tree的概念,tree可以將一些時(shí)間序列組織起來使其具有層次結(jié)構(gòu),和文件系統(tǒng)一樣,tree中的葉子類比于文件系統(tǒng)的文件,tree中的branch類比于文件系統(tǒng)的文件夾,還可以繼續(xù)在里面創(chuàng)建新的文件夾。其相關(guān)定義可參考官網(wǎng)。
在tsdb中創(chuàng)建一棵樹步驟如下:
現(xiàn)在按照上面的流程進(jìn)行操作實(shí)際一遍,首先對時(shí)間序列、數(shù)的規(guī)則進(jìn)行說明。
現(xiàn)在我們有如下的時(shí)間序列數(shù)據(jù):
圖1
這些時(shí)間序列需要滿足如下規(guī)則(rules),level表示數(shù)的第幾層,order表示同一level的不同rule有不同的優(yōu)先級。level 0 有兩個(gè)rule,當(dāng)滿足order為0的rule時(shí),會(huì)跳過order為1的rule;反之order為1的rule就會(huì)生效。
圖2
基于上面的時(shí)間序列和tree的規(guī)則,可以得到下面的tree:
圖3
下面按照步步驟對這棵樹進(jìn)行生成:
?
{"name":"Network","description":"","notes":"","rules":null,"created":1368964815,"strictMatch":false,"storeFailures":false,"enabled":false}創(chuàng)建成功后 可以用 get方式請求 /api/tree 接口查詢tree的相關(guān)信息,并可以獲得新創(chuàng)建tree的id,treeId下面也會(huì)用到。
?
{"type":"tagk","field":"dc","description":"a tagk named data center","level":0,"order":0,"treeId":1}{"type":"tagk","field":"host","description":"a tagk named host","regex":".*\\.(.*)\\.mysite\\.com","level":0,"order":1,"treeId":1}{"type":"tagk","field":"host","description":"a tagk named host","separator":"\\.","level":1,"order":0,"treeId":1}{"type":"metric","description":"metric","separator":"\\.","level":2,"order":0,"treeId":1}| treeId | 用于指定測試的tree |
| tsuids | 指定時(shí)間序列,試圖將這些時(shí)間序列放入這顆樹中進(jìn)行測試,多個(gè)tsuid以 ","相隔 |
這里的tsuids當(dāng)然是指圖1中時(shí)間序列對應(yīng)的tsuid,可以用 /api/query接口進(jìn)行查詢。
/api/tree/test會(huì)返回這些時(shí)間序列基于這棵樹的層次關(guān)系,若這個(gè)層次結(jié)構(gòu)不滿足需求則需要對rule進(jìn)行修改,若滿則需求則可進(jìn)行下一步。
至此這棵樹的定義就已經(jīng)完成,可以用 /api/tree/branch 接口對tree的分支進(jìn)行查詢,查詢的參數(shù)有兩個(gè):
| treeid | tree的id |
| branch | branch的id |
兩個(gè)參數(shù)只需要一個(gè),當(dāng)傳遞treeid時(shí),就會(huì)返回root branch的信息。當(dāng)只傳遞branch時(shí),就會(huì)返回對應(yīng)branch的信息。當(dāng)兩個(gè)參數(shù)都傳遞時(shí),參數(shù)treeid就會(huì)被忽略。
?
總結(jié)
以上是生活随笔為你收集整理的OpenTSDB 开发指南之 查询数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hive - HWI 简单使用
- 下一篇: C++ 中export 关键字的尴尬处境