@ranimontagna/agent-toolkit 0.1.4 → 0.1.5

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.
Files changed (30) hide show
  1. package/README.md +282 -277
  2. package/docs/assets/install-plan.svg +29 -0
  3. package/docs/assets/install-skill-packages.svg +31 -0
  4. package/docs/assets/install-status.svg +32 -0
  5. package/package.json +10 -9
  6. package/setup-agent-toolkit.sh +1 -1
  7. package/skills/backend/fastify-best-practices/LICENSE +21 -0
  8. package/skills/backend/fastify-best-practices/NOTICE.md +11 -0
  9. package/skills/backend/fastify-best-practices/SKILL.md +75 -0
  10. package/skills/backend/fastify-best-practices/rules/authentication.md +521 -0
  11. package/skills/backend/fastify-best-practices/rules/configuration.md +217 -0
  12. package/skills/backend/fastify-best-practices/rules/content-type.md +387 -0
  13. package/skills/backend/fastify-best-practices/rules/cors-security.md +445 -0
  14. package/skills/backend/fastify-best-practices/rules/database.md +320 -0
  15. package/skills/backend/fastify-best-practices/rules/decorators.md +416 -0
  16. package/skills/backend/fastify-best-practices/rules/deployment.md +423 -0
  17. package/skills/backend/fastify-best-practices/rules/error-handling.md +412 -0
  18. package/skills/backend/fastify-best-practices/rules/hooks.md +464 -0
  19. package/skills/backend/fastify-best-practices/rules/http-proxy.md +247 -0
  20. package/skills/backend/fastify-best-practices/rules/logging.md +402 -0
  21. package/skills/backend/fastify-best-practices/rules/performance.md +425 -0
  22. package/skills/backend/fastify-best-practices/rules/plugins.md +320 -0
  23. package/skills/backend/fastify-best-practices/rules/routes.md +467 -0
  24. package/skills/backend/fastify-best-practices/rules/schemas.md +585 -0
  25. package/skills/backend/fastify-best-practices/rules/serialization.md +475 -0
  26. package/skills/backend/fastify-best-practices/rules/testing.md +536 -0
  27. package/skills/backend/fastify-best-practices/rules/typescript.md +458 -0
  28. package/skills/backend/fastify-best-practices/rules/websockets.md +421 -0
  29. package/skills/backend/fastify-best-practices/tile.json +11 -0
  30. package/skills/core/agent-toolkit-maintainer/SKILL.md +16 -14
