gri 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/MIT-LICENSE.txt +20 -0
  4. data/README.md +132 -0
  5. data/Rakefile +5 -0
  6. data/bin/grapher +17 -0
  7. data/bin/gri +5 -0
  8. data/bin/gricast +17 -0
  9. data/bin/grispark +5 -0
  10. data/bin/griwalk +9 -0
  11. data/bin/trad +19 -0
  12. data/bin/trad-http +17 -0
  13. data/gri.gemspec +21 -0
  14. data/lib/fluent/plugin/out_gri.rb +56 -0
  15. data/lib/gri/api.rb +28 -0
  16. data/lib/gri/app_collector.rb +154 -0
  17. data/lib/gri/app_walker.rb +23 -0
  18. data/lib/gri/blank.rb +49 -0
  19. data/lib/gri/builtindefs.rb +211 -0
  20. data/lib/gri/cast.rb +84 -0
  21. data/lib/gri/cgraph.rb +37 -0
  22. data/lib/gri/clist.rb +163 -0
  23. data/lib/gri/collector.rb +284 -0
  24. data/lib/gri/config.rb +134 -0
  25. data/lib/gri/ds_list.rb +166 -0
  26. data/lib/gri/format_helper.rb +112 -0
  27. data/lib/gri/gparams.rb +43 -0
  28. data/lib/gri/graph.rb +239 -0
  29. data/lib/gri/grapher.rb +70 -0
  30. data/lib/gri/ldb.rb +160 -0
  31. data/lib/gri/list.rb +242 -0
  32. data/lib/gri/log.rb +140 -0
  33. data/lib/gri/loop.rb +109 -0
  34. data/lib/gri/ltsv.rb +58 -0
  35. data/lib/gri/main.rb +107 -0
  36. data/lib/gri/mlog.rb +22 -0
  37. data/lib/gri/mmsgpack.rb +57 -0
  38. data/lib/gri/msnmp.rb +601 -0
  39. data/lib/gri/page.rb +235 -0
  40. data/lib/gri/pcollector.rb +209 -0
  41. data/lib/gri/plugin.rb +75 -0
  42. data/lib/gri/plugin/bootstrap.rb +65 -0
  43. data/lib/gri/plugin/cisco.rb +98 -0
  44. data/lib/gri/plugin/exec_collector.rb +89 -0
  45. data/lib/gri/plugin/juniper.rb +5 -0
  46. data/lib/gri/plugin/netsnmp.rb +8 -0
  47. data/lib/gri/plugin/ucdavis.rb +176 -0
  48. data/lib/gri/plugin/writer_fluentd.rb +26 -0
  49. data/lib/gri/polling_unit.rb +88 -0
  50. data/lib/gri/q.rb +5 -0
  51. data/lib/gri/request.rb +29 -0
  52. data/lib/gri/rrd.rb +438 -0
  53. data/lib/gri/scheduler.rb +68 -0
  54. data/lib/gri/sgraph.rb +147 -0
  55. data/lib/gri/spark.rb +94 -0
  56. data/lib/gri/tra_collector.rb +80 -0
  57. data/lib/gri/trad.rb +170 -0
  58. data/lib/gri/updater.rb +201 -0
  59. data/lib/gri/util_daemon.rb +19 -0
  60. data/lib/gri/util_marshal.rb +13 -0
  61. data/lib/gri/utils.rb +63 -0
  62. data/lib/gri/vendor.rb +76 -0
  63. data/lib/gri/version.rb +3 -0
  64. data/lib/gri/wmain.rb +67 -0
  65. data/lib/gri/writer.rb +184 -0
  66. data/mcollector +47 -0
  67. data/test/mock.rb +60 -0
  68. data/test/root/gra/.sysdb/sysdb.txt +3 -0
  69. data/test/root/gra/testhost/.records.txt +2 -0
  70. data/test/root/if.def +2 -0
  71. data/test/root/test.conf +4 -0
  72. data/test/root/testtab +9 -0
  73. data/test/root/testtab2 +2 -0
  74. data/test/root/tra/testhost/_/20130614 +20 -0
  75. data/test/test_app.rb +58 -0
  76. data/test/test_builtindefs.rb +24 -0
  77. data/test/test_collector.rb +58 -0
  78. data/test/test_config.rb +62 -0
  79. data/test/test_ds_list.rb +48 -0
  80. data/test/test_exec_collector.rb +33 -0
  81. data/test/test_format_helper.rb +68 -0
  82. data/test/test_graph.rb +69 -0
  83. data/test/test_ldb.rb +29 -0
  84. data/test/test_list.rb +65 -0
  85. data/test/test_log.rb +16 -0
  86. data/test/test_loop.rb +35 -0
  87. data/test/test_ltsv.rb +38 -0
  88. data/test/test_main.rb +19 -0
  89. data/test/test_mmsgpack.rb +27 -0
  90. data/test/test_msnmp.rb +147 -0
  91. data/test/test_page.rb +51 -0
  92. data/test/test_pcollector.rb +71 -0
  93. data/test/test_plugin.rb +62 -0
  94. data/test/test_plugin_cisco.rb +23 -0
  95. data/test/test_polling_unit.rb +58 -0
  96. data/test/test_request.rb +26 -0
  97. data/test/test_rrd.rb +53 -0
  98. data/test/test_rrd_updater.rb +139 -0
  99. data/test/test_scheduler.rb +31 -0
  100. data/test/test_tra_collector.rb +40 -0
  101. data/test/test_trad.rb +33 -0
  102. data/test/test_util_marshal.rb +17 -0
  103. data/test/test_utils.rb +15 -0
  104. data/test/test_vendor.rb +40 -0
  105. data/test/test_writer.rb +33 -0
  106. data/test/unittest_helper.rb +27 -0
  107. metadata +208 -0
