これで過去の分を入れるようなバッチを作るかなと 書いていましたが、いざ始めてみると事前調査が必要だったりしたのでまとめます。
http://www.tepco.co.jp/forecast/html/images/juyo-2011.csv
ここから2011年のデータを取得します。
注意:この作業を行うにあたって、心構えとしては
・運用中のzabbixが不安定になる覚悟をする。
・バックアップを取ったデータベースがなければ、過去データはすべて破棄する覚悟。
・作業を行った直後は問題がなかったとしても、特殊なデータや状況が発生した時に、データ破損してしまうことを受け入れる覚悟。
これらのことが許容できる環境の持ち主か、どうにもせっぱつまっていて、上記のリスクに比べたら相当に致命的な状況まで追い込まれている人じゃない限り、やらないほうが良い作業だと思っています。※技術力向上のためにやれるなら幸せかもですが。
■データの挿入先であるtrendsテーブルを調査
まずはテーブルを見つけました。trends テーブルとtrends_unit です。使い分けはどうなのか?何を入れるべきかを調べました。
PUBLIC | trends | TABLE | zabbix PUBLIC | trends_uint | TABLE | zabbix |
■テーブル構造
zabbix=# \d trends TABLE "public.trends" Column | TYPE | Modifiers -----------+---------------+---------------------------- itemid | bigint | NOT NULL DEFAULT 0::bigint clock | INTEGER | NOT NULL DEFAULT 0 num | INTEGER | NOT NULL DEFAULT 0 value_min | numeric(16,4) | NOT NULL DEFAULT 0.0000 value_avg | numeric(16,4) | NOT NULL DEFAULT 0.0000 value_max | numeric(16,4) | NOT NULL DEFAULT 0.0000 Indexes: "trends_pkey" PRIMARY KEY, btree (itemid, clock) zabbix=# \d trends_uint TABLE "public.trends_uint" Column | TYPE | Modifiers -----------+---------------+----------------------------- itemid | bigint | NOT NULL DEFAULT 0::bigint clock | INTEGER | NOT NULL DEFAULT 0 num | INTEGER | NOT NULL DEFAULT 0 value_min | numeric(20,0) | NOT NULL DEFAULT 0::numeric value_avg | numeric(20,0) | NOT NULL DEFAULT 0::numeric value_max | numeric(20,0) | NOT NULL DEFAULT 0::numeric Indexes: "trends_uint_pkey" PRIMARY KEY, btree (itemid, clock) |
itemid はアイテムと紐づくところでしょうし、clockは1時間ごとの時間が入っているはずです。
value_*はそれぞれ、値が入っているところはグラフなどで見ていました。
不思議なのは、num です。これは何者?何に使うの?っていうことが分からないとバッチで入れるなんてできないと思いましたので調べました。
まずは、前回で作った電力使用量と使用率のアイテムから、どんな値が入っているかを調べてみます。
■現在のデータから対象のitemid を見つける。
itmes テーブルの構造です。僕はkey_には固定文言が入ると思ったのでlike で探してみました。
zabbix=# \d items TABLE "public.items" Column | TYPE | Modifiers -----------------------+------------------------+----------------------------------------- itemid | bigint | NOT NULL DEFAULT 0::bigint TYPE | INTEGER | NOT NULL DEFAULT 0 snmp_community | character varying(64) | NOT NULL DEFAULT ''::character varying snmp_oid | character varying(255) | NOT NULL DEFAULT ''::character varying snmp_port | INTEGER | NOT NULL DEFAULT 161 hostid | bigint | NOT NULL DEFAULT 0::bigint description | character varying(255) | NOT NULL DEFAULT ''::character varying key_ | character varying(255) | NOT NULL DEFAULT ''::character varying delay | INTEGER | NOT NULL DEFAULT 0 history | INTEGER | NOT NULL DEFAULT 90 trends | INTEGER | NOT NULL DEFAULT 365 lastvalue | character varying(255) | lastclock | INTEGER | prevvalue | character varying(255) | status | INTEGER | NOT NULL DEFAULT 0 value_type | INTEGER | NOT NULL DEFAULT 0 trapper_hosts | character varying(255) | NOT NULL DEFAULT ''::character varying units | character varying(10) | NOT NULL DEFAULT ''::character varying multiplier | INTEGER | NOT NULL DEFAULT 0 delta | INTEGER | NOT NULL DEFAULT 0 prevorgvalue | character varying(255) | snmpv3_securityname | character varying(64) | NOT NULL DEFAULT ''::character varying snmpv3_securitylevel | INTEGER | NOT NULL DEFAULT 0 snmpv3_authpassphrase | character varying(64) | NOT NULL DEFAULT ''::character varying snmpv3_privpassphrase | character varying(64) | NOT NULL DEFAULT ''::character varying formula | character varying(255) | NOT NULL DEFAULT '1'::character varying error | character varying(128) | NOT NULL DEFAULT ''::character varying lastlogsize | INTEGER | NOT NULL DEFAULT 0 logtimefmt | character varying(64) | NOT NULL DEFAULT ''::character varying templateid | bigint | NOT NULL DEFAULT 0::bigint valuemapid | bigint | NOT NULL DEFAULT 0::bigint delay_flex | character varying(255) | NOT NULL DEFAULT ''::character varying params | text | NOT NULL DEFAULT ''::text ipmi_sensor | character varying(128) | NOT NULL DEFAULT ''::character varying data_type | INTEGER | NOT NULL DEFAULT 0 authtype | INTEGER | NOT NULL DEFAULT 0 username | character varying(64) | NOT NULL DEFAULT ''::character varying password | character varying(64) | NOT NULL DEFAULT ''::character varying publickey | character varying(64) | NOT NULL DEFAULT ''::character varying privatekey | character varying(64) | NOT NULL DEFAULT ''::character varying mtime | INTEGER | NOT NULL DEFAULT 0 Indexes: "items_pkey" PRIMARY KEY, btree (itemid) "items_1" UNIQUE, btree (hostid, key_) "items_3" btree (status) "items_4" btree (templateid) |
WHERE key_ like ‘%denki%’ にて、アイテムを探しました。SQL叩かずに、Pgadminなど使って調べたほうが早いかもしれませんが、CUIでできるところまでやるのが癖になってしまっています。
zabbix=# SELECT itemid,TYPE,key_,trends,units,data_type FROM items WHERE key_ LIKE '%denki%'; itemid | TYPE | key_ | trends | units | data_type --------+------+----------------------+--------+-------+----------- 22497 | 0 | denki.VALUE[MIN,20] | 365 | w | 0 22498 | 0 | denki.VALUE[rate,20] | 365 | % | 0 (2 rows) |
あっさりと見つかったのですが、22497(使用量)が入っているテーブルと、22498(使用率)が入っているテーブルは違いました。
zabbix=# SELECT * FROM trends WHERE itemid IN (22497,22498) LIMIT 5; itemid | clock | num | value_min | value_avg | value_max --------+------------+-----+-----------+-----------+----------- 22498 | 1309870800 | 10 | 71.1900 | 72.2360 | 73.6000 22498 | 1309867200 | 1 | 71.8500 | 71.8500 | 71.8500 22498 | 1309874400 | 10 | 65.9000 | 68.3120 | 70.8200 22498 | 1309878000 | 1 | 64.4200 | 64.4200 | 64.4200 22498 | 1309881600 | 10 | 56.0000 | 57.2920 | 58.6800 (5 rows) |
※電気使用量がない
zabbix=# SELECT * FROM trends WHERE itemid = 22497 LIMIT 5; itemid | clock | num | value_min | value_avg | value_max --------+-------+-----+-----------+-----------+----------- (0 rows) |
■trends_uintにあった。
zabbix=# SELECT * FROM trends_uint WHERE itemid = 22497 LIMIT 5; itemid | clock | num | value_min | value_avg | value_max --------+------------+-----+-----------+-----------+----------- 22497 | 1309705200 | 2 | 3124 | 3138 | 3153 22497 | 1309708800 | 9 | 2759 | 2842 | 2926 22497 | 1309712400 | 11 | 2652 | 2701 | 2765 22497 | 1309716000 | 11 | 2610 | 2628 | 2661 22497 | 1309719600 | 11 | 2598 | 2610 | 2631 (5 rows) ※途中から倍数で調整したのでこんな形 22497 | 1309816800 | 11 | 2896 | 3033 | 3163 22497 | 1309820400 | 11 | 3171 | 6377275424 | 35300000000 22497 | 1309824000 | 11 | 35640000000 | 37525454543 | 38930000000 22497 | 1309827600 | 11 | 39300000000 | 40225454543 | 41030000000 22497 | 1309831200 | 11 | 41080000000 | 41630909090 | 42060000000 |
■numってなんだろう?
ここで疑問にわいたのがnum というカラムの存在。下記のように要素をとってみると見事にバラバラ。
zabbix=# SELECT DISTINCT(num) FROM trends_uint WHERE itemid = 22497 ; num ----- 6 14 13 12 8 1 9 2 7 10 11 (11 rows) |
どうも、11が一番数として多いみたいなんだけれど、どういうことなのか調べてみた。
zabbix=# SELECT * FROM trends_uint WHERE itemid = 22497 ORDER BY num LIMIT 1000; itemid | clock | num | value_min | value_avg | value_max --------+------------+-----+-------------+-------------+------------- 22497 | 1309964400 | 1 | 32430000000 | 32430000000 | 32430000000 22497 | 1311001200 | 1 | 34480000000 | 34480000000 | 34480000000 22497 | 1310914800 | 1 | 34060000000 | 34060000000 | 34060000000 22497 | 1310482800 | 1 | 34380000000 | 34380000000 | 34380000000 22497 | 1310396400 | 1 | 35040000000 | 35040000000 | 35040000000 22497 | 1310050800 | 1 | 32070000000 | 32070000000 | 32070000000 22497 | 1310223600 | 1 | 33750000000 | 33750000000 | 33750000000 22497 | 1309878000 | 1 | 32920000000 | 32920000000 | 32920000000 22497 | 1310828400 | 1 | 34100000000 | 34100000000 | 34100000000 22497 | 1310742000 | 1 | 35110000000 | 35110000000 | 35110000000 22497 | 1310137200 | 1 | 34010000000 | 34010000000 | 34010000000 22497 | 1311087600 | 1 | 32810000000 | 32810000000 | 32810000000 22497 | 1310655600 | 1 | 33910000000 | 33910000000 | 33910000000 22497 | 1311174000 | 1 | 29820000000 | 29820000000 | 29820000000 22497 | 1310569200 | 1 | 33990000000 | 33990000000 | 33990000000 22497 | 1309957200 | 2 | 35770000000 | 35940000000 | 36110000000 22497 | 1309705200 | 2 | 3124 | 3138 | 3153 22497 | 1310310000 | 2 | 32530000000 | 32530000000 | 32530000000 22497 | 1309791600 | 6 | 3365 | 3431 | 3509 22497 | 1310839200 | 7 | 27350000000 | 27595714284 | 27790000000 22497 | 1309932000 | 7 | 41850000000 | 42101428570 | 42450000000 22497 | 1310832000 | 8 | 29840000000 | 30376249998 | 31070000000 22497 | 1309881600 | 8 | 28560000000 | 29143749998 | 29930000000 22497 | 1310313600 | 8 | 28400000000 | 28967499999 | 29700000000 22497 | 1310486400 | 9 | 29870000000 | 30479999999 | 31380000000 22497 | 1311091200 | 9 | 28990000000 | 29528888888 | 30210000000 22497 | 1311004800 | 9 | 30090000000 | 30679999999 | 31410000000 22497 | 1310918400 | 9 | 29640000000 | 30312222220 | 31110000000 22497 | 1310659200 | 9 | 29110000000 | 29816666664 | 30650000000 22497 | 1310140800 | 9 | 29440000000 | 30132222221 | 30970000000 22497 | 1311177600 | 9 | 26230000000 | 26672222220 | 27180000000 22497 | 1310572800 | 9 | 29450000000 | 30109999999 | 30740000000 22497 | 1310745600 | 9 | 30890000000 | 31497777776 | 32360000000 22497 | 1310227200 | 9 | 29270000000 | 29926666664 | 30620000000 22497 | 1309708800 | 9 | 2759 | 2842 | 2926 22497 | 1309867200 | 9 | 36720000000 | 37706666665 | 38800000000 22497 | 1310400000 | 9 | 30060000000 | 30735555553 | 31630000000 22497 | 1310054400 | 9 | 28040000000 | 28655555554 | 29480000000 22497 | 1309896000 | 10 | 26080000000 | 26327999998 | 26560000000 22497 | 1309921200 | 10 | 40230000000 | 40942999998 | 42040000000 22497 | 1309928400 | 10 | 42430000000 | 42492999999 | 42580000000 22497 | 1309924800 | 10 | 40530000000 | 41782999998 | 42450000000 22497 | 1309910400 | 10 | 36680000000 | 38296999997 | 39570000000 22497 | 1309917600 | 10 | 41180000000 | 41622999999 | 42000000000 22497 | 1309914000 | 10 | 39790000000 | 40484999999 | 41060000000 22497 | 1309906800 | 10 | 32420000000 | 34408999998 | 36450000000 22497 | 1309870800 | 10 | 36380000000 | 36914999998 | 37610000000 22497 | 1309874400 | 10 | 33680000000 | 34942999998 | 36190000000 22497 | 1309885200 | 10 | 27350000000 | 27858999997 | 28590000000 22497 | 1309888800 | 10 | 26680000000 | 26885999999 | 27110000000 22497 | 1309892400 | 10 | 26320000000 | 26544999997 | 26680000000 22497 | 1310180400 | 11 | 40940000000 | 41366363633 | 41800000000 22497 | 1310184000 | 11 | 41110000000 | 41846363634 | 42270000000 22497 | 1310187600 | 11 | 42300000000 | 42451818180 | 42670000000 22497 | 1310191200 | 11 | 42110000000 | 42299090908 | 42560000000 22497 | 1310194800 | 11 | 41710000000 | 41991818180 | 42210000000 22497 | 1310198400 | 11 | 40270000000 | 40909999998 | 41820000000 22497 | 1310202000 | 11 | 39630000000 | 39877272725 | 40180000000 22497 | 1310205600 | 11 | 39770000000 | 40109090906 | 40450000000 22497 | 1310209200 | 11 | 38650000000 | 39257272726 | 39960000000 22497 | 1310212800 | 11 | 36770000000 | 37688181815 | 38590000000 22497 | 1310216400 | 11 | 36120000000 | 36916363634 | 37840000000 22497 | 1310220000 | 11 | 34350000000 | 35370909089 | 36560000000 22497 | 1310230800 | 11 | 27820000000 | 28470909089 | 29180000000 22497 | 1310234400 | 11 | 27050000000 | 27359999997 | 27850000000 22497 | 1310238000 | 11 | 26420000000 | 26810909088 | 27110000000 22497 | 1309903200 | 11 | 29490000000 | 30714545453 | 32140000000 22497 | 1310414400 | 12 | 27170000000 | 27545833331 | 28050000000 22497 | 1310306400 | 12 | 33490000000 | 34488333332 | 35700000000 22497 | 1311141600 | 12 | 40330000000 | 40657499997 | 41020000000 22497 | 1310932800 | 12 | 27360000000 | 27613333330 | 27950000000 22497 | 1310727600 | 12 | 41290000000 | 42091666664 | 42810000000 22497 | 1311199200 | 12 | 26430000000 | 27009999998 | 27460000000 22497 | 1310475600 | 12 | 37710000000 | 38419999997 | 39190000000 22497 | 1309899600 | 13 | 26660000000 | 27809999997 | 29480000000 22497 | 1310515200 | 13 | 38640000000 | 40651538458 | 42020000000 22497 | 1310101200 | 13 | 41300000000 | 41459230766 | 41650000000 22497 | 1309996800 | 14 | 34030000000 | 35414285711 | 36800000000 |
1の時にはvalue_min,value_avg,value_max が同じ数字。
2にもvalueが同じものはあるし、6,7,8,9,10は法則すらパッと見てわからない。
11は一番多く、割愛。12,13,14もあるけれどやっぱり不明。
■trends が入っているプログラムを探す。
zabbix-1.8.4のソースからインストールしたので、コンパイルしたディレクトリに移動して、
# fgrep -R ‘trends’ ./*
こんな感じで探した。
./create/data/data.sql:insert into help_items values (5,'zabbix[trends]','Number of values stored in table TRENDS.'); ./create/data/data.sql:insert into help_items values (5,'zabbix[trends_uint]','Number of values stored in table TRENDS_UINT.'); ./frontends/php/api/classes/class.citem.php: 'trends', ./frontends/php/api/classes/class.citem.php: 'trends_uint', ./src/libs/zbxdbcache/dbcache.c: value_type = trends[0].value_type; ./src/libs/zbxdbcache/dbcache.c: case ITEM_VALUE_TYPE_FLOAT: table_name = "trends"; break; ./src/libs/zbxdbcache/dbcache.c: case ITEM_VALUE_TYPE_UINT64: table_name = "trends_uint"; break; ./src/libs/zbxdbcache/dbcache.c: zbx_error("Unsupported value type for trends"); ./src/libs/zbxdbcache/dbcache.c: for (i = 0; i < *trends_num; i++) ./src/libs/zbxdbcache/dbcache.c: trend = &trends[i]; ./src/libs/zbxdbcache/dbcache.c: trends_to = i + 1; ./src/libs/zbxdbcache/dbcache.c: for (i = 0; i < trends_to; i++) ./src/libs/zbxdbcache/dbcache.c: trend = &trends[i]; ./src/libs/zbxdbcache/dbcache.c: if (i == trends_to) ./src/libs/zbxdbcache/dbcache.c: /* if 'trends' is not a primary trends buffer */ ■一番有力 ./src/libs/zbxdbhigh/db.c: result = DBselect("select num,value_min,value_avg,value_max from trends where itemid=" ZBX_FS_UI64 " and clock=%d", ./src/libs/zbxdbhigh/db.c: DBexecute("update trends set num=%d, value_min=" ZBX_FS_DBL ", value_avg=" ZBX_FS_DBL ", value_max=" ZBX_FS_DBL " where itemid=" ZBX_FS_UI64 " and clock=%d", ./src/libs/zbxdbhigh/db.c: DBexecute("insert into trends (clock,itemid,num,value_min,value_avg,value_max) values (%d," ZBX_FS_UI64 ",%d," ZBX_FS_DBL "," ZBX_FS_DBL "," ZBX_FS_DBL ")", ./src/libs/zbxdbhigh/db.c: result = DBselect("select num,value_min,value_avg,value_max from trends_uint where itemid=" ZBX_FS_UI64 " and clock=%d", ./src/libs/zbxdbhigh/db.c: DBexecute("update trends_uint set num=%d,value_min=" ZBX_FS_UI64 ",value_avg=" ZBX_FS_UI64 ",value_max=" ZBX_FS_UI64 " where itemid=" ZBX_FS_UI64 " and clock=%d", ./src/libs/zbxdbhigh/db.c: DBexecute("insert into trends_uint (clock,itemid,num,value_min,value_avg,value_max) values (%d," ZBX_FS_UI64 ",%d," ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ")", |
■核心。 int DBadd_trend(zbx_uint64_t itemid, double value, int clock) { DB_RESULT result; DB_ROW row; int hour; int num; double value_min, value_avg, value_max; zabbix_log(LOG_LEVEL_DEBUG,"In add_trend()"); hour=clock-clock%3600; result = DBselect("select num,value_min,value_avg,value_max from trends where itemid=" ZBX_FS_UI64 " and clock=%d", itemid, hour); row=DBfetch(result); if(row) { num=atoi(row[0]); value_min=atof(row[1]); value_avg=atof(row[2]); value_max=atof(row[3]); if(value<value_min) value_min=value; if(value>value_max) value_max=value; value_avg=(num*value_avg+value)/(num+1); num++; DBexecute("update trends set num=%d, value_min=" ZBX_FS_DBL ", value_avg=" ZBX_FS_DBL ", value_max=" ZBX_FS_DBL " where itemid=" ZBX_FS_UI64 " and clock=%d", num, value_min, value_avg, value_max, itemid, hour); } else { DBexecute("insert into trends (clock,itemid,num,value_min,value_avg,value_max) values (%d," ZBX_FS_UI64 ",%d," ZBX_FS_DBL "," ZBX_FS_DBL "," ZBX_FS_DBL ")", hour, itemid, 1, value, value, value); } DBfree_result(result); return SUCCEED; |
この部分を見ると、今までのデータをチェックして、num をインクリメントしている。つまり、何回もこのデータはUPDATEされるということ。
インクリメントされた回数を表しているのなら、納得。このアイテムは5分おきに取得しているので、11回は55分となる。きっちり12回というのもあるだろうし、それ以上というのは、ちょっと頻度多くとってしまったからだろう。
とりあえず、テーブルの構造が分かったので、安心してinsert時にnum = 1 で入れられます。
今後も入れるかもしれません。その時は、シェルスクリプトで計算するのが面倒くさいので、ストアドプロシージャを使って、clockとitemid、valueを渡してチェックとインクリメント、平均値計算をするようにとか思っています。
7/31 追記
続きです。