Stackdriver logging

When the environment variable STACKDRIVER_LOGGING is set to true, send
request logs in a format that Stackdriver knows how to interpret. Also,
set the log level accordint to the status code. 4xx responses are logged
as warnings and 5xx responses are logged as errors.
This commit is contained in:
Eric Mc Sween 2019-10-24 22:02:55 -04:00
parent a7117731bf
commit 166211b278
3 changed files with 92 additions and 40 deletions

View file

@ -1,29 +1,55 @@
os = require("os") os = require("os")
yn = require("yn")
STACKDRIVER_LOGGING = yn(process.env['STACKDRIVER_LOGGING'])
module.exports.monitor = (logger) -> module.exports.monitor = (logger) ->
return (req, res, next) -> return (req, res, next) ->
Metrics = require("./metrics") Metrics = require("./metrics")
startTime = new Date() startTime = process.hrtime()
end = res.end end = res.end
res.end = () -> res.end = () ->
end.apply(this, arguments) end.apply(this, arguments)
responseTime = new Date() - startTime responseTime = process.hrtime(startTime)
responseTimeMs = Math.round(responseTime[0] * 1000 + responseTime[1] / 1000)
if req.route?.path? if req.route?.path?
routePath = req.route.path.toString().replace(/\//g, '_').replace(/\:/g, '').slice(1) routePath = req.route.path.toString().replace(/\//g, '_').replace(/\:/g, '').slice(1)
Metrics.timing("http_request", responseTime, null, {method:req.method, status_code: res.statusCode, path:routePath}) Metrics.timing("http_request", responseTimeMs, null, {method:req.method, status_code: res.statusCode, path:routePath})
logger.log remoteIp = req.ip || req.socket?.socket?.remoteAddress || req.socket?.remoteAddress
req: reqUrl = req.originalUrl || req.url
url: req.originalUrl || req.url referrer = req.headers['referer'] || req.headers['referrer']
method: req.method if STACKDRIVER_LOGGING
referrer: req.headers['referer'] || req.headers['referrer'] info =
"remote-addr": req.ip || req.socket?.socket?.remoteAddress || req.socket?.remoteAddress httpRequest:
"user-agent": req.headers["user-agent"] requestMethod: req.method
"content-length": req.headers["content-length"] requestUrl: reqUrl
res: requestSize: req.headers["content-length"]
"content-length": res._headers?["content-length"] status: res.statusCode
statusCode: res.statusCode responseSize: res._headers?["content-length"]
"response-time": responseTime userAgent: req.headers["user-agent"]
"http request" remoteIp: remoteIp
referer: referrer
latency:
seconds: responseTime[0]
nanos: responseTime[1]
protocol: req.protocol
else
info =
req:
url: reqUrl
method: req.method
referrer: referrer
"remote-addr": remoteIp
"user-agent": req.headers["user-agent"]
"content-length": req.headers["content-length"]
res:
"content-length": res._headers?["content-length"]
statusCode: res.statusCode
"response-time": responseTimeMs
if res.statusCode >= 500
logger.error(info, "%s %s", req.method, reqUrl)
else if res.statusCode >= 400 and res.statusCode < 500
logger.warn(info, "%s %s", req.method, reqUrl)
else
logger.info(info, "%s %s", req.method, reqUrl)
next() next()

View file

@ -7,13 +7,14 @@
"url": "https://github.com/sharelatex/metrics-sharelatex.git" "url": "https://github.com/sharelatex/metrics-sharelatex.git"
}, },
"dependencies": { "dependencies": {
"@google-cloud/debug-agent": "^3.0.0",
"@google-cloud/profiler": "^0.2.3",
"@google-cloud/trace-agent": "^3.2.0",
"coffee-script": "1.6.0", "coffee-script": "1.6.0",
"lynx": "~0.1.1", "lynx": "~0.1.1",
"prom-client": "^11.1.3", "prom-client": "^11.1.3",
"underscore": "~1.6.0", "underscore": "~1.6.0",
"@google-cloud/debug-agent": "^3.0.0", "yn": "^3.1.1"
"@google-cloud/profiler": "^0.2.3",
"@google-cloud/trace-agent": "^3.2.0"
}, },
"devDependencies": { "devDependencies": {
"bunyan": "^1.0.0", "bunyan": "^1.0.0",

View file

@ -1,31 +1,56 @@
os = require("os") os = require("os")
yn = require("yn")
STACKDRIVER_LOGGING = yn(process.env['STACKDRIVER_LOGGING'])
module.exports.monitor = (logger) -> module.exports.monitor = (logger) ->
return (req, res, next) -> return (req, res, next) ->
Metrics = require("./metrics") Metrics = require("./metrics")
startTime = new Date() startTime = process.hrtime()
end = res.end end = res.end
res.end = () -> res.end = () ->
end.apply(this, arguments) end.apply(this, arguments)
responseTime = new Date() - startTime responseTime = process.hrtime(startTime)
responseTimeMs = Math.round(responseTime[0] * 1000 + responseTime[1] / 1000)
if req.route?.path? if req.route?.path?
routePath = req.route.path.toString().replace(/\//g, '_').replace(/\:/g, '').slice(1) routePath = req.route.path.toString().replace(/\//g, '_').replace(/\:/g, '').slice(1)
key = "http-requests.#{routePath}.#{req.method}.#{res.statusCode}" key = "http-requests.#{routePath}.#{req.method}.#{res.statusCode}"
Metrics.timing(key, responseTimeMs)
Metrics.timing(key, responseTime) remoteIp = req.ip || req.socket?.socket?.remoteAddress || req.socket?.remoteAddress
logger.log reqUrl = req.originalUrl || req.url
req: referrer = req.headers['referer'] || req.headers['referrer']
url: req.originalUrl || req.url if STACKDRIVER_LOGGING
method: req.method info =
referrer: req.headers['referer'] || req.headers['referrer'] httpRequest:
"remote-addr": req.ip || req.socket?.socket?.remoteAddress || req.socket?.remoteAddress requestMethod: req.method
"user-agent": req.headers["user-agent"] requestUrl: reqUrl
"content-length": req.headers["content-length"] requestSize: req.headers["content-length"]
res: status: res.statusCode
"content-length": res._headers?["content-length"] responseSize: res._headers?["content-length"]
statusCode: res.statusCode userAgent: req.headers["user-agent"]
"response-time": responseTime remoteIp: remoteIp
"http request" referer: referrer
latency:
seconds: responseTime[0]
nanos: responseTime[1]
protocol: req.protocol
else
info =
req:
url: reqUrl
method: req.method
referrer: referrer
"remote-addr": remoteIp
"user-agent": req.headers["user-agent"]
"content-length": req.headers["content-length"]
res:
"content-length": res._headers?["content-length"]
statusCode: res.statusCode
"response-time": responseTimeMs
if res.statusCode >= 500
logger.error(info, "%s %s", req.method, reqUrl)
else if res.statusCode >= 400 and res.statusCode < 500
logger.warn(info, "%s %s", req.method, reqUrl)
else
logger.info(info, "%s %s", req.method, reqUrl)
next() next()