原文地址: http://www.micmiu.com/enterprise-app/snmp/snmp-jrobin-core-demo/
最近接触一个流量统计和网管的系统,对相关信息和技术做了一些了解和学习,在此记录,以供自己日后回顾,同时也方便给刚接触的TX们一些参考。
MRTG(Multi Router Traffic Grapher,MRTG),相信接触过网络管理的人,应该不会对它陌生的。MRTG是比较早的技术了,后来在此基础上发展了RRD技术,相比MRTG而言更加灵活方便。
JRobin(基于LGPL授权的开源技术)就是RRD的一个Java实现的版本。JRobin支持在RRD(Round Robin Database)上的所有标准操作:CREATE, UPDATE, FETCH, LAST, DUMP, XPORT和GRAPH。JRobin的API适合于那些熟悉RRDTool的概念与逻辑,但更喜欢使用纯Java实现的人。如果你提供相同的数据给RRDTool与JRobin,你将会得到相同的结果与图形。
ps:JRobin的官网:
http://oldwww.jrobin.org/
http://www.jrobin.org/index.php/Main_Page
先从Core API 开始了解学习如何定义RRD模板、如何创建RRD文件、如何获取RrdDb、如何将RRD文件和XML之间转换以及如何从RRD文件里读取数据等基础内容,下面是学习时写的一些测试代码:TestCoreRrd.java
1 | package com.snmp.jrobin; |
2 |
3 | import org.jrobin.core.DsDef; |
4 | import org.jrobin.core.DsTypes; |
5 | import org.jrobin.core.FetchData; |
6 | import org.jrobin.core.FetchRequest; |
7 | import org.jrobin.core.RrdDb; |
8 | import org.jrobin.core.RrdDef; |
9 | import org.jrobin.core.Sample; |
10 | import org.jrobin.core.Util; |
11 |
12 | /** |
13 | * JRobin Core学习 |
14 | * @author Michael sun |
15 | */ |
16 | public class TestCoreRrd { |
17 | /** |
18 | * @param args |
19 | */ |
20 | public static void main(String[] args) { |
21 | // 2010-10-01:1285862400L 2010-11-01:1288540800L |
22 | long startTime = Util.getTimestamp( 2010 , 10 - 1 , 1 ); |
23 | long endTime = Util.getTimestamp( 2010 , 11 - 1 , 1 ); |
24 |
25 | TestCoreRrd test = new TestCoreRrd(); |
26 | String rootPath = "d:/test/jrobin/" ; |
27 | String rrdName = "demo_flow.rrd" ; |
28 | // 测试创建RrdDef |
29 | RrdDef rrdDef = test.createRrdDef(rootPath, rrdName, startTime); |
30 | // 测试创建RRD文件 初始数据 |
31 | test.createRRDInitData(startTime, endTime, rootPath, rrdName, rrdDef); |
32 | // 测试获取RrdDb的方法 |
33 | test.getRrdDbMethod(rootPath); |
34 | // 测试FetchData获取RRD |
35 | test.fetchRrdData(rootPath, rrdName); |
36 | } |
37 |
38 | /** |
39 | * 创建RRDDef |
40 | */ |
41 | private RrdDef createRrdDef(String rootPath, String rrdName, long startTime) { |
42 | try { |
43 |
44 | String rrdPath = rootPath + rrdName; |
45 | RrdDef rrdDef = new RrdDef(rrdPath, startTime - 1 , 300 ); |
46 | // DsTypes: GAUGE COUNTER DERIVE ABSOLUTE |
47 | DsDef dsDef = new DsDef( "input" , DsTypes.DT_COUNTER, 600 , 0 , |
48 | Double.NaN); |
49 | rrdDef.addDatasource(dsDef); |
50 |
51 | rrdDef.addDatasource( "output" , DsTypes.DT_COUNTER, 600 , 0 , |
52 | Double.NaN); |
53 |
54 | rrdDef.addArchive( "AVERAGE" , 0.5 , 1 , 600 ); |
55 | rrdDef.addArchive( "AVERAGE" , 0.5 , 6 , 700 ); |
56 | rrdDef.addArchive( "AVERAGE" , 0.5 , 24 , 797 ); |
57 | rrdDef.addArchive( "AVERAGE" , 0.5 , 288 , 775 ); |
58 | rrdDef.addArchive( "MAX" , 0.5 , 1 , 600 ); |
59 | rrdDef.addArchive( "MAX" , 0.5 , 6 , 700 ); |
60 | rrdDef.addArchive( "MAX" , 0.5 , 24 , 797 ); |
61 | rrdDef.addArchive( "MAX" , 0.5 , 288 , 775 ); |
62 |
63 | // RRD file definition is completed |
64 |
65 | rrdDef.exportXmlTemplate(rootPath + rrdName + "_template.xml" ); |
66 | System.out.println( "[RrdDef Template export xml success]" ); |
67 |
68 | return rrdDef; |
69 | } catch (Exception e) { |
70 | e.printStackTrace(); |
71 | return null ; |
72 | } |
73 | } |
74 |
75 | /** |
76 | * 通过RrdDef创建RRD文件并初始化数据 |
77 | */ |
78 | private void createRRDInitData( long startTime, long endTime, |
79 | String rootPath, String rrdName, RrdDef rrdDef) { |
80 | try { |
81 |
82 | RrdDb rrdDb = new RrdDb(rrdDef); |
83 | // / by this point, rrd file can be found on your disk |
84 |
85 | // 模拟一些测试数据 |
86 | //Math.sin(2 * Math.PI * (t / 86400.0)) * baseval; |
87 | int baseval = 50 ; |
88 | for ( long t = startTime; t < endTime; t += 300 ) { |
89 | Sample sample = rrdDb.createSample(t); |
90 | double tmpval = Math.random() * baseval; |
91 | double tmpval2 = Math.random() * baseval; |
92 | sample.setValue( "input" , tmpval + 50 ); |
93 | sample.setValue( "output" , tmpval2 + 50 ); |
94 | sample.update(); |
95 | } |
96 | System.out.println( "[RrdDb init data success]" ); |
97 | System.out.println( "[Rrd path]:" + rrdDef.getPath()); |
98 |
99 | // rrdDb.dumpXml(rootPath + rrdName + "_rrd.xml") |
100 | rrdDb.exportXml(rootPath + rrdName + ".xml" ); |
101 |
102 | // If your RRD files are updated rarely, open them only when |
103 | // necessary and close them as soon as possible. |
104 | rrdDb.close(); |
105 |
106 | System.out.println( "[RrdDb export xml success]" ); |
107 | } catch (Exception e) { |
108 | e.printStackTrace(); |
109 |
110 | } |
111 | } |
112 |
113 | /** |
114 | * 除根据RrdDef以外获取RrdDb的其他方法 |
115 | */ |
116 | private void getRrdDbMethod(String rootPath) { |
117 | try { |
118 |
119 | // 根据RRD文件获取RrdDb |
120 | String rrdFullPath = rootPath + "demo_flow.rrd" ; |
121 | RrdDb rrdDb = new RrdDb(rrdFullPath); |
122 | System.out.println( "[info:]" + rrdDb.getInfo() + "[path:]" |
123 | + rrdDb.getPath()); |
124 | rrdDb.close(); |
125 |
126 | // 根据XML文件获取RrdDb |
127 | rrdDb = new RrdDb(rootPath + "copy.rrd" , rootPath |
128 | + "demo_flow_rrd.xml" ); |
129 | System.out.println( "[info:]" + rrdDb.getInfo() + "[path:]" |
130 | + rrdDb.getPath()); |
131 | rrdDb.close(); |
132 | } catch (Exception e) { |
133 | e.printStackTrace(); |
134 | } |
135 | } |
136 |
137 | /** |
138 | * |
139 | */ |
140 | private void fetchRrdData(String rootPath, String rrdName) { |
141 | try { |
142 | // open the file |
143 | RrdDb rrd = new RrdDb(rootPath + rrdName); |
144 |
145 | // create fetch request using the database reference |
146 | FetchRequest request = rrd.createFetchRequest( "AVERAGE" , Util |
147 | .getTimestamp( 2010 , 10 - 1 , 1 ), Util.getTimestamp( 2010 , |
148 | 10 - 1 , 2 )); |
149 |
150 | System.out.println( "[requet dump:]" + request.dump()); |
151 |
152 | // filter the datasources you really need |
153 | // String[] filterDataSource = { "input", "output" }; |
154 | // request.setFilter(filterDataSource); |
155 |
156 | // if you want only the "input" datasource use: |
157 | // request.setFilter("input"); |
158 |
159 | // execute the request |
160 | FetchData fetchData = request.fetchData(); |
161 | int columnCount = fetchData.getColumnCount(); |
162 | int rowCount = fetchData.getRowCount(); |
163 | long [] timestamps = fetchData.getTimestamps(); |
164 | System.out.println( "[data column count:]" + columnCount); |
165 | System.out.println( "[data row count:]" + rowCount); |
166 |
167 | // System.out.println("[fetch data dump:]" + fetchData.dump()); |
168 | // 循环获取数据 |
169 | double [][] values = fetchData.getValues(); |
170 | StringBuffer buffer = new StringBuffer( "" ); |
171 | for ( int row = 0 ; row < rowCount; row++) { |
172 | buffer.append(timestamps[row]); |
173 | buffer.append( ": " ); |
174 | for ( int dsIndex = 0 ; dsIndex < columnCount; dsIndex++) { |
175 | buffer.append(Util.formatDouble(values[dsIndex][row])); |
176 | buffer.append( " " ); |
177 | } |
178 | buffer.append( "\n" ); |
179 | } |
180 | System.out.println( "[fetch data display :]\n" + buffer); |
181 | } catch (Exception e) { |
182 | e.printStackTrace(); |
183 | } |
184 |
185 | } |
186 | } |
RRD定义的模板导出XML:
1 | < rrd_def > |
2 | < path >d:/test/jrobin/demo_flow.rrd</ path > |
3 | < step >300</ step > |
4 | < start >1285862399</ start > |
5 | < datasource > |
6 | < name >input</ name > |
7 | < type >COUNTER</ type > |
8 | < heartbeat >600</ heartbeat > |
9 | < min >+0.0000000000E00</ min > |
10 | < max >U</ max > |
11 | </ datasource > |
12 | < datasource > |
13 | < name >output</ name > |
14 | < type >COUNTER</ type > |
15 | < heartbeat >600</ heartbeat > |
16 | < min >+0.0000000000E00</ min > |
17 | < max >U</ max > |
18 | </ datasource > |
19 | < archive > |
20 | < cf >AVERAGE</ cf > |
21 | < xff >+5.0000000000E-01</ xff > |
22 | < steps >1</ steps > |
23 | < rows >600</ rows > |
24 | </ archive > |
25 | < archive > |
26 | < cf >AVERAGE</ cf > |
27 | < xff >+5.0000000000E-01</ xff > |
28 | < steps >6</ steps > |
29 | < rows >700</ rows > |
30 | </ archive > |
31 | < archive > |
32 | < cf >AVERAGE</ cf > |
33 | < xff >+5.0000000000E-01</ xff > |
34 | < steps >24</ steps > |
35 | < rows >797</ rows > |
36 | </ archive > |
37 | < archive > |
38 | < cf >AVERAGE</ cf > |
39 | < xff >+5.0000000000E-01</ xff > |
40 | < steps >288</ steps > |
41 | < rows >775</ rows > |
42 | </ archive > |
43 | < archive > |
44 | < cf >MAX</ cf > |
45 | < xff >+5.0000000000E-01</ xff > |
46 | < steps >1</ steps > |
47 | < rows >600</ rows > |
48 | </ archive > |
49 | < archive > |
50 | < cf >MAX</ cf > |
51 | < xff >+5.0000000000E-01</ xff > |
52 | < steps >6</ steps > |
53 | < rows >700</ rows > |
54 | </ archive > |
55 | < archive > |
56 | < cf >MAX</ cf > |
57 | < xff >+5.0000000000E-01</ xff > |
58 | < steps >24</ steps > |
59 | < rows >797</ rows > |
60 | </ archive > |
61 | < archive > |
62 | < cf >MAX</ cf > |
63 | < xff >+5.0000000000E-01</ xff > |
64 | < steps >288</ steps > |
65 | < rows >775</ rows > |
66 | </ archive > |
67 | </ rrd_def > |
RRD文件转换成XML文件的片段:
1 | < rrd > |
2 | <!-- JRobin, version 0.1 --> |
3 | < version >0001</ version > |
4 | <!-- Seconds --> |
5 | < step >300</ step > |
6 | <!-- Sun Oct 31 23:55:00 CST 2010 --> |
7 | < lastupdate >1288540500</ lastupdate > |
8 | < ds > |
9 | < name >input</ name > |
10 | < type >COUNTER</ type > |
11 | < minimal_heartbeat >600</ minimal_heartbeat > |
12 | < min >+0.0000000000E00</ min > |
13 | < max >NaN</ max > |
14 | <!-- PDP Status --> |
15 | < last_ds >+6.9973544356E01</ last_ds > |
16 | < value >+0.0000000000E00</ value > |
17 | < unknown_sec >0</ unknown_sec > |
18 | </ ds > |
19 | < ds > |
20 | < name >output</ name > |
21 | < type >COUNTER</ type > |
22 | < minimal_heartbeat >600</ minimal_heartbeat > |
23 | < min >+0.0000000000E00</ min > |
24 | < max >NaN</ max > |
25 | <!-- PDP Status --> |
26 | < last_ds >+9.4423065918E01</ last_ds > |
27 | < value >+0.0000000000E00</ value > |
28 | < unknown_sec >0</ unknown_sec > |
29 | </ ds > |
30 | < rra > |
31 | < cf >AVERAGE</ cf > |
32 | <!-- 300 seconds --> |
33 | < pdp_per_row >1</ pdp_per_row > |
34 | < xff >+5.0000000000E-01</ xff > |
35 | < cdp_prep > |
36 | < ds > |
37 | < value >NaN</ value > |
38 | < unknown_datapoints >0</ unknown_datapoints > |
39 | </ ds > |
40 | < ds > |
41 | < value >NaN</ value > |
42 | < unknown_datapoints >0</ unknown_datapoints > |
43 | </ ds > |
44 | </ cdp_prep > |
45 | < database > |
46 | <!-- Fri Oct 29 22:00:00 CST 2010 / 1288360800 --> |
47 | < row > |
48 | < v >+1.4316557626E07</ v > |
49 | < v >+1.2619069495E-01</ v > |
50 | </ row > |
51 | <!-- Fri Oct 29 22:05:00 CST 2010 / 1288361100 --> |
52 | < row > |
53 | < v >+1.4063324411E-02</ v > |
54 | < v >+1.4316557534E07</ v > |
55 | </ row > |
56 | <!-- 省略部分信息--> |
57 | ........................... |
58 | </ database > |
59 | </ rra > |
60 | <!-- 省略部分信息--> |
61 | ............................... |
62 | </ rrd > |