Skip to content

Commit

Permalink
Merge pull request #251 from Mashape/http-logging
Browse files Browse the repository at this point in the history
Http logging
  • Loading branch information
thibaultcha committed May 21, 2015
2 parents 9d4799b + af31b0e commit e9dcaf3
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 2 deletions.
4 changes: 4 additions & 0 deletions kong-0.3.0-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ build = {
["kong.plugins.udplog.handler"] = "kong/plugins/udplog/handler.lua",
["kong.plugins.udplog.log"] = "kong/plugins/udplog/log.lua",
["kong.plugins.udplog.schema"] = "kong/plugins/udplog/schema.lua",

["kong.plugins.httplog.handler"] = "kong/plugins/httplog/handler.lua",
["kong.plugins.httplog.log"] = "kong/plugins/httplog/log.lua",
["kong.plugins.httplog.schema"] = "kong/plugins/httplog/schema.lua",

["kong.plugins.filelog.handler"] = "kong/plugins/filelog/handler.lua",
["kong.plugins.filelog.log"] = "kong/plugins/filelog/log.lua",
Expand Down
1 change: 1 addition & 0 deletions kong.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins_available:
- tcplog
- udplog
- filelog
- httplog
- cors
- request_transformer

Expand Down
15 changes: 15 additions & 0 deletions kong/plugins/httplog/handler.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local BasePlugin = require "kong.plugins.base_plugin"
local log = require "kong.plugins.httplog.log"

local HttpLogHandler = BasePlugin:extend()

function HttpLogHandler:new()
HttpLogHandler.super.new(self, "httplog")
end

function HttpLogHandler:log(conf)
HttpLogHandler.super.log(self)
log.execute(conf)
end

return HttpLogHandler
74 changes: 74 additions & 0 deletions kong/plugins/httplog/log.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
local cjson = require "cjson"
local url = require "socket.url"

local _M = {}

-- Generates http payload .
-- @param `method` http method to be used to send data
-- @param `parsed_url` contains the host details
-- @param `message` Message to be logged
-- @return `payload` http payload
local function generate_post_payload(method, parsed_url, message)
local body = cjson.encode(message);
local payload = string.format("%s %s HTTP/1.1\r\nHost: %s\r\nConnection: Keep-Alive\r\nContent-Type: application/json\r\nContent-Length: %s\r\n\r\n%s",
method:upper(), parsed_url.path, parsed_url.host, string.len(body), body)
return payload
end

-- Parse host url
-- @param `url` host url
-- @return `parsed_url` a table with host details like domain name, port, path etc
local function parse_url(host_url)
local parsed_url = url.parse(host_url)
if not parsed_url.port then
if parsed_url.scheme == "http" then
parsed_url.port = 80
elseif parsed_url.scheme == "https" then
parsed_url.port = 443
end
end
if not parsed_url.path then
parsed_url.path = "/"
end
return parsed_url
end

-- Log to a Http end point.
-- @param `premature`
-- @param `conf` Configuration table, holds http endpoint details
-- @param `message` Message to be logged
local function log(premature, conf, message)
local ok, err
local parsed_url = parse_url(conf.http_endpoint)
local host = parsed_url.host
local port = tonumber(parsed_url.port)

local sock = ngx.socket.tcp()
sock:settimeout(conf.timeout)

ok, err = sock:connect(host, port)
if not ok then
ngx.log(ngx.ERR, "failed to connect to "..host..":"..tostring(port)..": ", err)
return
end

ok, err = sock:send(generate_post_payload(conf.method, parsed_url, message).."\r\n")
if not ok then
ngx.log(ngx.ERR, "failed to send data to "..host..":"..tostring(port)..": ", err)
end

ok, err = sock:setkeepalive(conf.keepalive)
if not ok then
ngx.log(ngx.ERR, "failed to keepalive to "..host..":"..tostring(port)..": ", err)
return
end
end

function _M.execute(conf)
local ok, err = ngx.timer.at(0, log, conf, ngx.ctx.log_message)
if not ok then
ngx.log(ngx.ERR, "failed to create timer: ", err)
end
end

return _M
6 changes: 6 additions & 0 deletions kong/plugins/httplog/schema.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
return {
http_endpoint = { required = true, type = "string" },
method = { default = "POST", enum = { "POST", "PUT", "PATCH" } },
timeout = { default = 10000, type = "number" },
keepalive = { default = 60000, type = "number" }
}
4 changes: 2 additions & 2 deletions spec/integration/cli/start_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ describe("CLI", function()
}
}

