<?xml version="1.0" encoding="UTF-8"?>
<plugin-url>
  <approved type="boolean">true</approved>
  <author>Scout, Eric Lindvall</author>
  <cached-tag-list>http, url monitoring</cached-tag-list>
  <canonical-name nil="true"></canonical-name>
  <code>require 'benchmark'
require 'net/http'
require 'net/https'
require 'uri'

class UrlMonitor &lt; Scout::Plugin
  include Net
  
  TEST_USAGE = &quot;#{File.basename($0)} url URL last_run LAST_RUN&quot;
  TIMEOUT_LENGTH = 50 # seconds
  
  def build_report
    url = option(&quot;url&quot;).to_s.strip
    if url.empty?
      return error(&quot;A url wasn't provided.&quot;)
    end
    
    unless url =~ %r{\Ahttps?://}
      url = &quot;http://#{url}&quot;
    end
    
    response = nil
    response_time = Benchmark.realtime do
      response = http_response(url)
    end

    report(:status =&gt; response.class.to_s[/^Net::HTTP(.*)$/, 1],
           :response_time =&gt; response_time)
    
    is_up = valid_http_response?(response) ? 1 : 0
    report(:up =&gt; is_up)
    
    if is_up != memory(:was_up)
      if is_up == 0
        alert(&quot;The URL [#{url}] is not responding&quot;, unindent(&lt;&lt;-EOF))
            URL: #{url}

            Code: #{response.code}
            Status: #{response.class.to_s[/^Net::HTTP(.*)$/, 1]}
            Message: #{response.message}
          EOF
        remember(:down_at =&gt; Time.now)
      else
        if memory(:was_up) &amp;&amp; memory(:down_at)
          alert( &quot;The URL [#{url}] is responding again&quot;,
                 &quot;URL: #{url}\n\nStatus: #{response.class.to_s[/^Net::HTTP(.*)$/, 1]}. &quot; +
                 &quot;Was unresponsive for #{(Time.now - memory(:down_at)).to_i} seconds&quot;)
        else
          alert( &quot;The URL [#{url}] is responding&quot;,
                 &quot;URL: #{url}\n\nStatus: #{response.class.to_s[/^Net::HTTP(.*)$/, 1]}. &quot;)
        end
        memory.delete(:down_at)
      end
    end
    
    remember(:was_up =&gt; is_up)
  rescue Exception =&gt; e
    error( &quot;Error monitoring url [#{url}]&quot;,
           &quot;#{e.message}&lt;br&gt;&lt;br&gt;#{e.backtrace.join('&lt;br&gt;')}&quot; )
  end
  
  def valid_http_response?(result)
    [HTTPOK,HTTPFound].include?(result.class) 
  end
  
  # returns the http response (string) from a url
  def http_response(url)
    uri = URI.parse(url)

    response = nil
    retry_url_trailing_slash = true
    retry_url_execution_expired = true
    begin
      http = Net::HTTP.new(uri.host,uri.port)
      http.use_ssl = url =~ %r{\Ahttps://}
      http.start(){|http|
            http.open_timeout = TIMEOUT_LENGTH
            req = Net::HTTP::Get.new((uri.path != '' ? uri.path : '/' ) + (uri.query ? ('?' + uri.query) : ''))
            if uri.user &amp;&amp; uri.password
              req.basic_auth uri.user, uri.password
            end
            response = http.request(req)
      }
    rescue Exception =&gt; e
      # forgot the trailing slash...add and retry
      if e.message == &quot;HTTP request path is empty&quot; and retry_url_trailing_slash
        url += '/'
        uri = URI.parse(url)
        h = Net::HTTP.new(uri.host)
        retry_url_trailing_slash = false
        retry
      elsif e.message =~ /execution expired/ and retry_url_execution_expired
        retry_url_execution_expired = false
        retry
      else
        response = e.to_s
      end
    end
        
    return response
  end

  def unindent(string)
    indentation = string[/\A\s*/]
    string.strip.gsub(/^#{indentation}/, &quot;&quot;)
  end
end
</code>
  <created-at type="datetime">2007-12-12T15:50:57-08:00</created-at>
  <default-triggers type="yaml" nil="true"></default-triggers>
  <description>Monitors the availability of a URL, sending an alert if the URL is not reachable. 
&lt;br/&gt;
An alert is generated every time the URL is unreachable.
&lt;br/&gt;
Accepts a single option - the url to monitor.</description>
  <featured type="boolean">false</featured>
  <id type="integer">2</id>
  <metadata type="yaml">--- |
options:
  url:
    name: Url
    notes: The full URL (including http://) of the URL to monitor. You can provide basic authentication options as well (http://user:pass@domain.com)
    default: &quot;http://www.scoutapp.com/&quot;

metadata:
  response_time:          
    label: Response Time
    units: secs
    precision: 2
    larger_is_better: false
  up:          
    label: Url Reachable
    precision: 0
    larger_is_better: true

</metadata>
  <name>URL Monitoring</name>
  <plugins-count type="integer">242</plugins-count>
  <rating-avg type="decimal">3.0</rating-avg>
  <rating-count type="integer">1</rating-count>
  <rating-total type="integer">3</rating-total>
  <readme>URL Monitoring Plugin
=====================
Created by [Highgroove Studios LLC](http://www.highgroove.com)

Compatibility 
-------------
Works fully on Linux and OSX. 

</readme>
  <schema type="yaml" nil="true"></schema>
  <scout-version type="integer">3</scout-version>
  <short-description>Monitors the availability of a URL, sending an alert if the URL is not reachable. 

The following data is reported:

* Url Reachable (1 if reachable, 0 if not)
* Response Time (secs)</short-description>
  <tested-platforms>linux macosx</tested-platforms>
  <total-usage-count type="integer">0</total-usage-count>
  <updated-at type="datetime">2010-01-21T15:08:55-08:00</updated-at>
  <url>http://github.com/highgroove/scout-plugins/raw/master/url_monitor/url_monitor.rb</url>
</plugin-url>
