Skip to main content
Glama
file-logger.ts3 kB
/* * This file is part of BrowserLoop. * * BrowserLoop is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * BrowserLoop is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with BrowserLoop. If not, see <https://www.gnu.org/licenses/>. */ import { appendFileSync, existsSync, mkdirSync } from 'node:fs'; import { dirname } from 'node:path'; export class FileLogger { private logPath: string; private debugEnabled: boolean; constructor() { // Try different log paths in order of preference const logPaths = [ '/var/log/browserloop.log', '/tmp/browserloop.log', `${process.env.HOME}/.browserloop.log`, './browserloop.log', ]; this.logPath = this.findWritableLogPath(logPaths); this.debugEnabled = process.env.BROWSERLOOP_DEBUG === 'true'; // Initialize log file with startup message when debug is enabled if (this.debugEnabled) { this.initializeLogFile(); } } private findWritableLogPath(paths: string[]): string { for (const path of paths) { try { // Try to create directory if it doesn't exist const dir = dirname(path); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } // Test write access appendFileSync(path, ''); return path; } catch { // Continue to next path } } // Fallback to stderr if no file path works return ''; } private initializeLogFile() { if (!this.logPath) return; try { const timestamp = new Date().toISOString(); const startupMessage = `\n=== BrowserLoop Debug Log Started at ${timestamp} ===\n`; appendFileSync(this.logPath, startupMessage); } catch { // Silent failure - don't interfere with MCP protocol } } log(message: string) { // File logging only depends on debug being enabled, not silent mode if (!this.debugEnabled || !this.logPath) { return; } try { const timestamp = new Date().toISOString(); const logEntry = `[${timestamp}] ${message}\n`; appendFileSync(this.logPath, logEntry); } catch { // Silent failure - don't interfere with MCP protocol } } debug(message: string) { this.log(`[DEBUG] ${message}`); } warn(message: string) { this.log(`[WARN] ${message}`); } error(message: string) { this.log(`[ERROR] ${message}`); } getLogPath(): string { return this.logPath; } } // Export singleton instance export const fileLogger = new FileLogger();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mattiasw/browserloop'

If you have feedback or need assistance with the MCP directory API, please join our Discord server