@morojs/moro 1.6.0 → 1.6.1
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/README.md +256 -74
- package/dist/core/auth/morojs-adapter.js +20 -20
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/config/file-loader.d.ts +6 -1
- package/dist/core/config/file-loader.js +249 -19
- package/dist/core/config/file-loader.js.map +1 -1
- package/dist/core/config/index.d.ts +12 -41
- package/dist/core/config/index.js +54 -65
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/loader.d.ts +7 -0
- package/dist/core/config/loader.js +269 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.d.ts +2 -2
- package/dist/core/config/schema.js +44 -52
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.d.ts +3 -10
- package/dist/core/config/utils.js +58 -31
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/config/validation.d.ts +17 -0
- package/dist/core/config/validation.js +131 -0
- package/dist/core/config/validation.js.map +1 -0
- package/dist/core/database/adapters/drizzle.d.ts +1 -1
- package/dist/core/database/adapters/drizzle.js +11 -18
- package/dist/core/database/adapters/drizzle.js.map +1 -1
- package/dist/core/database/adapters/index.d.ts +7 -7
- package/dist/core/database/adapters/index.js +29 -19
- package/dist/core/database/adapters/index.js.map +1 -1
- package/dist/core/database/adapters/mongodb.d.ts +1 -13
- package/dist/core/database/adapters/mongodb.js +10 -46
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +1 -14
- package/dist/core/database/adapters/mysql.js +9 -19
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.d.ts +2 -12
- package/dist/core/database/adapters/postgresql.js +9 -19
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.d.ts +1 -12
- package/dist/core/database/adapters/redis.js +13 -48
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/database/adapters/sqlite.d.ts +1 -3
- package/dist/core/database/adapters/sqlite.js +8 -19
- package/dist/core/database/adapters/sqlite.js.map +1 -1
- package/dist/core/database/index.d.ts +2 -2
- package/dist/core/database/index.js +18 -2
- package/dist/core/database/index.js.map +1 -1
- package/dist/core/docs/index.d.ts +9 -9
- package/dist/core/docs/index.js +35 -14
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/openapi-generator.d.ts +2 -2
- package/dist/core/docs/openapi-generator.js +16 -11
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/schema-to-openapi.d.ts +2 -2
- package/dist/core/docs/schema-to-openapi.js +11 -5
- package/dist/core/docs/schema-to-openapi.js.map +1 -1
- package/dist/core/docs/simple-docs.d.ts +1 -1
- package/dist/core/docs/simple-docs.js +9 -4
- package/dist/core/docs/simple-docs.js.map +1 -1
- package/dist/core/docs/swagger-ui.d.ts +2 -2
- package/dist/core/docs/swagger-ui.js +29 -26
- package/dist/core/docs/swagger-ui.js.map +1 -1
- package/dist/core/docs/zod-to-openapi.js +28 -31
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/events/event-bus.d.ts +1 -1
- package/dist/core/events/event-bus.js +10 -6
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/events/index.d.ts +2 -2
- package/dist/core/events/index.js +5 -1
- package/dist/core/events/index.js.map +1 -1
- package/dist/core/framework.d.ts +12 -19
- package/dist/core/framework.js +100 -277
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +1 -13
- package/dist/core/http/http-server.js +85 -175
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/index.d.ts +3 -4
- package/dist/core/http/index.js +8 -3
- package/dist/core/http/index.js.map +1 -1
- package/dist/core/http/router.d.ts +1 -13
- package/dist/core/http/router.js +43 -117
- package/dist/core/http/router.js.map +1 -1
- package/dist/core/logger/filters.d.ts +1 -1
- package/dist/core/logger/filters.js +23 -20
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.d.ts +3 -3
- package/dist/core/logger/index.js +24 -2
- package/dist/core/logger/index.js.map +1 -1
- package/dist/core/logger/logger.d.ts +14 -30
- package/dist/core/logger/logger.js +223 -398
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.d.ts +1 -1
- package/dist/core/logger/outputs.js +17 -8
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/file.js +47 -10
- package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cache/index.js +17 -10
- package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cache/memory.js +7 -3
- package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +1 -3
- package/dist/core/middleware/built-in/adapters/cache/redis.js +9 -11
- package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/azure.js +7 -3
- package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +7 -3
- package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +1 -3
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +10 -12
- package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/cdn/index.js +17 -10
- package/dist/core/middleware/built-in/adapters/cdn/index.js.map +1 -1
- package/dist/core/middleware/built-in/adapters/index.d.ts +4 -4
- package/dist/core/middleware/built-in/adapters/index.js +23 -4
- package/dist/core/middleware/built-in/adapters/index.js.map +1 -1
- package/dist/core/middleware/built-in/auth-helpers.js +22 -11
- package/dist/core/middleware/built-in/auth-helpers.js.map +1 -1
- package/dist/core/middleware/built-in/auth-providers.d.ts +1 -1
- package/dist/core/middleware/built-in/auth-providers.js +9 -4
- package/dist/core/middleware/built-in/auth-providers.js.map +1 -1
- package/dist/core/middleware/built-in/auth.d.ts +2 -2
- package/dist/core/middleware/built-in/auth.js +26 -93
- package/dist/core/middleware/built-in/auth.js.map +1 -1
- package/dist/core/middleware/built-in/cache.d.ts +2 -2
- package/dist/core/middleware/built-in/cache.js +12 -11
- package/dist/core/middleware/built-in/cache.js.map +1 -1
- package/dist/core/middleware/built-in/cdn.d.ts +2 -2
- package/dist/core/middleware/built-in/cdn.js +9 -5
- package/dist/core/middleware/built-in/cdn.js.map +1 -1
- package/dist/core/middleware/built-in/cookie.d.ts +1 -1
- package/dist/core/middleware/built-in/cookie.js +7 -3
- package/dist/core/middleware/built-in/cookie.js.map +1 -1
- package/dist/core/middleware/built-in/cors.d.ts +1 -1
- package/dist/core/middleware/built-in/cors.js +7 -3
- package/dist/core/middleware/built-in/cors.js.map +1 -1
- package/dist/core/middleware/built-in/csp.d.ts +1 -1
- package/dist/core/middleware/built-in/csp.js +8 -5
- package/dist/core/middleware/built-in/csp.js.map +1 -1
- package/dist/core/middleware/built-in/csrf.d.ts +1 -1
- package/dist/core/middleware/built-in/csrf.js +8 -5
- package/dist/core/middleware/built-in/csrf.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker.js +7 -3
- package/dist/core/middleware/built-in/error-tracker.js.map +1 -1
- package/dist/core/middleware/built-in/index.d.ts +27 -28
- package/dist/core/middleware/built-in/index.js +78 -48
- package/dist/core/middleware/built-in/index.js.map +1 -1
- package/dist/core/middleware/built-in/performance-monitor.js +7 -3
- package/dist/core/middleware/built-in/performance-monitor.js.map +1 -1
- package/dist/core/middleware/built-in/rate-limit.d.ts +1 -1
- package/dist/core/middleware/built-in/rate-limit.js +7 -3
- package/dist/core/middleware/built-in/rate-limit.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger.js +8 -5
- package/dist/core/middleware/built-in/request-logger.js.map +1 -1
- package/dist/core/middleware/built-in/session.d.ts +2 -2
- package/dist/core/middleware/built-in/session.js +15 -11
- package/dist/core/middleware/built-in/session.js.map +1 -1
- package/dist/core/middleware/built-in/sse.d.ts +1 -1
- package/dist/core/middleware/built-in/sse.js +14 -12
- package/dist/core/middleware/built-in/sse.js.map +1 -1
- package/dist/core/middleware/built-in/validation.d.ts +1 -1
- package/dist/core/middleware/built-in/validation.js +7 -3
- package/dist/core/middleware/built-in/validation.js.map +1 -1
- package/dist/core/middleware/index.d.ts +4 -4
- package/dist/core/middleware/index.js +28 -8
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/core/modules/auto-discovery.d.ts +2 -19
- package/dist/core/modules/auto-discovery.js +74 -391
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/index.d.ts +2 -2
- package/dist/core/modules/index.js +9 -2
- package/dist/core/modules/index.js.map +1 -1
- package/dist/core/modules/modules.d.ts +3 -3
- package/dist/core/modules/modules.js +54 -23
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/index.d.ts +3 -4
- package/dist/core/networking/adapters/index.js +7 -3
- package/dist/core/networking/adapters/index.js.map +1 -1
- package/dist/core/networking/adapters/socketio-adapter.d.ts +1 -1
- package/dist/core/networking/adapters/socketio-adapter.js +40 -5
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +2 -2
- package/dist/core/networking/adapters/ws-adapter.js +43 -8
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/index.d.ts +2 -3
- package/dist/core/networking/index.js +7 -2
- package/dist/core/networking/index.js.map +1 -1
- package/dist/core/networking/service-discovery.js +12 -8
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/networking/websocket-adapter.js +2 -1
- package/dist/core/networking/websocket-adapter.js.map +1 -1
- package/dist/core/networking/websocket-manager.d.ts +3 -3
- package/dist/core/networking/websocket-manager.js +11 -9
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/routing/app-integration.d.ts +2 -2
- package/dist/core/routing/app-integration.js +12 -7
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/index.d.ts +2 -22
- package/dist/core/routing/index.js +27 -185
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/aws-lambda-adapter.d.ts +3 -3
- package/dist/core/runtime/aws-lambda-adapter.js +6 -2
- package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
- package/dist/core/runtime/base-adapter.d.ts +2 -2
- package/dist/core/runtime/base-adapter.js +7 -3
- package/dist/core/runtime/base-adapter.js.map +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.d.ts +3 -3
- package/dist/core/runtime/cloudflare-workers-adapter.js +6 -2
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
- package/dist/core/runtime/index.d.ts +12 -12
- package/dist/core/runtime/index.js +35 -22
- package/dist/core/runtime/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.d.ts +4 -4
- package/dist/core/runtime/node-adapter.js +49 -18
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/core/runtime/vercel-edge-adapter.d.ts +3 -3
- package/dist/core/runtime/vercel-edge-adapter.js +6 -2
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
- package/dist/core/utilities/circuit-breaker.js +5 -1
- package/dist/core/utilities/circuit-breaker.js.map +1 -1
- package/dist/core/utilities/container.js +22 -12
- package/dist/core/utilities/container.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +2 -2
- package/dist/core/utilities/hooks.js +12 -7
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/core/utilities/index.d.ts +4 -5
- package/dist/core/utilities/index.js +19 -5
- package/dist/core/utilities/index.js.map +1 -1
- package/dist/core/validation/adapters.d.ts +1 -1
- package/dist/core/validation/adapters.js +26 -15
- package/dist/core/validation/adapters.js.map +1 -1
- package/dist/core/validation/index.d.ts +4 -6
- package/dist/core/validation/index.js +28 -57
- package/dist/core/validation/index.js.map +1 -1
- package/dist/core/validation/schema-interface.js +9 -3
- package/dist/core/validation/schema-interface.js.map +1 -1
- package/dist/index.d.ts +52 -51
- package/dist/index.js +132 -23
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +10 -61
- package/dist/moro.js +237 -575
- package/dist/moro.js.map +1 -1
- package/dist/types/auth.js +9 -3
- package/dist/types/auth.js.map +1 -1
- package/dist/types/cache.js +2 -1
- package/dist/types/cdn.js +2 -1
- package/dist/types/config.d.ts +2 -70
- package/dist/types/config.js +2 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/core.d.ts +42 -36
- package/dist/types/core.js +2 -1
- package/dist/types/database.js +2 -1
- package/dist/types/discovery.js +2 -1
- package/dist/types/events.js +2 -1
- package/dist/types/hooks.d.ts +1 -1
- package/dist/types/hooks.js +2 -1
- package/dist/types/http.d.ts +1 -16
- package/dist/types/http.js +2 -1
- package/dist/types/logger.d.ts +0 -7
- package/dist/types/logger.js +2 -1
- package/dist/types/module.d.ts +0 -11
- package/dist/types/module.js +2 -1
- package/dist/types/runtime.d.ts +1 -1
- package/dist/types/runtime.js +2 -1
- package/dist/types/session.js +2 -1
- package/package.json +52 -19
- package/src/core/auth/morojs-adapter.ts +13 -18
- package/src/core/config/file-loader.ts +273 -13
- package/src/core/config/index.ts +34 -83
- package/src/core/config/loader.ts +633 -0
- package/src/core/config/schema.ts +33 -44
- package/src/core/config/utils.ts +31 -24
- package/src/core/config/validation.ts +140 -0
- package/src/core/database/README.md +16 -26
- package/src/core/database/adapters/drizzle.ts +6 -18
- package/src/core/database/adapters/index.ts +13 -13
- package/src/core/database/adapters/mongodb.ts +5 -53
- package/src/core/database/adapters/mysql.ts +4 -32
- package/src/core/database/adapters/postgresql.ts +5 -30
- package/src/core/database/adapters/redis.ts +8 -61
- package/src/core/database/adapters/sqlite.ts +3 -19
- package/src/core/database/index.ts +2 -2
- package/src/core/docs/index.ts +8 -8
- package/src/core/docs/openapi-generator.ts +4 -4
- package/src/core/docs/schema-to-openapi.ts +6 -3
- package/src/core/docs/simple-docs.ts +2 -2
- package/src/core/docs/swagger-ui.ts +16 -19
- package/src/core/docs/zod-to-openapi.ts +34 -34
- package/src/core/events/event-bus.ts +2 -2
- package/src/core/events/index.ts +2 -2
- package/src/core/framework.ts +67 -311
- package/src/core/http/http-server.ts +45 -190
- package/src/core/http/index.ts +3 -4
- package/src/core/http/router.ts +40 -129
- package/src/core/logger/filters.ts +5 -13
- package/src/core/logger/index.ts +3 -4
- package/src/core/logger/logger.ts +216 -435
- package/src/core/logger/outputs.ts +3 -1
- package/src/core/middleware/built-in/adapters/cache/file.ts +3 -3
- package/src/core/middleware/built-in/adapters/cache/index.ts +7 -7
- package/src/core/middleware/built-in/adapters/cache/memory.ts +2 -2
- package/src/core/middleware/built-in/adapters/cache/redis.ts +4 -18
- package/src/core/middleware/built-in/adapters/cdn/azure.ts +2 -2
- package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +2 -2
- package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +5 -16
- package/src/core/middleware/built-in/adapters/cdn/index.ts +7 -7
- package/src/core/middleware/built-in/adapters/index.ts +4 -4
- package/src/core/middleware/built-in/auth-helpers.ts +1 -1
- package/src/core/middleware/built-in/auth-providers.ts +1 -1
- package/src/core/middleware/built-in/auth.ts +21 -102
- package/src/core/middleware/built-in/cache.ts +6 -8
- package/src/core/middleware/built-in/cdn.ts +4 -4
- package/src/core/middleware/built-in/cookie.ts +2 -2
- package/src/core/middleware/built-in/cors.ts +2 -2
- package/src/core/middleware/built-in/csp.ts +3 -3
- package/src/core/middleware/built-in/csrf.ts +3 -3
- package/src/core/middleware/built-in/error-tracker.ts +1 -1
- package/src/core/middleware/built-in/index.ts +30 -38
- package/src/core/middleware/built-in/performance-monitor.ts +1 -1
- package/src/core/middleware/built-in/rate-limit.ts +2 -2
- package/src/core/middleware/built-in/request-logger.ts +1 -3
- package/src/core/middleware/built-in/session.ts +8 -7
- package/src/core/middleware/built-in/sse.ts +9 -11
- package/src/core/middleware/built-in/validation.ts +2 -2
- package/src/core/middleware/index.ts +6 -6
- package/src/core/modules/auto-discovery.ts +15 -478
- package/src/core/modules/index.ts +2 -2
- package/src/core/modules/modules.ts +12 -23
- package/src/core/networking/adapters/index.ts +3 -4
- package/src/core/networking/adapters/socketio-adapter.ts +3 -5
- package/src/core/networking/adapters/ws-adapter.ts +9 -8
- package/src/core/networking/index.ts +2 -3
- package/src/core/networking/service-discovery.ts +7 -6
- package/src/core/networking/websocket-manager.ts +7 -7
- package/src/core/routing/app-integration.ts +3 -3
- package/src/core/routing/index.ts +17 -201
- package/src/core/runtime/aws-lambda-adapter.ts +3 -3
- package/src/core/runtime/base-adapter.ts +2 -2
- package/src/core/runtime/cloudflare-workers-adapter.ts +3 -3
- package/src/core/runtime/index.ts +13 -13
- package/src/core/runtime/node-adapter.ts +10 -16
- package/src/core/runtime/vercel-edge-adapter.ts +3 -3
- package/src/core/utilities/hooks.ts +3 -3
- package/src/core/utilities/index.ts +4 -5
- package/src/core/validation/adapters.ts +1 -1
- package/src/core/validation/index.ts +16 -68
- package/src/index.ts +66 -73
- package/src/moro.ts +204 -685
- package/src/types/config.ts +2 -71
- package/src/types/core.ts +47 -49
- package/src/types/hooks.ts +1 -1
- package/src/types/http.ts +1 -23
- package/src/types/logger.ts +0 -9
- package/src/types/module.ts +0 -12
- package/src/types/runtime.ts +1 -1
- package/tsconfig.json +2 -4
- package/dist/core/config/config-manager.d.ts +0 -44
- package/dist/core/config/config-manager.js +0 -104
- package/dist/core/config/config-manager.js.map +0 -1
- package/dist/core/config/config-sources.d.ts +0 -21
- package/dist/core/config/config-sources.js +0 -499
- package/dist/core/config/config-sources.js.map +0 -1
- package/dist/core/config/config-validator.d.ts +0 -21
- package/dist/core/config/config-validator.js +0 -788
- package/dist/core/config/config-validator.js.map +0 -1
- package/dist/core/http/uws-http-server.d.ts +0 -64
- package/dist/core/http/uws-http-server.js +0 -688
- package/dist/core/http/uws-http-server.js.map +0 -1
- package/dist/core/middleware/built-in/jwt-helpers.d.ts +0 -118
- package/dist/core/middleware/built-in/jwt-helpers.js +0 -218
- package/dist/core/middleware/built-in/jwt-helpers.js.map +0 -1
- package/dist/core/networking/adapters/uws-adapter.d.ts +0 -44
- package/dist/core/networking/adapters/uws-adapter.js +0 -513
- package/dist/core/networking/adapters/uws-adapter.js.map +0 -1
- package/dist/core/utilities/package-utils.d.ts +0 -38
- package/dist/core/utilities/package-utils.js +0 -57
- package/dist/core/utilities/package-utils.js.map +0 -1
- package/jest.config.mjs +0 -41
- package/src/core/config/config-manager.ts +0 -133
- package/src/core/config/config-sources.ts +0 -596
- package/src/core/config/config-validator.ts +0 -1113
- package/src/core/http/uws-http-server.ts +0 -794
- package/src/core/middleware/built-in/jwt-helpers.ts +0 -243
- package/src/core/networking/adapters/uws-adapter.ts +0 -619
- package/src/core/utilities/package-utils.ts +0 -59
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Moro Logger - Beautiful, Fast, Feature-Rich
|
|
2
2
|
import { performance } from 'perf_hooks';
|
|
3
|
-
|
|
3
|
+
// import { format } from 'util'; // Not currently used
|
|
4
4
|
import {
|
|
5
5
|
LogLevel,
|
|
6
6
|
LogEntry,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
LogFilter,
|
|
11
11
|
LogMetrics,
|
|
12
12
|
ColorScheme,
|
|
13
|
-
} from '../../types/logger
|
|
13
|
+
} from '../../types/logger';
|
|
14
14
|
|
|
15
15
|
export class MoroLogger implements Logger {
|
|
16
16
|
private level: LogLevel = 'info';
|
|
@@ -41,27 +41,13 @@ export class MoroLogger implements Logger {
|
|
|
41
41
|
private lastTimestamp = 0;
|
|
42
42
|
private timestampCacheInterval = 100; // 100ms for better precision
|
|
43
43
|
|
|
44
|
-
//
|
|
45
|
-
private static readonly ENTRY_POOL: LogEntry[] = [];
|
|
46
|
-
private static readonly MAX_POOL_SIZE = 100;
|
|
47
|
-
private static poolIndex = 0;
|
|
48
|
-
|
|
49
|
-
// String builder for efficient concatenation
|
|
50
|
-
private static stringBuilder: string[] = [];
|
|
51
|
-
private static stringBuilderIndex = 0;
|
|
52
|
-
|
|
53
|
-
// Buffered output for performance
|
|
44
|
+
// Buffered output for micro-batching
|
|
54
45
|
private outputBuffer: string[] = [];
|
|
55
46
|
private bufferSize = 0;
|
|
56
|
-
private maxBufferSize =
|
|
47
|
+
private maxBufferSize = 1024; // 1KB buffer
|
|
57
48
|
private flushTimeout: NodeJS.Timeout | null = null;
|
|
58
49
|
private flushInterval = 1; // 1ms micro-batching
|
|
59
50
|
|
|
60
|
-
// Buffer overflow protection
|
|
61
|
-
private bufferOverflowThreshold: number;
|
|
62
|
-
private emergencyFlushInProgress = false;
|
|
63
|
-
private isDestroyed = false;
|
|
64
|
-
|
|
65
51
|
// High-performance output methods
|
|
66
52
|
|
|
67
53
|
private static readonly LEVELS: Record<LogLevel, number> = {
|
|
@@ -72,6 +58,84 @@ export class MoroLogger implements Logger {
|
|
|
72
58
|
fatal: 4,
|
|
73
59
|
};
|
|
74
60
|
|
|
61
|
+
// Static pre-allocated strings for maximum performance
|
|
62
|
+
private static readonly LEVEL_STRINGS: Record<LogLevel, string> = {
|
|
63
|
+
debug: 'DEBUG',
|
|
64
|
+
info: 'INFO',
|
|
65
|
+
warn: 'WARN',
|
|
66
|
+
error: 'ERROR',
|
|
67
|
+
fatal: 'FATAL',
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Pre-allocated ANSI color codes
|
|
71
|
+
private static readonly ANSI_COLORS = {
|
|
72
|
+
reset: '\x1b[0m',
|
|
73
|
+
bold: '\x1b[1m',
|
|
74
|
+
dim: '\x1b[2m',
|
|
75
|
+
red: '\x1b[31m',
|
|
76
|
+
green: '\x1b[32m',
|
|
77
|
+
yellow: '\x1b[33m',
|
|
78
|
+
blue: '\x1b[34m',
|
|
79
|
+
magenta: '\x1b[35m',
|
|
80
|
+
cyan: '\x1b[36m',
|
|
81
|
+
white: '\x1b[37m',
|
|
82
|
+
gray: '\x1b[90m',
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Object pool for LogEntry reuse
|
|
86
|
+
private static readonly ENTRY_POOL: LogEntry[] = [];
|
|
87
|
+
private static readonly MAX_POOL_SIZE = 100;
|
|
88
|
+
private static poolIndex = 0;
|
|
89
|
+
|
|
90
|
+
// Object pool management
|
|
91
|
+
private static getPooledEntry(): LogEntry {
|
|
92
|
+
if (MoroLogger.poolIndex > 0) {
|
|
93
|
+
return MoroLogger.ENTRY_POOL[--MoroLogger.poolIndex];
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
timestamp: new Date(),
|
|
97
|
+
level: 'info',
|
|
98
|
+
message: '',
|
|
99
|
+
context: undefined,
|
|
100
|
+
metadata: undefined,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private static returnPooledEntry(entry: LogEntry): void {
|
|
105
|
+
if (MoroLogger.poolIndex < MoroLogger.MAX_POOL_SIZE) {
|
|
106
|
+
// Reset the entry
|
|
107
|
+
entry.timestamp = new Date();
|
|
108
|
+
entry.level = 'info';
|
|
109
|
+
entry.message = '';
|
|
110
|
+
entry.context = undefined;
|
|
111
|
+
entry.metadata = undefined;
|
|
112
|
+
MoroLogger.ENTRY_POOL[MoroLogger.poolIndex++] = entry;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// String builder for efficient concatenation
|
|
117
|
+
private static stringBuilder: string[] = [];
|
|
118
|
+
private static stringBuilderIndex = 0;
|
|
119
|
+
|
|
120
|
+
private static resetStringBuilder(): void {
|
|
121
|
+
MoroLogger.stringBuilderIndex = 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private static appendToBuilder(str: string): void {
|
|
125
|
+
if (MoroLogger.stringBuilderIndex < MoroLogger.stringBuilder.length) {
|
|
126
|
+
MoroLogger.stringBuilder[MoroLogger.stringBuilderIndex++] = str;
|
|
127
|
+
} else {
|
|
128
|
+
MoroLogger.stringBuilder.push(str);
|
|
129
|
+
MoroLogger.stringBuilderIndex++;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private static buildString(): string {
|
|
134
|
+
const result = MoroLogger.stringBuilder.slice(0, MoroLogger.stringBuilderIndex).join('');
|
|
135
|
+
MoroLogger.resetStringBuilder();
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
|
|
75
139
|
private static readonly COLORS: ColorScheme = {
|
|
76
140
|
debug: '\x1b[36m', // Cyan
|
|
77
141
|
info: '\x1b[32m', // Green
|
|
@@ -82,23 +146,13 @@ export class MoroLogger implements Logger {
|
|
|
82
146
|
context: '\x1b[34m', // Blue
|
|
83
147
|
metadata: '\x1b[37m', // White
|
|
84
148
|
performance: '\x1b[36m', // Cyan
|
|
85
|
-
reset: '\x1b[0m', // Reset
|
|
86
149
|
};
|
|
87
150
|
|
|
88
151
|
private static readonly RESET = '\x1b[0m';
|
|
89
152
|
private static readonly BOLD = '\x1b[1m';
|
|
90
153
|
|
|
91
|
-
// Static pre-allocated strings for performance
|
|
92
|
-
private static readonly LEVEL_STRINGS: Record<LogLevel, string> = {
|
|
93
|
-
debug: 'DEBUG',
|
|
94
|
-
info: 'INFO ',
|
|
95
|
-
warn: 'WARN ',
|
|
96
|
-
error: 'ERROR',
|
|
97
|
-
fatal: 'FATAL',
|
|
98
|
-
};
|
|
99
|
-
|
|
100
154
|
constructor(options: LoggerOptions = {}) {
|
|
101
|
-
this.options =
|
|
155
|
+
this.options = {
|
|
102
156
|
level: 'info',
|
|
103
157
|
enableColors: true,
|
|
104
158
|
enableTimestamp: true,
|
|
@@ -109,18 +163,11 @@ export class MoroLogger implements Logger {
|
|
|
109
163
|
outputs: [],
|
|
110
164
|
filters: [],
|
|
111
165
|
maxEntries: 1000,
|
|
112
|
-
maxBufferSize: 1000,
|
|
113
166
|
...options,
|
|
114
|
-
}
|
|
167
|
+
};
|
|
115
168
|
|
|
116
169
|
this.level = this.options.level || 'info';
|
|
117
170
|
|
|
118
|
-
// Initialize buffer size from options
|
|
119
|
-
this.maxBufferSize = this.options.maxBufferSize || 1000;
|
|
120
|
-
|
|
121
|
-
// Initialize buffer overflow protection
|
|
122
|
-
this.bufferOverflowThreshold = this.maxBufferSize * 2;
|
|
123
|
-
|
|
124
171
|
// Add default console output
|
|
125
172
|
this.addOutput({
|
|
126
173
|
name: 'console',
|
|
@@ -133,58 +180,6 @@ export class MoroLogger implements Logger {
|
|
|
133
180
|
this.options.filters?.forEach(filter => this.addFilter(filter));
|
|
134
181
|
}
|
|
135
182
|
|
|
136
|
-
// Object pooling methods
|
|
137
|
-
private static getPooledEntry(): LogEntry {
|
|
138
|
-
if (MoroLogger.ENTRY_POOL.length > 0) {
|
|
139
|
-
const entry = MoroLogger.ENTRY_POOL.pop()!;
|
|
140
|
-
// Properly reset ALL properties to prevent memory leaks
|
|
141
|
-
entry.timestamp = new Date();
|
|
142
|
-
entry.level = 'info';
|
|
143
|
-
entry.message = '';
|
|
144
|
-
entry.context = undefined;
|
|
145
|
-
entry.metadata = undefined;
|
|
146
|
-
entry.performance = undefined;
|
|
147
|
-
entry.moduleId = undefined;
|
|
148
|
-
return entry;
|
|
149
|
-
}
|
|
150
|
-
return MoroLogger.createFreshEntry();
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// ADD this new method:
|
|
154
|
-
private static createFreshEntry(): LogEntry {
|
|
155
|
-
return {
|
|
156
|
-
timestamp: new Date(),
|
|
157
|
-
level: 'info',
|
|
158
|
-
message: '',
|
|
159
|
-
context: undefined,
|
|
160
|
-
metadata: undefined,
|
|
161
|
-
performance: undefined,
|
|
162
|
-
moduleId: undefined,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
private static returnPooledEntry(entry: LogEntry): void {
|
|
167
|
-
if (MoroLogger.ENTRY_POOL.length < MoroLogger.MAX_POOL_SIZE) {
|
|
168
|
-
MoroLogger.ENTRY_POOL.push(entry);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// String builder methods
|
|
173
|
-
private static resetStringBuilder(): void {
|
|
174
|
-
MoroLogger.stringBuilder.length = 0;
|
|
175
|
-
MoroLogger.stringBuilderIndex = 0;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
private static appendToBuilder(str: string): void {
|
|
179
|
-
MoroLogger.stringBuilder[MoroLogger.stringBuilderIndex++] = str;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private static buildString(): string {
|
|
183
|
-
const result = MoroLogger.stringBuilder.join('');
|
|
184
|
-
MoroLogger.resetStringBuilder();
|
|
185
|
-
return result;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
183
|
debug(message: string, context?: string, metadata?: Record<string, any>): void {
|
|
189
184
|
this.log('debug', message, context, metadata);
|
|
190
185
|
}
|
|
@@ -227,9 +222,7 @@ export class MoroLogger implements Logger {
|
|
|
227
222
|
}
|
|
228
223
|
|
|
229
224
|
child(context: string, metadata?: Record<string, any>): Logger {
|
|
230
|
-
|
|
231
|
-
const childOptions = { ...this.options, level: this.level };
|
|
232
|
-
const childLogger = new MoroLogger(childOptions);
|
|
225
|
+
const childLogger = new MoroLogger(this.options);
|
|
233
226
|
childLogger.contextPrefix = this.contextPrefix ? `${this.contextPrefix}:${context}` : context;
|
|
234
227
|
childLogger.contextMetadata = { ...this.contextMetadata, ...metadata };
|
|
235
228
|
childLogger.outputs = this.outputs;
|
|
@@ -245,10 +238,6 @@ export class MoroLogger implements Logger {
|
|
|
245
238
|
this.level = level;
|
|
246
239
|
}
|
|
247
240
|
|
|
248
|
-
getLevel(): LogLevel {
|
|
249
|
-
return this.level;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
241
|
addOutput(output: LogOutput): void {
|
|
253
242
|
this.outputs.set(output.name, output);
|
|
254
243
|
}
|
|
@@ -298,17 +287,6 @@ export class MoroLogger implements Logger {
|
|
|
298
287
|
return this.cachedTimestamp;
|
|
299
288
|
}
|
|
300
289
|
|
|
301
|
-
// Cached timestamp generation (updates once per second)
|
|
302
|
-
private getFastCachedTimestamp(): string {
|
|
303
|
-
const now = Date.now();
|
|
304
|
-
if (now - this.lastTimestamp > 1000) {
|
|
305
|
-
// Update every second
|
|
306
|
-
this.lastTimestamp = now;
|
|
307
|
-
this.cachedTimestamp = new Date(now).toISOString().slice(0, 19).replace('T', ' ');
|
|
308
|
-
}
|
|
309
|
-
return this.cachedTimestamp;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
290
|
getMetrics(): LogMetrics {
|
|
313
291
|
const now = Date.now();
|
|
314
292
|
const uptime = (now - this.startTime) / 1000; // seconds
|
|
@@ -336,54 +314,62 @@ export class MoroLogger implements Logger {
|
|
|
336
314
|
};
|
|
337
315
|
}
|
|
338
316
|
|
|
339
|
-
// Optimized logging method
|
|
317
|
+
// Optimized logging method with aggressive level checking
|
|
340
318
|
private log(
|
|
341
319
|
level: LogLevel,
|
|
342
320
|
message: string,
|
|
343
321
|
context?: string,
|
|
344
322
|
metadata?: Record<string, any>
|
|
345
323
|
): void {
|
|
346
|
-
//
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
324
|
+
// AGGRESSIVE LEVEL CHECK - numeric comparison for maximum speed
|
|
325
|
+
const levelNum = MoroLogger.LEVELS[level];
|
|
326
|
+
const effectiveLevelNum = this.parent
|
|
327
|
+
? MoroLogger.LEVELS[this.parent.level]
|
|
328
|
+
: MoroLogger.LEVELS[this.level];
|
|
350
329
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (MoroLogger.LEVELS[level] < MoroLogger.LEVELS[effectiveLevel as LogLevel]) {
|
|
354
|
-
return;
|
|
330
|
+
if (levelNum < effectiveLevelNum) {
|
|
331
|
+
return; // Exit immediately if level is too low
|
|
355
332
|
}
|
|
356
333
|
|
|
357
|
-
//
|
|
334
|
+
// ULTRA-FAST PATH: Just message, no context, no metadata
|
|
358
335
|
if (!metadata && !context && !this.contextPrefix && !this.contextMetadata) {
|
|
359
|
-
|
|
336
|
+
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
337
|
+
this.output(`${levelStr} ${message}\n`, level);
|
|
360
338
|
return;
|
|
361
339
|
}
|
|
362
340
|
|
|
363
|
-
//
|
|
341
|
+
// FAST PATH: Message + context, no metadata
|
|
364
342
|
if (!metadata && !this.contextMetadata) {
|
|
365
|
-
|
|
343
|
+
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
344
|
+
if (context) {
|
|
345
|
+
this.output(`${levelStr} [${context}] ${message}\n`, level);
|
|
346
|
+
} else {
|
|
347
|
+
this.output(`${levelStr} ${message}\n`, level);
|
|
348
|
+
}
|
|
366
349
|
return;
|
|
367
350
|
}
|
|
368
351
|
|
|
369
|
-
//
|
|
370
|
-
if (metadata && Object.keys(metadata).length
|
|
371
|
-
|
|
352
|
+
// MEDIUM PATH: Message + context + simple metadata
|
|
353
|
+
if (metadata && Object.keys(metadata).length <= 3 && !this.contextMetadata) {
|
|
354
|
+
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
355
|
+
const contextStr = context ? `[${context}] ` : '';
|
|
356
|
+
const metaStr = this.stringify(metadata);
|
|
357
|
+
this.output(`${levelStr} ${contextStr}${message} ${metaStr}\n`, level);
|
|
372
358
|
return;
|
|
373
359
|
}
|
|
374
360
|
|
|
375
|
-
//
|
|
361
|
+
// FULL PATH: All features enabled
|
|
376
362
|
this.fullLog(level, message, context, metadata);
|
|
377
363
|
}
|
|
378
364
|
|
|
379
|
-
// Full logging with all features
|
|
365
|
+
// Full logging with all features using object pooling
|
|
380
366
|
private fullLog(
|
|
381
367
|
level: LogLevel,
|
|
382
368
|
message: string,
|
|
383
369
|
context?: string,
|
|
384
370
|
metadata?: Record<string, any>
|
|
385
371
|
): void {
|
|
386
|
-
//
|
|
372
|
+
// Get pooled entry to avoid allocation
|
|
387
373
|
const entry = MoroLogger.getPooledEntry();
|
|
388
374
|
const now = Date.now();
|
|
389
375
|
|
|
@@ -402,7 +388,6 @@ export class MoroLogger implements Logger {
|
|
|
402
388
|
if (this.filters.size > 0) {
|
|
403
389
|
for (const filter of this.filters.values()) {
|
|
404
390
|
if (!filter.filter(entry)) {
|
|
405
|
-
MoroLogger.returnPooledEntry(entry);
|
|
406
391
|
return;
|
|
407
392
|
}
|
|
408
393
|
}
|
|
@@ -417,89 +402,8 @@ export class MoroLogger implements Logger {
|
|
|
417
402
|
// Write to outputs with batched processing
|
|
418
403
|
this.writeToOutputs(entry, level);
|
|
419
404
|
|
|
420
|
-
// Return entry to pool
|
|
421
|
-
MoroLogger.returnPooledEntry(entry);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// Absolute minimal logging - pure speed, no overhead
|
|
425
|
-
private complexLog(
|
|
426
|
-
level: LogLevel,
|
|
427
|
-
message: string,
|
|
428
|
-
context?: string,
|
|
429
|
-
metadata?: Record<string, any>
|
|
430
|
-
): void {
|
|
431
|
-
// Use object pooling for LogEntry (Pino's technique)
|
|
432
|
-
const entry = MoroLogger.getPooledEntry();
|
|
433
|
-
const now = Date.now();
|
|
434
|
-
|
|
435
|
-
entry.timestamp = new Date(now);
|
|
436
|
-
entry.level = level;
|
|
437
|
-
entry.message = message;
|
|
438
|
-
entry.context = this.contextPrefix
|
|
439
|
-
? context
|
|
440
|
-
? `${this.contextPrefix}:${context}`
|
|
441
|
-
: this.contextPrefix
|
|
442
|
-
: context;
|
|
443
|
-
entry.metadata = this.createMetadata(metadata);
|
|
444
|
-
entry.performance = this.options.enablePerformance ? this.getPerformanceData(now) : undefined;
|
|
445
|
-
|
|
446
|
-
// Write to outputs with batched processing
|
|
447
|
-
this.writeToOutputs(entry, level);
|
|
448
|
-
|
|
449
|
-
// Return entry to pool
|
|
450
|
-
MoroLogger.returnPooledEntry(entry);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// Simple log writer with colors for minimal overhead cases
|
|
454
|
-
private writeSimpleLog(level: LogLevel, message: string, context?: string): void {
|
|
455
|
-
const colors = this.options.enableColors !== false;
|
|
456
|
-
const levelReset = colors ? MoroLogger.RESET : '';
|
|
457
|
-
|
|
458
|
-
MoroLogger.resetStringBuilder();
|
|
459
|
-
|
|
460
|
-
// Timestamp with caching optimization
|
|
461
|
-
if (this.options.enableTimestamp !== false) {
|
|
462
|
-
const timestamp = this.getFastCachedTimestamp();
|
|
463
|
-
if (colors) {
|
|
464
|
-
MoroLogger.appendToBuilder(MoroLogger.COLORS.timestamp);
|
|
465
|
-
MoroLogger.appendToBuilder(timestamp);
|
|
466
|
-
MoroLogger.appendToBuilder(levelReset);
|
|
467
|
-
} else {
|
|
468
|
-
MoroLogger.appendToBuilder(timestamp);
|
|
469
|
-
}
|
|
470
|
-
MoroLogger.appendToBuilder(' ');
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Level with pre-allocated strings
|
|
474
|
-
const levelStr = MoroLogger.LEVEL_STRINGS[level];
|
|
475
|
-
if (colors) {
|
|
476
|
-
MoroLogger.appendToBuilder(MoroLogger.COLORS[level]);
|
|
477
|
-
MoroLogger.appendToBuilder(MoroLogger.BOLD);
|
|
478
|
-
MoroLogger.appendToBuilder(levelStr);
|
|
479
|
-
MoroLogger.appendToBuilder(levelReset);
|
|
480
|
-
} else {
|
|
481
|
-
MoroLogger.appendToBuilder(levelStr);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Context
|
|
485
|
-
if (context && this.options.enableContext !== false) {
|
|
486
|
-
MoroLogger.appendToBuilder(' ');
|
|
487
|
-
if (colors) {
|
|
488
|
-
MoroLogger.appendToBuilder(MoroLogger.COLORS.context);
|
|
489
|
-
MoroLogger.appendToBuilder(`[${context}]`);
|
|
490
|
-
MoroLogger.appendToBuilder(levelReset);
|
|
491
|
-
} else {
|
|
492
|
-
MoroLogger.appendToBuilder(`[${context}]`);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// Message
|
|
497
|
-
MoroLogger.appendToBuilder(' ');
|
|
498
|
-
MoroLogger.appendToBuilder(message);
|
|
499
|
-
|
|
500
|
-
// Output main log line with high-performance method
|
|
501
|
-
const finalMessage = MoroLogger.buildString();
|
|
502
|
-
this.output(`${finalMessage}\n`, level);
|
|
405
|
+
// Return entry to pool after a short delay to allow async operations
|
|
406
|
+
setTimeout(() => MoroLogger.returnPooledEntry(entry), 0);
|
|
503
407
|
}
|
|
504
408
|
|
|
505
409
|
private updateMetrics(entry: LogEntry): void {
|
|
@@ -553,39 +457,24 @@ export class MoroLogger implements Logger {
|
|
|
553
457
|
private writeToOutputs(entry: LogEntry, level: LogLevel): void {
|
|
554
458
|
if (this.outputs.size === 0) return;
|
|
555
459
|
|
|
556
|
-
let successCount = 0;
|
|
557
|
-
const errors: Array<{ outputName: string; error: any }> = [];
|
|
558
|
-
|
|
559
460
|
for (const output of this.outputs.values()) {
|
|
560
461
|
if (!output.level || MoroLogger.LEVELS[level] >= MoroLogger.LEVELS[output.level]) {
|
|
561
462
|
try {
|
|
562
463
|
output.write(entry);
|
|
563
|
-
successCount++;
|
|
564
464
|
} catch (error) {
|
|
565
|
-
|
|
566
|
-
|
|
465
|
+
// Fallback to console.error for logger errors
|
|
466
|
+
// eslint-disable-next-line no-console
|
|
467
|
+
console.error('Logger output error:', error);
|
|
567
468
|
}
|
|
568
469
|
}
|
|
569
470
|
}
|
|
570
|
-
|
|
571
|
-
// If all outputs fail, use emergency console
|
|
572
|
-
if (successCount === 0 && this.outputs.size > 0) {
|
|
573
|
-
this.emergencyConsoleWrite(entry);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// Log output errors (but avoid infinite loops)
|
|
577
|
-
if (errors.length > 0 && level !== 'error') {
|
|
578
|
-
this.error(`Logger output errors: ${errors.length} failed`, 'MoroLogger', {
|
|
579
|
-
errors: errors.map(e => e.outputName),
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
471
|
}
|
|
583
472
|
|
|
584
473
|
private writeToConsole(entry: LogEntry): void {
|
|
585
474
|
const format = this.options.format || 'pretty';
|
|
586
475
|
|
|
587
476
|
if (format === 'json') {
|
|
588
|
-
this.output(
|
|
477
|
+
this.output(JSON.stringify(entry) + '\n', entry.level);
|
|
589
478
|
return;
|
|
590
479
|
}
|
|
591
480
|
|
|
@@ -602,8 +491,6 @@ export class MoroLogger implements Logger {
|
|
|
602
491
|
|
|
603
492
|
private writePrettyLog(entry: LogEntry): void {
|
|
604
493
|
const colors = this.options.enableColors !== false;
|
|
605
|
-
const levelReset = colors ? MoroLogger.RESET : '';
|
|
606
|
-
|
|
607
494
|
MoroLogger.resetStringBuilder();
|
|
608
495
|
|
|
609
496
|
// Timestamp with caching optimization
|
|
@@ -612,29 +499,37 @@ export class MoroLogger implements Logger {
|
|
|
612
499
|
if (colors) {
|
|
613
500
|
MoroLogger.appendToBuilder(MoroLogger.COLORS.timestamp);
|
|
614
501
|
MoroLogger.appendToBuilder(timestamp);
|
|
615
|
-
MoroLogger.appendToBuilder(
|
|
502
|
+
MoroLogger.appendToBuilder(MoroLogger.RESET);
|
|
616
503
|
} else {
|
|
617
504
|
MoroLogger.appendToBuilder(timestamp);
|
|
618
505
|
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Level with color using pre-allocated strings
|
|
509
|
+
const levelColor = colors ? MoroLogger.COLORS[entry.level] : '';
|
|
510
|
+
const levelReset = colors ? MoroLogger.RESET : '';
|
|
511
|
+
const levelText = MoroLogger.LEVEL_STRINGS[entry.level];
|
|
512
|
+
|
|
513
|
+
// Add space after timestamp if present
|
|
514
|
+
if (this.options.enableTimestamp !== false) {
|
|
619
515
|
MoroLogger.appendToBuilder(' ');
|
|
620
516
|
}
|
|
621
517
|
|
|
622
|
-
// Level with pre-allocated strings
|
|
623
|
-
const levelStr = MoroLogger.LEVEL_STRINGS[entry.level];
|
|
624
518
|
if (colors) {
|
|
625
|
-
MoroLogger.appendToBuilder(
|
|
519
|
+
MoroLogger.appendToBuilder(levelColor);
|
|
626
520
|
MoroLogger.appendToBuilder(MoroLogger.BOLD);
|
|
627
|
-
MoroLogger.appendToBuilder(
|
|
521
|
+
MoroLogger.appendToBuilder(levelText);
|
|
628
522
|
MoroLogger.appendToBuilder(levelReset);
|
|
629
523
|
} else {
|
|
630
|
-
MoroLogger.appendToBuilder(
|
|
524
|
+
MoroLogger.appendToBuilder(levelText);
|
|
631
525
|
}
|
|
632
526
|
|
|
633
527
|
// Context
|
|
634
528
|
if (entry.context && this.options.enableContext !== false) {
|
|
635
|
-
MoroLogger.
|
|
529
|
+
const contextColor = colors ? MoroLogger.COLORS.context : '';
|
|
530
|
+
MoroLogger.appendToBuilder(' '); // Space before context
|
|
636
531
|
if (colors) {
|
|
637
|
-
MoroLogger.appendToBuilder(
|
|
532
|
+
MoroLogger.appendToBuilder(contextColor);
|
|
638
533
|
MoroLogger.appendToBuilder(`[${entry.context}]`);
|
|
639
534
|
MoroLogger.appendToBuilder(levelReset);
|
|
640
535
|
} else {
|
|
@@ -643,7 +538,7 @@ export class MoroLogger implements Logger {
|
|
|
643
538
|
}
|
|
644
539
|
|
|
645
540
|
// Message
|
|
646
|
-
MoroLogger.appendToBuilder(' ');
|
|
541
|
+
MoroLogger.appendToBuilder(' '); // Space before message
|
|
647
542
|
MoroLogger.appendToBuilder(entry.message);
|
|
648
543
|
|
|
649
544
|
// Performance info
|
|
@@ -659,7 +554,7 @@ export class MoroLogger implements Logger {
|
|
|
659
554
|
}
|
|
660
555
|
|
|
661
556
|
if (perfParts.length > 0) {
|
|
662
|
-
MoroLogger.appendToBuilder(' ');
|
|
557
|
+
MoroLogger.appendToBuilder(' '); // Space before performance info
|
|
663
558
|
if (colors) {
|
|
664
559
|
MoroLogger.appendToBuilder(perfColor);
|
|
665
560
|
MoroLogger.appendToBuilder(`(${perfParts.join(', ')})`);
|
|
@@ -680,20 +575,19 @@ export class MoroLogger implements Logger {
|
|
|
680
575
|
const cleanMetadata = this.cleanMetadata(entry.metadata);
|
|
681
576
|
|
|
682
577
|
if (Object.keys(cleanMetadata).length > 0) {
|
|
683
|
-
MoroLogger.appendToBuilder(' ');
|
|
684
578
|
if (colors) {
|
|
685
579
|
MoroLogger.appendToBuilder(metaColor);
|
|
686
|
-
MoroLogger.appendToBuilder(this.
|
|
580
|
+
MoroLogger.appendToBuilder(this.stringify(cleanMetadata));
|
|
687
581
|
MoroLogger.appendToBuilder(levelReset);
|
|
688
582
|
} else {
|
|
689
|
-
MoroLogger.appendToBuilder(this.
|
|
583
|
+
MoroLogger.appendToBuilder(this.stringify(cleanMetadata));
|
|
690
584
|
}
|
|
691
585
|
}
|
|
692
586
|
}
|
|
693
587
|
|
|
694
588
|
// Output main log line with high-performance method
|
|
695
589
|
const finalMessage = MoroLogger.buildString();
|
|
696
|
-
this.output(
|
|
590
|
+
this.output(finalMessage + '\n', entry.level);
|
|
697
591
|
|
|
698
592
|
// Stack trace for errors
|
|
699
593
|
if (entry.metadata?.stack && (entry.level === 'error' || entry.level === 'fatal')) {
|
|
@@ -713,199 +607,79 @@ export class MoroLogger implements Logger {
|
|
|
713
607
|
return clean;
|
|
714
608
|
}
|
|
715
609
|
|
|
716
|
-
//
|
|
717
|
-
private
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
) {
|
|
723
|
-
this.emergencyFlushInProgress = true;
|
|
724
|
-
this.forceFlushBuffer();
|
|
725
|
-
this.emergencyFlushInProgress = false;
|
|
610
|
+
// Fast JSON stringify with error handling
|
|
611
|
+
private stringify(obj: any): string {
|
|
612
|
+
try {
|
|
613
|
+
return JSON.stringify(obj);
|
|
614
|
+
} catch {
|
|
615
|
+
return '[Circular Reference]';
|
|
726
616
|
}
|
|
617
|
+
}
|
|
727
618
|
|
|
619
|
+
// High-performance output with micro-batching
|
|
620
|
+
private output(message: string, level: LogLevel = 'info'): void {
|
|
621
|
+
// Add to buffer
|
|
728
622
|
this.outputBuffer.push(message);
|
|
729
|
-
this.bufferSize
|
|
623
|
+
this.bufferSize += message.length;
|
|
730
624
|
|
|
731
|
-
//
|
|
732
|
-
if (
|
|
625
|
+
// Flush immediately if buffer is full or for errors
|
|
626
|
+
if (this.bufferSize >= this.maxBufferSize || level === 'error' || level === 'fatal') {
|
|
733
627
|
this.flushBuffer();
|
|
734
628
|
} else {
|
|
629
|
+
// Schedule flush with micro-batching
|
|
735
630
|
this.scheduleFlush();
|
|
736
631
|
}
|
|
737
632
|
}
|
|
738
633
|
|
|
739
634
|
private scheduleFlush(): void {
|
|
740
|
-
if (this.flushTimeout
|
|
741
|
-
return; // Already scheduled or destroyed
|
|
742
|
-
}
|
|
635
|
+
if (this.flushTimeout) return; // Already scheduled
|
|
743
636
|
|
|
744
637
|
this.flushTimeout = setTimeout(() => {
|
|
745
638
|
this.flushBuffer();
|
|
639
|
+
this.flushTimeout = null;
|
|
746
640
|
}, this.flushInterval);
|
|
747
|
-
|
|
748
|
-
// Unref the timeout so it doesn't prevent process exit (important for tests)
|
|
749
|
-
this.flushTimeout.unref();
|
|
750
641
|
}
|
|
751
642
|
|
|
752
|
-
|
|
753
|
-
if (this.outputBuffer.length === 0)
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// Group messages by stream type
|
|
758
|
-
const stdoutMessages: string[] = [];
|
|
759
|
-
const stderrMessages: string[] = [];
|
|
643
|
+
private flushBuffer(): void {
|
|
644
|
+
if (this.outputBuffer.length === 0) return;
|
|
760
645
|
|
|
761
|
-
|
|
762
|
-
//
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
646
|
+
try {
|
|
647
|
+
// Group by stream type for efficiency
|
|
648
|
+
const stdoutMessages: string[] = [];
|
|
649
|
+
const stderrMessages: string[] = [];
|
|
650
|
+
|
|
651
|
+
for (const message of this.outputBuffer) {
|
|
652
|
+
// Determine stream based on message content (simple heuristic)
|
|
653
|
+
if (message.includes('ERROR') || message.includes('FATAL')) {
|
|
654
|
+
stderrMessages.push(message);
|
|
655
|
+
} else {
|
|
656
|
+
stdoutMessages.push(message);
|
|
657
|
+
}
|
|
767
658
|
}
|
|
768
|
-
}
|
|
769
659
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
if (stdoutMessages.length > 0 && process.stdout.writable) {
|
|
660
|
+
// Write to streams
|
|
661
|
+
if (stdoutMessages.length > 0) {
|
|
773
662
|
process.stdout.write(stdoutMessages.join(''));
|
|
774
663
|
}
|
|
775
|
-
if (stderrMessages.length > 0
|
|
664
|
+
if (stderrMessages.length > 0) {
|
|
776
665
|
process.stderr.write(stderrMessages.join(''));
|
|
777
666
|
}
|
|
778
667
|
} catch {
|
|
779
|
-
// Fallback to console if
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
668
|
+
// Fallback to console methods if stream write fails
|
|
669
|
+
for (const message of this.outputBuffer) {
|
|
670
|
+
if (message.includes('ERROR') || message.includes('FATAL')) {
|
|
671
|
+
// eslint-disable-next-line no-console
|
|
672
|
+
console.error(message.trim());
|
|
673
|
+
} else {
|
|
674
|
+
// eslint-disable-next-line no-console
|
|
675
|
+
console.log(message.trim());
|
|
676
|
+
}
|
|
785
677
|
}
|
|
786
678
|
}
|
|
787
679
|
|
|
788
|
-
//
|
|
680
|
+
// Reset buffer
|
|
789
681
|
this.outputBuffer.length = 0;
|
|
790
682
|
this.bufferSize = 0;
|
|
791
|
-
|
|
792
|
-
// Clear timeout
|
|
793
|
-
if (this.flushTimeout) {
|
|
794
|
-
clearTimeout(this.flushTimeout);
|
|
795
|
-
this.flushTimeout = null;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
// Emergency flush for buffer overflow protection
|
|
800
|
-
private forceFlushBuffer(): void {
|
|
801
|
-
if (this.outputBuffer.length === 0) return;
|
|
802
|
-
|
|
803
|
-
try {
|
|
804
|
-
const message = this.outputBuffer.join('');
|
|
805
|
-
process.stdout.write(message);
|
|
806
|
-
} catch (error) {
|
|
807
|
-
// Emergency fallback - write individual messages
|
|
808
|
-
for (const msg of this.outputBuffer) {
|
|
809
|
-
try {
|
|
810
|
-
process.stdout.write(msg);
|
|
811
|
-
} catch {
|
|
812
|
-
// If even this fails, give up on this batch
|
|
813
|
-
break;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
} finally {
|
|
817
|
-
this.outputBuffer.length = 0;
|
|
818
|
-
this.bufferSize = 0;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
// Safe stringify with circular reference detection
|
|
823
|
-
private safeStringify(obj: any, maxDepth = 3): string {
|
|
824
|
-
const seen = new WeakSet();
|
|
825
|
-
|
|
826
|
-
const stringify = (value: any, depth: number): any => {
|
|
827
|
-
if (depth > maxDepth) return '[Max Depth Reached]';
|
|
828
|
-
if (value === null || typeof value !== 'object') return value;
|
|
829
|
-
if (seen.has(value)) return '[Circular Reference]';
|
|
830
|
-
|
|
831
|
-
seen.add(value);
|
|
832
|
-
|
|
833
|
-
if (Array.isArray(value)) {
|
|
834
|
-
return value.map(item => stringify(item, depth + 1));
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
const result: any = {};
|
|
838
|
-
for (const [key, val] of Object.entries(value)) {
|
|
839
|
-
if (typeof val !== 'function') {
|
|
840
|
-
// Skip functions
|
|
841
|
-
result[key] = stringify(val, depth + 1);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
return result;
|
|
845
|
-
};
|
|
846
|
-
|
|
847
|
-
try {
|
|
848
|
-
return JSON.stringify(stringify(obj, 0));
|
|
849
|
-
} catch (error) {
|
|
850
|
-
return '[Stringify Error]';
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
// Configuration validation
|
|
855
|
-
private validateOptions(options: LoggerOptions): LoggerOptions {
|
|
856
|
-
const validated = { ...options };
|
|
857
|
-
|
|
858
|
-
// Validate log level
|
|
859
|
-
const validLevels = ['debug', 'info', 'warn', 'error', 'fatal'];
|
|
860
|
-
if (validated.level && !validLevels.includes(validated.level)) {
|
|
861
|
-
console.warn(`[MoroLogger] Invalid log level: ${validated.level}, defaulting to 'info'`);
|
|
862
|
-
validated.level = 'info';
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// Validate max entries
|
|
866
|
-
if (validated.maxEntries !== undefined) {
|
|
867
|
-
if (validated.maxEntries < 1 || validated.maxEntries > 100000) {
|
|
868
|
-
console.warn(
|
|
869
|
-
`[MoroLogger] Invalid maxEntries: ${validated.maxEntries}, defaulting to 1000`
|
|
870
|
-
);
|
|
871
|
-
validated.maxEntries = 1000;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
// Validate buffer size
|
|
876
|
-
if (validated.maxBufferSize !== undefined) {
|
|
877
|
-
if (validated.maxBufferSize < 10 || validated.maxBufferSize > 10000) {
|
|
878
|
-
console.warn(
|
|
879
|
-
`[MoroLogger] Invalid maxBufferSize: ${validated.maxBufferSize}, defaulting to 1000`
|
|
880
|
-
);
|
|
881
|
-
validated.maxBufferSize = 1000;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
return validated;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
// Error handling methods
|
|
889
|
-
private handleOutputError(outputName: string, error: any): void {
|
|
890
|
-
// Could implement output retry logic, circuit breaker, etc.
|
|
891
|
-
// For now, just track the error
|
|
892
|
-
if (!this.metrics.outputErrors) {
|
|
893
|
-
this.metrics.outputErrors = {};
|
|
894
|
-
}
|
|
895
|
-
this.metrics.outputErrors[outputName] = (this.metrics.outputErrors[outputName] || 0) + 1;
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
private emergencyConsoleWrite(entry: LogEntry): void {
|
|
899
|
-
const message = `${entry.timestamp.toISOString()} ${entry.level.toUpperCase()} ${entry.message}`;
|
|
900
|
-
try {
|
|
901
|
-
if (entry.level === 'error' || entry.level === 'fatal') {
|
|
902
|
-
process.stderr.write(`[EMERGENCY] ${message}\n`);
|
|
903
|
-
} else {
|
|
904
|
-
process.stdout.write(`[EMERGENCY] ${message}\n`);
|
|
905
|
-
}
|
|
906
|
-
} catch {
|
|
907
|
-
// If even emergency write fails, there's nothing more we can do
|
|
908
|
-
}
|
|
909
683
|
}
|
|
910
684
|
|
|
911
685
|
// Force flush streams (useful for shutdown)
|
|
@@ -920,40 +694,28 @@ export class MoroLogger implements Logger {
|
|
|
920
694
|
this.flushBuffer();
|
|
921
695
|
|
|
922
696
|
try {
|
|
923
|
-
// Force flush streams
|
|
697
|
+
// Force flush streams
|
|
924
698
|
if (process.stdout.writable) {
|
|
925
|
-
process.stdout.
|
|
699
|
+
process.stdout.end();
|
|
926
700
|
}
|
|
927
701
|
if (process.stderr.writable) {
|
|
928
|
-
process.stderr.
|
|
702
|
+
process.stderr.end();
|
|
929
703
|
}
|
|
930
704
|
} catch {
|
|
931
705
|
// Ignore flush errors
|
|
932
706
|
}
|
|
933
707
|
}
|
|
934
708
|
|
|
935
|
-
//
|
|
936
|
-
public
|
|
937
|
-
//
|
|
938
|
-
this.isDestroyed = true;
|
|
939
|
-
|
|
940
|
-
// Clear any remaining timeouts
|
|
709
|
+
// Cleanup method to clear all timeouts and handles
|
|
710
|
+
public cleanup(): void {
|
|
711
|
+
// Clear any pending flush timeout
|
|
941
712
|
if (this.flushTimeout) {
|
|
942
713
|
clearTimeout(this.flushTimeout);
|
|
943
714
|
this.flushTimeout = null;
|
|
944
715
|
}
|
|
945
716
|
|
|
946
|
-
// Flush any remaining
|
|
717
|
+
// Flush any remaining output
|
|
947
718
|
this.flushBuffer();
|
|
948
|
-
|
|
949
|
-
// Clear outputs and filters
|
|
950
|
-
this.outputs.clear();
|
|
951
|
-
this.filters.clear();
|
|
952
|
-
|
|
953
|
-
// Clear history
|
|
954
|
-
this.history.length = 0;
|
|
955
|
-
this.historyIndex = 0;
|
|
956
|
-
this.historySize = 0;
|
|
957
719
|
}
|
|
958
720
|
}
|
|
959
721
|
|
|
@@ -969,6 +731,33 @@ export const logger = new MoroLogger({
|
|
|
969
731
|
format: (process.env.LOG_FORMAT as any) || 'pretty',
|
|
970
732
|
});
|
|
971
733
|
|
|
734
|
+
// Add cleanup handlers for Jest and other test runners
|
|
735
|
+
if (typeof process !== 'undefined') {
|
|
736
|
+
// Cleanup on process exit
|
|
737
|
+
process.on('beforeExit', () => {
|
|
738
|
+
logger.cleanup();
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
process.on('SIGINT', () => {
|
|
742
|
+
logger.cleanup();
|
|
743
|
+
process.exit(0);
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
process.on('SIGTERM', () => {
|
|
747
|
+
logger.cleanup();
|
|
748
|
+
process.exit(0);
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
// For Jest and other test runners - cleanup on uncaught exceptions
|
|
752
|
+
process.on('uncaughtException', () => {
|
|
753
|
+
logger.cleanup();
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
process.on('unhandledRejection', () => {
|
|
757
|
+
logger.cleanup();
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
972
761
|
/**
|
|
973
762
|
* Configure the global logger with new settings
|
|
974
763
|
* This allows runtime configuration of the logger
|
|
@@ -981,14 +770,6 @@ export function configureGlobalLogger(options: Partial<LoggerOptions>): void {
|
|
|
981
770
|
// For now, focusing on level which is the most critical
|
|
982
771
|
}
|
|
983
772
|
|
|
984
|
-
/**
|
|
985
|
-
* Destroy the global logger and clean up resources (for testing)
|
|
986
|
-
* @internal
|
|
987
|
-
*/
|
|
988
|
-
export function destroyGlobalLogger(): void {
|
|
989
|
-
logger.destroy();
|
|
990
|
-
}
|
|
991
|
-
|
|
992
773
|
/**
|
|
993
774
|
* Apply logging configuration from the config system and/or createApp options
|
|
994
775
|
*/
|