@@ -0,0 +1,23 @@
1
+ module GRI
2
+ class AppWalker
3
+ attr_reader :config, :writers, :metrics
4
+
5
+ def initialize config
6
+ @config = config
7
+ @writers = []
8
+ @metrics = Hash.new 0
9
+ end
10
+
11
+ def run
12
+ if ARGV.size == 2
13
+ host, sym_oid = ARGV
14
+ snmp = SNMP.new host
15
+ snmp.version = @config['version'] || '1'
16
+ snmp.community = @config['community'] || 'public'
17
+ snmp.walk(sym_oid) {|oid, tag, val|
18
+ p [oid, tag, val]
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/gri/blank.rb ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ class Object
4
+ def blank?
5
+ respond_to?(:empty?) ? empty? : !self
6
+ end
7
+
8
+ def present?
9
+ !blank?
10
+ end
11
+ end
12
+
13
+ class NilClass
14
+ def blank?
15
+ true
16
+ end
17
+ end
18
+
19
+ class FalseClass
20
+ def blank?
21
+ true
22
+ end
23
+ end
24
+
25
+ class TrueClass
26
+ def blank?
27
+ false
28
+ end
29
+ end
30
+
31
+ class Array
32
+ alias_method :blank?, :empty?
33
+ end
34
+
35
+ class Hash
36
+ alias_method :blank?, :empty?
37
+ end
38
+
39
+ class String
40
+ def blank?
41
+ self !~ /[^[:space:]]/
42
+ end
43
+ end
44
+
45
+ class Numeric #:nodoc:
46
+ def blank?
47
+ false
48
+ end
49
+ end
@@ -0,0 +1,211 @@
1
+ module GRI
2
+ DEFS = {
3
+ 'num'=>{
4
+ :ds=>['num,num,GAUGE,,,,:index'],
5
+ :rra=>['RRA:AVERAGE:0.5:15:10000',
6
+ 'RRA:MAX:0.5:1:50000', 'RRA:MAX:0.5:15:10000', 'RRA:MAX:0.5:180:10000'],
7
+ :prop=>{:name=>'_index', :description=>'description', :lastvalue=>'num'},
8
+ :list=>['Num', '%N,%L\r'],
9
+ :graph=>[['', 0]],
10
+ :composite=>['', 's', 'v', 't'],
11
+ },
12
+ 'grimetrics'=>{:ds=>['number,number,GAUGE'],
13
+ :prop=>{:name=>'_index'},
14
+ :list_text=>['grimetrics', '%N,%L\r'],
15
+ :composite=>['s'],
16
+ :graph=>[['n', 0]],
17
+ },
18
+
19
+ 'interfaces'=>{:cat=>'',
20
+ :oid=>['ifDescr', 'ifSpeed', 'ifAdminStatus', 'ifOperStatus', 'ifType',
21
+ 'ifInOctets', 'ifOutOctets',
22
+ 'ifInDiscards', 'ifOutDiscards',
23
+ 'ifInErrors', 'ifOutErrors',
24
+ 'ifInUcastPkts', 'ifOutUcastPkts',
25
+ 'ifInNUcastPkts', 'ifOutNUcastPkts',],
26
+ :index_key => 'ifDescr',
27
+ :exclude? => proc {|record|
28
+ record['ifOperStatus'].to_i != 1 or
29
+ record['ifSpeed'].to_i == 0 or
30
+ (Integer(record['ifInOctets']) == 0 and
31
+ Integer(record['ifOutOctets']) == 0) or
32
+ /(^(Loopback|Null|Async|lo)\d+)|cef layer|atm subif/ === record['ifDescr']
33
+ },
34
+ :hidden? => proc {|record|
35
+ /cef layer|atm subif|unrouted.VLAN/ === record['ifDescr']
36
+ },
37
+ :tdb=>['', 'ifDescr', 'ifAlias', 'ifSpeed',
38
+ 'ifInOctets', 'ifOutOctets', 'ifInDiscards', 'ifOutDiscards',
39
+ 'ifInErrors', 'ifOutErrors', 'ifHCInOctets', 'ifHCOutOctets',],
40
+ :ds=>['ifInOctets,inoctet,DERIVE,MAX,AREA,#90f090,in,8',
41
+ 'ifOutOctets,outoctet,DERIVE,MAX,LINE1,#0000ff,out,8',
42
+ 'ifInDiscards,indiscard,DERIVE,MAX,LINE1,#00ff0f',
43
+ 'ifOutDiscards,outdiscard,DERIVE,MAX,LINE1,#00afff',
44
+ 'ifInErrors,inerror,DERIVE,MAX,LINE1,#ff0f0f',
45
+ 'ifOutErrors,outerror,DERIVE,MAX,LINE1,#ffaf00',
46
+ 'ifInUcastPkts,inucast,DERIVE,MAX,LINE1,#90f090',
47
+ 'ifOutUcastPkts,outucast,DERIVE,MAX,LINE1,#0000ef',
48
+ 'ifInNUcastPkts,innucast,DERIVE,MAX,LINE1,#ff0f0f',
49
+ 'ifOutNUcastPkts,outnucast,DERIVE,MAX,LINE1,#ffaf00'],
50
+ :prop=>{:name=>'ifDescr', :description=>'ifAlias',
51
+ :ostatus=>'ifOperStatus', :astatus=>'ifAdminStatus',
52
+ :ipaddr=>'ipaddr', :ub=>'ifSpeed',},
53
+ :list=>['Status,Interface,Description,IP Address', '%S,%N,%D,%I'],
54
+ :graph=>[['bps', 1000, [0, nil], /Octets/],
55
+ ['pps', 1000, [0, nil], /N?UcastPkts/],
56
+ ['packets/5min', 1000, [0, nil], /Error|Discard/]], #/
57
+ :composite=>['s', 'v', 't'],
58
+ },
59
+ 'ifMIB'=>{:cat=>'',
60
+ :oid=>['ifHCInOctets', 'ifHCOutOctets', 'ifHighSpeed', 'ifAlias'],
61
+ :fix_workhash=>proc {|wh|
62
+ for k, r in wh['']
63
+ r['ifInOctets'] = r['ifHCInOctets'] if r['ifHCInOctets']
64
+ r['ifOutOctets'] = r['ifHCOutOctets'] if r['ifHCOutOctets']
65
+ if r['ifHighSpeed'] and r['ifHighSpeed'].to_i > 4000
66
+ r['ifSpeed'] = r['ifHighSpeed'].to_i * 1_000_000
67
+ end
68
+ end
69
+ },
70
+ },
71
+ 'ipaddr'=>{
72
+ :oid=>['ipAdEntIfIndex', 'ipAdEntNetMask'],
73
+ :feed => lambda {|h, enoid, tag, val|
74
+ ind = BER.dec_oid(enoid[9..-1]).join('.')
75
+ h[ind] ||= {}
76
+ if tag == 2
77
+ h[ind]['ifIndex'] = val
78
+ elsif tag == 0x40 # IPv4 Addr
79
+ h[ind]['mask'] = val
80
+ end
81
+ },
82
+ :fix_workhash => lambda {|wh|
83
+ ifrecord = wh[''] || {}
84
+ for k, record in wh[:ipaddr]
85
+ a = k + '/' + record['mask']
86
+ ind = record['ifIndex']
87
+ if (r = ifrecord[ind])
88
+ if r['ipaddr']
89
+ r['ipaddr'] += ',' + a
90
+ else
91
+ r['ipaddr'] = a
92
+ end
93
+ end
94
+ end
95
+ wh.delete :ipaddr
96
+ },
97
+ },
98
+ 'tcp'=>{
99
+ :oid=>['tcpCurrEstab', 'tcpActiveOpens',
100
+ 'tcpPassiveOpens', 'tcpAttemptFails', 'tcpEstabResets',
101
+ 'tcpInSegs', 'tcpOutSegs', 'tcpRetransSegs',
102
+ 'tcpInErrs', 'tcpOutRsts',],
103
+ :tdb=>['tcp', 'tcpCurrEstab', 'tcpActiveOpens',
104
+ 'tcpPassiveOpens', 'tcpAttemptFails', 'tcpEstabResets',
105
+ 'tcpInSegs', 'tcpOutSegs', 'tcpRetransSegs',
106
+ 'tcpInErrs', 'tcpOutRsts',],
107
+ :ds=>[
108
+ 'tcpCurrEstab,tcpCurrEstab,GAUGE,MAX,AREA,#90f090',
109
+ 'tcpActiveOpens,tcpActiveOpens,DERIVE,MAX,LINE1,#0000ff',
110
+ 'tcpPassiveOpens,tcpPassiveOpens,DERIVE,MAX,LINE1,#c000ff',
111
+ 'tcpAttemptFails,tcpAttemptFails,DERIVE,MAX,LINE1,#ff0000',
112
+ 'tcpEstabResets,tcpEstabResets,DERIVE,MAX,LINE1,#ff9030',
113
+
114
+ 'tcpInSegs,tcpInSegs,DERIVE,MAX,AREA,#99ff99',
115
+ 'tcpOutSegs,tcpOutSegs,DERIVE,MAX,LINE1,#0000ff',
116
+ 'tcpRetransSegs,tcpRetransSegs,DERIVE,MAX,LINE1,#00ffff',
117
+ 'tcpInErrs,tcpInErrs,DERIVE,MAX,LINE1,#ff0000',
118
+ 'tcpOutRsts,tcpOutRsts,DERIVE,MAX,LINE1,#ff9030',
119
+ ],
120
+ :prop=>{:name=>'tcp'},
121
+ :list=>['TCP'],
122
+ :graph=>[
123
+ ['connection', 0, [0, nil],
124
+ /tcp(CurrEstab|ActiveOpens|PassiveOpens|AttemptFails|EstabResets)/],
125
+ ['packet/sec', 0, [0, nil],
126
+ /tcp(InSegs|OutSegs|RetransSegs|InErrs|OutRsts)/]
127
+ ],
128
+ },
129
+ 'udp'=>{
130
+ :oid=>['udpInDatagrams', 'udpOutDatagrams',
131
+ 'udpNoPorts', 'udpInErrors'],
132
+ :tdb=>['udp', 'udpInDatagrams', 'udpOutDatagrams',
133
+ 'udpNoPorts', 'udpInErrors'],
134
+ :ds=>[
135
+ 'udpInDatagrams,udpInDatagrams,DERIVE,MAX,AREA,#90f090',
136
+ 'udpOutDatagrams,udpOutDatagrams,DERIVE,MAX,LINE1,#0000ef',
137
+ 'udpNoPorts,udpNoPorts,DERIVE,MAX,LINE1,#00afff',
138
+ 'udpInErrors,udpInErrors,DERIVE,MAX,LINE1,#ff0f0f',
139
+ ],
140
+ :prop=>{:name=>'udp'},
141
+ :list=>['UDP'], :graph=>[['"datagram/sec"', 0, [0, nil]]],
142
+ },
143
+
144
+ 'entityu'=>{:oid=>['entPhysicalDescr', 'entPhysicalName'],},
145
+
146
+ 'hrSystemNumUsers'=>{
147
+ :oid=>['hrSystemNumUsers'],
148
+ :tdb=>['hrsystemnumusers', 'hrSystemNumUsers'],
149
+ :ds=>['hrSystemNumUsers,users,GAUGE,MAX,LINE1,#ff4020,users'],
150
+ :prop=>{:name=>'users', :lastvalue=>'hrSystemNumUsers'},
151
+ :graph=>[['"users"', 0]],
152
+ :list=>['Users', '%N, %L\r'],
153
+ },
154
+
155
+ 'hrStorage'=>{
156
+ :oid=>['hrStorageEntry'],
157
+ :tdb=>['hrStorage', 'hrStorageDescr', 'hrStorageSize', 'hrStorageUsed'],
158
+ :fix_workhash=>lambda {|wh|
159
+ if (h = wh[:hrStorage])
160
+ h.reject! {|k, v|
161
+ v['hrStorageType'] != "+\x06\x01\x02\x01\x19\x02\x01\x04"}
162
+ h.each {|k, v|
163
+ u = v['hrStorageAllocationUnits'].to_i
164
+ v.delete 'hrStorageType'
165
+ v['hrStorageSize'] = v['hrStorageSize'].to_i * u
166
+ v['hrStorageUsed'] = v['hrStorageUsed'].to_i * u
167
+ }
168
+ end
169
+ },
170
+ :ds=>['hrStorageUsed,used,GAUGE,MAX,AREA,#40ff40'],
171
+ :prop=>{:name=>'hrStorageDescr',
172
+ :lastvalue=>'hrStorageUsed', :ub=>'hrStorageSize'},
173
+ :list=>['Storage Used', '%N, %1024L / %1024U\r'],
174
+ :graph=>[['storage used', 1024]],
175
+ :composite=>['s', 'v', 't'],
176
+ },
177
+
178
+ :term => {
179
+ :default=>[['Daily', 30*3600], ['Weekly', 8*24*3600],
180
+ ['Monthly', 31*24*3600], ['Yearly', 365*24*3600]],
181
+ :short=>[['Last 3 hours', 3*3600], ['Daily', 30*3600],
182
+ ['Weekly', 8*24*3600], ['Monthly', 31*24*3600]],
183
+ :long=>[['Weekly', 8*24*3600], ['Monthly', 31*24*3600],
184
+ ['Yearly', 365*24*3600], ['Last 6 years', 6*365*24*3600]],
185
+ :verylong=>[['Monthly', 31*24*3600], ['Yearly', 365*24*3600],
186
+ ['Last 8 years', 8*365*24*3600]],
187
+ }
188
+ }
189
+
190
+ class <<DEFS
191
+ alias :update :merge!
192
+ def get_specs key
193
+ unless @specs
194
+ @specs = {}
195
+ for k, dhash in self
196
+ next unless String === k
197
+ data_name = dhash[:data_name] || dhash[:cat] ||
198
+ (dhash[:tdb] and dhash[:tdb].first) ||
199
+ k.gsub(/-/, '')
200
+ spec = (@specs[data_name.to_s] ||= {})
201
+ [:list, :index_key, :named_index, :tdb, :ds, :rra, :prop,
202
+ :graph, :composite, :exclude?, :hidden?].each {|symkey|
203
+ spec[symkey] = dhash[symkey] if dhash[symkey]
204
+ }
205
+ spec[:list] ||= dhash[:list_text] #XXX
206
+ end
207
+ end
208
+ @specs[key.to_s]
209
+ end
210
+ end
211
+ end
data/lib/gri/cast.rb ADDED
@@ -0,0 +1,84 @@
1
+ require 'gri/config'
2
+ require 'gri/log'
3
+ require 'gri/wmain'
4
+ require 'gri/api'
5
+ require 'gri/list'
6
+ require 'gri/page'
7
+ require 'gri/cgraph'
8
+ require 'gri/clist'
9
+
10
+ module GRI
11
+ class Cast
12
+ def self.parse_path_info env
13
+ if (path_info = env['PATH_INFO']) =~ %r{^/(?:list|graph)\b}
14
+ path_info = Regexp.last_match.post_match
15
+ end
16
+ if path_info
17
+ dummy, service_name, section_name, graph_name = path_info.split /\// #/
18
+ end
19
+ return service_name, section_name, graph_name
20
+ end
21
+
22
+ def initialize
23
+ root_dir = Config['root-dir'] ||= Config::ROOT_PATH
24
+ log_dir = Config['log-dir'] || Config['root-dir'] + '/log'
25
+ Log.init "#{log_dir}/#{File.basename $0}.log"
26
+ rescue SystemCallError
27
+ Log.init '/tmp/gricast.log'
28
+ end
29
+
30
+ def call env
31
+ req = GRI::Request.new env
32
+ params = req.params
33
+ cast_dir = Config['cast-dir'] || (Config::ROOT_PATH + '/cast')
34
+ if params['grp']
35
+ cast_dir = cast_dir + '/' + params['grp']
36
+ end
37
+
38
+ if (req.query_string =~ /\A(\d+),(\d+)\z/)
39
+ app = Page.new :dirs=>[cast_dir], :clicked=>true, :imgx=>$1, :imgy=>$2
40
+ elsif params['r'] or params['tag']
41
+ if params['stime']
42
+ app = Graph.new :dirs=>[cast_dir]
43
+ else
44
+ app = Page.new :dirs=>[cast_dir]
45
+ end
46
+ elsif params['search'].to_i == 1
47
+ app = List.new :dirs=>[cast_dir]
48
+ elsif
49
+ case env['PATH_INFO']
50
+ when %r{^/api/}
51
+ app = API.new
52
+ when %r{^/graph/}
53
+ app = Cgraph.new :dir=>cast_dir
54
+ when %r{^/page}
55
+ app = Page.new :dirs=>[cast_dir]
56
+ else
57
+ app = Clist.new :dir=>cast_dir
58
+ end
59
+ end
60
+ app.call env
61
+ end
62
+
63
+ def public_dir
64
+ File.dirname(__FILE__) + '/../../public'
65
+ end
66
+
67
+ def self.layout
68
+ <<EOS
69
+ <html>
70
+ <head>
71
+ <title><%= @title %></title>
72
+ <style>
73
+ td.text-right {text-align:right;}
74
+ hr {border:none;border-top:1px #cccccc solid;}
75
+ </style>
76
+ </head>
77
+ <body>
78
+ <%= yield %>
79
+ </body>
80
+ </html>
81
+ EOS
82
+ end
83
+ end
84
+ end
data/lib/gri/cgraph.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'gri/rrd'
2
+ require 'gri/graph'
3
+
4
+ module GRI
5
+ class Cgraph
6
+ TERMS = {'sh'=>['Hour', 3600], 's8h'=>['8Hours', 8*3600],
7
+ 'd'=>['Day', 24*3600], 'w'=>['Week', 7*24*3600],
8
+ 'm'=>['Month', 31*24*3600], 'y'=>['Year', 366*24*3600]}
9
+
10
+ def initialize options={}
11
+ @options = options
12
+ end
13
+
14
+ def call env
15
+ req = Rack::Request.new env
16
+ service_name, section_name, graph_name = Cast.parse_path_info env
17
+
18
+ begin
19
+ cast_dir = @options[:dir]
20
+ gra_dir = "#{cast_dir}/#{service_name}"
21
+
22
+ params = GParams.new
23
+ params['r'] = "#{section_name}_num_#{graph_name}"
24
+ params['z'] = 'gf'
25
+ t = req.params['t'] || 'd'
26
+ params['title'] = TERMS[t].first
27
+ gr = Graph.new :dirs=>[gra_dir]
28
+ etime = Time.now.to_i
29
+ stime = etime - TERMS[t][1]
30
+ img = gr.graph stime, etime, params
31
+ [200, {'Content-type' => 'image/png'}, [img]]
32
+ rescue
33
+ [500, {}, []]
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/gri/clist.rb ADDED
@@ -0,0 +1,163 @@
1
+ require 'gri/format_helper'
2
+ require 'gri/util_marshal'
3
+
4
+ module GRI
5
+ class Clist
6
+ TERMS = {'sh'=>[['sh', 's8h'], 'hour/8hours', 0],
7
+ 'd'=>[['d', 'w'], 'day/week', 3],
8
+ 'm'=>[['m', 'y'], 'month/year', 4]}
9
+
10
+ include FormatHelper
11
+
12
+ def initialize options={}
13
+ @options = options
14
+ end
15
+
16
+ def call env
17
+ req = Rack::Request.new env
18
+ if (path_info = env['PATH_INFO']) =~ %r{^/list}
19
+ path_info = Regexp.last_match.post_match
20
+ end
21
+ if path_info
22
+ dummy, service_name, section_name, graph_name = path_info.split /\// #/
23
+ end
24
+
25
+ list_item = path_info
26
+ dir = @options[:dir] || Config['cast-dir'] ||
27
+ (Config::ROOT_PATH + '/cast')
28
+
29
+ pt = req.params['t'] || 'd'
30
+ t = TERMS[pt] || TERMS['d']
31
+ dirs = scan_dir dir, service_name, section_name, graph_name
32
+ @title = 'list'
33
+ body = render(Cast.layout) {render template, binding}
34
+ [200, {'Content-type' => 'text/html'}, body]
35
+ end
36
+
37
+ def scan_dir dir, service_name, section_name, graph_name
38
+ h = {}
39
+ for f0 in Dir.glob(dir + '/' + (service_name || '*'))
40
+ b0 = File.basename f0
41
+ if File.directory? f0
42
+ h[b0] = {}
43
+ for f1 in Dir.glob(f0 + '/' + (section_name || '*'))
44
+ b1 = File.basename f1
45
+ if File.directory? f1
46
+ h[b0][b1] = {}
47
+ pat = graph_name ? "#{section_name}_num_#{graph_name}.rrd" : '*'
48
+ for f2 in Dir.glob(f1 + '/' + pat)
49
+ b2 = File.basename f2
50
+ if b2 =~ /^(?:[^_]+)_(?:[^_]+)_(.+).rrd/
51
+ h[b0][b1][$1] = true
52
+ end
53
+ end
54
+ end
55
+ end
56
+ else
57
+ h[b0] = true
58
+ end
59
+ end
60
+ h
61
+ end
62
+
63
+ def sysdb_path dir
64
+ sysdb_path = dir + '/.sysdb/sysdb.dump'
65
+ end
66
+
67
+ def load_sysdb dir
68
+ sysdb = Marshal.load_from_file sysdb_path(dir) || {}
69
+ end
70
+
71
+ def mk_graph_tag service_name, section_name, graph_name, t, ind
72
+ cs = (Time.now - Cgraph::TERMS[t[0][ind]][1]).strftime('%Y-%m-%d %H:%M:%S')
73
+ u = "?grp=#{service_name}&r=#{section_name}_num_#{graph_name}&pt=s"
74
+ gu = "graph/#{service_name}/#{section_name}/#{graph_name}"
75
+ img = "<img src=\"#{url_to gu + '?t=' + t[0][ind]}\"/>"
76
+ "<a href=\"#{u}&cs=#{Rack::Utils.escape cs}\">#{img}</a>"
77
+ end
78
+
79
+ CMNAME = {'s'=>'stack', 'v'=>'overlay', ''=>'sum', 't'=>'tile'}
80
+ def mk_comp_links comps, host, ckeys, aparam
81
+ links = []
82
+ for cm in comps
83
+ href_fp = url_to "?p=#{cm}&#{aparam}"
84
+ href = href_fp + ckeys.map {|k| "r=#{host}_#{k}"}.join('&')
85
+ links.push mk_tag('a', {:href=>href}, CMNAME[cm])
86
+ end
87
+ links
88
+ end
89
+
90
+ def template
91
+ <<'EOS'
92
+ <% if section_name -%>
93
+
94
+ <% d0 = dirs.keys.first -%>
95
+
96
+ <% if (ckeys = dirs[d0][section_name].keys.map {|k| "num_#{k}"}).size > 1 -%>
97
+ <div style="float: right!important;" class="pull-right"><ul class="pagination">
98
+ <% for u in mk_comp_links(DEFS['num'][:composite], section_name, ckeys, "grp=#{d0}&") -%>
99
+ <li><%= u %></li>
100
+ <% end -%>
101
+ </ul></div>
102
+ <% end -%>
103
+
104
+ <div style="float: right!important;" class="pull-right"><ul class="pagination">
105
+ <% for k, v in TERMS.sort_by {|kk, vv| vv[2]} -%>
106
+ <li style="display: inline"<%= (pt == k) ? " class=active" : '' %>>
107
+ <a href="<%= url_to "list/#{d0}/#{section_name}?t=#{k}" %>"><%= v[1] %></a>
108
+ </li>
109
+ <% end -%>
110
+ </ul></div>
111
+
112
+
113
+ <section>
114
+ <h1>
115
+ <a href="<%= url_to ''%>">Home</a> &raquo;
116
+ <a href="<%= url_to "list/#{d0}"%>"><%= d0 %></a> &raquo;
117
+ <% if graph_name -%>
118
+ <a href="<%= url_to "list/#{d0}/#{section_name}"%>"><%= section_name%></a> &raquo;
119
+ <%= graph_name %>
120
+ <% else -%>
121
+ <%= section_name%>
122
+ <% end -%>
123
+ </h1>
124
+
125
+ <% for graph_name in dirs[d0][section_name].keys.sort -%>
126
+ <h2>
127
+ <a href="<%= url_to "list/#{d0}/#{section_name}/#{graph_name}"%>"><%= graph_name %></a>
128
+ </h2>
129
+ <%= mk_graph_tag service_name, section_name, graph_name, t, 0 %>
130
+ <%= mk_graph_tag service_name, section_name, graph_name, t, 1 %>
131
+ <% end %>
132
+ </section>
133
+
134
+ <% else -%><!-- if section_name -->
135
+
136
+ <section>
137
+ <h1>
138
+ <a href="<%= url_to ''%>">Home</a>
139
+ <% if service_name -%>
140
+ &raquo; <%= service_name %>
141
+ <% end -%>
142
+ </h1>
143
+
144
+ <% for d0 in dirs.keys.sort %>
145
+ <h2><a href="<%= url_to('list') + '/' + d0 %>"><%=h d0 %>
146
+ </a></h2>
147
+ <!--a href="<%= url_to "?search=1&grp=#{d0}" %>">search</a-->
148
+ <table class="table table-striped">
149
+ <% for d1 in dirs[d0].keys.sort -%>
150
+ <tr>
151
+ <td><a href="<%= url_to('list')+'/'+d0+'/'+d1 %>"><%= d1 %></a></td>
152
+ </tr>
153
+ <% end -%>
154
+ </table>
155
+ </section>
156
+ <% end %>
157
+
158
+ <% end -%><!-- if section_name -->
159
+ <hr/>
160
+ EOS
161
+ end
162
+ end
163
+ end