Class: RRD

Inherits:
Object show all
Defined in:
lib/gri/rrd.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(address = nil, base_dir = nil) ⇒ RRD

Returns a new instance of RRD.



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/gri/rrd.rb', line 93

def initialize address=nil, base_dir=nil
  @address = address
  @base_dir = base_dir

  @imgformat = 'PNG'
  @update_buf = []
  @x_grid_hash = {}
  @show_graph_date = false
  @fonts = []
  RRDm.start unless RRDm.running?
  @version = (RRDm.version =~ /\A(1\.\d)\./) ? $1 : '1.0'
end

Instance Attribute Details

#created_pObject (readonly)

Returns the value of attribute created_p.



88
89
90
# File 'lib/gri/rrd.rb', line 88

def created_p
  @created_p
end

#ds_aryObject (readonly)

Returns the value of attribute ds_ary.



89
90
91
# File 'lib/gri/rrd.rb', line 89

def ds_ary
  @ds_ary
end

#fontsObject

Returns the value of attribute fonts.



87
88
89
# File 'lib/gri/rrd.rb', line 87

def fonts
  @fonts
end

#heightObject

Returns the value of attribute height.



82
83
84
# File 'lib/gri/rrd.rb', line 82

def height
  @height
end

#imgformatObject

Returns the value of attribute imgformat.



84
85
86
# File 'lib/gri/rrd.rb', line 84

def imgformat
  @imgformat
end

#lower_limitObject

Returns the value of attribute lower_limit.



85
86
87
# File 'lib/gri/rrd.rb', line 85

def lower_limit
  @lower_limit
end

#show_graph_date=(value) ⇒ Object (writeonly)

Sets the attribute show_graph_date

Parameters:

  • value

    the value to set the attribute show_graph_date to.



91
92
93
# File 'lib/gri/rrd.rb', line 91

def show_graph_date=(value)
  @show_graph_date = value
end

#titleObject

Returns the value of attribute title.



83
84
85
# File 'lib/gri/rrd.rb', line 83

def title
  @title
end

#versionObject (readonly)

Returns the value of attribute version.



90
91
92
# File 'lib/gri/rrd.rb', line 90

def version
  @version
end

#vertical_labelObject

Returns the value of attribute vertical_label.



83
84
85
# File 'lib/gri/rrd.rb', line 83

def vertical_label
  @vertical_label
end

#widthObject

Returns the value of attribute width.



82
83
84
# File 'lib/gri/rrd.rb', line 82

def width
  @width
end

#x_grid_hashObject

Returns the value of attribute x_grid_hash.



86
87
88
# File 'lib/gri/rrd.rb', line 86

def x_grid_hash
  @x_grid_hash
end

Class Method Details

.defstr(rrdpaths, ds, cf, cname, line, color, legend, mag = 1, lower_bound = nil, upper_bound = nil) ⇒ Object



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# File 'lib/gri/rrd.rb', line 391

def self.defstr rrdpaths, ds, cf, cname, line, color, legend,
    mag=1, lower_bound=nil, upper_bound=nil
  expr = []
  st = {}
  n = 0

  limitstr = if lower_bound and upper_bound and (lower_bound != upper_bound)
 ",#{lower_bound},#{upper_bound},LIMIT"
             elsif lower_bound
               ",DUP,#{lower_bound},GE,EXC,UNKN,IF"
      else
 ''
      end
  if rrdpaths.size > 1
    vnames = []
    for rrdpath in rrdpaths
	basename = File.basename rrdpath, '.rrd'
	vname = "v#{st[basename] ||= (n+=1)}#{ds}"
	vnames.push vname
      expr.push "DEF:#{vname}=#{rrdpath}:#{ds}:#{cf} "
    end
    tmpstr = "CDEF:#{cname}=" +
	vnames.map {|vname|
      "#{vname},UN,0,#{vname},IF,#{mag},*#{limitstr}"
      }.join(',') + ',+' * (vnames.size-1)
    expr.push tmpstr
    #expr.push ',FLOOR' if ds =~ /(in|out)ucast/
  else
    rrdpath, = rrdpaths
    expr.push "DEF:v#{cname}=#{rrdpath}:#{ds}:#{cf} "
    expr.push "CDEF:#{cname}=v#{cname}#{limitstr},#{mag},* "
  end

  if line == 'XPORT'
    expr.push " XPORT:#{cname}:\"#{legend}\""
  else
    expr.push " #{line}:#{cname}#{color}"
    unless legend == '-'
      esc_legend = legend.gsub(':', '\:')
      expr.push ":\"#{esc_legend}\" "
      expr.push "GPRINT:#{cname}:MAX:\"(max\\:%.2lf%s\" "
      expr.push "GPRINT:#{cname}:AVERAGE:\"avg\\:%.2lf%s\" "
      expr.push "GPRINT:#{cname}:LAST:\"last\\:%.2lf%s)\""
    end
  end
  return expr.join('')
end

Instance Method Details

#buffered_update(*args) ⇒ Object



139
140
141
142
143
# File 'lib/gri/rrd.rb', line 139

