* refactor(logger): improve logger format * chore: improve log format * feat(logger): plugin-logger * feat: allow to download log files, close T-1917 * chore: update yarn.lock * chore: improve log format * fix: add maxsize params * chore: add userId field to request * chore: remove userId from request * chore: change userId in response * chore: change action in response * chore: add database logger * fix: build * fix: test * chore: solve conflicts * fix: escape delimiter in message * refactor: improve create logger api * chore: update app logger options * chore: remove colorize for json * fix: bug of data2tree * fix: test * chore: log * chore: remove GITHUB_ACTION check * fix: bug * chore: change version * fix: transports * fix: mockServer * chore: use new plugin settings api * fix: version * fix: build * feat: support logfmt * fix: build * fix: build * fix: test * chore: update config * fix: test * fix: bug * fix: test * fix: format * chore: update path * fix: build * fix: bug * chore: update comment * fix: allow to custom format * fix: package.json * fix: version * fix: bug
		
			
				
	
	
		
			72 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			72 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { getLoggerFilePath } from './config';
 | |
| import { AppLoggerOptions, createLogger } from './logger';
 | |
| import { pick } from 'lodash';
 | |
| const defaultRequestWhitelist = [
 | |
|   'action',
 | |
|   'header.x-role',
 | |
|   'header.x-hostname',
 | |
|   'header.x-timezone',
 | |
|   'header.x-locale',
 | |
|   'referer',
 | |
| ];
 | |
| const defaultResponseWhitelist = ['status'];
 | |
| 
 | |
| export const requestLogger = (appName: string, options?: AppLoggerOptions) => {
 | |
|   const requestLogger = createLogger({
 | |
|     dirname: getLoggerFilePath(appName),
 | |
|     filename: 'request',
 | |
|     ...(options?.request || {}),
 | |
|   });
 | |
|   return async (ctx, next) => {
 | |
|     const reqId = ctx.reqId;
 | |
|     const path = /^\/api\/(.+):(.+)/.exec(ctx.path);
 | |
|     const contextLogger = ctx.app.log.child({ reqId, module: path?.[1], submodule: path?.[2] });
 | |
|     // ctx.reqId = reqId;
 | |
|     ctx.logger = ctx.log = contextLogger;
 | |
|     const startTime = Date.now();
 | |
|     const requestInfo = {
 | |
|       method: ctx.method,
 | |
|       path: ctx.url,
 | |
|     };
 | |
|     requestLogger.info({
 | |
|       reqId,
 | |
|       message: 'request',
 | |
|       ...requestInfo,
 | |
|       req: pick(ctx.request.toJSON(), options?.request?.requestWhitelist || defaultRequestWhitelist),
 | |
|       action: ctx.action?.toJSON?.(),
 | |
|     });
 | |
|     let error: Error;
 | |
|     try {
 | |
|       await next();
 | |
|     } catch (e) {
 | |
|       error = e;
 | |
|     } finally {
 | |
|       const cost = Date.now() - startTime;
 | |
|       const status = ctx.status;
 | |
|       const info = {
 | |
|         reqId,
 | |
|         message: 'response',
 | |
|         ...requestInfo,
 | |
|         res: pick(ctx.response.toJSON(), options?.request?.responseWhitelist || defaultResponseWhitelist),
 | |
|         action: ctx.action?.toJSON?.(),
 | |
|         userId: ctx.auth?.user?.id,
 | |
|         status: ctx.status,
 | |
|         cost,
 | |
|       };
 | |
|       if (Math.floor(status / 100) == 5) {
 | |
|         requestLogger.error({ ...info, res: ctx.body?.['errors'] || ctx.body });
 | |
|       } else if (Math.floor(status / 100) == 4) {
 | |
|         requestLogger.warn({ ...info, res: ctx.body?.['errors'] || ctx.body });
 | |
|       } else {
 | |
|         requestLogger.info(info);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     ctx.res.setHeader('X-Request-Id', reqId);
 | |
| 
 | |
|     if (error) {
 | |
|       throw error;
 | |
|     }
 | |
|   };
 | |
| };
 |