blob: 624fb1f6e008d38d12bace3595e227398abc2971 [file] [log] [blame]
-- Copyright (c) 2015 Adobe Systems Incorporated. All rights reserved.
--
-- Permission is hereby granted, free of charge, to any person obtaining a
-- copy of this software and associated documentation files (the "Software"),
-- to deal in the Software without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Software, and to permit persons to whom the
-- Software is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.
-- Records the metrics for the current request.
--
-- # Sample StatsD messages
-- # pub.publisher_name.consumer.consumer_name.app.application_name.service.service_name.prod.region.useast.request.device_links.POST.200.count
-- # pub.publisher_name.consumer.consumer_name.app.application_name.service.service_name.prod.region.useast.request.device_links.POST.200.responseTime
-- # pub.publisher_name.consumer.consumer_name.app.application_name.service.service_name.prod.region.useast.request.device_links.POST.200.upstreamResponseTime
-- # pub.publisher_name.consumer.consumer_name.app.application_name.service.service_name.prod.region.useast.request.validate_request.GET.200.responseTime
--
-- NOTE: by default it logs the root-path of the request. If the root path is used for versioning ( i.e. v1.0 ) there is the property $metric_path that
-- can be set on the location block in order to override the root-path
--
-- Created by IntelliJ IDEA.
-- User: nramaswa
-- Date: 3/14/14
-- Time: 12:45 AM
-- To change this template use File | Settings | File Templates.
--
local MetricsCls = require "metrics.MetricsBuffer"
local metrics = MetricsCls:new()
local M = {}
function M:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
-- To replace . with _
local function normalizeString(input)
return input:gsub("%.", "_")
end
local function getPathForMetrics(serviceName)
local user_defined_path = ngx.var.metrics_path
if user_defined_path ~= nil and #user_defined_path < 2 then
user_defined_path = nil
end
local request_uri = user_defined_path or ngx.var.uri or "/" .. serviceName
local pattern = "(?:\\/?\\/?)([^\\/:]+)" -- To get the first part of the request uri excluding content after :
local requestPathFromURI, err = ngx.re.match(request_uri, pattern)
local requestPath = serviceName -- default value
if err then
ngx.log(ngx.WARN, "Assigned requestPath as serviceName due to error in extracting requestPathFromURI: ", err)
end
if requestPathFromURI then
if requestPathFromURI[1] then
requestPath = requestPathFromURI[1]
requestPath = requestPath:gsub("%.", "_")
--ngx.log(ngx.INFO, "\n the extracted requestPath::"..requestPath)
end
end
return requestPath
end
function M:logCurrentRequest()
-- Variables used in the bucket path
local publisherName = ngx.var.publisher_org_name or "undefined"
local consumerName = ngx.var.consumer_org_name or "undefined"
local appName = ngx.var.app_name or "undefined"
local serviceName = ngx.var.service_name or "undefined"
local realm = ngx.var.service_env or ngx.var.realm or "sandbox"
local requestMethod = ngx.var.request_method or "undefined"
local status = ngx.var.status or "0"
local validateRequestStatus = ngx.var.validate_request_status or "0"
-- Values for metrics - converted tonumber() later
local bucketCountValue = 1
local requestTime = tonumber(ngx.var.request_time) or -1
local upstreamResponseTime = tonumber(ngx.var.upstream_response_time) or -1
local validateTime = tonumber(ngx.var.validate_request_response_time) or -1
local rgnName = ngx.var.aws_region or "undefined"
local bytesSent = tonumber(ngx.var.bytes_sent) or -1
local bytesReceived = tonumber(ngx.var.request_length) or -1
-- ---------------------------------------------------------------------- --
-- ------------- Logging for all the requests --------------- --
-- ---------------------------------------------------------------------- --
local bucket = "publisher." .. normalizeString(publisherName) ..
".consumer." .. normalizeString(consumerName) ..
".application." .. normalizeString(appName) ..
".service." .. normalizeString(serviceName) ..
"." .. realm ..
".region." .. rgnName ..
".request.";
local validate_request_response_time = bucket .. "validate_request." .. validateRequestStatus .. ".responseTime";
local requestPath = getPathForMetrics(serviceName)
local bytes_sent = bucket .. "bytesSent";
local bytes_received = bucket .. "bytesReceived";
--bandwidth data - update only if its greater than zero to sum up all calls
if bytesSent > 0 then
metrics:count(bytes_sent, bytesSent)
end
if bytesReceived > 0 then
metrics:count(bytes_received, bytesReceived)
end
-- log validate timer entry only if its passed
if validateTime >= 0 then
metrics:timer(validate_request_response_time, validateTime)
end
-- ---------------------------------------------------------------------- --
-- ------------- Non-blocked requests related logging --------------- --
-- ---------------------------------------------------------------------- --
-- Choosing log buckets in statsd based on validation success/failure in the gateway
if (validateRequestStatus == "200" or validateRequestStatus == "0" or validateRequestStatus == 200 or validateRequestStatus == "na") then
local cc_bucket = bucket ..
requestPath .. "." ..
requestMethod .. "." .. status;
local cc_response_time = cc_bucket .. ".responseTime";
local cc_upstream_response_time = cc_bucket .. ".upstreamResponseTime";
local hit_count_for_bucket = cc_bucket .. ".count";
--increament the count for all the calls
metrics:count(hit_count_for_bucket, bucketCountValue)
-- timers
if requestTime >= 0 then
metrics:timer(cc_response_time, requestTime)
end
--timer data - update only if its greater than or = zero as its avging all calls
if upstreamResponseTime >= 0 then
metrics:timer(cc_upstream_response_time, upstreamResponseTime)
end
return
end
-- ---------------------------------------------------------------------- --
-- ------------- Blocked requests related logging --------------- --
-- ---------------------------------------------------------------------- --
local blocked_bucket = bucket .. "_blocked_"
local code_count_bucket = blocked_bucket .. "." .. validateRequestStatus .. ".count"
local bytes_sent_bucket = blocked_bucket .. ".bytesSent"
local bytes_received_bucket = blocked_bucket .. ".bytesReceived"
--increament the count for all the calls
metrics:count(code_count_bucket, bucketCountValue)
--bandwidth data - update only if its greater than zero to sum up all calls
if bytesSent > 0 then
metrics:count(bytes_sent_bucket, bytesSent)
end
if bytesReceived > 0 then
metrics:count(bytes_received_bucket, bytesReceived)
end
end
return M