-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add gauges for all monitors in content node #3770
Changes from all commits
b6cc984
8ae5f35
9fb116f
c1e088d
2272e3c
67a76a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
const Bull = require('bull') | ||
const redis = require('../redis') | ||
const config = require('../config') | ||
const { MONITORS, getMonitorRedisKey } = require('./monitors') | ||
const { | ||
MONITORS, | ||
PROMETHEUS_MONITORS, | ||
getMonitorRedisKey | ||
} = require('./monitors') | ||
const { logger } = require('../logging') | ||
|
||
const QUEUE_INTERVAL_MS = 60 * 1000 | ||
|
@@ -22,7 +26,7 @@ const MONITORING_QUEUE_HISTORY = 500 | |
* 2. Refreshes the value and stores the update in redis | ||
*/ | ||
class MonitoringQueue { | ||
constructor() { | ||
constructor(prometheusRegistry) { | ||
this.queue = new Bull('monitoring-queue', { | ||
redis: { | ||
port: config.get('redisPort'), | ||
|
@@ -34,6 +38,8 @@ class MonitoringQueue { | |
} | ||
}) | ||
|
||
this.prometheusRegistry = prometheusRegistry | ||
|
||
// Clean up anything that might be still stuck in the queue on restart | ||
this.queue.empty() | ||
|
||
|
@@ -48,11 +54,11 @@ class MonitoringQueue { | |
|
||
// Iterate over each monitor and set a new value if the cached | ||
// value is not fresh. | ||
Object.values(MONITORS).forEach(async (monitor) => { | ||
Object.keys(MONITORS).forEach(async (monitorKey) => { | ||
try { | ||
await this.refresh(monitor) | ||
await this.refresh(MONITORS[monitorKey], monitorKey) | ||
} catch (e) { | ||
this.logStatus(`Error on ${monitor.name} ${e}`) | ||
this.logStatus(`Error on ${monitorKey} ${e}`) | ||
} | ||
}) | ||
|
||
|
@@ -71,29 +77,48 @@ class MonitoringQueue { | |
* them on init | ||
*/ | ||
async seedInitialValues() { | ||
await this.refresh(MONITORS.STORAGE_PATH_SIZE) | ||
await this.refresh(MONITORS.STORAGE_PATH_USED) | ||
await this.refresh(MONITORS.STORAGE_PATH_SIZE, 'STORAGE_PATH_SIZE') | ||
await this.refresh(MONITORS.STORAGE_PATH_USED, 'STORAGE_PATH_USED') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not ideal but w/e |
||
} | ||
|
||
async refresh(monitor) { | ||
const key = getMonitorRedisKey(monitor) | ||
/** | ||
* Refresh monitor in redis and prometheus (if integer) | ||
* @param {Object} monitorVal Object containing the monitor props like { func, ttl, type, name } | ||
* @param {*} monitorKey name of the monitor eg `THIRTY_DAY_ROLLING_SYNC_SUCCESS_COUNT` | ||
*/ | ||
async refresh(monitorVal, monitorKey) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ass far as the order everything else in this file is monitor first so i was trying to preserve the consistency. but i do agree the monitorVal name is confusing |
||
const key = getMonitorRedisKey(monitorVal) | ||
const ttlKey = `${key}:ttl` | ||
|
||
// If the value is fresh, exit early | ||
const isFresh = await redis.get(ttlKey) | ||
if (isFresh) return | ||
|
||
const value = await monitor.func() | ||
this.logStatus(`Computed value for ${monitor.name} ${value}`) | ||
const value = await monitorVal.func() | ||
this.logStatus(`Computed value for ${monitorVal.name} ${value}`) | ||
|
||
// store integer monitors in prometheus | ||
try { | ||
if (PROMETHEUS_MONITORS.hasOwnProperty(monitorKey)) { | ||
const metric = this.prometheusRegistry.getMetric( | ||
this.prometheusRegistry.metricNames[`MONITOR_${monitorKey}`] | ||
) | ||
metric.set({}, value) | ||
} | ||
} catch (e) { | ||
logger.debug( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if anything above log 98 should be a debug and this one should be info/warn haha |
||
`Couldn't store value: ${value} in prometheus for metric: ${monitorKey}` | ||
) | ||
} | ||
|
||
// Set the value | ||
redis.set(key, value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. btw the bug i mentioned on linear is that this call is not awaited (although that might have been intentional) |
||
|
||
if (monitor.ttl) { | ||
if (monitorVal.ttl) { | ||
// Set a TTL (in seconds) key to track when this value needs refreshing. | ||
// We store a separate TTL key rather than expiring the value itself | ||
// so that in the case of an error, the current value can still be read | ||
redis.set(ttlKey, 1, 'EX', monitor.ttl) | ||
redis.set(ttlKey, 1, 'EX', monitorVal.ttl) | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -294,6 +294,12 @@ const MONITORS = { | |
LATEST_FIND_REPLICA_SET_UPDATES_JOB_SUCCESS | ||
} | ||
|
||
const PROMETHEUS_MONITORS = {} | ||
for (const monitor in MONITORS) { | ||
if (MONITORS[monitor]?.type === 'int') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whats your thinking for the non-int monitors? we gonna keep writing them all to redis for now unchanged? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep exactly, keep as is |
||
PROMETHEUS_MONITORS[monitor] = MONITORS[monitor] | ||
} | ||
|
||
const getMonitorRedisKey = (monitor) => | ||
`${MONITORING_REDIS_PREFIX}:${monitor.name}` | ||
|
||
|
@@ -346,6 +352,7 @@ const getMonitors = async (monitors) => { | |
|
||
module.exports = { | ||
MONITORS, | ||
PROMETHEUS_MONITORS, | ||
getMonitorRedisKey, | ||
getMonitors | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need the key to look up the metric form METRIC_NAMES
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object.entries(MONITORS).forEach(async (monitorKey, monitorProps) => {}
would be v clean here 🙂