Skip to content

Latest commit

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Hook

Hook is a simple node package used for counting unique occurances (by key) in a window of time that performs and has a low memory footprint. It works with multiple instances of node if used in conjunction with redis.

This allows for throttling and statistics tracking over a period of time.

Use Cases

  • tracking request count by url, ip, etc.. over a specific amount of time (minute, day, hour, etc...)
  • throttling users based on the same principles.

Examples

middleware

Throttle by ip address

var hook = require('hook');
var connect = require('connect');
var IP_LIMIT = 1000;
var IP_PER = "day"; // hour or minute
var app = connect(
hook.middleware.throttleIP(IP_LIMIT, IP_PER) ); 

Count urls by day and generate a realtime report:

var app = express.createServer(
hook.middleware.countURL("day")
);
app.get('/stats', function(req, res, next) { req.writeHead(200, { "Content-type": "text/html" });
req.end(hook.middleware.htmlTable();
});

More specific throttling

// throttle by url. // A url can only be visited 10 times in an hour
// hour on minute granularity
connect(
hook.middleware.throttle({
limit: 10,
buckets: 60,
seconds: 60,
prefix: "ip"
}, function (req) { return req.url; })
);

RangeCounter API

Range counters are used for collecting data in a sliding window. They are not meant to be persistent. Instead, they are a snapshot of statistical data. They are a few concepts that need to be defined:

  • buckets: this is the number of containers which the counters keep. They represent a period of time in which counts/keys fall into.
  • time per bucket: this is the number of seconds each bucket should represent. For instance: 24 buckets at 3600 seconds each will keep track of data for a day in hourly increments.

Example

Say we want to limit the number of times a user can log in a 10 minute time period:

var redis = require('redis').createClient();
var buckets = 10;
var seconds = 60;
var prefix = "login:users"; // for redis
var users = new hook.RangeCounter(buckets, seconds, prefix);
var limit = 100;
function userLoggedIn(username) {
users.inc(username); }
function canUserLogin(username) {
return users.getCount(username) < limit;
}
// sync counter data to redis (prefix key is "login:users");
// if you have multiple node instances running, they will sync up
// to each other every 5 seconds
setInterval(function () { hook.RangeCounter.sync(redis, users) }, 5000);

new hook.RangeCounter(buckets, seconds, prefix)

Instantiates a range counter. Inputs:

  • buckets: the number of buckets to store counts (more for more granularity
  • seconds: the number of seconds each bucket represents
  • prefix: the prefix used for keys in redis

counter.inc(key)

Increments counter for a specific key (eg. ip address, url)

counter.getCount(key)

Returns integer for the count of a key

counter.getCounts()

Returns a hash where the keys are the keys and the counts are the values.

About

NodeJS time-based counter meant for HTTP throttling and statistics

Resources

Stars

9 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages