feat: add allowed Linear API operations to MCP config
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import winston from 'winston'
|
||||
import LokiTransport from 'winston-loki'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV === 'development'
|
||||
|
||||
// Custom format for structured logging
|
||||
const structuredFormat = winston.format.combine(
|
||||
winston.format.timestamp({ format: 'ISO' }),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.json({
|
||||
replacer: (_key, value) =>
|
||||
typeof value === 'bigint' ? value.toString() : value,
|
||||
})
|
||||
)
|
||||
|
||||
// Console format for development
|
||||
const consoleFormat = winston.format.combine(
|
||||
winston.format.timestamp({ format: 'HH:mm:ss' }),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.colorize(),
|
||||
winston.format.simple(),
|
||||
winston.format.printf(({ timestamp, level, message, service, requestId, ...meta }) => {
|
||||
const requestInfo = requestId ? `[${requestId}]` : ''
|
||||
const serviceInfo = service ? `[${service}]` : '[mozdIT]'
|
||||
const metaStr = Object.keys(meta).length ? `\n${JSON.stringify(meta, null, 2)}` : ''
|
||||
return `${timestamp} ${serviceInfo} ${level} ${requestInfo} ${message}${metaStr}`
|
||||
})
|
||||
)
|
||||
|
||||
// Transports configuration
|
||||
const transports: winston.transport[] = [
|
||||
// Loki transport for centralized logging
|
||||
...(process.env.LOKI_HOST
|
||||
? [
|
||||
new LokiTransport({
|
||||
host: process.env.LOKI_HOST,
|
||||
labels: {
|
||||
app: 'mozdit-web',
|
||||
environment: process.env.NODE_ENV || 'development',
|
||||
service: 'frontend'
|
||||
},
|
||||
basicAuth: process.env.LOKI_USERNAME && process.env.LOKI_PASSWORD
|
||||
? `${process.env.LOKI_USERNAME}:${process.env.LOKI_PASSWORD}`
|
||||
: undefined,
|
||||
json: true,
|
||||
format: winston.format.json(),
|
||||
onConnectionError: (err: Error) => console.error('Loki connection error:', err)
|
||||
})
|
||||
]
|
||||
: []),
|
||||
|
||||
// Console for development logging
|
||||
new winston.transports.Console({
|
||||
level: isDevelopment ? 'debug' : 'info',
|
||||
format: isDevelopment ? consoleFormat : structuredFormat,
|
||||
handleExceptions: true,
|
||||
handleRejections: true
|
||||
})
|
||||
]
|
||||
|
||||
// Root logger configuration
|
||||
export const logger = winston.createLogger({
|
||||
level: isDevelopment ? 'debug' : 'info',
|
||||
format: structuredFormat,
|
||||
defaultMeta: {
|
||||
service: 'mozdit-web',
|
||||
version: process.env.npm_package_version || '1.0.0',
|
||||
environment: process.env.NODE_ENV || 'development'
|
||||
},
|
||||
transports,
|
||||
exceptionHandlers: transports,
|
||||
rejectionHandlers: transports
|
||||
})
|
||||
|
||||
// Specialized loggers for different components
|
||||
export const createComponentLogger = (component: string) => {
|
||||
return logger.child({ component })
|
||||
}
|
||||
|
||||
export const requestLogger = logger.child({ component: 'request' })
|
||||
export const apiLogger = logger.child({ component: 'api' })
|
||||
export const dbLogger = logger.child({ component: 'database' })
|
||||
export const authLogger = logger.child({ component: 'auth' })
|
||||
export const errorLogger = logger.child({ component: 'error' })
|
||||
|
||||
// Request ID generator for correlation
|
||||
export const generateRequestId = (): string =>
|
||||
`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||
|
||||
// Helper function for timing operations
|
||||
export const withTiming = async <T>(
|
||||
operation: string,
|
||||
fn: () => Promise<T>,
|
||||
metadata: any = {}
|
||||
): Promise<T> => {
|
||||
const startTime = Date.now()
|
||||
logger.debug(`Started ${operation}`, metadata)
|
||||
|
||||
try {
|
||||
const result = await fn()
|
||||
const duration = Date.now() - startTime
|
||||
logger.debug(`Completed ${operation} in ${duration}ms`, { ...metadata, duration })
|
||||
return result
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime
|
||||
logger.error(`Failed ${operation} in ${duration}ms`, { ...metadata, duration, error })
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Graceful shutdown
|
||||
const gracefulShutdown = () => {
|
||||
logger.info('Initiating graceful shutdown...')
|
||||
logger.end()
|
||||
}
|
||||
|
||||
process.on('SIGTERM', gracefulShutdown)
|
||||
process.on('SIGINT', gracefulShutdown)
|
||||
|
||||
export default logger
|
||||
Reference in New Issue
Block a user