chore: add config for logging and update dockerfile
This commit is contained in:
@@ -44,7 +44,10 @@
|
||||
"mcp__ide__getDiagnostics",
|
||||
"Bash(done)",
|
||||
"Bash(npm run lint:*)",
|
||||
"Bash(wc:*)"
|
||||
"Bash(wc:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(docker build:*)",
|
||||
"Bash(find:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -20,9 +20,10 @@ RUN npm ci --workspace=backend --include-workspace-root --prefer-offline --no-au
|
||||
# Copy backend source code
|
||||
COPY backend ./backend/
|
||||
|
||||
# Build TypeScript (run from backend directory)
|
||||
# Build TypeScript (run from backend directory) and prune dev dependencies
|
||||
WORKDIR /app/backend
|
||||
RUN npm run build
|
||||
RUN npm run build && \
|
||||
npm prune --omit=dev --workspace=backend --include-workspace-root
|
||||
|
||||
# =============================================================================
|
||||
# Stage 2: Production - Optimized runtime
|
||||
@@ -46,8 +47,8 @@ COPY --from=builder /app/package.json /app/package-lock.json ./
|
||||
# Copy backend package files
|
||||
COPY --from=builder /app/backend/package.json ./backend/
|
||||
|
||||
# Install production dependencies only for backend workspace
|
||||
RUN npm ci --workspace=backend --include-workspace-root --omit=dev --prefer-offline --no-audit
|
||||
# Copy production node_modules from builder to leverage cached install
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
|
||||
# Copy built application
|
||||
COPY --from=builder /app/backend/dist ./backend/dist
|
||||
|
||||
@@ -1,15 +1,41 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { promises as fs } from 'fs';
|
||||
import fsSync from 'fs';
|
||||
import path from 'path';
|
||||
import winston from 'winston';
|
||||
import { authenticate } from '../middleware/auth';
|
||||
import { requirePermission } from '../middleware/rbac';
|
||||
import { logger } from '../utils/logger';
|
||||
import { config } from '../config';
|
||||
|
||||
const router = Router();
|
||||
|
||||
const LOG_DIR = path.join(__dirname, '../../logs');
|
||||
const LOG_DIR = config.logFile ? path.dirname(config.logFile) : path.join(__dirname, '../../logs');
|
||||
const ERROR_LOG_FILE = path.join(LOG_DIR, 'client-errors.log');
|
||||
|
||||
// Ensure logs directory exists for file transport at startup
|
||||
if (!fsSync.existsSync(LOG_DIR)) {
|
||||
fsSync.mkdirSync(LOG_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
const clientErrorLogger = winston.createLogger({
|
||||
level: 'info',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.json()
|
||||
),
|
||||
defaultMeta: { service: 'flashpoint-web-client-errors' },
|
||||
transports: [
|
||||
new winston.transports.File({
|
||||
filename: ERROR_LOG_FILE,
|
||||
maxsize: 10485760, // 10MB
|
||||
maxFiles: 5,
|
||||
tailable: true
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
interface ErrorReport {
|
||||
type: 'client_error' | 'network_error' | 'api_error' | 'route_error';
|
||||
message: string;
|
||||
@@ -18,9 +44,11 @@ interface ErrorReport {
|
||||
timestamp: string;
|
||||
userAgent: string;
|
||||
userId?: number;
|
||||
context?: Record<string, any>;
|
||||
context?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
type AuthenticatedRequest = Request & { user?: { id: number } };
|
||||
|
||||
/**
|
||||
* Ensure logs directory exists
|
||||
*/
|
||||
@@ -37,10 +65,7 @@ async function ensureLogDir(): Promise<void> {
|
||||
*/
|
||||
async function logError(report: ErrorReport): Promise<void> {
|
||||
try {
|
||||
await ensureLogDir();
|
||||
|
||||
const logLine = JSON.stringify(report) + '\n';
|
||||
await fs.appendFile(ERROR_LOG_FILE, logLine, 'utf8');
|
||||
clientErrorLogger.info('client_error', report);
|
||||
} catch (error) {
|
||||
logger.error('Failed to log client error:', error);
|
||||
}
|
||||
@@ -106,8 +131,9 @@ router.post('/report', async (req: Request, res: Response) => {
|
||||
}
|
||||
|
||||
// Add user ID if authenticated
|
||||
if ((req as any).user) {
|
||||
report.userId = (req as any).user.id;
|
||||
const authReq = req as AuthenticatedRequest;
|
||||
if (authReq.user) {
|
||||
report.userId = authReq.user.id;
|
||||
}
|
||||
|
||||
// Add timestamp if not provided
|
||||
|
||||
@@ -37,6 +37,9 @@ services:
|
||||
- ${FLASHPOINT_HOST_PATH:?FLASHPOINT_HOST_PATH environment variable must be set}:/data/flashpoint:ro
|
||||
# User database (persistent)
|
||||
- backend-db:/app/data
|
||||
# Application logs (persistent)
|
||||
# Set BACKEND_LOGS_PATH to bind-mount a host directory
|
||||
- ${BACKEND_LOGS_PATH:-backend-logs}:/app/logs
|
||||
environment:
|
||||
- NODE_ENV=${NODE_ENV:-production}
|
||||
- TZ=${TZ:-UTC}
|
||||
@@ -126,6 +129,9 @@ volumes:
|
||||
# Persistent volume for user database
|
||||
backend-db:
|
||||
driver: local
|
||||
# Persistent volume for backend logs
|
||||
backend-logs:
|
||||
driver: local
|
||||
|
||||
# =============================================================================
|
||||
# Quick Start with Pre-built Images
|
||||
|
||||
@@ -11,6 +11,9 @@ services:
|
||||
- ${FLASHPOINT_HOST_PATH:?FLASHPOINT_HOST_PATH environment variable must be set}:/data/flashpoint:ro
|
||||
# User database (persistent)
|
||||
- backend-db:/app/data
|
||||
# Application logs (persistent)
|
||||
# Set BACKEND_LOGS_PATH to bind-mount a host directory
|
||||
- ${BACKEND_LOGS_PATH:-backend-logs}:/app/logs
|
||||
environment:
|
||||
- NODE_ENV=${NODE_ENV:-production}
|
||||
- TZ=${TZ:-UTC}
|
||||
@@ -158,6 +161,9 @@ volumes:
|
||||
# Persistent volume for user database
|
||||
backend-db:
|
||||
driver: local
|
||||
# Persistent volume for backend logs
|
||||
backend-logs:
|
||||
driver: local
|
||||
|
||||
# =============================================================================
|
||||
# Flashpoint Web App - Production Docker Compose Configuration
|
||||
|
||||
+2
-1
@@ -17,7 +17,8 @@ services:
|
||||
# User database (persistent)
|
||||
- backend-db:/app/data
|
||||
# Application logs (persistent)
|
||||
- backend-logs:/app/logs
|
||||
# Set BACKEND_LOGS_PATH to bind-mount a host directory
|
||||
- ${BACKEND_LOGS_PATH:-backend-logs}:/app/logs
|
||||
environment:
|
||||
- NODE_ENV=${NODE_ENV:-production}
|
||||
- TZ=${TZ:-UTC}
|
||||
|
||||
@@ -23,9 +23,10 @@ RUN npm ci --workspace=game-service --include-workspace-root --prefer-offline --
|
||||
# Copy game-service source code
|
||||
COPY game-service ./game-service/
|
||||
|
||||
# Build TypeScript (run from game-service directory)
|
||||
# Build TypeScript (run from game-service directory) and prune dev dependencies
|
||||
WORKDIR /app/game-service
|
||||
RUN npm run build
|
||||
RUN npm run build && \
|
||||
npm prune --omit=dev --workspace=game-service --include-workspace-root
|
||||
|
||||
# =============================================================================
|
||||
# Stage 2: Production - Optimized runtime
|
||||
@@ -49,8 +50,8 @@ COPY --from=builder /app/package.json /app/package-lock.json ./
|
||||
# Copy game-service package files
|
||||
COPY --from=builder /app/game-service/package.json ./game-service/
|
||||
|
||||
# Install production dependencies only for game-service workspace
|
||||
RUN npm ci --workspace=game-service --include-workspace-root --omit=dev --prefer-offline --no-audit
|
||||
# Copy production node_modules from builder to leverage cached install
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
|
||||
# Copy built application
|
||||
COPY --from=builder /app/game-service/dist ./game-service/dist
|
||||
|
||||
Reference in New Issue
Block a user