UNPKG

sfcoe-ailabs

Version:

AI-powered code review tool with static analysis integration for comprehensive code quality assessment.

282 lines (281 loc) 9.01 kB
import * as process from 'node:process'; import { DatadogLogger, } from '../observability/logging/index.js'; import { DatadogMetrics, } from '../observability/metrics/index.js'; import { DATADOG_DEFAULT_CONSTANTS } from './constants.js'; /** * Centralized logger utility for debug and error logging * This serves as a facade to the Datadog logger backend */ export class Logger { static initialized = false; /** * Initialize the logger with Datadog configuration * * @param config - The Datadog logger configuration object * @returns The initialized Winston logger instance */ static initialize(config) { if (this.initialized) { return DatadogLogger.getInstance(); } const logger = DatadogLogger.initialize(config); this.initialized = true; return logger; } /** * Check if logger is initialized * * @returns True if the logger is initialized, false otherwise */ static isInitialized() { return this.initialized; } /** * Log debug messages (only when debug is enabled) * * @param message - The debug message to log * @param args - Additional arguments to include in the log metadata */ static debug(message, ...args) { const meta = this.argsToMeta(args); DatadogLogger.debug(message, meta); } /** * Log info messages */ static info(message, ...args) { const meta = this.argsToMeta(args); DatadogLogger.info(message, meta); } /** * Log warning messages */ static warn(message, ...args) { const meta = this.argsToMeta(args); DatadogLogger.warn(message, meta); } /** * Log error messages */ static error(message, ...args) { const meta = this.argsToMeta(args); // Handle error objects in the args const errorArg = args.find((arg) => arg instanceof Error); if (errorArg) { DatadogLogger.error(message, errorArg); } else { DatadogLogger.error(message, meta); } } /** * Log with custom level and metadata (backward compatibility) */ static log(level, message, ...args) { const meta = this.argsToMeta(args); DatadogLogger.log(level, message, meta); } /** * Convert variadic arguments to metadata object for structured logging */ static argsToMeta(args) { if (args.length === 0) { return {}; } // If first argument is already an object, use it if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) { return args[0]; } // Convert args to indexed object const meta = {}; args.forEach((arg) => { if (arg instanceof Error) { meta['error'] = { message: arg.message, stack: arg.stack, name: arg.name, }; } else { meta['data'] = arg; } }); return meta; } } /** * High-level metrics utility for the application * This serves as a facade to the Datadog metrics backend */ export class Metrics { static initialized = false; /** * Initialize the metrics system with Datadog configuration */ static initialize(config) { if (this.initialized) { return; } DatadogMetrics.initialize(config); this.initialized = true; } /** * Check if metrics system is initialized */ static isInitialized() { return this.initialized; } /** * Send a counter metric */ static increment(metric, value = 1, tags = []) { DatadogMetrics.increment(metric, value, tags); } /** * Send a decrement metric */ static decrement(metric, value = 1, tags = []) { DatadogMetrics.decrement(metric, value, tags); } /** * Send a gauge metric */ static gauge(metric, value, tags = []) { DatadogMetrics.gauge(metric, value, tags); } /** * Send a histogram metric */ static histogram(metric, value, tags = []) { DatadogMetrics.histogram(metric, value, tags); } /** * Send a timing metric */ static timing(metric, value, tags = []) { DatadogMetrics.timing(metric, value, tags); } /** * Send a distribution metric */ static distribution(metric, value, tags = []) { DatadogMetrics.distribution(metric, value, tags); } /** * Send a set metric */ static set(metric, value, tags = []) { DatadogMetrics.set(metric, value, tags); } /** * Flush buffered metrics immediately */ static flush() { DatadogMetrics.flush(); } /** * Close the metrics client */ static close() { DatadogMetrics.close(); } } /** * Utility to initialize observability components (logging and metrics) */ export class ObservabilityInitializer { static initialized = false; /** * Initialize both logging and metrics with provided configuration * * @param flags Record of command flags that will be included in logs and metrics. * The following flags are included by default: * - pull-request-id: Added as pullRequestId in logs and pull-request-id tag in metrics * - repo-dir: Added as repoDir in logs and repo-dir tag in metrics * - from: Added as from in logs and from tag in metrics * - to: Added as to in logs and to tag in metrics * - ai-provider: Added as aiProvider in logs and ai-provider tag in metrics * - ai-model: Added as aiModel in logs and ai-model tag in metrics * - git-provider: Added as gitProvider in logs and git-provider tag in metrics * - git-owner: Added as gitOwner in logs and git-owner tag in metrics * - git-repo: Added as gitRepo in logs and git-repo tag in metrics * * @example * ```typescript * // Basic usage with command flags * ObservabilityInitializer.initialize(flags); * * // Usage with custom flags object * ObservabilityInitializer.initialize({ * 'pull-request-id': '123', * 'ai-provider': 'OpenAI', * 'custom-flag': 'custom-value' // This won't be included unless added to default list * }); * ``` */ static initialize(flags) { if (this.initialized) { return; } // Build configuration const config = this.buildConfigFromEnv(flags); // Initialize logger Logger.initialize(config.logger); // Initialize metrics Metrics.initialize(config.metrics); // Mark as initialized this.initialized = true; } /** * Check if observability is initialized */ static isInitialized() { return this.initialized; } /** * Get default flags to include in observability metadata */ static getDefaultFlagsToInclude() { return [...DATADOG_DEFAULT_CONSTANTS.observabilityFlags]; } /** * Build configuration from environment variables and flags with custom flag inclusion */ static buildConfigFromEnv(flags) { const flagsToInclude = this.getDefaultFlagsToInclude(); // Build custom metadata from flags const customMeta = {}; if (flags) { for (const flagKey of flagsToInclude) { const flagValue = flags[flagKey]; if (flagValue !== undefined && flagValue !== null && flagValue !== '') { customMeta[flagKey] = flagValue; } } } return { logger: { apiKey: process.env.DD_API_KEY ?? '', ddsource: process.env.DD_SOURCE ?? DATADOG_DEFAULT_CONSTANTS.ddsource, hostname: process.env.DD_HOSTNAME ?? DATADOG_DEFAULT_CONSTANTS.hostname, service: process.env.DD_SERVICE ?? DATADOG_DEFAULT_CONSTANTS.service, environment: process.env.DD_ENV ?? DATADOG_DEFAULT_CONSTANTS.environment, logLevel: process.env.LOG_LEVEL ?? DATADOG_DEFAULT_CONSTANTS.logLevel, customMeta, }, metrics: { apiKey: process.env.DD_API_KEY ?? '', host: process.env.DD_HOSTNAME ?? DATADOG_DEFAULT_CONSTANTS.hostname, prefix: `${process.env.DD_METRIC_PREFIX ?? DATADOG_DEFAULT_CONSTANTS.prefix}.`, globalTags: [ `source:${process.env.DD_SOURCE ?? DATADOG_DEFAULT_CONSTANTS.ddsource}`, `service:${process.env.DD_SERVICE ?? DATADOG_DEFAULT_CONSTANTS.service}`, `env:${DATADOG_DEFAULT_CONSTANTS.environment}`, ], }, }; } }