From 214ff28d7c36af9310c522da22b1f687d0383a5a Mon Sep 17 00:00:00 2001 From: Ali Zemani Date: Wed, 28 Aug 2024 12:36:16 +0330 Subject: [PATCH] logs ? --- src/index.ts | 26 ++++++++----------- src/utils/logs.ts | 64 +++++++++++------------------------------------ 2 files changed, 24 insertions(+), 66 deletions(-) diff --git a/src/index.ts b/src/index.ts index 865216d..d4346b7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,8 +4,6 @@ import { createBot } from "./bot/bot"; import HomePageContent from "./front"; import AboutPageContent from "./front/about"; import pageLayout from "./front/layout"; -import { CurrentConversation, User } from "./types"; -import { KVModel } from "./utils/kv-storage"; import Logger from "./utils/logs"; import { Router } from "./utils/router"; import { convertToPersianNumbers } from "./utils/tools"; @@ -56,9 +54,9 @@ router.get( "/api/chart-data", async (request: Request, env: Environment, ctx: ExecutionContext) => { let onlineUsersChartData; - let onlineUsersCount; - let conversationsCount; - let usersCount; + let onlineUsersCount = 0; + let conversationsCount = 0; + let usersCount = 0; try { const logger = new Logger(env.nekonymousr2); @@ -71,23 +69,18 @@ router.get( endDate ); - const logs = await logger.getLogs(); - onlineUsersCount = logs.filter( - (log) => log.action === "new_conversation" - ).length; - conversationsCount = logs.filter( - (log) => log.action === "new_conversation" - ).length; - usersCount = logs.filter((log) => log.action === "new_user").length; + const newConversationLogs = await logger.getLogs("new_conversation"); + const newUserLogs = await logger.getLogs("new_user"); + + onlineUsersCount = newConversationLogs.length; + conversationsCount = newConversationLogs.length; // Assuming each "new_conversation" log represents a conversation + usersCount = newUserLogs.length; } catch (error) { console.error("Failed to generate chart data", error); onlineUsersChartData = { labels: [], data: [], }; - onlineUsersCount = 0; - conversationsCount = 0; - usersCount = 0; } return Response.json({ @@ -98,6 +91,7 @@ router.get( }); } ); + /** * Define the bot webhook route. * This handles incoming webhook requests from Telegram to the bot. diff --git a/src/utils/logs.ts b/src/utils/logs.ts index 2bf4e74..a5e8e10 100644 --- a/src/utils/logs.ts +++ b/src/utils/logs.ts @@ -13,12 +13,13 @@ class Logger { } /** - * Generates a unique key for each log entry based on the current timestamp. + * Generates a unique key for each log entry based on the current timestamp and action. + * @param {string} action - The action name to include in the log key. * @returns {string} - The key to use when storing the log entry in R2. */ - private generateLogKey(): string { + private generateLogKey(action: string): string { const timestamp = new Date().toISOString(); - return `${this.logKeyPrefix}${timestamp}.json`; + return `${this.logKeyPrefix}${action}/${timestamp}.json`; } /** @@ -41,7 +42,7 @@ class Logger { details, }; - const logKey = this.generateLogKey(); + const logKey = this.generateLogKey(action); await this.r2Bucket.put(logKey, JSON.stringify(logEntry)); } catch (error) { console.error(`Failed to save log entry for action: ${action}`, error); @@ -51,21 +52,19 @@ class Logger { /** * Retrieves log entries from the R2 bucket. * If the R2 bucket is not available, this method will return an empty array. - * @param {string} [prefix] - An optional prefix to filter log entries (e.g., specific actions). + * @param {string} [action] - An optional action to filter log entries (e.g., "new_user"). * @returns {Promise} - A promise that resolves to an array of log entries. */ - public async getLogs(prefix?: string): Promise { + public async getLogs(action?: string): Promise { if (!this.r2Bucket) { console.warn("R2 bucket is not defined. Returning an empty log list."); return []; } try { + const prefix = action ? `${this.logKeyPrefix}${action}/` : this.logKeyPrefix; const logs: LogEntry[] = []; - const options = prefix - ? { prefix: `${this.logKeyPrefix}${prefix}` } - : { prefix: this.logKeyPrefix }; - const objects = await this.r2Bucket.list(options); + const objects = await this.r2Bucket.list({ prefix }); for (const object of objects.objects) { const logData = await this.r2Bucket.get(object.key); @@ -95,11 +94,6 @@ class Logger { startDate: Date, endDate: Date ): Promise { - if (!this.r2Bucket) { - console.warn("R2 bucket is not defined. Returning an empty log list."); - return []; - } - const allLogs = await this.getLogs(action); return allLogs.filter((log) => { const logDate = new Date(log.timestamp); @@ -108,52 +102,22 @@ class Logger { } /** - * Example usage: Generates a JSON array of online users per week for graphing purposes. - * If the R2 bucket is not available, this method will return an empty array. + * Generates chart data for online users per week. + * If the R2 bucket is not available, this method will return empty labels and data. * @param {Date} startDate - The start of the week. * @param {Date} endDate - The end of the week. - * @returns {Promise} - A promise that resolves to a JSON array of online user data. + * @returns {Promise<{ labels: string[], data: number[] }>} - A promise that resolves to an object with labels and data for graphing. */ - public async generateOnlineUsersReport( + public async generateOnlineUsersChartData( startDate: Date, endDate: Date - ): Promise { - if (!this.r2Bucket) { - console.warn("R2 bucket is not defined. Returning an empty report."); - return []; - } - + ): Promise<{ labels: string[]; data: number[] }> { const logs = await this.getLogsByActionAndDateRange( "new_conversation", startDate, endDate ); - const onlineUsers: any[] = logs.map((log) => ({ - timestamp: log.timestamp, - })); - - return onlineUsers; - } - - /** - * Example usage: Generates chart data for online users per week. - * If the R2 bucket is not available, this method will return empty labels and data. - * @param {Date} startDate - The start of the week. - * @param {Date} endDate - The end of the week. - * @returns {Promise<{ labels: string[], data: number[] }>} - A promise that resolves to an object with labels and data for graphing. - */ - public async generateOnlineUsersChartData( - startDate: Date, - endDate: Date - ): Promise<{ labels: string[]; data: number[] }> { - if (!this.r2Bucket) { - console.warn("R2 bucket is not defined. Returning empty chart data."); - return { labels: [], data: [] }; - } - - const logs = await this.generateOnlineUsersReport(startDate, endDate); - // Group by day and count online users const chartData: { [key: string]: number } = {}; logs.forEach((log) => { const day = log.timestamp.split("T")[0]; // Get only the date part