import winston from "winston"; /** * Structured Logging mit Winston * Erstellt JSON-Logs für bessere Analyse und Monitoring */ export const logger = winston.createLogger({ level: process.env.LOG_LEVEL || "info", format: winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json() ), defaultMeta: { service: "graphql-middlelayer", environment: process.env.NODE_ENV || "development", }, transports: [ // Console Output (für Development) new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), winston.format.printf(({ timestamp, level, message, ...meta }) => { const metaStr = Object.keys(meta).length ? JSON.stringify(meta, null, 2) : ""; return `${timestamp} [${level}]: ${message} ${metaStr}`; }) ), }), // File Output (für Production) ...(process.env.NODE_ENV === "production" ? [ new winston.transports.File({ filename: "logs/error.log", level: "error", }), new winston.transports.File({ filename: "logs/combined.log", }), ] : []), ], }); // Helper-Funktionen für strukturiertes Logging export const logQuery = ( operationName: string, variables: any, duration: number ) => { logger.info("GraphQL Query executed", { operation: operationName, variables, duration: `${duration}ms`, type: "query", }); }; export const logError = (error: Error, context?: Record) => { logger.error("Error occurred", { error: { message: error.message, stack: error.stack, name: error.name, }, ...context, type: "error", }); }; export const logCacheHit = (key: string, type: string) => { logger.debug("Cache hit", { cacheKey: key, cacheType: type, type: "cache", }); }; export const logCacheMiss = (key: string, type: string) => { logger.debug("Cache miss", { cacheKey: key, cacheType: type, type: "cache", }); };