added user metrics

This commit is contained in:
mrjvs
2023-10-29 16:23:30 +01:00
parent 1f85631f55
commit 54ae6cac3d
7 changed files with 78 additions and 9 deletions

View File

@@ -21,8 +21,8 @@ Backend for movie-web
- [ ] consume provider metrics
- [ ] DELETE user - should delete all associated data
- [ ] prometheus metrics
- [ ] requests
- [ ] user count
- [X] requests
- [X] user count
- [ ] provider metrics
- [ ] ratelimits (stored in redis)
- [X] switch to pnpm

View File

@@ -1,4 +1,5 @@
import { setupFastify } from '@/modules/fastify';
import { setupFastify, startFastify } from '@/modules/fastify';
import { setupMetrics } from '@/modules/metrics';
import { setupMikroORM } from '@/modules/mikro';
import { scopedLogger } from '@/services/logger';
@@ -9,8 +10,11 @@ async function bootstrap(): Promise<void> {
evt: 'setup',
});
const app = await setupFastify();
await setupMikroORM();
await setupFastify();
await setupMetrics(app);
await startFastify(app);
log.info(`App setup, ready to accept connections`, {
evt: 'success',

View File

@@ -72,9 +72,14 @@ export async function setupFastify(): Promise<FastifyInstance> {
},
);
if (!exportedApp) throw new Error('no app to export in fastify');
return exportedApp;
}
export function startFastify(app: FastifyInstance) {
// listen to port
log.info(`listening to port`, { evt: 'setup-listen' });
return new Promise((resolve) => {
return new Promise<void>((resolve) => {
app.listen(
{
port: conf.server.port,
@@ -91,7 +96,7 @@ export async function setupFastify(): Promise<FastifyInstance> {
log.info(`fastify setup successfully`, {
evt: 'setup-success',
});
resolve(exportedApp as FastifyInstance);
resolve();
},
);
});

View File

@@ -9,11 +9,8 @@ import { userProgressRouter } from '@/routes/users/progress';
import { userSessionsRouter } from '@/routes/users/sessions';
import { userSettingsRouter } from '@/routes/users/settings';
import { FastifyInstance } from 'fastify';
import metricsPlugin from 'fastify-metrics';
export async function setupRoutes(app: FastifyInstance) {
await app.register(metricsPlugin, { endpoint: '/metrics' });
await app.register(manageAuthRouter.register);
await app.register(loginAuthRouter.register);
await app.register(userSessionsRouter.register);

View File

@@ -0,0 +1,39 @@
import { getORM } from '@/modules/mikro';
import { FastifyInstance } from 'fastify';
import { Counter } from 'prom-client';
import metricsPlugin from 'fastify-metrics';
import { updateMetrics } from '@/modules/metrics/update';
import { scopedLogger } from '@/services/logger';
const log = scopedLogger('metrics');
export type Metrics = {
user: Counter<'namespace'>;
};
let metrics: null | Metrics = null;
export function getMetrics() {
if (!metrics) throw new Error('metrics not initialized');
return metrics;
}
export async function setupMetrics(app: FastifyInstance) {
log.info(`Setting up metrics...`, { evt: 'start' });
await app.register(metricsPlugin, { endpoint: '/metrics' });
metrics = {
user: new Counter({
name: 'user_count',
help: 'user_help',
labelNames: ['namespace'],
}),
};
const orm = getORM();
const em = orm.em.fork();
log.info(`Syncing up metrics...`, { evt: 'sync' });
await updateMetrics(em, metrics);
log.info(`Metrics initialized!`, { evt: 'end' });
}

View File

@@ -0,0 +1,22 @@
import { User } from '@/db/models/User';
import { Metrics } from '@/modules/metrics';
import { EntityManager } from '@mikro-orm/postgresql';
export async function updateMetrics(em: EntityManager, metrics: Metrics) {
const users = await em
.createQueryBuilder(User)
.groupBy('namespace')
.count()
.select(['namespace', 'count'])
.execute<
{
namespace: string;
count: string;
}[]
>();
metrics.user.reset();
users.forEach((v) => {
metrics?.user.inc({ namespace: v.namespace }, Number(v.count));
});
}

View File

@@ -1,5 +1,6 @@
import { formatSession } from '@/db/models/Session';
import { User, formatUser } from '@/db/models/User';
import { getMetrics } from '@/modules/metrics';
import { assertCaptcha } from '@/services/captcha';
import { handle } from '@/services/handler';
import { makeRouter } from '@/services/router';
@@ -37,6 +38,7 @@ export const manageAuthRouter = makeRouter((app) => {
);
await em.persistAndFlush([user, session]);
getMetrics().user.inc({ namespace: body.namespace }, 1);
return {
user: formatUser(user),