<?xml version="1.0" encoding="UTF-8"?>
<plugin-url>
  <approved type="boolean">true</approved>
  <author>Scout, Eric Lindvall</author>
  <cached-tag-list>memory, process</cached-tag-list>
  <canonical-name nil="true"></canonical-name>
  <code>class ProcessUsage &lt; Scout::Plugin  
  MEM_CONVERSION = 1024
  
  def build_report
    if option(:command_name).nil? or option(:command_name) == &quot;&quot;
      return error(&quot;Please specify the name of the process you want to monitor.&quot;)
    end
    ps_command   = option(:ps_command) || &quot;ps auxww&quot;
    ps_regex     = (option(:ps_regex) || &quot;(?i:\\bCOMMAND\\b)&quot;).to_s.gsub(&quot;COMMAND&quot;) { Regexp.escape(option(:command_name)) }

    ps_output = `#{ps_command}`
    unless $?.success?
      return error(&quot;Couldn't use `ps` as expected.&quot;, error.message)
    end

    ps_lines = ps_output.split(/\n/)
    fields   = ps_lines.shift.downcase.split
    unless (memory_index = fields.index(&quot;rss&quot;)) &amp;&amp; (pid_index = fields.index('pid'))
      return error( &quot;RSS or PID field not found.&quot;,
                    &quot;The output from `#{ps_command}` did not include the needed RSS and PID fields.&quot; )
    end

    # narrow the ps lines to just those mentioning the process we're interested in
    process_lines = ps_lines.grep(Regexp.new(ps_regex))

    if process_lines.any?
      rss_values = process_lines.map { |com| Float(com.split[memory_index]).abs }
      pids       = process_lines.map { |com| Integer(com.split[pid_index]) }
      highest    = rss_values.max
      total      = rss_values.inject(0){|s,value| s + value }
      restarts   = 0

      if remembered_pids = memory(:pids)
        # Find how many new pids we haven't seen before
        new_pids     = (pids - remembered_pids).length

        # Find how many more pids we have now than before
        started_pids = pids.length - remembered_pids.length
        started_pids = 0 if started_pids &lt; 1

        # Don't include newly started processes as restarts
        restarts = new_pids - started_pids
      end

      report(:memory        =&gt; (highest/MEM_CONVERSION).to_i,
             :total_rss     =&gt; (total/MEM_CONVERSION).to_i,
             :num_processes =&gt; process_lines.size,
             :restarts      =&gt; restarts)

      remember(:pids =&gt; pids)
    else
      error( &quot;Command not found.&quot;,
             &quot;No processes found matching #{option(:command_name)}.&quot; )
    end
  rescue Exception =&gt; e
    error(&quot;Error when executing: #{e.class}&quot;, e.message)
  end
end
</code>
  <created-at type="datetime">2007-12-12T15:49:41-08:00</created-at>
  <default-triggers type="yaml" nil="true"></default-triggers>
  <description>Given a process name, this plugin monitors:

* _Number of Processes_ - the number of matching processes running
* _Largest Process Memory Usage_ - the memory usage (RSS) of the largest instance
* _Total Memory Usage_ - the total memory usage (RSS) across all process instances.
* _Restarts_ - the number of process restarts

</description>
  <featured type="boolean">true</featured>
  <id type="integer">1</id>
  <metadata type="yaml">--- |
options:
  command_name:
    name: Command Name
    notes: The name of the command to pull statistics for.
    default: mongrel_rails
  ps_command:
    name: The Process Status (ps) Command
    notes: The command with options. The default works on most systems.
    default: ps auxww
  ps_regex:
    name: The regex used to match a command name.
    notes: &quot;By default, this matches a command name anywhere in the ps output line.  The word COMMAND get's replaced with the command you gave (regex escaped).  You may wish to try the following pattern if you only want to match a command in the last column:  (?i:COMMAND\\s+$)&quot;
    default: &quot;(?i:\\bCOMMAND\\b)&quot;
    
metadata:
  memory:          
    label: Largest Process Memory Usage
    units: MB
    precision: 0
  total_rss:          
    label: Total Memory Usage
    units: MB
    precision: 0
  num_processes:          
    label: Number of Processes
    units: &quot;&quot;
    precision: 0
  restarts:          
    label: Restarts
    units: &quot;&quot;
    precision: 0
     
triggers:
  - type: peak
    dname: memory
    max_value: 10
  - type: trend
    dname: memory
    direction: UP
    percentage_change: 20
    duration: 60
    window_reference: LAST_WEEK
    min_value: 5

</metadata>
  <name>Process Usage</name>
  <plugins-count type="integer">247</plugins-count>
  <rating-avg type="decimal">4.0</rating-avg>
  <rating-count type="integer">2</rating-count>
  <rating-total type="integer">8</rating-total>
  <readme>Process Usage Plugin
====================

Created by [Highgroove Studios LLC](http://www.highgroove.com)

Compatibility 
-------------

Works on Linux and OSX.

</readme>
  <schema type="yaml" nil="true"></schema>
  <scout-version type="integer">3</scout-version>
  <short-description>Monitors the memory usage of a process, generating an alert if it exceeds a specified threshold. </short-description>
  <tested-platforms>linux macosx solaris</tested-platforms>
  <total-usage-count type="integer">0</total-usage-count>
  <updated-at type="datetime">2010-01-21T15:18:47-08:00</updated-at>
  <url>http://github.com/highgroove/scout-plugins/raw/master/process_memory/process_usage.rb</url>
</plugin-url>
