Changeset efa9375336eec306ede14a9a1032985a71482810

Show
Ignore:
Timestamp:
08/21/10 23:18:58 (8 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1282432738 +0000
git-parent:

[ece3776d1e32717531011b29258a0f7d5d7bf201]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1282432738 +0000
Message:

refs #294 resmon no support arbitrary json objects

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • configure.in

    rc380e91 refa9375  
    647647src/jlog/perl/Makefile.PL 
    648648src/udns/Makefile 
     649src/json-lib/Makefile 
    649650src/man/Makefile 
    650651src/modules/Makefile 
  • src/Makefile.in

    r68099ff refa9375  
    6767 
    6868NOIT_LIBS=udns/libudns.o noitedit/libnoitedit.a eventer/libeventer.a \ 
    69         jlog/libjlog.a utils/libnoit_utils.a 
     69        jlog/libjlog.a utils/libnoit_utils.a json-lib/libnoitjson.a 
    7070 
    7171STRATCON_OBJS=stratcond.o noit_listener.o \ 
     
    7979 
    8080STRATCON_LIBS=udns/libudns.o noitedit/libnoitedit.a eventer/libeventer.a \ 
    81         jlog/libjlog.a utils/libnoit_utils.a 
     81        jlog/libjlog.a utils/libnoit_utils.a json-lib/libnoitjson.a 
    8282 
    8383all:    noitd stratcond noit.conf test-noit.conf stratcon.conf test-stratcon.conf java-bits make-modules make-man 
     
    117117        @echo "- building utils bits" 
    118118        @(cd utils && make -s libnoit_utils.a) 
     119 
     120json-lib/libnoitjson.a: 
     121        @echo "- building json bits" 
     122        @(cd json-lib && make -s libnoitjson.a) 
    119123 
    120124man/noitd.usage.h:      make-man 
     
    132136                -Leventer -leventer \ 
    133137                utils/*.o \ 
     138                json-lib/*.o \ 
    134139                -Ljlog -ljlog \ 
    135140                -Lnoitedit -lnoitedit \ 
     
    145150                -Leventer -leventer \ 
    146151                utils/*.o \ 
     152                json-lib/*.o \ 
    147153                -Ljlog -ljlog \ 
    148154                -Lnoitedit -lnoitedit \ 
     
    253259        (cd noitedit && make clean) 
    254260        (cd utils && make clean) 
     261        (cd json-lib && make clean) 
    255262        (cd lua && make clean) 
    256263        (cd java && make clean) 
  • src/modules-lua/noit/module/resmon.lua

    r9f0fee7 refa9375  
    9090local HttpClient = require 'noit.HttpClient' 
    9191 
    92 function initiate(module, check) 
    93     local url = check.config.url or 'http:///' 
    94     local schema, host, uri = string.match(url, "^(https?)://([^/]*)(.+)$"); 
    95     local port 
    96     local use_ssl = false 
    97     local codere = noit.pcre(check.config.code or '^200$') 
    98     local good = false 
    99     local starttime = noit.timeval.now() 
    100  
    101     local user = check.config.auth_user or nil 
    102     local pass = check.config.auth_password or nil 
    103     local encoded = nil 
    104     if (user ~= nil and pass ~= nil) then 
    105         encoded = noit.base64_encode(user .. ':' .. pass) 
    106     end 
    107  
    108     -- assume the worst. 
    109     check.bad() 
    110     check.unavailable() 
    111  
    112     if host == nil then host = check.target end 
    113     if schema == nil then 
    114         schema = 'http' 
    115         uri = '/' 
    116     end 
    117     if schema == 'http' then 
    118         port = check.config.port or 81 
    119     elseif schema == 'https' then 
    120         port = check.config.port or 443 
    121         use_ssl = true 
    122     else 
    123         error(schema .. " not supported") 
    124     end  
    125  
    126     local output = '' 
    127  
    128     -- callbacks from the HttpClient 
    129     local callbacks = { } 
    130     callbacks.consume = function (str) output = output .. str end 
    131     local client = HttpClient:new(callbacks) 
    132     local rv, err = client:connect(check.target, port, use_ssl) 
    133     
    134     if rv ~= 0 then 
    135         check.status(err or "unknown error") 
    136         return 
    137     end 
    138  
    139     -- perform the request 
    140     local headers = {} 
    141     headers.Host = host 
    142     if encoded ~= nil then 
    143         headers["Authorization"] = "Basic " .. encoded 
    144     end 
    145     client:do_request("GET", uri, headers) 
    146     client:get_response() 
    147  
    148     -- parse the xml doc 
    149     local doc = noit.parsexml(output) 
    150     if doc == nil then 
    151         noit.log("error", "bad xml: %s", output) 
    152     end 
     92function json_metric(check, prefix, o) 
     93    local cnt = 1 
     94    if type(o) == "table" then 
     95        cnt = 0 
     96        for k, v in pairs(o) do 
     97            cnt = cnt + json_metric(check, prefix and (prefix .. '`' .. k) or k, v) 
     98        end 
     99    elseif type(o) == "string" then 
     100        check.metric_string(prefix, o) 
     101    elseif type(o) == "number" then 
     102        check.metric_double(prefix, o) 
     103    elseif type(o) == "boolean" then 
     104        check.metric_int32(prefix, o and 1 or 0) 
     105    end 
     106    return cnt 
     107end 
     108 
     109function json_to_metrics(check, doc) 
     110    local services = 0 
     111    check.available() 
     112    local data = doc:document() 
     113    services = json_metric(check, nil, data) 
     114    check.metric_uint32("services", services) 
     115    if services > 0 then check.good() else check.bad() end 
     116    check.status("services=" .. services) 
     117end 
     118 
     119function xml_to_metrics(check, doc) 
    153120    check.available() 
    154121 
     
    203170end 
    204171 
     172function initiate(module, check) 
     173    local url = check.config.url or 'http:///' 
     174    local schema, host, uri = string.match(url, "^(https?)://([^/]*)(.+)$"); 
     175    local port 
     176    local use_ssl = false 
     177    local codere = noit.pcre(check.config.code or '^200$') 
     178    local good = false 
     179    local starttime = noit.timeval.now() 
     180 
     181    local user = check.config.auth_user or nil 
     182    local pass = check.config.auth_password or nil 
     183    local encoded = nil 
     184    if (user ~= nil and pass ~= nil) then 
     185        encoded = noit.base64_encode(user .. ':' .. pass) 
     186    end 
     187 
     188    -- assume the worst. 
     189    check.bad() 
     190    check.unavailable() 
     191 
     192    if host == nil then host = check.target end 
     193    if schema == nil then 
     194        schema = 'http' 
     195        uri = '/' 
     196    end 
     197    if schema == 'http' then 
     198        port = check.config.port or 81 
     199    elseif schema == 'https' then 
     200        port = check.config.port or 443 
     201        use_ssl = true 
     202    else 
     203        error(schema .. " not supported") 
     204    end  
     205 
     206    local output = '' 
     207 
     208    -- callbacks from the HttpClient 
     209    local callbacks = { } 
     210    local hdrs_in = { } 
     211    callbacks.consume = function (str) output = output .. str end 
     212    callbacks.headers = function (t) hdrs_in = t end 
     213    local client = HttpClient:new(callbacks) 
     214    local rv, err = client:connect(check.target, port, use_ssl) 
     215    
     216    if rv ~= 0 then 
     217        check.status(err or "unknown error") 
     218        return 
     219    end 
     220 
     221    -- perform the request 
     222    local headers = {} 
     223    headers.Host = host 
     224    if encoded ~= nil then 
     225        headers["Authorization"] = "Basic " .. encoded 
     226    end 
     227    client:do_request("GET", uri, headers) 
     228    client:get_response() 
     229 
     230    local jsondoc = nil 
     231    if string.find(hdrs_in["content-type"] or '', 'json') ~= nil or 
     232       string.find(hdrs_in["content-type"] or '', 'javascript') ~= nil then 
     233        jsondoc = noit.parsejson(output) 
     234        if jsondoc == nil then 
     235            noit.log("error", "bad json: %s", output) 
     236            check.status("json parse error") 
     237            return 
     238        end 
     239    end 
     240 
     241    if jsondoc ~= nil then 
     242        json_to_metrics(check, jsondoc) 
     243        return 
     244    end 
     245 
     246    -- try xml by "default" (assuming no json-specific content header) 
     247 
     248    -- parse the xml doc 
     249    local doc = noit.parsexml(output) 
     250    if doc == nil then 
     251        jsondoc = noit.parsejson(output) 
     252        if jsondoc == nil then 
     253            noit.log("error", "bad xml: %s", output) 
     254            check.status("xml parse error") 
     255            return 
     256        end 
     257        json_to_metrics(check, jsondoc) 
     258        return 
     259    end 
     260     
     261    xml_to_metrics(check, doc) 
     262end 
     263 
  • src/modules/lua_noit.c

    rf365f50 refa9375  
    5757#include "utils/noit_b64.h" 
    5858#include "eventer/eventer.h" 
     59#include "json-lib/json.h" 
    5960#include "lua_noit.h" 
    6061 
     
    7778       return 1; \ 
    7879     } 
     80 
     81typedef struct { 
     82  struct json_tokener *tok; 
     83  struct json_object *root; 
     84} json_crutch; 
    7985 
    8086static void 
     
    16561662  return 0; 
    16571663} 
     1664 
     1665static int 
     1666noit_lua_json_tostring(lua_State *L) { 
     1667  int n; 
     1668  json_crutch **docptr; 
     1669  const char *jsonstring; 
     1670  n = lua_gettop(L); 
     1671  /* the first arg is implicitly self (it's a method) */ 
     1672  docptr = lua_touserdata(L, lua_upvalueindex(1)); 
     1673  if(docptr != lua_touserdata(L, 1)) 
     1674    luaL_error(L, "must be called as method"); 
     1675  if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1); 
     1676  jsonstring = json_object_to_json_string((*docptr)->root); 
     1677  lua_pushstring(L, jsonstring); 
     1678  /* jsonstring is freed with the root object later */ 
     1679  return 1; 
     1680} 
     1681static int 
     1682noit_json_object_to_luatype(lua_State *L, struct json_object *o) { 
     1683  if(!o) { 
     1684    lua_pushnil(L); 
     1685    return 1; 
     1686  } 
     1687  switch(json_object_get_type(o)) { 
     1688    case json_type_null: lua_pushnil(L); break; 
     1689    case json_type_object: 
     1690    { 
     1691      struct lh_table *lh; 
     1692      struct lh_entry *el; 
     1693      lh = json_object_get_object(o); 
     1694      lua_createtable(L, 0, lh->count); 
     1695      lh_foreach(lh, el) { 
     1696        noit_json_object_to_luatype(L, (struct json_object *)el->v); 
     1697        lua_setfield(L, -2, el->k); 
     1698      } 
     1699      break; 
     1700    } 
     1701    case json_type_string: lua_pushstring(L, json_object_get_string(o)); break; 
     1702    case json_type_boolean: lua_pushboolean(L, json_object_get_boolean(o)); break; 
     1703    case json_type_double: lua_pushnumber(L, json_object_get_double(o)); break; 
     1704    case json_type_int: lua_pushnumber(L, json_object_get_int(o)); break; 
     1705    case json_type_array: 
     1706    { 
     1707      int i, cnt; 
     1708      struct array_list *al; 
     1709      al = json_object_get_array(o); 
     1710      cnt = al ? array_list_length(al) : 0; 
     1711      lua_createtable(L, 0, cnt); 
     1712      for(i=0;i<cnt;i++) { 
     1713        noit_json_object_to_luatype(L, (struct json_object *)array_list_get_idx(al, i)); 
     1714        lua_rawseti(L, -2, i); 
     1715      } 
     1716      break; 
     1717    } 
     1718  } 
     1719  return 1; 
     1720} 
     1721static int 
     1722noit_lua_json_document(lua_State *L) { 
     1723  int n; 
     1724  json_crutch **docptr; 
     1725  n = lua_gettop(L); 
     1726  /* the first arg is implicitly self (it's a method) */ 
     1727  docptr = lua_touserdata(L, lua_upvalueindex(1)); 
     1728  if(docptr != lua_touserdata(L, 1)) 
     1729    luaL_error(L, "must be called as method"); 
     1730  if(n != 1) luaL_error(L, "expects no arguments, got %d", n - 1); 
     1731  return noit_json_object_to_luatype(L, (*docptr)->root); 
     1732} 
     1733static int 
     1734nl_parsejson(lua_State *L) { 
     1735  json_crutch **docptr, *doc; 
     1736  const char *in; 
     1737  size_t inlen; 
     1738 
     1739  if(lua_gettop(L) != 1) luaL_error(L, "parsejson requires one argument");  
     1740 
     1741  in = lua_tolstring(L, 1, &inlen); 
     1742  doc = calloc(1, sizeof(*doc)); 
     1743  doc->tok = json_tokener_new(); 
     1744  doc->root = json_tokener_parse_ex(doc->tok, in, inlen); 
     1745  if(is_error(doc->root)) { 
     1746    json_tokener_free(doc->tok); 
     1747    if(doc->root) json_object_put(doc->root); 
     1748    free(doc); 
     1749    lua_pushnil(L); 
     1750    return 1; 
     1751  } 
     1752 
     1753  docptr = (json_crutch **)lua_newuserdata(L, sizeof(doc));  
     1754  *docptr = doc; 
     1755  luaL_getmetatable(L, "noit.json"); 
     1756  lua_setmetatable(L, -2); 
     1757  return 1; 
     1758} 
     1759static int 
     1760noit_lua_json_gc(lua_State *L) { 
     1761  json_crutch **json; 
     1762  json = (json_crutch **)lua_touserdata(L,1); 
     1763  if((*json)->tok) json_tokener_free((*json)->tok); 
     1764  if((*json)->root) json_object_put((*json)->root); 
     1765  free(*json); 
     1766  return 0; 
     1767} 
     1768static int 
     1769noit_json_index_func(lua_State *L) { 
     1770  int n; 
     1771  const char *k; 
     1772  json_crutch **udata; 
     1773  n = lua_gettop(L); /* number of arguments */ 
     1774  assert(n == 2); 
     1775  if(!luaL_checkudata(L, 1, "noit.json")) { 
     1776    luaL_error(L, "metatable error, arg1 not a noit.json!"); 
     1777  } 
     1778  udata = lua_touserdata(L, 1); 
     1779  if(!lua_isstring(L, 2)) { 
     1780    luaL_error(L, "metatable error, arg2 not a string!"); 
     1781  } 
     1782  k = lua_tostring(L, 2); 
     1783  switch(*k) { 
     1784    case 'd': 
     1785     LUA_DISPATCH(document, noit_lua_json_document); 
     1786     break; 
     1787    case 't': 
     1788     LUA_DISPATCH(tostring, noit_lua_json_tostring); 
     1789     break; 
     1790    default: 
     1791     break; 
     1792  } 
     1793  luaL_error(L, "noit.json no such element: %s", k); 
     1794  return 0; 
     1795} 
    16581796static const luaL_Reg noitlib[] = { 
    16591797  { "sleep", nl_sleep }, 
     
    16731811  { "conf_get_number", nl_conf_get_float }, 
    16741812  { "parsexml", nl_parsexml }, 
     1813  { "parsejson", nl_parsejson }, 
    16751814  { NULL, NULL } 
    16761815}; 
     
    16991838  lua_pushcfunction(L, noit_lua_pcre_gc); 
    17001839  lua_setfield(L, -2, "__gc"); 
     1840 
     1841  luaL_newmetatable(L, "noit.json"); 
     1842  lua_pushcfunction(L, noit_lua_json_gc); 
     1843  lua_setfield(L, -2, "__gc"); 
     1844  luaL_newmetatable(L, "noit.json"); 
     1845  lua_pushcclosure(L, noit_json_index_func, 0); 
     1846  lua_setfield(L, -2, "__index"); 
    17011847 
    17021848  luaL_newmetatable(L, "noit.xmldoc");