def buffered_update(*args)
  res = flush_buffer if @update_buf.size > 40
  @update_buf += args
  res
end

#dump(dst = nil) ⇒ Object



331
332
333
334
335
336
337
338
# File 'lib/gri/rrd.rb', line 331

def dump dst=nil
  tmp_path = dst || "/tmp/rrdtmp#{$$}.xml"
  open(tmp_path, 'w') {|out|
    RRDm.cmd 'dump', @rrdname#, tmp_path
    str, = RRDm.read out
  }
  return tmp_path
end

#fetch(cf, resolution = nil, starttime = nil, endtime = nil) ⇒ Object



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/gri/rrd.rb', line 270

def fetch cf, resolution=nil, starttime=nil, endtime=nil
  args = []
  if resolution
    resolution = resolution.to_i
    if starttime and endtime
	starttime = starttime.to_i / resolution * resolution
	endtime = endtime.to_i / resolution * resolution
    end
    args.push ['--resolution', resolution]
  end
  args.push ['--start', starttime.to_i] if starttime
  args.push ['--end', endtime.to_i] if endtime
  RRDm.cmd 'fetch', @rrdname, cf, *args
  str, = RRDm.read
  collect = []
  s = nil #XXX
  for line in str.split("\n")
    timestr, *remain = line.split
    time = timestr.to_i
    if time > 0
	collect.push [Time.at(time),
 remain.collect {|s|
   if s =~ /^nan$/i
     nil
   else
     s.to_f
   end
 }]
    else
	ds_ary = line.split
	ds_ary.shift
	@ds_ary = ds_ary if ds_ary.size > 0
    end
  end
  return collect
end

#flush_buffer(v = false) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/gri/rrd.rb', line 145

def flush_buffer v=false
  if @update_buf.size > 0
    begin
	unless @created_p
 create *@args
 @created_p = true
	end
      res = update *@update_buf
    end
    @update_buf = []
  end
  res
end

#graph(fname, starttime, endtime, *misc_args) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/gri/rrd.rb', line 188

def graph fname, starttime, endtime, *misc_args
  starttime = starttime.to_i
  endtime = endtime.to_i
  if misc_args.first.kind_of? Symbol
    cmd = misc_args.shift.to_s
  else
    daemon = @address ? " --daemon #{@address}" : ''
    cmd = "graph#{daemon}"
  end
  args = [cmd, fname, '--start', starttime, '--end', endtime]
  args.push '--slope-mode' if @version >= '1.2'
  args.push '--width ' + @width.to_s if @width
  args.push '--height ' + @height.to_s if @height
  args.push '--lower-limit ' + @lower_limit.to_s if @lower_limit
  args.push '--imgformat ' + @imgformat
  args.push '--title ' + @title if @title
  args.push '--vertical-label ' + @vertical_label if @vertical_label
  if @version >= '1.3'
    for fstr in @fonts
      (fstr =~ /^(DEFAULT|TITLE|AXIS|UNIT|LEGEND):(\d+):/) and
        args.push "-n \"#{fstr}\""
    end
  end

  dt = endtime - starttime
  vtime = Time.at(starttime)
  vcolor = '#ff7f7f'
  xgrid = nil
  if dt < 3 * 3600
    vtime = Time.local(vtime.year, vtime.mon, vtime.day) + 24*3600
    args.push "VRULE:#{vtime.to_i}#{vcolor}" if vtime.to_i < endtime
    xgrid = 'MINUTE:10:HOUR:1:MINUTE:10:0:%H:%M'
  elsif dt < 12 * 3600
    vtime = Time.local(vtime.year, vtime.mon, vtime.day) + 24*3600
    args.push "VRULE:#{vtime.to_i}#{vcolor}" if vtime.to_i < endtime
    xgrid = 'MINUTE:30:HOUR:1:HOUR:1:0:%H:%M'
  elsif dt < 6 * 24 * 3600
    vtime = Time.local(vtime.year, vtime.mon, vtime.day) + 24*3600
    while vtime.to_i < endtime
	args.push "VRULE:#{vtime.to_i}#{vcolor}"
	vtime += 24*3600
    end
    xgrid = 'HOUR:1:HOUR:6:HOUR:6:0:%H:%M'
  elsif dt < 14 * 24 * 3600
    tmptime = vtime + ((8 - vtime.wday) % 7)*24*3600
    vtime = Time.local(tmptime.year, tmptime.mon, tmptime.day)
    while vtime.to_i < endtime
	args.push "VRULE:#{vtime.to_i}#{vcolor}"
	vtime += 7*24*3600
    end
    xgrid = 'HOUR:6:DAY:1:DAY:1:86400:%a'
  elsif dt < 90 * 24 * 3600
    tmptime = Time.local(vtime.year, vtime.mon) + 31*24*3600 + 3610
    vtime = Time.local(tmptime.year, tmptime.mon)
    while vtime.to_i < endtime
	args.push "VRULE:#{vtime.to_i}#{vcolor}"
	tmptime = vtime + 31*24*3600 + 3610
	vtime = Time.local(tmptime.year, tmptime.mon, 1)
    end
    xgrid = 'DAY:1:WEEK:1:WEEK:1:86400:%m/%d'
  else
    vtime = Time.local(vtime.year+1)
    while vtime.to_i < endtime
	args.push "VRULE:#{vtime.to_i}#{vcolor}"
	vtime = Time.local(vtime.year+1)
    end
    xgrid = 'MONTH:3:YEAR:1:YEAR:1:31536000:%Y' if dt > 400 * 24 * 3600
  end
  args.push "--x-grid \"#{xgrid}\"" if xgrid

  if @show_graph_date
    cstr = "COMMENT:" +
	Time.at(starttime).strftime('"%Y/%m/%d %H:%M - ') +
	Time.at(endtime).strftime('%Y/%m/%d %H:%M\n"')
    args.push cstr
  end

  args += misc_args
  RRDm.cmd args
  return RRDm.read
