@opengis/fastify-table
Version:
core-plugins
154 lines (153 loc) • 5.96 kB
JavaScript
import os from "os";
import process from "process";
import util from "node:util";
import { exec } from "node:child_process";
import { config, getFolder, pgClients, getRedis } from "../../../utils.js";
const execAsync = util.promisify(exec);
const platform = os.platform();
const processFolder = os.homedir();
const formatMemoryUsage = (data) => `${(data / 1024 / 1024).toFixed(2)} MB`;
const rclient = getRedis();
const rclient2 = getRedis({ db: 2 });
// const rclient10 = getRedis({ db: 10 });
const filesFolder = getFolder(config);
const redisKey = "logger-process-online";
const sqlQuery = `select datname as dbname, application_name as app, client_addr as client_ip,
(now()-backend_start)::text as msec, state, query from pg_stat_activity where datname=$1`;
const prev = {};
const cpuUsage = () => {
const usage = process.cpuUsage();
const cpus = os.cpus();
const total = cpus.reduce((acc, curr) => acc + Object.values(curr.times).reduce((a, b) => a + b, 0), 0);
if (!prev.usage || !prev.total) {
Object.assign(prev, { usage, total });
return 0;
}
const diffUsage = (usage.user - prev.usage.user + usage.system - prev.usage.system) / 1000;
const diffTotal = total - prev.total;
Object.assign(prev, { usage, total });
return (diffUsage / diffTotal) * cpus.length * 100;
};
cpuUsage();
export default async function loggerSystem(req) {
const { pg = pgClients.client } = req || {};
const dbName = pg?.options?.database;
const dbsize = config.redis
? await rclient.get(`${dbName}:content:dbsize:${redisKey}`)
: null;
const dbVerion = pg?.query
? await pg
.query("select version();")
.then((el) => el.rows?.[0]?.version)
: null;
const dbSize = dbsize ||
(pg?.query
? await pg
.query(`select pg_size_pretty(pg_database_size($1))`, [dbName])
.then((el) => el.rows?.[0]?.pg_size_pretty)
: null);
const query = pg?.query
? await pg.query(sqlQuery, [dbName]).then((el) => el.rows || [])
: null;
const { stdout: topProcess } = platform === "win32"
? { stdout: "Cant show top on this system type" }
: await execAsync("top -b -n 1");
const osInfo = `${os.version()} ${os.machine?.() || ""}`;
const cpuInfo = os.cpus();
const totalMemory = os.totalmem();
const memory = process.memoryUsage();
const resource = process.resourceUsage();
const currentCpuUsage = cpuUsage();
const redisInfo = config.redis ? await rclient.info() : "";
const lines = redisInfo.split("\r\n").filter((el) => el && el.split);
const redis = {};
for (let i = 0; i < lines.length; i += 1) {
const [key, val] = lines[i].split(":");
if (val) {
redis[key] = val;
}
}
if (config.redis) {
await rclient.set(`${dbName}:content:dbsize:${redisKey}`, dbSize, "EX", 30 * 60);
}
const latency = config.redis ? await rclient.latency("latest") : null;
const uptime = pg?.query
? await pg
.query("select extract('epoch' from current_timestamp - pg_postmaster_start_time())::int as uptime")
.then((el) => el.rows?.[0]?.uptime)
: null;
const metric5 = config.redis
? await rclient2.hgetall(`${dbName}:system_metrics`)
: {};
Object.keys(metric5 || {})
.filter((el) => el.startsWith("time"))
.forEach((m) => {
metric5[m] /= 1000.0;
});
const metricSort = metric5
? JSON.parse(JSON.stringify(metric5, Object.keys(metric5).sort()))
: undefined;
const userOnline = config.redis
? await rclient2.scan([
"0",
"match",
`session_auth:${dbName}:*`,
"count",
"10000",
])
: [];
// const userOnline = await rclient10.scan(['0', 'match', 'sess:*', 'count', '10000']);
const uptimes = {
"uptime:node": Math.round(process.uptime()),
"uptime:system": os.uptime(),
"uptime:pg": uptime,
"uptime:redis": typeof redis?.uptime_in_seconds === "number"
? redis.uptime_in_seconds - 0
: 0,
};
return {
process: {
root: process.cwd(),
processFolder,
saveDirectory: filesFolder,
dbhost: pg?.options?.host,
dbport: pg?.options?.port,
dbname: dbName,
},
uptimes,
metric: {
cpu: `${Math.round(currentCpuUsage)} %`,
memory: `${Math.round((memory.rss / totalMemory) * 100 * 100) / 100} %`,
"user.online": userOnline?.[1]?.length,
"node.total": formatMemoryUsage(memory.heapTotal),
"node.used": formatMemoryUsage(memory.heapUsed),
"node.rss": formatMemoryUsage(memory.rss),
"node.cpu.time": resource.systemCPUTime,
"node.cpu.load": os.loadavg()[0],
"redis.ram": redis.used_memory_human,
"redis.latency": latency?.join?.(","),
"redis.ram.peak": redis.used_memory_peak_human,
"redis.clients": redis.connected_clients,
"redis.db0": redis.db0?.split(",")?.[0]?.substring(5),
"redis.db1": redis.db1?.split(",")?.[0]?.substring(5),
"redis.db2": redis.db2?.split(",")?.[0]?.substring(5),
"redis.db10": redis.db10?.split(",")?.[0]?.substring(5),
"pg.connection": query?.length,
dbsize: dbSize,
filesize: 0,
},
metricSort,
system: {
os: osInfo,
release: os.release(),
core: cpuInfo?.length,
cpu: cpuInfo?.[0]?.model,
ram: formatMemoryUsage(totalMemory),
db: dbVerion,
redis: rclient?.server_info?.redis_version,
node: process.version,
},
top: topProcess,
query,
};
}