diff --git a/README.md b/README.md index 696427f..d4f87a5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,23 @@ -Boundary MongoDB Plugin ------------------------ +# Boundary MongoDB Plugin + Collects metrics from a MongoDB server instance. MongoDB statistics are pulled via a REST API call. See video [walkthrough](https://help.boundary.com/hc/articles/201842211). -### Prerequisites +## Prerequisites + +### Supported OS | OS | Linux | Windows | SmartOS | OS X | |:----------|:-----:|:-------:|:-------:|:----:| | Supported | v | v | v | v | +##### The statistics are pulled from http://hostname:(port+1000)/_status. If you did not change the MongoDB default port, we will use 28107. + +#### Boundary Meter Versions V4.0 Or Later + +- To install new meter go to Settings->Installation or [see instructons|https://help.boundary.com/hc/en-us/sections/200634331-Installation]. +- To upgrade the meter to the latest version - [see instructons|https://help.boundary.com/hc/en-us/articles/201573102-Upgrading-the-Boundary-Meter]. + +#### For Boundary Meter less than V4.0 | Runtime | node.js | Python | Java | |:---------|:-------:|:------:|:----:| @@ -27,7 +37,9 @@ The statistics are pulled from http://hostname:(port+1000)/_status. If you did 3. If after enabling the Mongo REST interface, you are still unable to collect information from the REST interface and if you are polling remotely, ensure that the port that is serving the Mongo REST interfaces is open. You can bypasss any firewall restrictions by running locally where the MongoDB is running. -#### Plugin Configuration Fields +### Plugin Configuration Fields + +#### For All Versions |Field Name|Description | |:---------|:---------------------------------------------------------------------------------------------------------------------| @@ -39,7 +51,7 @@ The statistics are pulled from http://hostname:(port+1000)/_status. If you did ### Metrics Collected -Tracks the following metrics for [MongoDB](http://www.mongodb.org/) +#### For All Versions |Metric Name |Description | |:----------------------|:--------------------------------------------------------------------| @@ -59,3 +71,8 @@ Tracks the following metrics for [MongoDB](http://www.mongodb.org/) |Mongo deletes |The number of mongo delete operations | |Mongo getmore |The number of mongo getmore operations | |Mongo commands |The number of mongo commands issued | + +### References + +Tracks the following metrics for [MongoDB](http://www.mongodb.org/) + diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..ae4a7e3 --- /dev/null +++ b/init.lua @@ -0,0 +1,125 @@ +local boundary = require("boundary") +local os = require("os") +local timer = require("timer") +local http = require("http") +local json = require("json") +local fs = require("fs") + +-- set default parameters if not found in param.json +local param = boundary.param or { + source = os.hostname, + pollInterval = 5000, + hostname = "127.0.0.1", + port = "28017" +} + +-- lookup +-- use an array of attrs to drill down through nested tables to retrieve a value +function lookup(table, attrs) + local v = table; + for i, a in ipairs(attrs) do + v = v[a] + end + return v +end + +-- fnFactory returns a function(current, previous) that when called +-- will output the metric string ready for printing +-- name - name of metric +-- func - type of metric (diff, cur or ratio) +-- format - printf type format specifier for the result eg "%d" +-- params - parameters specific to build the required function +function fnFactory(name, func, format, params) + local mask = "MONGO_" .. name .. " " .. format .. " %s\n" + local str = function(v) return string.format(mask, v, param.source) end + + return ({ + -- diff calculates the difference between a current and previous values + diff = function (attrs, scale) + return function (c, p) + return str((scale or 1) * lookup(c, attrs) - lookup(p, attrs)) + end + end, + -- cur returns a current value + cur = function (attrs, scale) + return function (c) + return str((scale or 1) * lookup(c, attrs)) + end + end, + -- ratio takes values a and b from the current data and returns a/b + ratio = function (attrs1, attrs2, scale) + return function (c) + return str((scale or 1) * lookup(c, attrs1) / lookup(c, attrs2)) + end + end, + -- split takes values a and b from the current data and returns a/(a+b) + split = function (attrs1, attrs2, scale) + return function (c) + local a = lookup(c, attrs1) + return str((scale or 1) * a / (a + lookup(c, attrs2))) + end + end + })[func](unpack(params)) +end + +-- build a table of functions to convert metrics into strings +local conversions = {} +for i, v in ipairs({ + {"BTREE_ACCESSES", "diff", "%d", {{"indexCounters", "accesses"}}}, + {"BTREE_HITS", "diff", "%d", {{"indexCounters", "hits"}}}, + {"BTREE_MISSES", "diff", "%d", {{"indexCounters", "misses"}}}, + {"BTREE_RESETS", "diff", "%d", {{"indexCounters", "resets"}}}, + {"BTREE_MISS_RATIO", "diff", "%d", {{"indexCounters", "missRatio"}}}, + {"CONNECTIONS", "cur", "%d", {{"connections", "current"}}}, + {"CONNECTIONS_AVAILABLE", "cur", "%d", {{"connections", "available"}}}, + {"CONNECTION_LIMIT", "split", "%f", {{"connections", "current"}, {"connections", "available"}}}, + {"GLOBAL_LOCK", "ratio", "%f", {{"globalLock", "lockTime"}, {"globalLock", "totalTime"}}}, + {"MEM_RESIDENT", "cur", "%d", {{"mem", "resident"}, 1024*1024}}, + {"MEM_VIRTUAL", "cur", "%d", {{"mem", "virtual"}, 1024*1024}}, + {"MEM_MAPPED", "cur", "%d", {{"mem", "mapped"}, 1024*1024}}, + {"OPS_INSERTS", "diff", "%d", {{"opcounters", "insert"}}}, + {"OPS_QUERY", "diff", "%d", {{"opcounters", "query"}}}, + {"OPS_UPDATE", "diff", "%d", {{"opcounters", "update"}}}, + {"OPS_DELETE", "diff", "%d", {{"opcounters", "delete"}}}, + {"OPS_GETMORE", "diff", "%d", {{"opcounters", "getmore"}}}, + {"OPS_COMMAND", "diff", "%d", {{"opcounters", "command"}}} +}) do + table.insert(conversions, fnFactory(table.unpack(v))) +end + +print("_bevent:Boundary MongoDB plugin up : version 1.0|t:info|tags:lua,mongodb,plugin") + +local previous; + +-- poll the server every pollInterval and use the +-- conversion functions to extract relevent data +timer.setInterval(param.pollInterval, function () + local data = "" + local req = http.request({ + host = param.hostname, + port = param.port, + path = "/_status" + }, function (res) + res:on("end", function () + current = json.parse(data).serverStatus + if (previous) then + local t = {} + for i, f in ipairs(conversions) do + table.insert(t, f(current, previous)) + end + fs.writeSync(1, -1, table.concat(t)) + end + previous = current + res:destroy() + end) + res:on("data", function (chunk) data = data .. chunk end) + res:on("error", function (err) end) + end) + req:on("error", function(err) + msg = tostring(err) + process.stderr:write("Error while sending a request: " .. msg) + end) + + req:done() +end) + diff --git a/metrics.json b/metrics.json new file mode 100644 index 0000000..1d6d25f --- /dev/null +++ b/metrics.json @@ -0,0 +1,149 @@ +{ + "result": [ + { + "name": "MONGO_BTREE_ACCESSES", + "displayName": "MongoDB Index Accesses", + "description": "Number of times that database operations have accessed indexes.", + "unit": "number", + "displayNameShort": "MongoDB Accesses", + "defaultAggregate": "count" + }, + { + "name": "MONGO_BTREE_HITS", + "displayName": "MongoDB Index Accesses from Memory", + "description": "Number of index accesses from memory.", + "unit": "number", + "displayNameShort": "MongoDB Hits", + "defaultAggregate": "count" + }, + { + "name": "MONGO_BTREE_MISSES", + "displayName": "MongoDB Index Accesses from Store", + "description": "Number of index accesses requiring indexes to be loaded.", + "unit": "number", + "displayNameShort": "MongoDB Misses", + "defaultAggregate": "count" + }, + { + "name": "MONGO_BTREE_RESETS", + "displayName": "MongoDB Index Counter Resets", + "description": "Number of times that the index counters were reset.", + "unit": "number", + "displayNameShort": "MongoDB Resets", + "defaultAggregate": "count" + }, + { + "name": "MONGO_BTREE_MISS_RATIO", + "displayName": "MongoDB Ratio of Index Hits to Index Misses", + "description": "Ratio of hits to misses.", + "unit": "ratio", + "displayNameShort": "MongoDB Miss Ratio", + "defaultAggregate": "ratio" + }, + { + "name": "MONGO_CONNECTIONS", + "displayName": "MongoDB Client Connection Count", + "description": "Number of active client connections to the database.", + "unit": "number", + "displayNameShort": "MongoDB Connections", + "defaultAggregate": "count" + }, + { + "name": "MONGO_CONNECTIONS_AVAILABLE", + "displayName": "MongoDB Client Connection Available", + "description": "Number of unused client connections to the database.", + "unit": "number", + "displayNameShort": "MongoDB Connections Available", + "defaultAggregate": "count" + }, + { + "name": "MONGO_CONNECTION_LIMIT", + "displayName": "MongoDB Client Connection Limit", + "description": "Ratio of client connections to total available connections.", + "unit": "ratio", + "displayNameShort": "MongoDB Connection Limit", + "defaultAggregate": "ratio" + }, + { + "name": "MONGO_GLOBAL_LOCK", + "displayName": "MongoDB Global Lock Ratio", + "description": "Ratio of time locked to time running.", + "unit": "ratio", + "displayNameShort": "MongoDB Lock", + "defaultAggregate": "ratio" + }, + { + "name": "MONGO_MEM_RESIDENT", + "displayName": "MongoDB RAM Usage", + "description": "Number of bytes of RAM used.", + "unit": "number", + "displayNameShort": "MongoDB RAM", + "defaultAggregate": "number" + }, + { + "name": "MONGO_MEM_VIRTUAL", + "displayName": "MongoDB Virtual Memory Usage", + "description": "Number of bytes of virtual memory used.", + "unit": "number", + "displayNameShort": "MongoDB Vmem", + "defaultAggregate": "number" + }, + { + "name": "MONGO_MEM_MAPPED", + "displayName": "MongoDB Mapped Memory Usage", + "description": "Number of bytes of mapped memory used.", + "unit": "number", + "displayNameShort": "MongoDB Mmem", + "defaultAggregate": "number" + }, + { + "name": "MONGO_OPS_INSERTS", + "displayName": "MongoDB Insert Operation Count", + "description": "Count of insert operations.", + "unit": "number", + "displayNameShort": "MongoDB Insert", + "defaultAggregate": "number" + }, + { + "name": "MONGO_OPS_QUERY", + "displayName": "MongoDB Query Operation Count", + "description": "Count of query operations.", + "unit": "number", + "displayNameShort": "MongoDB Querie", + "defaultAggregate": "number" + }, + { + "name": "MONGO_OPS_UPDATE", + "displayName": "MongoDB Update Operation Count", + "description": "Count of update operations.", + "unit": "number", + "displayNameShort": "MongoDB Update", + "defaultAggregate": "number" + }, + { + "name": "MONGO_OPS_DELETE", + "displayName": "MongoDB Delete Operation Count", + "description": "Count of delete operations.", + "unit": "number", + "displayNameShort": "MongoDB Delete", + "defaultAggregate": "number" + }, + { + "name": "MONGO_OPS_GETMORE", + "displayName": "MongoDB GetMore Operation Count", + "description": "Count of getmore operations.", + "unit": "number", + "displayNameShort": "MongoDB GetMore", + "defaultAggregate": "number" + }, + { + "name": "MONGO_OPS_COMMAND", + "displayName": "MongoDB Command Operation Count", + "description": "Count of command operations.", + "unit": "number", + "displayNameShort": "MongoDB Command", + "defaultAggregate": "number" + } + ] +} + diff --git a/plugin.json b/plugin.json index 8548e5a..31e6847 100644 --- a/plugin.json +++ b/plugin.json @@ -2,12 +2,16 @@ "description" : "Displays important mongodb metrics", "icon" : "icon.png", "command" : "node index.js", + "command_lua": "boundary-meter init.lua", "postExtract" : "npm install", + "postExtract_lua" : "", "ignore" : "node_modules", "metrics" : [ + "MONGO_BTREE_ACCESSES", "MONGO_BTREE_HITS", "MONGO_BTREE_MISSES", + "MONGO_BTREE_RESETS", "MONGO_BTREE_MISS_RATIO", "MONGO_CONNECTIONS", "MONGO_CONNECTIONS_AVAILABLE", @@ -58,6 +62,14 @@ "description" : "(optional) Pasword to access MongoDB", "type" : "password" }, + { + "title": "Poll Time (sec)", + "name": "pollInterval", + "description": "The Poll Interval to call the command. Defaults 5 seconds", + "type": "string", + "default": 5000, + "required": false + }, { "title" : "Source", "name" : "source",