From e9e6d8a69c42d674a9552e578af9862d74f1b951 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Mon, 13 May 2024 14:37:02 +0100 Subject: [PATCH] Server: Add uploaded data size to report --- packages/server/src/routes/admin/reports.ts | 8 ++++++ .../src/services/reports/userActivity.test.ts | 2 ++ .../src/services/reports/userActivity.ts | 26 +++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/server/src/routes/admin/reports.ts b/packages/server/src/routes/admin/reports.ts index f234bfc5c9..18096f63de 100644 --- a/packages/server/src/routes/admin/reports.ts +++ b/packages/server/src/routes/admin/reports.ts @@ -9,6 +9,7 @@ import { adminUserUrl, adminReportUrl } from '../../utils/urlUtils'; import { Hour } from '../../utils/time'; import { ErrorNotFound } from '../../utils/errors'; import { ReportType } from '../../services/reports/types'; +import { formatBytes } from '../../utils/bytes'; const router: Router = new Router(RouteType.Web); @@ -59,6 +60,9 @@ router.get('admin/reports/:id', async (path: SubPath, ctx: AppContext) => { { value: change.delete_count.toString(), }, + { + value: formatBytes(change.uploaded_size), + }, ], }); } @@ -85,6 +89,10 @@ router.get('admin/reports/:id', async (path: SubPath, ctx: AppContext) => { name: 'deleted_count', label: 'Deleted', }, + { + name: 'uploaded_size', + label: 'Uploaded', + }, ], rows: changeRows, }; diff --git a/packages/server/src/services/reports/userActivity.test.ts b/packages/server/src/services/reports/userActivity.test.ts index 3b6c849b81..01c4846de1 100644 --- a/packages/server/src/services/reports/userActivity.test.ts +++ b/packages/server/src/services/reports/userActivity.test.ts @@ -50,6 +50,7 @@ describe('reports/userActivity', () => { create_count: 0, update_count: 2, delete_count: 1, + uploaded_size: 0, }, { user_id: user2.id, @@ -57,6 +58,7 @@ describe('reports/userActivity', () => { create_count: 1, update_count: 1, delete_count: 0, + uploaded_size: 350, // Note: this will break whenever the item sync format is changed }, ], ); diff --git a/packages/server/src/services/reports/userActivity.ts b/packages/server/src/services/reports/userActivity.ts index 1cf7880617..0f1e33cf6d 100644 --- a/packages/server/src/services/reports/userActivity.ts +++ b/packages/server/src/services/reports/userActivity.ts @@ -1,5 +1,6 @@ import { DbConnection } from '../../db'; -import { ChangeType, Uuid } from '../database/types'; +import { unique } from '../../utils/array'; +import { ChangeType, Item, Uuid } from '../database/types'; export interface Options { interval: number; @@ -19,6 +20,7 @@ export default async (db: DbConnection, options: Options = null) => { updated_time: number; counter: number; type: ChangeType; + item_id: Uuid; } interface GroupedChange { @@ -27,14 +29,17 @@ export default async (db: DbConnection, options: Options = null) => { create_count: number; update_count: number; delete_count: number; + uploaded_size: number; } + type ItemSlice = Pick; + let changes: ChangeSlice[] = []; let counter = 0; while (true) { const query = db('changes') - .select('user_id', 'updated_time', 'counter', 'type') + .select('user_id', 'updated_time', 'counter', 'item_id', 'type') .orderBy('counter', 'desc') .limit(options.batchSize); @@ -53,7 +58,14 @@ export default async (db: DbConnection, options: Options = null) => { counter = filteredResults[filteredResults.length - 1].counter; } + const itemIds = unique(changes.map(c => c.item_id)); + + const items: ItemSlice[] = await db('items') + .select('id', 'content_size') + .whereIn('id', itemIds); + const groupedChanges: GroupedChange[] = []; + for (const c of changes) { let grouped = groupedChanges.find(g => g.user_id === c.user_id); if (!grouped) { @@ -63,6 +75,7 @@ export default async (db: DbConnection, options: Options = null) => { create_count: 0, update_count: 0, delete_count: 0, + uploaded_size: 0, }; groupedChanges.push(grouped); @@ -72,6 +85,15 @@ export default async (db: DbConnection, options: Options = null) => { if (c.type === ChangeType.Update) grouped.update_count++; if (c.type === ChangeType.Delete) grouped.delete_count++; grouped.total_count++; + + const item = items.find(it => it.id === c.item_id); + if (item) { + if ([ChangeType.Create, ChangeType.Update].includes(c.type)) { + grouped.uploaded_size += item.content_size; + } + } + + if (!itemIds.includes(c.item_id)) itemIds.push(c.item_id); } groupedChanges.sort((a, b) => {