mirror of
https://github.com/ntop/ntopng.git
synced 2026-06-01 22:42:06 +00:00
Top Talkers and Top applications can be retrieved via MySQL both interface-wide and per-host. A couple of tabs, namely "Top Talkers" and "Top Applications" become available in the historical page of interfaces and hosts. Upon focus of each tab, an ajax request is triggered and data is fetched from MySQL. TODO: interface wide top-talkers are retrieved from sqlite and need to be moved to mysql.
284 lines
8.3 KiB
Lua
284 lines
8.3 KiB
Lua
--
|
|
-- (C) 2013-15 - ntop.org
|
|
--
|
|
|
|
dirs = ntop.getDirs()
|
|
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
|
|
|
|
require "top_talkers"
|
|
require "json"
|
|
|
|
local top_talkers_intf = {}
|
|
|
|
if(ntop.isPro()) then
|
|
package.path = dirs.installdir .. "/pro/scripts/lua/modules/top_scripts/?.lua;" .. package.path
|
|
local new = require("top_aggregate")
|
|
if(type(new) ~= "table") then new = {} end
|
|
-- Add pro methods to local method table
|
|
for k,v in pairs(new) do
|
|
top_talkers_intf[k] = v
|
|
end
|
|
end
|
|
|
|
local function getTopTalkers(ifid, ifname)
|
|
return getCurrentTopTalkers(ifid, ifname, nil, nil, true, nil, nil,
|
|
top_talkers_intf.uniqueKey)
|
|
end
|
|
|
|
local function getTopTalkersBy(ifid, ifname, filter_col, filter_val)
|
|
return getCurrentTopTalkers(ifid, ifname, filter_col, filter_val, true, nil, nil,
|
|
top_talkers_intf.uniqueKey)
|
|
end
|
|
|
|
local function getTopTalkersClean(ifid, ifname, param)
|
|
top = getCurrentTopTalkers(ifid, ifname, nil, nil, false, param, true,
|
|
top_talkers_intf.uniqueKey)
|
|
section_beginning = string.find(top, '%[')
|
|
if(section_beginning == nil) then
|
|
return("[ ]\n")
|
|
else
|
|
return(string.sub(top, section_beginning))
|
|
end
|
|
end
|
|
|
|
local function printTopTalkersTable(tbl)
|
|
local rsp = "{\n"
|
|
|
|
for i,v in pairs(tbl) do
|
|
local outouterlooped = 0
|
|
for dk,dv in pairs(v) do
|
|
rsp = rsp..'"'..dk..'": [\n'
|
|
local keys = getKeys(dv, "value")
|
|
local outerlooped = 0
|
|
for tv,tk in pairsByKeys(keys, rev) do
|
|
rv = dv[tk]
|
|
rsp = rsp.."{ "
|
|
local looped = 0
|
|
for k,v in pairs(rv) do
|
|
rsp = rsp..'"'..k..'": '
|
|
if(k == "value") then
|
|
rsp = rsp..tostring(v)
|
|
else
|
|
rsp = rsp..'"'..v..'"'
|
|
end
|
|
rsp = rsp..", "
|
|
looped = looped + 1
|
|
end
|
|
if(looped > 0) then
|
|
rsp = string.sub(rsp, 1, -3)
|
|
end
|
|
rsp = rsp.."},\n"
|
|
outerlooped = outerlooped + 1
|
|
end
|
|
if(outerlooped > 0) then
|
|
rsp = string.sub(rsp, 1, -3)
|
|
end
|
|
rsp = rsp.."],\n"
|
|
outouterlooped = outouterlooped + 1
|
|
end
|
|
if(outouterlooped > 0) then
|
|
rsp= string.sub(rsp, 1, -3)
|
|
end
|
|
end
|
|
|
|
rsp = rsp.."\n}"
|
|
|
|
return rsp
|
|
|
|
end
|
|
|
|
local function topTalkersSectionInTableOP(tblarray, arithOp)
|
|
local ret = {}
|
|
local outer_cnt = 1
|
|
local num_glob = 1
|
|
|
|
for _,tbl in pairs(tblarray) do
|
|
for _,outer in pairs(tbl) do
|
|
if(ret[outer_cnt] == nil) then ret[outer_cnt] = {} end
|
|
for key, value in pairs(outer) do
|
|
for _,record in pairs(value) do
|
|
local found = false
|
|
if(ret[outer_cnt][key] == nil) then ret[outer_cnt][key] = {} end
|
|
for _,el in pairs(ret[outer_cnt][key]) do
|
|
if(found == false and el["address"] == record["address"]) then
|
|
el["value"] = arithOp(el["value"], record["value"])
|
|
found = true
|
|
end
|
|
end
|
|
if(found == false) then
|
|
ret[outer_cnt][key][num_glob] = record
|
|
num_glob = num_glob + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
local function getTopTalkersFromJSONDirection(table, wantedDir, add_vlan)
|
|
local elements = ""
|
|
|
|
-- For each VLAN, get hosts and concatenate them
|
|
for i,vlan in pairs(table["vlan"]) do
|
|
local vlanid = vlan["label"]
|
|
local vlanname = vlan["name"]
|
|
-- XXX hosts is an array of (senders, receivers) pairs?
|
|
for i2,hostpair in pairs(vlan[top_talkers_intf.JSONkey]) do
|
|
-- hostpair is { "senders": [...], "receivers": [...] }
|
|
for k2,direction in pairs(hostpair) do
|
|
-- direction is "senders": [...] or "receivers": [...]
|
|
if(k2 ~= wantedDir) then goto continue end
|
|
-- scan hosts
|
|
for i2,host in pairs(direction) do
|
|
-- host is { "label": ..., "value": ..., "url": ... }
|
|
elements = elements.."{ "
|
|
local n_el = 0
|
|
for k3,v3 in pairs(host) do
|
|
elements = elements..'"'..k3..'": '
|
|
if(k3 == "value") then
|
|
elements = elements..tostring(v3)
|
|
else
|
|
elements = elements..'"'..v3..'"'
|
|
end
|
|
elements = elements..", "
|
|
n_el = n_el + 1
|
|
end
|
|
if(add_vlan ~= nil) then
|
|
elements = elements..'"vlanm": "'..vlanname..'", '
|
|
elements = elements..'"vlan": "'..vlanid..'", '
|
|
end
|
|
if(n_el ~= 0) then
|
|
elements = string.sub(elements, 1, -3)
|
|
end
|
|
elements = elements.." },\n"
|
|
end
|
|
::continue::
|
|
end
|
|
end
|
|
end
|
|
|
|
return elements
|
|
end
|
|
|
|
local function printTopTalkersFromTable(table, add_vlan)
|
|
if(table == nil or table["vlan"] == nil) then return "[ ]\n" end
|
|
|
|
local elements = "{\n"
|
|
elements = elements..'"senders": [\n'
|
|
local result = getTopTalkersFromJSONDirection(table, "senders", add_vlan)
|
|
if(result ~= "") then
|
|
result = string.sub(result, 1, -3) --remove comma
|
|
end
|
|
elements = elements..result
|
|
elements = elements.."],\n"
|
|
elements = elements..'"receivers": [\n'
|
|
result = getTopTalkersFromJSONDirection(table, "receivers", add_vlan)
|
|
if(result ~= "") then
|
|
result = string.sub(result, 1, -3) --remove comma
|
|
end
|
|
elements = elements..result
|
|
elements = elements.."]\n"
|
|
elements = elements.."}\n"
|
|
|
|
return elements
|
|
end
|
|
|
|
local function getTopTalkersFromJSON(content, add_vlan)
|
|
if(content == nil) then return("[ ]\n") end
|
|
local table = parseJSON(content)
|
|
local rsp = printTopTalkersFromTable(table, add_vlan)
|
|
if(rsp == nil or rsp == "") then return "[ ]\n" end
|
|
return rsp
|
|
end
|
|
|
|
local function getHistoricalTopTalkers(ifid, ifname, epoch, add_vlan)
|
|
if(epoch == nil) then
|
|
return("[ ]\n")
|
|
end
|
|
|
|
res = ntop.getMinuteSampling(ifid, tonumber(epoch))
|
|
return getTopTalkersFromJSON(res, add_vlan)
|
|
end
|
|
|
|
local function getHistoricalTopTalkersInInterval(ifid, ifname, epoch_start, epoch_end, add_vlan)
|
|
local json = require ("dkjson")
|
|
if epoch_start == nil or epoch_end == nil or epoch_start == "" or epoch_end == "" then
|
|
return json.encode({}, nil)
|
|
end
|
|
|
|
local query = ntop.getMinuteSamplingsInterval(ifid, tonumber(epoch_start), tonumber(epoch_end))
|
|
-- sum up the selected 1-minute top talker statistics to have an aggregated 'top'
|
|
-- please keep in mind that this is an approximation of the real top talkers
|
|
-- the resulting table will be like the following
|
|
--[[
|
|
table
|
|
senders table
|
|
senders.216.58.210.238 number 7743
|
|
senders.173.194.112.169 number 2586
|
|
...
|
|
receivers table
|
|
receivers.216.58.210.238 number 5281
|
|
receivers.173.194.112.169 number 3093
|
|
...
|
|
--]]
|
|
local res = {["senders"] = {}, ["receivers"] = {}}
|
|
for record,_ in pairs(query) do
|
|
record = parseJSON(record)
|
|
if not record or not next(record) or not record["vlan"] then goto next_record end
|
|
-- tprint(record)
|
|
for _, vlan in pairs(record["vlan"]) do
|
|
local vlanid = vlan["label"]
|
|
local vlanname = vlan["name"]
|
|
-- TODO: handle vlans
|
|
if not vlan["hosts"] then goto next_vlan end
|
|
for _, host_pair in pairs(vlan["hosts"]) do
|
|
for direction, top_hosts in pairs(host_pair) do
|
|
for _, host in pairs(top_hosts) do
|
|
local label = host["address"]
|
|
local traffic = tonumber(host["value"])
|
|
if label == nil then label = "" end
|
|
if traffic == nil then traffic = 0 end
|
|
if res[direction][label] == nil then
|
|
res[direction][label] = traffic
|
|
else
|
|
res[direction][label] = res[direction][label] + traffic
|
|
end
|
|
end
|
|
end
|
|
end
|
|
::next_vlan::
|
|
end
|
|
::next_record::
|
|
end
|
|
-- tprint(res)
|
|
-- reformat the output so that it becomes easier to parse
|
|
local pretty_res = {}
|
|
for direction, hosts in pairs(res) do
|
|
local t = {}
|
|
for addr, traffic in pairs(hosts) do
|
|
table.insert(pretty_res, {["addr"] = addr, ["bytes"] = traffic, ["direction"] = direction})
|
|
end
|
|
end
|
|
res = pretty_res
|
|
return res
|
|
end
|
|
|
|
top_talkers_intf.name = "Top Talkers"
|
|
top_talkers_intf.infoScript = "host_details.lua"
|
|
top_talkers_intf.infoScriptKey = "host"
|
|
top_talkers_intf.key = "host"
|
|
top_talkers_intf.JSONkey = "hosts"
|
|
top_talkers_intf.uniqueKey = "top_talkers"
|
|
top_talkers_intf.getTop = getTopTalkers
|
|
top_talkers_intf.getTopBy = getTopTalkersBy
|
|
top_talkers_intf.getTopClean = getTopTalkersClean
|
|
top_talkers_intf.getTopFromJSON = getTopTalkersFromJSON
|
|
top_talkers_intf.printTopTable = printTopTalkersTable
|
|
top_talkers_intf.getHistoricalTop = getHistoricalTopTalkers
|
|
top_talkers_intf.getHistoricalTopInInterval = getHistoricalTopTalkersInInterval
|
|
top_talkers_intf.topSectionInTableOp = topTalkersSectionInTableOP
|
|
top_talkers_intf.numLevels = 2
|
|
|
|
return top_talkers_intf
|