@blac/logging-plugin 2.0.5 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -6
- package/dist/index.js.map +1 -1
- package/package.json +11 -5
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/formatters/SimpleFormatter.ts
|
|
3
3
|
var SimpleFormatter = class {
|
|
4
4
|
constructor(config) {
|
|
@@ -54,7 +54,6 @@ var SimpleFormatter = class {
|
|
|
54
54
|
return `${(ms / 6e4).toFixed(1)}m`;
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
|
-
|
|
58
57
|
//#endregion
|
|
59
58
|
//#region src/formatters/GroupedFormatter.ts
|
|
60
59
|
var GroupedFormatter = class {
|
|
@@ -128,7 +127,6 @@ var GroupedFormatter = class {
|
|
|
128
127
|
return `${(ms / 6e4).toFixed(1)}m`;
|
|
129
128
|
}
|
|
130
129
|
};
|
|
131
|
-
|
|
132
130
|
//#endregion
|
|
133
131
|
//#region src/monitors/InstanceCountMonitor.ts
|
|
134
132
|
var InstanceCountMonitor = class {
|
|
@@ -163,7 +161,6 @@ var InstanceCountMonitor = class {
|
|
|
163
161
|
this.warnedClasses.clear();
|
|
164
162
|
}
|
|
165
163
|
};
|
|
166
|
-
|
|
167
164
|
//#endregion
|
|
168
165
|
//#region src/monitors/LifecycleMonitor.ts
|
|
169
166
|
var LifecycleMonitor = class {
|
|
@@ -231,7 +228,6 @@ var LifecycleMonitor = class {
|
|
|
231
228
|
this.warnedClasses.clear();
|
|
232
229
|
}
|
|
233
230
|
};
|
|
234
|
-
|
|
235
231
|
//#endregion
|
|
236
232
|
//#region src/types.ts
|
|
237
233
|
function resolveConfig(config = {}) {
|
|
@@ -252,7 +248,6 @@ function resolveConfig(config = {}) {
|
|
|
252
248
|
prefix: config.prefix ?? "[BlaC]"
|
|
253
249
|
};
|
|
254
250
|
}
|
|
255
|
-
|
|
256
251
|
//#endregion
|
|
257
252
|
//#region src/LoggingPlugin.ts
|
|
258
253
|
const STATE_CHANGE_RATE_LIMIT = 1e3;
|
|
@@ -362,7 +357,7 @@ var LoggingPlugin = class {
|
|
|
362
357
|
else this.groupedFormatter.logWarning(message, details);
|
|
363
358
|
}
|
|
364
359
|
};
|
|
365
|
-
|
|
366
360
|
//#endregion
|
|
367
361
|
exports.LoggingPlugin = LoggingPlugin;
|
|
362
|
+
|
|
368
363
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/formatters/SimpleFormatter.ts","../src/formatters/GroupedFormatter.ts","../src/monitors/InstanceCountMonitor.ts","../src/monitors/LifecycleMonitor.ts","../src/types.ts","../src/LoggingPlugin.ts"],"sourcesContent":["import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class SimpleFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.logger.log(\n `${this.prefix} Plugin installed (${stats.registeredTypes} types, ${stats.totalInstances} instances)`,\n );\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const isolated = metadata.isIsolated ? ' (isolated)' : '';\n this.logger.log(`${this.prefix} Created ${instanceId}${isolated}`);\n }\n\n logInstanceDisposed(metadata: InstanceMetadata, lifespanMs: number): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const lifespan = this.formatDuration(lifespanMs);\n this.logger.log(\n `${this.prefix} Disposed ${instanceId} (lived ${lifespan})`,\n );\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n _callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const prev = this.formatState(previousState);\n const curr = this.formatState(currentState);\n this.logger.log(`${this.prefix} ${instanceId} state: ${prev} → ${curr}`);\n\n if (includeCallstack && _callstack) {\n this.logger.log(`${this.prefix} Callstack: ${_callstack}`);\n }\n }\n\n logWarning(message: string): void {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.logger.log(\n `${this.prefix} Stats: ${stats.totalInstances} instances across ${stats.registeredTypes} types`,\n );\n }\n\n private formatState(state: unknown): string {\n if (state === null) return 'null';\n if (state === undefined) return 'undefined';\n if (typeof state === 'object') {\n try {\n const str = JSON.stringify(state);\n return str.length > 50 ? str.slice(0, 50) + '...' : str;\n } catch {\n return '[Object]';\n }\n }\n return String(state);\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class GroupedFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n private group(label: string, collapsed = true): void {\n if (collapsed && this.logger.groupCollapsed) {\n this.logger.groupCollapsed(label);\n } else if (this.logger.group) {\n this.logger.group(label);\n } else {\n this.logger.log(label);\n }\n }\n\n private groupEnd(): void {\n if (this.logger.groupEnd) {\n this.logger.groupEnd();\n }\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.group(`${this.prefix} Plugin installed`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.groupEnd();\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata, initialState: unknown): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Created ${instanceId}`);\n this.logger.log('Class:', metadata.className);\n this.logger.log('Instance ID:', metadata.id);\n this.logger.log('Isolated:', metadata.isIsolated);\n this.logger.log('Initial state:', initialState);\n if (metadata.callstack) {\n this.logger.log('Callstack:', metadata.callstack);\n }\n this.groupEnd();\n }\n\n logInstanceDisposed(\n metadata: InstanceMetadata,\n lifespanMs: number,\n stateChangeCount: number,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Disposed ${instanceId}`);\n this.logger.log('Lifespan:', this.formatDuration(lifespanMs));\n this.logger.log('State changes:', stateChangeCount);\n this.logger.log('Final state:', metadata.state);\n this.groupEnd();\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} ${instanceId} state changed`);\n this.logger.log('Previous:', previousState);\n this.logger.log('Current:', currentState);\n if (includeCallstack && callstack) {\n this.logger.log('Callstack:', callstack);\n }\n this.groupEnd();\n }\n\n logWarning(message: string, details?: Record<string, unknown>): void {\n if (details) {\n this.group(`${this.prefix} ⚠️ ${message}`, false);\n for (const [key, value] of Object.entries(details)) {\n this.logger.log(`${key}:`, value);\n }\n this.groupEnd();\n } else {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.group(`${this.prefix} Stats`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.logger.log('Breakdown:', stats.typeBreakdown);\n this.groupEnd();\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { ResolvedConfig } from '../types';\n\nexport class InstanceCountMonitor {\n private instanceCounts = new Map<string, number>();\n private warnedClasses = new Set<string>();\n private threshold: number;\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.threshold = config.instanceCountWarningThreshold;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string): void {\n const count = (this.instanceCounts.get(className) ?? 0) + 1;\n this.instanceCounts.set(className, count);\n\n if (count >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `High instance count: ${className} has ${count} instances`,\n {\n className,\n count,\n threshold: this.threshold,\n },\n );\n }\n }\n\n onInstanceDisposed(className: string): void {\n const count = this.instanceCounts.get(className) ?? 0;\n if (count > 0) {\n this.instanceCounts.set(className, count - 1);\n }\n\n if (count - 1 < this.threshold) {\n this.warnedClasses.delete(className);\n }\n }\n\n getStats(): Map<string, number> {\n return new Map(this.instanceCounts);\n }\n\n reset(): void {\n this.instanceCounts.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { ResolvedConfig } from '../types';\n\ninterface LifecycleEvent {\n timestamp: number;\n type: 'created' | 'disposed';\n}\n\ninterface InstanceInfo {\n createdAt: number;\n stateChangeCount: number;\n}\n\nexport class LifecycleMonitor {\n private lifecycleHistory = new Map<string, LifecycleEvent[]>();\n private instanceInfo = new Map<string, InstanceInfo>();\n private windowMs: number;\n private threshold: number;\n private enabled: boolean;\n private warnedClasses = new Set<string>();\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.windowMs = config.rapidLifecycleWindowMs;\n this.threshold = config.rapidLifecycleThreshold;\n this.enabled = config.detectRapidLifecycles;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.set(instanceId, {\n createdAt: Date.now(),\n stateChangeCount: 0,\n });\n\n this.recordEvent(className, 'created');\n this.checkRapidLifecycle(className);\n }\n\n onInstanceDisposed(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.delete(instanceId);\n this.recordEvent(className, 'disposed');\n this.checkRapidLifecycle(className);\n }\n\n onStateChanged(instanceId: string): void {\n const info = this.instanceInfo.get(instanceId);\n if (info) {\n info.stateChangeCount++;\n }\n }\n\n getInstanceInfo(instanceId: string): InstanceInfo | undefined {\n return this.instanceInfo.get(instanceId);\n }\n\n private recordEvent(className: string, type: 'created' | 'disposed'): void {\n const now = Date.now();\n const events = this.lifecycleHistory.get(className) ?? [];\n\n events.push({ timestamp: now, type });\n\n const cutoff = now - this.windowMs;\n const filtered = events.filter((e) => e.timestamp > cutoff);\n this.lifecycleHistory.set(className, filtered);\n }\n\n private checkRapidLifecycle(className: string): void {\n const events = this.lifecycleHistory.get(className) ?? [];\n const cycleCount = Math.min(\n events.filter((e) => e.type === 'created').length,\n events.filter((e) => e.type === 'disposed').length,\n );\n\n if (cycleCount >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `Rapid lifecycle: ${className} created/disposed ${cycleCount} times in ${this.windowMs}ms`,\n {\n className,\n cycleCount,\n windowMs: this.windowMs,\n threshold: this.threshold,\n },\n );\n\n setTimeout(() => {\n this.warnedClasses.delete(className);\n }, this.windowMs);\n }\n }\n\n reset(): void {\n this.lifecycleHistory.clear();\n this.instanceInfo.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { StateContainer } from '@blac/core';\n\nexport type LogLevel = 'minimal' | 'info' | 'debug' | 'verbose';\n\nexport type LogFormat = 'simple' | 'grouped';\n\nexport interface Logger {\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n group?(label: string): void;\n groupEnd?(): void;\n groupCollapsed?(label: string): void;\n}\n\nexport interface FilterContext {\n instance: StateContainer<any>;\n className: string;\n instanceId: string;\n isIsolated: boolean;\n}\n\nexport type FilterFn = (ctx: FilterContext) => boolean;\n\nexport interface LoggingPluginConfig {\n /** Log verbosity level (default: 'info') */\n level?: LogLevel;\n\n /** Output format (default: 'grouped') */\n format?: LogFormat;\n\n /** Custom logger implementation (default: console) */\n logger?: Logger;\n\n /** Filter which instances to log */\n filter?: FilterFn;\n\n /** Include class names to log (whitelist) */\n include?: string[];\n\n /** Exclude class names from logging (blacklist) */\n exclude?: string[];\n\n /** Log instance creation/disposal (default: true) */\n logLifecycle?: boolean;\n\n /** Log state changes (default: true) */\n logStateChanges?: boolean;\n\n /** Include callstack in state change logs (default: false) */\n includeCallstack?: boolean;\n\n /** Warn when instance count exceeds threshold (default: 50) */\n instanceCountWarningThreshold?: number;\n\n /** Warn on rapid init/dispose cycles (default: true) */\n detectRapidLifecycles?: boolean;\n\n /** Time window for rapid lifecycle detection in ms (default: 1000) */\n rapidLifecycleWindowMs?: number;\n\n /** Number of cycles in window to trigger warning (default: 5) */\n rapidLifecycleThreshold?: number;\n\n /** Log prefix (default: '[BlaC]') */\n prefix?: string;\n}\n\nexport interface ResolvedConfig {\n level: LogLevel;\n format: LogFormat;\n logger: Logger;\n filter: FilterFn | undefined;\n include: string[] | undefined;\n exclude: string[] | undefined;\n logLifecycle: boolean;\n logStateChanges: boolean;\n includeCallstack: boolean;\n instanceCountWarningThreshold: number;\n detectRapidLifecycles: boolean;\n rapidLifecycleWindowMs: number;\n rapidLifecycleThreshold: number;\n prefix: string;\n}\n\nexport function resolveConfig(\n config: LoggingPluginConfig = {},\n): ResolvedConfig {\n return {\n level: config.level ?? 'info',\n format: config.format ?? 'grouped',\n logger: config.logger ?? console,\n filter: config.filter,\n include: config.include,\n exclude: config.exclude,\n logLifecycle: config.logLifecycle ?? true,\n logStateChanges: config.logStateChanges ?? true,\n includeCallstack: config.includeCallstack ?? false,\n instanceCountWarningThreshold: config.instanceCountWarningThreshold ?? 50,\n detectRapidLifecycles: config.detectRapidLifecycles ?? true,\n rapidLifecycleWindowMs: config.rapidLifecycleWindowMs ?? 1000,\n rapidLifecycleThreshold: config.rapidLifecycleThreshold ?? 5,\n prefix: config.prefix ?? '[BlaC]',\n };\n}\n","import type { BlacPlugin, PluginContext, StateContainer } from '@blac/core';\nimport { SimpleFormatter } from './formatters/SimpleFormatter';\nimport { GroupedFormatter } from './formatters/GroupedFormatter';\nimport { InstanceCountMonitor } from './monitors/InstanceCountMonitor';\nimport { LifecycleMonitor } from './monitors/LifecycleMonitor';\nimport type {\n LoggingPluginConfig,\n ResolvedConfig,\n FilterContext,\n} from './types';\nimport { resolveConfig } from './types';\n\nconst STATE_CHANGE_RATE_LIMIT = 1000; // max state changes per second\n\nexport class LoggingPlugin implements BlacPlugin {\n readonly name = 'LoggingPlugin';\n readonly version = '1.0.0';\n\n private config: ResolvedConfig;\n private context?: PluginContext;\n private simpleFormatter: SimpleFormatter;\n private groupedFormatter: GroupedFormatter;\n private instanceCountMonitor: InstanceCountMonitor;\n private lifecycleMonitor: LifecycleMonitor;\n\n // Rate limiting for state changes\n private stateChangeCount = 0;\n private stateChangeWindowStart = Date.now();\n private stateChangeLoggingDisabled = false;\n\n constructor(config: LoggingPluginConfig = {}) {\n this.config = resolveConfig(config);\n\n const warningHandler = (\n message: string,\n details?: Record<string, unknown>,\n ) => {\n this.logWarning(message, details);\n };\n\n this.simpleFormatter = new SimpleFormatter(this.config);\n this.groupedFormatter = new GroupedFormatter(this.config);\n this.instanceCountMonitor = new InstanceCountMonitor(\n this.config,\n warningHandler,\n );\n this.lifecycleMonitor = new LifecycleMonitor(this.config, warningHandler);\n }\n\n onInstall(context: PluginContext): void {\n this.context = context;\n const stats = context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstall(stats);\n } else {\n this.groupedFormatter.logInstall(stats);\n }\n }\n\n onUninstall(): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logUninstall();\n } else {\n this.groupedFormatter.logUninstall();\n }\n\n this.instanceCountMonitor.reset();\n this.lifecycleMonitor.reset();\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = Date.now();\n this.stateChangeLoggingDisabled = false;\n this.context = undefined;\n }\n\n onInstanceCreated(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.instanceCountMonitor.onInstanceCreated(metadata.className);\n this.lifecycleMonitor.onInstanceCreated(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceCreated(metadata);\n } else {\n this.groupedFormatter.logInstanceCreated(\n metadata,\n context.getState(instance),\n );\n }\n }\n\n onStateChanged<S extends object>(\n instance: StateContainer<S>,\n previousState: S,\n currentState: S,\n callstack: string | undefined,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.lifecycleMonitor.onStateChanged(metadata.id);\n\n if (!this.shouldLogStateChanges()) return;\n\n // Check rate limit\n if (this.stateChangeLoggingDisabled) return;\n\n const now = Date.now();\n if (now - this.stateChangeWindowStart >= 1000) {\n // Reset window\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = now;\n }\n\n this.stateChangeCount++;\n\n if (this.stateChangeCount > STATE_CHANGE_RATE_LIMIT) {\n this.stateChangeLoggingDisabled = true;\n this.logWarning(\n `State change logging disabled: exceeded ${STATE_CHANGE_RATE_LIMIT} changes/second`,\n );\n return;\n }\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n } else {\n this.groupedFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n }\n }\n\n onInstanceDisposed(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n const info = this.lifecycleMonitor.getInstanceInfo(metadata.id);\n const lifespanMs = info ? Date.now() - info.createdAt : 0;\n const stateChangeCount = info?.stateChangeCount ?? 0;\n\n this.instanceCountMonitor.onInstanceDisposed(metadata.className);\n this.lifecycleMonitor.onInstanceDisposed(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceDisposed(metadata, lifespanMs);\n } else {\n this.groupedFormatter.logInstanceDisposed(\n metadata,\n lifespanMs,\n stateChangeCount,\n );\n }\n }\n\n logStats(): void {\n if (!this.context) return;\n const stats = this.context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStats(stats);\n } else {\n this.groupedFormatter.logStats(stats);\n }\n }\n\n private shouldLog(\n instance: StateContainer<any>,\n className: string,\n instanceId: string,\n isIsolated: boolean,\n ): boolean {\n if (this.config.include && !this.config.include.includes(className)) {\n return false;\n }\n\n if (this.config.exclude?.includes(className)) {\n return false;\n }\n\n if (this.config.filter) {\n const ctx: FilterContext = {\n instance,\n className,\n instanceId,\n isIsolated,\n };\n return this.config.filter(ctx);\n }\n\n return true;\n }\n\n private shouldLogLifecycle(): boolean {\n if (!this.config.logLifecycle) return false;\n return this.config.level !== 'minimal';\n }\n\n private shouldLogStateChanges(): boolean {\n if (!this.config.logStateChanges) return false;\n return (\n this.config.level === 'info' ||\n this.config.level === 'debug' ||\n this.config.level === 'verbose'\n );\n }\n\n private logWarning(message: string, details?: Record<string, unknown>): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logWarning(message);\n } else {\n this.groupedFormatter.logWarning(message, details);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/formatters/SimpleFormatter.ts","../src/formatters/GroupedFormatter.ts","../src/monitors/InstanceCountMonitor.ts","../src/monitors/LifecycleMonitor.ts","../src/types.ts","../src/LoggingPlugin.ts"],"sourcesContent":["import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class SimpleFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.logger.log(\n `${this.prefix} Plugin installed (${stats.registeredTypes} types, ${stats.totalInstances} instances)`,\n );\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const isolated = metadata.isIsolated ? ' (isolated)' : '';\n this.logger.log(`${this.prefix} Created ${instanceId}${isolated}`);\n }\n\n logInstanceDisposed(metadata: InstanceMetadata, lifespanMs: number): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const lifespan = this.formatDuration(lifespanMs);\n this.logger.log(\n `${this.prefix} Disposed ${instanceId} (lived ${lifespan})`,\n );\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n _callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const prev = this.formatState(previousState);\n const curr = this.formatState(currentState);\n this.logger.log(`${this.prefix} ${instanceId} state: ${prev} → ${curr}`);\n\n if (includeCallstack && _callstack) {\n this.logger.log(`${this.prefix} Callstack: ${_callstack}`);\n }\n }\n\n logWarning(message: string): void {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.logger.log(\n `${this.prefix} Stats: ${stats.totalInstances} instances across ${stats.registeredTypes} types`,\n );\n }\n\n private formatState(state: unknown): string {\n if (state === null) return 'null';\n if (state === undefined) return 'undefined';\n if (typeof state === 'object') {\n try {\n const str = JSON.stringify(state);\n return str.length > 50 ? str.slice(0, 50) + '...' : str;\n } catch {\n return '[Object]';\n }\n }\n return String(state);\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class GroupedFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n private group(label: string, collapsed = true): void {\n if (collapsed && this.logger.groupCollapsed) {\n this.logger.groupCollapsed(label);\n } else if (this.logger.group) {\n this.logger.group(label);\n } else {\n this.logger.log(label);\n }\n }\n\n private groupEnd(): void {\n if (this.logger.groupEnd) {\n this.logger.groupEnd();\n }\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.group(`${this.prefix} Plugin installed`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.groupEnd();\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata, initialState: unknown): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Created ${instanceId}`);\n this.logger.log('Class:', metadata.className);\n this.logger.log('Instance ID:', metadata.id);\n this.logger.log('Isolated:', metadata.isIsolated);\n this.logger.log('Initial state:', initialState);\n if (metadata.callstack) {\n this.logger.log('Callstack:', metadata.callstack);\n }\n this.groupEnd();\n }\n\n logInstanceDisposed(\n metadata: InstanceMetadata,\n lifespanMs: number,\n stateChangeCount: number,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Disposed ${instanceId}`);\n this.logger.log('Lifespan:', this.formatDuration(lifespanMs));\n this.logger.log('State changes:', stateChangeCount);\n this.logger.log('Final state:', metadata.state);\n this.groupEnd();\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} ${instanceId} state changed`);\n this.logger.log('Previous:', previousState);\n this.logger.log('Current:', currentState);\n if (includeCallstack && callstack) {\n this.logger.log('Callstack:', callstack);\n }\n this.groupEnd();\n }\n\n logWarning(message: string, details?: Record<string, unknown>): void {\n if (details) {\n this.group(`${this.prefix} ⚠️ ${message}`, false);\n for (const [key, value] of Object.entries(details)) {\n this.logger.log(`${key}:`, value);\n }\n this.groupEnd();\n } else {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.group(`${this.prefix} Stats`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.logger.log('Breakdown:', stats.typeBreakdown);\n this.groupEnd();\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { ResolvedConfig } from '../types';\n\nexport class InstanceCountMonitor {\n private instanceCounts = new Map<string, number>();\n private warnedClasses = new Set<string>();\n private threshold: number;\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.threshold = config.instanceCountWarningThreshold;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string): void {\n const count = (this.instanceCounts.get(className) ?? 0) + 1;\n this.instanceCounts.set(className, count);\n\n if (count >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `High instance count: ${className} has ${count} instances`,\n {\n className,\n count,\n threshold: this.threshold,\n },\n );\n }\n }\n\n onInstanceDisposed(className: string): void {\n const count = this.instanceCounts.get(className) ?? 0;\n if (count > 0) {\n this.instanceCounts.set(className, count - 1);\n }\n\n if (count - 1 < this.threshold) {\n this.warnedClasses.delete(className);\n }\n }\n\n getStats(): Map<string, number> {\n return new Map(this.instanceCounts);\n }\n\n reset(): void {\n this.instanceCounts.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { ResolvedConfig } from '../types';\n\ninterface LifecycleEvent {\n timestamp: number;\n type: 'created' | 'disposed';\n}\n\ninterface InstanceInfo {\n createdAt: number;\n stateChangeCount: number;\n}\n\nexport class LifecycleMonitor {\n private lifecycleHistory = new Map<string, LifecycleEvent[]>();\n private instanceInfo = new Map<string, InstanceInfo>();\n private windowMs: number;\n private threshold: number;\n private enabled: boolean;\n private warnedClasses = new Set<string>();\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.windowMs = config.rapidLifecycleWindowMs;\n this.threshold = config.rapidLifecycleThreshold;\n this.enabled = config.detectRapidLifecycles;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.set(instanceId, {\n createdAt: Date.now(),\n stateChangeCount: 0,\n });\n\n this.recordEvent(className, 'created');\n this.checkRapidLifecycle(className);\n }\n\n onInstanceDisposed(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.delete(instanceId);\n this.recordEvent(className, 'disposed');\n this.checkRapidLifecycle(className);\n }\n\n onStateChanged(instanceId: string): void {\n const info = this.instanceInfo.get(instanceId);\n if (info) {\n info.stateChangeCount++;\n }\n }\n\n getInstanceInfo(instanceId: string): InstanceInfo | undefined {\n return this.instanceInfo.get(instanceId);\n }\n\n private recordEvent(className: string, type: 'created' | 'disposed'): void {\n const now = Date.now();\n const events = this.lifecycleHistory.get(className) ?? [];\n\n events.push({ timestamp: now, type });\n\n const cutoff = now - this.windowMs;\n const filtered = events.filter((e) => e.timestamp > cutoff);\n this.lifecycleHistory.set(className, filtered);\n }\n\n private checkRapidLifecycle(className: string): void {\n const events = this.lifecycleHistory.get(className) ?? [];\n const cycleCount = Math.min(\n events.filter((e) => e.type === 'created').length,\n events.filter((e) => e.type === 'disposed').length,\n );\n\n if (cycleCount >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `Rapid lifecycle: ${className} created/disposed ${cycleCount} times in ${this.windowMs}ms`,\n {\n className,\n cycleCount,\n windowMs: this.windowMs,\n threshold: this.threshold,\n },\n );\n\n setTimeout(() => {\n this.warnedClasses.delete(className);\n }, this.windowMs);\n }\n }\n\n reset(): void {\n this.lifecycleHistory.clear();\n this.instanceInfo.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { StateContainer } from '@blac/core';\n\nexport type LogLevel = 'minimal' | 'info' | 'debug' | 'verbose';\n\nexport type LogFormat = 'simple' | 'grouped';\n\nexport interface Logger {\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n group?(label: string): void;\n groupEnd?(): void;\n groupCollapsed?(label: string): void;\n}\n\nexport interface FilterContext {\n instance: StateContainer<any>;\n className: string;\n instanceId: string;\n isIsolated: boolean;\n}\n\nexport type FilterFn = (ctx: FilterContext) => boolean;\n\nexport interface LoggingPluginConfig {\n /** Log verbosity level (default: 'info') */\n level?: LogLevel;\n\n /** Output format (default: 'grouped') */\n format?: LogFormat;\n\n /** Custom logger implementation (default: console) */\n logger?: Logger;\n\n /** Filter which instances to log */\n filter?: FilterFn;\n\n /** Include class names to log (whitelist) */\n include?: string[];\n\n /** Exclude class names from logging (blacklist) */\n exclude?: string[];\n\n /** Log instance creation/disposal (default: true) */\n logLifecycle?: boolean;\n\n /** Log state changes (default: true) */\n logStateChanges?: boolean;\n\n /** Include callstack in state change logs (default: false) */\n includeCallstack?: boolean;\n\n /** Warn when instance count exceeds threshold (default: 50) */\n instanceCountWarningThreshold?: number;\n\n /** Warn on rapid init/dispose cycles (default: true) */\n detectRapidLifecycles?: boolean;\n\n /** Time window for rapid lifecycle detection in ms (default: 1000) */\n rapidLifecycleWindowMs?: number;\n\n /** Number of cycles in window to trigger warning (default: 5) */\n rapidLifecycleThreshold?: number;\n\n /** Log prefix (default: '[BlaC]') */\n prefix?: string;\n}\n\nexport interface ResolvedConfig {\n level: LogLevel;\n format: LogFormat;\n logger: Logger;\n filter: FilterFn | undefined;\n include: string[] | undefined;\n exclude: string[] | undefined;\n logLifecycle: boolean;\n logStateChanges: boolean;\n includeCallstack: boolean;\n instanceCountWarningThreshold: number;\n detectRapidLifecycles: boolean;\n rapidLifecycleWindowMs: number;\n rapidLifecycleThreshold: number;\n prefix: string;\n}\n\nexport function resolveConfig(\n config: LoggingPluginConfig = {},\n): ResolvedConfig {\n return {\n level: config.level ?? 'info',\n format: config.format ?? 'grouped',\n logger: config.logger ?? console,\n filter: config.filter,\n include: config.include,\n exclude: config.exclude,\n logLifecycle: config.logLifecycle ?? true,\n logStateChanges: config.logStateChanges ?? true,\n includeCallstack: config.includeCallstack ?? false,\n instanceCountWarningThreshold: config.instanceCountWarningThreshold ?? 50,\n detectRapidLifecycles: config.detectRapidLifecycles ?? true,\n rapidLifecycleWindowMs: config.rapidLifecycleWindowMs ?? 1000,\n rapidLifecycleThreshold: config.rapidLifecycleThreshold ?? 5,\n prefix: config.prefix ?? '[BlaC]',\n };\n}\n","import type { BlacPlugin, PluginContext, StateContainer } from '@blac/core';\nimport { SimpleFormatter } from './formatters/SimpleFormatter';\nimport { GroupedFormatter } from './formatters/GroupedFormatter';\nimport { InstanceCountMonitor } from './monitors/InstanceCountMonitor';\nimport { LifecycleMonitor } from './monitors/LifecycleMonitor';\nimport type {\n LoggingPluginConfig,\n ResolvedConfig,\n FilterContext,\n} from './types';\nimport { resolveConfig } from './types';\n\nconst STATE_CHANGE_RATE_LIMIT = 1000; // max state changes per second\n\nexport class LoggingPlugin implements BlacPlugin {\n readonly name = 'LoggingPlugin';\n readonly version = '1.0.0';\n\n private config: ResolvedConfig;\n private context?: PluginContext;\n private simpleFormatter: SimpleFormatter;\n private groupedFormatter: GroupedFormatter;\n private instanceCountMonitor: InstanceCountMonitor;\n private lifecycleMonitor: LifecycleMonitor;\n\n // Rate limiting for state changes\n private stateChangeCount = 0;\n private stateChangeWindowStart = Date.now();\n private stateChangeLoggingDisabled = false;\n\n constructor(config: LoggingPluginConfig = {}) {\n this.config = resolveConfig(config);\n\n const warningHandler = (\n message: string,\n details?: Record<string, unknown>,\n ) => {\n this.logWarning(message, details);\n };\n\n this.simpleFormatter = new SimpleFormatter(this.config);\n this.groupedFormatter = new GroupedFormatter(this.config);\n this.instanceCountMonitor = new InstanceCountMonitor(\n this.config,\n warningHandler,\n );\n this.lifecycleMonitor = new LifecycleMonitor(this.config, warningHandler);\n }\n\n onInstall(context: PluginContext): void {\n this.context = context;\n const stats = context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstall(stats);\n } else {\n this.groupedFormatter.logInstall(stats);\n }\n }\n\n onUninstall(): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logUninstall();\n } else {\n this.groupedFormatter.logUninstall();\n }\n\n this.instanceCountMonitor.reset();\n this.lifecycleMonitor.reset();\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = Date.now();\n this.stateChangeLoggingDisabled = false;\n this.context = undefined;\n }\n\n onInstanceCreated(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.instanceCountMonitor.onInstanceCreated(metadata.className);\n this.lifecycleMonitor.onInstanceCreated(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceCreated(metadata);\n } else {\n this.groupedFormatter.logInstanceCreated(\n metadata,\n context.getState(instance),\n );\n }\n }\n\n onStateChanged<S extends object>(\n instance: StateContainer<S>,\n previousState: S,\n currentState: S,\n callstack: string | undefined,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.lifecycleMonitor.onStateChanged(metadata.id);\n\n if (!this.shouldLogStateChanges()) return;\n\n // Check rate limit\n if (this.stateChangeLoggingDisabled) return;\n\n const now = Date.now();\n if (now - this.stateChangeWindowStart >= 1000) {\n // Reset window\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = now;\n }\n\n this.stateChangeCount++;\n\n if (this.stateChangeCount > STATE_CHANGE_RATE_LIMIT) {\n this.stateChangeLoggingDisabled = true;\n this.logWarning(\n `State change logging disabled: exceeded ${STATE_CHANGE_RATE_LIMIT} changes/second`,\n );\n return;\n }\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n } else {\n this.groupedFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n }\n }\n\n onInstanceDisposed(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n const info = this.lifecycleMonitor.getInstanceInfo(metadata.id);\n const lifespanMs = info ? Date.now() - info.createdAt : 0;\n const stateChangeCount = info?.stateChangeCount ?? 0;\n\n this.instanceCountMonitor.onInstanceDisposed(metadata.className);\n this.lifecycleMonitor.onInstanceDisposed(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceDisposed(metadata, lifespanMs);\n } else {\n this.groupedFormatter.logInstanceDisposed(\n metadata,\n lifespanMs,\n stateChangeCount,\n );\n }\n }\n\n logStats(): void {\n if (!this.context) return;\n const stats = this.context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStats(stats);\n } else {\n this.groupedFormatter.logStats(stats);\n }\n }\n\n private shouldLog(\n instance: StateContainer<any>,\n className: string,\n instanceId: string,\n isIsolated: boolean,\n ): boolean {\n if (this.config.include && !this.config.include.includes(className)) {\n return false;\n }\n\n if (this.config.exclude?.includes(className)) {\n return false;\n }\n\n if (this.config.filter) {\n const ctx: FilterContext = {\n instance,\n className,\n instanceId,\n isIsolated,\n };\n return this.config.filter(ctx);\n }\n\n return true;\n }\n\n private shouldLogLifecycle(): boolean {\n if (!this.config.logLifecycle) return false;\n return this.config.level !== 'minimal';\n }\n\n private shouldLogStateChanges(): boolean {\n if (!this.config.logStateChanges) return false;\n return (\n this.config.level === 'info' ||\n this.config.level === 'debug' ||\n this.config.level === 'verbose'\n );\n }\n\n private logWarning(message: string, details?: Record<string, unknown>): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logWarning(message);\n } else {\n this.groupedFormatter.logWarning(message, details);\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -53,7 +53,6 @@ var SimpleFormatter = class {
|
|
|
53
53
|
return `${(ms / 6e4).toFixed(1)}m`;
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
-
|
|
57
56
|
//#endregion
|
|
58
57
|
//#region src/formatters/GroupedFormatter.ts
|
|
59
58
|
var GroupedFormatter = class {
|
|
@@ -127,7 +126,6 @@ var GroupedFormatter = class {
|
|
|
127
126
|
return `${(ms / 6e4).toFixed(1)}m`;
|
|
128
127
|
}
|
|
129
128
|
};
|
|
130
|
-
|
|
131
129
|
//#endregion
|
|
132
130
|
//#region src/monitors/InstanceCountMonitor.ts
|
|
133
131
|
var InstanceCountMonitor = class {
|
|
@@ -162,7 +160,6 @@ var InstanceCountMonitor = class {
|
|
|
162
160
|
this.warnedClasses.clear();
|
|
163
161
|
}
|
|
164
162
|
};
|
|
165
|
-
|
|
166
163
|
//#endregion
|
|
167
164
|
//#region src/monitors/LifecycleMonitor.ts
|
|
168
165
|
var LifecycleMonitor = class {
|
|
@@ -230,7 +227,6 @@ var LifecycleMonitor = class {
|
|
|
230
227
|
this.warnedClasses.clear();
|
|
231
228
|
}
|
|
232
229
|
};
|
|
233
|
-
|
|
234
230
|
//#endregion
|
|
235
231
|
//#region src/types.ts
|
|
236
232
|
function resolveConfig(config = {}) {
|
|
@@ -251,7 +247,6 @@ function resolveConfig(config = {}) {
|
|
|
251
247
|
prefix: config.prefix ?? "[BlaC]"
|
|
252
248
|
};
|
|
253
249
|
}
|
|
254
|
-
|
|
255
250
|
//#endregion
|
|
256
251
|
//#region src/LoggingPlugin.ts
|
|
257
252
|
const STATE_CHANGE_RATE_LIMIT = 1e3;
|
|
@@ -361,7 +356,7 @@ var LoggingPlugin = class {
|
|
|
361
356
|
else this.groupedFormatter.logWarning(message, details);
|
|
362
357
|
}
|
|
363
358
|
};
|
|
364
|
-
|
|
365
359
|
//#endregion
|
|
366
360
|
export { LoggingPlugin };
|
|
361
|
+
|
|
367
362
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/formatters/SimpleFormatter.ts","../src/formatters/GroupedFormatter.ts","../src/monitors/InstanceCountMonitor.ts","../src/monitors/LifecycleMonitor.ts","../src/types.ts","../src/LoggingPlugin.ts"],"sourcesContent":["import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class SimpleFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.logger.log(\n `${this.prefix} Plugin installed (${stats.registeredTypes} types, ${stats.totalInstances} instances)`,\n );\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const isolated = metadata.isIsolated ? ' (isolated)' : '';\n this.logger.log(`${this.prefix} Created ${instanceId}${isolated}`);\n }\n\n logInstanceDisposed(metadata: InstanceMetadata, lifespanMs: number): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const lifespan = this.formatDuration(lifespanMs);\n this.logger.log(\n `${this.prefix} Disposed ${instanceId} (lived ${lifespan})`,\n );\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n _callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const prev = this.formatState(previousState);\n const curr = this.formatState(currentState);\n this.logger.log(`${this.prefix} ${instanceId} state: ${prev} → ${curr}`);\n\n if (includeCallstack && _callstack) {\n this.logger.log(`${this.prefix} Callstack: ${_callstack}`);\n }\n }\n\n logWarning(message: string): void {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.logger.log(\n `${this.prefix} Stats: ${stats.totalInstances} instances across ${stats.registeredTypes} types`,\n );\n }\n\n private formatState(state: unknown): string {\n if (state === null) return 'null';\n if (state === undefined) return 'undefined';\n if (typeof state === 'object') {\n try {\n const str = JSON.stringify(state);\n return str.length > 50 ? str.slice(0, 50) + '...' : str;\n } catch {\n return '[Object]';\n }\n }\n return String(state);\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class GroupedFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n private group(label: string, collapsed = true): void {\n if (collapsed && this.logger.groupCollapsed) {\n this.logger.groupCollapsed(label);\n } else if (this.logger.group) {\n this.logger.group(label);\n } else {\n this.logger.log(label);\n }\n }\n\n private groupEnd(): void {\n if (this.logger.groupEnd) {\n this.logger.groupEnd();\n }\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.group(`${this.prefix} Plugin installed`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.groupEnd();\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata, initialState: unknown): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Created ${instanceId}`);\n this.logger.log('Class:', metadata.className);\n this.logger.log('Instance ID:', metadata.id);\n this.logger.log('Isolated:', metadata.isIsolated);\n this.logger.log('Initial state:', initialState);\n if (metadata.callstack) {\n this.logger.log('Callstack:', metadata.callstack);\n }\n this.groupEnd();\n }\n\n logInstanceDisposed(\n metadata: InstanceMetadata,\n lifespanMs: number,\n stateChangeCount: number,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Disposed ${instanceId}`);\n this.logger.log('Lifespan:', this.formatDuration(lifespanMs));\n this.logger.log('State changes:', stateChangeCount);\n this.logger.log('Final state:', metadata.state);\n this.groupEnd();\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} ${instanceId} state changed`);\n this.logger.log('Previous:', previousState);\n this.logger.log('Current:', currentState);\n if (includeCallstack && callstack) {\n this.logger.log('Callstack:', callstack);\n }\n this.groupEnd();\n }\n\n logWarning(message: string, details?: Record<string, unknown>): void {\n if (details) {\n this.group(`${this.prefix} ⚠️ ${message}`, false);\n for (const [key, value] of Object.entries(details)) {\n this.logger.log(`${key}:`, value);\n }\n this.groupEnd();\n } else {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.group(`${this.prefix} Stats`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.logger.log('Breakdown:', stats.typeBreakdown);\n this.groupEnd();\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { ResolvedConfig } from '../types';\n\nexport class InstanceCountMonitor {\n private instanceCounts = new Map<string, number>();\n private warnedClasses = new Set<string>();\n private threshold: number;\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.threshold = config.instanceCountWarningThreshold;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string): void {\n const count = (this.instanceCounts.get(className) ?? 0) + 1;\n this.instanceCounts.set(className, count);\n\n if (count >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `High instance count: ${className} has ${count} instances`,\n {\n className,\n count,\n threshold: this.threshold,\n },\n );\n }\n }\n\n onInstanceDisposed(className: string): void {\n const count = this.instanceCounts.get(className) ?? 0;\n if (count > 0) {\n this.instanceCounts.set(className, count - 1);\n }\n\n if (count - 1 < this.threshold) {\n this.warnedClasses.delete(className);\n }\n }\n\n getStats(): Map<string, number> {\n return new Map(this.instanceCounts);\n }\n\n reset(): void {\n this.instanceCounts.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { ResolvedConfig } from '../types';\n\ninterface LifecycleEvent {\n timestamp: number;\n type: 'created' | 'disposed';\n}\n\ninterface InstanceInfo {\n createdAt: number;\n stateChangeCount: number;\n}\n\nexport class LifecycleMonitor {\n private lifecycleHistory = new Map<string, LifecycleEvent[]>();\n private instanceInfo = new Map<string, InstanceInfo>();\n private windowMs: number;\n private threshold: number;\n private enabled: boolean;\n private warnedClasses = new Set<string>();\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.windowMs = config.rapidLifecycleWindowMs;\n this.threshold = config.rapidLifecycleThreshold;\n this.enabled = config.detectRapidLifecycles;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.set(instanceId, {\n createdAt: Date.now(),\n stateChangeCount: 0,\n });\n\n this.recordEvent(className, 'created');\n this.checkRapidLifecycle(className);\n }\n\n onInstanceDisposed(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.delete(instanceId);\n this.recordEvent(className, 'disposed');\n this.checkRapidLifecycle(className);\n }\n\n onStateChanged(instanceId: string): void {\n const info = this.instanceInfo.get(instanceId);\n if (info) {\n info.stateChangeCount++;\n }\n }\n\n getInstanceInfo(instanceId: string): InstanceInfo | undefined {\n return this.instanceInfo.get(instanceId);\n }\n\n private recordEvent(className: string, type: 'created' | 'disposed'): void {\n const now = Date.now();\n const events = this.lifecycleHistory.get(className) ?? [];\n\n events.push({ timestamp: now, type });\n\n const cutoff = now - this.windowMs;\n const filtered = events.filter((e) => e.timestamp > cutoff);\n this.lifecycleHistory.set(className, filtered);\n }\n\n private checkRapidLifecycle(className: string): void {\n const events = this.lifecycleHistory.get(className) ?? [];\n const cycleCount = Math.min(\n events.filter((e) => e.type === 'created').length,\n events.filter((e) => e.type === 'disposed').length,\n );\n\n if (cycleCount >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `Rapid lifecycle: ${className} created/disposed ${cycleCount} times in ${this.windowMs}ms`,\n {\n className,\n cycleCount,\n windowMs: this.windowMs,\n threshold: this.threshold,\n },\n );\n\n setTimeout(() => {\n this.warnedClasses.delete(className);\n }, this.windowMs);\n }\n }\n\n reset(): void {\n this.lifecycleHistory.clear();\n this.instanceInfo.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { StateContainer } from '@blac/core';\n\nexport type LogLevel = 'minimal' | 'info' | 'debug' | 'verbose';\n\nexport type LogFormat = 'simple' | 'grouped';\n\nexport interface Logger {\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n group?(label: string): void;\n groupEnd?(): void;\n groupCollapsed?(label: string): void;\n}\n\nexport interface FilterContext {\n instance: StateContainer<any>;\n className: string;\n instanceId: string;\n isIsolated: boolean;\n}\n\nexport type FilterFn = (ctx: FilterContext) => boolean;\n\nexport interface LoggingPluginConfig {\n /** Log verbosity level (default: 'info') */\n level?: LogLevel;\n\n /** Output format (default: 'grouped') */\n format?: LogFormat;\n\n /** Custom logger implementation (default: console) */\n logger?: Logger;\n\n /** Filter which instances to log */\n filter?: FilterFn;\n\n /** Include class names to log (whitelist) */\n include?: string[];\n\n /** Exclude class names from logging (blacklist) */\n exclude?: string[];\n\n /** Log instance creation/disposal (default: true) */\n logLifecycle?: boolean;\n\n /** Log state changes (default: true) */\n logStateChanges?: boolean;\n\n /** Include callstack in state change logs (default: false) */\n includeCallstack?: boolean;\n\n /** Warn when instance count exceeds threshold (default: 50) */\n instanceCountWarningThreshold?: number;\n\n /** Warn on rapid init/dispose cycles (default: true) */\n detectRapidLifecycles?: boolean;\n\n /** Time window for rapid lifecycle detection in ms (default: 1000) */\n rapidLifecycleWindowMs?: number;\n\n /** Number of cycles in window to trigger warning (default: 5) */\n rapidLifecycleThreshold?: number;\n\n /** Log prefix (default: '[BlaC]') */\n prefix?: string;\n}\n\nexport interface ResolvedConfig {\n level: LogLevel;\n format: LogFormat;\n logger: Logger;\n filter: FilterFn | undefined;\n include: string[] | undefined;\n exclude: string[] | undefined;\n logLifecycle: boolean;\n logStateChanges: boolean;\n includeCallstack: boolean;\n instanceCountWarningThreshold: number;\n detectRapidLifecycles: boolean;\n rapidLifecycleWindowMs: number;\n rapidLifecycleThreshold: number;\n prefix: string;\n}\n\nexport function resolveConfig(\n config: LoggingPluginConfig = {},\n): ResolvedConfig {\n return {\n level: config.level ?? 'info',\n format: config.format ?? 'grouped',\n logger: config.logger ?? console,\n filter: config.filter,\n include: config.include,\n exclude: config.exclude,\n logLifecycle: config.logLifecycle ?? true,\n logStateChanges: config.logStateChanges ?? true,\n includeCallstack: config.includeCallstack ?? false,\n instanceCountWarningThreshold: config.instanceCountWarningThreshold ?? 50,\n detectRapidLifecycles: config.detectRapidLifecycles ?? true,\n rapidLifecycleWindowMs: config.rapidLifecycleWindowMs ?? 1000,\n rapidLifecycleThreshold: config.rapidLifecycleThreshold ?? 5,\n prefix: config.prefix ?? '[BlaC]',\n };\n}\n","import type { BlacPlugin, PluginContext, StateContainer } from '@blac/core';\nimport { SimpleFormatter } from './formatters/SimpleFormatter';\nimport { GroupedFormatter } from './formatters/GroupedFormatter';\nimport { InstanceCountMonitor } from './monitors/InstanceCountMonitor';\nimport { LifecycleMonitor } from './monitors/LifecycleMonitor';\nimport type {\n LoggingPluginConfig,\n ResolvedConfig,\n FilterContext,\n} from './types';\nimport { resolveConfig } from './types';\n\nconst STATE_CHANGE_RATE_LIMIT = 1000; // max state changes per second\n\nexport class LoggingPlugin implements BlacPlugin {\n readonly name = 'LoggingPlugin';\n readonly version = '1.0.0';\n\n private config: ResolvedConfig;\n private context?: PluginContext;\n private simpleFormatter: SimpleFormatter;\n private groupedFormatter: GroupedFormatter;\n private instanceCountMonitor: InstanceCountMonitor;\n private lifecycleMonitor: LifecycleMonitor;\n\n // Rate limiting for state changes\n private stateChangeCount = 0;\n private stateChangeWindowStart = Date.now();\n private stateChangeLoggingDisabled = false;\n\n constructor(config: LoggingPluginConfig = {}) {\n this.config = resolveConfig(config);\n\n const warningHandler = (\n message: string,\n details?: Record<string, unknown>,\n ) => {\n this.logWarning(message, details);\n };\n\n this.simpleFormatter = new SimpleFormatter(this.config);\n this.groupedFormatter = new GroupedFormatter(this.config);\n this.instanceCountMonitor = new InstanceCountMonitor(\n this.config,\n warningHandler,\n );\n this.lifecycleMonitor = new LifecycleMonitor(this.config, warningHandler);\n }\n\n onInstall(context: PluginContext): void {\n this.context = context;\n const stats = context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstall(stats);\n } else {\n this.groupedFormatter.logInstall(stats);\n }\n }\n\n onUninstall(): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logUninstall();\n } else {\n this.groupedFormatter.logUninstall();\n }\n\n this.instanceCountMonitor.reset();\n this.lifecycleMonitor.reset();\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = Date.now();\n this.stateChangeLoggingDisabled = false;\n this.context = undefined;\n }\n\n onInstanceCreated(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.instanceCountMonitor.onInstanceCreated(metadata.className);\n this.lifecycleMonitor.onInstanceCreated(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceCreated(metadata);\n } else {\n this.groupedFormatter.logInstanceCreated(\n metadata,\n context.getState(instance),\n );\n }\n }\n\n onStateChanged<S extends object>(\n instance: StateContainer<S>,\n previousState: S,\n currentState: S,\n callstack: string | undefined,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.lifecycleMonitor.onStateChanged(metadata.id);\n\n if (!this.shouldLogStateChanges()) return;\n\n // Check rate limit\n if (this.stateChangeLoggingDisabled) return;\n\n const now = Date.now();\n if (now - this.stateChangeWindowStart >= 1000) {\n // Reset window\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = now;\n }\n\n this.stateChangeCount++;\n\n if (this.stateChangeCount > STATE_CHANGE_RATE_LIMIT) {\n this.stateChangeLoggingDisabled = true;\n this.logWarning(\n `State change logging disabled: exceeded ${STATE_CHANGE_RATE_LIMIT} changes/second`,\n );\n return;\n }\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n } else {\n this.groupedFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n }\n }\n\n onInstanceDisposed(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n const info = this.lifecycleMonitor.getInstanceInfo(metadata.id);\n const lifespanMs = info ? Date.now() - info.createdAt : 0;\n const stateChangeCount = info?.stateChangeCount ?? 0;\n\n this.instanceCountMonitor.onInstanceDisposed(metadata.className);\n this.lifecycleMonitor.onInstanceDisposed(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceDisposed(metadata, lifespanMs);\n } else {\n this.groupedFormatter.logInstanceDisposed(\n metadata,\n lifespanMs,\n stateChangeCount,\n );\n }\n }\n\n logStats(): void {\n if (!this.context) return;\n const stats = this.context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStats(stats);\n } else {\n this.groupedFormatter.logStats(stats);\n }\n }\n\n private shouldLog(\n instance: StateContainer<any>,\n className: string,\n instanceId: string,\n isIsolated: boolean,\n ): boolean {\n if (this.config.include && !this.config.include.includes(className)) {\n return false;\n }\n\n if (this.config.exclude?.includes(className)) {\n return false;\n }\n\n if (this.config.filter) {\n const ctx: FilterContext = {\n instance,\n className,\n instanceId,\n isIsolated,\n };\n return this.config.filter(ctx);\n }\n\n return true;\n }\n\n private shouldLogLifecycle(): boolean {\n if (!this.config.logLifecycle) return false;\n return this.config.level !== 'minimal';\n }\n\n private shouldLogStateChanges(): boolean {\n if (!this.config.logStateChanges) return false;\n return (\n this.config.level === 'info' ||\n this.config.level === 'debug' ||\n this.config.level === 'verbose'\n );\n }\n\n private logWarning(message: string, details?: Record<string, unknown>): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logWarning(message);\n } else {\n this.groupedFormatter.logWarning(message, details);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/formatters/SimpleFormatter.ts","../src/formatters/GroupedFormatter.ts","../src/monitors/InstanceCountMonitor.ts","../src/monitors/LifecycleMonitor.ts","../src/types.ts","../src/LoggingPlugin.ts"],"sourcesContent":["import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class SimpleFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.logger.log(\n `${this.prefix} Plugin installed (${stats.registeredTypes} types, ${stats.totalInstances} instances)`,\n );\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const isolated = metadata.isIsolated ? ' (isolated)' : '';\n this.logger.log(`${this.prefix} Created ${instanceId}${isolated}`);\n }\n\n logInstanceDisposed(metadata: InstanceMetadata, lifespanMs: number): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const lifespan = this.formatDuration(lifespanMs);\n this.logger.log(\n `${this.prefix} Disposed ${instanceId} (lived ${lifespan})`,\n );\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n _callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n const prev = this.formatState(previousState);\n const curr = this.formatState(currentState);\n this.logger.log(`${this.prefix} ${instanceId} state: ${prev} → ${curr}`);\n\n if (includeCallstack && _callstack) {\n this.logger.log(`${this.prefix} Callstack: ${_callstack}`);\n }\n }\n\n logWarning(message: string): void {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.logger.log(\n `${this.prefix} Stats: ${stats.totalInstances} instances across ${stats.registeredTypes} types`,\n );\n }\n\n private formatState(state: unknown): string {\n if (state === null) return 'null';\n if (state === undefined) return 'undefined';\n if (typeof state === 'object') {\n try {\n const str = JSON.stringify(state);\n return str.length > 50 ? str.slice(0, 50) + '...' : str;\n } catch {\n return '[Object]';\n }\n }\n return String(state);\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { InstanceMetadata } from '@blac/core';\nimport type { Logger, ResolvedConfig } from '../types';\n\nexport class GroupedFormatter {\n private logger: Logger;\n private prefix: string;\n\n constructor(config: ResolvedConfig) {\n this.logger = config.logger;\n this.prefix = config.prefix;\n }\n\n private formatInstanceId(className: string, id: string): string {\n const shortId = id.length > 8 ? id.slice(0, 8) : id;\n return `${className}#${shortId}`;\n }\n\n private group(label: string, collapsed = true): void {\n if (collapsed && this.logger.groupCollapsed) {\n this.logger.groupCollapsed(label);\n } else if (this.logger.group) {\n this.logger.group(label);\n } else {\n this.logger.log(label);\n }\n }\n\n private groupEnd(): void {\n if (this.logger.groupEnd) {\n this.logger.groupEnd();\n }\n }\n\n logInstall(stats: { registeredTypes: number; totalInstances: number }): void {\n this.group(`${this.prefix} Plugin installed`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.groupEnd();\n }\n\n logUninstall(): void {\n this.logger.log(`${this.prefix} Plugin uninstalled`);\n }\n\n logInstanceCreated(metadata: InstanceMetadata, initialState: unknown): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Created ${instanceId}`);\n this.logger.log('Class:', metadata.className);\n this.logger.log('Instance ID:', metadata.id);\n this.logger.log('Isolated:', metadata.isIsolated);\n this.logger.log('Initial state:', initialState);\n if (metadata.callstack) {\n this.logger.log('Callstack:', metadata.callstack);\n }\n this.groupEnd();\n }\n\n logInstanceDisposed(\n metadata: InstanceMetadata,\n lifespanMs: number,\n stateChangeCount: number,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} Disposed ${instanceId}`);\n this.logger.log('Lifespan:', this.formatDuration(lifespanMs));\n this.logger.log('State changes:', stateChangeCount);\n this.logger.log('Final state:', metadata.state);\n this.groupEnd();\n }\n\n logStateChanged(\n metadata: InstanceMetadata,\n previousState: unknown,\n currentState: unknown,\n callstack: string | undefined,\n includeCallstack: boolean,\n ): void {\n const instanceId = this.formatInstanceId(metadata.className, metadata.id);\n this.group(`${this.prefix} ${instanceId} state changed`);\n this.logger.log('Previous:', previousState);\n this.logger.log('Current:', currentState);\n if (includeCallstack && callstack) {\n this.logger.log('Callstack:', callstack);\n }\n this.groupEnd();\n }\n\n logWarning(message: string, details?: Record<string, unknown>): void {\n if (details) {\n this.group(`${this.prefix} ⚠️ ${message}`, false);\n for (const [key, value] of Object.entries(details)) {\n this.logger.log(`${key}:`, value);\n }\n this.groupEnd();\n } else {\n this.logger.warn(`${this.prefix} ⚠️ ${message}`);\n }\n }\n\n logStats(stats: {\n registeredTypes: number;\n totalInstances: number;\n typeBreakdown: Record<string, number>;\n }): void {\n this.group(`${this.prefix} Stats`);\n this.logger.log('Registered types:', stats.registeredTypes);\n this.logger.log('Total instances:', stats.totalInstances);\n this.logger.log('Breakdown:', stats.typeBreakdown);\n this.groupEnd();\n }\n\n private formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n }\n}\n","import type { ResolvedConfig } from '../types';\n\nexport class InstanceCountMonitor {\n private instanceCounts = new Map<string, number>();\n private warnedClasses = new Set<string>();\n private threshold: number;\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.threshold = config.instanceCountWarningThreshold;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string): void {\n const count = (this.instanceCounts.get(className) ?? 0) + 1;\n this.instanceCounts.set(className, count);\n\n if (count >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `High instance count: ${className} has ${count} instances`,\n {\n className,\n count,\n threshold: this.threshold,\n },\n );\n }\n }\n\n onInstanceDisposed(className: string): void {\n const count = this.instanceCounts.get(className) ?? 0;\n if (count > 0) {\n this.instanceCounts.set(className, count - 1);\n }\n\n if (count - 1 < this.threshold) {\n this.warnedClasses.delete(className);\n }\n }\n\n getStats(): Map<string, number> {\n return new Map(this.instanceCounts);\n }\n\n reset(): void {\n this.instanceCounts.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { ResolvedConfig } from '../types';\n\ninterface LifecycleEvent {\n timestamp: number;\n type: 'created' | 'disposed';\n}\n\ninterface InstanceInfo {\n createdAt: number;\n stateChangeCount: number;\n}\n\nexport class LifecycleMonitor {\n private lifecycleHistory = new Map<string, LifecycleEvent[]>();\n private instanceInfo = new Map<string, InstanceInfo>();\n private windowMs: number;\n private threshold: number;\n private enabled: boolean;\n private warnedClasses = new Set<string>();\n private onWarning: (\n message: string,\n details?: Record<string, unknown>,\n ) => void;\n\n constructor(\n config: ResolvedConfig,\n onWarning: (message: string, details?: Record<string, unknown>) => void,\n ) {\n this.windowMs = config.rapidLifecycleWindowMs;\n this.threshold = config.rapidLifecycleThreshold;\n this.enabled = config.detectRapidLifecycles;\n this.onWarning = onWarning;\n }\n\n onInstanceCreated(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.set(instanceId, {\n createdAt: Date.now(),\n stateChangeCount: 0,\n });\n\n this.recordEvent(className, 'created');\n this.checkRapidLifecycle(className);\n }\n\n onInstanceDisposed(className: string, instanceId: string): void {\n if (!this.enabled) return;\n\n this.instanceInfo.delete(instanceId);\n this.recordEvent(className, 'disposed');\n this.checkRapidLifecycle(className);\n }\n\n onStateChanged(instanceId: string): void {\n const info = this.instanceInfo.get(instanceId);\n if (info) {\n info.stateChangeCount++;\n }\n }\n\n getInstanceInfo(instanceId: string): InstanceInfo | undefined {\n return this.instanceInfo.get(instanceId);\n }\n\n private recordEvent(className: string, type: 'created' | 'disposed'): void {\n const now = Date.now();\n const events = this.lifecycleHistory.get(className) ?? [];\n\n events.push({ timestamp: now, type });\n\n const cutoff = now - this.windowMs;\n const filtered = events.filter((e) => e.timestamp > cutoff);\n this.lifecycleHistory.set(className, filtered);\n }\n\n private checkRapidLifecycle(className: string): void {\n const events = this.lifecycleHistory.get(className) ?? [];\n const cycleCount = Math.min(\n events.filter((e) => e.type === 'created').length,\n events.filter((e) => e.type === 'disposed').length,\n );\n\n if (cycleCount >= this.threshold && !this.warnedClasses.has(className)) {\n this.warnedClasses.add(className);\n this.onWarning(\n `Rapid lifecycle: ${className} created/disposed ${cycleCount} times in ${this.windowMs}ms`,\n {\n className,\n cycleCount,\n windowMs: this.windowMs,\n threshold: this.threshold,\n },\n );\n\n setTimeout(() => {\n this.warnedClasses.delete(className);\n }, this.windowMs);\n }\n }\n\n reset(): void {\n this.lifecycleHistory.clear();\n this.instanceInfo.clear();\n this.warnedClasses.clear();\n }\n}\n","import type { StateContainer } from '@blac/core';\n\nexport type LogLevel = 'minimal' | 'info' | 'debug' | 'verbose';\n\nexport type LogFormat = 'simple' | 'grouped';\n\nexport interface Logger {\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n group?(label: string): void;\n groupEnd?(): void;\n groupCollapsed?(label: string): void;\n}\n\nexport interface FilterContext {\n instance: StateContainer<any>;\n className: string;\n instanceId: string;\n isIsolated: boolean;\n}\n\nexport type FilterFn = (ctx: FilterContext) => boolean;\n\nexport interface LoggingPluginConfig {\n /** Log verbosity level (default: 'info') */\n level?: LogLevel;\n\n /** Output format (default: 'grouped') */\n format?: LogFormat;\n\n /** Custom logger implementation (default: console) */\n logger?: Logger;\n\n /** Filter which instances to log */\n filter?: FilterFn;\n\n /** Include class names to log (whitelist) */\n include?: string[];\n\n /** Exclude class names from logging (blacklist) */\n exclude?: string[];\n\n /** Log instance creation/disposal (default: true) */\n logLifecycle?: boolean;\n\n /** Log state changes (default: true) */\n logStateChanges?: boolean;\n\n /** Include callstack in state change logs (default: false) */\n includeCallstack?: boolean;\n\n /** Warn when instance count exceeds threshold (default: 50) */\n instanceCountWarningThreshold?: number;\n\n /** Warn on rapid init/dispose cycles (default: true) */\n detectRapidLifecycles?: boolean;\n\n /** Time window for rapid lifecycle detection in ms (default: 1000) */\n rapidLifecycleWindowMs?: number;\n\n /** Number of cycles in window to trigger warning (default: 5) */\n rapidLifecycleThreshold?: number;\n\n /** Log prefix (default: '[BlaC]') */\n prefix?: string;\n}\n\nexport interface ResolvedConfig {\n level: LogLevel;\n format: LogFormat;\n logger: Logger;\n filter: FilterFn | undefined;\n include: string[] | undefined;\n exclude: string[] | undefined;\n logLifecycle: boolean;\n logStateChanges: boolean;\n includeCallstack: boolean;\n instanceCountWarningThreshold: number;\n detectRapidLifecycles: boolean;\n rapidLifecycleWindowMs: number;\n rapidLifecycleThreshold: number;\n prefix: string;\n}\n\nexport function resolveConfig(\n config: LoggingPluginConfig = {},\n): ResolvedConfig {\n return {\n level: config.level ?? 'info',\n format: config.format ?? 'grouped',\n logger: config.logger ?? console,\n filter: config.filter,\n include: config.include,\n exclude: config.exclude,\n logLifecycle: config.logLifecycle ?? true,\n logStateChanges: config.logStateChanges ?? true,\n includeCallstack: config.includeCallstack ?? false,\n instanceCountWarningThreshold: config.instanceCountWarningThreshold ?? 50,\n detectRapidLifecycles: config.detectRapidLifecycles ?? true,\n rapidLifecycleWindowMs: config.rapidLifecycleWindowMs ?? 1000,\n rapidLifecycleThreshold: config.rapidLifecycleThreshold ?? 5,\n prefix: config.prefix ?? '[BlaC]',\n };\n}\n","import type { BlacPlugin, PluginContext, StateContainer } from '@blac/core';\nimport { SimpleFormatter } from './formatters/SimpleFormatter';\nimport { GroupedFormatter } from './formatters/GroupedFormatter';\nimport { InstanceCountMonitor } from './monitors/InstanceCountMonitor';\nimport { LifecycleMonitor } from './monitors/LifecycleMonitor';\nimport type {\n LoggingPluginConfig,\n ResolvedConfig,\n FilterContext,\n} from './types';\nimport { resolveConfig } from './types';\n\nconst STATE_CHANGE_RATE_LIMIT = 1000; // max state changes per second\n\nexport class LoggingPlugin implements BlacPlugin {\n readonly name = 'LoggingPlugin';\n readonly version = '1.0.0';\n\n private config: ResolvedConfig;\n private context?: PluginContext;\n private simpleFormatter: SimpleFormatter;\n private groupedFormatter: GroupedFormatter;\n private instanceCountMonitor: InstanceCountMonitor;\n private lifecycleMonitor: LifecycleMonitor;\n\n // Rate limiting for state changes\n private stateChangeCount = 0;\n private stateChangeWindowStart = Date.now();\n private stateChangeLoggingDisabled = false;\n\n constructor(config: LoggingPluginConfig = {}) {\n this.config = resolveConfig(config);\n\n const warningHandler = (\n message: string,\n details?: Record<string, unknown>,\n ) => {\n this.logWarning(message, details);\n };\n\n this.simpleFormatter = new SimpleFormatter(this.config);\n this.groupedFormatter = new GroupedFormatter(this.config);\n this.instanceCountMonitor = new InstanceCountMonitor(\n this.config,\n warningHandler,\n );\n this.lifecycleMonitor = new LifecycleMonitor(this.config, warningHandler);\n }\n\n onInstall(context: PluginContext): void {\n this.context = context;\n const stats = context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstall(stats);\n } else {\n this.groupedFormatter.logInstall(stats);\n }\n }\n\n onUninstall(): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logUninstall();\n } else {\n this.groupedFormatter.logUninstall();\n }\n\n this.instanceCountMonitor.reset();\n this.lifecycleMonitor.reset();\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = Date.now();\n this.stateChangeLoggingDisabled = false;\n this.context = undefined;\n }\n\n onInstanceCreated(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.instanceCountMonitor.onInstanceCreated(metadata.className);\n this.lifecycleMonitor.onInstanceCreated(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceCreated(metadata);\n } else {\n this.groupedFormatter.logInstanceCreated(\n metadata,\n context.getState(instance),\n );\n }\n }\n\n onStateChanged<S extends object>(\n instance: StateContainer<S>,\n previousState: S,\n currentState: S,\n callstack: string | undefined,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n this.lifecycleMonitor.onStateChanged(metadata.id);\n\n if (!this.shouldLogStateChanges()) return;\n\n // Check rate limit\n if (this.stateChangeLoggingDisabled) return;\n\n const now = Date.now();\n if (now - this.stateChangeWindowStart >= 1000) {\n // Reset window\n this.stateChangeCount = 0;\n this.stateChangeWindowStart = now;\n }\n\n this.stateChangeCount++;\n\n if (this.stateChangeCount > STATE_CHANGE_RATE_LIMIT) {\n this.stateChangeLoggingDisabled = true;\n this.logWarning(\n `State change logging disabled: exceeded ${STATE_CHANGE_RATE_LIMIT} changes/second`,\n );\n return;\n }\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n } else {\n this.groupedFormatter.logStateChanged(\n metadata,\n previousState,\n currentState,\n callstack,\n this.config.includeCallstack,\n );\n }\n }\n\n onInstanceDisposed(\n instance: StateContainer<any>,\n context: PluginContext,\n ): void {\n const metadata = context.getInstanceMetadata(instance);\n\n if (\n !this.shouldLog(\n instance,\n metadata.className,\n metadata.id,\n metadata.isIsolated,\n )\n ) {\n return;\n }\n\n const info = this.lifecycleMonitor.getInstanceInfo(metadata.id);\n const lifespanMs = info ? Date.now() - info.createdAt : 0;\n const stateChangeCount = info?.stateChangeCount ?? 0;\n\n this.instanceCountMonitor.onInstanceDisposed(metadata.className);\n this.lifecycleMonitor.onInstanceDisposed(metadata.className, metadata.id);\n\n if (!this.shouldLogLifecycle()) return;\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logInstanceDisposed(metadata, lifespanMs);\n } else {\n this.groupedFormatter.logInstanceDisposed(\n metadata,\n lifespanMs,\n stateChangeCount,\n );\n }\n }\n\n logStats(): void {\n if (!this.context) return;\n const stats = this.context.getStats();\n\n if (this.config.format === 'simple') {\n this.simpleFormatter.logStats(stats);\n } else {\n this.groupedFormatter.logStats(stats);\n }\n }\n\n private shouldLog(\n instance: StateContainer<any>,\n className: string,\n instanceId: string,\n isIsolated: boolean,\n ): boolean {\n if (this.config.include && !this.config.include.includes(className)) {\n return false;\n }\n\n if (this.config.exclude?.includes(className)) {\n return false;\n }\n\n if (this.config.filter) {\n const ctx: FilterContext = {\n instance,\n className,\n instanceId,\n isIsolated,\n };\n return this.config.filter(ctx);\n }\n\n return true;\n }\n\n private shouldLogLifecycle(): boolean {\n if (!this.config.logLifecycle) return false;\n return this.config.level !== 'minimal';\n }\n\n private shouldLogStateChanges(): boolean {\n if (!this.config.logStateChanges) return false;\n return (\n this.config.level === 'info' ||\n this.config.level === 'debug' ||\n this.config.level === 'verbose'\n );\n }\n\n private logWarning(message: string, details?: Record<string, unknown>): void {\n if (this.config.format === 'simple') {\n this.simpleFormatter.logWarning(message);\n } else {\n this.groupedFormatter.logWarning(message, details);\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blac/logging-plugin",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Brendan Mullins <jsnanigans@gmail.com>",
|
|
6
6
|
"description": "Logging and debugging plugin for BlaC state management",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/jsnanigans/blac/issues"
|
|
15
15
|
},
|
|
16
|
+
"type": "module",
|
|
16
17
|
"main": "./dist/index.cjs",
|
|
17
18
|
"module": "./dist/index.js",
|
|
18
19
|
"types": "./dist/index.d.ts",
|
|
@@ -33,6 +34,9 @@
|
|
|
33
34
|
"README.md",
|
|
34
35
|
"LICENSE"
|
|
35
36
|
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
36
40
|
"sideEffects": false,
|
|
37
41
|
"keywords": [
|
|
38
42
|
"blac",
|
|
@@ -41,15 +45,16 @@
|
|
|
41
45
|
"state-management",
|
|
42
46
|
"devtools"
|
|
43
47
|
],
|
|
44
|
-
"
|
|
45
|
-
"@blac/core": "2.0.
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@blac/core": "^2.0.6"
|
|
46
50
|
},
|
|
47
51
|
"devDependencies": {
|
|
48
52
|
"prettier": "^3.6.2",
|
|
49
53
|
"typescript": "^5.9.2",
|
|
50
54
|
"vitest": "3.2.4",
|
|
51
55
|
"publint": "^0.3.12",
|
|
52
|
-
"tsdown": "^0.15.7"
|
|
56
|
+
"tsdown": "^0.15.7",
|
|
57
|
+
"@blac/core": "2.0.6"
|
|
53
58
|
},
|
|
54
59
|
"scripts": {
|
|
55
60
|
"dev": "tsdown --watch",
|
|
@@ -58,7 +63,8 @@
|
|
|
58
63
|
"format": "prettier --write \".\"",
|
|
59
64
|
"lint": "eslint src --ext .ts,.tsx",
|
|
60
65
|
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
61
|
-
"
|
|
66
|
+
"test": "node ../../scripts/run-workspace-bin.mjs vitest run --passWithNoTests",
|
|
67
|
+
"verify": "node ../../scripts/run-workspace-bin.mjs publint",
|
|
62
68
|
"typecheck": "tsc --noEmit",
|
|
63
69
|
"deploy": "pnpm publish --access public"
|
|
64
70
|
}
|