# class Metric

A class for handling metrics. This is currently ridiculously hackish.

### Attributes

basedir[W]
label[RW]
name[RW]
type[RW]
value[RW]
values[W]

### Public Class Methods

labelize(name) click to toggle source

Convert a name into a label.

    # File lib/puppet/util/metric.rb, line 178
    def self.labelize(name)
      name.to_s.capitalize.gsub("_", " ")
    end

new(name,label = nil) click to toggle source

    # File lib/puppet/util/metric.rb, line 122
    def initialize(name,label = nil)
      @name = name.to_s

      @label = label || self.class.labelize(name)

      @values = []
    end

### Public Instance Methods

[](name) click to toggle source

Return a specific value

    # File lib/puppet/util/metric.rb, line 13
    def [](name)
      if value = @values.find { |v| v[0] == name }
        return value[2]
      else
        return 0
      end
    end

basedir() click to toggle source

    # File lib/puppet/util/metric.rb, line 21
    def basedir
      if defined?(@basedir)
        @basedir
      else
        Puppet[:rrddir]
      end
    end

create(start = nil) click to toggle source

    # File lib/puppet/util/metric.rb, line 29
    def create(start = nil)
      Puppet.settings.use(:main, :metrics)

      start ||= Time.now.to_i - 5

      args = []

      if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
        @rrd = RRDtool.new(self.path)
      end

      values.each { |value|
        # the 7200 is the heartbeat -- this means that any data that isn't
        # more frequently than every two hours gets thrown away
        args.push "DS:#{value[0]}:GAUGE:7200:U:U"
      }
      args.push "RRA:AVERAGE:0.5:1:300"

      begin
        if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
          @rrd.create( Puppet[:rrdinterval], start, args)
        else
          RRD.create( self.path, '-s', Puppet[:rrdinterval].to_s, '-b', start.to_i.to_s, *args)
        end
      rescue => detail
        raise "Could not create RRD file #{path}: #{detail}"
      end
    end

dump() click to toggle source

    # File lib/puppet/util/metric.rb, line 58
    def dump
      if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
        puts @rrd.info
      else
        puts RRD.info(self.path)
      end
    end

graph(range = nil) click to toggle source

    # File lib/puppet/util/metric.rb, line 66
    def graph(range = nil)
      unless Puppet.features.rrd? || Puppet.features.rrd_legacy?
        Puppet.warning "RRD library is missing; cannot graph metrics"
        return
      end

      unit = 60 * 60 * 24
      colorstack = %w{#00ff00 #ff0000 #0000ff #ffff00 #ff99ff #ff9966 #66ffff #990000 #099000 #000990 #f00990 #0f0f0f #555555 #333333 #ffffff}

      {:daily => unit, :weekly => unit * 7, :monthly => unit * 30, :yearly => unit * 365}.each do |name, time|
        file = self.path.sub(/\.rrd$/, "-#{name}.png")
        args = [file]

        args.push("--title",self.label)
        args.push("--imgformat","PNG")
        args.push("--interlace")
        i = 0
        defs = []
        lines = []
        #p @values.collect { |s,l| s }
        values.zip(colorstack).each { |value,color|
          next if value.nil?
          # this actually uses the data label
          defs.push("DEF:#{value[0]}=#{self.path}:#{value[0]}:AVERAGE")
          lines.push("LINE2:#{value[0]}#{color}:#{value[1]}")
        }
        args << defs
        args << lines
        args.flatten!
        if range
          if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
            args.push("--start",range[0],"--end",range[1])
          else
            args.push("--start",range[0].to_i.to_s,"--end",range[1].to_i.to_s)
          end
        else
          if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
            args.push("--start", Time.now.to_i - time, "--end", Time.now.to_i)
          else
            args.push("--start", (Time.now.to_i - time).to_s, "--end", Time.now.to_i.to_s)
          end
        end

        begin
          #Puppet.warning "args = #{args}"
          if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
            RRDtool.graph( args )
          else
            RRD.graph( *args )
          end
        rescue => detail
          Puppet.err "Failed to graph #{self.name}: #{detail}"
        end
      end
    end

newvalue(name,value,label = nil) click to toggle source

    # File lib/puppet/util/metric.rb, line 134
    def newvalue(name,value,label = nil)
      raise ArgumentError.new("metric name #{name.inspect} is not a string") unless name.is_a? String
      label ||= self.class.labelize(name)
      @values.push [name,label,value]
    end

path() click to toggle source

    # File lib/puppet/util/metric.rb, line 130
    def path
      File.join(self.basedir, @name + ".rrd")
    end

store(time) click to toggle source

    # File lib/puppet/util/metric.rb, line 140
    def store(time)
      unless Puppet.features.rrd? || Puppet.features.rrd_legacy?
        Puppet.warning "RRD library is missing; cannot store metrics"
        return
      end
      self.create(time - 5) unless FileTest.exists?(self.path)

      if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
        @rrd ||= RRDtool.new(self.path)
      end

      # XXX this is not terribly error-resistant
      args = [time]
      temps = []
      values.each { |value|
        #Puppet.warning "value[0]: #{value[0]}; value[1]: #{value[1]}; value[2]: #{value[2]}; "
        args.push value[2]
        temps.push value[0]
      }
      arg = args.join(":")
      template = temps.join(":")
      begin
        if Puppet.features.rrd_legacy? && ! Puppet.features.rrd?
          @rrd.update( template, [ arg ] )
        else
          RRD.update( self.path, '-t', template, arg )
        end
        #system("rrdtool updatev #{self.path} '#{arg}'")
      rescue => detail
        raise Puppet::Error, "Failed to update #{self.name}: #{detail}"
      end
    end

values() click to toggle source

    # File lib/puppet/util/metric.rb, line 173
    def values
      @values.sort { |a, b| a[1] <=> b[1] }
    end