end

#graphgen(stime, etime, args) ⇒ Object



382
383
384
385
386
387
388
389
# File 'lib/gri/rrd.rb', line 382

def graphgen stime, etime, args
  tmp_file = "/tmp/rrdtmp#{$$}"
  img = nil
  graph tmp_file, stime, etime, args
  open(tmp_file) {|f| img = f.read}
  File.unlink tmp_file
  img
end

#infoObject



325
326
327
328
329
# File 'lib/gri/rrd.rb', line 325

def info
  RRDm.cmd 'info', @rrdname
  str, = RRDm.read
  return str.split("\n")
end

#remove_base_dir(*args) ⇒ Object



114
115
116
117
118
119
120
121
122
123
# File 'lib/gri/rrd.rb', line 114

def remove_base_dir *args
  return args unless @base_dir
  if @base_dir[-1, 1] == ?/
    base_dir = @base_dir
  else
    base_dir = @base_dir + '/'
  end
  re = /\A#{base_dir}/
  args.map {|arg| arg.sub(re, '')}
end

#resize(num, deltasize) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
# File 'lib/gri/rrd.rb', line 313

def resize num, deltasize
  if deltasize >= 0
    rrcmd = 'GROW'
  else
    rrcmd = 'SHRINK'
  end
  RRDm.cmd 'resize', @rrdname, num, rrcmd, deltasize.abs
  str, = RRDm.read
  File.rename 'resize.rrd', @rrdname
  return str.split("\n")
end

#restore(src = nil) ⇒ Object



340
341
342
343
344
345
# File 'lib/gri/rrd.rb', line 340

def restore src=nil
  tmp_path = src
  RRDm.cmd 'restore', tmp_path, @rrdname
  str, = RRDm.read
  return tmp_path
end

#rrainfoObject



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/gri/rrd.rb', line 357

def rrainfo
  ary = info
  rra = []
  step, = ary[2].scan(/^step = (\d+)$/)[0]
  if step
    for line in ary
	if line =~ /^rra\[(\d+)\]\.(.*)/
 num = $1.to_i
 remain = $2
 #p [$1, remain]
 rra[num] = [] unless rra[num]
 case remain
 when /^cf = "(\w+)"/
   rra[num][0] = $1
 when /^rows = (\d+)/
   rra[num][1] = $1.to_i
 when /^pdp_per_row = (\d+)/
   rra[num][2] = $1.to_i
 end
	end
    end
  end
  return step, rra
end

#set_create_args(*args) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/gri/rrd.rb', line 106

def set_create_args *args
  @rrdname = args.shift
  if @rrdname
    @created_p = File.exist? @rrdname
    @args = args
  end
end

#tune(args) ⇒ Object



307
308
309
310
311
# File 'lib/gri/rrd.rb', line 307

def tune args
  RRDm.cmd 'tune', @rrdname, *args
  str, = RRDm.read
  return str.split("\n")
end

#update(*args) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/gri/rrd.rb', line 159

def update(*args)
  daemon = @address ? " --daemon #{@address}" : ''
  path = remove_base_dir @rrdname
  RRDm.cmd "update#{daemon}", path.first, *args
  begin
    str, = RRDm.read
  rescue RuntimeError => e
    if e.message =~ /last update time is (\d+)/
      last_update = $1.to_i
      pargs = []
      args.each {|arg|
        if arg.split(':')[0].to_i > last_update
          pargs.push arg
        end
      }
      if pargs.size == 0
        return nil
      end
      args = pargs
      RRDm.cmd "update#{daemon}", path, *args
      str, = RRDm.read rescue nil
    else
      Log.error "#{@rrdname}: #{$!}"
    end
  end
  lines = str.split(/\n/).select {|line| line =~ /^\[/} if str
  lines
end

#xport(starttime, endtime, *misc_args) ⇒ Object



347
348
349
350
351
352
353
354
355
# File 'lib/gri/rrd.rb', line 347

def xport starttime, endtime, *misc_args
  starttime = starttime.to_i
  endtime = endtime.to_i
  cmd = "xport#{@address ? " --daemon #{@address}" : ''}"
  args = [cmd, '--json', '--start', starttime, '--end', endtime] + misc_args
  RRDm.cmd args
  str, = RRDm.read
  return str
end