feat: implement comprehensive health check endpoints for API, Auth, and Realtime services to monitor database, Redis, MinIO, and InfluxDB connectivity.
This commit is contained in:
@@ -16,10 +16,19 @@ app.get('/', (req, res) => {
|
|||||||
res.redirect('/health');
|
res.redirect('/health');
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/health', (req, res) => {
|
app.get('/health', async (req, res) => {
|
||||||
|
const postgres = await require('./storage/postgres').checkPostgres();
|
||||||
|
const influx = await require('./storage/influx').checkInflux();
|
||||||
|
const minio = await require('./storage/minio').checkMinio();
|
||||||
|
|
||||||
|
const allOk = Object.values(postgres).every(s => s === 'connected') && influx && minio;
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
status: "ok",
|
status: allOk ? "ok" : "degraded",
|
||||||
service: "api",
|
service: "api",
|
||||||
|
databases: postgres,
|
||||||
|
influx: influx ? 'connected' : 'disconnected',
|
||||||
|
minio: minio ? 'connected' : 'disconnected',
|
||||||
version: version,
|
version: version,
|
||||||
build_number: vBuild,
|
build_number: vBuild,
|
||||||
version_state: vState
|
version_state: vState
|
||||||
|
|||||||
@@ -59,9 +59,19 @@ async function query(bucket, relativeTime, measurement, sensor, field) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkInflux() {
|
||||||
|
try {
|
||||||
|
await querying.rows(`from(bucket: "boat") |> range(start: -1s) |> limit(n:1)`).next();
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
write:append,
|
write:append,
|
||||||
writeBatch,
|
writeBatch,
|
||||||
query
|
query,
|
||||||
|
checkInflux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,6 +123,15 @@ async function getFileStream(bucket, objectName) {
|
|||||||
return dataStream;
|
return dataStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkMinio() {
|
||||||
|
try {
|
||||||
|
await client.listBuckets();
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
bucketExists,
|
bucketExists,
|
||||||
getBuckets,
|
getBuckets,
|
||||||
@@ -132,5 +141,6 @@ module.exports = {
|
|||||||
removeObject,
|
removeObject,
|
||||||
upload,
|
upload,
|
||||||
download,
|
download,
|
||||||
getFileStream
|
getFileStream,
|
||||||
|
checkMinio
|
||||||
}
|
}
|
||||||
@@ -70,10 +70,24 @@ async function remove(table, condition, params, type = 'users') {
|
|||||||
const sql = `DELETE FROM ${table} WHERE ${condition}`;
|
const sql = `DELETE FROM ${table} WHERE ${condition}`;
|
||||||
return await query(sql, params, type);
|
return await query(sql, params, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkPostgres() {
|
||||||
|
const status = {};
|
||||||
|
for (const [name, pool] of Object.entries(pools)) {
|
||||||
|
try {
|
||||||
|
await pool.query('SELECT NOW()');
|
||||||
|
status[name] = 'connected';
|
||||||
|
} catch (error) {
|
||||||
|
status[name] = 'disconnected';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
query,
|
query,
|
||||||
append,
|
append,
|
||||||
remove,
|
remove,
|
||||||
getClient,
|
getClient,
|
||||||
|
checkPostgres,
|
||||||
pools
|
pools
|
||||||
};
|
};
|
||||||
@@ -35,6 +35,22 @@ app.set('view engine', 'html');
|
|||||||
const authRoutes = require('./routes/auth');
|
const authRoutes = require('./routes/auth');
|
||||||
app.use('/', authRoutes);
|
app.use('/', authRoutes);
|
||||||
|
|
||||||
|
app.get('/health', async (req, res) => {
|
||||||
|
const dbConnected = await database.checkPostgres();
|
||||||
|
const redisHelper = require('./storage/redis');
|
||||||
|
const redisConnected = await redisHelper.checkRedis();
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
status: dbConnected && redisConnected ? "ok" : "degraded",
|
||||||
|
service: "auth",
|
||||||
|
database: dbConnected ? "connected" : "disconnected",
|
||||||
|
redis: redisConnected ? "connected" : "disconnected",
|
||||||
|
version: version,
|
||||||
|
build_number: vBuild,
|
||||||
|
version_state: vState
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Startup
|
// Startup
|
||||||
async function start() {
|
async function start() {
|
||||||
await database.initDb();
|
await database.initDb();
|
||||||
|
|||||||
@@ -97,9 +97,19 @@ async function initDb() {
|
|||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkPostgres() {
|
||||||
|
try {
|
||||||
|
await pool.query('SELECT NOW()');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
pool,
|
pool,
|
||||||
query,
|
query,
|
||||||
getClient,
|
getClient,
|
||||||
initDb
|
initDb,
|
||||||
|
checkPostgres
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,4 +33,16 @@ function connected() {
|
|||||||
return redis.status === 'ready';
|
return redis.status === 'ready';
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { redis, configure, connected };
|
async function checkRedis() {
|
||||||
|
try {
|
||||||
|
if (redis.status !== 'ready') {
|
||||||
|
await redis.connect().catch(() => {});
|
||||||
|
}
|
||||||
|
await redis.ping();
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { redis, configure, connected, checkRedis };
|
||||||
@@ -12,8 +12,10 @@ const pool = new Pool({
|
|||||||
async function checkDB() {
|
async function checkDB() {
|
||||||
try {
|
try {
|
||||||
await pool.query('SELECT NOW()');
|
await pool.query('SELECT NOW()');
|
||||||
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Database connection failed:', error);
|
console.error('Database connection failed:', error);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,15 @@ async function getWatcherCount(sensorId) {
|
|||||||
return parseInt(count) || 0;
|
return parseInt(count) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkRedis() {
|
||||||
|
try {
|
||||||
|
await redis.ping();
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setSession,
|
setSession,
|
||||||
getSession,
|
getSession,
|
||||||
@@ -74,6 +83,7 @@ module.exports = {
|
|||||||
addWatcher,
|
addWatcher,
|
||||||
removeWatcher,
|
removeWatcher,
|
||||||
getWatcherCount,
|
getWatcherCount,
|
||||||
|
checkRedis,
|
||||||
redis,
|
redis,
|
||||||
redisSub
|
redisSub
|
||||||
};
|
};
|
||||||
@@ -22,9 +22,14 @@ app.get('/', (req, res) => {
|
|||||||
res.redirect('/health');
|
res.redirect('/health');
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/health', (req, res) => {
|
app.get('/health', async (req, res) => {
|
||||||
|
const dbConnected = await require('./helper/authdb').checkDB();
|
||||||
|
const redisConnected = await redisHelper.checkRedis();
|
||||||
|
|
||||||
res.status(200).send({
|
res.status(200).send({
|
||||||
status: 'OK',
|
status: dbConnected && redisConnected ? 'OK' : 'DEGRADED',
|
||||||
|
database: dbConnected ? 'connected' : 'disconnected',
|
||||||
|
redis: redisConnected ? 'connected' : 'disconnected',
|
||||||
service: 'realtime',
|
service: 'realtime',
|
||||||
version: process.env.VERSION,
|
version: process.env.VERSION,
|
||||||
build: process.env.VERSION_BUILD,
|
build: process.env.VERSION_BUILD,
|
||||||
|
|||||||
Reference in New Issue
Block a user