@noony-serverless/core 0.3.4 → 0.4.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 +199 -0
- package/build/core/containerPool.d.ts +129 -26
- package/build/core/containerPool.js +213 -68
- package/build/core/handler.d.ts +2 -2
- package/build/core/handler.js +6 -12
- package/build/core/index.d.ts +1 -0
- package/build/core/index.js +1 -0
- package/build/core/logger.d.ts +89 -1
- package/build/core/logger.js +136 -5
- package/build/core/telemetry/config.d.ts +331 -0
- package/build/core/telemetry/config.js +153 -0
- package/build/core/telemetry/index.d.ts +22 -0
- package/build/core/telemetry/index.js +45 -0
- package/build/core/telemetry/provider.d.ts +203 -0
- package/build/core/telemetry/provider.js +3 -0
- package/build/core/telemetry/providers/console-provider.d.ts +54 -0
- package/build/core/telemetry/providers/console-provider.js +124 -0
- package/build/core/telemetry/providers/index.d.ts +10 -0
- package/build/core/telemetry/providers/index.js +19 -0
- package/build/core/telemetry/providers/noop-provider.d.ts +51 -0
- package/build/core/telemetry/providers/noop-provider.js +67 -0
- package/build/core/telemetry/providers/opentelemetry-provider.d.ts +102 -0
- package/build/core/telemetry/providers/opentelemetry-provider.js +342 -0
- package/build/middlewares/bodyValidationMiddleware.js +1 -1
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +16 -8
- package/build/middlewares/dependencyInjectionMiddleware.js +31 -11
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +1 -1
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/FastAuthGuard.js +3 -2
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +7 -9
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +11 -32
- package/build/middlewares/index.d.ts +1 -0
- package/build/middlewares/index.js +1 -0
- package/build/middlewares/openTelemetryMiddleware.d.ts +162 -0
- package/build/middlewares/openTelemetryMiddleware.js +359 -0
- package/build/middlewares/rateLimitingMiddleware.js +16 -5
- package/build/utils/container.utils.js +4 -1
- package/build/utils/fastify-wrapper.d.ts +74 -0
- package/build/utils/fastify-wrapper.js +175 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.js +23 -1
- package/build/utils/otel.helper.d.ts +122 -0
- package/build/utils/otel.helper.js +258 -0
- package/build/utils/pubsub-trace.utils.d.ts +102 -0
- package/build/utils/pubsub-trace.utils.js +155 -0
- package/build/utils/wrapper-utils.d.ts +177 -0
- package/build/utils/wrapper-utils.js +236 -0
- package/package.json +61 -2
|
@@ -3,98 +3,243 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.containerPool = exports.ContainerPool = void 0;
|
|
4
4
|
const typedi_1 = require("typedi");
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Symbol used to mark services as "deleted" in request-local scope
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
const TOMBSTONE = Symbol('TOMBSTONE');
|
|
10
|
+
/**
|
|
11
|
+
* Hybrid Proxy Container Pool for serverless environments
|
|
12
|
+
*
|
|
13
|
+
* This implementation uses a zero-copy proxy pattern that provides:
|
|
14
|
+
* - Process Lifetime (Global): Services initialized once and shared across requests
|
|
15
|
+
* - Request Lifetime (Local): Services isolated per request with zero overhead
|
|
16
|
+
*
|
|
17
|
+
* Architecture:
|
|
18
|
+
* - Global Container: Singleton with process-lifetime services (DB, Logger, etc.)
|
|
19
|
+
* - Proxy Container: Lightweight wrapper per-request that shadows local overrides
|
|
20
|
+
* - Memory: O(1) per request (just the proxy + local overrides Map)
|
|
21
|
+
* - Performance: ~99% memory reduction vs traditional container pooling
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* Basic usage with global services:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Initialize global services once at startup
|
|
27
|
+
* containerPool.initializeGlobal([
|
|
28
|
+
* { id: 'Database', value: new DatabaseService() },
|
|
29
|
+
* { id: 'Logger', value: new LoggerService() }
|
|
30
|
+
* ]);
|
|
31
|
+
*
|
|
32
|
+
* // Per-request: Create lightweight proxy
|
|
33
|
+
* const container = containerPool.createProxyContainer();
|
|
34
|
+
* const db = container.get('Database'); // From global
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* Request-scoped services with local overrides:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Global services
|
|
41
|
+
* containerPool.initializeGlobal([
|
|
42
|
+
* { id: UserService, value: new UserService() }
|
|
43
|
+
* ]);
|
|
44
|
+
*
|
|
45
|
+
* // Per-request: Add request-scoped data
|
|
46
|
+
* const container = containerPool.createProxyContainer();
|
|
47
|
+
* container.set('RequestId', 'req-123'); // Local scope only
|
|
48
|
+
* container.set('CurrentUser', currentUser); // Local scope only
|
|
49
|
+
*
|
|
50
|
+
* const userService = container.get(UserService); // From global
|
|
51
|
+
* const requestId = container.get('RequestId'); // From local
|
|
52
|
+
* ```
|
|
8
53
|
*/
|
|
9
54
|
class ContainerPool {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
createdContainers = 0;
|
|
13
|
-
constructor(maxPoolSize = 10) {
|
|
14
|
-
this.maxPoolSize = maxPoolSize;
|
|
15
|
-
}
|
|
55
|
+
static globalContainer = null;
|
|
56
|
+
static useProxy = true;
|
|
16
57
|
/**
|
|
17
|
-
*
|
|
58
|
+
* Initialize the global container with process-lifetime services
|
|
59
|
+
* This should be called once at application startup
|
|
60
|
+
*
|
|
61
|
+
* @param services - Array of service definitions to register globally
|
|
62
|
+
* @param options - Configuration options
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* containerPool.initializeGlobal([
|
|
67
|
+
* { id: 'config', value: { apiUrl: 'https://api.example.com' } },
|
|
68
|
+
* { id: DatabaseService, value: new DatabaseService() },
|
|
69
|
+
* { id: LoggerService, value: new LoggerService() }
|
|
70
|
+
* ]);
|
|
71
|
+
* ```
|
|
18
72
|
*/
|
|
19
|
-
|
|
20
|
-
if (
|
|
21
|
-
|
|
73
|
+
static initializeGlobal(services = [], options) {
|
|
74
|
+
if (options?.useProxy !== undefined) {
|
|
75
|
+
this.useProxy = options.useProxy;
|
|
22
76
|
}
|
|
23
|
-
// Create
|
|
24
|
-
if (this.
|
|
25
|
-
this.
|
|
26
|
-
return typedi_1.Container.of();
|
|
77
|
+
// Create global container if not exists
|
|
78
|
+
if (!this.globalContainer) {
|
|
79
|
+
this.globalContainer = typedi_1.Container.of('__noony_global__');
|
|
27
80
|
}
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
81
|
+
// Register all global services
|
|
82
|
+
services.forEach((service) => {
|
|
83
|
+
this.globalContainer.set(service.id, service.value);
|
|
84
|
+
});
|
|
31
85
|
}
|
|
32
86
|
/**
|
|
33
|
-
*
|
|
87
|
+
* Create a lightweight proxy container for a single request
|
|
88
|
+
*
|
|
89
|
+
* The proxy provides:
|
|
90
|
+
* - Read access to global services (zero-copy)
|
|
91
|
+
* - Local overrides for request-scoped data
|
|
92
|
+
* - Automatic garbage collection (no manual cleanup needed)
|
|
93
|
+
*
|
|
94
|
+
* @returns A proxy container instance with request-local scope
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* async function handleRequest(req, res) {
|
|
99
|
+
* const container = containerPool.createProxyContainer();
|
|
100
|
+
*
|
|
101
|
+
* // Add request-specific data
|
|
102
|
+
* container.set('TraceId', req.headers['x-trace-id']);
|
|
103
|
+
*
|
|
104
|
+
* // Access global services
|
|
105
|
+
* const db = container.get(DatabaseService);
|
|
106
|
+
*
|
|
107
|
+
* // No cleanup needed - auto GC'd
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
34
110
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.resetContainer(container);
|
|
40
|
-
this.availableContainers.push(container);
|
|
111
|
+
static createProxyContainer() {
|
|
112
|
+
// Ensure global container is initialized
|
|
113
|
+
if (!this.globalContainer) {
|
|
114
|
+
this.initializeGlobal([]);
|
|
41
115
|
}
|
|
42
|
-
//
|
|
116
|
+
// Request-local overrides Map (only allocates if services are set)
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
+
const localOverrides = new Map();
|
|
119
|
+
// Create proxy that intercepts container operations
|
|
120
|
+
const proxyContainer = new Proxy(this.globalContainer, {
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
get(target, prop, receiver) {
|
|
123
|
+
// Intercept 'get' method for service resolution
|
|
124
|
+
if (prop === 'get') {
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
+
return function (serviceId) {
|
|
127
|
+
// 1. Check local overrides first (request scope)
|
|
128
|
+
if (localOverrides.has(serviceId)) {
|
|
129
|
+
const value = localOverrides.get(serviceId);
|
|
130
|
+
// Handle tombstone (service marked as "deleted")
|
|
131
|
+
if (value === TOMBSTONE) {
|
|
132
|
+
throw new Error(`Service "${String(serviceId)}" not found (removed in request scope)`);
|
|
133
|
+
}
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
// 2. Fallback to global container (process scope)
|
|
137
|
+
return target.get(serviceId);
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// Intercept 'set' method to write to local scope only
|
|
141
|
+
if (prop === 'set') {
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
143
|
+
return function (serviceId, value) {
|
|
144
|
+
// ✅ Write to local scope ONLY - never mutate global
|
|
145
|
+
localOverrides.set(serviceId, value);
|
|
146
|
+
return proxyContainer;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// Intercept 'remove' method to mark as deleted locally
|
|
150
|
+
if (prop === 'remove') {
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
return function (serviceId) {
|
|
153
|
+
// Mark service as "deleted" in local scope using tombstone
|
|
154
|
+
localOverrides.set(serviceId, TOMBSTONE);
|
|
155
|
+
return proxyContainer;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// Intercept 'reset' method to clear local overrides
|
|
159
|
+
if (prop === 'reset') {
|
|
160
|
+
return function () {
|
|
161
|
+
// Clear local overrides - revert to pure global state
|
|
162
|
+
localOverrides.clear();
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
// Intercept 'has' method for service existence check
|
|
166
|
+
if (prop === 'has') {
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
+
return function (serviceId) {
|
|
169
|
+
// Check local overrides first
|
|
170
|
+
if (localOverrides.has(serviceId)) {
|
|
171
|
+
const value = localOverrides.get(serviceId);
|
|
172
|
+
// Tombstone means service is "deleted"
|
|
173
|
+
return value !== TOMBSTONE;
|
|
174
|
+
}
|
|
175
|
+
// Fallback to global container
|
|
176
|
+
return target.has(serviceId);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// For all other properties/methods, delegate to global container
|
|
180
|
+
const value = Reflect.get(target, prop, receiver);
|
|
181
|
+
// Bind methods to target to preserve 'this' context
|
|
182
|
+
if (typeof value === 'function') {
|
|
183
|
+
return value.bind(target);
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
return proxyContainer;
|
|
43
189
|
}
|
|
44
190
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
191
|
+
* Create a middleware-compatible container factory
|
|
192
|
+
*
|
|
193
|
+
* @param services - Optional services to set as local overrides per-request
|
|
194
|
+
* @returns Function that creates proxy container with optional local services
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const handler = new Handler()
|
|
199
|
+
* .use(containerPool.asMiddleware([
|
|
200
|
+
* { id: 'RequestId', value: 'req-123' }
|
|
201
|
+
* ]))
|
|
202
|
+
* .handle(async (context) => {
|
|
203
|
+
* const requestId = context.container.get('RequestId');
|
|
204
|
+
* });
|
|
205
|
+
* ```
|
|
48
206
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
// If any issues occur, don't add back to pool
|
|
60
|
-
console.warn('Failed to reset container, discarding:', error);
|
|
61
|
-
}
|
|
207
|
+
static asMiddleware(services = []) {
|
|
208
|
+
return (existingContainer) => {
|
|
209
|
+
const container = existingContainer || this.createProxyContainer();
|
|
210
|
+
// Set local services if provided
|
|
211
|
+
services.forEach((service) => {
|
|
212
|
+
container.set(service.id, service.value);
|
|
213
|
+
});
|
|
214
|
+
return container;
|
|
215
|
+
};
|
|
62
216
|
}
|
|
63
217
|
/**
|
|
64
|
-
* Get
|
|
218
|
+
* Get statistics about the container pool
|
|
219
|
+
* (Maintained for backward compatibility)
|
|
65
220
|
*/
|
|
66
|
-
getStats() {
|
|
221
|
+
static getStats() {
|
|
67
222
|
return {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
maxSize: this.maxPoolSize,
|
|
223
|
+
useProxy: this.useProxy,
|
|
224
|
+
globalInitialized: this.globalContainer !== null,
|
|
71
225
|
};
|
|
72
226
|
}
|
|
73
227
|
/**
|
|
74
|
-
*
|
|
228
|
+
* Clear the global container (useful for testing)
|
|
229
|
+
* ⚠️ WARNING: This resets ALL global services
|
|
75
230
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const container = typedi_1.Container.of();
|
|
81
|
-
this.createdContainers++;
|
|
82
|
-
this.availableContainers.push(container);
|
|
83
|
-
}
|
|
231
|
+
static clear() {
|
|
232
|
+
if (this.globalContainer) {
|
|
233
|
+
this.globalContainer.reset();
|
|
234
|
+
this.globalContainer = null;
|
|
84
235
|
}
|
|
85
236
|
}
|
|
86
|
-
/**
|
|
87
|
-
* Clear all containers from the pool
|
|
88
|
-
*/
|
|
89
|
-
clear() {
|
|
90
|
-
this.availableContainers = [];
|
|
91
|
-
this.createdContainers = 0;
|
|
92
|
-
}
|
|
93
237
|
}
|
|
94
238
|
exports.ContainerPool = ContainerPool;
|
|
95
|
-
|
|
96
|
-
|
|
239
|
+
/**
|
|
240
|
+
* Global container pool instance
|
|
241
|
+
* Pre-initialized for immediate use in serverless environments
|
|
242
|
+
*/
|
|
243
|
+
const containerPool = ContainerPool;
|
|
97
244
|
exports.containerPool = containerPool;
|
|
98
|
-
// Warm up the pool for better cold start performance
|
|
99
|
-
containerPool.warmUp(3);
|
|
100
245
|
//# sourceMappingURL=containerPool.js.map
|
package/build/core/handler.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context,
|
|
1
|
+
import { Context, GenericRequest, GenericResponse } from './core';
|
|
2
2
|
/**
|
|
3
3
|
* Interface representing a base structure for middleware with optional lifecycle methods.
|
|
4
4
|
*
|
|
@@ -51,7 +51,7 @@ export declare class Handler<T = unknown, U = unknown> {
|
|
|
51
51
|
* Performance optimization: Pre-compute middleware arrays to avoid runtime array operations
|
|
52
52
|
*/
|
|
53
53
|
private precomputeMiddlewareArrays;
|
|
54
|
-
execute(req:
|
|
54
|
+
execute(req: GenericRequest<T>, res: GenericResponse): Promise<void>;
|
|
55
55
|
/**
|
|
56
56
|
* Execute before middlewares with optimized batching for independent middlewares
|
|
57
57
|
*/
|
package/build/core/handler.js
CHANGED
|
@@ -66,8 +66,8 @@ class Handler {
|
|
|
66
66
|
async execute(req, res) {
|
|
67
67
|
const genericReq = (0, core_1.adaptGCPRequest)(req);
|
|
68
68
|
const genericRes = (0, core_1.adaptGCPResponse)(res);
|
|
69
|
-
//
|
|
70
|
-
const container = containerPool_1.containerPool.
|
|
69
|
+
// Hybrid Proxy Container: Lightweight zero-copy container per request
|
|
70
|
+
const container = containerPool_1.containerPool.createProxyContainer();
|
|
71
71
|
const context = (0, core_1.createContext)(genericReq, genericRes, {
|
|
72
72
|
container,
|
|
73
73
|
});
|
|
@@ -83,10 +83,7 @@ class Handler {
|
|
|
83
83
|
// Execute error handlers using pre-computed array
|
|
84
84
|
await this.executeErrorMiddlewares(error, context);
|
|
85
85
|
}
|
|
86
|
-
finally
|
|
87
|
-
// Always return container to pool for reuse
|
|
88
|
-
containerPool_1.containerPool.release(container);
|
|
89
|
-
}
|
|
86
|
+
// No finally block needed - proxy container is auto-GC'd
|
|
90
87
|
}
|
|
91
88
|
/**
|
|
92
89
|
* Execute before middlewares with optimized batching for independent middlewares
|
|
@@ -124,8 +121,8 @@ class Handler {
|
|
|
124
121
|
* Framework-agnostic execute method that works with GenericRequest/GenericResponse
|
|
125
122
|
*/
|
|
126
123
|
async executeGeneric(req, res) {
|
|
127
|
-
//
|
|
128
|
-
const container = containerPool_1.containerPool.
|
|
124
|
+
// Hybrid Proxy Container: Lightweight zero-copy container per request
|
|
125
|
+
const container = containerPool_1.containerPool.createProxyContainer();
|
|
129
126
|
const context = (0, core_1.createContext)(req, res, {
|
|
130
127
|
container,
|
|
131
128
|
});
|
|
@@ -141,10 +138,7 @@ class Handler {
|
|
|
141
138
|
// Execute error handlers using pre-computed array
|
|
142
139
|
await this.executeErrorMiddlewares(error, context);
|
|
143
140
|
}
|
|
144
|
-
finally
|
|
145
|
-
// Always return container to pool for reuse
|
|
146
|
-
containerPool_1.containerPool.release(container);
|
|
147
|
-
}
|
|
141
|
+
// No finally block needed - proxy container is auto-GC'd
|
|
148
142
|
}
|
|
149
143
|
}
|
|
150
144
|
exports.Handler = Handler;
|
package/build/core/index.d.ts
CHANGED
package/build/core/index.js
CHANGED
|
@@ -20,5 +20,6 @@ __exportStar(require("./handler"), exports);
|
|
|
20
20
|
__exportStar(require("./logger"), exports);
|
|
21
21
|
__exportStar(require("./containerPool"), exports);
|
|
22
22
|
__exportStar(require("./performanceMonitor"), exports);
|
|
23
|
+
__exportStar(require("./telemetry"), exports);
|
|
23
24
|
__exportStar(require("../middlewares"), exports);
|
|
24
25
|
//# sourceMappingURL=index.js.map
|
package/build/core/logger.d.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
+
import type { Span, Context as OtelContext } from '@opentelemetry/api';
|
|
2
|
+
import { type OTELLogContext } from '../utils/otel.helper';
|
|
1
3
|
export interface LogOptions {
|
|
2
4
|
structuredData?: boolean;
|
|
3
5
|
[key: string]: boolean | string | number | object | undefined;
|
|
4
6
|
}
|
|
7
|
+
export interface LoggerConfig {
|
|
8
|
+
enableOTEL?: boolean;
|
|
9
|
+
structuredLogging?: boolean;
|
|
10
|
+
debugMode?: boolean;
|
|
11
|
+
}
|
|
5
12
|
declare class Logger {
|
|
6
13
|
private logDataPool;
|
|
7
14
|
private isDebugEnabled;
|
|
8
15
|
private timestampCache;
|
|
9
16
|
private lastTimestamp;
|
|
10
|
-
|
|
17
|
+
private enableOTEL;
|
|
18
|
+
private otelContext?;
|
|
19
|
+
constructor(config?: LoggerConfig);
|
|
11
20
|
/**
|
|
12
21
|
* Performance optimized timestamp generation with caching
|
|
13
22
|
* Cache timestamps for up to 1 second to reduce Date object creation
|
|
@@ -15,6 +24,7 @@ declare class Logger {
|
|
|
15
24
|
private getTimestamp;
|
|
16
25
|
/**
|
|
17
26
|
* Optimized log method with object pooling and lazy evaluation
|
|
27
|
+
* Includes automatic OTEL trace/span ID injection when enabled
|
|
18
28
|
*/
|
|
19
29
|
private log;
|
|
20
30
|
/**
|
|
@@ -28,6 +38,83 @@ declare class Logger {
|
|
|
28
38
|
* Performance monitoring method for internal framework use
|
|
29
39
|
*/
|
|
30
40
|
logPerformance(operation: string, duration: number, metadata?: Record<string, unknown>): void;
|
|
41
|
+
/**
|
|
42
|
+
* Create a child logger with a specific span context
|
|
43
|
+
*
|
|
44
|
+
* This method creates a new logger instance that will automatically include
|
|
45
|
+
* the trace/span IDs from the provided span in all log entries.
|
|
46
|
+
*
|
|
47
|
+
* Useful for passing logger instances to services/functions that need
|
|
48
|
+
* to log within a specific span context.
|
|
49
|
+
*
|
|
50
|
+
* @param span - OpenTelemetry span to attach to logs
|
|
51
|
+
* @returns New logger instance with span context
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { trace } from '@opentelemetry/api';
|
|
56
|
+
* import { logger } from '@noony-serverless/core';
|
|
57
|
+
*
|
|
58
|
+
* const tracer = trace.getTracer('my-service');
|
|
59
|
+
* const span = tracer.startSpan('process-order');
|
|
60
|
+
*
|
|
61
|
+
* const spanLogger = logger.withSpan(span);
|
|
62
|
+
* spanLogger.info('Processing order'); // Includes span's trace/span IDs
|
|
63
|
+
*
|
|
64
|
+
* span.end();
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
withSpan(span: Span): Logger;
|
|
68
|
+
/**
|
|
69
|
+
* Create a child logger with a specific OTEL context
|
|
70
|
+
*
|
|
71
|
+
* This method creates a new logger instance that will automatically include
|
|
72
|
+
* trace/span IDs from the provided OTEL context in all log entries.
|
|
73
|
+
*
|
|
74
|
+
* Useful when working with OTEL Context propagation (e.g., Pub/Sub messages).
|
|
75
|
+
*
|
|
76
|
+
* @param context - OpenTelemetry context to extract span from
|
|
77
|
+
* @returns New logger instance with context
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { context, propagation } from '@opentelemetry/api';
|
|
82
|
+
* import { logger } from '@noony-serverless/core';
|
|
83
|
+
*
|
|
84
|
+
* // Extract context from Pub/Sub message
|
|
85
|
+
* const extractedContext = propagation.extract(
|
|
86
|
+
* context.active(),
|
|
87
|
+
* message.attributes
|
|
88
|
+
* );
|
|
89
|
+
*
|
|
90
|
+
* const contextLogger = logger.withOTEL(extractedContext);
|
|
91
|
+
* contextLogger.info('Processing message'); // Includes trace/span IDs
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
withOTEL(otelContext: OtelContext): Logger;
|
|
95
|
+
/**
|
|
96
|
+
* Create a child logger with custom OTEL context
|
|
97
|
+
*
|
|
98
|
+
* This method creates a new logger instance with manually specified
|
|
99
|
+
* trace/span IDs. Useful when you have trace context from external sources.
|
|
100
|
+
*
|
|
101
|
+
* @param context - OTEL log context with trace/span IDs
|
|
102
|
+
* @returns New logger instance with custom context
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* import { logger } from '@noony-serverless/core';
|
|
107
|
+
*
|
|
108
|
+
* const customLogger = logger.withContext({
|
|
109
|
+
* traceId: '13ea7e3c2d3b4547baaa399062df1f2d',
|
|
110
|
+
* spanId: '1234567890123456',
|
|
111
|
+
* traceFlags: 1
|
|
112
|
+
* });
|
|
113
|
+
*
|
|
114
|
+
* customLogger.info('Custom trace context'); // Includes specified IDs
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
withContext(context: OTELLogContext): Logger;
|
|
31
118
|
/**
|
|
32
119
|
* Get logger statistics for monitoring
|
|
33
120
|
*/
|
|
@@ -35,6 +122,7 @@ declare class Logger {
|
|
|
35
122
|
poolSize: number;
|
|
36
123
|
maxPoolSize: number;
|
|
37
124
|
debugEnabled: boolean;
|
|
125
|
+
otelEnabled: boolean;
|
|
38
126
|
};
|
|
39
127
|
}
|
|
40
128
|
export declare const logger: Logger;
|