feat: add logger.js and signifigantly improve logging
This commit is contained in:
168
app.js
168
app.js
@ -2,6 +2,7 @@ const express = require("express");
|
||||
const path = require("path");
|
||||
const bodyParser = require("body-parser");
|
||||
const API = require("./src/js/index.js");
|
||||
const { logger } = require('./src/js/logger');
|
||||
const favicon = require('serve-favicon');
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3512;
|
||||
@ -30,12 +31,12 @@ try {
|
||||
if (fs.existsSync(replacementsPath)) {
|
||||
const replacementsContent = fs.readFileSync(replacementsPath, 'utf8');
|
||||
keyReplacements = JSON.parse(replacementsContent);
|
||||
// console.log("Replacements loaded successfully");
|
||||
// logger.debug("Replacements loaded successfully");
|
||||
} else {
|
||||
console.log("replacements.json not found, key replacement disabled");
|
||||
logger.warn("replacements.json not found, key replacement disabled");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading replacements file:", error);
|
||||
logger.error("Error loading replacements file:", { error: error.message });
|
||||
}
|
||||
|
||||
const replaceJsonKeys = (obj) => {
|
||||
@ -52,14 +53,14 @@ const replaceJsonKeys = (obj) => {
|
||||
|
||||
// DEBUG: Log replacements when they happen
|
||||
// if (newKey !== key) {
|
||||
// console.log(`Replacing key "${key}" with "${newKey}"`);
|
||||
// logger.debug(`Replacing key "${key}" with "${newKey}"`);
|
||||
// }
|
||||
|
||||
// Also check if the value should be replaced (if it's a string)
|
||||
let value = obj[key];
|
||||
if (typeof value === 'string' && keyReplacements[value]) {
|
||||
value = keyReplacements[value];
|
||||
// console.log(`Replacing value "${obj[key]}" with "${value}"`);
|
||||
// logger.debug(`Replacing value "${obj[key]}" with "${value}"`);
|
||||
}
|
||||
|
||||
// Process value recursively if it's an object or array
|
||||
@ -140,26 +141,26 @@ const timeoutPromise = (ms) => {
|
||||
// Helper function to ensure login
|
||||
const ensureLogin = async (ssoToken) => {
|
||||
if (!activeSessions.has(ssoToken)) {
|
||||
console.log(`Attempting to login with SSO token: ${ssoToken.substring(0, 5)}...`);
|
||||
// console.log(`Attempting to login with SSO token: ${ssoToken}`);
|
||||
logger.info(`Attempting to login with SSO token: ${ssoToken.substring(0, 5)}...`);
|
||||
// logger.info(`Attempting to login with SSO token: ${ssoToken}`);
|
||||
const loginResult = await Promise.race([
|
||||
API.login(ssoToken),
|
||||
timeoutPromise(10000), // 10 second timeout
|
||||
]);
|
||||
|
||||
console.log(`Login successful: ${JSON.stringify(loginResult)}`);
|
||||
console.log(`Session created at: ${new Date().toISOString()}`);
|
||||
logger.debug(`Login successful: ${JSON.stringify(loginResult)}`);
|
||||
logger.debug(`Session created at: ${new Date().toISOString()}`);
|
||||
activeSessions.set(ssoToken, new Date());
|
||||
} else {
|
||||
console.log("Using existing session");
|
||||
logger.debug("Using existing session");
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to handle API errors
|
||||
const handleApiError = (error, res) => {
|
||||
console.error("API Error:", error);
|
||||
console.error(`Error Stack: ${error.stack}`);
|
||||
console.error(`Error Time: ${new Date().toISOString()}`);
|
||||
logger.error("API Error:", error);
|
||||
logger.error(`Error Stack: ${error.stack}`);
|
||||
logger.error(`Error Time: ${new Date().toISOString()}`);
|
||||
|
||||
// Try to extract more useful information from the error
|
||||
let errorMessage = error.message || "Unknown API error";
|
||||
@ -167,7 +168,7 @@ const handleApiError = (error, res) => {
|
||||
|
||||
// Handle the specific JSON parsing error
|
||||
if (errorName === "SyntaxError" && errorMessage.includes("JSON")) {
|
||||
console.log("JSON parsing error detected");
|
||||
logger.debug("JSON parsing error detected");
|
||||
return res.status(200).json({
|
||||
status: "error",
|
||||
message:
|
||||
@ -188,9 +189,9 @@ const handleApiError = (error, res) => {
|
||||
|
||||
// API endpoint to fetch stats
|
||||
app.post("/api/stats", async (req, res) => {
|
||||
console.log("Received request for /api/stats");
|
||||
console.log(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
console.log(`Request JSON: ${JSON.stringify({
|
||||
logger.debug("Received request for /api/stats");
|
||||
logger.debug(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
logger.debug(`Request JSON: ${JSON.stringify({
|
||||
username: req.body.username,
|
||||
platform: req.body.platform,
|
||||
game: req.body.game,
|
||||
@ -203,17 +204,17 @@ app.post("/api/stats", async (req, res) => {
|
||||
const { username, ssoToken, platform, game, apiCall, sanitize, replaceKeys } = req.body;
|
||||
|
||||
/*
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Request details - Username: ${username}, Platform: ${platform}, Game: ${game}, API Call: ${apiCall}`
|
||||
);
|
||||
|
||||
console.log("=== STATS REQUEST ===");
|
||||
console.log(`Username: ${username || 'Not provided'}`);
|
||||
console.log(`Platform: ${platform}`);
|
||||
console.log(`Game: ${game}`);
|
||||
console.log(`API Call: ${apiCall}`);
|
||||
console.log(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
console.log("====================="); */
|
||||
logger.debug("=== STATS REQUEST ===");
|
||||
logger.debug(`Username: ${username || 'Not provided'}`);
|
||||
logger.debug(`Platform: ${platform}`);
|
||||
logger.debug(`Game: ${game}`);
|
||||
logger.debug(`API Call: ${apiCall}`);
|
||||
logger.debug(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
logger.debug("====================="); */
|
||||
|
||||
if (!ssoToken) {
|
||||
return res.status(400).json({ error: "SSO Token is required" });
|
||||
@ -226,7 +227,7 @@ app.post("/api/stats", async (req, res) => {
|
||||
|
||||
// Clear previous session if it exists
|
||||
if (activeSessions.has(ssoToken)) {
|
||||
console.log("Clearing previous session");
|
||||
logger.debug("Clearing previous session");
|
||||
activeSessions.delete(ssoToken);
|
||||
}
|
||||
|
||||
@ -255,7 +256,7 @@ app.post("/api/stats", async (req, res) => {
|
||||
// Check if the platform is valid for the game
|
||||
const requiresUno = ["mw2", "wz2", "mw3", "wzm"].includes(game);
|
||||
if (requiresUno && platform !== "uno" && apiCall !== "mapList") {
|
||||
console.log(`${game} requires Uno ID`);
|
||||
logger.warn(`${game} requires Uno ID`);
|
||||
return res.status(200).json({
|
||||
status: "error",
|
||||
message: `${game} requires Uno ID (numerical ID)`,
|
||||
@ -264,7 +265,7 @@ app.post("/api/stats", async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Attempting to fetch ${game} data for ${username} on ${platform}`
|
||||
);
|
||||
let data;
|
||||
@ -384,13 +385,13 @@ app.post("/api/stats", async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Data fetched successfully");
|
||||
console.log(`Response Size: ~${JSON.stringify(data).length / 1024} KB`);
|
||||
console.log(`Response Time: ${new Date().toISOString()}`);
|
||||
logger.debug("Data fetched successfully");
|
||||
logger.debug(`Response Size: ~${JSON.stringify(data).length / 1024} KB`);
|
||||
logger.debug(`Response Time: ${new Date().toISOString()}`);
|
||||
|
||||
// Safely handle the response data
|
||||
if (!data) {
|
||||
console.log("No data returned from API");
|
||||
logger.warn("No data returned from API");
|
||||
return res.json({
|
||||
status: "partial_success",
|
||||
message: "No data returned from API, but no error thrown",
|
||||
@ -399,7 +400,7 @@ app.post("/api/stats", async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
// console.log("Returning data to client");
|
||||
// logger.debug("Returning data to client");
|
||||
|
||||
const { sanitize, replaceKeys } = req.body;
|
||||
|
||||
@ -426,9 +427,9 @@ app.post("/api/stats", async (req, res) => {
|
||||
|
||||
// API endpoint to fetch recent matches
|
||||
app.post("/api/matches", async (req, res) => {
|
||||
console.log("Received request for /api/matches");
|
||||
console.log(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
console.log(`Request JSON: ${JSON.stringify({
|
||||
logger.debug("Received request for /api/matches");
|
||||
logger.debug(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
logger.debug(`Request JSON: ${JSON.stringify({
|
||||
username: req.body.username,
|
||||
platform: req.body.platform,
|
||||
game: req.body.game,
|
||||
@ -440,16 +441,16 @@ app.post("/api/matches", async (req, res) => {
|
||||
const { username, ssoToken, platform, game, sanitize, replaceKeys } = req.body;
|
||||
|
||||
/*
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Request details - Username: ${username}, Platform: ${platform}, Game: ${game}`
|
||||
);
|
||||
|
||||
console.log("=== MATCHES REQUEST ===");
|
||||
console.log(`Username: ${username}`);
|
||||
console.log(`Platform: ${platform}`);
|
||||
console.log(`Game: ${game}`);
|
||||
console.log(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
console.log("========================"); */
|
||||
logger.debug("=== MATCHES REQUEST ===");
|
||||
logger.debug(`Username: ${username}`);
|
||||
logger.debug(`Platform: ${platform}`);
|
||||
logger.debug(`Game: ${game}`);
|
||||
logger.debug(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
logger.debug("========================"); */
|
||||
|
||||
if (!username || !ssoToken) {
|
||||
return res
|
||||
@ -478,7 +479,7 @@ app.post("/api/matches", async (req, res) => {
|
||||
};
|
||||
|
||||
try {
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Attempting to fetch combat history for ${username} on ${platform}`
|
||||
);
|
||||
let data;
|
||||
@ -565,9 +566,9 @@ app.post("/api/matches", async (req, res) => {
|
||||
|
||||
// API endpoint to fetch match info
|
||||
app.post("/api/matchInfo", async (req, res) => {
|
||||
console.log("Received request for /api/matchInfo");
|
||||
console.log(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
console.log(`Request JSON: ${JSON.stringify({
|
||||
logger.debug("Received request for /api/matchInfo");
|
||||
logger.debug(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
logger.debug(`Request JSON: ${JSON.stringify({
|
||||
matchId: req.body.matchId,
|
||||
platform: req.body.platform,
|
||||
game: req.body.game,
|
||||
@ -580,16 +581,16 @@ app.post("/api/matchInfo", async (req, res) => {
|
||||
const mode = "mp";
|
||||
|
||||
/*
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Request details - Match ID: ${matchId}, Platform: ${platform}, Game: ${game}`
|
||||
);
|
||||
|
||||
console.log("=== MATCH INFO REQUEST ===");
|
||||
console.log(`Match ID: ${matchId}`);
|
||||
console.log(`Platform: ${platform}`);
|
||||
console.log(`Game: ${game}`);
|
||||
console.log(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
console.log("=========================="); */
|
||||
logger.debug("=== MATCH INFO REQUEST ===");
|
||||
logger.debug(`Match ID: ${matchId}`);
|
||||
logger.debug(`Platform: ${platform}`);
|
||||
logger.debug(`Game: ${game}`);
|
||||
logger.debug(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
logger.debug("=========================="); */
|
||||
|
||||
if (!matchId || !ssoToken) {
|
||||
return res
|
||||
@ -618,7 +619,7 @@ app.post("/api/matchInfo", async (req, res) => {
|
||||
};
|
||||
|
||||
try {
|
||||
console.log(`Attempting to fetch match info for match ID: ${matchId}`);
|
||||
logger.debug(`Attempting to fetch match info for match ID: ${matchId}`);
|
||||
let data;
|
||||
|
||||
// Fetch match info based on game
|
||||
@ -691,9 +692,9 @@ app.post("/api/matchInfo", async (req, res) => {
|
||||
|
||||
// API endpoint for user-related API calls
|
||||
app.post("/api/user", async (req, res) => {
|
||||
console.log("Received request for /api/user");
|
||||
console.log(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
console.log(`Request JSON: ${JSON.stringify({
|
||||
logger.debug("Received request for /api/user");
|
||||
logger.debug(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
logger.debug(`Request JSON: ${JSON.stringify({
|
||||
username: req.body.username,
|
||||
platform: req.body.platform,
|
||||
userCall: req.body.userCall,
|
||||
@ -705,16 +706,16 @@ app.post("/api/user", async (req, res) => {
|
||||
const { username, ssoToken, platform, userCall, sanitize, replaceKeys } = req.body;
|
||||
|
||||
/*
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Request details - Username: ${username}, Platform: ${platform}, User Call: ${userCall}`
|
||||
);
|
||||
|
||||
console.log("=== USER DATA REQUEST ===");
|
||||
console.log(`Username: ${username || 'Not provided'}`);
|
||||
console.log(`Platform: ${platform}`);
|
||||
console.log(`User Call: ${userCall}`);
|
||||
console.log(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
console.log("========================="); */
|
||||
logger.debug("=== USER DATA REQUEST ===");
|
||||
logger.debug(`Username: ${username || 'Not provided'}`);
|
||||
logger.debug(`Platform: ${platform}`);
|
||||
logger.debug(`User Call: ${userCall}`);
|
||||
logger.debug(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
logger.debug("========================="); */
|
||||
|
||||
if (!ssoToken) {
|
||||
return res.status(400).json({ error: "SSO Token is required" });
|
||||
@ -753,7 +754,7 @@ app.post("/api/user", async (req, res) => {
|
||||
};
|
||||
|
||||
try {
|
||||
console.log(`Attempting to fetch user data for ${userCall}`);
|
||||
logger.debug(`Attempting to fetch user data for ${userCall}`);
|
||||
let data;
|
||||
|
||||
// Fetch user data based on userCall
|
||||
@ -817,9 +818,9 @@ app.post("/api/user", async (req, res) => {
|
||||
|
||||
// API endpoint for fuzzy search
|
||||
app.post("/api/search", async (req, res) => {
|
||||
console.log("Received request for /api/search");
|
||||
console.log(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
console.log(`Request JSON: ${JSON.stringify({
|
||||
logger.debug("Received request for /api/search");
|
||||
logger.debug(`Request IP: ${req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress}`);
|
||||
logger.debug(`Request JSON: ${JSON.stringify({
|
||||
username: req.body.username,
|
||||
platform: req.body.platform,
|
||||
sanitize: req.body.sanitize,
|
||||
@ -830,15 +831,15 @@ app.post("/api/search", async (req, res) => {
|
||||
const { username, ssoToken, platform, sanitize, replaceKeys } = req.body;
|
||||
|
||||
/*
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Request details - Username to search: ${username}, Platform: ${platform}`
|
||||
);
|
||||
|
||||
console.log("=== SEARCH REQUEST ===");
|
||||
console.log(`Search Term: ${username}`);
|
||||
console.log(`Platform: ${platform}`);
|
||||
console.log(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
console.log("======================"); */
|
||||
logger.debug("=== SEARCH REQUEST ===");
|
||||
logger.debug(`Search Term: ${username}`);
|
||||
logger.debug(`Platform: ${platform}`);
|
||||
logger.debug(`Processing Options - Sanitize: ${sanitize}, Replace Keys: ${replaceKeys}`);
|
||||
logger.debug("======================"); */
|
||||
|
||||
if (!username || !ssoToken) {
|
||||
return res
|
||||
@ -867,7 +868,7 @@ app.post("/api/search", async (req, res) => {
|
||||
};
|
||||
|
||||
try {
|
||||
console.log(
|
||||
logger.debug(
|
||||
`Attempting fuzzy search for ${username} on platform ${platform}`
|
||||
);
|
||||
const data = await fetchWithTimeout(() =>
|
||||
@ -929,15 +930,14 @@ app.post('/api/log', (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// For structured logging in production, consider using a logging service
|
||||
console.log(`[USER_ACTIVITY] ${JSON.stringify(enrichedLog)}`);
|
||||
|
||||
// Optional: Store logs in database for advanced analytics
|
||||
// storeLogInDatabase(enrichedLog);
|
||||
// Use the dedicated user activity logger
|
||||
logger.userActivity(enrichedLog.eventType || 'unknown', enrichedLog);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error processing log data:', error);
|
||||
console.log('Raw request body:', req.body);
|
||||
logger.error('Error processing log data', {
|
||||
error: error.message,
|
||||
rawBody: typeof req.body === 'object' ? '[Object]' : req.body
|
||||
});
|
||||
}
|
||||
|
||||
// Always return 200 to avoid client-side errors
|
||||
@ -980,5 +980,5 @@ app.get("/", (req, res) => {
|
||||
|
||||
// Start the server
|
||||
app.listen(port, () => {
|
||||
console.log(`Server running on http://localhost:${port}`);
|
||||
logger.info(`Server running on http://localhost:${port}`);
|
||||
});
|
||||
|
Reference in New Issue
Block a user