glutenfree
Version:
A profiler/loganalyzer for nginx/Cetrea Aw.
162 lines (125 loc) • 3.85 kB
text/coffeescript
cluster = require("cluster")
winston = require("winston")
http = require("http")
util = require("util")
_ = require("underscore")
logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({'timestamp':true})
]
})
logger.info "PrWrkr##{cluster.worker.id}: online, waiting for input"
# holds timeout
reporter = {}
# cluster id - holds id of master
clusterId = ""
# handle message, specifically "targeting"
cluster.worker.on(
"message"
(msg) ->
switch msg.subject
when "targeting"
logger.info "PrWorker##{cluster.worker.id}: targeting received (http://#{msg.server}:#{msg.port} w #{msg.user}:#{msg.password}), hitting #{msg.targeting.length} targets, pause set to #{msg.pause}"
http.globalAgent.maxSockets = 1024
clusterId = msg.clusterId
# start hitting targets
hit(msg.server, msg.port, msg.user, msg.password, msg.targeting, msg.pause)
# report back to master
reporter = report(msg.reportinterval || 10000)
)
# report is an array containing all results which have not yet been shipped to master
hits = []
hitcount = 0
hit = (server, port, user, password, targets, pause = 10) ->
# select a target, targets most used functions
r = Math.random()*100
#logger.debug "r at #{r}, looking at", targets
target = _.find(targets, ((t) -> r < t.acc_percentage))
# if no target can be found then reschedule a hit
if not target?
setTimeout(
->
hit(server, port, user, password, targets, pause)
pause # this should be 0 for prod
)
return
#logger.debug "#{r} hitting", target
#logger.debug "PrWrkr##{cluster.worker.id}: hit #{hitcount++} at http://#{user}:#{password}@#{server}:#{port}/#{target.path}"
# record time
t0 = Date.now()
# do request
req = http.get({
host: server
port: port
headers: target?.headers
auth: "#{user}:#{password}"
# method: "GET" # default
path: "/#{target?.path}"
},
(res) ->
logger.debug "PrWrkr##{cluster.worker.id}: hit w status #{res.statusCode}"
# etag
target?.headers =
"If-None-Match" : res.headers["etag"] || target?.headers?["If-None-Match"]
"Connection": "Keep-Alive"
hits.push({
type: "response"
path: target?.path
status: res.statusCode
at: Date.now()
time: Date.now() - t0
worker: cluster?.worker?.id
cluster: clusterId
})
# continue
#process.nextTick( -> hit(server, port, user, password, targets))
setTimeout(
->
hit(server, port, user, password, targets, pause)
pause # this should be 0 for prod
)
)
req.on(
"error",
(e) ->
#logger.debug "PrWrkr##{cluster.worker.id}: miss!"
hits.push({
type: "error"
msg: e.message
path: target?.path
time: Date.now() - t0
})
# continue
setTimeout(
-> hit(server, port, user, password, targets, pause)
pause
)
)
req.end()
report = (interval) ->
if hits.length > 0
logger.debug "PrWrkr##{cluster.worker.id}: sending report to master (#{hits.length} hits)"
try
# send report to cluster master
cluster.worker.send(
subject: "report"
report:
hits: hits || []
)
# reset hits
hits = []
catch err
logger.error "PrWrkr##{cluster.worker.id}: Could not report to master."
# if interval > 0 then start loop
if interval > 0 then reporter = setTimeout((->report(interval)),interval)
# handle disconnect
cluster.worker.on(
"disconnect",
->
# cancel existing report
clearTimeout(reporter)
# report remaining
report(0)
logger.info "report, disconnect"
process.exit(0)
)