glasswork 0.9.1 → 0.10.0
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/core/bootstrap.d.ts +2 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/bootstrap.js +121 -44
- package/dist/core/bootstrap.js.map +1 -1
- package/dist/core/types.d.ts +53 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/http/error-handler.d.ts +28 -3
- package/dist/http/error-handler.d.ts.map +1 -1
- package/dist/http/error-handler.js +97 -22
- package/dist/http/error-handler.js.map +1 -1
- package/dist/http/errors.d.ts +52 -22
- package/dist/http/errors.d.ts.map +1 -1
- package/dist/http/errors.js +62 -42
- package/dist/http/errors.js.map +1 -1
- package/dist/http/route-helpers.d.ts +13 -0
- package/dist/http/route-helpers.d.ts.map +1 -1
- package/dist/http/route-helpers.js +15 -3
- package/dist/http/route-helpers.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/list-query/builder.d.ts +5 -0
- package/dist/list-query/builder.d.ts.map +1 -1
- package/dist/list-query/builder.js +34 -1
- package/dist/list-query/builder.js.map +1 -1
- package/dist/list-query/schema-helpers.d.ts +2 -2
- package/dist/list-query/schema-helpers.js +2 -2
- package/dist/list-query/schema-helpers.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +28 -18
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/observability/exception-tracking.d.ts +214 -0
- package/dist/observability/exception-tracking.d.ts.map +1 -0
- package/dist/observability/exception-tracking.js +238 -0
- package/dist/observability/exception-tracking.js.map +1 -0
- package/dist/observability/pino-logger.d.ts +108 -0
- package/dist/observability/pino-logger.d.ts.map +1 -0
- package/dist/observability/pino-logger.js +158 -0
- package/dist/observability/pino-logger.js.map +1 -0
- package/dist/observability/request-context.d.ts +105 -0
- package/dist/observability/request-context.d.ts.map +1 -0
- package/dist/observability/request-context.js +115 -0
- package/dist/observability/request-context.js.map +1 -0
- package/dist/openapi/openapi.d.ts.map +1 -1
- package/dist/openapi/openapi.js +3 -1
- package/dist/openapi/openapi.js.map +1 -1
- package/dist/utils/environment.d.ts +2 -1
- package/dist/utils/environment.d.ts.map +1 -1
- package/dist/utils/environment.js +11 -2
- package/dist/utils/environment.js.map +1 -1
- package/dist/utils/logger.d.ts +43 -9
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +60 -16
- package/dist/utils/logger.js.map +1 -1
- package/package.json +6 -1
- package/dist/authorization/ability-middleware.d.ts +0 -61
- package/dist/authorization/ability-middleware.d.ts.map +0 -1
- package/dist/authorization/ability-middleware.js +0 -74
- package/dist/authorization/ability-middleware.js.map +0 -1
- package/dist/authorization/index.d.ts +0 -46
- package/dist/authorization/index.d.ts.map +0 -1
- package/dist/authorization/index.js +0 -46
- package/dist/authorization/index.js.map +0 -1
- package/dist/authorization/route-helpers.d.ts +0 -106
- package/dist/authorization/route-helpers.d.ts.map +0 -1
- package/dist/authorization/route-helpers.js +0 -136
- package/dist/authorization/route-helpers.js.map +0 -1
- package/dist/authorization/service-proxy.d.ts +0 -59
- package/dist/authorization/service-proxy.d.ts.map +0 -1
- package/dist/authorization/service-proxy.js +0 -110
- package/dist/authorization/service-proxy.js.map +0 -1
- package/dist/authorization/types.d.ts +0 -58
- package/dist/authorization/types.d.ts.map +0 -1
- package/dist/authorization/types.js +0 -7
- package/dist/authorization/types.js.map +0 -1
- package/dist/hooks/authorization-hook.d.ts +0 -100
- package/dist/hooks/authorization-hook.d.ts.map +0 -1
- package/dist/hooks/authorization-hook.js +0 -93
- package/dist/hooks/authorization-hook.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -54
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -55
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/service-hooks.d.ts +0 -82
- package/dist/hooks/service-hooks.d.ts.map +0 -1
- package/dist/hooks/service-hooks.js +0 -158
- package/dist/hooks/service-hooks.js.map +0 -1
- package/dist/hooks/types.d.ts +0 -151
- package/dist/hooks/types.d.ts.map +0 -1
- package/dist/hooks/types.js +0 -2
- package/dist/hooks/types.js.map +0 -1
- package/dist/openapi/hooks.d.ts +0 -14
- package/dist/openapi/hooks.d.ts.map +0 -1
- package/dist/openapi/hooks.js +0 -83
- package/dist/openapi/hooks.js.map +0 -1
- package/dist/openapi/openapi-transformer.d.ts +0 -13
- package/dist/openapi/openapi-transformer.d.ts.map +0 -1
- package/dist/openapi/openapi-transformer.js +0 -87
- package/dist/openapi/openapi-transformer.js.map +0 -1
- package/dist/utils/pagination.d.ts +0 -48
- package/dist/utils/pagination.d.ts.map +0 -1
- package/dist/utils/pagination.js +0 -42
- package/dist/utils/pagination.js.map +0 -1
- package/dist/utils/serialize-dates.d.ts +0 -27
- package/dist/utils/serialize-dates.d.ts.map +0 -1
- package/dist/utils/serialize-dates.js +0 -39
- package/dist/utils/serialize-dates.js.map +0 -1
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { isTest } from '../utils/environment.js';
|
|
2
|
+
import { getRequestContext, setRequestUser } from './request-context.js';
|
|
3
|
+
/**
|
|
4
|
+
* Default exception tracking configuration.
|
|
5
|
+
* Only tracks 5xx server errors by default.
|
|
6
|
+
*/
|
|
7
|
+
export const defaultTrackStatusCodes = (statusCode) => statusCode >= 500;
|
|
8
|
+
/**
|
|
9
|
+
* Determine if an exception should be tracked based on explicit flag and status code rules.
|
|
10
|
+
*
|
|
11
|
+
* @param explicitTrack - Explicit track flag from exception (overrides status code rules)
|
|
12
|
+
* @param statusCode - HTTP status code
|
|
13
|
+
* @param config - Tracking configuration
|
|
14
|
+
* @returns true if the exception should be tracked
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export function shouldTrackException(explicitTrack, statusCode, config) {
|
|
19
|
+
// Explicit tracking flag takes precedence
|
|
20
|
+
if (explicitTrack !== undefined) {
|
|
21
|
+
return explicitTrack;
|
|
22
|
+
}
|
|
23
|
+
// Otherwise use status code rules
|
|
24
|
+
return config.trackStatusCodes(statusCode);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create middleware for exception tracking context setup.
|
|
28
|
+
*
|
|
29
|
+
* This middleware sets up request context for exception tracking.
|
|
30
|
+
* Actual exception capture is handled in the error handler.
|
|
31
|
+
*
|
|
32
|
+
* @param config - Exception tracking configuration
|
|
33
|
+
* @returns Hono middleware handler
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { createExceptionTrackingMiddleware } from 'glasswork';
|
|
38
|
+
*
|
|
39
|
+
* app.use(createExceptionTrackingMiddleware({
|
|
40
|
+
* tracker,
|
|
41
|
+
* trackStatusCodes: (status) => status >= 500,
|
|
42
|
+
* }));
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function createExceptionTrackingMiddleware(config) {
|
|
46
|
+
return async (c, next) => {
|
|
47
|
+
// Get request context from AsyncLocalStorage if available
|
|
48
|
+
const ctx = getRequestContext();
|
|
49
|
+
const requestId = ctx?.requestId ?? c.get('requestId');
|
|
50
|
+
config.tracker.setContext('request', {
|
|
51
|
+
id: requestId,
|
|
52
|
+
method: c.req.method,
|
|
53
|
+
path: c.req.path,
|
|
54
|
+
userAgent: c.req.header('user-agent'),
|
|
55
|
+
});
|
|
56
|
+
await next();
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a CloudWatch-based exception tracker.
|
|
61
|
+
*
|
|
62
|
+
* This tracker publishes custom metrics to CloudWatch for error monitoring.
|
|
63
|
+
* It's a zero-dependency option that works natively with AWS infrastructure.
|
|
64
|
+
*
|
|
65
|
+
* **Features:**
|
|
66
|
+
* - Publishes `ErrorCount` metric on each exception
|
|
67
|
+
* - Includes dimensions for path, error type, status code
|
|
68
|
+
* - Optional console logging for CloudWatch Logs visibility
|
|
69
|
+
* - Works without additional dependencies in Lambda
|
|
70
|
+
*
|
|
71
|
+
* **CloudWatch Alarms:**
|
|
72
|
+
* Create alarms on the `ErrorCount` metric to get notified of issues.
|
|
73
|
+
*
|
|
74
|
+
* @param options - Configuration options
|
|
75
|
+
* @returns Exception tracker instance
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* import { createCloudWatchTracker, bootstrap } from 'glasswork';
|
|
80
|
+
*
|
|
81
|
+
* const tracker = createCloudWatchTracker({
|
|
82
|
+
* namespace: 'MyApp/Errors',
|
|
83
|
+
* dimensions: {
|
|
84
|
+
* environment: process.env.NODE_ENV,
|
|
85
|
+
* service: 'user-api',
|
|
86
|
+
* },
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* const { app } = await bootstrap(AppModule, {
|
|
90
|
+
* exceptionTracking: { tracker },
|
|
91
|
+
* });
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export function createCloudWatchTracker(options = {}) {
|
|
95
|
+
const { namespace = 'Application/Errors', dimensions = {}, cloudWatchClient, logToConsole = !isTest(), } = options;
|
|
96
|
+
// Lazy-load AWS SDK to avoid bundling if not used
|
|
97
|
+
let cwClient = cloudWatchClient ?? null;
|
|
98
|
+
async function getClient() {
|
|
99
|
+
if (cwClient)
|
|
100
|
+
return cwClient;
|
|
101
|
+
try {
|
|
102
|
+
// Dynamic import to avoid bundling if not used
|
|
103
|
+
const { CloudWatchClient } = await import('@aws-sdk/client-cloudwatch');
|
|
104
|
+
cwClient = new CloudWatchClient({});
|
|
105
|
+
return cwClient;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// AWS SDK not available - log only
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function putMetric(metricName, value, extraDimensions = {}) {
|
|
113
|
+
const client = await getClient();
|
|
114
|
+
if (!client)
|
|
115
|
+
return;
|
|
116
|
+
try {
|
|
117
|
+
const { PutMetricDataCommand } = await import('@aws-sdk/client-cloudwatch');
|
|
118
|
+
const allDimensions = { ...dimensions, ...extraDimensions };
|
|
119
|
+
const dimensionArray = Object.entries(allDimensions).map(([Name, Value]) => ({
|
|
120
|
+
Name,
|
|
121
|
+
Value,
|
|
122
|
+
}));
|
|
123
|
+
await client.send(new PutMetricDataCommand({
|
|
124
|
+
Namespace: namespace,
|
|
125
|
+
MetricData: [
|
|
126
|
+
{
|
|
127
|
+
MetricName: metricName,
|
|
128
|
+
Value: value,
|
|
129
|
+
Unit: 'Count',
|
|
130
|
+
Timestamp: new Date(),
|
|
131
|
+
Dimensions: dimensionArray,
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
// Don't throw - exception tracking should never break the app
|
|
138
|
+
if (logToConsole) {
|
|
139
|
+
console.error('[CloudWatchTracker] Failed to put metric:', err);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const contextStore = {};
|
|
144
|
+
return {
|
|
145
|
+
captureException(error, context) {
|
|
146
|
+
const ctx = getRequestContext();
|
|
147
|
+
if (logToConsole) {
|
|
148
|
+
console.error('[Exception]', {
|
|
149
|
+
error: error.message,
|
|
150
|
+
stack: error.stack,
|
|
151
|
+
requestId: ctx?.requestId ?? context?.requestId,
|
|
152
|
+
userId: ctx?.userId,
|
|
153
|
+
...context,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// Publish metric to CloudWatch
|
|
157
|
+
void putMetric('ErrorCount', 1, {
|
|
158
|
+
ErrorType: error.name || 'Error',
|
|
159
|
+
Path: String(context?.path ?? ctx?.path ?? 'unknown'),
|
|
160
|
+
StatusCode: String(context?.statusCode ?? 500),
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
captureMessage(message, level, context) {
|
|
164
|
+
const ctx = getRequestContext();
|
|
165
|
+
if (logToConsole) {
|
|
166
|
+
const logFn = level === 'error' ? console.error : level === 'warning' ? console.warn : console.log;
|
|
167
|
+
logFn(`[${level.toUpperCase()}]`, message, {
|
|
168
|
+
requestId: ctx?.requestId,
|
|
169
|
+
userId: ctx?.userId,
|
|
170
|
+
...context,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (level === 'error') {
|
|
174
|
+
void putMetric('ErrorCount', 1, {
|
|
175
|
+
ErrorType: 'Message',
|
|
176
|
+
Path: String(context?.path ?? ctx?.path ?? 'unknown'),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
setUser(user) {
|
|
181
|
+
// Set user in request context (preferred method)
|
|
182
|
+
// User info will be available via getRequestContext() for logging and tracking
|
|
183
|
+
setRequestUser(user.id);
|
|
184
|
+
},
|
|
185
|
+
setContext(key, data) {
|
|
186
|
+
contextStore[key] = data;
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Create a console-only exception tracker for development.
|
|
192
|
+
*
|
|
193
|
+
* This tracker logs exceptions to the console without sending to external services.
|
|
194
|
+
* Useful for local development and testing.
|
|
195
|
+
*
|
|
196
|
+
* @returns Exception tracker instance
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```typescript
|
|
200
|
+
* import { createConsoleTracker, bootstrap, isDevelopment } from 'glasswork';
|
|
201
|
+
*
|
|
202
|
+
* const tracker = isDevelopment()
|
|
203
|
+
* ? createConsoleTracker()
|
|
204
|
+
* : createCloudWatchTracker({ namespace: 'MyApp/Errors' });
|
|
205
|
+
*
|
|
206
|
+
* const { app } = await bootstrap(AppModule, {
|
|
207
|
+
* exceptionTracking: { tracker },
|
|
208
|
+
* });
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export function createConsoleTracker() {
|
|
212
|
+
return {
|
|
213
|
+
captureException(error, context) {
|
|
214
|
+
const ctx = getRequestContext();
|
|
215
|
+
console.error('[Exception]', {
|
|
216
|
+
error: error.message,
|
|
217
|
+
stack: error.stack,
|
|
218
|
+
requestId: ctx?.requestId ?? context?.requestId,
|
|
219
|
+
...context,
|
|
220
|
+
});
|
|
221
|
+
},
|
|
222
|
+
captureMessage(message, level, context) {
|
|
223
|
+
const ctx = getRequestContext();
|
|
224
|
+
const logFn = level === 'error' ? console.error : level === 'warning' ? console.warn : console.log;
|
|
225
|
+
logFn(`[${level.toUpperCase()}]`, message, {
|
|
226
|
+
requestId: ctx?.requestId,
|
|
227
|
+
...context,
|
|
228
|
+
});
|
|
229
|
+
},
|
|
230
|
+
setUser() {
|
|
231
|
+
// No-op for console tracker
|
|
232
|
+
},
|
|
233
|
+
setContext() {
|
|
234
|
+
// No-op for console tracker
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=exception-tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exception-tracking.js","sourceRoot":"","sources":["../../src/observability/exception-tracking.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { Logger } from '../utils/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Pino logger interface - subset of pino.Logger for type compatibility.
|
|
5
|
+
* This allows the framework to work with Pino without a hard dependency.
|
|
6
|
+
*/
|
|
7
|
+
export interface PinoLogger {
|
|
8
|
+
level: string;
|
|
9
|
+
debug: (obj: object, msg?: string) => void;
|
|
10
|
+
info: (obj: object, msg?: string) => void;
|
|
11
|
+
warn: (obj: object, msg?: string) => void;
|
|
12
|
+
error: (obj: object, msg?: string) => void;
|
|
13
|
+
child: (bindings: Record<string, unknown>) => PinoLogger;
|
|
14
|
+
flush?: () => void | Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Options for creating a context-aware Pino logger.
|
|
18
|
+
*/
|
|
19
|
+
export interface ContextAwarePinoOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Base Pino logger instance.
|
|
22
|
+
* Create with: `pino({ level: 'info' })`
|
|
23
|
+
*/
|
|
24
|
+
pino: PinoLogger;
|
|
25
|
+
/**
|
|
26
|
+
* Service name to include in all logs.
|
|
27
|
+
* Useful for filtering logs by service in CloudWatch.
|
|
28
|
+
*/
|
|
29
|
+
service?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a context-aware logger that automatically includes request context.
|
|
33
|
+
*
|
|
34
|
+
* This logger wraps a Pino instance and automatically injects:
|
|
35
|
+
* - requestId (from AsyncLocalStorage)
|
|
36
|
+
* - userId (if set via setRequestUser)
|
|
37
|
+
* - service name
|
|
38
|
+
*
|
|
39
|
+
* The logger uses Pino's structured logging format, optimized for CloudWatch Logs Insights.
|
|
40
|
+
*
|
|
41
|
+
* @param options - Configuration options
|
|
42
|
+
* @returns Logger instance compatible with Glasswork's Logger interface
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* import pino from 'pino';
|
|
47
|
+
* import { createContextAwarePinoLogger } from 'glasswork';
|
|
48
|
+
*
|
|
49
|
+
* const logger = createContextAwarePinoLogger({
|
|
50
|
+
* pino: pino({ level: 'info' }),
|
|
51
|
+
* service: 'user-service',
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* // In your service (requestId automatically included!)
|
|
55
|
+
* logger.info('Creating user', { email: 'test@example.com' });
|
|
56
|
+
* // Output: {"level":"info","requestId":"abc-123","service":"user-service","msg":"Creating user","email":"test@example.com"}
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function createContextAwarePinoLogger(options: ContextAwarePinoOptions): Logger;
|
|
60
|
+
/**
|
|
61
|
+
* Create HTTP request logging middleware for Pino.
|
|
62
|
+
*
|
|
63
|
+
* This middleware logs HTTP requests with:
|
|
64
|
+
* - requestId
|
|
65
|
+
* - method, path, status
|
|
66
|
+
* - duration (ms)
|
|
67
|
+
* - userId (if authenticated)
|
|
68
|
+
*
|
|
69
|
+
* @param pino - Pino logger instance
|
|
70
|
+
* @returns Hono middleware handler
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import pino from 'pino';
|
|
75
|
+
* import { createPinoHttpMiddleware } from 'glasswork';
|
|
76
|
+
*
|
|
77
|
+
* const logger = pino({ level: 'info' });
|
|
78
|
+
* app.use(createPinoHttpMiddleware(logger));
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function createPinoHttpMiddleware(pino: PinoLogger): MiddlewareHandler;
|
|
82
|
+
/**
|
|
83
|
+
* Default Pino configuration optimized for AWS Lambda.
|
|
84
|
+
*
|
|
85
|
+
* Features:
|
|
86
|
+
* - JSON output (CloudWatch Logs Insights compatible)
|
|
87
|
+
* - Minimal formatting overhead
|
|
88
|
+
* - Fast serialization
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* import pino from 'pino';
|
|
93
|
+
* import { lambdaPinoConfig } from 'glasswork';
|
|
94
|
+
*
|
|
95
|
+
* const logger = pino(lambdaPinoConfig);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare const lambdaPinoConfig: {
|
|
99
|
+
level: string;
|
|
100
|
+
formatters: {
|
|
101
|
+
level: (label: string) => {
|
|
102
|
+
level: string;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
transport: undefined;
|
|
106
|
+
base: undefined;
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=pino-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pino-logger.d.ts","sourceRoot":"","sources":["../../src/observability/pino-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,UAAU,CAAC;IACzD,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,IAAI,EAAE,UAAU,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CA2DrF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,iBAAiB,CA8B5E;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB;;;uBAIV,MAAM;;;;;;CAMxB,CAAC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { getRequestContext } from './request-context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a context-aware logger that automatically includes request context.
|
|
4
|
+
*
|
|
5
|
+
* This logger wraps a Pino instance and automatically injects:
|
|
6
|
+
* - requestId (from AsyncLocalStorage)
|
|
7
|
+
* - userId (if set via setRequestUser)
|
|
8
|
+
* - service name
|
|
9
|
+
*
|
|
10
|
+
* The logger uses Pino's structured logging format, optimized for CloudWatch Logs Insights.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Configuration options
|
|
13
|
+
* @returns Logger instance compatible with Glasswork's Logger interface
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import pino from 'pino';
|
|
18
|
+
* import { createContextAwarePinoLogger } from 'glasswork';
|
|
19
|
+
*
|
|
20
|
+
* const logger = createContextAwarePinoLogger({
|
|
21
|
+
* pino: pino({ level: 'info' }),
|
|
22
|
+
* service: 'user-service',
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // In your service (requestId automatically included!)
|
|
26
|
+
* logger.info('Creating user', { email: 'test@example.com' });
|
|
27
|
+
* // Output: {"level":"info","requestId":"abc-123","service":"user-service","msg":"Creating user","email":"test@example.com"}
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function createContextAwarePinoLogger(options) {
|
|
31
|
+
const { pino, service } = options;
|
|
32
|
+
function getBindings() {
|
|
33
|
+
const ctx = getRequestContext();
|
|
34
|
+
const bindings = {};
|
|
35
|
+
if (ctx?.requestId) {
|
|
36
|
+
bindings.requestId = ctx.requestId;
|
|
37
|
+
}
|
|
38
|
+
if (ctx?.userId) {
|
|
39
|
+
bindings.userId = ctx.userId;
|
|
40
|
+
}
|
|
41
|
+
if (service) {
|
|
42
|
+
bindings.service = service;
|
|
43
|
+
}
|
|
44
|
+
// Include custom context
|
|
45
|
+
if (ctx?.custom) {
|
|
46
|
+
Object.assign(bindings, ctx.custom);
|
|
47
|
+
}
|
|
48
|
+
return bindings;
|
|
49
|
+
}
|
|
50
|
+
function createLogObject(_msg, meta) {
|
|
51
|
+
const bindings = getBindings();
|
|
52
|
+
let obj = { ...bindings };
|
|
53
|
+
// Handle meta arguments
|
|
54
|
+
for (const item of meta) {
|
|
55
|
+
if (item && typeof item === 'object' && !Array.isArray(item)) {
|
|
56
|
+
obj = { ...obj, ...item };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return obj;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
debug(msg, ...meta) {
|
|
63
|
+
pino.debug(createLogObject(msg, meta), msg);
|
|
64
|
+
},
|
|
65
|
+
info(msg, ...meta) {
|
|
66
|
+
pino.info(createLogObject(msg, meta), msg);
|
|
67
|
+
},
|
|
68
|
+
warn(msg, ...meta) {
|
|
69
|
+
pino.warn(createLogObject(msg, meta), msg);
|
|
70
|
+
},
|
|
71
|
+
error(msg, ...meta) {
|
|
72
|
+
pino.error(createLogObject(msg, meta), msg);
|
|
73
|
+
},
|
|
74
|
+
child(bindings) {
|
|
75
|
+
return createContextAwarePinoLogger({
|
|
76
|
+
pino: pino.child(bindings),
|
|
77
|
+
service,
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create HTTP request logging middleware for Pino.
|
|
84
|
+
*
|
|
85
|
+
* This middleware logs HTTP requests with:
|
|
86
|
+
* - requestId
|
|
87
|
+
* - method, path, status
|
|
88
|
+
* - duration (ms)
|
|
89
|
+
* - userId (if authenticated)
|
|
90
|
+
*
|
|
91
|
+
* @param pino - Pino logger instance
|
|
92
|
+
* @returns Hono middleware handler
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* import pino from 'pino';
|
|
97
|
+
* import { createPinoHttpMiddleware } from 'glasswork';
|
|
98
|
+
*
|
|
99
|
+
* const logger = pino({ level: 'info' });
|
|
100
|
+
* app.use(createPinoHttpMiddleware(logger));
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export function createPinoHttpMiddleware(pino) {
|
|
104
|
+
return async (c, next) => {
|
|
105
|
+
const start = Date.now();
|
|
106
|
+
await next();
|
|
107
|
+
const duration = Date.now() - start;
|
|
108
|
+
const ctx = getRequestContext();
|
|
109
|
+
const logObject = {
|
|
110
|
+
requestId: ctx?.requestId,
|
|
111
|
+
method: c.req.method,
|
|
112
|
+
path: c.req.path,
|
|
113
|
+
status: c.res.status,
|
|
114
|
+
duration,
|
|
115
|
+
};
|
|
116
|
+
if (ctx?.userId) {
|
|
117
|
+
logObject.userId = ctx.userId;
|
|
118
|
+
}
|
|
119
|
+
// Use appropriate log level based on status
|
|
120
|
+
if (c.res.status >= 500) {
|
|
121
|
+
pino.error(logObject, 'HTTP Request');
|
|
122
|
+
}
|
|
123
|
+
else if (c.res.status >= 400) {
|
|
124
|
+
pino.warn(logObject, 'HTTP Request');
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
pino.info(logObject, 'HTTP Request');
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Default Pino configuration optimized for AWS Lambda.
|
|
133
|
+
*
|
|
134
|
+
* Features:
|
|
135
|
+
* - JSON output (CloudWatch Logs Insights compatible)
|
|
136
|
+
* - Minimal formatting overhead
|
|
137
|
+
* - Fast serialization
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* import pino from 'pino';
|
|
142
|
+
* import { lambdaPinoConfig } from 'glasswork';
|
|
143
|
+
*
|
|
144
|
+
* const logger = pino(lambdaPinoConfig);
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export const lambdaPinoConfig = {
|
|
148
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
149
|
+
// Use safe formatters that work in Lambda
|
|
150
|
+
formatters: {
|
|
151
|
+
level: (label) => ({ level: label }),
|
|
152
|
+
},
|
|
153
|
+
// Disable pretty printing
|
|
154
|
+
transport: undefined,
|
|
155
|
+
// Disable pid/hostname for smaller logs
|
|
156
|
+
base: undefined,
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=pino-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pino-logger.js","sourceRoot":"","sources":["../../src/observability/pino-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import type { MiddlewareHandler } from 'hono';
|
|
3
|
+
/**
|
|
4
|
+
* Request context stored in AsyncLocalStorage.
|
|
5
|
+
* Available anywhere in your code during a request lifecycle.
|
|
6
|
+
*/
|
|
7
|
+
export interface RequestContext {
|
|
8
|
+
/** Unique request identifier for correlation */
|
|
9
|
+
requestId: string;
|
|
10
|
+
/** HTTP method */
|
|
11
|
+
method: string;
|
|
12
|
+
/** Request path */
|
|
13
|
+
path: string;
|
|
14
|
+
/** Optional user ID (set via setUser) */
|
|
15
|
+
userId?: string;
|
|
16
|
+
/** Custom context data */
|
|
17
|
+
custom: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* AsyncLocalStorage instance for request context.
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare const requestContextStorage: AsyncLocalStorage<RequestContext>;
|
|
24
|
+
/**
|
|
25
|
+
* Get the current request context.
|
|
26
|
+
* Returns undefined if called outside a request lifecycle.
|
|
27
|
+
*
|
|
28
|
+
* @returns Current request context or undefined
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* import { getRequestContext } from 'glasswork';
|
|
33
|
+
*
|
|
34
|
+
* function someUtility() {
|
|
35
|
+
* const ctx = getRequestContext();
|
|
36
|
+
* if (ctx) {
|
|
37
|
+
* console.log('Request ID:', ctx.requestId);
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function getRequestContext(): RequestContext | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Get the current request ID.
|
|
45
|
+
* Returns undefined if called outside a request lifecycle.
|
|
46
|
+
*
|
|
47
|
+
* This is a convenience function for the common case of just needing the request ID.
|
|
48
|
+
*
|
|
49
|
+
* @returns Current request ID or undefined
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* import { getRequestId } from 'glasswork';
|
|
54
|
+
*
|
|
55
|
+
* class UserService {
|
|
56
|
+
* async create(data: CreateUserDto) {
|
|
57
|
+
* const requestId = getRequestId();
|
|
58
|
+
* this.logger.info({ requestId, email: data.email }, 'Creating user');
|
|
59
|
+
* // ...
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function getRequestId(): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Set user information in the current request context.
|
|
67
|
+
* Useful for correlating logs and errors with users after authentication.
|
|
68
|
+
*
|
|
69
|
+
* @param userId - User identifier
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { setRequestUser } from 'glasswork';
|
|
74
|
+
*
|
|
75
|
+
* // In auth middleware
|
|
76
|
+
* const user = await validateToken(token);
|
|
77
|
+
* setRequestUser(user.id);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function setRequestUser(userId: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* Set custom context data for the current request.
|
|
83
|
+
* Useful for adding business-specific context to logs.
|
|
84
|
+
*
|
|
85
|
+
* @param key - Context key
|
|
86
|
+
* @param value - Context value
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* import { setRequestContext } from 'glasswork';
|
|
91
|
+
*
|
|
92
|
+
* // Add tenant ID for multi-tenant apps
|
|
93
|
+
* setRequestContext('tenantId', tenant.id);
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function setRequestContextValue(key: string, value: unknown): void;
|
|
97
|
+
/**
|
|
98
|
+
* Middleware that initializes AsyncLocalStorage request context.
|
|
99
|
+
* Applied automatically by bootstrap when using the built-in logger.
|
|
100
|
+
*
|
|
101
|
+
* @returns Hono middleware handler
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
export declare function createRequestContextMiddleware(): MiddlewareHandler;
|
|
105
|
+
//# sourceMappingURL=request-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/observability/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,mCAA0C,CAAC;AAE7E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKnD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAKxE;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,IAAI,iBAAiB,CAelE"}
|