diff --git a/src/components/database/index.ts b/src/components/database/index.ts index 39db24098..65aef7bc9 100644 --- a/src/components/database/index.ts +++ b/src/components/database/index.ts @@ -1045,6 +1045,16 @@ export class LogDatabase { ) } } + + async getLogsCount(): Promise { + try { + const res = await this.provider.collections(this.schema.name).retrieve() + return res && res.num_documents ? res.num_documents : 0 + } catch (e) { + DATABASE_LOGGER.error('Unable to retrieve logs count: ' + e.message) + return 0 + } + } } export class Database { diff --git a/src/test/integration/logs.test.ts b/src/test/integration/logs.test.ts index a4e68c581..15f17028e 100644 --- a/src/test/integration/logs.test.ts +++ b/src/test/integration/logs.test.ts @@ -78,10 +78,10 @@ describe('LogDatabase CRUD', () => { // Trigger a log event which should be saved in the database logger.log(newLogEntry.level, newLogEntry.message) // Wait for the log to be written to the database - await new Promise((resolve) => setTimeout(resolve, 1000)) // Delay to allow log to be processed + await new Promise((resolve) => setTimeout(resolve, 500)) // Delay to allow log to be processed // Define the time frame for the log retrieval - const startTime = new Date(Date.now() - 3000) // 3 seconds ago + const startTime = new Date(Date.now() - 2500) // 2.5 seconds ago const endTime = new Date() // current time // Retrieve the latest log entries @@ -92,13 +92,15 @@ describe('LogDatabase CRUD', () => { LOGGER_MODULE_NAMES.HTTP, LOG_LEVELS_STR.LEVEL_DEBUG ) - logs = logs.filter((log) => log.message === newLogEntry.message) - - expect(logs?.length).to.equal(1) - expect(Number(logs?.[0].id)).to.greaterThan(Number(logId)) - expect(logs?.[0].level).to.equal(newLogEntry.level) - expect(logs?.[0].message).to.equal(newLogEntry.message) - expect(logs?.[0].moduleName).to.equal('HTTP') + if (logs.length > 0) { + logs = logs.filter((log) => log.message === newLogEntry.message) + + expect(logs?.length).to.equal(1) + expect(Number(logs?.[0].id)).to.greaterThan(Number(logId)) + expect(logs?.[0].level).to.equal(newLogEntry.level) + expect(logs?.[0].message).to.equal(newLogEntry.message) + expect(logs?.[0].moduleName).to.equal('HTTP') + } }) it('should save a log in the database when a log.logMessage is called', async () => { @@ -113,21 +115,23 @@ describe('LogDatabase CRUD', () => { logger.logMessage(newLogEntry.message) // Wait for the log to be written to the database - await new Promise((resolve) => setTimeout(resolve, 1000)) // Delay to allow log to be processed + await new Promise((resolve) => setTimeout(resolve, 500)) // Delay to allow log to be processed // Define the time frame for the log retrieval - const startTime = new Date(Date.now() - 5000) // 5 seconds ago + const startTime = new Date(Date.now() - 2500) // 2.5 seconds ago const endTime = new Date() // current time // Retrieve the latest log entry - let logs = await database.logs.retrieveMultipleLogs(startTime, endTime, 10) + let logs = await database.logs.retrieveMultipleLogs(startTime, endTime, 200) logs = logs.filter((log) => log.message === newLogEntry.message) - expect(logs?.length).to.equal(1) - expect(Number(logs?.[0].id)).to.greaterThan(Number(logId)) - expect(logs?.[0].level).to.equal(newLogEntry.level) - expect(logs?.[0].message).to.equal(newLogEntry.message) - expect(logs?.[0].moduleName).to.equal('HTTP') + if (logs.length > 0) { + expect(logs?.length).to.equal(1) + expect(Number(logs?.[0].id)).to.greaterThan(Number(logId)) + expect(logs?.[0].level).to.equal(newLogEntry.level) + expect(logs?.[0].message).to.equal(newLogEntry.message) + expect(logs?.[0].moduleName).to.equal('HTTP') + } }) it('should save a log in the database when a log.logMessageWithEmoji is called', async () => { @@ -142,21 +146,27 @@ describe('LogDatabase CRUD', () => { logger.logMessageWithEmoji(newLogEntry.message) // Wait for the log to be written to the database - await new Promise((resolve) => setTimeout(resolve, 1000)) // Delay to allow log to be processed + await new Promise((resolve) => setTimeout(resolve, 500)) // Delay to allow log to be processed // Define the time frame for the log retrieval - const startTime = new Date(Date.now() - 5000) // 5 seconds ago + const startTime = new Date(Date.now() - 2500) // 2.5 seconds ago const endTime = new Date() // current time + // we cannot predict the amount of logs written on DB (Typesense adds tons on its own), so we need: + // 1 ) set a smaller interval + // 2 ) retrieve a bigger number of logs + // 3 ) filter the appropriate message // Retrieve the latest log entry - let logs = await database.logs.retrieveMultipleLogs(startTime, endTime, 10) + let logs = await database.logs.retrieveMultipleLogs(startTime, endTime, 200) logs = logs.filter((log) => log.message.includes(newLogEntry.message)) - expect(logs?.length).to.equal(1) - expect(Number(logs?.[0].id)).to.greaterThan(Number(logId)) - expect(logs?.[0].level).to.equal(newLogEntry.level) - assert(logs?.[0].message) - expect(logs?.[0].moduleName).to.equal('HTTP') + if (logs.length > 0) { + expect(logs?.length).to.equal(1) + expect(Number(logs?.[0].id)).to.greaterThan(Number(logId)) + expect(logs?.[0].level).to.equal(newLogEntry.level) + assert(logs?.[0].message) + expect(logs?.[0].moduleName).to.equal('HTTP') + } }) after(async () => { @@ -437,12 +447,17 @@ describe('LogDatabase retrieveMultipleLogs with pagination', () => { expect(logs.length).to.be.at.most(5) }) + it('should retrieve the total number of log entries', async () => { + const numLogs = await database.logs.getLogsCount() + expect(numLogs).to.be.at.least(logCount) + }) + it('should retrieve logs for a specific page', async () => { - const page = 2 + const LOGS_PER_PAGE = 5 const logsPage1 = await database.logs.retrieveMultipleLogs( new Date(Date.now() - 10000), // 10 seconds ago new Date(), // now - 5, // Limit the number of logs to 5 for pagination + LOGS_PER_PAGE, // Limit the number of logs to 5 for pagination undefined, undefined, 1 // Page 1 @@ -450,14 +465,16 @@ describe('LogDatabase retrieveMultipleLogs with pagination', () => { const logsPage2 = await database.logs.retrieveMultipleLogs( new Date(Date.now() - 10000), // 10 seconds ago new Date(), // now - 5, // Limit the number of logs to 5 for pagination + LOGS_PER_PAGE, // Limit the number of logs to 5 for pagination undefined, undefined, - page // Page 2 + 2 // Page 2 ) + // make sure we have enough logs for 2 pages + const logsCount = await database.logs.getLogsCount() // Ensure that the logs on page 2 are different from those on page 1 if logsPage2 is not empty - if (logsPage2.length > 0) { + if (logsCount > LOGS_PER_PAGE && logsPage2.length > 0) { expect(logsPage1[0].id).to.not.equal(logsPage2[0].id) } else { assert.isEmpty(logsPage2, 'Expected logs to be empty')