yinzerflow 0.4.4 → 0.5.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/README.md +31 -26
- package/docs/configuration/configuration.md +815 -0
- package/docs/core/core-concepts.md +801 -0
- package/docs/core/error-handling.md +391 -153
- package/docs/core/logging.md +426 -68
- package/docs/modules/body-parsing.md +561 -0
- package/docs/modules/cors.md +369 -0
- package/docs/modules/index.md +125 -0
- package/docs/modules/ip-security.md +280 -0
- package/docs/modules/rate-limiting.md +795 -0
- package/index.d.ts +278 -76
- package/index.js +18 -18
- package/index.js.map +17 -8
- package/package.json +5 -3
- package/docs/configuration/advanced-configuration-options.md +0 -302
- package/docs/configuration/configuration-patterns.md +0 -500
- package/docs/core/context.md +0 -230
- package/docs/core/examples.md +0 -444
- package/docs/core/request.md +0 -161
- package/docs/core/response.md +0 -212
- package/docs/core/routes.md +0 -720
- package/docs/quick-reference.md +0 -346
- package/docs/security/body-parsing.md +0 -296
- package/docs/security/cors.md +0 -189
- package/docs/security/ip-security.md +0 -234
- package/docs/security/security-overview.md +0 -282
- package/docs/start-here.md +0 -184
package/docs/core/logging.md
CHANGED
|
@@ -1,117 +1,405 @@
|
|
|
1
|
-
# Logging
|
|
1
|
+
# 📖 Logging
|
|
2
2
|
|
|
3
|
-
YinzerFlow provides a flexible logging system with built-in Pittsburgh personality and
|
|
3
|
+
YinzerFlow provides a flexible logging system with built-in Pittsburgh personality, performance tracking, and support for custom logger implementations.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
For detailed configuration examples and patterns, see [Configuration Guide](../configuration/configuration.md).
|
|
6
|
+
|
|
7
|
+
# ⚙️ Usage
|
|
8
|
+
|
|
9
|
+
## 🎛️ Settings
|
|
10
|
+
|
|
11
|
+
### Log Level — @default <span style="color: #2ecc71">`'info'`</span>
|
|
12
|
+
|
|
13
|
+
Minimum log level to output messages.
|
|
6
14
|
|
|
7
15
|
```typescript
|
|
8
|
-
import {
|
|
16
|
+
import { createLogger } from 'yinzerflow';
|
|
9
17
|
|
|
10
18
|
const logger = createLogger({
|
|
11
|
-
|
|
12
|
-
logLevel: 'info'
|
|
19
|
+
logLevel: 'info' // 'off', 'error', 'warn', 'info'
|
|
13
20
|
});
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
networkLogs: true
|
|
19
|
-
});
|
|
22
|
+
logger.info('This will be logged');
|
|
23
|
+
logger.warn('This will be logged');
|
|
24
|
+
logger.error('This will be logged');
|
|
20
25
|
```
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
<aside>
|
|
28
|
+
|
|
29
|
+
Options: `'off' | 'error' | 'warn' | 'info'`
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| `networkLogs` | `boolean` | `false` | Enable nginx-style network request logging |
|
|
30
|
-
| `networkLogger` | `Logger` | `undefined` | Custom logger for network logs (can be same as `logger` or different) |
|
|
31
|
+
- `'off'`: No logging at all
|
|
32
|
+
- `'error'`: Only errors
|
|
33
|
+
- `'warn'`: Warnings and errors
|
|
34
|
+
- `'info'`: All messages (most verbose)
|
|
35
|
+
</aside>
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
### Prefix — @default <span style="color: #2ecc71">`'YINZER'`</span>
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
Prefix for log messages to identify different components.
|
|
35
40
|
|
|
36
41
|
```typescript
|
|
37
|
-
import {
|
|
42
|
+
import { createLogger } from 'yinzerflow';
|
|
43
|
+
|
|
44
|
+
const dbLogger = createLogger({
|
|
45
|
+
prefix: 'DATABASE',
|
|
46
|
+
logLevel: 'error'
|
|
47
|
+
});
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
log.warn('Deprecated feature used');
|
|
42
|
-
log.error('Operation failed');
|
|
49
|
+
dbLogger.error('Connection failed');
|
|
50
|
+
// Output: [DATABASE] ❌ [timestamp] [ERROR] Connection failed - aw jeez
|
|
43
51
|
```
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
<aside>
|
|
54
|
+
|
|
55
|
+
Options: `string`
|
|
56
|
+
|
|
57
|
+
- Default: `'YINZER'`
|
|
58
|
+
- Used to identify different components or modules
|
|
59
|
+
- Appears in all log messages as `[PREFIX]`
|
|
60
|
+
</aside>
|
|
61
|
+
|
|
62
|
+
### Custom Logger — @default <span style="color: #2ecc71">`undefined`</span>
|
|
63
|
+
|
|
64
|
+
Custom logger implementation for integration with external logging systems.
|
|
46
65
|
|
|
47
66
|
```typescript
|
|
48
|
-
import {
|
|
67
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
49
68
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
69
|
+
// Winston logger implementation
|
|
70
|
+
const winstonLogger = {
|
|
71
|
+
info: (...args) => winston.info(args.join(' ')),
|
|
72
|
+
warn: (...args) => winston.warn(args.join(' ')),
|
|
73
|
+
error: (...args) => winston.error(args.join(' '))
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const app = new YinzerFlow({
|
|
77
|
+
port: 3000,
|
|
78
|
+
logger: winstonLogger
|
|
53
79
|
});
|
|
80
|
+
```
|
|
54
81
|
|
|
55
|
-
|
|
56
|
-
|
|
82
|
+
<aside>
|
|
83
|
+
|
|
84
|
+
Options: `Logger | undefined`
|
|
85
|
+
|
|
86
|
+
- Custom logger must implement `info`, `warn`, `error` methods
|
|
87
|
+
- Each method accepts variable arguments
|
|
88
|
+
- Methods should not return values (void)
|
|
89
|
+
- Falls back to built-in logger if undefined
|
|
90
|
+
</aside>
|
|
91
|
+
|
|
92
|
+
### Network Logs — @default <span style="color: #e74c3c">`false`</span>
|
|
93
|
+
|
|
94
|
+
Enable nginx-style network request logging.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { YinzerFlow } from 'yinzerflow';
|
|
98
|
+
|
|
99
|
+
const app = new YinzerFlow({
|
|
100
|
+
port: 3000,
|
|
101
|
+
networkLogs: true // Enable network request logging
|
|
102
|
+
});
|
|
57
103
|
```
|
|
58
104
|
|
|
59
|
-
|
|
105
|
+
<aside>
|
|
106
|
+
|
|
107
|
+
Options: `boolean`
|
|
108
|
+
|
|
109
|
+
- `false`: No network logging (default)
|
|
110
|
+
- `true`: Enable nginx-style request/response logging
|
|
111
|
+
- Separate from application logging
|
|
112
|
+
- Can use different logger instance
|
|
113
|
+
</aside>
|
|
114
|
+
|
|
115
|
+
# ✨ Best Practices
|
|
116
|
+
|
|
117
|
+
- **Use appropriate log levels** - error for failures, warn for issues, info for status
|
|
118
|
+
- **Create component-specific loggers** - Use different prefixes for different modules
|
|
119
|
+
- **Integrate with external systems** - Use custom loggers for Winston, Pino, etc.
|
|
120
|
+
- **Enable network logs in development** - Use `networkLogs: true` for debugging
|
|
121
|
+
- **Use table logging for structured data** - Use `log.table()` for arrays and objects
|
|
122
|
+
- **Avoid logging sensitive data** - Be careful with passwords, tokens, etc.
|
|
123
|
+
|
|
124
|
+
# 💻 Examples
|
|
125
|
+
|
|
126
|
+
### Production API
|
|
127
|
+
|
|
128
|
+
**Use Case:** Production API with structured logging and external log management
|
|
129
|
+
|
|
130
|
+
**Description:** Production-ready logging with Winston integration, structured JSON output, and comprehensive error tracking for monitoring and debugging.
|
|
60
131
|
|
|
61
132
|
```typescript
|
|
62
133
|
import { YinzerFlow, createLogger } from 'yinzerflow';
|
|
134
|
+
import winston from 'winston';
|
|
135
|
+
|
|
136
|
+
// Production Winston logger
|
|
137
|
+
const winstonLogger = winston.createLogger({
|
|
138
|
+
level: 'info',
|
|
139
|
+
format: winston.format.combine(
|
|
140
|
+
winston.format.timestamp(),
|
|
141
|
+
winston.format.errors({ stack: true }),
|
|
142
|
+
winston.format.json()
|
|
143
|
+
),
|
|
144
|
+
transports: [
|
|
145
|
+
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
|
146
|
+
new winston.transports.File({ filename: 'combined.log' }),
|
|
147
|
+
new winston.transports.Console({
|
|
148
|
+
format: winston.format.simple()
|
|
149
|
+
})
|
|
150
|
+
]
|
|
151
|
+
});
|
|
63
152
|
|
|
64
|
-
|
|
153
|
+
// Custom logger implementation
|
|
154
|
+
const customLogger = {
|
|
155
|
+
info: (...args) => winstonLogger.info(args.join(' ')),
|
|
156
|
+
warn: (...args) => winstonLogger.warn(args.join(' ')),
|
|
157
|
+
error: (...args) => winstonLogger.error(args.join(' '))
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Component-specific loggers
|
|
161
|
+
const dbLogger = createLogger({
|
|
162
|
+
prefix: 'DATABASE',
|
|
163
|
+
logLevel: 'error',
|
|
164
|
+
logger: customLogger
|
|
165
|
+
});
|
|
65
166
|
|
|
66
|
-
const
|
|
167
|
+
const authLogger = createLogger({
|
|
168
|
+
prefix: 'AUTH',
|
|
169
|
+
logLevel: 'warn',
|
|
170
|
+
logger: customLogger
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const apiLogger = createLogger({
|
|
174
|
+
prefix: 'API',
|
|
175
|
+
logLevel: 'info',
|
|
176
|
+
logger: customLogger
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const app = new YinzerFlow({
|
|
67
180
|
port: 3000,
|
|
68
|
-
logger,
|
|
181
|
+
logger: customLogger,
|
|
69
182
|
networkLogs: true,
|
|
70
|
-
networkLogger:
|
|
183
|
+
networkLogger: customLogger
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Database operations
|
|
187
|
+
const connectToDatabase = async () => {
|
|
188
|
+
try {
|
|
189
|
+
await database.connect();
|
|
190
|
+
dbLogger.info('Database connection established');
|
|
191
|
+
} catch (error) {
|
|
192
|
+
dbLogger.error('Database connection failed', error);
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// Authentication operations
|
|
198
|
+
const validateToken = async (token: string) => {
|
|
199
|
+
try {
|
|
200
|
+
const user = await jwt.verify(token);
|
|
201
|
+
authLogger.info('Token validated successfully', { userId: user.id });
|
|
202
|
+
return user;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
authLogger.warn('Token validation failed', { token: token.substring(0, 10) + '...' });
|
|
205
|
+
throw new Error('Invalid token');
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// API operations
|
|
210
|
+
app.get('/api/users', async (ctx) => {
|
|
211
|
+
try {
|
|
212
|
+
apiLogger.info('Fetching users', {
|
|
213
|
+
requestId: ctx.state.requestId,
|
|
214
|
+
ipAddress: ctx.request.ipAddress
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const users = await getAllUsers();
|
|
218
|
+
|
|
219
|
+
apiLogger.info('Users fetched successfully', {
|
|
220
|
+
count: users.length,
|
|
221
|
+
requestId: ctx.state.requestId
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return { users };
|
|
225
|
+
} catch (error) {
|
|
226
|
+
apiLogger.error('Failed to fetch users', {
|
|
227
|
+
error: error.message,
|
|
228
|
+
requestId: ctx.state.requestId
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
ctx.response.setStatusCode(500);
|
|
232
|
+
return { error: 'Internal server error' };
|
|
233
|
+
}
|
|
71
234
|
});
|
|
72
235
|
|
|
73
|
-
//
|
|
236
|
+
// Error handling with logging
|
|
237
|
+
app.onError(async (ctx, error) => {
|
|
238
|
+
apiLogger.error('Unhandled error', {
|
|
239
|
+
error: error.message,
|
|
240
|
+
stack: error.stack,
|
|
241
|
+
requestId: ctx.state.requestId,
|
|
242
|
+
method: ctx.request.method,
|
|
243
|
+
path: ctx.request.path,
|
|
244
|
+
ipAddress: ctx.request.ipAddress
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
ctx.response.setStatusCode(500);
|
|
248
|
+
return { error: 'Internal server error' };
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
await app.listen();
|
|
74
252
|
```
|
|
75
253
|
|
|
76
|
-
|
|
254
|
+
### Dev API
|
|
255
|
+
|
|
256
|
+
**Use Case:** Development server with detailed logging and debugging
|
|
77
257
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
- **Silent Operation**: Set `logLevel: 'off'` for environments with external log management
|
|
83
|
-
- **Script and Utility Logging**: Use shared `log` instance in standalone scripts and database seeds
|
|
258
|
+
**Description:** Development configuration with built-in logger, extensive debugging information, and table logging for easier development and testing.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { YinzerFlow, log, createLogger } from 'yinzerflow';
|
|
84
262
|
|
|
85
|
-
|
|
263
|
+
// Development loggers with different prefixes
|
|
264
|
+
const dbLogger = createLogger({
|
|
265
|
+
prefix: 'DATABASE',
|
|
266
|
+
logLevel: 'info'
|
|
267
|
+
});
|
|
86
268
|
|
|
87
|
-
|
|
269
|
+
const authLogger = createLogger({
|
|
270
|
+
prefix: 'AUTH',
|
|
271
|
+
logLevel: 'warn'
|
|
272
|
+
});
|
|
88
273
|
|
|
89
|
-
|
|
274
|
+
const apiLogger = createLogger({
|
|
275
|
+
prefix: 'API',
|
|
276
|
+
logLevel: 'info'
|
|
277
|
+
});
|
|
90
278
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
279
|
+
const app = new YinzerFlow({
|
|
280
|
+
port: 3000,
|
|
281
|
+
logLevel: 'info',
|
|
282
|
+
networkLogs: true // Enable network logging for debugging
|
|
283
|
+
});
|
|
95
284
|
|
|
96
|
-
|
|
285
|
+
// Database operations with detailed logging
|
|
286
|
+
const connectToDatabase = async () => {
|
|
287
|
+
try {
|
|
288
|
+
log.info('Connecting to database...');
|
|
289
|
+
await database.connect();
|
|
290
|
+
dbLogger.info('Database connection established');
|
|
291
|
+
|
|
292
|
+
// Log database configuration (non-sensitive)
|
|
293
|
+
dbLogger.info('Database configuration', {
|
|
294
|
+
host: process.env.DB_HOST,
|
|
295
|
+
port: process.env.DB_PORT,
|
|
296
|
+
database: process.env.DB_NAME
|
|
297
|
+
});
|
|
298
|
+
} catch (error) {
|
|
299
|
+
dbLogger.error('Database connection failed', error);
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// Authentication with detailed logging
|
|
305
|
+
const validateToken = async (token: string) => {
|
|
306
|
+
try {
|
|
307
|
+
authLogger.info('Validating token', { tokenLength: token.length });
|
|
308
|
+
const user = await jwt.verify(token);
|
|
309
|
+
authLogger.info('Token validated successfully', { userId: user.id });
|
|
310
|
+
return user;
|
|
311
|
+
} catch (error) {
|
|
312
|
+
authLogger.warn('Token validation failed', { error: error.message });
|
|
313
|
+
throw new Error('Invalid token');
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// API operations with comprehensive logging
|
|
318
|
+
app.get('/api/users', async (ctx) => {
|
|
319
|
+
try {
|
|
320
|
+
apiLogger.info('Fetching users', {
|
|
321
|
+
requestId: ctx.state.requestId,
|
|
322
|
+
ipAddress: ctx.request.ipAddress,
|
|
323
|
+
userAgent: ctx.request.headers['user-agent']
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
const users = await getAllUsers();
|
|
327
|
+
|
|
328
|
+
// Use table logging for structured data
|
|
329
|
+
apiLogger.table(users, 'Users fetched successfully');
|
|
330
|
+
|
|
331
|
+
apiLogger.info('Users fetched successfully', {
|
|
332
|
+
count: users.length,
|
|
333
|
+
requestId: ctx.state.requestId
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
return { users };
|
|
337
|
+
} catch (error) {
|
|
338
|
+
apiLogger.error('Failed to fetch users', {
|
|
339
|
+
error: error.message,
|
|
340
|
+
stack: error.stack,
|
|
341
|
+
requestId: ctx.state.requestId
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
ctx.response.setStatusCode(500);
|
|
345
|
+
return { error: 'Internal server error' };
|
|
346
|
+
}
|
|
347
|
+
});
|
|
97
348
|
|
|
98
|
-
|
|
349
|
+
// Debug route with extensive logging
|
|
350
|
+
app.get('/debug', async (ctx) => {
|
|
351
|
+
log.info('Debug route accessed');
|
|
352
|
+
|
|
353
|
+
// Log request details
|
|
354
|
+
apiLogger.info('Debug request details', {
|
|
355
|
+
method: ctx.request.method,
|
|
356
|
+
path: ctx.request.path,
|
|
357
|
+
headers: ctx.request.headers,
|
|
358
|
+
query: ctx.request.query,
|
|
359
|
+
params: ctx.request.params,
|
|
360
|
+
body: ctx.request.body,
|
|
361
|
+
ipAddress: ctx.request.ipAddress
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// Log state information
|
|
365
|
+
apiLogger.table(ctx.state, 'Request state');
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
message: 'Debug information logged',
|
|
369
|
+
timestamp: new Date().toISOString()
|
|
370
|
+
};
|
|
371
|
+
});
|
|
99
372
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
373
|
+
// Error handling with detailed logging
|
|
374
|
+
app.onError(async (ctx, error) => {
|
|
375
|
+
log.error('Unhandled error occurred', error);
|
|
376
|
+
|
|
377
|
+
apiLogger.error('Unhandled error details', {
|
|
378
|
+
error: error.message,
|
|
379
|
+
stack: error.stack,
|
|
380
|
+
requestId: ctx.state.requestId,
|
|
381
|
+
method: ctx.request.method,
|
|
382
|
+
path: ctx.request.path,
|
|
383
|
+
ipAddress: ctx.request.ipAddress,
|
|
384
|
+
headers: ctx.request.headers,
|
|
385
|
+
body: ctx.request.body
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
ctx.response.setStatusCode(500);
|
|
389
|
+
return { error: 'Internal server error' };
|
|
390
|
+
});
|
|
104
391
|
|
|
105
|
-
|
|
392
|
+
await app.listen();
|
|
393
|
+
```
|
|
106
394
|
|
|
107
|
-
|
|
395
|
+
## 🚀 Performance Notes
|
|
108
396
|
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
397
|
+
- **Early returns**: Log level checks prevent unnecessary processing when logging is disabled
|
|
398
|
+
- **Native console methods**: Uses built-in console methods for optimal performance
|
|
399
|
+
- **Minimal overhead**: Logging adds minimal overhead when disabled
|
|
400
|
+
- **Table optimization**: Table logging uses native console.table for efficient display
|
|
113
401
|
|
|
114
|
-
## Security
|
|
402
|
+
## 🔒 Security Notes
|
|
115
403
|
|
|
116
404
|
YinzerFlow implements several security measures for safe logging:
|
|
117
405
|
|
|
@@ -120,11 +408,81 @@ YinzerFlow implements several security measures for safe logging:
|
|
|
120
408
|
- **YinzerFlow Solution**: Uses native `console.log` formatting to prevent accidental serialization of sensitive objects
|
|
121
409
|
|
|
122
410
|
### 🛡️ Log Level Protection
|
|
123
|
-
- **Problem**: Verbose logging in production can impact performance and expose internal details
|
|
411
|
+
- **Problem**: Verbose logging in production can impact performance and expose internal details
|
|
124
412
|
- **YinzerFlow Solution**: Configurable log levels with early returns to minimize overhead when logging is disabled
|
|
125
413
|
|
|
126
414
|
### 🛡️ Logger Isolation
|
|
127
415
|
- **Problem**: Custom loggers could interfere with framework logging
|
|
128
416
|
- **YinzerFlow Solution**: Clean interface boundaries and isolated logger instances prevent conflicts
|
|
129
417
|
|
|
130
|
-
|
|
418
|
+
### 🛡️ Network Logging Security
|
|
419
|
+
- **Problem**: Network logs can expose sensitive request data
|
|
420
|
+
- **YinzerFlow Solution**: Network logging is separate and configurable, allowing selective logging
|
|
421
|
+
|
|
422
|
+
## 🔧 Troubleshooting
|
|
423
|
+
|
|
424
|
+
### Logs Not Appearing
|
|
425
|
+
- **Problem**: Log messages not showing up
|
|
426
|
+
- **Fix**: Check log level configuration
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
// ❌ Wrong - log level too high
|
|
430
|
+
const logger = createLogger({ logLevel: 'error' });
|
|
431
|
+
logger.info('This will not appear'); // Blocked by log level
|
|
432
|
+
|
|
433
|
+
// ✅ Correct - appropriate log level
|
|
434
|
+
const logger = createLogger({ logLevel: 'info' });
|
|
435
|
+
logger.info('This will appear'); // Will be logged
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Custom Logger Not Working
|
|
439
|
+
- **Problem**: Custom logger not being used
|
|
440
|
+
- **Fix**: Check logger interface implementation
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
// ❌ Wrong - missing required methods
|
|
444
|
+
const customLogger = {
|
|
445
|
+
info: (...args) => console.log(...args)
|
|
446
|
+
// Missing warn and error methods
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// ✅ Correct - implement all required methods
|
|
450
|
+
const customLogger = {
|
|
451
|
+
info: (...args) => console.log(...args),
|
|
452
|
+
warn: (...args) => console.warn(...args),
|
|
453
|
+
error: (...args) => console.error(...args)
|
|
454
|
+
};
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Network Logs Not Working
|
|
458
|
+
- **Problem**: Network request logs not appearing
|
|
459
|
+
- **Fix**: Enable network logging in configuration
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
// ❌ Wrong - network logging disabled
|
|
463
|
+
const app = new YinzerFlow({
|
|
464
|
+
port: 3000,
|
|
465
|
+
networkLogs: false // Disabled
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// ✅ Correct - enable network logging
|
|
469
|
+
const app = new YinzerFlow({
|
|
470
|
+
port: 3000,
|
|
471
|
+
networkLogs: true // Enabled
|
|
472
|
+
});
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Table Logging Not Working
|
|
476
|
+
- **Problem**: Table logs not displaying properly
|
|
477
|
+
- **Fix**: Use appropriate data types for table logging
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
// ❌ Wrong - primitive data
|
|
481
|
+
logger.table('string data'); // Not suitable for table display
|
|
482
|
+
|
|
483
|
+
// ✅ Correct - structured data
|
|
484
|
+
logger.table([
|
|
485
|
+
{ id: 1, name: 'John' },
|
|
486
|
+
{ id: 2, name: 'Jane' }
|
|
487
|
+
]); // Will display as table
|
|
488
|
+
```
|