root/src/modules-lua/noit/module/resmon.lua

Revision 72e62f78f28e05bb81e934d01101f777d85e2cd2, 5.8 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 8 years ago)

first whack, please test the crap out of this. refs #181

  • Property mode set to 100644
Line 
1 -- Copyright (c) 2008, OmniTI Computer Consulting, Inc.
2 -- All rights reserved.
3 --
4 -- Redistribution and use in source and binary forms, with or without
5 -- modification, are permitted provided that the following conditions are
6 -- met:
7 --
8 --     * Redistributions of source code must retain the above copyright
9 --       notice, this list of conditions and the following disclaimer.
10 --     * Redistributions in binary form must reproduce the above
11 --       copyright notice, this list of conditions and the following
12 --       disclaimer in the documentation and/or other materials provided
13 --       with the distribution.
14 --     * Neither the name OmniTI Computer Consulting, Inc. nor the names
15 --       of its contributors may be used to endorse or promote products
16 --       derived from this software without specific prior written
17 --       permission.
18 --
19 -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 -- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 -- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 -- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 -- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 -- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 module(..., package.seeall)
32
33 function onload(image)
34   image.xml_description([=[
35 <module>
36   <name>resmon</name>
37   <description><para>The resmon module performs services checks against a Resmon service.</para>
38   <para><ulink url="https://labs.omniti.com/trac/resmon"><citetitle>Resmon</citetitle></ulink> is a light-weight resource monitor that exposes health of services over HTTP in XML.</para>
39   <para>This module rides on the http module and provides a secondary phase of XML parsing on the contents that extracts Resmon status messages into metrics that can be trended.</para>
40   </description>
41   <loader>lua</loader>
42   <object>noit.module.resmon</object>
43   <checkconfig>
44     <parameter name="url"
45                required="required"
46                allowed=".+">The URL including schema and hostname (as you would type into a browser's location bar).</parameter>
47     <parameter name="port"
48                required="optional"
49                allowed="\d+">The TCP port can be specified to overide the default of 81.</parameter>
50   </checkconfig>
51   <examples>
52     <example>
53       <title>Checking resmon services on OmniTI Labs.</title>
54       <para>This example checks the Resmon service on OmniTI Labs.</para>
55       <programlisting><![CDATA[
56       <noit>
57         <modules>
58           <loader image="lua" name="lua">
59             <config><directory>/opt/reconnoiter/libexec/modules-lua/?.lua</directory></config>
60           </loader>
61           <module loader="lua" name="resmon" object="noit.module.resmon"/>
62         </modules>
63         <checks>
64           <labs target="8.8.38.5" module="resmon">
65             <check uuid="36b8ba72-7968-11dd-a67f-d39a2cc3f9de"/>
66           </labs>
67         </checks>
68       </noit>
69     ]]></programlisting>
70     </example>
71   </examples>
72 </module>
73 ]=]);
74   return 0
75 end
76
77 function init(module)
78   return 0
79 end
80
81 function config(module, options)
82   return 0
83 end
84
85 local HttpClient = require 'noit.HttpClient'
86
87 function initiate(module, check)
88     local url = check.config.url or 'http:///'
89     local schema, host, uri = string.match(url, "^(https?)://([^/]*)(.+)$");
90     local port
91     local use_ssl = false
92     local codere = noit.pcre(check.config.code or '^200$')
93     local good = false
94     local starttime = noit.timeval.now()
95
96     -- assume the worst.
97     check.bad()
98     check.unavailable()
99
100     if host == nil then host = check.target end
101     if schema == nil then
102         schema = 'http'
103         uri = '/'
104     end
105     if schema == 'http' then
106         port = check.config.port or 81
107     elseif schema == 'https' then
108         port = check.config.port or 443
109         use_ssl = true
110     else
111         error(schema .. " not supported")
112     end
113
114     local output = ''
115
116     -- callbacks from the HttpClient
117     local callbacks = { }
118     callbacks.consume = function (str) output = output .. str end
119     local client = HttpClient:new(callbacks)
120     local rv, err = client:connect(check.target, port, use_ssl)
121    
122     if rv ~= 0 then
123         check.status(err or "unknown error")
124         return
125     end
126
127     -- perform the request
128     local headers = {}
129     headers.Host = host
130     client:do_request("GET", uri, headers)
131     client:get_response()
132
133     -- parse the xml doc
134     local doc = noit.parsexml(output)
135     if doc == nil then
136         noit.log("error", "bad xml: %s", output)
137     end
138     check.available()
139
140     local services = 0
141     local result
142     for result in doc:xpath("/ResmonResults/ResmonResult") do
143         services = services + 1
144         local module = result:attr("module") or "DUMMY"
145         local service = result:attr("service") or "DUMMY"
146         local prefix = module .. '`' .. service .. '`'
147         local obj
148         obj = (doc:xpath("last_runtime_seconds", result))()
149         local ds = tonumber(obj and obj:contents())
150         if ds ~= nil then ds = math.floor(ds * 1000) end
151         check.metric_uint32(prefix .. "duration", ds)
152         obj = (doc:xpath("state", result))()
153         check.metric_string(prefix .. "state", obj and obj:contents())
154         obj = (doc:xpath("message", result))()
155         check.metric_string(prefix .. "message", obj and obj:contents())
156     end
157     check.metric_uint32("services", services)
158     local status = ''
159     if services > 0 then check.good() else check.bad() end
160     check.status("services=" .. services)
161 end
162
Note: See TracBrowser for help on using the browser.