Skip to content

Commit e206d92

Browse files
authored
Merge pull request #11 from hexawulf/codex/add-winston-logging-to-codepatchwork
Add winston logger
2 parents 424bdf6 + dd15ace commit e206d92

3 files changed

Lines changed: 52 additions & 31 deletions

File tree

server/index.ts

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import camelCase from "camelcase";
1212
import helmet from "helmet";
1313
import { registerRoutes } from "./routes";
1414
import { setupVite, serveStatic, log } from "./vite";
15+
import logger from "../src/logger.js";
1516

1617
/* ────────────────────────────────────────────────────────────────── */
1718
/* 0. Verify & load your service-account JSON */
@@ -20,10 +21,10 @@ const svcPath = path.resolve(
2021
process.cwd(),
2122
process.env.GOOGLE_APPLICATION_CREDENTIALS!
2223
);
23-
console.log("→ SERVICE ACCOUNT path:", svcPath);
24-
console.log("→ Exists on disk? ", fs.existsSync(svcPath));
24+
logger.info(`→ SERVICE ACCOUNT path: ${svcPath}`);
25+
logger.info(`→ Exists on disk? ${fs.existsSync(svcPath)}`);
2526
if (!fs.existsSync(svcPath)) {
26-
console.error("❌ service account JSON not found. Aborting.");
27+
logger.error("❌ service account JSON not found. Aborting.");
2728
process.exit(1);
2829
}
2930

