Spaces:
Sleeping
Sleeping
| /** | |
| * Gradio関連のログ出力を統一的に管理するロガー | |
| * JSON形式で構造化ログを出力 | |
| */ | |
| /** | |
| * ログ用の時刻フォーマットを生成 | |
| * @returns {string} YYYY/MM/DD HH:MM:SS形式の時刻文字列 | |
| */ | |
| function getLogTimestamp(): string { | |
| // JST (Asia/Tokyo) タイムゾーンで日時を取得 | |
| const now = new Date(); | |
| const jstDate = new Date(now.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' })); | |
| const year = jstDate.getFullYear(); | |
| const month = String(jstDate.getMonth() + 1).padStart(2, '0'); | |
| const day = String(jstDate.getDate()).padStart(2, '0'); | |
| const hours = String(jstDate.getHours()).padStart(2, '0'); | |
| const minutes = String(jstDate.getMinutes()).padStart(2, '0'); | |
| const seconds = String(jstDate.getSeconds()).padStart(2, '0'); | |
| return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; | |
| } | |
| interface BaseLogData { | |
| timestamp: string; | |
| component: 'Pool' | 'API'; | |
| event: string; | |
| userIdentifier?: string; | |
| backend?: string; | |
| } | |
| interface PoolLogData extends BaseLogData { | |
| component: 'Pool'; | |
| } | |
| interface APILogData extends BaseLogData { | |
| component: 'API'; | |
| endpoint?: string; | |
| apiName?: string; | |
| userEmail?: string; | |
| } | |
| interface ErrorLogData extends BaseLogData { | |
| errorType?: 'CONNECTION' | 'TRANSIENT' | 'PERMANENT'; | |
| error?: string; | |
| } | |
| type LogData = PoolLogData | APILogData | ErrorLogData; | |
| /** | |
| * [Pool]ログを出力 | |
| */ | |
| function logPool(event: string, userIdentifier?: string, backend?: string): void { | |
| const logData: PoolLogData = { | |
| timestamp: getLogTimestamp(), | |
| component: 'Pool', | |
| event, | |
| ...(userIdentifier && { userIdentifier }), | |
| ...(backend && { backend }), | |
| }; | |
| console.log(JSON.stringify(logData)); | |
| } | |
| /** | |
| * エラーオブジェクトを文字列に変換 | |
| * @param error - エラーオブジェクト | |
| * @returns エラー情報を含む文字列 | |
| */ | |
| function serializeError(error: unknown): string { | |
| if (error instanceof Error) { | |
| const details: Record<string, unknown> = { | |
| message: error.message, | |
| name: error.name, | |
| }; | |
| // エラーコード(ECONNREFUSED等)を取得 | |
| if ('code' in error && error.code) { | |
| details.code = error.code; | |
| } | |
| // ステータスコード(HTTP 403等)を取得 | |
| if ('status' in error && typeof error.status === 'number') { | |
| details.status = error.status; | |
| } | |
| // その他の有用なプロパティを取得 | |
| if ('cause' in error && error.cause) { | |
| details.cause = String(error.cause); | |
| } | |
| return JSON.stringify(details); | |
| } | |
| if (typeof error === 'object' && error !== null) { | |
| try { | |
| return JSON.stringify(error); | |
| } catch { | |
| return String(error); | |
| } | |
| } | |
| return String(error); | |
| } | |
| /** | |
| * [Pool]エラーログを出力 | |
| */ | |
| function logPoolError( | |
| event: string, | |
| error: unknown, | |
| errorType?: 'CONNECTION' | 'TRANSIENT' | 'PERMANENT', | |
| userIdentifier?: string, | |
| backend?: string, | |
| ): void { | |
| const logData: ErrorLogData = { | |
| timestamp: getLogTimestamp(), | |
| component: 'Pool', | |
| event, | |
| error: serializeError(error), | |
| ...(errorType && { errorType }), | |
| ...(userIdentifier && { userIdentifier }), | |
| ...(backend && { backend }), | |
| }; | |
| console.error(JSON.stringify(logData)); | |
| } | |
| /** | |
| * [API REQUEST]ログを出力 | |
| */ | |
| function logAPIRequest(apiName: string, endpoint: string, userIdentifier: string, backend: string, userEmail?: string): void { | |
| const logData: APILogData = { | |
| timestamp: getLogTimestamp(), | |
| component: 'API', | |
| event: 'REQUEST', | |
| apiName, | |
| endpoint, | |
| userIdentifier, | |
| backend, | |
| ...(userEmail && { userEmail }), | |
| }; | |
| console.log(JSON.stringify(logData)); | |
| } | |
| /** | |
| * [API RESPONSE]ログを出力(成功時) | |
| */ | |
| function logAPIResponse( | |
| apiName: string, | |
| endpoint: string, | |
| userIdentifier: string, | |
| backend: string, | |
| durationMs: number, | |
| responseSizeMB: number, | |
| userEmail?: string, | |
| ): void { | |
| const logData = { | |
| timestamp: getLogTimestamp(), | |
| component: 'API', | |
| event: 'RESPONSE', | |
| apiName, | |
| endpoint, | |
| userIdentifier, | |
| backend, | |
| durationSec: Math.round(durationMs / 1000), | |
| responseSizeMB, | |
| ...(userEmail && { userEmail }), | |
| ...(responseSizeMB > 1 && { warning: 'Large response' }), | |
| }; | |
| console.log(JSON.stringify(logData)); | |
| } | |
| export const gradioLogger = { | |
| logPool, | |
| logPoolError, | |
| logAPIRequest, | |
| logAPIResponse, | |
| }; | |
| // レガシーログ用にgetLogTimestampもエクスポート | |
| export { getLogTimestamp }; | |