Consolidate some stats server functions
This commit is contained in:
@ -1,65 +1,13 @@
|
|||||||
const redis = require('redis')
|
|
||||||
const subDays = require('date-fns/sub_days')
|
const subDays = require('date-fns/sub_days')
|
||||||
const prettyBytes = require('pretty-bytes')
|
const prettyBytes = require('pretty-bytes')
|
||||||
const invariant = require('invariant')
|
|
||||||
const table = require('text-table')
|
const table = require('text-table')
|
||||||
|
const {
|
||||||
|
sumKeys,
|
||||||
|
sumTopScores,
|
||||||
|
createDayKey
|
||||||
|
} = require('../server/StatsServer')
|
||||||
|
|
||||||
const RedisURL = process.env.REDIS_URL
|
const now = new Date
|
||||||
|
|
||||||
invariant(
|
|
||||||
RedisURL,
|
|
||||||
'Missing the $REDIS_URL environment variable'
|
|
||||||
)
|
|
||||||
|
|
||||||
const sumValues = (array) =>
|
|
||||||
array.reduce((memo, n) => memo + (parseInt(n, 10) || 0), 0)
|
|
||||||
|
|
||||||
const db = redis.createClient(RedisURL)
|
|
||||||
|
|
||||||
const getKeyValues = (keys) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
db.mget(keys, (error, values) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error)
|
|
||||||
} else {
|
|
||||||
resolve(values)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const sumKeys = (keys) =>
|
|
||||||
getKeyValues(keys).then(sumValues)
|
|
||||||
|
|
||||||
const createScoresMap = (array) => {
|
|
||||||
const map = {}
|
|
||||||
|
|
||||||
for (let i = 0; i < array.length; i += 2)
|
|
||||||
map[array[i]] = parseInt(array[i + 1], 10)
|
|
||||||
|
|
||||||
return map
|
|
||||||
}
|
|
||||||
|
|
||||||
const getTopScores = (key, n = 10) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
db.zrevrange(key, 0, n, 'withscores', (error, value) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error)
|
|
||||||
} else {
|
|
||||||
resolve(createScoresMap(value))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const sumTopScores = (keys, n) =>
|
|
||||||
Promise.all(keys.map(key => getTopScores(key, n))).then(values => {
|
|
||||||
return values.reduce((memo, map) => {
|
|
||||||
Object.keys(map).forEach(key => {
|
|
||||||
memo[key] = (memo[key] || 0) + map[key]
|
|
||||||
})
|
|
||||||
|
|
||||||
return memo
|
|
||||||
}, {})
|
|
||||||
})
|
|
||||||
|
|
||||||
const createRange = (start, end) => {
|
const createRange = (start, end) => {
|
||||||
const range = []
|
const range = []
|
||||||
@ -70,14 +18,6 @@ const createRange = (start, end) => {
|
|||||||
return range
|
return range
|
||||||
}
|
}
|
||||||
|
|
||||||
const createDayKey = (date) =>
|
|
||||||
`${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`
|
|
||||||
|
|
||||||
const createHourKey = (date) =>
|
|
||||||
`${createDayKey(date)}-${date.getUTCHours()}`
|
|
||||||
|
|
||||||
const now = new Date
|
|
||||||
|
|
||||||
const createPastDays = (n) =>
|
const createPastDays = (n) =>
|
||||||
createRange(1, n + 1).map(days => subDays(now, days)).reverse()
|
createRange(1, n + 1).map(days => subDays(now, days)).reverse()
|
||||||
|
|
||||||
|
78
server/StatsServer.js
Normal file
78
server/StatsServer.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const redis = require('redis')
|
||||||
|
const invariant = require('invariant')
|
||||||
|
|
||||||
|
const RedisURL = process.env.REDIS_URL
|
||||||
|
|
||||||
|
invariant(
|
||||||
|
RedisURL,
|
||||||
|
'Missing the $REDIS_URL environment variable'
|
||||||
|
)
|
||||||
|
|
||||||
|
const db = redis.createClient(RedisURL)
|
||||||
|
|
||||||
|
const sumValues = (array) =>
|
||||||
|
array.reduce((memo, n) => memo + (parseInt(n, 10) || 0), 0)
|
||||||
|
|
||||||
|
const getKeyValues = (keys) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
db.mget(keys, (error, values) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error)
|
||||||
|
} else {
|
||||||
|
resolve(values)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const sumKeys = (keys) =>
|
||||||
|
getKeyValues(keys).then(sumValues)
|
||||||
|
|
||||||
|
const createScoresMap = (array) => {
|
||||||
|
const map = {}
|
||||||
|
|
||||||
|
for (let i = 0; i < array.length; i += 2)
|
||||||
|
map[array[i]] = parseInt(array[i + 1], 10)
|
||||||
|
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTopScores = (key, n = 10) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
db.zrevrange(key, 0, n, 'withscores', (error, value) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error)
|
||||||
|
} else {
|
||||||
|
resolve(createScoresMap(value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const sumTopScores = (keys, n) =>
|
||||||
|
Promise.all(keys.map(key => getTopScores(key, n))).then(values => {
|
||||||
|
return values.reduce((memo, map) => {
|
||||||
|
Object.keys(map).forEach(key => {
|
||||||
|
memo[key] = (memo[key] || 0) + map[key]
|
||||||
|
})
|
||||||
|
|
||||||
|
return memo
|
||||||
|
}, {})
|
||||||
|
})
|
||||||
|
|
||||||
|
const createDayKey = (date) =>
|
||||||
|
`${date.getUTCFullYear()}-${date.getUTCMonth()}-${date.getUTCDate()}`
|
||||||
|
|
||||||
|
const createHourKey = (date) =>
|
||||||
|
`${createDayKey(date)}-${date.getUTCHours()}`
|
||||||
|
|
||||||
|
const createMinuteKey = (date) =>
|
||||||
|
`${createDayKey(date)}-${date.getUTCMinutes()}`
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getKeyValues,
|
||||||
|
sumKeys,
|
||||||
|
getTopScores,
|
||||||
|
sumTopScores,
|
||||||
|
createDayKey,
|
||||||
|
createHourKey,
|
||||||
|
createMinuteKey
|
||||||
|
}
|
@ -1,6 +1,11 @@
|
|||||||
require('isomorphic-fetch')
|
require('isomorphic-fetch')
|
||||||
const invariant = require('invariant')
|
|
||||||
const redis = require('redis')
|
const redis = require('redis')
|
||||||
|
const invariant = require('invariant')
|
||||||
|
const {
|
||||||
|
createDayKey,
|
||||||
|
createHourKey,
|
||||||
|
createMinuteKey
|
||||||
|
} = require('../server/StatsServer')
|
||||||
|
|
||||||
const CloudflareEmail = process.env.CLOUDFLARE_EMAIL
|
const CloudflareEmail = process.env.CLOUDFLARE_EMAIL
|
||||||
const CloudflareKey = process.env.CLOUDFLARE_KEY
|
const CloudflareKey = process.env.CLOUDFLARE_KEY
|
||||||
@ -157,7 +162,7 @@ const processPerDayTimeseries = (ts) =>
|
|||||||
'ERROR: per-day timeseries must span exactly one day'
|
'ERROR: per-day timeseries must span exactly one day'
|
||||||
)
|
)
|
||||||
|
|
||||||
const dayKey = `${since.getUTCFullYear()}-${since.getUTCMonth()}-${since.getUTCDate()}`
|
const dayKey = createDayKey(since)
|
||||||
|
|
||||||
// Q: How many requests do we serve per day?
|
// Q: How many requests do we serve per day?
|
||||||
db.set(`stats-requests-${dayKey}`, ts.requests.all)
|
db.set(`stats-requests-${dayKey}`, ts.requests.all)
|
||||||
@ -223,7 +228,7 @@ const processPerHourTimeseries = (ts) =>
|
|||||||
'ERROR: per-hour timeseries must span exactly one hour'
|
'ERROR: per-hour timeseries must span exactly one hour'
|
||||||
)
|
)
|
||||||
|
|
||||||
const hourKey = `${since.getUTCFullYear()}-${since.getUTCMonth()}-${since.getUTCDate()}-${since.getUTCHours()}`
|
const hourKey = createHourKey(since)
|
||||||
|
|
||||||
// Q: How many requests do we serve per hour? (expire after 7 days)
|
// Q: How many requests do we serve per hour? (expire after 7 days)
|
||||||
db.setex(`stats-requests-${hourKey}`, (oneDaySeconds * 7), ts.requests.all)
|
db.setex(`stats-requests-${hourKey}`, (oneDaySeconds * 7), ts.requests.all)
|
||||||
@ -259,7 +264,7 @@ const processPerMinuteTimeseries = (ts) =>
|
|||||||
'ERROR: per-minute timeseries must span exactly one minute'
|
'ERROR: per-minute timeseries must span exactly one minute'
|
||||||
)
|
)
|
||||||
|
|
||||||
const minuteKey = `${since.getUTCFullYear()}-${since.getUTCMonth()}-${since.getUTCDate()}-${since.getUTCHours()}-${since.getUTCMinutes()}`
|
const minuteKey = createMinuteKey(since)
|
||||||
|
|
||||||
// Q: How many requests do we serve per minute? (expire after 1 day)
|
// Q: How many requests do we serve per minute? (expire after 1 day)
|
||||||
db.setex(`stats-requests-${minuteKey}`, oneDaySeconds, ts.requests.all)
|
db.setex(`stats-requests-${minuteKey}`, oneDaySeconds, ts.requests.all)
|
||||||
|
Reference in New Issue
Block a user