@@ -91,7 +92,7 @@ app.use(
9192
/* 4. CRITICAL FIX: JSON-only middleware for ALL API routes */
9293
/* ────────────────────────────────────────────────────────────────── */
9394
app.use('/api', (req, res, next) => {
94-
console.log(`[API] ${req.method} ${req.path} - Request received`);
95+
logger.info(`[API] ${req.method} ${req.path} - Request received`);
9596

9697
// Force Content-Type to application/json for all API responses
9798
res.setHeader('Content-Type', 'application/json');
@@ -104,7 +105,7 @@ app.use('/api', (req, res, next) => {
104105
res.send = function(data: any) {
105106
// If Express tries to send HTML (like error pages), convert to JSON
106107
if (typeof data === 'string' && (data.includes('<!DOCTYPE') || data.includes('<html>'))) {
107-
console.log(`[API] 🚨 Converting HTML response to JSON for ${req.method} ${req.path}`);
108+
logger.info(`[API] 🚨 Converting HTML response to JSON for ${req.method} ${req.path}`);
108109
this.setHeader('Content-Type', 'application/json');
109110
return originalSend.call(this, JSON.stringify({
110111
message: "API endpoint error",
@@ -125,7 +126,7 @@ app.use('/api', (req, res, next) => {
125126
const newSend = result.send;
126127
result.send = function(data: any) {
127128
if (typeof data === 'string' && (data.includes('<!DOCTYPE') || data.includes('<html>'))) {
128-
console.log(`[API] 🚨 Converting status ${statusCode} HTML to JSON for ${req.method} ${req.path}`);
129+
logger.info(`[API] 🚨 Converting status ${statusCode} HTML to JSON for ${req.method} ${req.path}`);
129130
this.setHeader('Content-Type', 'application/json');
130131
return originalSend.call(this, JSON.stringify({
131132
message: "API Error",
@@ -203,15 +204,15 @@ app.use((req, res, next) => {
203204
/* 7. Route registration */
204205
/* ────────────────────────────────────────────────────────────────── */
205206
(async () => {
206-
console.log("🔧 Starting route registration...");
207+
logger.info("🔧 Starting route registration...");
207208
const server = await registerRoutes(app);
208-
console.log("✅ Route registration complete");
209+
logger.info("✅ Route registration complete");
209210

210211
/* ──────────────────────────────────────────────────────────────── */
211212
/* 8. 404 Handler for unmatched API routes - MUST BE BEFORE GLOBAL */
212213
/* ──────────────────────────────────────────────────────────────── */
213214
app.use('/api/*', (req, res) => {
214-
console.log(`[404] API route not found: ${req.method} ${req.path}`);
215+
logger.info(`[404] API route not found: ${req.method} ${req.path}`);
215216
res.status(404).json({
216217
message: "API endpoint not found",
217218
path: req.path,
@@ -237,7 +238,7 @@ app.use((req, res, next) => {
237238
/* 9. Enhanced global error handler - MUST BE AFTER 404 HANDLER */
238239
/* ──────────────────────────────────────────────────────────────── */
239240
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
240-
console.error(`[💥 GLOBAL ERROR] ${req.method} ${req.path}:`, err.stack || err);
241+
logger.error(`[💥 GLOBAL ERROR] ${req.method} ${req.path}:`, err.stack || err);
241242

242243
// Ensure we don't send if headers already sent
243244
if (!res.headersSent) {
@@ -277,41 +278,41 @@ app.use((req, res, next) => {
277278
log(`🚀 Serving on port ${port}`);
278279
log(`📡 API available at http://localhost:${port}/api/`);
279280
log(`🧪 Test API at http://localhost:${port}/api/test`);
280-
console.log("---");
281-
console.log("🔧 API Endpoints registered:");
282-
console.log(" GET /api/test");
283-
console.log(" GET /api/snippets");
284-
console.log(" GET /api/snippets/:id");
285-
console.log(" POST /api/snippets");
286-
console.log(" PUT /api/snippets/:id");
287-
console.log(" DELETE /api/snippets/:id");
288-
console.log(" POST /api/snippets/:id/favorite");
289-
console.log(" GET /api/languages");
290-
console.log(" GET /api/tags");
291-
console.log(" POST /api/auth/user");
292-
console.log(" GET /api/auth/me");
293-
console.log("---");
281+
logger.info("---");
282+
logger.info("🔧 API Endpoints registered:");
283+
logger.info(" GET /api/test");
284+
logger.info(" GET /api/snippets");
285+
logger.info(" GET /api/snippets/:id");
286+
logger.info(" POST /api/snippets");
287+
logger.info(" PUT /api/snippets/:id");
288+
logger.info(" DELETE /api/snippets/:id");
289+
logger.info(" POST /api/snippets/:id/favorite");
290+
logger.info(" GET /api/languages");
291+
logger.info(" GET /api/tags");
292+
logger.info(" POST /api/auth/user");
293+
logger.info(" GET /api/auth/me");
294+
logger.info("---");
294295
}
295296
);
296297

297298
// Handle process termination gracefully
298299
process.on('SIGTERM', () => {
299-
console.log('🛑 SIGTERM received, shutting down gracefully');
300+
logger.info('🛑 SIGTERM received, shutting down gracefully');
300301
server.close(() => {
301-
console.log('✅ Server closed');
302+
logger.info('✅ Server closed');
302303
process.exit(0);
303304
});
304305
});
305306

306307
process.on('SIGINT', () => {
307-
console.log('🛑 SIGINT received, shutting down gracefully');
308+
logger.info('🛑 SIGINT received, shutting down gracefully');
308309
server.close(() => {
309-
console.log('✅ Server closed');
310+
logger.info('✅ Server closed');
310311
process.exit(0);
311312
});
312313
});
313314

314315
})().catch((error) => {
315-
console.error('❌ Failed to start server:', error);
316+
logger.error("❌ Failed to start server:", error);
316317
process.exit(1);
317318
});

server/routes.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { DecodedIdToken } from "firebase-admin/auth";
66
import { pool } from "./db";
77
import { storage } from "./storage";
88
import { simpleStorage } from "./simple-storage";
9+
import logger from "../src/logger.js";
910
import {
1011
insertSnippetSchema,
1112
insertCollectionSchema,
@@ -19,10 +20,10 @@ import { z } from "zod";
1920
;(async () => {
2021
try {
2122
const client = await pool.connect();
22-
console.log("✅ DATABASE CONNECTION TEST: OK —", (await client.query("SELECT NOW()")).rows[0].now);
23+
logger.info(`✅ DATABASE CONNECTION TEST: OK — ${(await client.query("SELECT NOW()")).rows[0].now}`);
2324
client.release();
2425
} catch (e) {
25-
console.error("❌ DATABASE CONNECTION TEST: FAILED", e);
26+
logger.error("❌ DATABASE CONNECTION TEST: FAILED", e);
2627
}
2728
})();
2829

src/logger.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { createLogger, format, transports } from 'winston';
2+
3+
const logger = createLogger({
4+
level: 'info',
5+
format: format.combine(
6+
format.colorize(),
7+
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
8+
format.printf(({ timestamp, level, message, ...meta }) => {
9+
const metaString = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';
10+
return `${timestamp} [${level}]: ${message}${metaString}`;
11+
})
12+
),
13+
transports: [
14+
new transports.Console(),
15+
new transports.File({ filename: '/home/zk/logs/codepatchwork.log' })
16+
]
17+
});
18+
19+
export default logger;

0 commit comments

Comments
 (0)