@@ -0,0 +1,402 @@
1
+ ---
2
+ name: logging
3
+ description: Logging with Pino in Fastify
4
+ metadata:
5
+ tags: logging, pino, debugging, observability
6
+ ---
7
+
8
+ # Logging with Pino
9
+
10
+ ## Built-in Pino Integration
11
+
12
+ Fastify uses Pino for high-performance logging:
13
+
14
+ ```typescript
15
+ import Fastify from 'fastify';
16
+
17
+ const app = Fastify({
18
+ logger: true, // Enable default logging
19
+ });
20
+
21
+ // Or with configuration
22
+ const app = Fastify({
23
+ logger: {
24
+ level: 'info',
25
+ transport: {
26
+ target: 'pino-pretty',
27
+ options: {
28
+ colorize: true,
29
+ },
30
+ },
31
+ },
32
+ });
33
+ ```
34
+
35
+ ## Log Levels
36
+
37
+ Available log levels (in order of severity):
38
+
39
+ ```typescript
40
+ app.log.trace('Detailed debugging');
41
+ app.log.debug('Debugging information');
42
+ app.log.info('General information');
43
+ app.log.warn('Warning messages');
44
+ app.log.error('Error messages');
45
+ app.log.fatal('Fatal errors');
46
+ ```
47
+
48
+ ## Request-Scoped Logging
49
+
50
+ Each request has its own logger with request context:
51
+
52
+ ```typescript
53
+ app.get('/users/:id', async (request) => {
54
+ // Logs include request ID automatically
55
+ request.log.info('Fetching user');
56
+
57
+ const user = await db.users.findById(request.params.id);
58
+
59
+ if (!user) {
60
+ request.log.warn({ userId: request.params.id }, 'User not found');
61
+ return { error: 'Not found' };
62
+ }
63
+
64
+ request.log.info({ userId: user.id }, 'User fetched');
65
+ return user;
66
+ });
67
+ ```
68
+
69
+ ## Structured Logging
70
+
71
+ Always use structured logging with objects:
72
+
73
+ ```typescript
74
+ // GOOD - structured, searchable
75
+ request.log.info({
76
+ action: 'user_created',
77
+ userId: user.id,
78
+ email: user.email,
79
+ }, 'User created successfully');
80
+
81
+ request.log.error({
82
+ err: error,
83
+ userId: request.params.id,
84
+ operation: 'fetch_user',
85
+ }, 'Failed to fetch user');
86
+
87
+ // BAD - unstructured, hard to parse
88
+ request.log.info(`User ${user.id} created with email ${user.email}`);
89
+ request.log.error(`Failed to fetch user: ${error.message}`);
90
+ ```
91
+
92
+ ## Logging Configuration by Environment
93
+
94
+ ```typescript
95
+ function getLoggerConfig() {
96
+ if (process.env.NODE_ENV === 'production') {
97
+ return {
98
+ level: 'info',
99
+ // JSON output for log aggregation
100
+ };
101
+ }
102
+
103
+ if (process.env.NODE_ENV === 'test') {
104
+ return false; // Disable logging in tests
105
+ }
106
+
107
+ // Development
108
+ return {
109
+ level: 'debug',
110
+ transport: {
111
+ target: 'pino-pretty',
112
+ options: {
113
+ colorize: true,
114
+ translateTime: 'HH:MM:ss Z',
115
+ ignore: 'pid,hostname',
116
+ },
117
+ },
118
+ };
119
+ }
120
+
121
+ const app = Fastify({
122
+ logger: getLoggerConfig(),
123
+ });
124
+ ```
125
+
126
+ ## Custom Serializers
127
+
128
+ Customize how objects are serialized:
129
+
130
+ ```typescript
131
+ const app = Fastify({
132
+ logger: {
133
+ level: 'info',
134
+ serializers: {
135
+ // Customize request serialization
136
+ req: (request) => ({
137
+ method: request.method,
138
+ url: request.url,
139
+ headers: {
140
+ host: request.headers.host,
141
+ 'user-agent': request.headers['user-agent'],
142
+ },
143
+ remoteAddress: request.ip,
144
+ }),
145
+
146
+ // Customize response serialization
147
+ res: (response) => ({
148
+ statusCode: response.statusCode,
149
+ }),
150
+
151
+ // Custom serializer for users
152
+ user: (user) => ({
153
+ id: user.id,
154
+ email: user.email,
155
+ // Exclude sensitive fields
156
+ }),
157
+ },
158
+ },
159
+ });
160
+
161
+ // Use custom serializer
162
+ request.log.info({ user: request.user }, 'User action');
163
+ ```
164
+
165
+ ## Redacting Sensitive Data
166
+
167
+ Prevent logging sensitive information:
168
+
169
+ ```typescript
170
+ import Fastify from 'fastify';
171
+
172
+ const app = Fastify({
173
+ logger: {
174
+ level: 'info',
175
+ redact: {
176
+ paths: [
177
+ 'req.headers.authorization',
178
+ 'req.headers.cookie',
179
+ 'body.password',
180
+ 'body.creditCard',
181
+ '*.password',
182
+ '*.secret',
183
+ '*.token',
184
+ ],
185
+ censor: '[REDACTED]',
186
+ },
187
+ },
188
+ });
189
+ ```
190
+
191
+ ## Child Loggers
192
+
193
+ Create child loggers with additional context:
194
+
195
+ ```typescript
196
+ app.addHook('onRequest', async (request) => {
197
+ // Add user context to all logs for this request
198
+ if (request.user) {
199
+ request.log = request.log.child({
200
+ userId: request.user.id,
201
+ userRole: request.user.role,
202
+ });
203
+ }
204
+ });
205
+
206
+ // Service-level child logger
207
+ const userService = {
208
+ log: app.log.child({ service: 'UserService' }),
209
+
210
+ async create(data) {
211
+ this.log.info({ email: data.email }, 'Creating user');
212
+ // ...
213
+ },
214
+ };
215
+ ```
216
+
217
+ ## Request Logging Configuration
218
+
219
+ Customize automatic request logging:
220
+
221
+ ```typescript
222
+ const app = Fastify({
223
+ logger: true,
224
+ disableRequestLogging: true, // Disable default request/response logs
225
+ });
226
+
227
+ // Custom request logging
228
+ app.addHook('onRequest', async (request) => {
229
+ request.log.info({
230
+ method: request.method,
231
+ url: request.url,
232
+ query: request.query,
233
+ }, 'Request received');
234
+ });
235
+
236
+ app.addHook('onResponse', async (request, reply) => {
237
+ request.log.info({
238
+ statusCode: reply.statusCode,
239
+ responseTime: reply.elapsedTime,
240
+ }, 'Request completed');
241
+ });
242
+ ```
243
+
244
+ ## Logging Errors
245
+
246
+ Properly log errors with stack traces:
247
+
248
+ ```typescript
249
+ app.setErrorHandler((error, request, reply) => {
250
+ // Log error with full details
251
+ request.log.error({
252
+ err: error, // Pino serializes error objects properly
253
+ url: request.url,
254
+ method: request.method,
255
+ body: request.body,
256
+ query: request.query,
257
+ }, 'Request error');
258
+
259
+ reply.code(error.statusCode || 500).send({
260
+ error: error.message,
261
+ });
262
+ });
263
+
264
+ // In handlers
265
+ app.get('/data', async (request) => {
266
+ try {
267
+ return await fetchData();
268
+ } catch (error) {
269
+ request.log.error({ err: error }, 'Failed to fetch data');
270
+ throw error;
271
+ }
272
+ });
273
+ ```
274
+
275
+ ## Log Destinations
276
+
277
+ Configure where logs are sent:
278
+
279
+ ```typescript
280
+ import { createWriteStream } from 'node:fs';
281
+
282
+ // File output
283
+ const app = Fastify({
284
+ logger: {
285
+ level: 'info',
286
+ stream: createWriteStream('./app.log'),
287
+ },
288
+ });
289
+
290
+ // Multiple destinations with pino.multistream
291
+ import pino from 'pino';
292
+
293
+ const streams = [
294
+ { stream: process.stdout },
295
+ { stream: createWriteStream('./app.log') },
296
+ { level: 'error', stream: createWriteStream('./error.log') },
297
+ ];
298
+
299
+ const app = Fastify({
300
+ logger: pino({ level: 'info' }, pino.multistream(streams)),
301
+ });
302
+ ```
303
+
304
+ ## Log Rotation
305
+
306
+ Use pino-roll for log rotation:
307
+
308
+ ```bash
309
+ node app.js | pino-roll --frequency daily --extension .log
310
+ ```
311
+
312
+ Or configure programmatically:
313
+
314
+ ```typescript
315
+ import { createStream } from 'rotating-file-stream';
316
+
317
+ const stream = createStream('app.log', {
318
+ size: '10M', // Rotate every 10MB
319
+ interval: '1d', // Rotate daily
320
+ compress: 'gzip',
321
+ path: './logs',
322
+ });
323
+
324
+ const app = Fastify({
325
+ logger: {
326
+ level: 'info',
327
+ stream,
328
+ },
329
+ });
330
+ ```
331
+
332
+ ## Log Aggregation
333
+
334
+ Format logs for aggregation services:
335
+
336
+ ```typescript
337
+ // For ELK Stack, Datadog, etc. - use default JSON format
338
+ const app = Fastify({
339
+ logger: {
340
+ level: 'info',
341
+ // Default JSON output works with most log aggregators
342
+ },
343
+ });
344
+
345
+ // Add service metadata
346
+ const app = Fastify({
347
+ logger: {
348
+ level: 'info',
349
+ base: {
350
+ service: 'user-api',
351
+ version: process.env.APP_VERSION,
352
+ environment: process.env.NODE_ENV,
353
+ },
354
+ },
355
+ });
356
+ ```
357
+
358
+ ## Request ID Tracking
359
+
360
+ Use request IDs for distributed tracing:
361
+
362
+ ```typescript
363
+ const app = Fastify({
364
+ logger: true,
365
+ requestIdHeader: 'x-request-id', // Use incoming header
366
+ genReqId: (request) => {
367
+ // Generate ID if not provided
368
+ return request.headers['x-request-id'] || crypto.randomUUID();
369
+ },
370
+ });
371
+
372
+ // Forward request ID to downstream services
373
+ app.addHook('onRequest', async (request) => {
374
+ request.requestId = request.id;
375
+ });
376
+
377
+ // Include in outgoing requests
378
+ const response = await fetch('http://other-service/api', {
379
+ headers: {
380
+ 'x-request-id': request.id,
381
+ },
382
+ });
383
+ ```
384
+
385
+ ## Performance Considerations
386
+
387
+ Pino is fast, but consider:
388
+
389
+ ```typescript
390
+ // Avoid string concatenation in log calls
391
+ // BAD
392
+ request.log.info('User ' + user.id + ' did ' + action);
393
+
394
+ // GOOD
395
+ request.log.info({ userId: user.id, action }, 'User action');
396
+
397
+ // Use appropriate log levels
398
+ // Don't log at info level in hot paths
399
+ if (app.log.isLevelEnabled('debug')) {
400
+ request.log.debug({ details: expensiveToCompute() }, 'Debug info');
401
+ }
402
+ ```