From e372ce696465b19d1d45bbfa9e4ff3c3bf4a54be Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Thu, 20 Jun 2024 18:23:38 +0700 Subject: [PATCH 1/7] add analytic metrics --- cortex-js/src/command.ts | 3 + .../repositories/telemetry.interface.ts | 20 +++- .../telemetry/crash-report.interface.ts | 16 --- .../domain/telemetry/telemetry.interface.ts | 28 +++-- .../infrastructure/commanders/chat.command.ts | 19 ++- .../infrastructure/commanders/init.command.ts | 23 +++- .../commanders/models/model-pull.command.ts | 16 ++- .../telemetry/telemetry.repository.ts | 100 ++++++++++++---- .../file-manager/file-manager.service.ts | 29 +++++ .../usecases/telemetry/telemetry.usecases.ts | 108 +++++++++++++++++- 10 files changed, 305 insertions(+), 57 deletions(-) delete mode 100644 cortex-js/src/domain/telemetry/crash-report.interface.ts diff --git a/cortex-js/src/command.ts b/cortex-js/src/command.ts index 402ac5147..8a57f07d1 100644 --- a/cortex-js/src/command.ts +++ b/cortex-js/src/command.ts @@ -28,10 +28,13 @@ async function bootstrap() { telemetryUseCase = await app.resolve(TelemetryUsecases); contextService = await app.resolve(ContextService); + const anonymousData = await telemetryUseCase!.updateAnonymousData(); + await telemetryUseCase!.sendActivationEvent(TelemetrySource.CLI); telemetryUseCase!.sendCrashReport(); await contextService!.init(async () => { contextService!.set('source', TelemetrySource.CLI); + contextService!.set('sessionId', anonymousData?.sessionId); return CommandFactory.runApplication(app); }); diff --git a/cortex-js/src/domain/repositories/telemetry.interface.ts b/cortex-js/src/domain/repositories/telemetry.interface.ts index f67d77aeb..065f07a85 100644 --- a/cortex-js/src/domain/repositories/telemetry.interface.ts +++ b/cortex-js/src/domain/repositories/telemetry.interface.ts @@ -1,6 +1,8 @@ import { CrashReportAttributes, + EventAttributes, Telemetry, + TelemetryAnonymized, TelemetrySource, } from '../telemetry/telemetry.interface'; @@ -8,15 +10,31 @@ export abstract class TelemetryRepository { abstract readCrashReports( callback: (Telemetry: Telemetry) => void, ): Promise; + abstract createCrashReport( crashReport: CrashReportAttributes, source?: TelemetrySource, ): Promise; + abstract getLastCrashReport(): Promise; + abstract markLastCrashReportAsSent(): Promise; + abstract sendTelemetryToOTelCollector( endpoint: string, telemetry: Telemetry, ): Promise; - abstract sendTelemetryToServer(telemetry: Telemetry): Promise; + + abstract sendTelemetryToServer( + telemetryEvent: Telemetry['event'], + ): Promise; + + abstract sendEvent( + events: EventAttributes[], + source: TelemetrySource, + ): Promise; + + abstract getAnonymizedData(): Promise; + + abstract updateAnonymousData(data: TelemetryAnonymized): Promise; } diff --git a/cortex-js/src/domain/telemetry/crash-report.interface.ts b/cortex-js/src/domain/telemetry/crash-report.interface.ts deleted file mode 100644 index 7eb55a707..000000000 --- a/cortex-js/src/domain/telemetry/crash-report.interface.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface TelemetryResource { - timestamp: number; - osName: string; - osVersion: string; - appVersion: string; - architecture: string; -} - -export interface CrashReportAttributes { - timestamp: number; - modelId: string; - operation: string; - params: any; - contextLength: number; - tokenPerSecond: number; -} diff --git a/cortex-js/src/domain/telemetry/telemetry.interface.ts b/cortex-js/src/domain/telemetry/telemetry.interface.ts index b1ed951e2..471a34f38 100644 --- a/cortex-js/src/domain/telemetry/telemetry.interface.ts +++ b/cortex-js/src/domain/telemetry/telemetry.interface.ts @@ -8,14 +8,7 @@ export interface TelemetryResource { source?: TelemetrySource; cpu?: string; gpus?: string; - // todo: consider about sessionId - // sessionId: string; -} - -export interface CrashReportEvent { - modelId?: string; - sessionId: string; - stack?: string; + sessionId?: string; } export interface Resource { @@ -77,6 +70,7 @@ export interface CrashReportAttributes { stack?: string; message: string; payload: CrashReportPayload; + sessionId?: string; } export interface TelemetryEventMetadata { @@ -90,3 +84,21 @@ export interface Telemetry { resourceLogs: TelemetryEvent[]; }; } + +export enum EventName { + INIT = 'init', + DOWNLOAD_MODEL = 'download-model', + CHAT = 'chat', + ACTIVATE = 'activate', +} + +export interface EventAttributes { + name: string; + modelId?: string; + sessionId?: string; +} + +export interface TelemetryAnonymized { + sessionId: string | null; + lastActiveAt?: string | null; +} diff --git a/cortex-js/src/infrastructure/commanders/chat.command.ts b/cortex-js/src/infrastructure/commanders/chat.command.ts index cbb4dadce..cd915bfb5 100644 --- a/cortex-js/src/infrastructure/commanders/chat.command.ts +++ b/cortex-js/src/infrastructure/commanders/chat.command.ts @@ -11,6 +11,11 @@ import { ModelsUsecases } from '@/usecases/models/models.usecases'; import { SetCommandContext } from './decorators/CommandContext'; import { ContextService } from '@/util/context.service'; import { ModelStat } from './types/model-stat.interface'; +import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; +import { + EventName, + TelemetrySource, +} from '@/domain/telemetry/telemetry.interface'; type ChatOptions = { threadId?: string; @@ -36,6 +41,7 @@ export class ChatCommand extends CommandRunner { private readonly modelsUsecases: ModelsUsecases, private readonly psCliUsecases: PSCliUsecases, readonly contextService: ContextService, + private readonly telemetryUsecases: TelemetryUsecases, ) { super(); } @@ -66,14 +72,23 @@ export class ChatCommand extends CommandRunner { } if (!message) options.attach = true; - - return this.chatCliUsecases.chat( + const result = await this.chatCliUsecases.chat( modelId, options.threadId, message, // Accept both message from inputs or arguments options.attach, false, // Do not stop cortex session or loaded model ); + this.telemetryUsecases.sendEvent( + [ + { + name: EventName.CHAT, + modelId, + }, + ], + TelemetrySource.CLI, + ); + return result; } modelInquiry = async (models: ModelStat[]) => { diff --git a/cortex-js/src/infrastructure/commanders/init.command.ts b/cortex-js/src/infrastructure/commanders/init.command.ts index b843c78f5..f4da926dc 100644 --- a/cortex-js/src/infrastructure/commanders/init.command.ts +++ b/cortex-js/src/infrastructure/commanders/init.command.ts @@ -8,6 +8,11 @@ import { InitCliUsecases } from './usecases/init.cli.usecases'; import { InitOptions } from './types/init-options.interface'; import { SetCommandContext } from './decorators/CommandContext'; import { ContextService } from '@/util/context.service'; +import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; +import { + EventName, + TelemetrySource, +} from '@/domain/telemetry/telemetry.interface'; @SubCommand({ name: 'init', @@ -24,16 +29,24 @@ export class InitCommand extends CommandRunner { private readonly inquirerService: InquirerService, private readonly initUsecases: InitCliUsecases, readonly contextService: ContextService, + private readonly telemetryUsecases: TelemetryUsecases, ) { super(); } async run(passedParams: string[], options?: InitOptions): Promise { - if (options?.silent) { - return this.initSilently(passedParams); - } else { - return this.initPrompts(passedParams, options); - } + const result = options?.silent + ? await this.initSilently(passedParams) + : await this.initPrompts(passedParams, options); + this.telemetryUsecases.sendEvent( + [ + { + name: EventName.INIT, + }, + ], + TelemetrySource.CLI, + ); + return result; } private initSilently = async ( diff --git a/cortex-js/src/infrastructure/commanders/models/model-pull.command.ts b/cortex-js/src/infrastructure/commanders/models/model-pull.command.ts index c6b81d9cf..b0e4471ca 100644 --- a/cortex-js/src/infrastructure/commanders/models/model-pull.command.ts +++ b/cortex-js/src/infrastructure/commanders/models/model-pull.command.ts @@ -4,6 +4,11 @@ import { SetCommandContext } from '../decorators/CommandContext'; import { ContextService } from '@/util/context.service'; import { ModelsCliUsecases } from '@commanders/usecases/models.cli.usecases'; import { ModelNotFoundException } from '@/infrastructure/exception/model-not-found.exception'; +import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; +import { + EventName, + TelemetrySource, +} from '@/domain/telemetry/telemetry.interface'; @SubCommand({ name: 'pull', @@ -18,6 +23,7 @@ export class ModelPullCommand extends CommandRunner { constructor( private readonly modelsCliUsecases: ModelsCliUsecases, readonly contextService: ContextService, + private readonly telemetryUsecases: TelemetryUsecases, ) { super(); } @@ -27,7 +33,15 @@ export class ModelPullCommand extends CommandRunner { console.error('Model Id is required'); exit(1); } - + this.telemetryUsecases.sendEvent( + [ + { + name: EventName.DOWNLOAD_MODEL, + modelId: passedParams[0], + }, + ], + TelemetrySource.CLI, + ); await this.modelsCliUsecases .pullModel(passedParams[0]) .catch((e: Error) => { diff --git a/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts b/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts index fe5be3be5..39f4a1f71 100644 --- a/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts +++ b/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts @@ -10,6 +10,8 @@ import { TelemetryResource, Telemetry, TelemetryEventMetadata, + EventAttributes, + TelemetryAnonymized, } from '@/domain/telemetry/telemetry.interface'; import { Injectable } from '@nestjs/common'; import { join } from 'path'; @@ -29,6 +31,7 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { }; private readonly crashReportFileName = 'crash-report.jsonl'; + private readonly anonymizedDataFileName = 'metadata.json'; constructor(private readonly fileManagerService: FileManagerService) {} private async getTelemetryDirectory(): Promise { @@ -45,18 +48,17 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { return hash.digest('hex'); } - async sendTelemetryToServer(telemetry: Telemetry) { + async sendTelemetryToServer( + telemetryEvent: Telemetry['event'], + type: 'crash-report' | 'metrics' = 'crash-report', + ): Promise { try { - await axios.post( - `${telemetryServerUrl}/api/v1/crash-report`, - telemetry.event, - { - headers: { - 'Content-Type': 'application/json', - 'cortex-checksum': this.generateChecksum(telemetry.event), - }, + await axios.post(`${telemetryServerUrl}/api/v1/${type}`, telemetryEvent, { + headers: { + 'Content-Type': 'application/json', + 'cortex-checksum': this.generateChecksum(telemetryEvent), }, - ); + }); } catch (error) {} } @@ -117,10 +119,11 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { crashReport: CrashReportAttributes, source: TelemetrySource, ): Promise { - const telemetryEvent = await this.convertCrashReportToTelemetryEvent( - crashReport, + const telemetryEvent = await this.convertToTelemetryEvent({ + attributes: crashReport, source, - ); + type: 'crash-report', + }); const metadata: TelemetryEventMetadata = { createdAt: new Date().toISOString(), sentAt: null, @@ -136,11 +139,15 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { ); } - private async convertCrashReportToTelemetryEvent( - crashReport: CrashReportAttributes, - // move this to telemetryResource - source: TelemetrySource, - ): Promise { + private async convertToTelemetryEvent({ + attributes, + source, + type, + }: { + attributes: CrashReportAttributes | EventAttributes; + source: TelemetrySource; + type: 'crash-report' | 'metrics'; + }): Promise { const gpus = (await systemInformation.graphics()).controllers.map( ({ model, vendor, vram, vramDynamic }) => ({ model, @@ -149,9 +156,17 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { vramDynamic, }), ); + + const body = + type === 'crash-report' + ? (attributes as CrashReportAttributes).message + : (attributes as EventAttributes).name; + + const severity = type === 'crash-report' ? 'ERROR' : 'INFO'; + const resourceAttributes: Attribute[] = Object.entries({ ...this.telemetryResource, - 'service.name': 'crash-reporting', + 'service.name': type, cpu: os.cpus()[0].model, gpus: JSON.stringify(gpus), source, @@ -159,7 +174,7 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { key, value: { stringValue: value }, })); - const telemetryLogAttributes: Attribute[] = Object.entries(crashReport).map( + const telemetryLogAttributes: Attribute[] = Object.entries(attributes).map( ([key, value]) => { if (typeof value === 'object') { return { @@ -194,8 +209,8 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { startTimeUnixNano: ( BigInt(Date.now()) * BigInt(1000000) ).toString(), - body: { stringValue: crashReport.message }, - severityText: 'ERROR', + body: { stringValue: body }, + severityText: severity, attributes: telemetryLogAttributes, }, ], @@ -203,4 +218,45 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { ], }; } + + async sendEvent( + events: EventAttributes[], + source: TelemetrySource, + ): Promise { + const telemetryEvents = await Promise.all( + events.map(async (event) => + this.convertToTelemetryEvent({ + attributes: event, + source, + type: 'metrics', + }), + ), + ); + await this.sendTelemetryToServer( + { + resourceLogs: telemetryEvents, + }, + 'metrics', + ); + } + + async getAnonymizedData(): Promise { + const content = await this.fileManagerService.readFile( + join(await this.getTelemetryDirectory(), this.anonymizedDataFileName), + ); + + if (!content) { + return null; + } + + const data = JSON.parse(content) as TelemetryAnonymized; + return data; + } + + async updateAnonymousData(data: TelemetryAnonymized): Promise { + return this.fileManagerService.writeFile( + join(await this.getTelemetryDirectory(), this.anonymizedDataFileName), + JSON.stringify(data), + ); + } } diff --git a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts index 09faef48e..a07de2f9b 100644 --- a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts +++ b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts @@ -239,4 +239,33 @@ export class FileManagerService { await promises.mkdir(folderPath, { recursive: true }); } } + + async readFile(filePath: string): Promise { + try { + const isFileExist = existsSync(filePath); + if (!isFileExist) { + return null; + } + const content = await promises.readFile(filePath, { + encoding: 'utf8', + }); + return content; + } catch (error) { + console.error('Error reading json file:', error); + throw error; + } + } + async writeFile(filePath: string, data: any): Promise { + try { + const dirPath = filePath.split('/').slice(0, -1).join('/'); + await this.createFolderIfNotExistInDataFolder(dirPath); + return promises.writeFile(filePath, data, { + encoding: 'utf8', + flag: 'w+', + }); + } catch (error) { + console.error('Error writing json file:', error); + throw error; + } + } } diff --git a/cortex-js/src/usecases/telemetry/telemetry.usecases.ts b/cortex-js/src/usecases/telemetry/telemetry.usecases.ts index e31a766fe..0ee52a17a 100644 --- a/cortex-js/src/usecases/telemetry/telemetry.usecases.ts +++ b/cortex-js/src/usecases/telemetry/telemetry.usecases.ts @@ -1,16 +1,25 @@ import { TelemetryRepository } from '@/domain/repositories/telemetry.interface'; import { CrashReportAttributes, + EventAttributes, + EventName, Telemetry, + TelemetryAnonymized, TelemetrySource, } from '@/domain/telemetry/telemetry.interface'; import { ContextService } from '@/util/context.service'; import { HttpException, Inject, Injectable, Scope } from '@nestjs/common'; +import { v4 } from 'uuid'; @Injectable({ scope: Scope.TRANSIENT }) export class TelemetryUsecases { private readonly crashReports: string[] = []; - private readonly maxSize = 100; + private readonly maxSize = 10; + private metricQueue: EventAttributes[] = []; + private readonly maxQueueSize = 10; + private readonly flushInterval = 1000 * 60 * 5; + private interval: NodeJS.Timeout = this.flushMetricQueueInterval(); + private lastActiveAt?: string | null; constructor( @Inject('TELEMETRY_REPOSITORY') @@ -46,7 +55,7 @@ export class TelemetryUsecases { const crashReport = await this.telemetryRepository.getLastCrashReport(); if (crashReport && !crashReport.metadata.sentAt) { const promises = [ - this.telemetryRepository.sendTelemetryToServer(crashReport), + this.telemetryRepository.sendTelemetryToServer(crashReport.event), ]; const collectorEndpoint = process.env.CORTEX_EXPORTER_OLTP_ENDPOINT; if (collectorEndpoint) { @@ -80,6 +89,7 @@ export class TelemetryUsecases { endpoint: this.contextService.get('endpoint') || '', command: this.contextService.get('command') || '', }, + sessionId: this.contextService.get('sessionId') || '', }; } @@ -87,6 +97,10 @@ export class TelemetryUsecases { return process.env.CORTEX_CRASH_REPORT !== '0'; } + private isMetricsEnabled(): boolean { + return process.env.CORTEX_METRICS !== '0'; + } + private async catchException(): Promise { process.on('uncaughtException', async (error: Error) => { await this.createCrashReport( @@ -102,4 +116,94 @@ export class TelemetryUsecases { ); }); } + + async sendEvent( + events: EventAttributes[], + source: TelemetrySource, + ): Promise { + try { + if (!this.isMetricsEnabled()) return; + const sessionId = (this.contextService.get('sessionId') as string) || ''; + const sessionEvents = events.map((event) => ({ + ...event, + sessionId, + })); + await this.telemetryRepository.sendEvent(sessionEvents, source); + } catch (e) { + console.error('Error sending event:', e); + } + } + + async sendActivationEvent(source: TelemetrySource): Promise { + try { + if (!this.isMetricsEnabled()) return; + if (!this.lastActiveAt) { + const currentData = await this.telemetryRepository.getAnonymizedData(); + this.lastActiveAt = currentData?.lastActiveAt; + } + console.log('lastActiveAt:', this.lastActiveAt); + const isActivatedToday = + this.lastActiveAt && + new Date(this.lastActiveAt).getDate() === new Date().getDate(); + console.log('isActivatedToday:', isActivatedToday); + if (isActivatedToday) return; + console.log('Sending activation event'); + await this.telemetryRepository.sendEvent( + [ + { + name: EventName.ACTIVATE, + }, + ], + source, + ); + this.lastActiveAt = new Date().toISOString(); + await this.updateAnonymousData(this.lastActiveAt); + } catch (e) { + console.error('Error sending activation event:', e); + } + } + + async addEventToQueue(event: EventAttributes): Promise { + if (!this.isMetricsEnabled()) return; + this.metricQueue.push({ + ...event, + sessionId: this.contextService.get('sessionId') || '', + }); + if (this.metricQueue.length >= this.maxQueueSize) { + await this.flushMetricQueue(); + } + } + + private async flushMetricQueue(): Promise { + if (this.metricQueue.length > 0) { + clearInterval(this.interval); + await this.sendEvent(this.metricQueue, TelemetrySource.CORTEX_SERVER); + this.interval = this.flushMetricQueueInterval(); + this.metricQueue = []; + } + } + + private flushMetricQueueInterval(): NodeJS.Timeout { + return setInterval(() => { + this.flushMetricQueue(); + }, this.flushInterval); + } + + async updateAnonymousData( + lastActiveAt?: string, + ): Promise { + try { + const currentData = await this.telemetryRepository.getAnonymizedData(); + const updatedData = { + ...currentData, + sessionId: currentData?.sessionId || v4(), + ...(lastActiveAt && { lastActiveAt }), + }; + await this.telemetryRepository.updateAnonymousData(updatedData); + return updatedData; + } catch (e) { + console.error('Error updating anonymous data:', e); + return null; + } + } } From f1c168500cf9d2bc90bd76d08a060b871ffdc8fb Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Fri, 21 Jun 2024 11:43:25 +0700 Subject: [PATCH 2/7] update metrics --- cortex-js/src/command.ts | 4 +-- .../commanders/usecases/init.cli.usecases.ts | 11 ++---- .../src/infrastructure/constants/cortex.ts | 2 +- .../controllers/chat.controller.ts | 19 ++++++++++- .../controllers/models.controller.ts | 34 ++++++++++++++++--- cortex-js/src/usecases/chat/chat.usecases.ts | 2 +- 6 files changed, 54 insertions(+), 18 deletions(-) diff --git a/cortex-js/src/command.ts b/cortex-js/src/command.ts index 8a57f07d1..1ecb58d56 100644 --- a/cortex-js/src/command.ts +++ b/cortex-js/src/command.ts @@ -29,12 +29,12 @@ async function bootstrap() { contextService = await app.resolve(ContextService); const anonymousData = await telemetryUseCase!.updateAnonymousData(); - await telemetryUseCase!.sendActivationEvent(TelemetrySource.CLI); - telemetryUseCase!.sendCrashReport(); await contextService!.init(async () => { contextService!.set('source', TelemetrySource.CLI); contextService!.set('sessionId', anonymousData?.sessionId); + telemetryUseCase!.sendActivationEvent(TelemetrySource.CLI); + telemetryUseCase!.sendCrashReport(); return CommandFactory.runApplication(app); }); diff --git a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts index 5c8fda51c..57ada02c1 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/init.cli.usecases.ts @@ -1,11 +1,4 @@ -import { - cpSync, - createWriteStream, - existsSync, - readdir, - readdirSync, - rmSync, -} from 'fs'; +import { cpSync, createWriteStream, existsSync, readdirSync, rmSync } from 'fs'; import { delimiter, join } from 'path'; import { HttpService } from '@nestjs/axios'; import { Presets, SingleBar } from 'cli-progress'; @@ -298,7 +291,7 @@ export class InitCliUsecases { /** * Download and install ONNX engine * @param version - * @param engineFileName + * @param engineFileName */ async installONNXEngine( version: string = 'latest', diff --git a/cortex-js/src/infrastructure/constants/cortex.ts b/cortex-js/src/infrastructure/constants/cortex.ts index 7d458da59..bc2d91064 100644 --- a/cortex-js/src/infrastructure/constants/cortex.ts +++ b/cortex-js/src/infrastructure/constants/cortex.ts @@ -48,4 +48,4 @@ export const CORTEX_ONNX_ENGINE_RELEASES_URL = export const CUDA_DOWNLOAD_URL = 'https://catalog.jan.ai/dist/cuda-dependencies///cuda.tar.gz'; -export const telemetryServerUrl = 'http://192.168.100.30:1338/'; +export const telemetryServerUrl = 'http://192.168.100.30:1338'; diff --git a/cortex-js/src/infrastructure/controllers/chat.controller.ts b/cortex-js/src/infrastructure/controllers/chat.controller.ts index 01039e9ce..0d0b9e3eb 100644 --- a/cortex-js/src/infrastructure/controllers/chat.controller.ts +++ b/cortex-js/src/infrastructure/controllers/chat.controller.ts @@ -4,11 +4,19 @@ import { ChatUsecases } from '@/usecases/chat/chat.usecases'; import { Response } from 'express'; import { ApiOperation, ApiTags, ApiResponse } from '@nestjs/swagger'; import { ChatCompletionResponseDto } from '../dtos/chat/chat-completion-response.dto'; +import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; +import { + EventName, + TelemetrySource, +} from '@/domain/telemetry/telemetry.interface'; @ApiTags('Inference') @Controller('chat') export class ChatController { - constructor(private readonly chatService: ChatUsecases) {} + constructor( + private readonly chatService: ChatUsecases, + private readonly telemetryUsecases: TelemetryUsecases, + ) {} @ApiOperation({ summary: 'Create chat completion', @@ -34,5 +42,14 @@ export class ChatController { } else { res.json(await this.chatService.inference(createChatDto, headers)); } + this.telemetryUsecases.sendEvent( + [ + { + name: EventName.CHAT, + modelId: createChatDto.model, + }, + ], + TelemetrySource.CORTEX_SERVER, + ); } } diff --git a/cortex-js/src/infrastructure/controllers/models.controller.ts b/cortex-js/src/infrastructure/controllers/models.controller.ts index 8df1d7391..83deb16ae 100644 --- a/cortex-js/src/infrastructure/controllers/models.controller.ts +++ b/cortex-js/src/infrastructure/controllers/models.controller.ts @@ -21,6 +21,11 @@ import { StartModelSuccessDto } from '@/infrastructure/dtos/models/start-model-s import { TransformInterceptor } from '../interceptors/transform.interceptor'; import { CortexUsecases } from '@/usecases/cortex/cortex.usecases'; import { ModelSettingsDto } from '../dtos/models/model-settings.dto'; +import { + EventName, + TelemetrySource, +} from '@/domain/telemetry/telemetry.interface'; +import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; @ApiTags('Models') @Controller('models') @@ -29,6 +34,7 @@ export class ModelsController { constructor( private readonly modelsUsecases: ModelsUsecases, private readonly cortexUsecases: CortexUsecases, + private readonly telemetryUsecases: TelemetryUsecases, ) {} @HttpCode(201) @@ -110,8 +116,18 @@ export class ModelsController { ], }) @Get('download/:modelId(*)') - downloadModel(@Param('modelId') modelId: string) { - return this.modelsUsecases.downloadModel(modelId); + async downloadModel(@Param('modelId') modelId: string) { + const result = await this.modelsUsecases.downloadModel(modelId); + this.telemetryUsecases.sendEvent( + [ + { + name: EventName.DOWNLOAD_MODEL, + modelId, + }, + ], + TelemetrySource.CORTEX_SERVER, + ); + return result; } @ApiOperation({ @@ -146,8 +162,18 @@ export class ModelsController { description: 'The unique identifier of the model.', }) @Get('pull/:modelId(*)') - pullModel(@Param('modelId') modelId: string) { - return this.modelsUsecases.pullModel(modelId); + async pullModel(@Param('modelId') modelId: string) { + const result = await this.modelsUsecases.pullModel(modelId); + this.telemetryUsecases.sendEvent( + [ + { + name: EventName.DOWNLOAD_MODEL, + modelId, + }, + ], + TelemetrySource.CORTEX_SERVER, + ); + return result; } @HttpCode(200) diff --git a/cortex-js/src/usecases/chat/chat.usecases.ts b/cortex-js/src/usecases/chat/chat.usecases.ts index 806ebb06a..08705995c 100644 --- a/cortex-js/src/usecases/chat/chat.usecases.ts +++ b/cortex-js/src/usecases/chat/chat.usecases.ts @@ -26,7 +26,7 @@ export class ChatUsecases { ): Promise { const { model: modelId } = createChatDto; const model = await this.modelRepository.findOne(modelId); - + console.log('model', model); if (!model) { throw new ModelNotFoundException(modelId); } From 9143f9d4059119e3d38384dcca27315031d0bd35 Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Fri, 21 Jun 2024 14:21:00 +0700 Subject: [PATCH 3/7] add new event --- .../src/domain/telemetry/telemetry.interface.ts | 1 + cortex-js/src/infrastructure/constants/cortex.ts | 2 +- .../src/usecases/telemetry/telemetry.usecases.ts | 15 ++++++--------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/cortex-js/src/domain/telemetry/telemetry.interface.ts b/cortex-js/src/domain/telemetry/telemetry.interface.ts index 471a34f38..3275c21cd 100644 --- a/cortex-js/src/domain/telemetry/telemetry.interface.ts +++ b/cortex-js/src/domain/telemetry/telemetry.interface.ts @@ -90,6 +90,7 @@ export enum EventName { DOWNLOAD_MODEL = 'download-model', CHAT = 'chat', ACTIVATE = 'activate', + NEW_ACTIVATE = 'new_activate', } export interface EventAttributes { diff --git a/cortex-js/src/infrastructure/constants/cortex.ts b/cortex-js/src/infrastructure/constants/cortex.ts index bc2d91064..1c9fd1f80 100644 --- a/cortex-js/src/infrastructure/constants/cortex.ts +++ b/cortex-js/src/infrastructure/constants/cortex.ts @@ -48,4 +48,4 @@ export const CORTEX_ONNX_ENGINE_RELEASES_URL = export const CUDA_DOWNLOAD_URL = 'https://catalog.jan.ai/dist/cuda-dependencies///cuda.tar.gz'; -export const telemetryServerUrl = 'http://192.168.100.30:1338'; +export const telemetryServerUrl = 'http://localhost:1338'; diff --git a/cortex-js/src/usecases/telemetry/telemetry.usecases.ts b/cortex-js/src/usecases/telemetry/telemetry.usecases.ts index 0ee52a17a..8f0fec724 100644 --- a/cortex-js/src/usecases/telemetry/telemetry.usecases.ts +++ b/cortex-js/src/usecases/telemetry/telemetry.usecases.ts @@ -42,7 +42,6 @@ export class TelemetryUsecases { this.crashReports.shift(); } this.crashReports.push(JSON.stringify(crashReport)); - await this.telemetryRepository.createCrashReport(crashReport, source); } catch (e) {} return; @@ -141,26 +140,25 @@ export class TelemetryUsecases { const currentData = await this.telemetryRepository.getAnonymizedData(); this.lastActiveAt = currentData?.lastActiveAt; } - console.log('lastActiveAt:', this.lastActiveAt); const isActivatedToday = this.lastActiveAt && new Date(this.lastActiveAt).getDate() === new Date().getDate(); - console.log('isActivatedToday:', isActivatedToday); if (isActivatedToday) return; - console.log('Sending activation event'); - await this.telemetryRepository.sendEvent( + const isNewActivation = !this.lastActiveAt; + await this.sendEvent( [ { - name: EventName.ACTIVATE, + name: isNewActivation ? EventName.NEW_ACTIVATE : EventName.ACTIVATE, }, ], source, ); + console.log('Activation event sent', isNewActivation); this.lastActiveAt = new Date().toISOString(); - await this.updateAnonymousData(this.lastActiveAt); } catch (e) { console.error('Error sending activation event:', e); } + await this.updateAnonymousData(this.lastActiveAt); } async addEventToQueue(event: EventAttributes): Promise { @@ -190,7 +188,7 @@ export class TelemetryUsecases { } async updateAnonymousData( - lastActiveAt?: string, + lastActiveAt?: string | null, ): Promise { try { const currentData = await this.telemetryRepository.getAnonymizedData(); @@ -202,7 +200,6 @@ export class TelemetryUsecases { await this.telemetryRepository.updateAnonymousData(updatedData); return updatedData; } catch (e) { - console.error('Error updating anonymous data:', e); return null; } } From e220861a0a8892ba41a01216f1f0518efad659dd Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Thu, 27 Jun 2024 01:17:19 +0700 Subject: [PATCH 4/7] send benchmark to server --- cortex-js/src/command.ts | 2 + .../repositories/telemetry.interface.ts | 10 ++++ .../domain/telemetry/telemetry.interface.ts | 9 ++++ .../usecases/benchmark.cli.usecases.ts | 49 +++++++++++++++---- .../usecases/cli.usecases.module.ts | 2 + .../controllers/chat.controller.ts | 13 ++--- .../controllers/models.controller.ts | 26 +++------- .../telemetry/telemetry.repository.ts | 21 +++++++- cortex-js/src/main.ts | 4 ++ .../usecases/telemetry/telemetry.usecases.ts | 47 ++++++++++++++---- 10 files changed, 137 insertions(+), 46 deletions(-) diff --git a/cortex-js/src/command.ts b/cortex-js/src/command.ts index 1ecb58d56..495888038 100644 --- a/cortex-js/src/command.ts +++ b/cortex-js/src/command.ts @@ -17,10 +17,12 @@ async function bootstrap() { logger: ['warn', 'error'], errorHandler: async (error) => { await telemetryUseCase!.createCrashReport(error, TelemetrySource.CLI); + console.error(error); process.exit(1); }, serviceErrorHandler: async (error) => { await telemetryUseCase!.createCrashReport(error, TelemetrySource.CLI); + console.error(error); process.exit(1); }, }); diff --git a/cortex-js/src/domain/repositories/telemetry.interface.ts b/cortex-js/src/domain/repositories/telemetry.interface.ts index 065f07a85..ff33edea1 100644 --- a/cortex-js/src/domain/repositories/telemetry.interface.ts +++ b/cortex-js/src/domain/repositories/telemetry.interface.ts @@ -1,4 +1,6 @@ +import { ModelStat } from '@/infrastructure/commanders/types/model-stat.interface'; import { + BenchmarkHardware, CrashReportAttributes, EventAttributes, Telemetry, @@ -37,4 +39,12 @@ export abstract class TelemetryRepository { abstract getAnonymizedData(): Promise; abstract updateAnonymousData(data: TelemetryAnonymized): Promise; + + abstract sendBenchmarkToServer(data: { + hardware: BenchmarkHardware; + results: any; + metrics: any; + model: ModelStat; + sessionId: string; + }): Promise; } diff --git a/cortex-js/src/domain/telemetry/telemetry.interface.ts b/cortex-js/src/domain/telemetry/telemetry.interface.ts index 3275c21cd..c897a436e 100644 --- a/cortex-js/src/domain/telemetry/telemetry.interface.ts +++ b/cortex-js/src/domain/telemetry/telemetry.interface.ts @@ -103,3 +103,12 @@ export interface TelemetryAnonymized { sessionId: string | null; lastActiveAt?: string | null; } +export interface BenchmarkHardware { + gpu: any[]; + cpu: any; + board: any; + disk: any[]; + chassis: any; + memLayout: any[]; + os: any; +} diff --git a/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts index 19cf6c951..b3022e6fe 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts @@ -13,6 +13,9 @@ import { CortexUsecases } from '@/usecases/cortex/cortex.usecases'; import { inspect } from 'util'; import { defaultBenchmarkConfiguration } from '@/infrastructure/constants/benchmark'; import { PSCliUsecases } from './ps.cli.usecases'; +import { ModelStat } from '../types/model-stat.interface'; +import { BenchmarkHardware } from '@/domain/telemetry/telemetry.interface'; +import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; @Injectable() export class BenchmarkCliUsecases { @@ -21,6 +24,7 @@ export class BenchmarkCliUsecases { private readonly cortexUsecases: CortexUsecases, private readonly fileService: FileManagerService, private readonly psUsecases: PSCliUsecases, + private readonly telemetryUsecases: TelemetryUsecases, ) {} config: BenchmarkConfig; @@ -46,7 +50,6 @@ export class BenchmarkCliUsecases { detached: false, shell: process.platform == 'win32', }); - return this.cortexUsecases .startCortex() .then(() => @@ -64,8 +67,9 @@ export class BenchmarkCliUsecases { .then((model) => { if (!model) throw new Error('Model is not started, please try again!'); + return model; }) - .then(() => this.runBenchmarks()) + .then((model) => this.runBenchmarks(model)) .then(() => { serveProcess.kill(); process.exit(0); @@ -101,11 +105,22 @@ export class BenchmarkCliUsecases { * using the systeminformation library * @returns the system resources */ - private async getSystemResources() { + private async getSystemResources(): Promise< + BenchmarkHardware & { + cpuLoad: any; + mem: any; + } + > { return { - cpu: await si.currentLoad(), + cpuLoad: await si.currentLoad(), mem: await si.mem(), gpu: (await si.graphics()).controllers, + cpu: await si.cpu(), + board: await si.baseboard(), + disk: await si.diskLayout(), + chassis: await si.chassis(), + memLayout: await si.memLayout(), + os: await si.osInfo(), }; } @@ -116,11 +131,12 @@ export class BenchmarkCliUsecases { * @returns the resource change */ private async getResourceChange(startData: any, endData: any) { + console.log(startData.cpuLoad.currentLoad, endData.cpuLoad.currentLoad); return { - cpu: - startData.cpu && endData.cpu - ? ((endData.cpu.currentload - startData.cpu.currentload) / - startData.cpu.currentload) * + cpuLoad: + startData.cpuLoad && endData.cpuLoad + ? ((endData.cpuLoad.currentLoad - startData.cpuLoad.currentLoad) / + startData.cpuLoad.currentLoad) * 100 : null, mem: @@ -203,7 +219,7 @@ export class BenchmarkCliUsecases { /** * Run the benchmarks */ - private async runBenchmarks() { + private async runBenchmarks(model: ModelStat) { const allResults: any[] = []; const rounds = this.config.num_rounds || 1; @@ -255,6 +271,7 @@ export class BenchmarkCliUsecases { hardware: await this.getSystemResources(), results: allResults, metrics, + model, }; bar.stop(); @@ -262,6 +279,20 @@ export class BenchmarkCliUsecases { await this.fileService.getBenchmarkPath(), 'output.json', ); + await this.telemetryUsecases.sendBenchmarkEvent({ + hardware: { + cpu: output.hardware.cpu, + gpu: output.hardware.gpu, + memLayout: output.hardware.memLayout, + board: output.hardware.board, + disk: output.hardware.disk, + chassis: output.hardware.chassis, + os: output.hardware.os, + }, + results: output.results, + metrics: output.metrics, + model, + }); fs.writeFileSync(outputFilePath, JSON.stringify(output, null, 2)); console.log(`Benchmark results and metrics saved to ${outputFilePath}`); diff --git a/cortex-js/src/infrastructure/commanders/usecases/cli.usecases.module.ts b/cortex-js/src/infrastructure/commanders/usecases/cli.usecases.module.ts index 0c2576ed7..8f33fecd6 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/cli.usecases.module.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/cli.usecases.module.ts @@ -12,6 +12,7 @@ import { MessagesModule } from '@/usecases/messages/messages.module'; import { FileManagerModule } from '@/infrastructure/services/file-manager/file-manager.module'; import { PSCliUsecases } from './ps.cli.usecases'; import { BenchmarkCliUsecases } from './benchmark.cli.usecases'; +import { TelemetryModule } from '@/usecases/telemetry/telemetry.module'; @Module({ imports: [ @@ -23,6 +24,7 @@ import { BenchmarkCliUsecases } from './benchmark.cli.usecases'; AssistantsModule, MessagesModule, FileManagerModule, + TelemetryModule, ], providers: [ InitCliUsecases, diff --git a/cortex-js/src/infrastructure/controllers/chat.controller.ts b/cortex-js/src/infrastructure/controllers/chat.controller.ts index 0d0b9e3eb..0918b7431 100644 --- a/cortex-js/src/infrastructure/controllers/chat.controller.ts +++ b/cortex-js/src/infrastructure/controllers/chat.controller.ts @@ -42,14 +42,9 @@ export class ChatController { } else { res.json(await this.chatService.inference(createChatDto, headers)); } - this.telemetryUsecases.sendEvent( - [ - { - name: EventName.CHAT, - modelId: createChatDto.model, - }, - ], - TelemetrySource.CORTEX_SERVER, - ); + this.telemetryUsecases.addEventToQueue({ + name: EventName.CHAT, + modelId: createChatDto.model, + }); } } diff --git a/cortex-js/src/infrastructure/controllers/models.controller.ts b/cortex-js/src/infrastructure/controllers/models.controller.ts index 83deb16ae..666b099ec 100644 --- a/cortex-js/src/infrastructure/controllers/models.controller.ts +++ b/cortex-js/src/infrastructure/controllers/models.controller.ts @@ -118,15 +118,10 @@ export class ModelsController { @Get('download/:modelId(*)') async downloadModel(@Param('modelId') modelId: string) { const result = await this.modelsUsecases.downloadModel(modelId); - this.telemetryUsecases.sendEvent( - [ - { - name: EventName.DOWNLOAD_MODEL, - modelId, - }, - ], - TelemetrySource.CORTEX_SERVER, - ); + this.telemetryUsecases.addEventToQueue({ + name: EventName.DOWNLOAD_MODEL, + modelId, + }); return result; } @@ -164,15 +159,10 @@ export class ModelsController { @Get('pull/:modelId(*)') async pullModel(@Param('modelId') modelId: string) { const result = await this.modelsUsecases.pullModel(modelId); - this.telemetryUsecases.sendEvent( - [ - { - name: EventName.DOWNLOAD_MODEL, - modelId, - }, - ], - TelemetrySource.CORTEX_SERVER, - ); + this.telemetryUsecases.addEventToQueue({ + name: EventName.DOWNLOAD_MODEL, + modelId, + }); return result; } diff --git a/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts b/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts index 39f4a1f71..4549c6034 100644 --- a/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts +++ b/cortex-js/src/infrastructure/repositories/telemetry/telemetry.repository.ts @@ -12,6 +12,7 @@ import { TelemetryEventMetadata, EventAttributes, TelemetryAnonymized, + BenchmarkHardware, } from '@/domain/telemetry/telemetry.interface'; import { Injectable } from '@nestjs/common'; import { join } from 'path'; @@ -19,6 +20,7 @@ import packageJson from '@/../package.json'; import axios from 'axios'; import { telemetryServerUrl } from '@/infrastructure/constants/cortex'; import { FileManagerService } from '@/infrastructure/services/file-manager/file-manager.service'; +import { ModelStat } from '@/infrastructure/commanders/types/model-stat.interface'; // refactor using convert to dto @Injectable() @@ -31,7 +33,7 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { }; private readonly crashReportFileName = 'crash-report.jsonl'; - private readonly anonymizedDataFileName = 'metadata.json'; + private readonly anonymizedDataFileName = 'session.json'; constructor(private readonly fileManagerService: FileManagerService) {} private async getTelemetryDirectory(): Promise { @@ -62,6 +64,23 @@ export class TelemetryRepositoryImpl implements TelemetryRepository { } catch (error) {} } + async sendBenchmarkToServer(data: { + hardware: BenchmarkHardware; + results: any; + metrics: any; + model: ModelStat; + sessionId: string; + }): Promise { + try { + await axios.post(`${telemetryServerUrl}/api/v1/benchmark`, data, { + headers: { + 'Content-Type': 'application/json', + 'cortex-checksum': this.generateChecksum(data), + }, + }); + } catch (error) {} + } + async sendTelemetryToOTelCollector(endpoint: string, telemetry: Telemetry) { try { console.log('Sending telemetry to OTel collector'); diff --git a/cortex-js/src/main.ts b/cortex-js/src/main.ts index ac3c0d243..d41144133 100644 --- a/cortex-js/src/main.ts +++ b/cortex-js/src/main.ts @@ -8,6 +8,7 @@ import { } from '@/infrastructure/constants/cortex'; import { SeedService } from './usecases/seed/seed.service'; import { FileManagerService } from './infrastructure/services/file-manager/file-manager.service'; +import { TelemetryUsecases } from './usecases/telemetry/telemetry.usecases'; async function bootstrap() { const app = await NestFactory.create(AppModule, { @@ -17,10 +18,13 @@ async function bootstrap() { const seedService = app.get(SeedService); await seedService.seed(); + const telemetryService = await app.resolve(TelemetryUsecases); const fileService = app.get(FileManagerService); await fileService.getConfig(); + await telemetryService.initInterval(); + app.useGlobalPipes( new ValidationPipe({ transform: true, diff --git a/cortex-js/src/usecases/telemetry/telemetry.usecases.ts b/cortex-js/src/usecases/telemetry/telemetry.usecases.ts index 8f0fec724..f4713a0ae 100644 --- a/cortex-js/src/usecases/telemetry/telemetry.usecases.ts +++ b/cortex-js/src/usecases/telemetry/telemetry.usecases.ts @@ -1,5 +1,6 @@ import { TelemetryRepository } from '@/domain/repositories/telemetry.interface'; import { + BenchmarkHardware, CrashReportAttributes, EventAttributes, EventName, @@ -7,6 +8,7 @@ import { TelemetryAnonymized, TelemetrySource, } from '@/domain/telemetry/telemetry.interface'; +import { ModelStat } from '@/infrastructure/commanders/types/model-stat.interface'; import { ContextService } from '@/util/context.service'; import { HttpException, Inject, Injectable, Scope } from '@nestjs/common'; import { v4 } from 'uuid'; @@ -17,8 +19,8 @@ export class TelemetryUsecases { private readonly maxSize = 10; private metricQueue: EventAttributes[] = []; private readonly maxQueueSize = 10; - private readonly flushInterval = 1000 * 60 * 5; - private interval: NodeJS.Timeout = this.flushMetricQueueInterval(); + private readonly flushInterval = 1000 * 5; + private interval: NodeJS.Timeout; private lastActiveAt?: string | null; constructor( @@ -100,6 +102,10 @@ export class TelemetryUsecases { return process.env.CORTEX_METRICS !== '0'; } + private isBenchmarkEnabled(): boolean { + return process.env.CORTEX_BENCHMARK !== '0'; + } + private async catchException(): Promise { process.on('uncaughtException', async (error: Error) => { await this.createCrashReport( @@ -116,6 +122,10 @@ export class TelemetryUsecases { }); } + async initInterval(): Promise { + this.interval = this.flushMetricQueueInterval(); + } + async sendEvent( events: EventAttributes[], source: TelemetrySource, @@ -128,9 +138,7 @@ export class TelemetryUsecases { sessionId, })); await this.telemetryRepository.sendEvent(sessionEvents, source); - } catch (e) { - console.error('Error sending event:', e); - } + } catch (e) {} } async sendActivationEvent(source: TelemetrySource): Promise { @@ -153,11 +161,8 @@ export class TelemetryUsecases { ], source, ); - console.log('Activation event sent', isNewActivation); this.lastActiveAt = new Date().toISOString(); - } catch (e) { - console.error('Error sending activation event:', e); - } + } catch (e) {} await this.updateAnonymousData(this.lastActiveAt); } @@ -203,4 +208,28 @@ export class TelemetryUsecases { return null; } } + + async sendBenchmarkEvent({ + hardware, + results, + metrics, + model, + }: { + hardware: BenchmarkHardware; + results: any; + metrics: any; + model: ModelStat; + }): Promise { + try { + if (!this.isBenchmarkEnabled()) return; + const sessionId: string = this.contextService.get('sessionId') || ''; + await this.telemetryRepository.sendBenchmarkToServer({ + hardware, + results, + metrics, + model, + sessionId, + }); + } catch (e) {} + } } From 3d9bb0bb865547138ea0484415422d230a425f7d Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Thu, 27 Jun 2024 09:39:23 +0700 Subject: [PATCH 5/7] remove console.log --- .../commanders/usecases/benchmark.cli.usecases.ts | 1 - .../services/file-manager/file-manager.service.ts | 2 -- cortex-js/src/usecases/chat/chat.usecases.ts | 1 - 3 files changed, 4 deletions(-) diff --git a/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts index b3022e6fe..29161e9c2 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts @@ -131,7 +131,6 @@ export class BenchmarkCliUsecases { * @returns the resource change */ private async getResourceChange(startData: any, endData: any) { - console.log(startData.cpuLoad.currentLoad, endData.cpuLoad.currentLoad); return { cpuLoad: startData.cpuLoad && endData.cpuLoad diff --git a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts index a07de2f9b..006a8f453 100644 --- a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts +++ b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts @@ -251,7 +251,6 @@ export class FileManagerService { }); return content; } catch (error) { - console.error('Error reading json file:', error); throw error; } } @@ -264,7 +263,6 @@ export class FileManagerService { flag: 'w+', }); } catch (error) { - console.error('Error writing json file:', error); throw error; } } diff --git a/cortex-js/src/usecases/chat/chat.usecases.ts b/cortex-js/src/usecases/chat/chat.usecases.ts index 08705995c..8399b6a3f 100644 --- a/cortex-js/src/usecases/chat/chat.usecases.ts +++ b/cortex-js/src/usecases/chat/chat.usecases.ts @@ -26,7 +26,6 @@ export class ChatUsecases { ): Promise { const { model: modelId } = createChatDto; const model = await this.modelRepository.findOne(modelId); - console.log('model', model); if (!model) { throw new ModelNotFoundException(modelId); } From cc3d853e145a1868bcdad32c92f3a45df9e32355 Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Thu, 27 Jun 2024 14:12:34 +0700 Subject: [PATCH 6/7] fix conflict --- cortex-js/src/app.ts | 4 ++++ cortex-js/src/infrastructure/commanders/init.command.ts | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cortex-js/src/app.ts b/cortex-js/src/app.ts index 9eb1d8d70..6a977d48a 100644 --- a/cortex-js/src/app.ts +++ b/cortex-js/src/app.ts @@ -3,6 +3,7 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; import { FileManagerService } from './infrastructure/services/file-manager/file-manager.service'; import { ValidationPipe } from '@nestjs/common'; +import { TelemetryUsecases } from './usecases/telemetry/telemetry.usecases'; export const getApp = async () => { const app = await NestFactory.create(AppModule, { snapshot: true, @@ -16,6 +17,9 @@ export const getApp = async () => { const fileService = app.get(FileManagerService); await fileService.getConfig(); + const telemetryService = await app.resolve(TelemetryUsecases); + await telemetryService.initInterval(); + app.useGlobalPipes( new ValidationPipe({ transform: true, diff --git a/cortex-js/src/infrastructure/commanders/init.command.ts b/cortex-js/src/infrastructure/commanders/init.command.ts index 4b335f282..38cde473b 100644 --- a/cortex-js/src/infrastructure/commanders/init.command.ts +++ b/cortex-js/src/infrastructure/commanders/init.command.ts @@ -7,7 +7,6 @@ import { import { InitCliUsecases } from './usecases/init.cli.usecases'; import { InitOptions } from './types/init-options.interface'; import { SetCommandContext } from './decorators/CommandContext'; -import { ContextService } from '@/util/context.service'; import { TelemetryUsecases } from '@/usecases/telemetry/telemetry.usecases'; import { EventName, From 2cefa8f7965fc1cb040198a99262fe988e501c2a Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Thu, 27 Jun 2024 15:52:53 +0700 Subject: [PATCH 7/7] fix lint --- .../commanders/usecases/benchmark.cli.usecases.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts b/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts index dc371716b..c3a8b8d9a 100644 --- a/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts +++ b/cortex-js/src/infrastructure/commanders/usecases/benchmark.cli.usecases.ts @@ -63,11 +63,7 @@ export class BenchmarkCliUsecases { .then(() => this.psUsecases .getModels() - .then((models) => - models.find( - (e) => e.modelId === model, - ), - ), + .then((models) => models.find((e) => e.modelId === model)), ) .then((model) => { if (!model)