replace_conf_property("plugins_available", {"ssl", "keyauth", "basicauth", "tcplog", "udplog", "filelog", "request_transformer"})
replace_conf_property("plugins_available", {"ssl", "keyauth", "basicauth", "tcplog", "udplog", "filelog", "httplog", "request_transformer"})

assert.has_error(function()
spec_helper.start_kong(SERVER_CONF, true)
end, "You are using a plugin that has not been enabled in the configuration: ratelimiting")
end)

it("should work the used plugins are enabled", function()
replace_conf_property("plugins_available", {"ssl", "keyauth", "basicauth", "tcplog", "udplog", "filelog", "request_transformer", "ratelimiting", "cors"})
replace_conf_property("plugins_available", {"ssl", "keyauth", "basicauth", "tcplog", "udplog", "filelog", "httplog", "request_transformer", "ratelimiting", "cors"})

local _, exit_code = spec_helper.start_kong(SERVER_CONF, true)
assert.are.same(0, exit_code)
Expand Down
20 changes: 20 additions & 0 deletions spec/plugins/logging_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ local TEST_CONF = "kong_TEST.yml"

local TCP_PORT = 7777
local UDP_PORT = 8888
local HTTP_PORT = 8989

describe("Logging Plugins", function()

Expand All @@ -26,6 +27,7 @@ describe("Logging Plugins", function()
plugin_configuration = {
{ name = "tcplog", value = { host = "127.0.0.1", port = 7777 }, __api = 1 },
{ name = "udplog", value = { host = "127.0.0.1", port = 8888 }, __api = 1 },
{ name = "httplog", value = { http_endpoint = "http://localhost:"..HTTP_PORT, method = "POST"}, __api = 1 },
{ name = "filelog", value = {}, __api = 1 }
}
}
Expand Down Expand Up @@ -73,6 +75,24 @@ describe("Logging Plugins", function()
assert.are.same("127.0.0.1", log_message.ip)
end)

it("should log to Http", function()
local thread = spec_helper.start_http_server(HTTP_PORT) -- Starting the mock TCP server

-- Making the request
local _, status = http_client.get(STUB_GET_URL, nil, { host = "logging.com" })
assert.are.equal(200, status)

-- Getting back the TCP server input
local ok, res = thread:join()
assert.truthy(ok)
assert.truthy(res)

-- Making sure it's alright
assert.are.same("POST / HTTP/1.1", res[1])
local log_message = cjson.decode(res[7])
assert.are.same("127.0.0.1", log_message.ip)
end)

it("should log to file", function()
local uuid = string.gsub(uuid(), "-", "")

Expand Down
34 changes: 34 additions & 0 deletions spec/spec_helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,40 @@ function _M.start_tcp_server(port, ...)
return thread
end


-- Starts a HTTP server
-- @param `port` The port where the server will be listening to
-- @return `thread` A thread object
function _M.start_http_server(port, ...)
local thread = Threads.new({
function(port)
local socket = require "socket"
local server = assert(socket.bind("*", port))
local client = server:accept()
local lines = {}
local count = 1
local line, err = nil, nil
while true do
line, err = client:receive()
if not err then
lines[count] = line
line = nil
if count == 7 then
client:send("ok" .. "\n")
break
end
count = count + 1;
end
end
client:close()
return lines
end;
}, port)

thread:start(...)
return thread
end

-- Starts a UDP server
-- @param `port` The port where the server will be listening to
-- @return `thread` A thread object
Expand Down
1 change: 1 addition & 0 deletions spec/unit/statics_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ plugins_available:
- tcplog
- udplog
- filelog
- httplog
- cors
- request_transformer
Expand Down

0 comments on commit e9dcaf3

Please sign in to comment.