Class: Scout::Plugin

Inherits:
Object
  • Object
show all
Defined in:
lib/scout/plugin.rb

Constant Summary collapse

EMBEDDED_OPTIONS_REGEX =
/OPTIONS ?= ?<<-?([A-Z_]+)(.*)\1/m

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(last_run, memory, options) ⇒ Plugin

Creates a new Scout Plugin to run.



65
66
67
68
69
# File 'lib/scout/plugin.rb', line 65

def initialize(last_run, memory, options)
  @last_run = last_run
  @memory   = memory
  @options  = options
end

Class Attribute Details

.last_definedObject

Returns the value of attribute last_defined.



11
12
13
# File 'lib/scout/plugin.rb', line 11

def last_defined
  @last_defined
end

Class Method Details

.extract_code_class(code) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/scout/plugin.rb', line 53

def extract_code_class(code)
  match = /class\s\b(\w*)\s*?<\s*Scout::Plugin/.match(code)

  if match
    return match[1]
  else
    raise ArgumentError, "can't identify plugin class"
  end
end

.extract_options_yaml_from_code(code) ⇒ Object

extracts the internal YAML, if any, and returns the YAML string. returns nil if no embedded options.



48
49
50
51
# File 'lib/scout/plugin.rb', line 48

def extract_options_yaml_from_code(code)
  code =~ EMBEDDED_OPTIONS_REGEX
  return $2
end

.has_embedded_options?(code) ⇒ Boolean

true if the code seems to have embedded options

Returns:

  • (Boolean)


42
43
44
# File 'lib/scout/plugin.rb', line 42

def has_embedded_options?(code)
  code =~ EMBEDDED_OPTIONS_REGEX
end

.inherited(new_plugin) ⇒ Object



13
14
15
# File 'lib/scout/plugin.rb', line 13

def inherited(new_plugin)
  @last_defined = new_plugin
end

.load(last_run, memory, options) ⇒ Object



17
18
19
# File 'lib/scout/plugin.rb', line 17

def load(last_run, memory, options)
  new(last_run, memory, options)
end

.needs(*libraries) ⇒ Object

You can use this method to indicate one or more libraries your plugin requires:

class MyNeedyPlugin < Scout::Plugin
  needs "faster_csv", "elif"
  # ...
end

Your build_report() method will not be called if all libraries cannot be loaded. RubyGems will be loaded if needed to find the libraries.



33
34
35
36
37
38
39
# File 'lib/scout/plugin.rb', line 33

def needs(*libraries)
  if libraries.empty?
    @needs ||= [ ]
  else
    needs.push(*libraries.flatten)
  end
end

Instance Method Details

#counter(name, value, options = {}, &block) ⇒ Object

Usage:

counter(:rkbps, stats['rsect'] / 2, :per => :second)
counter(:rpm, request_counter, :per => :minute)
counter(:swap_ins, vmstat['pswpin'], :per => :second, :round => true)


174
175
176
177
178
179
180
181
182
183
184
185
186
187
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
# File 'lib/scout/plugin.rb', line 174

def counter(name, value, options = {}, &block)
  current_time = Time.now

  if data = memory("_counter_#{name}")
    last_time, last_value = data[:time], data[:value]
    elapsed_seconds       = current_time - last_time

    # We won't log it if the value has wrapped or enough time hasn't
    # elapsed
    if value >= last_value && elapsed_seconds >= 1
      if block
        result = block.call(last_value, value)
      else
        result = value - last_value
      end

      case options[:per]
      when :second, 'second'
        result = result / elapsed_seconds.to_f
      when :minute, 'minute'
        result = result / elapsed_seconds.to_f * 60.0
      else
        raise "Unknown option for ':per': #{options[:per].inspect}"
      end

      if options[:round]
        # Backward compatibility
        options[:round] = 1 if options[:round] == true

        result = (result * (10 ** options[:round])).round / (10 ** options[:round]).to_f
      end

      report(name => result)
    end
  else # report nil to reserve the metric name in rrd
    report(name => nil)
  end

  remember("_counter_#{name}" => { :time => current_time, :value => value })
end

#data_for_serverObject

Builds the data to send to the server.

We programatically define several helper methods for creating this data.

Usage:

reports << {:data => "here"}
report(:data => "here")
add_report(:data => "here")

alerts << {:subject => "subject", :body => "body"}
alert("subject", "body")
alert(:subject => "subject", :body => "body")
add_alert("subject", "body")
add_alert(:subject => "subject", :body => "body")

errors << {:subject => "subject", :body => "body"}
error("subject", "body")
error(:subject => "subject", :body => "body")
add_error("subject", "body")
add_error(:subject => "subject", :body => "body")


97
98
99
100
101
102
103
# File 'lib/scout/plugin.rb', line 97

def data_for_server
  @data_for_server ||= { :reports   => [ ],
                         :alerts    => [ ],
                         :errors    => [ ],
                         :summaries => [ ],
                         :memory  => { } }
end

#memory(name = nil) ⇒ Object

Usage:

memory(:no_track)
memory.delete(:no_track)
memory.clear


143
144
145
146
147
148
149
150
# File 'lib/scout/plugin.rb', line 143

def memory(name = nil)
  if name.nil?
    data_for_server[:memory]
  else
    @memory[name] ||
    @memory[name.is_a?(String) ? name.to_sym : String(name)]
  end
end

#option(name) ⇒ Object



71
72
73
# File 'lib/scout/plugin.rb', line 71

def option(name)
  @options[name] || @options[name.is_a?(String) ? name.to_sym : String(name)]
end

#remember(*args) ⇒ Object

Usage:

remember(:name, value)
remember(:name1, value1, :name2, value2)
remember(:name => value)
remember(:name1 => value1, :name2 => value2)
remember(:name1, value1, :name2 => value2)


161
162
163
164
165
# File 'lib/scout/plugin.rb', line 161

def remember(*args)
  hashes, other = args.partition { |value| value.is_a? Hash }
  hashes.each { |hash| memory.merge!(hash) }
  (0...other.size).step(2) { |i| memory.merge!(other[i] => other[i + 1]) }
end

#runObject

Old plugins will work because they override this method. New plugins can now leave this method in place, add a build_report() method instead, and use the new helper methods to build up content inside which will automatically be returned as the end result of the run.



221
222
223
224
# File 'lib/scout/plugin.rb', line 221

def run
  build_report if self.class.needs.all? { |l| library_available?(l) }
  data_for_server
end