add timestamped log files with automatic cleanup
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.0.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- **Timestamped log files**: Log files now include timestamps in filename (`relay-server-{timestamp}.log`) instead of overwriting a single file
|
||||
- **Automatic log cleanup**: Keeps only the 10 most recent log files, deleting older ones automatically
|
||||
- **Async log writes**: Logger now uses a queue for async file writes instead of blocking sync writes
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "playwriter",
|
||||
"description": "",
|
||||
"version": "0.0.19",
|
||||
"version": "0.0.20",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,26 +1,56 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import util from 'node:util'
|
||||
import { ensureDataDir, getLogFilePath } from './utils.js'
|
||||
import { LOG_FILE_PATH } from './utils.js'
|
||||
|
||||
export type Logger = {
|
||||
log(...args: unknown[]): void
|
||||
error(...args: unknown[]): void
|
||||
log(...args: unknown[]): Promise<void>
|
||||
error(...args: unknown[]): Promise<void>
|
||||
logFilePath: string
|
||||
}
|
||||
|
||||
function cleanupOldLogs(logsDir: string): void {
|
||||
if (!fs.existsSync(logsDir)) {
|
||||
return
|
||||
}
|
||||
const files = fs.readdirSync(logsDir)
|
||||
.filter((f) => f.startsWith('relay-server-') && f.endsWith('.log'))
|
||||
.map((f) => ({
|
||||
name: f,
|
||||
path: path.join(logsDir, f),
|
||||
mtime: fs.statSync(path.join(logsDir, f)).mtime.getTime(),
|
||||
}))
|
||||
.sort((a, b) => b.mtime - a.mtime)
|
||||
|
||||
if (files.length > 10) {
|
||||
files.slice(10).forEach((f) => {
|
||||
fs.unlinkSync(f.path)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function createFileLogger({ logFilePath }: { logFilePath?: string } = {}): Logger {
|
||||
const resolvedLogFilePath = logFilePath || getLogFilePath()
|
||||
ensureDataDir()
|
||||
const resolvedLogFilePath = logFilePath || LOG_FILE_PATH
|
||||
const logDir = path.dirname(resolvedLogFilePath)
|
||||
if (!fs.existsSync(logDir)) {
|
||||
fs.mkdirSync(logDir, { recursive: true })
|
||||
}
|
||||
cleanupOldLogs(logDir)
|
||||
fs.writeFileSync(resolvedLogFilePath, '')
|
||||
|
||||
const log = (...args: unknown[]) => {
|
||||
let queue: Promise<void> = Promise.resolve()
|
||||
|
||||
const log = (...args: unknown[]): Promise<void> => {
|
||||
const message = args.map(arg =>
|
||||
typeof arg === 'string' ? arg : util.inspect(arg, { depth: null, colors: false })
|
||||
).join(' ')
|
||||
fs.appendFileSync(resolvedLogFilePath, message + '\n')
|
||||
queue = queue.then(() => fs.promises.appendFile(resolvedLogFilePath, message + '\n'))
|
||||
return queue
|
||||
}
|
||||
|
||||
return {
|
||||
log,
|
||||
error: log
|
||||
error: log,
|
||||
logFilePath: resolvedLogFilePath,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1914,19 +1914,13 @@ describe('CDP Session Tests', () => {
|
||||
sampleFunctionNames: functionNames,
|
||||
}).toMatchInlineSnapshot(`
|
||||
{
|
||||
"durationMicroseconds": 8646,
|
||||
"durationMicroseconds": 11057,
|
||||
"hasNodes": true,
|
||||
"nodeCount": 20,
|
||||
"nodeCount": 4,
|
||||
"sampleFunctionNames": [
|
||||
"(root)",
|
||||
"(program)",
|
||||
"(idle)",
|
||||
"evaluate",
|
||||
"fibonacci",
|
||||
"fibonacci",
|
||||
"fibonacci",
|
||||
"fibonacci",
|
||||
"fibonacci",
|
||||
"fibonacci",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { fileURLToPath } from 'node:url'
|
||||
import vm from 'node:vm'
|
||||
import dedent from 'string-dedent'
|
||||
import { createPatch } from 'diff'
|
||||
import { getCdpUrl, getLogFilePath } from './utils.js'
|
||||
import { getCdpUrl, LOG_FILE_PATH } from './utils.js'
|
||||
import { waitForPageLoad, WaitForPageLoadOptions, WaitForPageLoadResult } from './wait-for-page-load.js'
|
||||
import { getCDPSessionForPage, CDPSession } from './cdp-session.js'
|
||||
|
||||
@@ -92,7 +92,6 @@ const lastSnapshots: WeakMap<Page, string> = new WeakMap()
|
||||
const cdpSessionCache: WeakMap<Page, CDPSession> = new WeakMap()
|
||||
|
||||
const RELAY_PORT = 19988
|
||||
const LOG_FILE_PATH = getLogFilePath()
|
||||
const NO_TABS_ERROR = `No browser tabs are connected. Please install and enable the Playwriter extension on at least one tab: https://chromewebstore.google.com/detail/playwriter-mcp/jfeammnjpkecdekppnclgkkffahnhfhe`
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { startPlayWriterCDPRelayServer } from './extension/cdp-relay.js'
|
||||
import { createFileLogger } from './create-logger.js'
|
||||
import { getLogFilePath } from './utils.js'
|
||||
|
||||
const logFilePath = getLogFilePath()
|
||||
process.title = 'playwriter-ws-server'
|
||||
|
||||
const logger = createFileLogger({ logFilePath })
|
||||
const logger = createFileLogger()
|
||||
|
||||
process.on('uncaughtException', async (err) => {
|
||||
await logger.error('Uncaught Exception:', err);
|
||||
@@ -26,7 +24,7 @@ export async function startServer({ port = 19988 }: { port?: number } = {}) {
|
||||
const server = await startPlayWriterCDPRelayServer({ port, logger })
|
||||
|
||||
console.log('CDP Relay Server running. Press Ctrl+C to stop.')
|
||||
console.log('Logs are being written to:', logFilePath)
|
||||
console.log('Logs are being written to:', logger.logFilePath)
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\nShutting down...')
|
||||
|
||||
+12
-2
@@ -19,10 +19,20 @@ export function ensureDataDir(): string {
|
||||
return dataDir
|
||||
}
|
||||
|
||||
export function getLogFilePath(): string {
|
||||
return process.env.PLAYWRITER_LOG_PATH || path.join(getDataDir(), 'relay-server.log')
|
||||
function getLogsDir(): string {
|
||||
return path.join(getDataDir(), 'logs')
|
||||
}
|
||||
|
||||
function getLogFilePath(): string {
|
||||
if (process.env.PLAYWRITER_LOG_PATH) {
|
||||
return process.env.PLAYWRITER_LOG_PATH
|
||||
}
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
|
||||
return path.join(getLogsDir(), `relay-server-${timestamp}.log`)
|
||||
}
|
||||
|
||||
export const LOG_FILE_PATH = getLogFilePath()
|
||||
|
||||
// export function getDidPromptReviewPath(): string {
|
||||
// return path.join(getDataDir(), 'did-prompt-review')
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user