From b05d83f18e06aa79ab4e7fc690731eb313053f6a Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Thu, 19 Jun 2025 23:24:32 +0300 Subject: [PATCH 01/13] Create standalone package for logging services --- packages/libs/logger/README.md | 269 ++++++++++++++++++++ packages/libs/logger/package.json | 39 +++ packages/libs/logger/src/abstract-logger.ts | 113 ++++++++ packages/libs/logger/src/index.ts | 53 ++++ packages/libs/logger/src/nest-logger.ts | 93 +++++++ packages/libs/logger/src/pino-logger.ts | 63 +++++ packages/libs/logger/src/types.ts | 40 +++ packages/libs/logger/tsconfig.json | 22 ++ 8 files changed, 692 insertions(+) create mode 100644 packages/libs/logger/README.md create mode 100644 packages/libs/logger/package.json create mode 100644 packages/libs/logger/src/abstract-logger.ts create mode 100644 packages/libs/logger/src/index.ts create mode 100644 packages/libs/logger/src/nest-logger.ts create mode 100644 packages/libs/logger/src/pino-logger.ts create mode 100644 packages/libs/logger/src/types.ts create mode 100644 packages/libs/logger/tsconfig.json diff --git a/packages/libs/logger/README.md b/packages/libs/logger/README.md new file mode 100644 index 0000000000..5b52da00cb --- /dev/null +++ b/packages/libs/logger/README.md @@ -0,0 +1,269 @@ +# @human-protocol/logger + +A unified logging package for Human Protocol services and oracles, based on Pino with NestJS integration. This package follows the same pattern as the Reputation Oracle logger. + +## Features + +- **Unified logging interface** across all services and oracles +- **Pino-based** for high performance logging +- **NestJS integration** with custom logger override +- **Structured logging** with metadata support +- **Error serialization** with stack traces +- **Environment-aware** configuration (development, production, test) +- **Pretty printing** for development environments +- **Singleton pattern** with child loggers for context + +## Installation + +```bash +npm install @human-protocol/logger +``` + +## Usage + +### Basic Logger (Reputation Oracle Style) + +```typescript +import logger from '@human-protocol/logger'; + +// Use the default logger +logger.info('Service started'); +logger.error('An error occurred', new Error('Something went wrong')); +logger.debug('Debug information', { userId: 123, action: 'login' }); + +// Create child loggers with context +const serviceLogger = logger.child({ + context: 'MyService', +}); + +serviceLogger.info('Service operation completed'); +serviceLogger.error('Service error', { operation: 'create', userId: 123 }); +``` + +### NestJS Integration + +```typescript +import logger, { nestLoggerOverride } from '@human-protocol/logger'; + +// In your main.ts +const app = await NestFactory.create(AppModule, { + logger: nestLoggerOverride, +}); + +// Use the logger in your app +logger.info(`API server is running on http://${host}:${port}`); +``` + +### Service Implementation + +```typescript +import { Injectable } from '@nestjs/common'; +import logger from '@human-protocol/logger'; + +@Injectable() +export class MyService { + private readonly logger = logger.child({ + context: MyService.name, + }); + + doSomething() { + this.logger.info('Something happened'); + this.logger.error('An error occurred', new Error('Something went wrong')); + } +} +``` + +### Child Loggers + +```typescript +import logger from '@human-protocol/logger'; + +const userLogger = logger.child({ component: 'user-service' }); +const paymentLogger = logger.child({ component: 'payment-service' }); + +userLogger.info('User created', { userId: 123 }); +paymentLogger.info('Payment processed', { paymentId: 'pay_123' }); +``` + +### Custom Logger (Advanced) + +```typescript +import { createLogger, LogLevel } from '@human-protocol/logger'; + +const logger = createLogger( + { + name: 'CustomLogger', + level: LogLevel.DEBUG, + pretty: true, + disabled: false, + }, + { + service: 'my-service', + environment: 'development', + }, +); +``` + +## API Reference + +### Default Exports + +- `logger` - The default logger instance (singleton) +- `nestLoggerOverride` - NestJS logger override for app-wide logging + +### `logger.child(bindings)` + +Creates a child logger with additional context. + +**Parameters:** +- `bindings` (ChildBindings): Additional metadata bindings + +### `createLogger(options, bindings)` + +Creates a custom logger with full configuration. + +**Parameters:** +- `options` (LoggerOptions): Logger configuration +- `bindings` (LogMeta): Additional metadata bindings + +### Logger Interface + +```typescript +interface Logger { + debug(message: string, errorOrMeta?: unknown): void; + info(message: string, errorOrMeta?: unknown): void; + warn(message: string, errorOrMeta?: unknown): void; + error(message: string, errorOrMeta?: unknown): void; + child(bindings: ChildBindings): Logger; +} +``` + +## Log Levels + +- `DEBUG`: Detailed debug information +- `INFO`: General information messages +- `WARN`: Warning messages +- `ERROR`: Error messages + +## Environment Configuration + +The logger automatically adapts based on the environment: + +- **Development**: Debug level, pretty printing enabled +- **Production**: Info level, structured JSON output +- **Test**: Logging disabled by default + +## Migration from Existing Loggers + +### From NestJS Logger + +**Before:** +```typescript +import { Logger } from '@nestjs/common'; + +export class MyService { + private readonly logger = new Logger(MyService.name); + + doSomething() { + this.logger.log('Something happened'); + } +} +``` + +**After:** +```typescript +import logger from '@human-protocol/logger'; + +export class MyService { + private readonly logger = logger.child({ + context: MyService.name, + }); + + doSomething() { + this.logger.info('Something happened'); + } +} +``` + +### From Reputation Oracle Local Logger + +**Before:** +```typescript +import logger from '../../logger'; + +export class MyService { + private readonly logger = logger.child({ + context: MyService.name, + }); +} +``` + +**After:** +```typescript +import logger from '@human-protocol/logger'; + +export class MyService { + private readonly logger = logger.child({ + context: MyService.name, + }); +} +``` + +## Examples + +### Complete Service Example + +```typescript +import { Injectable } from '@nestjs/common'; +import logger from '@human-protocol/logger'; + +@Injectable() +export class UserService { + private readonly logger = logger.child({ + context: UserService.name, + }); + + async createUser(userData: any) { + try { + this.logger.info('Creating user', { email: userData.email }); + + // ... user creation logic + + this.logger.info('User created successfully', { userId: user.id }); + return user; + } catch (error) { + this.logger.error('Failed to create user', error); + throw error; + } + } + + async getUser(userId: string) { + this.logger.debug('Fetching user', { userId }); + + // ... user fetching logic + + return user; + } +} +``` + +### Main Application Setup + +```typescript +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import logger, { nestLoggerOverride } from '@human-protocol/logger'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule, { + logger: nestLoggerOverride, + }); + + const port = process.env.PORT || 3000; + await app.listen(port); + + logger.info(`Application is running on port ${port}`); +} + +bootstrap(); +``` \ No newline at end of file diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json new file mode 100644 index 0000000000..bc192e2fcb --- /dev/null +++ b/packages/libs/logger/package.json @@ -0,0 +1,39 @@ +{ + "name": "@human-protocol/logger", + "version": "1.0.0", + "description": "Unified logging package for Human Protocol services and oracles", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc", + "clean": "rm -rf dist", + "test": "jest", + "test:watch": "jest --watch", + "lint": "eslint \"src/**/*.ts\" --fix" + }, + "dependencies": { + "pino": "^9.6.0" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "@types/node": "^22.10.5", + "jest": "^29.7.0", + "pino-pretty": "^13.0.0", + "ts-jest": "^29.2.5", + "typescript": "^5.6.3" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0" + }, + "files": [ + "dist/**/*" + ], + "keywords": [ + "logging", + "pino", + "nestjs", + "human-protocol" + ], + "author": "Human Protocol", + "license": "MIT" +} diff --git a/packages/libs/logger/src/abstract-logger.ts b/packages/libs/logger/src/abstract-logger.ts new file mode 100644 index 0000000000..612317e061 --- /dev/null +++ b/packages/libs/logger/src/abstract-logger.ts @@ -0,0 +1,113 @@ +import { ChildBindings, Logger, LogLevel, LogMeta, LogRecord } from './types'; + +function isPlainObject(maybeObj: unknown): maybeObj is LogMeta { + return Object.prototype.toString.call(maybeObj) === '[object Object]'; +} + +function isValidLoggerName(maybeName: unknown): maybeName is string { + return typeof maybeName === 'string' && maybeName.length > 0; +} + +function serializeError(error: Error) { + const { name, message, stack, ...errorProps } = error; + + return { + kind: name, + message, + stack, + ...errorProps, + }; +} + +abstract class LoggerWrapper implements Logger { + protected readonly bindings: LogMeta; + private readonly name?: string; + + constructor(bindings: LogMeta = {}) { + if (!isPlainObject(bindings)) { + throw new Error('Logger bindings must be a plain object'); + } + + const { name, ..._bindings } = bindings; + + this.bindings = _bindings; + + if (name && isValidLoggerName(name)) { + this.name = name; + } + } + + debug(message: string, errorOrMeta?: unknown): void { + this.log(LogLevel.DEBUG, message, errorOrMeta); + } + + info(message: string, errorOrMeta?: unknown): void { + this.log(LogLevel.INFO, message, errorOrMeta); + } + + warn(message: string, errorOrMeta?: unknown): void { + this.log(LogLevel.WARN, message, errorOrMeta); + } + + error(message: string, errorOrMeta?: unknown): void { + this.log(LogLevel.ERROR, message, errorOrMeta); + } + + child(bindings: ChildBindings): Logger { + if (!isPlainObject(bindings)) { + throw new Error('Log bindings required for child logger'); + } + + return this.createChild(bindings); + } + + protected abstract createChild(bindings: LogMeta): Logger; + + private log(level: LogLevel, message: string, errorOrMeta?: unknown): void { + const logMessage = typeof message === 'string' ? message : `${message}`; + + let metaArgument: LogMeta; + if (errorOrMeta === undefined) { + metaArgument = {}; + } else if (errorOrMeta instanceof Error) { + metaArgument = { + error: serializeError(errorOrMeta), + }; + } else if (isPlainObject(errorOrMeta)) { + const { error, ...meta } = errorOrMeta; + metaArgument = meta; + if (error instanceof Error) { + Object.assign(metaArgument, { + error: serializeError(error), + }); + } else if (error !== undefined) { + metaArgument.error = error; + } + } else { + /** + * Fallback in case somebody uses log in a wrong way + */ + metaArgument = { + meta: errorOrMeta, + }; + } + + const enrichedMeta: LogRecord = { + ...this.bindings, + ...metaArgument, + level, + message: logMessage, + timestamp: Date.now(), + }; + + if (this.name) { + enrichedMeta.logger = this.name; + } + + this.callLogger(level, enrichedMeta); + } + + protected abstract callLogger(level: LogLevel, log: LogRecord): void; +} + +export default LoggerWrapper; \ No newline at end of file diff --git a/packages/libs/logger/src/index.ts b/packages/libs/logger/src/index.ts new file mode 100644 index 0000000000..9156cae769 --- /dev/null +++ b/packages/libs/logger/src/index.ts @@ -0,0 +1,53 @@ +import { createLogger, WrappedPino } from './pino-logger'; +import NestLogger from './nest-logger'; +import { LogLevel } from './types'; + +// Environment detection similar to reputation oracle +enum EnvironmentName { + LOCAL = 'local', + DEVELOPMENT = 'development', + TEST = 'test', + STAGING = 'staging', + PRODUCTION = 'production', +} + +class Environment { + static readonly envName: string = + process.env.NODE_ENV || EnvironmentName.DEVELOPMENT; + + static isDevelopment(): boolean { + return [ + EnvironmentName.DEVELOPMENT, + EnvironmentName.TEST, + EnvironmentName.LOCAL, + ].includes(Environment.envName as EnvironmentName); + } + + static isTest(): boolean { + return Environment.envName === EnvironmentName.TEST; + } +} + +// Create default logger instance +const isDevelopment = Environment.isDevelopment(); + +const defaultLogger = createLogger( + { + name: 'DefaultLogger', + level: isDevelopment ? LogLevel.DEBUG : LogLevel.INFO, + pretty: isDevelopment, + disabled: Environment.isTest(), + }, + { + environment: Environment.envName, + service: 'human-protocol', + }, +); + +// Create NestJS logger override +export const nestLoggerOverride = new NestLogger( + defaultLogger.child({ name: 'NestLogger' }), +); + +// Export the default logger as the main export +export default defaultLogger; diff --git a/packages/libs/logger/src/nest-logger.ts b/packages/libs/logger/src/nest-logger.ts new file mode 100644 index 0000000000..876c8c7f98 --- /dev/null +++ b/packages/libs/logger/src/nest-logger.ts @@ -0,0 +1,93 @@ +import { LoggerService } from '@nestjs/common'; +import { Logger, LogLevel, LogMeta } from './types'; + +class NestLogger implements LoggerService { + constructor(private readonly loggerInstance: Logger) {} + + log(message: any, ...optionalParams: any[]) { + this.callLogger(LogLevel.INFO, message, ...optionalParams); + } + + warn(message: any, ...optionalParams: any[]) { + this.callLogger(LogLevel.WARN, message, ...optionalParams); + } + + error(message: any, ...optionalParams: any[]) { + let _message: any; + let _optionalParams: any[]; + + const firstParam = optionalParams[0] || ''; + if ( + typeof message === 'string' && + typeof firstParam === 'string' && + /\n\s+at\s.+:\d+:\d+/.test(firstParam) + ) { + /** + * It's a case when logger called as + * logger.error(error.message, error.stack) + */ + const error = new Error(message); + error.stack = firstParam; + + _message = error; + _optionalParams = optionalParams.slice(1); + } else { + _message = message; + if (optionalParams.length === 2 && optionalParams[0] === undefined) { + /** + * It's a case when logger called as + * logger.error(message) + * + * In this case Nest adds `undefined` "stack" + * as second param + */ + _optionalParams = [optionalParams[1]]; + } else { + _optionalParams = optionalParams; + } + } + + this.callLogger(LogLevel.ERROR, _message, ..._optionalParams); + } + + private callLogger( + level: LogLevel, + message: unknown, + ...optionalParams: unknown[] + ): void { + const logMeta: LogMeta = {}; + + let params: unknown[] = []; + // Nest always add "context" as last param + if (optionalParams.length) { + const lastParam = optionalParams.at(-1); + if (typeof lastParam === 'string') { + logMeta.context = lastParam; + params = optionalParams.slice(0, -1); + } else { + params = optionalParams; + } + } + + // Case when Nest logs something other than context + if (params.length) { + logMeta.messages = params; + } + + let _message = `unspecified nest ${level}`.toUpperCase(); + // Case when Nest logs just one argument: object + if (typeof message === 'object') { + if (message instanceof Error) { + logMeta.error = message; + } else { + Object.assign(logMeta, message); + } + } else if (message !== undefined) { + _message = message.toString(); + } + + this.loggerInstance[level](_message, logMeta); + } +} + +export default NestLogger; \ No newline at end of file diff --git a/packages/libs/logger/src/pino-logger.ts b/packages/libs/logger/src/pino-logger.ts new file mode 100644 index 0000000000..4635144522 --- /dev/null +++ b/packages/libs/logger/src/pino-logger.ts @@ -0,0 +1,63 @@ +import pino from 'pino'; +import LoggerWrapper from './abstract-logger'; +import { + ChildBindings, + LogMeta, + Logger, + LogLevel, + LoggerOptions, + LogRecord, +} from './types'; + +export class WrappedPino extends LoggerWrapper { + constructor( + private readonly pinoLogger: pino.Logger, + bindings?: LogMeta, + ) { + super(bindings); + } + + protected createChild(bindings: ChildBindings): Logger { + return new WrappedPino(this.pinoLogger, { + ...this.bindings, + ...bindings, + }); + } + + protected callLogger(level: LogLevel, log: LogRecord): void { + const _log: Partial = { ...log }; + + delete _log.level; + + this.pinoLogger[level](_log); + } +} + +const pinoLogLevelFormatter = (label: string) => ({ level: label }); + +export function createLogger( + { name, level, pretty, disabled }: LoggerOptions, + bindings: LogMeta = {}, +): WrappedPino { + const pinoLogger = pino({ + base: null, + level: level || LogLevel.INFO, + enabled: disabled !== true, + timestamp: false, + formatters: { + level: pinoLogLevelFormatter, + }, + transport: pretty + ? { + target: 'pino-pretty', + options: { + messageKey: 'message', + translateTime: "SYS:yyyy-mm-dd, HH:MM:ss'Z'", + colorize: true, + }, + } + : undefined, + }); + + return new WrappedPino(pinoLogger, { ...bindings, name }); +} \ No newline at end of file diff --git a/packages/libs/logger/src/types.ts b/packages/libs/logger/src/types.ts new file mode 100644 index 0000000000..ae14a97b0d --- /dev/null +++ b/packages/libs/logger/src/types.ts @@ -0,0 +1,40 @@ +export enum LogLevel { + DEBUG = 'debug', + INFO = 'info', + WARN = 'warn', + ERROR = 'error', +} + +export type LogMeta = Record; + +export type LogRecord = { + logger?: string; + level: `${LogLevel}`; + message: string; + timestamp: number; +} & LogMeta; + +type LogFn = { + (message: string, meta?: LogMeta): void; + (message: string, error: Error): void; + (message: string, errorOrMeta?: unknown): void; +}; + +export type ChildBindings = { name?: string } & LogMeta; + +export interface Logger { + debug: LogFn; + info: LogFn; + warn: LogFn; + error: LogFn; + child: (bindings: ChildBindings) => Logger; +} + +export type LoggerOptions = { + name?: string; + pretty?: boolean; + level?: `${LogLevel}`; + disabled?: boolean; + service?: string; + environment?: string; +}; \ No newline at end of file diff --git a/packages/libs/logger/tsconfig.json b/packages/libs/logger/tsconfig.json new file mode 100644 index 0000000000..0f92f4d445 --- /dev/null +++ b/packages/libs/logger/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020"], + "outDir": "./dist", + "rootDir": "./src", + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] +} \ No newline at end of file From 13909291152ab51ba43ec3e1225b54b254f3b407 Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Fri, 20 Jun 2025 02:13:37 +0300 Subject: [PATCH 02/13] Code cleanup --- packages/libs/logger/package.json | 4 ++++ .../server/src/logger => libs/logger/src}/README.md | 0 packages/libs/logger/src/__mocks__/index.ts | 11 +++++++++++ packages/libs/logger/src/abstract-logger.ts | 2 +- packages/libs/logger/src/index.ts | 2 +- packages/libs/logger/src/nest-logger.ts | 2 +- packages/libs/logger/src/pino-logger.ts | 2 +- 7 files changed, 19 insertions(+), 4 deletions(-) rename packages/{apps/reputation-oracle/server/src/logger => libs/logger/src}/README.md (100%) create mode 100644 packages/libs/logger/src/__mocks__/index.ts diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json index bc192e2fcb..ea48fbcc39 100644 --- a/packages/libs/logger/package.json +++ b/packages/libs/logger/package.json @@ -11,6 +11,10 @@ "test:watch": "jest --watch", "lint": "eslint \"src/**/*.ts\" --fix" }, + "repository": { + "url": "https://github.com/humanprotocol/human-protocol.git", + "directory": "packages/libs/logger" + }, "dependencies": { "pino": "^9.6.0" }, diff --git a/packages/apps/reputation-oracle/server/src/logger/README.md b/packages/libs/logger/src/README.md similarity index 100% rename from packages/apps/reputation-oracle/server/src/logger/README.md rename to packages/libs/logger/src/README.md diff --git a/packages/libs/logger/src/__mocks__/index.ts b/packages/libs/logger/src/__mocks__/index.ts new file mode 100644 index 0000000000..f4017058d8 --- /dev/null +++ b/packages/libs/logger/src/__mocks__/index.ts @@ -0,0 +1,11 @@ +import { Logger } from '../types'; + +const logger: Logger = { + child: () => logger, + info: jest.fn(), + debug: jest.fn(), + error: jest.fn(), + warn: jest.fn(), +}; + +export default logger; diff --git a/packages/libs/logger/src/abstract-logger.ts b/packages/libs/logger/src/abstract-logger.ts index 612317e061..2bf1f7f493 100644 --- a/packages/libs/logger/src/abstract-logger.ts +++ b/packages/libs/logger/src/abstract-logger.ts @@ -110,4 +110,4 @@ abstract class LoggerWrapper implements Logger { protected abstract callLogger(level: LogLevel, log: LogRecord): void; } -export default LoggerWrapper; \ No newline at end of file +export default LoggerWrapper; diff --git a/packages/libs/logger/src/index.ts b/packages/libs/logger/src/index.ts index 9156cae769..aea6ffb222 100644 --- a/packages/libs/logger/src/index.ts +++ b/packages/libs/logger/src/index.ts @@ -1,4 +1,4 @@ -import { createLogger, WrappedPino } from './pino-logger'; +import { createLogger } from './pino-logger'; import NestLogger from './nest-logger'; import { LogLevel } from './types'; diff --git a/packages/libs/logger/src/nest-logger.ts b/packages/libs/logger/src/nest-logger.ts index 876c8c7f98..a8347d52b7 100644 --- a/packages/libs/logger/src/nest-logger.ts +++ b/packages/libs/logger/src/nest-logger.ts @@ -90,4 +90,4 @@ class NestLogger implements LoggerService { } } -export default NestLogger; \ No newline at end of file +export default NestLogger; diff --git a/packages/libs/logger/src/pino-logger.ts b/packages/libs/logger/src/pino-logger.ts index 4635144522..09d0a055df 100644 --- a/packages/libs/logger/src/pino-logger.ts +++ b/packages/libs/logger/src/pino-logger.ts @@ -60,4 +60,4 @@ export function createLogger( }); return new WrappedPino(pinoLogger, { ...bindings, name }); -} \ No newline at end of file +} From c2a2e0425107f4414c07b5f9dbc11062a8085a76 Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Fri, 20 Jun 2025 02:27:54 +0300 Subject: [PATCH 03/13] Replace custom logger with generic logger package --- package.json | 4 +- packages/apps/dashboard/server/package.json | 1 + .../exchange-oracle/server/package.json | 1 + packages/apps/human-app/server/package.json | 1 + .../apps/job-launcher/server/package.json | 1 + .../reputation-oracle/server/package.json | 3 +- .../src/common/filters/exception.filter.ts | 2 +- .../integrations/hcaptcha/hcaptcha.service.ts | 2 +- .../slack-bot-app/slack-bot-app.ts | 2 +- .../server/src/logger/__mocks__/index.ts | 11 -- .../server/src/logger/abstract-logger.ts | 113 ------------------ .../server/src/logger/index.ts | 25 ---- .../server/src/logger/nest-logger.ts | 93 -------------- .../server/src/logger/pino-logger.ts | 63 ---------- .../server/src/logger/types.ts | 38 ------ .../apps/reputation-oracle/server/src/main.ts | 2 +- .../server/src/modules/abuse/abuse.service.ts | 2 +- .../src/modules/auth/auth.error-filter.ts | 2 +- .../server/src/modules/auth/auth.service.ts | 2 +- .../src/modules/cron-job/cron-job.service.ts | 2 +- .../modules/email/sendgrid.service.spec.ts | 5 +- .../src/modules/email/sendgrid.service.ts | 3 +- .../encryption/pgp-encryption.service.ts | 2 +- .../escrow-completion.service.ts | 2 +- .../modules/health/health.controller.spec.ts | 2 +- .../src/modules/kyc/kyc.error-filter.ts | 2 +- .../server/src/modules/kyc/kyc.service.ts | 2 +- .../src/modules/nda/nda.error-filter.ts | 2 +- .../qualification.error-filter.ts | 2 +- .../qualification/qualification.service.ts | 2 +- .../src/modules/storage/storage.service.ts | 2 +- .../src/modules/user/user.error-filter.ts | 2 +- .../webhook/webhook-incoming.service.ts | 2 +- .../webhook/webhook-outgoing.service.ts | 2 +- packages/libs/logger/package.json | 2 +- packages/libs/logger/tsconfig.json | 3 +- yarn.lock | 84 ++++++++++++- 37 files changed, 117 insertions(+), 374 deletions(-) delete mode 100644 packages/apps/reputation-oracle/server/src/logger/__mocks__/index.ts delete mode 100644 packages/apps/reputation-oracle/server/src/logger/abstract-logger.ts delete mode 100644 packages/apps/reputation-oracle/server/src/logger/index.ts delete mode 100644 packages/apps/reputation-oracle/server/src/logger/nest-logger.ts delete mode 100644 packages/apps/reputation-oracle/server/src/logger/pino-logger.ts delete mode 100644 packages/apps/reputation-oracle/server/src/logger/types.ts diff --git a/package.json b/package.json index e101aba252..5392ad0fde 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ "scripts": { "clean": "yarn workspaces foreach --all -p run clean", "lint": "yarn workspaces foreach --all -p run lint", + "test": "yarn workspaces foreach --all -p run test", "build:core": "yarn workspace @human-protocol/core build", "build:sdk": "yarn workspace @human-protocol/sdk build", - "build:libs": "yarn build:core && yarn build:sdk", + "build:logger": "yarn workspace @human-protocol/logger build", + "build:libs": "yarn build:core && yarn build:sdk && yarn build:logger", "docker:infra-up": "make -C ./docker-setup -f Makefile.dev infra-up", "docker:infra-stop": "make -C ./docker-setup -f Makefile.dev infra-stop", "docker:infra-down": "make -C ./docker-setup -f Makefile.dev infra-down", diff --git a/packages/apps/dashboard/server/package.json b/packages/apps/dashboard/server/package.json index 6e92cfc6a3..45b9d4ec53 100644 --- a/packages/apps/dashboard/server/package.json +++ b/packages/apps/dashboard/server/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@human-protocol/core": "workspace:*", + "@human-protocol/logger": "workspace:*", "@human-protocol/sdk": "workspace:*", "@nestjs/axios": "^3.1.2", "@nestjs/cache-manager": "^2.2.2", diff --git a/packages/apps/fortune/exchange-oracle/server/package.json b/packages/apps/fortune/exchange-oracle/server/package.json index 52e07a4a4a..4e86418ced 100644 --- a/packages/apps/fortune/exchange-oracle/server/package.json +++ b/packages/apps/fortune/exchange-oracle/server/package.json @@ -28,6 +28,7 @@ "generate-env-doc": "ts-node scripts/generate-env-doc.ts" }, "dependencies": { + "@human-protocol/logger": "workspace:*", "@human-protocol/sdk": "workspace:*", "@nestjs/axios": "^3.1.2", "@nestjs/common": "^10.2.7", diff --git a/packages/apps/human-app/server/package.json b/packages/apps/human-app/server/package.json index aeb54182fc..6079b888f4 100644 --- a/packages/apps/human-app/server/package.json +++ b/packages/apps/human-app/server/package.json @@ -25,6 +25,7 @@ "@automapper/classes": "^8.8.1", "@automapper/core": "^8.8.1", "@automapper/nestjs": "^8.8.1", + "@human-protocol/logger": "workspace:*", "@human-protocol/sdk": "workspace:*", "@nestjs/axios": "^3.1.2", "@nestjs/cache-manager": "^2.2.1", diff --git a/packages/apps/job-launcher/server/package.json b/packages/apps/job-launcher/server/package.json index 45917b536c..830ac22576 100644 --- a/packages/apps/job-launcher/server/package.json +++ b/packages/apps/job-launcher/server/package.json @@ -30,6 +30,7 @@ "dependencies": { "@google-cloud/storage": "^7.15.0", "@google-cloud/vision": "^4.3.2", + "@human-protocol/logger": "workspace:*", "@human-protocol/sdk": "workspace:*", "@nestjs/axios": "^3.1.2", "@nestjs/common": "^10.2.7", diff --git a/packages/apps/reputation-oracle/server/package.json b/packages/apps/reputation-oracle/server/package.json index 966238f64d..cdeef616dc 100644 --- a/packages/apps/reputation-oracle/server/package.json +++ b/packages/apps/reputation-oracle/server/package.json @@ -29,6 +29,7 @@ }, "dependencies": { "@human-protocol/core": "workspace:*", + "@human-protocol/logger": "workspace:*", "@human-protocol/sdk": "workspace:*", "@nestjs/axios": "^3.1.3", "@nestjs/common": "^10.2.7", @@ -62,7 +63,6 @@ "passport": "^0.7.0", "passport-jwt": "^4.0.1", "pg": "8.13.1", - "pino": "^9.6.0", "reflect-metadata": "^0.2.2", "rxjs": "^7.2.0", "typeorm": "^0.3.16", @@ -91,7 +91,6 @@ "eslint-plugin-prettier": "^5.2.1", "jest": "29.7.0", "nock": "^14.0.3", - "pino-pretty": "^13.0.0", "prettier": "^3.4.2", "source-map-support": "^0.5.20", "supertest": "^7.0.0", diff --git a/packages/apps/reputation-oracle/server/src/common/filters/exception.filter.ts b/packages/apps/reputation-oracle/server/src/common/filters/exception.filter.ts index d7d051436d..4878010ac4 100644 --- a/packages/apps/reputation-oracle/server/src/common/filters/exception.filter.ts +++ b/packages/apps/reputation-oracle/server/src/common/filters/exception.filter.ts @@ -7,7 +7,7 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; import { DatabaseError, isDuplicatedError } from '../../database'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { transformKeysFromCamelToSnake } from '../../utils/case-converters'; @Catch() diff --git a/packages/apps/reputation-oracle/server/src/integrations/hcaptcha/hcaptcha.service.ts b/packages/apps/reputation-oracle/server/src/integrations/hcaptcha/hcaptcha.service.ts index 4643db340c..1ecc5faa77 100644 --- a/packages/apps/reputation-oracle/server/src/integrations/hcaptcha/hcaptcha.service.ts +++ b/packages/apps/reputation-oracle/server/src/integrations/hcaptcha/hcaptcha.service.ts @@ -4,7 +4,7 @@ import { ethers } from 'ethers'; import { firstValueFrom } from 'rxjs'; import { HCaptchaConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { GetLabelerQueryParams, diff --git a/packages/apps/reputation-oracle/server/src/integrations/slack-bot-app/slack-bot-app.ts b/packages/apps/reputation-oracle/server/src/integrations/slack-bot-app/slack-bot-app.ts index 39b92d3039..9322c9552d 100644 --- a/packages/apps/reputation-oracle/server/src/integrations/slack-bot-app/slack-bot-app.ts +++ b/packages/apps/reputation-oracle/server/src/integrations/slack-bot-app/slack-bot-app.ts @@ -2,7 +2,7 @@ import { HttpService } from '@nestjs/axios'; import { View, ViewsOpenResponse } from '@slack/web-api'; import { IncomingWebhookSendArguments } from '@slack/webhook'; import { firstValueFrom } from 'rxjs'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import * as httpUtils from '../../utils/http'; export class SlackBotApp { diff --git a/packages/apps/reputation-oracle/server/src/logger/__mocks__/index.ts b/packages/apps/reputation-oracle/server/src/logger/__mocks__/index.ts deleted file mode 100644 index f4017058d8..0000000000 --- a/packages/apps/reputation-oracle/server/src/logger/__mocks__/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Logger } from '../types'; - -const logger: Logger = { - child: () => logger, - info: jest.fn(), - debug: jest.fn(), - error: jest.fn(), - warn: jest.fn(), -}; - -export default logger; diff --git a/packages/apps/reputation-oracle/server/src/logger/abstract-logger.ts b/packages/apps/reputation-oracle/server/src/logger/abstract-logger.ts deleted file mode 100644 index 2bf1f7f493..0000000000 --- a/packages/apps/reputation-oracle/server/src/logger/abstract-logger.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { ChildBindings, Logger, LogLevel, LogMeta, LogRecord } from './types'; - -function isPlainObject(maybeObj: unknown): maybeObj is LogMeta { - return Object.prototype.toString.call(maybeObj) === '[object Object]'; -} - -function isValidLoggerName(maybeName: unknown): maybeName is string { - return typeof maybeName === 'string' && maybeName.length > 0; -} - -function serializeError(error: Error) { - const { name, message, stack, ...errorProps } = error; - - return { - kind: name, - message, - stack, - ...errorProps, - }; -} - -abstract class LoggerWrapper implements Logger { - protected readonly bindings: LogMeta; - private readonly name?: string; - - constructor(bindings: LogMeta = {}) { - if (!isPlainObject(bindings)) { - throw new Error('Logger bindings must be a plain object'); - } - - const { name, ..._bindings } = bindings; - - this.bindings = _bindings; - - if (name && isValidLoggerName(name)) { - this.name = name; - } - } - - debug(message: string, errorOrMeta?: unknown): void { - this.log(LogLevel.DEBUG, message, errorOrMeta); - } - - info(message: string, errorOrMeta?: unknown): void { - this.log(LogLevel.INFO, message, errorOrMeta); - } - - warn(message: string, errorOrMeta?: unknown): void { - this.log(LogLevel.WARN, message, errorOrMeta); - } - - error(message: string, errorOrMeta?: unknown): void { - this.log(LogLevel.ERROR, message, errorOrMeta); - } - - child(bindings: ChildBindings): Logger { - if (!isPlainObject(bindings)) { - throw new Error('Log bindings required for child logger'); - } - - return this.createChild(bindings); - } - - protected abstract createChild(bindings: LogMeta): Logger; - - private log(level: LogLevel, message: string, errorOrMeta?: unknown): void { - const logMessage = typeof message === 'string' ? message : `${message}`; - - let metaArgument: LogMeta; - if (errorOrMeta === undefined) { - metaArgument = {}; - } else if (errorOrMeta instanceof Error) { - metaArgument = { - error: serializeError(errorOrMeta), - }; - } else if (isPlainObject(errorOrMeta)) { - const { error, ...meta } = errorOrMeta; - metaArgument = meta; - if (error instanceof Error) { - Object.assign(metaArgument, { - error: serializeError(error), - }); - } else if (error !== undefined) { - metaArgument.error = error; - } - } else { - /** - * Fallback in case somebody uses log in a wrong way - */ - metaArgument = { - meta: errorOrMeta, - }; - } - - const enrichedMeta: LogRecord = { - ...this.bindings, - ...metaArgument, - level, - message: logMessage, - timestamp: Date.now(), - }; - - if (this.name) { - enrichedMeta.logger = this.name; - } - - this.callLogger(level, enrichedMeta); - } - - protected abstract callLogger(level: LogLevel, log: LogRecord): void; -} - -export default LoggerWrapper; diff --git a/packages/apps/reputation-oracle/server/src/logger/index.ts b/packages/apps/reputation-oracle/server/src/logger/index.ts deleted file mode 100644 index 4509f80573..0000000000 --- a/packages/apps/reputation-oracle/server/src/logger/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createLogger } from './pino-logger'; -import NestLogger from './nest-logger'; -import { LogLevel } from './types'; -import Environment from '../utils/environment'; - -const isDevelopment = Environment.isDevelopment(); - -const defaultLogger = createLogger( - { - name: 'DefaultLogger', - level: isDevelopment ? LogLevel.DEBUG : LogLevel.INFO, - pretty: isDevelopment, - disabled: Environment.isTest(), - }, - { - environment: Environment.name, - service: 'reputation-oracle', - }, -); - -export const nestLoggerOverride = new NestLogger( - defaultLogger.child({ name: 'NestLogger' }), -); - -export default defaultLogger; diff --git a/packages/apps/reputation-oracle/server/src/logger/nest-logger.ts b/packages/apps/reputation-oracle/server/src/logger/nest-logger.ts deleted file mode 100644 index a8347d52b7..0000000000 --- a/packages/apps/reputation-oracle/server/src/logger/nest-logger.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { LoggerService } from '@nestjs/common'; -import { Logger, LogLevel, LogMeta } from './types'; - -class NestLogger implements LoggerService { - constructor(private readonly loggerInstance: Logger) {} - - log(message: any, ...optionalParams: any[]) { - this.callLogger(LogLevel.INFO, message, ...optionalParams); - } - - warn(message: any, ...optionalParams: any[]) { - this.callLogger(LogLevel.WARN, message, ...optionalParams); - } - - error(message: any, ...optionalParams: any[]) { - let _message: any; - let _optionalParams: any[]; - - const firstParam = optionalParams[0] || ''; - if ( - typeof message === 'string' && - typeof firstParam === 'string' && - /\n\s+at\s.+:\d+:\d+/.test(firstParam) - ) { - /** - * It's a case when logger called as - * logger.error(error.message, error.stack) - */ - const error = new Error(message); - error.stack = firstParam; - - _message = error; - _optionalParams = optionalParams.slice(1); - } else { - _message = message; - if (optionalParams.length === 2 && optionalParams[0] === undefined) { - /** - * It's a case when logger called as - * logger.error(message) - * - * In this case Nest adds `undefined` "stack" - * as second param - */ - _optionalParams = [optionalParams[1]]; - } else { - _optionalParams = optionalParams; - } - } - - this.callLogger(LogLevel.ERROR, _message, ..._optionalParams); - } - - private callLogger( - level: LogLevel, - message: unknown, - ...optionalParams: unknown[] - ): void { - const logMeta: LogMeta = {}; - - let params: unknown[] = []; - // Nest always add "context" as last param - if (optionalParams.length) { - const lastParam = optionalParams.at(-1); - if (typeof lastParam === 'string') { - logMeta.context = lastParam; - params = optionalParams.slice(0, -1); - } else { - params = optionalParams; - } - } - - // Case when Nest logs something other than context - if (params.length) { - logMeta.messages = params; - } - - let _message = `unspecified nest ${level}`.toUpperCase(); - // Case when Nest logs just one argument: object - if (typeof message === 'object') { - if (message instanceof Error) { - logMeta.error = message; - } else { - Object.assign(logMeta, message); - } - } else if (message !== undefined) { - _message = message.toString(); - } - - this.loggerInstance[level](_message, logMeta); - } -} - -export default NestLogger; diff --git a/packages/apps/reputation-oracle/server/src/logger/pino-logger.ts b/packages/apps/reputation-oracle/server/src/logger/pino-logger.ts deleted file mode 100644 index 09d0a055df..0000000000 --- a/packages/apps/reputation-oracle/server/src/logger/pino-logger.ts +++ /dev/null @@ -1,63 +0,0 @@ -import pino from 'pino'; -import LoggerWrapper from './abstract-logger'; -import { - ChildBindings, - LogMeta, - Logger, - LogLevel, - LoggerOptions, - LogRecord, -} from './types'; - -export class WrappedPino extends LoggerWrapper { - constructor( - private readonly pinoLogger: pino.Logger, - bindings?: LogMeta, - ) { - super(bindings); - } - - protected createChild(bindings: ChildBindings): Logger { - return new WrappedPino(this.pinoLogger, { - ...this.bindings, - ...bindings, - }); - } - - protected callLogger(level: LogLevel, log: LogRecord): void { - const _log: Partial = { ...log }; - - delete _log.level; - - this.pinoLogger[level](_log); - } -} - -const pinoLogLevelFormatter = (label: string) => ({ level: label }); - -export function createLogger( - { name, level, pretty, disabled }: LoggerOptions, - bindings: LogMeta = {}, -): WrappedPino { - const pinoLogger = pino({ - base: null, - level: level || LogLevel.INFO, - enabled: disabled !== true, - timestamp: false, - formatters: { - level: pinoLogLevelFormatter, - }, - transport: pretty - ? { - target: 'pino-pretty', - options: { - messageKey: 'message', - translateTime: "SYS:yyyy-mm-dd, HH:MM:ss'Z'", - colorize: true, - }, - } - : undefined, - }); - - return new WrappedPino(pinoLogger, { ...bindings, name }); -} diff --git a/packages/apps/reputation-oracle/server/src/logger/types.ts b/packages/apps/reputation-oracle/server/src/logger/types.ts deleted file mode 100644 index 4c5eb3fe1f..0000000000 --- a/packages/apps/reputation-oracle/server/src/logger/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -export enum LogLevel { - DEBUG = 'debug', - INFO = 'info', - WARN = 'warn', - ERROR = 'error', -} - -export type LogMeta = Record; - -export type LogRecord = { - logger?: string; - level: `${LogLevel}`; - message: string; - timestamp: number; -} & LogMeta; - -type LogFn = { - (message: string, meta?: LogMeta): void; - (message: string, error: Error): void; - (message: string, errorOrMeta?: unknown): void; -}; - -export type ChildBindings = { name?: string } & LogMeta; - -export interface Logger { - debug: LogFn; - info: LogFn; - warn: LogFn; - error: LogFn; - child: (bindings: ChildBindings) => Logger; -} - -export type LoggerOptions = { - name?: string; - pretty?: boolean; - level?: `${LogLevel}`; - disabled?: boolean; -}; diff --git a/packages/apps/reputation-oracle/server/src/main.ts b/packages/apps/reputation-oracle/server/src/main.ts index 62c688a44b..ad9e768fe3 100644 --- a/packages/apps/reputation-oracle/server/src/main.ts +++ b/packages/apps/reputation-oracle/server/src/main.ts @@ -9,7 +9,7 @@ import { IncomingMessage, ServerResponse } from 'http'; import { AppModule } from './app.module'; import { ServerConfigService } from './config'; -import logger, { nestLoggerOverride } from './logger'; +import logger, { nestLoggerOverride } from '@human-protocol/logger'; function rawBodyMiddleware( req: any, diff --git a/packages/apps/reputation-oracle/server/src/modules/abuse/abuse.service.ts b/packages/apps/reputation-oracle/server/src/modules/abuse/abuse.service.ts index 04c3b30015..17c4a7b661 100644 --- a/packages/apps/reputation-oracle/server/src/modules/abuse/abuse.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/abuse/abuse.service.ts @@ -8,7 +8,7 @@ import { Injectable } from '@nestjs/common'; import { ethers } from 'ethers'; import { isDuplicatedError } from '../../database'; import { ServerConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { Web3Service } from '../web3'; import { OutgoingWebhookEventType, OutgoingWebhookService } from '../webhook'; diff --git a/packages/apps/reputation-oracle/server/src/modules/auth/auth.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/auth/auth.error-filter.ts index 4b431061b0..d900d814bf 100644 --- a/packages/apps/reputation-oracle/server/src/modules/auth/auth.error-filter.ts +++ b/packages/apps/reputation-oracle/server/src/modules/auth/auth.error-filter.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { AuthError, diff --git a/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts b/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts index 0dad0671a0..e0062b8057 100644 --- a/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/auth/auth.service.ts @@ -9,7 +9,7 @@ import { ServerConfigService, Web3ConfigService, } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import * as httpUtils from '../../utils/http'; import * as securityUtils from '../../utils/security'; import * as web3Utils from '../../utils/web3'; diff --git a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts index 9d4ce0dbd2..ae0e76b030 100644 --- a/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/cron-job/cron-job.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { AbuseService } from '../abuse'; import { TokenRepository } from '../auth'; diff --git a/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.spec.ts index e069287166..7b005fb1c8 100644 --- a/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.spec.ts @@ -1,11 +1,12 @@ -jest.mock('../../logger'); +jest.mock('@human-protocol/logger'); +jest.mock('@human-protocol/sdk'); import { faker } from '@faker-js/faker'; import { Test, TestingModule } from '@nestjs/testing'; import { MailService } from '@sendgrid/mail'; import { EmailConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import Environment from '../../utils/environment'; import { EmailAction } from './constants'; import { diff --git a/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.ts b/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.ts index eca415c323..9badefe14d 100644 --- a/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/email/sendgrid.service.ts @@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common'; import { MailService } from '@sendgrid/mail'; import { EmailConfigService } from '../../config'; -import logger from '../../logger'; import Environment from '../../utils/environment'; import { EmailAction, SENDGRID_API_KEY_REGEX } from './constants'; import { EmailService } from './email.service'; +import logger from '@human-protocol/logger'; + export const SENDGRID_TEMPLATES = { signup: 'd-ca99cc7410aa4e6dab3e6042d5ecb9a3', resetPassword: 'd-3ac74546352a4e1abdd1689947632c22', diff --git a/packages/apps/reputation-oracle/server/src/modules/encryption/pgp-encryption.service.ts b/packages/apps/reputation-oracle/server/src/modules/encryption/pgp-encryption.service.ts index 03ad18e601..a96f33d61d 100644 --- a/packages/apps/reputation-oracle/server/src/modules/encryption/pgp-encryption.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/encryption/pgp-encryption.service.ts @@ -7,7 +7,7 @@ import { import { Injectable, OnModuleInit } from '@nestjs/common'; import { PGPConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { Web3Service } from '../web3'; diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts index a61c4f351f..a27c9f374d 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts @@ -18,7 +18,7 @@ import { BACKOFF_INTERVAL_SECONDS } from '../../common/constants'; import { isDuplicatedError } from '../../database'; import { JobManifest, JobRequestType } from '../../common/types'; import { ServerConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { calculateExponentialBackoffMs } from '../../utils/backoff'; import * as manifestUtils from '../../utils/manifest'; diff --git a/packages/apps/reputation-oracle/server/src/modules/health/health.controller.spec.ts b/packages/apps/reputation-oracle/server/src/modules/health/health.controller.spec.ts index a337df5c3e..a473dd1142 100644 --- a/packages/apps/reputation-oracle/server/src/modules/health/health.controller.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/health/health.controller.spec.ts @@ -7,7 +7,7 @@ import { TerminusModule, TypeOrmHealthIndicator, } from '@nestjs/terminus'; -import { nestLoggerOverride } from '../../logger'; +import { nestLoggerOverride } from '@human-protocol/logger'; import { ServerConfigService } from '../../config'; import { HealthController } from './health.controller'; diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error-filter.ts index 6d895fab85..cc2ba85c28 100644 --- a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error-filter.ts +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.error-filter.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { KycError } from './kyc.error'; @Catch(KycError) diff --git a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts index 3f53f928c4..681a198b93 100644 --- a/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/kyc/kyc.service.ts @@ -4,7 +4,7 @@ import { AxiosError } from 'axios'; import { catchError, firstValueFrom } from 'rxjs'; import { KycConfigService, Web3ConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import * as httpUtils from '../../utils/http'; import { UserNotFoundError, UserRepository } from '../user'; import { Web3Service } from '../web3'; diff --git a/packages/apps/reputation-oracle/server/src/modules/nda/nda.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/nda/nda.error-filter.ts index 100e065481..5d0722fa00 100644 --- a/packages/apps/reputation-oracle/server/src/modules/nda/nda.error-filter.ts +++ b/packages/apps/reputation-oracle/server/src/modules/nda/nda.error-filter.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { NDAError } from './nda.error'; @Catch(NDAError) diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error-filter.ts index 29cd162877..e6ea4b7ed6 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error-filter.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.error-filter.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { QualificationError, QualificationErrorMessage, diff --git a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts index ef24fa2681..b54b20c960 100644 --- a/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/qualification/qualification.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { v4 as uuidV4 } from 'uuid'; import { ServerConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { UserRepository, UserStatus } from '../user'; import { QualificationEntity } from './qualification.entity'; diff --git a/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts b/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts index 8a83b70a73..ba3fe31cc6 100644 --- a/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/storage/storage.service.ts @@ -3,7 +3,7 @@ import * as Minio from 'minio'; import { ContentType } from '../../common/enums'; import { S3ConfigService } from '../../config'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import * as httpUtils from '../../utils/http'; import { PgpEncryptionService } from '../encryption'; diff --git a/packages/apps/reputation-oracle/server/src/modules/user/user.error-filter.ts b/packages/apps/reputation-oracle/server/src/modules/user/user.error-filter.ts index 378df84c65..994c8c12d8 100644 --- a/packages/apps/reputation-oracle/server/src/modules/user/user.error-filter.ts +++ b/packages/apps/reputation-oracle/server/src/modules/user/user.error-filter.ts @@ -6,7 +6,7 @@ import { } from '@nestjs/common'; import { Request, Response } from 'express'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { UserError, diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts index b877cca8ec..9caed51404 100644 --- a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-incoming.service.ts @@ -5,7 +5,7 @@ import { isDuplicatedError } from '../../database'; import { ServerConfigService } from '../../config'; import { EscrowCompletionService } from '../escrow-completion'; import { calculateExponentialBackoffMs } from '../../utils/backoff'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { IncomingWebhookData, IncomingWebhookStatus } from './types'; import { IncomingWebhookEntity } from './webhook-incoming.entity'; diff --git a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts index c2fb0e56a4..ca471dbca9 100644 --- a/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/webhook/webhook-outgoing.service.ts @@ -13,7 +13,7 @@ import { calculateExponentialBackoffMs } from '../../utils/backoff'; import { transformKeysFromCamelToSnake } from '../../utils/case-converters'; import { formatAxiosError } from '../../utils/http'; import { signMessage } from '../../utils/web3'; -import logger from '../../logger'; +import logger from '@human-protocol/logger'; import { OutgoingWebhookStatus } from './types'; import { OutgoingWebhookEntity } from './webhook-outgoing.entity'; diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json index ea48fbcc39..3574766e01 100644 --- a/packages/libs/logger/package.json +++ b/packages/libs/logger/package.json @@ -7,7 +7,7 @@ "scripts": { "build": "tsc", "clean": "rm -rf dist", - "test": "jest", + "test": "jest --passWithNoTests", "test:watch": "jest --watch", "lint": "eslint \"src/**/*.ts\" --fix" }, diff --git a/packages/libs/logger/tsconfig.json b/packages/libs/logger/tsconfig.json index 0f92f4d445..cbeba0a438 100644 --- a/packages/libs/logger/tsconfig.json +++ b/packages/libs/logger/tsconfig.json @@ -15,7 +15,8 @@ "moduleResolution": "node", "resolveJsonModule": true, "experimentalDecorators": true, - "emitDecoratorMetadata": true + "emitDecoratorMetadata": true, + "useDefineForClassFields": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] diff --git a/yarn.lock b/yarn.lock index e092f6ed77..92c6a993b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3952,6 +3952,7 @@ __metadata: resolution: "@human-protocol/dashboard-server@workspace:packages/apps/dashboard/server" dependencies: "@human-protocol/core": "workspace:*" + "@human-protocol/logger": "workspace:*" "@human-protocol/sdk": "workspace:*" "@nestjs/axios": "npm:^3.1.2" "@nestjs/cache-manager": "npm:^2.2.2" @@ -4084,6 +4085,7 @@ __metadata: resolution: "@human-protocol/fortune-exchange-oracle-server@workspace:packages/apps/fortune/exchange-oracle/server" dependencies: "@golevelup/ts-jest": "npm:^0.6.1" + "@human-protocol/logger": "workspace:*" "@human-protocol/sdk": "workspace:*" "@nestjs/axios": "npm:^3.1.2" "@nestjs/cli": "npm:^10.3.2" @@ -4249,6 +4251,7 @@ __metadata: "@automapper/classes": "npm:^8.8.1" "@automapper/core": "npm:^8.8.1" "@automapper/nestjs": "npm:^8.8.1" + "@human-protocol/logger": "workspace:*" "@human-protocol/sdk": "workspace:*" "@nestjs/axios": "npm:^3.1.2" "@nestjs/cache-manager": "npm:^2.2.1" @@ -4363,6 +4366,7 @@ __metadata: "@golevelup/ts-jest": "npm:^0.6.1" "@google-cloud/storage": "npm:^7.15.0" "@google-cloud/vision": "npm:^4.3.2" + "@human-protocol/logger": "workspace:*" "@human-protocol/sdk": "workspace:*" "@nestjs/axios": "npm:^3.1.2" "@nestjs/cli": "npm:^10.3.2" @@ -4428,6 +4432,22 @@ __metadata: languageName: unknown linkType: soft +"@human-protocol/logger@workspace:*, @human-protocol/logger@workspace:packages/libs/logger": + version: 0.0.0-use.local + resolution: "@human-protocol/logger@workspace:packages/libs/logger" + dependencies: + "@types/jest": "npm:^29.5.12" + "@types/node": "npm:^22.10.5" + jest: "npm:^29.7.0" + pino: "npm:^9.6.0" + pino-pretty: "npm:^13.0.0" + ts-jest: "npm:^29.2.5" + typescript: "npm:^5.6.3" + peerDependencies: + "@nestjs/common": ^10.0.0 + languageName: unknown + linkType: soft + "@human-protocol/reputation-oracle@workspace:packages/apps/reputation-oracle/server": version: 0.0.0-use.local resolution: "@human-protocol/reputation-oracle@workspace:packages/apps/reputation-oracle/server" @@ -4435,6 +4455,7 @@ __metadata: "@faker-js/faker": "npm:^9.4.0" "@golevelup/ts-jest": "npm:^0.6.1" "@human-protocol/core": "workspace:*" + "@human-protocol/logger": "workspace:*" "@human-protocol/sdk": "workspace:*" "@nestjs/axios": "npm:^3.1.3" "@nestjs/cli": "npm:^10.3.2" @@ -4486,8 +4507,6 @@ __metadata: passport: "npm:^0.7.0" passport-jwt: "npm:^4.0.1" pg: "npm:8.13.1" - pino: "npm:^9.6.0" - pino-pretty: "npm:^13.0.0" prettier: "npm:^3.4.2" reflect-metadata: "npm:^0.2.2" rxjs: "npm:^7.2.0" @@ -9829,6 +9848,16 @@ __metadata: languageName: node linkType: hard +"@types/jest@npm:^29.5.12": + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" + dependencies: + expect: "npm:^29.0.0" + pretty-format: "npm:^29.0.0" + checksum: 10c0/18e0712d818890db8a8dab3d91e9ea9f7f19e3f83c2e50b312f557017dc81466207a71f3ed79cf4428e813ba939954fa26ffa0a9a7f153181ba174581b1c2aed + languageName: node + linkType: hard + "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -25663,6 +25692,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.2": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + "send@npm:0.19.0": version: 0.19.0 resolution: "send@npm:0.19.0" @@ -27395,6 +27433,46 @@ __metadata: languageName: node linkType: hard +"ts-jest@npm:^29.2.5": + version: 29.4.0 + resolution: "ts-jest@npm:29.4.0" + dependencies: + bs-logger: "npm:^0.2.6" + ejs: "npm:^3.1.10" + fast-json-stable-stringify: "npm:^2.1.0" + json5: "npm:^2.2.3" + lodash.memoize: "npm:^4.1.2" + make-error: "npm:^1.3.6" + semver: "npm:^7.7.2" + type-fest: "npm:^4.41.0" + yargs-parser: "npm:^21.1.1" + peerDependencies: + "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/transform": ^29.0.0 || ^30.0.0 + "@jest/types": ^29.0.0 || ^30.0.0 + babel-jest: ^29.0.0 || ^30.0.0 + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: ">=4.3 <6" + peerDependenciesMeta: + "@babel/core": + optional: true + "@jest/transform": + optional: true + "@jest/types": + optional: true + babel-jest: + optional: true + esbuild: + optional: true + jest-util: + optional: true + bin: + ts-jest: cli.js + checksum: 10c0/c266431200786995b5bd32f8e61f17a564ce231278aace1d98fb0ae670f24013aeea06c90ec6019431e5a6f5e798868785131bef856085c931d193e2efbcea04 + languageName: node + linkType: hard + "ts-node@npm:^10.0.0, ts-node@npm:^10.9.1, ts-node@npm:^10.9.2": version: 10.9.2 resolution: "ts-node@npm:10.9.2" @@ -27618,7 +27696,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^4.37.0": +"type-fest@npm:^4.37.0, type-fest@npm:^4.41.0": version: 4.41.0 resolution: "type-fest@npm:4.41.0" checksum: 10c0/f5ca697797ed5e88d33ac8f1fec21921839871f808dc59345c9cf67345bfb958ce41bd821165dbf3ae591cedec2bf6fe8882098dfdd8dc54320b859711a2c1e4 From ccb6cf1312da3bc585839d9ddc190792147cf10d Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Mon, 23 Jun 2025 16:19:23 +0300 Subject: [PATCH 04/13] Update dashboard logger dependency --- .../src/common/config/cache-factory.config.ts | 6 ++++-- packages/apps/dashboard/server/src/main.ts | 8 +++----- .../server/src/modules/details/details.service.ts | 8 ++++++-- .../src/modules/networks/networks.service.ts | 8 ++++++-- .../server/src/modules/stats/stats.service.ts | 14 +++++++++----- .../server/src/modules/storage/storage.service.ts | 10 +++++++--- 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/apps/dashboard/server/src/common/config/cache-factory.config.ts b/packages/apps/dashboard/server/src/common/config/cache-factory.config.ts index d62e2dd1f4..4f28804617 100644 --- a/packages/apps/dashboard/server/src/common/config/cache-factory.config.ts +++ b/packages/apps/dashboard/server/src/common/config/cache-factory.config.ts @@ -3,9 +3,11 @@ import { ConfigModule } from '@nestjs/config'; import * as _ from 'lodash'; import { RedisConfigService } from './redis-config.service'; import { redisStore } from 'cache-manager-redis-yet'; -import { Logger } from '@nestjs/common'; +import Logger from '@human-protocol/logger'; -const logger = new Logger('CacheFactoryRedisStore'); +const logger = Logger.child({ + context: 'CacheFactoryRedisStore', +}); const throttledRedisErrorLog = _.throttle((error) => { logger.error('Redis client network error', error); diff --git a/packages/apps/dashboard/server/src/main.ts b/packages/apps/dashboard/server/src/main.ts index d4bc1caa55..a23dece527 100644 --- a/packages/apps/dashboard/server/src/main.ts +++ b/packages/apps/dashboard/server/src/main.ts @@ -4,13 +4,11 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; import { EnvironmentConfigService } from './common/config/env-config.service'; +import logger, { nestLoggerOverride } from '@human-protocol/logger'; async function bootstrap() { const app = await NestFactory.create(AppModule, { - logger: - process.env.NODE_ENV === 'development' - ? ['log', 'debug', 'error', 'verbose', 'warn'] - : ['log', 'error', 'warn'], + logger: nestLoggerOverride, }); const configService: ConfigService = app.get(ConfigService); @@ -35,7 +33,7 @@ async function bootstrap() { const port = envConfigService.port; await app.listen(port, host, async () => { - console.info(`Dashboard server is running on http://${host}:${port}`); + logger.info(`Dashboard server is running on http://${host}:${port}`); }); } bootstrap(); diff --git a/packages/apps/dashboard/server/src/modules/details/details.service.ts b/packages/apps/dashboard/server/src/modules/details/details.service.ts index 361e674c10..1c3c7cc2d7 100644 --- a/packages/apps/dashboard/server/src/modules/details/details.service.ts +++ b/packages/apps/dashboard/server/src/modules/details/details.service.ts @@ -1,5 +1,5 @@ import { plainToInstance } from 'class-transformer'; -import { BadRequestException, Injectable, Logger } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { ChainId, EscrowUtils, @@ -34,10 +34,14 @@ import { } from '../../common/constants/operator'; import { GetOperatorsPaginationOptions } from 'src/common/types'; import { KVStoreDataDto } from './dto/details-response.dto'; +import Logger from '@human-protocol/logger'; @Injectable() export class DetailsService { - private readonly logger = new Logger(DetailsService.name); + private readonly logger = Logger.child({ + context: DetailsService.name, + }); + constructor( private readonly configService: EnvironmentConfigService, private readonly httpService: HttpService, diff --git a/packages/apps/dashboard/server/src/modules/networks/networks.service.ts b/packages/apps/dashboard/server/src/modules/networks/networks.service.ts index 26e9fbeab2..893604a128 100644 --- a/packages/apps/dashboard/server/src/modules/networks/networks.service.ts +++ b/packages/apps/dashboard/server/src/modules/networks/networks.service.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { ChainId, NETWORKS, StatisticsClient } from '@human-protocol/sdk'; import { Cache, CACHE_MANAGER } from '@nestjs/cache-manager'; @@ -9,10 +9,14 @@ import { } from '../../common/config/env-config.service'; import { OPERATING_NETWORKS_CACHE_KEY } from '../../common/config/redis-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import Logger from '@human-protocol/logger'; @Injectable() export class NetworksService { - private readonly logger = new Logger(NetworksService.name); + private readonly logger = Logger.child({ + context: NetworksService.name, + }); + constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache, private readonly envConfigService: EnvironmentConfigService, diff --git a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts index c40076db3b..90769d967c 100644 --- a/packages/apps/dashboard/server/src/modules/stats/stats.service.ts +++ b/packages/apps/dashboard/server/src/modules/stats/stats.service.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common'; +import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; import { lastValueFrom } from 'rxjs'; import dayjs from 'dayjs'; @@ -25,10 +25,14 @@ import { StorageService } from '../storage/storage.service'; import { CronJob } from 'cron'; import { SchedulerRegistry } from '@nestjs/schedule'; import { NetworksService } from '../networks/networks.service'; +import Logger from '@human-protocol/logger'; @Injectable() export class StatsService implements OnModuleInit { - private readonly logger = new Logger(StatsService.name); + private readonly logger = Logger.child({ + context: StatsService.name, + }); + constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache, private readonly redisConfigService: RedisConfigService, @@ -75,7 +79,7 @@ export class StatsService implements OnModuleInit { } private async fetchHistoricalHcaptchaStats(): Promise { - this.logger.log('Fetching historical hCaptcha stats.'); + this.logger.info('Fetching historical hCaptcha stats.'); let startDate = dayjs(HCAPTCHA_STATS_API_START_DATE); const currentDate = dayjs(); const dates = []; @@ -132,7 +136,7 @@ export class StatsService implements OnModuleInit { } async fetchTodayHcaptchaStats() { - this.logger.log('Fetching hCaptcha stats for today.'); + this.logger.info('Fetching hCaptcha stats for today.'); const today = dayjs().format('YYYY-MM-DD'); const from = today; const to = today; @@ -188,7 +192,7 @@ export class StatsService implements OnModuleInit { @Cron('*/15 * * * *') async fetchHmtGeneralStats() { - this.logger.log('Fetching HMT general stats across multiple networks.'); + this.logger.info('Fetching HMT general stats across multiple networks.'); const aggregatedStats: HmtGeneralStatsDto = { totalHolders: 0, totalTransactions: 0, diff --git a/packages/apps/dashboard/server/src/modules/storage/storage.service.ts b/packages/apps/dashboard/server/src/modules/storage/storage.service.ts index 5cb3f09d83..6de6af4b86 100644 --- a/packages/apps/dashboard/server/src/modules/storage/storage.service.ts +++ b/packages/apps/dashboard/server/src/modules/storage/storage.service.ts @@ -1,11 +1,15 @@ -import { Injectable, Logger, NotFoundException } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import * as Minio from 'minio'; import { S3ConfigService } from '../../common/config/s3-config.service'; import { Readable } from 'stream'; +import Logger from '@human-protocol/logger'; @Injectable() export class StorageService { - private readonly logger = new Logger(StorageService.name); + private readonly logger = Logger.child({ + context: StorageService.name, + }); + public readonly minioClient: Minio.Client; constructor(private s3ConfigService: S3ConfigService) { @@ -52,7 +56,7 @@ export class StorageService { }); }); } catch (e) { - this.logger.log(e); + this.logger.info(e); return []; } } From cce8b5426e611a0a3deb4395957e3ace30d94102 Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Mon, 23 Jun 2025 16:33:22 +0300 Subject: [PATCH 05/13] Update job-launcher logger dependency --- .../src/common/exceptions/exception.filter.ts | 6 ++- .../src/common/guards/signature.auth.ts | 12 +++--- .../src/common/guards/whitelist.auth.ts | 12 +++--- .../server/src/common/utils/slack.ts | 8 ++-- .../database/typeorm/typeorm-logger.module.ts | 2 +- packages/apps/job-launcher/server/src/main.ts | 4 +- .../src/modules/auth/auth.controller.ts | 13 +++--- .../gcv-content-moderation.service.ts | 9 ++-- .../src/modules/cron-job/cron-job.service.ts | 41 ++++++++++--------- .../server/src/modules/job/job.service.ts | 14 ++++--- .../src/modules/manifest/manifest.service.ts | 7 +++- .../modules/mutex/mutex-manager.service.ts | 16 +++++--- .../src/modules/payment/payment.service.ts | 16 +++++--- .../qualification/qualification.service.ts | 7 +++- .../server/src/modules/rate/rate.service.ts | 8 +++- .../routing-protocol.service.ts | 8 +++- .../src/modules/sendgrid/sendgrid.service.ts | 13 +++--- .../server/src/modules/web3/web3.service.ts | 8 +++- .../src/modules/webhook/webhook.repository.ts | 9 +++- .../src/modules/webhook/webhook.service.ts | 7 +++- 20 files changed, 136 insertions(+), 84 deletions(-) diff --git a/packages/apps/job-launcher/server/src/common/exceptions/exception.filter.ts b/packages/apps/job-launcher/server/src/common/exceptions/exception.filter.ts index 7ad8be772a..a2b28d02a1 100644 --- a/packages/apps/job-launcher/server/src/common/exceptions/exception.filter.ts +++ b/packages/apps/job-launcher/server/src/common/exceptions/exception.filter.ts @@ -3,7 +3,6 @@ import { Catch, ExceptionFilter as IExceptionFilter, HttpStatus, - Logger, } from '@nestjs/common'; import { Request, Response } from 'express'; import { @@ -15,10 +14,13 @@ import { ServerError, DatabaseError, } from '../errors'; +import Logger from '@human-protocol/logger'; @Catch() export class ExceptionFilter implements IExceptionFilter { - private logger = new Logger(ExceptionFilter.name); + private logger = Logger.child({ + context: ExceptionFilter.name, + }); private getStatus(exception: any): number { if (exception instanceof ValidationError) { diff --git a/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts b/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts index 8b536358f5..769afd269c 100644 --- a/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts +++ b/packages/apps/job-launcher/server/src/common/guards/signature.auth.ts @@ -1,18 +1,16 @@ import { EscrowUtils } from '@human-protocol/sdk'; -import { - CanActivate, - ExecutionContext, - Injectable, - Logger, -} from '@nestjs/common'; +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { HEADER_SIGNATURE_KEY } from '../constants'; import { Role } from '../enums/role'; import { AuthError } from '../errors'; import { verifySignature } from '../utils/signature'; +import Logger from '@human-protocol/logger'; @Injectable() export class SignatureAuthGuard implements CanActivate { - private readonly logger = new Logger(SignatureAuthGuard.name); + private readonly logger = Logger.child({ + context: SignatureAuthGuard.name, + }); constructor(private role: Role[]) {} diff --git a/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.ts b/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.ts index 5683a2b81f..2a7546e8e8 100644 --- a/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.ts +++ b/packages/apps/job-launcher/server/src/common/guards/whitelist.auth.ts @@ -1,15 +1,13 @@ -import { - CanActivate, - ExecutionContext, - Injectable, - Logger, -} from '@nestjs/common'; +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { WhitelistService } from '../../modules/whitelist/whitelist.service'; import { AuthError } from '../errors'; +import logger from '@human-protocol/logger'; @Injectable() export class WhitelistAuthGuard implements CanActivate { - private readonly logger = new Logger(WhitelistAuthGuard.name); + private readonly logger = logger.child({ + context: WhitelistAuthGuard.name, + }); constructor(private readonly whitelistService: WhitelistService) {} diff --git a/packages/apps/job-launcher/server/src/common/utils/slack.ts b/packages/apps/job-launcher/server/src/common/utils/slack.ts index e74d4fd02f..f74cfee993 100644 --- a/packages/apps/job-launcher/server/src/common/utils/slack.ts +++ b/packages/apps/job-launcher/server/src/common/utils/slack.ts @@ -1,11 +1,13 @@ -import { Logger } from '@nestjs/common'; import axios from 'axios'; +import Logger from '@human-protocol/logger'; export async function sendSlackNotification( webhookUrl: string, message: string, ): Promise { - const logger = new Logger('Slack'); + const logger = Logger.child({ + context: 'Slack', + }); const payload = { text: message, @@ -17,7 +19,7 @@ export async function sendSlackNotification( try { await axios.post(webhookUrl, payload); - logger.log('Slack notification sent:', payload); + logger.info('Slack notification sent:', payload); return true; } catch (e) { logger.error('Error sending Slack notification:', e); diff --git a/packages/apps/job-launcher/server/src/database/typeorm/typeorm-logger.module.ts b/packages/apps/job-launcher/server/src/database/typeorm/typeorm-logger.module.ts index b3bc43d760..3034b3e9ee 100644 --- a/packages/apps/job-launcher/server/src/database/typeorm/typeorm-logger.module.ts +++ b/packages/apps/job-launcher/server/src/database/typeorm/typeorm-logger.module.ts @@ -1,4 +1,4 @@ -import { Module, Logger } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { TypeOrmLoggerService } from './typeorm-logger.service'; diff --git a/packages/apps/job-launcher/server/src/main.ts b/packages/apps/job-launcher/server/src/main.ts index bb5e4019e0..093250b6ec 100644 --- a/packages/apps/job-launcher/server/src/main.ts +++ b/packages/apps/job-launcher/server/src/main.ts @@ -8,12 +8,14 @@ import { useContainer } from 'class-validator'; import helmet from 'helmet'; import { AppModule } from './app.module'; import { ServerConfigService } from './common/config/server-config.service'; +import logger, { nestLoggerOverride } from '@human-protocol/logger'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: { exposedHeaders: ['Content-Disposition'], }, + logger: nestLoggerOverride, }); useContainer(app.select(AppModule), { fallbackOnErrors: true }); @@ -38,7 +40,7 @@ async function bootstrap() { const port = serverConfigService.port; await app.listen(port, host, async () => { - console.info(`API server is running on http://${host}:${port}`); + logger.info(`API server is running on http://${host}:${port}`); }); } diff --git a/packages/apps/job-launcher/server/src/modules/auth/auth.controller.ts b/packages/apps/job-launcher/server/src/modules/auth/auth.controller.ts index cdd9440f7f..c93bfeea2d 100644 --- a/packages/apps/job-launcher/server/src/modules/auth/auth.controller.ts +++ b/packages/apps/job-launcher/server/src/modules/auth/auth.controller.ts @@ -4,7 +4,6 @@ import { Controller, HttpCode, Ip, - Logger, Post, Req, Request, @@ -38,6 +37,7 @@ import { import { AuthService } from './auth.service'; import { TokenType } from './token.entity'; import { TokenRepository } from './token.repository'; +import Logger from '@human-protocol/logger'; @ApiTags('Auth') @ApiResponse({ @@ -58,7 +58,9 @@ import { TokenRepository } from './token.repository'; }) @Controller('/auth') export class AuthJwtController { - private readonly logger = new Logger(AuthJwtController.name); + private readonly logger = Logger.child({ + context: AuthJwtController.name, + }); constructor( private readonly authService: AuthService, @@ -246,10 +248,9 @@ export class AuthJwtController { const apiKey = await this.authService.createOrUpdateAPIKey(req.user); return { apiKey }; } catch (e) { - this.logger.log( - e.message, - `${AuthJwtController.name} - ${ErrorAuth.ApiKeyCouldNotBeCreatedOrUpdated}`, - ); + this.logger.error(e.message, { + context: `${AuthJwtController.name} - ${ErrorAuth.ApiKeyCouldNotBeCreatedOrUpdated}`, + }); throw new ValidationError(ErrorAuth.ApiKeyCouldNotBeCreatedOrUpdated); } } diff --git a/packages/apps/job-launcher/server/src/modules/content-moderation/gcv-content-moderation.service.ts b/packages/apps/job-launcher/server/src/modules/content-moderation/gcv-content-moderation.service.ts index d4bd6f8b0c..46f018b3fa 100644 --- a/packages/apps/job-launcher/server/src/modules/content-moderation/gcv-content-moderation.service.ts +++ b/packages/apps/job-launcher/server/src/modules/content-moderation/gcv-content-moderation.service.ts @@ -1,6 +1,6 @@ import { Storage } from '@google-cloud/storage'; import { ImageAnnotatorClient, protos } from '@google-cloud/vision'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import NodeCache from 'node-cache'; import { SlackConfigService } from '../../common/config/slack-config.service'; import { VisionConfigService } from '../../common/config/vision-config.service'; @@ -31,10 +31,13 @@ import { ContentModerationRequestEntity } from './content-moderation-request.ent import { ContentModerationRequestRepository } from './content-moderation-request.repository'; import { ModerationResultDto } from './content-moderation.dto'; import { IContentModeratorService } from './content-moderation.interface'; +import Logger from '@human-protocol/logger'; @Injectable() export class GCVContentModerationService implements IContentModeratorService { - private readonly logger = new Logger(GCVContentModerationService.name); + private readonly logger = Logger.child({ + context: GCVContentModerationService.name, + }); private visionClient: ImageAnnotatorClient; private storage: Storage; @@ -327,7 +330,7 @@ export class GCVContentModerationService implements IContentModeratorService { const [operation] = await this.visionClient.asyncBatchAnnotateImages(requestPayload); const [filesResponse] = await operation.promise(); - this.logger.log( + this.logger.info( `Output written to GCS: ${filesResponse?.outputConfig?.gcsDestination?.uri}`, ); } catch (error) { diff --git a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts index abfc46cea1..4721f4f0f5 100644 --- a/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/cron-job/cron-job.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import { ErrorContentModeration, @@ -30,10 +30,13 @@ import { WebhookRepository } from '../webhook/webhook.repository'; import { WebhookService } from '../webhook/webhook.service'; import { CronJobEntity } from './cron-job.entity'; import { CronJobRepository } from './cron-job.repository'; +import Logger from '@human-protocol/logger'; @Injectable() export class CronJobService { - private readonly logger = new Logger(CronJobService.name); + private readonly logger = Logger.child({ + context: CronJobService.name, + }); constructor( private readonly cronJobRepository: CronJobRepository, @@ -67,7 +70,7 @@ export class CronJobService { return false; } - this.logger.log('Previous cron job is not completed yet'); + this.logger.info('Previous cron job is not completed yet'); return true; } @@ -132,7 +135,7 @@ export class CronJobService { return; } - this.logger.log('Create escrow START'); + this.logger.info('Create escrow START'); const cronJob = await this.startCronJob(CronJobType.CreateEscrow); try { @@ -158,7 +161,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Create escrow STOP'); + this.logger.info('Create escrow STOP'); await this.completeCronJob(cronJob); } @@ -172,7 +175,7 @@ export class CronJobService { return; } - this.logger.log('Setup escrow START'); + this.logger.info('Setup escrow START'); const cronJob = await this.startCronJob(CronJobType.SetupEscrow); try { @@ -199,7 +202,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Setup escrow STOP'); + this.logger.info('Setup escrow STOP'); await this.completeCronJob(cronJob); } @@ -213,7 +216,7 @@ export class CronJobService { return; } - this.logger.log('Fund escrow START'); + this.logger.info('Fund escrow START'); const cronJob = await this.startCronJob(CronJobType.FundEscrow); try { @@ -240,7 +243,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Fund escrow STOP'); + this.logger.info('Fund escrow STOP'); await this.completeCronJob(cronJob); } @@ -254,7 +257,7 @@ export class CronJobService { return; } - this.logger.log('Cancel jobs START'); + this.logger.info('Cancel jobs START'); const cronJob = await this.startCronJob(CronJobType.CancelEscrow); try { @@ -320,7 +323,7 @@ export class CronJobService { this.logger.error(e); } await this.completeCronJob(cronJob); - this.logger.log('Cancel jobs STOP'); + this.logger.info('Cancel jobs STOP'); return true; } @@ -338,7 +341,7 @@ export class CronJobService { return; } - this.logger.log('Pending webhooks START'); + this.logger.info('Pending webhooks START'); const cronJob = await this.startCronJob(CronJobType.ProcessPendingWebhook); try { @@ -362,7 +365,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Pending webhooks STOP'); + this.logger.info('Pending webhooks STOP'); await this.completeCronJob(cronJob); } @@ -378,7 +381,7 @@ export class CronJobService { return; } - this.logger.log('Abuse START'); + this.logger.info('Abuse START'); const cronJob = await this.startCronJob(CronJobType.Abuse); try { @@ -395,7 +398,7 @@ export class CronJobService { webhookEntity.escrowAddress, ); if (!jobEntity) { - this.logger.log(ErrorJob.NotFound, JobService.name); + this.logger.info(ErrorJob.NotFound, { context: JobService.name }); throw new NotFoundError(ErrorJob.NotFound); } if ( @@ -424,7 +427,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Abuse STOP'); + this.logger.info('Abuse STOP'); await this.completeCronJob(cronJob); } @@ -442,7 +445,7 @@ export class CronJobService { return; } - this.logger.log('Update jobs START'); + this.logger.info('Update jobs START'); const cronJob = await this.startCronJob(CronJobType.SyncJobStatuses); try { @@ -469,7 +472,7 @@ export class CronJobService { } while (eventsBatch.length === 100); } if (events.length === 0) { - this.logger.log('No events to process'); + this.logger.info('No events to process'); await this.completeCronJob(cronJob); return; } @@ -539,7 +542,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Update jobs STOP'); + this.logger.info('Update jobs STOP'); await this.completeCronJob(cronJob); } } diff --git a/packages/apps/job-launcher/server/src/modules/job/job.service.ts b/packages/apps/job-launcher/server/src/modules/job/job.service.ts index 93d0e9f284..de2cd77946 100644 --- a/packages/apps/job-launcher/server/src/modules/job/job.service.ts +++ b/packages/apps/job-launcher/server/src/modules/job/job.service.ts @@ -9,11 +9,11 @@ import { NETWORKS, StorageParams, } from '@human-protocol/sdk'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; import { - ValidationError as ClassValidationError, validate, + ValidationError as ClassValidationError, } from 'class-validator'; import { ethers } from 'ethers'; import { ServerConfigService } from '../../common/config/server-config.service'; @@ -76,12 +76,17 @@ import { import { JobEntity } from './job.entity'; import { EscrowAction } from './job.interface'; import { JobRepository } from './job.repository'; +import Logger from '@human-protocol/logger'; + @Injectable() export class JobService { - public readonly logger = new Logger(JobService.name); + public readonly logger = Logger.child({ + context: JobService.name, + }); public readonly storageParams: StorageParams; public readonly bucket: string; private cronJobRepository: CronJobRepository; + constructor( @Inject(Web3Service) private readonly web3Service: Web3Service, @@ -583,9 +588,8 @@ export class JobService { } if (allFortuneValidationErrors.length > 0) { - this.logger.log( + this.logger.info( ErrorJob.ResultValidationFailed, - JobService.name, allFortuneValidationErrors, ); throw new ValidationError(ErrorJob.ResultValidationFailed); diff --git a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts index 61836dde66..7cd83ea3b9 100644 --- a/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts +++ b/packages/apps/job-launcher/server/src/modules/manifest/manifest.service.ts @@ -8,7 +8,6 @@ import { import { ValidationError as ClassValidationError, Injectable, - Logger, } from '@nestjs/common'; import { validate } from 'class-validator'; import { ethers } from 'ethers'; @@ -71,10 +70,14 @@ import { ManifestDto, RestrictedAudience, } from './manifest.dto'; +import Logger from '@human-protocol/logger'; @Injectable() export class ManifestService { - public readonly logger = new Logger(ManifestService.name); + public readonly logger = Logger.child({ + context: ManifestService.name, + }); + public readonly storageParams: StorageParams; public readonly bucket: string; diff --git a/packages/apps/job-launcher/server/src/modules/mutex/mutex-manager.service.ts b/packages/apps/job-launcher/server/src/modules/mutex/mutex-manager.service.ts index 159face8a5..6bfd04b488 100644 --- a/packages/apps/job-launcher/server/src/modules/mutex/mutex-manager.service.ts +++ b/packages/apps/job-launcher/server/src/modules/mutex/mutex-manager.service.ts @@ -1,13 +1,17 @@ -import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common'; +import { Injectable, OnModuleDestroy } from '@nestjs/common'; import { E_TIMEOUT, Mutex, MutexInterface, withTimeout } from 'async-mutex'; import { ServerError } from '../../common/errors'; +import Logger from '@human-protocol/logger'; @Injectable() export class MutexManagerService implements OnModuleDestroy { private mutexes: WeakMap = new WeakMap(); private mutexTimeouts: Map = new Map(); private mutexTimeoutDuration = 120000; // 2 minutes - public readonly logger = new Logger(MutexManagerService.name); + + public readonly logger = Logger.child({ + context: MutexManagerService.name, + }); private getMutex(key: object, timeout: number): MutexInterface { if (!this.mutexes.has(key)) { @@ -46,16 +50,18 @@ export class MutexManagerService implements OnModuleDestroy { ): Promise { const mutex = this.getMutex(key, timeout); try { - this.logger.log( + this.logger.info( `Attempting to acquire lock for ${(key as any).id as string}...`, ); const result = await mutex.runExclusive(async () => { - this.logger.log( + this.logger.info( `Lock acquired for ${(key as any).id as string}, executing function...`, ); - this.logger.log( + + this.logger.info( `Function executed for ${(key as any).id as string}, lock released.`, ); + return await callback(); }); return result; diff --git a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts index 0809be590b..faec950c51 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/payment.service.ts @@ -3,7 +3,7 @@ import { HMToken, HMToken__factory, } from '@human-protocol/core/typechain-types'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ethers, formatUnits } from 'ethers'; import Stripe from 'stripe'; import { NetworkConfigService } from '../../common/config/network-config.service'; @@ -40,6 +40,7 @@ import { } from './payment.dto'; import { PaymentEntity } from './payment.entity'; import { PaymentRepository } from './payment.repository'; +import Logger from '@human-protocol/logger'; import { TOKEN_ADDRESSES } from '../../common/constants/tokens'; import { EscrowFundToken } from '../../common/enums/job'; @@ -53,7 +54,10 @@ import { UserRepository } from '../user/user.repository'; @Injectable() export class PaymentService { - private readonly logger = new Logger(PaymentService.name); + private readonly logger = Logger.child({ + context: PaymentService.name, + }); + private stripe: Stripe; constructor( @@ -91,7 +95,7 @@ export class PaymentService { }) ).id; } catch (error) { - this.logger.log(error.message, PaymentService.name); + this.logger.error(error.message, PaymentService.name); throw new ServerError(ErrorPayment.CustomerNotCreated); } } @@ -104,13 +108,13 @@ export class PaymentService { customer: customerId ?? undefined, }); } catch (error) { - this.logger.log(error.message, PaymentService.name); + this.logger.error(error.message, PaymentService.name); throw new ServerError(ErrorPayment.CardNotAssigned); } // Ensure the SetupIntent contains a client secret for completing the card setup process. if (!setupIntent?.client_secret) { - this.logger.log( + this.logger.error( ErrorPayment.ClientSecretDoesNotExist, PaymentService.name, ); @@ -128,7 +132,7 @@ export class PaymentService { const setup = await this.stripe.setupIntents.retrieve(data.setupId); if (!setup) { - this.logger.log(ErrorPayment.SetupNotFound, PaymentService.name); + this.logger.error(ErrorPayment.SetupNotFound, PaymentService.name); throw new NotFoundError(ErrorPayment.SetupNotFound); } diff --git a/packages/apps/job-launcher/server/src/modules/qualification/qualification.service.ts b/packages/apps/job-launcher/server/src/modules/qualification/qualification.service.ts index 00837e962a..6188ba4b0b 100644 --- a/packages/apps/job-launcher/server/src/modules/qualification/qualification.service.ts +++ b/packages/apps/job-launcher/server/src/modules/qualification/qualification.service.ts @@ -1,16 +1,19 @@ import { ChainId, KVStoreKeys, KVStoreUtils } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { firstValueFrom } from 'rxjs'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ErrorQualification, ErrorWeb3 } from '../../common/constants/errors'; import { ServerError } from '../../common/errors'; import { Web3Service } from '../web3/web3.service'; import { QualificationDto } from './qualification.dto'; +import Logger from '@human-protocol/logger'; @Injectable() export class QualificationService { - private readonly logger = new Logger(QualificationService.name); + private readonly logger = Logger.child({ + context: QualificationService.name, + }); constructor( private httpService: HttpService, diff --git a/packages/apps/job-launcher/server/src/modules/rate/rate.service.ts b/packages/apps/job-launcher/server/src/modules/rate/rate.service.ts index 8c5b008e62..cc9e51a3f2 100644 --- a/packages/apps/job-launcher/server/src/modules/rate/rate.service.ts +++ b/packages/apps/job-launcher/server/src/modules/rate/rate.service.ts @@ -1,5 +1,5 @@ import { HttpService } from '@nestjs/axios'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { firstValueFrom } from 'rxjs'; import { ServerConfigService } from '../../common/config/server-config.service'; import { COINGECKO_API_URL } from '../../common/constants'; @@ -7,10 +7,14 @@ import { ErrorCurrency } from '../../common/constants/errors'; import { CoingeckoTokenId } from '../../common/constants/payment'; import { EscrowFundToken } from '../../common/enums/job'; import { NotFoundError } from '../../common/errors'; +import Logger from '@human-protocol/logger'; @Injectable() export class RateService { - public readonly logger = new Logger(RateService.name); + public readonly logger = Logger.child({ + context: RateService.name, + }); + private cache: Map; constructor( diff --git a/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts b/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts index f57657182b..1811d73c24 100644 --- a/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts +++ b/packages/apps/job-launcher/server/src/modules/routing-protocol/routing-protocol.service.ts @@ -1,5 +1,5 @@ import { ChainId, Role } from '@human-protocol/sdk'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ErrorRoutingProtocol } from '../../common/constants/errors'; @@ -17,6 +17,7 @@ import { OracleIndex, OracleOrder, } from './routing-protocol.interface'; +import Logger from '@human-protocol/logger'; type OracleValue = { [reputationOracle: string]: { @@ -26,7 +27,10 @@ type OracleValue = { @Injectable() export class RoutingProtocolService { - public readonly logger = new Logger(RoutingProtocolService.name); + public readonly logger = Logger.child({ + context: RoutingProtocolService.name, + }); + private readonly chains: ChainId[]; private readonly reputationOracles: string[]; private readonly chainPriorityOrder: number[]; diff --git a/packages/apps/job-launcher/server/src/modules/sendgrid/sendgrid.service.ts b/packages/apps/job-launcher/server/src/modules/sendgrid/sendgrid.service.ts index 5a5c9bd71f..ba07477206 100644 --- a/packages/apps/job-launcher/server/src/modules/sendgrid/sendgrid.service.ts +++ b/packages/apps/job-launcher/server/src/modules/sendgrid/sendgrid.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { MailDataRequired, MailService } from '@sendgrid/mail'; import { SendgridConfigService } from '../../common/config/sendgrid-config.service'; import { @@ -7,10 +7,13 @@ import { } from '../../common/constants'; import { ErrorSendGrid } from '../../common/constants/errors'; import { ConflictError, ServerError } from '../../common/errors'; +import Logger from '@human-protocol/logger'; @Injectable() export class SendGridService { - private readonly logger = new Logger(SendGridService.name); + private readonly logger = Logger.child({ + context: SendGridService.name, + }); private readonly defaultFromEmail: string; private readonly defaultFromName: string; @@ -44,7 +47,7 @@ export class SendGridService { }: Partial): Promise { try { if (this.sendgridConfigService.apiKey === SENDGRID_API_KEY_DISABLED) { - this.logger.debug(personalizations); + this.logger.debug('Stripe disabled key', personalizations); return; } @@ -54,10 +57,10 @@ export class SendGridService { personalizations, ...emailData, }); - this.logger.log('Email sent successfully'); + this.logger.info('Email sent successfully'); return; } catch (error) { - this.logger.error(error, SendGridService.name); + this.logger.error(error, { context: SendGridService.name }); throw new ServerError(ErrorSendGrid.EmailNotSent); } } diff --git a/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts b/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts index b05e971802..9ae71a5bec 100644 --- a/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts +++ b/packages/apps/job-launcher/server/src/modules/web3/web3.service.ts @@ -1,15 +1,19 @@ import { ChainId, OperatorUtils, Role } from '@human-protocol/sdk'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { Wallet, ethers } from 'ethers'; import { NetworkConfigService } from '../../common/config/network-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { ErrorWeb3 } from '../../common/constants/errors'; import { ConflictError, ValidationError } from '../../common/errors'; import { AvailableOraclesDto, OracleDataDto } from './web3.dto'; +import Logger from '@human-protocol/logger'; @Injectable() export class Web3Service { - public readonly logger = new Logger(Web3Service.name); + public readonly logger = Logger.child({ + context: Web3Service.name, + }); + private signers: { [key: number]: Wallet } = {}; public readonly signerAddress: string; diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts index 1c5fe17804..a774955165 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.repository.ts @@ -1,20 +1,25 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { BaseRepository } from '../../database/base.repository'; import { DataSource, In, LessThanOrEqual } from 'typeorm'; import { ServerConfigService } from '../../common/config/server-config.service'; import { EventType, WebhookStatus } from '../../common/enums/webhook'; import { WebhookEntity } from './webhook.entity'; +import Logger from '@human-protocol/logger'; @Injectable() export class WebhookRepository extends BaseRepository { - private readonly logger = new Logger(WebhookRepository.name); + private readonly logger = Logger.child({ + context: WebhookRepository.name, + }); + constructor( private dataSource: DataSource, public readonly serverConfigService: ServerConfigService, ) { super(WebhookEntity, dataSource); } + public findByStatusAndType( status: WebhookStatus, type: EventType | EventType[], diff --git a/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts b/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts index 4bb967ca39..951875a7cc 100644 --- a/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts +++ b/packages/apps/job-launcher/server/src/modules/webhook/webhook.service.ts @@ -6,7 +6,7 @@ import { KVStoreUtils, } from '@human-protocol/sdk'; import { HttpService } from '@nestjs/axios'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { firstValueFrom } from 'rxjs'; import { ServerConfigService } from '../../common/config/server-config.service'; import { Web3ConfigService } from '../../common/config/web3-config.service'; @@ -23,10 +23,13 @@ import { Web3Service } from '../web3/web3.service'; import { WebhookDataDto } from './webhook.dto'; import { WebhookEntity } from './webhook.entity'; import { WebhookRepository } from './webhook.repository'; +import Logger from '@human-protocol/logger'; @Injectable() export class WebhookService { - private readonly logger = new Logger(WebhookService.name); + private readonly logger = Logger.child({ + context: WebhookService.name, + }); constructor( @Inject(Web3Service) From e292efa6fbb2eb47bea12c049f232eb4071df822 Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Mon, 23 Jun 2025 16:42:56 +0300 Subject: [PATCH 06/13] Update human-app logger dependency --- .../src/common/config/cache-factory.config.ts | 6 ++++-- .../server/src/common/config/params-decorators.ts | 6 ++++-- .../src/common/filter/global-exceptions.filter.ts | 6 ++++-- .../interceptors/axios-request.interceptor.ts | 8 ++++++-- .../exchange-oracle/exchange-oracle.gateway.ts | 7 +++++-- .../h-captcha-labeling/h-captcha-verify.gateway.ts | 9 +++++++-- packages/apps/human-app/server/src/main.ts | 14 ++++++-------- .../src/modules/cron-job/cron-job.service.ts | 14 +++++++++----- .../src/modules/h-captcha/h-captcha.service.ts | 11 +++++++++-- .../job-assignment/job-assignment.service.ts | 7 +++++-- .../oracle-discovery/oracle-discovery.service.ts | 7 +++++-- 11 files changed, 64 insertions(+), 31 deletions(-) diff --git a/packages/apps/human-app/server/src/common/config/cache-factory.config.ts b/packages/apps/human-app/server/src/common/config/cache-factory.config.ts index 53b06b8793..44a35b0427 100644 --- a/packages/apps/human-app/server/src/common/config/cache-factory.config.ts +++ b/packages/apps/human-app/server/src/common/config/cache-factory.config.ts @@ -1,12 +1,14 @@ -import { Logger } from '@nestjs/common'; import { CacheModuleAsyncOptions } from '@nestjs/cache-manager'; import { ConfigModule } from '@nestjs/config'; import _ from 'lodash'; import { redisStore } from 'cache-manager-redis-yet'; +import Logger from '@human-protocol/logger'; import { EnvironmentConfigService } from './environment-config.service'; -const logger = new Logger('CacheFactoryRedisStore'); +const logger = Logger.child({ + context: 'CacheFactoryRedisStore', +}); const throttledRedisErrorLog = _.throttle((error) => { logger.error('Redis client network error', error); diff --git a/packages/apps/human-app/server/src/common/config/params-decorators.ts b/packages/apps/human-app/server/src/common/config/params-decorators.ts index 52f2e46b90..23f2eb3a5b 100644 --- a/packages/apps/human-app/server/src/common/config/params-decorators.ts +++ b/packages/apps/human-app/server/src/common/config/params-decorators.ts @@ -3,12 +3,14 @@ import { createParamDecorator, ExecutionContext, UnauthorizedException, - Logger, } from '@nestjs/common'; import { jwtDecode } from 'jwt-decode'; import { JwtUserData } from '../utils/jwt-token.model'; +import Logger from '@human-protocol/logger'; -const logger = new Logger('JwtPayloadDecorator'); +const logger = Logger.child({ + context: 'JwtPayloadDecorator', +}); export const Authorization = createParamDecorator( (_data: unknown, ctx: ExecutionContext) => { diff --git a/packages/apps/human-app/server/src/common/filter/global-exceptions.filter.ts b/packages/apps/human-app/server/src/common/filter/global-exceptions.filter.ts index 2993c78a23..7d6b144246 100644 --- a/packages/apps/human-app/server/src/common/filter/global-exceptions.filter.ts +++ b/packages/apps/human-app/server/src/common/filter/global-exceptions.filter.ts @@ -4,12 +4,14 @@ import { ExceptionFilter, HttpException, HttpStatus, - Logger, } from '@nestjs/common'; +import Logger from '@human-protocol/logger'; @Catch() export class GlobalExceptionsFilter implements ExceptionFilter { - private readonly logger = new Logger(GlobalExceptionsFilter.name); + private readonly logger = Logger.child({ + context: GlobalExceptionsFilter.name, + }); catch(exception: any, host: ArgumentsHost) { const ctx = host.switchToHttp(); diff --git a/packages/apps/human-app/server/src/common/interceptors/axios-request.interceptor.ts b/packages/apps/human-app/server/src/common/interceptors/axios-request.interceptor.ts index 058f64f726..bfa27212b4 100644 --- a/packages/apps/human-app/server/src/common/interceptors/axios-request.interceptor.ts +++ b/packages/apps/human-app/server/src/common/interceptors/axios-request.interceptor.ts @@ -1,9 +1,13 @@ import axios from 'axios'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; +import Logger from '@human-protocol/logger'; + // This interceptor injection is guarded via IS_AXIOS_REQUEST_LOGGING_ENABLED environment variable. @Injectable() export class AxiosRequestInterceptor { - private readonly logger = new Logger(AxiosRequestInterceptor.name); + private readonly logger = Logger.child({ + context: AxiosRequestInterceptor.name, + }); constructor() { this.initializeRequestInterceptor(); diff --git a/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts b/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts index df6e6c38db..b83c3c2008 100644 --- a/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/exchange-oracle/exchange-oracle.gateway.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { AxiosRequestConfig } from 'axios'; import { lastValueFrom } from 'rxjs'; import { @@ -38,10 +38,13 @@ import { RegistrationInExchangeOracleCommand, RegistrationInExchangeOracleData, } from '../../modules/user-worker/model/worker-registration.model'; +import Logger from '@human-protocol/logger'; @Injectable() export class ExchangeOracleGateway { - logger = new Logger(ExchangeOracleGateway.name); + logger = Logger.child({ + context: ExchangeOracleGateway.name, + }); constructor( private httpService: HttpService, diff --git a/packages/apps/human-app/server/src/integrations/h-captcha-labeling/h-captcha-verify.gateway.ts b/packages/apps/human-app/server/src/integrations/h-captcha-labeling/h-captcha-verify.gateway.ts index 07c79fbb42..a446b50412 100644 --- a/packages/apps/human-app/server/src/integrations/h-captcha-labeling/h-captcha-verify.gateway.ts +++ b/packages/apps/human-app/server/src/integrations/h-captcha-labeling/h-captcha-verify.gateway.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { GatewayConfig, GatewayEndpointConfig, @@ -19,11 +19,16 @@ import { } from '../../modules/h-captcha/model/verify-token.model'; import { HCaptchaLabelingVerifyEndpoints } from '../../common/enums/reputation-oracle-endpoints'; import { toCleanObjParams } from '../../common/utils/gateway-common.utils'; +import Logger from '@human-protocol/logger'; Injectable(); export class HCaptchaVerifyGateway { + private readonly logger = Logger.child({ + context: HCaptchaVerifyGateway.name, + }); + private readonly gatewayConfig: GatewayConfig; - private readonly logger = new Logger(HCaptchaVerifyGateway.name); + constructor( private httpService: HttpService, gatewayConfigService: GatewayConfigService, diff --git a/packages/apps/human-app/server/src/main.ts b/packages/apps/human-app/server/src/main.ts index 788c74bdbc..e0ad759d0e 100644 --- a/packages/apps/human-app/server/src/main.ts +++ b/packages/apps/human-app/server/src/main.ts @@ -2,19 +2,17 @@ import { NestFactory, Reflector } from '@nestjs/core'; import { AppModule } from './app.module'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { ConfigService } from '@nestjs/config'; -import { - ClassSerializerInterceptor, - Logger, - ValidationPipe, -} from '@nestjs/common'; +import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common'; import { EnvironmentConfigService } from './common/config/environment-config.service'; import { GlobalExceptionsFilter } from './common/filter/global-exceptions.filter'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; +import Logger, { nestLoggerOverride } from '@human-protocol/logger'; async function bootstrap() { - const logger = new Logger(bootstrap.name); - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule, { + logger: nestLoggerOverride, + }); const configService: ConfigService = app.get(ConfigService); const envConfigService = new EnvironmentConfigService(configService); @@ -45,7 +43,7 @@ async function bootstrap() { app.useGlobalPipes(new ValidationPipe({ transform: true })); await app.listen(port, host, async () => { - logger.log(`Human APP server is running on http://${host}:${port}`); + Logger.info(`Human APP server is running on http://${host}:${port}`); }); } bootstrap(); diff --git a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts index 089324b618..9387346c10 100644 --- a/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/human-app/server/src/modules/cron-job/cron-job.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { CronJob } from 'cron'; import { ExchangeOracleGateway } from '../../integrations/exchange-oracle/exchange-oracle.gateway'; import { ReputationOracleGateway } from '../../integrations/reputation-oracle/reputation-oracle.gateway'; @@ -17,6 +17,7 @@ import { } from '../../common/enums/global-common'; import { SchedulerRegistry } from '@nestjs/schedule'; import { JobsDiscoveryService } from '../jobs-discovery/jobs-discovery.service'; +import Logger from '@human-protocol/logger'; function assertJobsDiscoveryResponseItemsFormat( items: JobsDiscoveryResponse['results'], @@ -41,7 +42,10 @@ function assertJobsDiscoveryResponseItemsFormat( @Injectable() export class CronJobService { - private readonly logger = new Logger(CronJobService.name); + private readonly logger = Logger.child({ + context: CronJobService.name, + }); + constructor( private readonly reputationOracleGateway: ReputationOracleGateway, private readonly exchangeOracleGateway: ExchangeOracleGateway, @@ -65,7 +69,7 @@ export class CronJobService { } async updateJobsListCron() { - this.logger.log('CRON START'); + this.logger.info('CRON START'); const oracles = await this.oracleDiscoveryService.discoverOracles(); @@ -80,7 +84,7 @@ export class CronJobService { for (const oracle of oracles) { if (oracle.executionsToSkip > 0) { - this.logger.log( + this.logger.info( `Skipping execution for oracle: ${oracle.address}. Remaining skips: ${oracle.executionsToSkip}`, ); @@ -100,7 +104,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('CRON END'); + this.logger.info('CRON END'); } async updateJobsListCache(oracle: DiscoveredOracle, token: string) { diff --git a/packages/apps/human-app/server/src/modules/h-captcha/h-captcha.service.ts b/packages/apps/human-app/server/src/modules/h-captcha/h-captcha.service.ts index 3b957239b2..bea9e57bc2 100644 --- a/packages/apps/human-app/server/src/modules/h-captcha/h-captcha.service.ts +++ b/packages/apps/human-app/server/src/modules/h-captcha/h-captcha.service.ts @@ -1,4 +1,4 @@ -import { HttpException, Inject, Injectable, Logger } from '@nestjs/common'; +import { HttpException, Inject, Injectable } from '@nestjs/common'; import { VerifyTokenCommand, VerifyTokenApiResponse, @@ -20,10 +20,14 @@ import { HCaptchaStatisticsGateway } from '../../integrations/h-captcha-labeling import { ReputationOracleGateway } from '../../integrations/reputation-oracle/reputation-oracle.gateway'; import { HCaptchaVerifyGateway } from '../../integrations/h-captcha-labeling/h-captcha-verify.gateway'; import { DAILY_HMT_SPENT_CACHE_KEY } from '../../common/constants/cache'; +import Logger from '@human-protocol/logger'; @Injectable() export class HCaptchaService { - private readonly logger = new Logger(HCaptchaService.name); + private readonly logger = Logger.child({ + context: HCaptchaService.name, + }); + constructor( private configService: EnvironmentConfigService, private hCaptchaLabelingGateway: HCaptchaStatisticsGateway, @@ -43,6 +47,7 @@ export class HCaptchaService { this.logger.error(errorMessage); throw new HttpException(errorMessage, 400); } + private createHCaptchaVerificationErrorMessage( response: VerifyTokenApiResponse | undefined, ): string { @@ -59,6 +64,7 @@ export class HCaptchaService { } return message; } + async enableLabeling( command: EnableLabelingCommand, ): Promise { @@ -97,6 +103,7 @@ export class HCaptchaService { ); return stats; } + private checkIfHcaptchaSitekeyPresent(siteKey: string) { if (!siteKey) { throw new HttpException('Labeling is not enabled for this account', 400); diff --git a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts index 7dd491cb9e..f8daa8bc60 100644 --- a/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts +++ b/packages/apps/human-app/server/src/modules/job-assignment/job-assignment.service.ts @@ -1,5 +1,5 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { ethers } from 'ethers'; import { Cache } from 'cache-manager'; import { decode } from 'jsonwebtoken'; @@ -21,10 +21,13 @@ import { paginateAndSortResults, } from '../../common/utils/pagination.utils'; import { JOB_ASSIGNMENT_CACHE_KEY } from '../../common/constants/cache'; +import Logger from '@human-protocol/logger'; @Injectable() export class JobAssignmentService { - logger = new Logger(JobAssignmentService.name); + logger = Logger.child({ + context: JobAssignmentService.name, + }); constructor( private readonly configService: EnvironmentConfigService, diff --git a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts index 3508b1ceea..084b99be52 100644 --- a/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts +++ b/packages/apps/human-app/server/src/modules/oracle-discovery/oracle-discovery.service.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; import { ChainId, IOperator, OperatorUtils, Role } from '@human-protocol/sdk'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { @@ -9,10 +9,13 @@ import { } from './model/oracle-discovery.model'; import { EnvironmentConfigService } from '../../common/config/environment-config.service'; import { KvStoreGateway } from '../../integrations/kv-store/kv-store.gateway'; +import Logger from '@human-protocol/logger'; @Injectable() export class OracleDiscoveryService { - logger = new Logger(OracleDiscoveryService.name); + logger = Logger.child({ + context: OracleDiscoveryService.name, + }); constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache, From 9f427a85da5b0d66c8789a58cf4e7d01a0310bcd Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Mon, 23 Jun 2025 17:27:28 +0300 Subject: [PATCH 07/13] Update exchange-oracle logger dependency --- .../src/common/exceptions/exception.filter.ts | 6 +++-- .../src/common/guards/signature.auth.ts | 13 +++++------ .../exchange-oracle/server/src/main.ts | 4 +++- .../modules/assignment/assignment.service.ts | 22 +++++++++---------- .../src/modules/cron-job/cron-job.service.ts | 13 ++++++----- .../server/src/modules/job/job.service.ts | 9 +++++--- .../server/src/modules/stats/stats.service.ts | 9 ++++++-- .../src/modules/storage/storage.service.ts | 14 +++++++++--- .../server/src/modules/web3/web3.service.ts | 11 +++++++--- .../src/modules/webhook/webhook.module.ts | 4 ++-- 10 files changed, 66 insertions(+), 39 deletions(-) diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/exceptions/exception.filter.ts b/packages/apps/fortune/exchange-oracle/server/src/common/exceptions/exception.filter.ts index 875fbb43f7..9d0be0fed1 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/common/exceptions/exception.filter.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/common/exceptions/exception.filter.ts @@ -3,7 +3,6 @@ import { Catch, ExceptionFilter as IExceptionFilter, HttpStatus, - Logger, } from '@nestjs/common'; import { Request, Response } from 'express'; import { @@ -15,10 +14,13 @@ import { ServerError, DatabaseError, } from '../errors'; +import Logger from '@human-protocol/logger'; @Catch() export class ExceptionFilter implements IExceptionFilter { - private logger = new Logger(ExceptionFilter.name); + private logger = Logger.child({ + context: ExceptionFilter.name, + }); private getStatus(exception: any): number { if (exception instanceof ValidationError) { diff --git a/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts b/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts index 97782a8d59..92dba3e70f 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/common/guards/signature.auth.ts @@ -1,10 +1,5 @@ import { EscrowUtils } from '@human-protocol/sdk'; -import { - CanActivate, - ExecutionContext, - Injectable, - Logger, -} from '@nestjs/common'; +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { AssignmentRepository } from '../../modules/assignment/assignment.repository'; import { HEADER_SIGNATURE_KEY } from '../constant'; @@ -12,10 +7,14 @@ import { ErrorAssignment, ErrorSignature } from '../constant/errors'; import { AuthSignatureRole } from '../enums/role'; import { AuthError, NotFoundError } from '../errors'; import { verifySignature } from '../utils/signature'; +import Logger from '@human-protocol/logger'; @Injectable() export class SignatureAuthGuard implements CanActivate { - private readonly logger = new Logger(SignatureAuthGuard.name); + private readonly logger = Logger.child({ + context: SignatureAuthGuard.name, + }); + constructor( private reflector: Reflector, private readonly assignmentRepository: AssignmentRepository, diff --git a/packages/apps/fortune/exchange-oracle/server/src/main.ts b/packages/apps/fortune/exchange-oracle/server/src/main.ts index 2683f7c886..7ec09c2e8b 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/main.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/main.ts @@ -7,10 +7,12 @@ import { useContainer } from 'class-validator'; import { AppModule } from './app.module'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { ServerConfigService } from './common/config/server-config.service'; +import logger, { nestLoggerOverride } from '@human-protocol/logger'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: true, + logger: nestLoggerOverride, }); const configService: ConfigService = app.get(ConfigService); @@ -51,7 +53,7 @@ async function bootstrap() { app.useGlobalPipes(new ValidationPipe({ transform: true })); await app.listen(port, host, async () => { - console.info(`API server is running on http://${host}:${port}`); + logger.info(`API server is running on http://${host}:${port}`); }); } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts index 55cffad2b7..ffea173be8 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/assignment/assignment.service.ts @@ -1,5 +1,5 @@ import { Escrow__factory } from '@human-protocol/core/typechain-types'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ServerConfigService } from '../../common/config/server-config.service'; import { ErrorAssignment, ErrorJob } from '../../common/constant/errors'; import { AssignmentStatus, JobStatus, JobType } from '../../common/enums/job'; @@ -20,10 +20,13 @@ import { } from './assignment.dto'; import { AssignmentEntity } from './assignment.entity'; import { AssignmentRepository } from './assignment.repository'; +import Logger from '@human-protocol/logger'; @Injectable() export class AssignmentService { - private readonly logger = new Logger(AssignmentService.name); + private readonly logger = Logger.child({ + context: AssignmentService.name, + }); constructor( private readonly assignmentRepository: AssignmentRepository, @@ -43,16 +46,13 @@ export class AssignmentService { ); if (!jobEntity) { - this.logger.log(ErrorAssignment.JobNotFound, AssignmentService.name); + this.logger.info(ErrorAssignment.JobNotFound); throw new ServerError(ErrorAssignment.JobNotFound); } else if (jobEntity.status !== JobStatus.ACTIVE) { - this.logger.log(ErrorJob.InvalidStatus, AssignmentService.name); + this.logger.info(ErrorJob.InvalidStatus); throw new ConflictError(ErrorJob.InvalidStatus); } else if (jobEntity.reputationNetwork !== jwtUser.reputationNetwork) { - this.logger.log( - ErrorAssignment.ReputationNetworkMismatch, - AssignmentService.name, - ); + this.logger.info(ErrorAssignment.ReputationNetworkMismatch); throw new ValidationError(ErrorAssignment.ReputationNetworkMismatch); } @@ -66,7 +66,7 @@ export class AssignmentService { assignmentEntity && assignmentEntity.status !== AssignmentStatus.CANCELED ) { - this.logger.log(ErrorAssignment.AlreadyExists, AssignmentService.name); + this.logger.info(ErrorAssignment.AlreadyExists); throw new ConflictError(ErrorAssignment.AlreadyExists); } @@ -90,7 +90,7 @@ export class AssignmentService { } if (currentAssignments >= manifest.submissionsRequired) { - this.logger.log(ErrorAssignment.FullyAssigned, AssignmentService.name); + this.logger.info(ErrorAssignment.FullyAssigned); throw new ValidationError(ErrorAssignment.FullyAssigned); } @@ -98,7 +98,7 @@ export class AssignmentService { const escrow = Escrow__factory.connect(data.escrowAddress, signer); const expirationDate = new Date(Number(await escrow.duration()) * 1000); if (expirationDate < new Date()) { - this.logger.log(ErrorAssignment.ExpiredEscrow, AssignmentService.name); + this.logger.info(ErrorAssignment.ExpiredEscrow); throw new ValidationError(ErrorAssignment.ExpiredEscrow); } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/cron-job/cron-job.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/cron-job/cron-job.service.ts index 9b1d31631b..ed508b1b69 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/cron-job/cron-job.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/cron-job/cron-job.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { Cron } from '@nestjs/schedule'; import { ErrorCronJob } from '../../common/constant/errors'; @@ -8,10 +8,13 @@ import { WebhookRepository } from '../webhook/webhook.repository'; import { WebhookService } from '../webhook/webhook.service'; import { CronJobEntity } from './cron-job.entity'; import { CronJobRepository } from './cron-job.repository'; +import Logger from '@human-protocol/logger'; @Injectable() export class CronJobService { - private readonly logger = new Logger(CronJobService.name); + private readonly logger = Logger.child({ + context: CronJobService.name, + }); constructor( private readonly cronJobRepository: CronJobRepository, @@ -39,7 +42,7 @@ export class CronJobService { return false; } - this.logger.log('Previous cron job is not completed yet'); + this.logger.info('Previous cron job is not completed yet'); return true; } @@ -69,7 +72,7 @@ export class CronJobService { return; } - this.logger.log('Pending webhooks START'); + this.logger.info('Pending webhooks START'); const cronJob = await this.startCronJob(CronJobType.ProcessPendingWebhook); try { @@ -92,7 +95,7 @@ export class CronJobService { this.logger.error(e); } - this.logger.log('Pending webhooks STOP'); + this.logger.info('Pending webhooks STOP'); await this.completeCronJob(cronJob); } } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts index ff17236276..b7f543b212 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/job/job.service.ts @@ -9,7 +9,7 @@ import { EscrowClient, StorageClient, } from '@human-protocol/sdk'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import { PGPConfigService } from '../../common/config/pgp-config.service'; import { ErrorAssignment, ErrorJob } from '../../common/constant/errors'; import { SortDirection } from '../../common/enums/collection'; @@ -39,10 +39,13 @@ import { WebhookRepository } from '../webhook/webhook.repository'; import { GetJobsDto, JobDto, ManifestDto } from './job.dto'; import { JobEntity } from './job.entity'; import { JobRepository } from './job.repository'; +import Logger from '@human-protocol/logger'; @Injectable() export class JobService { - public readonly logger = new Logger(JobService.name); + public readonly logger = Logger.child({ + context: JobService.name, + }); constructor( private readonly pgpConfigService: PGPConfigService, @@ -63,7 +66,7 @@ export class JobService { ); if (jobEntity) { - this.logger.log(ErrorJob.AlreadyExists, JobService.name); + this.logger.info(ErrorJob.AlreadyExists); throw new ConflictError(ErrorJob.AlreadyExists); } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/stats/stats.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/stats/stats.service.ts index 1ca6ee1d3c..6df68c3c19 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/stats/stats.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/stats/stats.service.ts @@ -1,12 +1,16 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { JobRepository } from '../job/job.repository'; import { AssignmentRepository } from '../assignment/assignment.repository'; import { AssignmentStatsDto, OracleStatsDto } from './stats.dto'; import { JobStatus } from '../../common/enums/job'; +import Logger from '@human-protocol/logger'; @Injectable() export class StatsService { - public readonly logger = new Logger(StatsService.name); + public readonly logger = Logger.child({ + context: StatsService.name, + }); + constructor( private jobRepository: JobRepository, private assignmentRepository: AssignmentRepository, @@ -32,6 +36,7 @@ export class StatsService { ), }); } + async getAssignmentStats(workerAddress: string): Promise { return new AssignmentStatsDto({ assignmentsTotal: diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts index b18126bdf9..34267e9010 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/storage/storage.service.ts @@ -6,16 +6,21 @@ import { KVStoreUtils, StorageClient, } from '@human-protocol/sdk'; -import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; import * as Minio from 'minio'; import { PGPConfigService } from '../../common/config/pgp-config.service'; import { S3ConfigService } from '../../common/config/s3-config.service'; import { NotFoundError, ServerError } from '../../common/errors'; import { ISolution } from '../../common/interfaces/job'; import { Web3Service } from '../web3/web3.service'; +import Logger from '@human-protocol/logger'; @Injectable() export class StorageService { + private readonly logger = Logger.child({ + context: StorageService.name, + }); + public readonly minioClient: Minio.Client; constructor( @@ -32,6 +37,7 @@ export class StorageService { useSSL: this.s3ConfigService.useSSL, }); } + public getJobUrl(escrowAddress: string, chainId: ChainId): string { return `${this.s3ConfigService.useSSL ? 'https' : 'http'}://${ this.s3ConfigService.endpoint @@ -102,7 +108,8 @@ export class StorageService { recordingOraclePublicKey, ]); } catch (e) { - Logger.error(e); + this.logger.error('Encryption error', e); + throw new ServerError('Encryption error'); } } @@ -120,7 +127,8 @@ export class StorageService { return this.getJobUrl(escrowAddress, chainId); } catch (e) { - Logger.error(e); + this.logger.error('File not uploaded', e); + throw new ServerError('File not uploaded'); } } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/web3/web3.service.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/web3/web3.service.ts index 855d1627f0..bb22d57c55 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/web3/web3.service.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/web3/web3.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Injectable, Logger } from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { Wallet, ethers } from 'ethers'; import { Web3Env } from '../../common/enums/web3'; import { @@ -10,11 +10,16 @@ import { ErrorWeb3 } from '../../common/constant/errors'; import { ChainId } from '@human-protocol/sdk'; import { Web3ConfigService } from '../../common/config/web3-config.service'; import { NetworkConfigService } from '../../common/config/network-config.service'; +import Logger from '@human-protocol/logger'; @Injectable() export class Web3Service { + public readonly logger = Logger.child({ + context: Web3Service.name, + }); + private signers: { [key: number]: Wallet } = {}; - public readonly logger = new Logger(Web3Service.name); + public readonly signerAddress: string; public readonly currentWeb3Env: string; @@ -43,7 +48,7 @@ export class Web3Service { public validateChainId(chainId: number): void { const validChainIds = this.getValidChains(); if (!validChainIds.includes(chainId)) { - this.logger.log(ErrorWeb3.InvalidChainId, Web3Service.name); + this.logger.info(ErrorWeb3.InvalidChainId); throw new BadRequestException(ErrorWeb3.InvalidChainId); } } diff --git a/packages/apps/fortune/exchange-oracle/server/src/modules/webhook/webhook.module.ts b/packages/apps/fortune/exchange-oracle/server/src/modules/webhook/webhook.module.ts index 25c1720873..334112a6fa 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/modules/webhook/webhook.module.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/modules/webhook/webhook.module.ts @@ -1,4 +1,4 @@ -import { Logger, Module } from '@nestjs/common'; +import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; @@ -25,7 +25,7 @@ import { AssignmentEntity } from '../assignment/assignment.entity'; AssignmentModule, ], controllers: [WebhookController], - providers: [Logger, WebhookService, WebhookRepository, AssignmentRepository], + providers: [WebhookService, WebhookRepository, AssignmentRepository], exports: [WebhookService], }) export class WebhookModule {} From ff7f03da4ecaba060ca86a79f74466eca1c1988e Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Mon, 23 Jun 2025 17:29:00 +0300 Subject: [PATCH 08/13] Update recording-oracle logger dependency --- packages/apps/fortune/recording-oracle/src/main.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/apps/fortune/recording-oracle/src/main.ts b/packages/apps/fortune/recording-oracle/src/main.ts index 991069853a..2b02b091f4 100644 --- a/packages/apps/fortune/recording-oracle/src/main.ts +++ b/packages/apps/fortune/recording-oracle/src/main.ts @@ -8,10 +8,12 @@ import { INestApplication } from '@nestjs/common'; import { AppModule } from './app.module'; import { ServerConfigService } from './common/config/server-config.service'; import { ConfigService } from '@nestjs/config'; +import logger, { nestLoggerOverride } from '@human-protocol/logger'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: true, + logger: nestLoggerOverride, }); const configService: ConfigService = app.get(ConfigService); @@ -44,7 +46,7 @@ async function bootstrap() { await app.listen(port, host, async () => { // eslint-disable-next-line no-console - console.info(`API server is running on http://${host}:${port}`); + logger.info(`API server is running on http://${host}:${port}`); }); } From c5287ee97e34688431f48b23cce787aa8f897284 Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Mon, 23 Jun 2025 20:29:50 +0300 Subject: [PATCH 09/13] Fix eslint dependencies --- .../src/modules/storage/storage.service.ts | 2 +- packages/libs/logger/package.json | 7 ++++ packages/libs/logger/src/index.ts | 4 +-- packages/libs/logger/src/pino-logger.ts | 4 +-- packages/libs/logger/src/types.ts | 2 +- yarn.lock | 35 ++++++++++++++++--- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/packages/apps/dashboard/server/src/modules/storage/storage.service.ts b/packages/apps/dashboard/server/src/modules/storage/storage.service.ts index 6de6af4b86..65e8e5e93b 100644 --- a/packages/apps/dashboard/server/src/modules/storage/storage.service.ts +++ b/packages/apps/dashboard/server/src/modules/storage/storage.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { Injectable, NotFoundException } from '@nestjs/common'; import * as Minio from 'minio'; import { S3ConfigService } from '../../common/config/s3-config.service'; import { Readable } from 'stream'; diff --git a/packages/libs/logger/package.json b/packages/libs/logger/package.json index 3574766e01..fd681e933d 100644 --- a/packages/libs/logger/package.json +++ b/packages/libs/logger/package.json @@ -21,8 +21,15 @@ "devDependencies": { "@types/jest": "^29.5.12", "@types/node": "^22.10.5", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.55.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^27.0.0", + "eslint-plugin-prettier": "^5.0.0", "jest": "^29.7.0", "pino-pretty": "^13.0.0", + "prettier": "^3.4.2", "ts-jest": "^29.2.5", "typescript": "^5.6.3" }, diff --git a/packages/libs/logger/src/index.ts b/packages/libs/logger/src/index.ts index aea6ffb222..5f4a77a5e0 100644 --- a/packages/libs/logger/src/index.ts +++ b/packages/libs/logger/src/index.ts @@ -41,12 +41,12 @@ const defaultLogger = createLogger( { environment: Environment.envName, service: 'human-protocol', - }, + } ); // Create NestJS logger override export const nestLoggerOverride = new NestLogger( - defaultLogger.child({ name: 'NestLogger' }), + defaultLogger.child({ name: 'NestLogger' }) ); // Export the default logger as the main export diff --git a/packages/libs/logger/src/pino-logger.ts b/packages/libs/logger/src/pino-logger.ts index 09d0a055df..703805ed24 100644 --- a/packages/libs/logger/src/pino-logger.ts +++ b/packages/libs/logger/src/pino-logger.ts @@ -12,7 +12,7 @@ import { export class WrappedPino extends LoggerWrapper { constructor( private readonly pinoLogger: pino.Logger, - bindings?: LogMeta, + bindings?: LogMeta ) { super(bindings); } @@ -37,7 +37,7 @@ const pinoLogLevelFormatter = (label: string) => ({ level: label }); export function createLogger( { name, level, pretty, disabled }: LoggerOptions, - bindings: LogMeta = {}, + bindings: LogMeta = {} ): WrappedPino { const pinoLogger = pino({ base: null, diff --git a/packages/libs/logger/src/types.ts b/packages/libs/logger/src/types.ts index ae14a97b0d..e3f1e8a3ff 100644 --- a/packages/libs/logger/src/types.ts +++ b/packages/libs/logger/src/types.ts @@ -37,4 +37,4 @@ export type LoggerOptions = { disabled?: boolean; service?: string; environment?: string; -}; \ No newline at end of file +}; diff --git a/yarn.lock b/yarn.lock index 92c6a993b1..4cec54ce41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4438,9 +4438,16 @@ __metadata: dependencies: "@types/jest": "npm:^29.5.12" "@types/node": "npm:^22.10.5" + "@typescript-eslint/eslint-plugin": "npm:^7.0.0" + "@typescript-eslint/parser": "npm:^7.0.0" + eslint: "npm:^8.55.0" + eslint-config-prettier: "npm:^9.0.0" + eslint-plugin-jest: "npm:^27.0.0" + eslint-plugin-prettier: "npm:^5.0.0" jest: "npm:^29.7.0" pino: "npm:^9.6.0" pino-pretty: "npm:^13.0.0" + prettier: "npm:^3.4.2" ts-jest: "npm:^29.2.5" typescript: "npm:^5.6.3" peerDependencies: @@ -10446,7 +10453,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^7.1.1, @typescript-eslint/eslint-plugin@npm:^7.13.1, @typescript-eslint/eslint-plugin@npm:^7.2.0": +"@typescript-eslint/eslint-plugin@npm:^7.0.0, @typescript-eslint/eslint-plugin@npm:^7.1.1, @typescript-eslint/eslint-plugin@npm:^7.13.1, @typescript-eslint/eslint-plugin@npm:^7.2.0": version: 7.18.0 resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0" dependencies: @@ -10531,7 +10538,7 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:^7.1.1, @typescript-eslint/parser@npm:^7.13.1, @typescript-eslint/parser@npm:^7.2.0": +"@typescript-eslint/parser@npm:^7.0.0, @typescript-eslint/parser@npm:^7.1.1, @typescript-eslint/parser@npm:^7.13.1, @typescript-eslint/parser@npm:^7.2.0": version: 7.18.0 resolution: "@typescript-eslint/parser@npm:7.18.0" dependencies: @@ -16130,7 +16137,7 @@ __metadata: languageName: node linkType: hard -"eslint-config-prettier@npm:^9.1.0": +"eslint-config-prettier@npm:^9.0.0, eslint-config-prettier@npm:^9.1.0": version: 9.1.0 resolution: "eslint-config-prettier@npm:9.1.0" peerDependencies: @@ -16293,7 +16300,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jest@npm:^27.9.0": +"eslint-plugin-jest@npm:^27.0.0, eslint-plugin-jest@npm:^27.9.0": version: 27.9.0 resolution: "eslint-plugin-jest@npm:27.9.0" dependencies: @@ -16351,6 +16358,26 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-prettier@npm:^5.0.0": + version: 5.5.0 + resolution: "eslint-plugin-prettier@npm:5.5.0" + dependencies: + prettier-linter-helpers: "npm:^1.0.0" + synckit: "npm:^0.11.7" + peerDependencies: + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" + prettier: ">=3.0.0" + peerDependenciesMeta: + "@types/eslint": + optional: true + eslint-config-prettier: + optional: true + checksum: 10c0/d739940d5f5ea9b4c3a52836b24907b273a46909cdd1def5526f8934e54082fe5aac13512eb2c27d538ca79e16916ca54c651e3372aa53b7d4297afb4c156d47 + languageName: node + linkType: hard + "eslint-plugin-prettier@npm:^5.2.1": version: 5.4.0 resolution: "eslint-plugin-prettier@npm:5.4.0" From 5a3d17e97d37a923dfac9d93e4b7f26a629f8126 Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Wed, 25 Jun 2025 18:22:48 +0300 Subject: [PATCH 10/13] Provide custom logger factory method --- packages/apps/dashboard/server/src/main.ts | 5 +++- .../exchange-oracle/server/src/main.ts | 5 +++- .../apps/fortune/recording-oracle/src/main.ts | 5 +++- packages/apps/human-app/server/src/main.ts | 5 +++- packages/apps/job-launcher/server/src/main.ts | 5 +++- .../apps/reputation-oracle/server/src/main.ts | 5 +++- packages/libs/logger/src/index.ts | 29 ++++++++++++++++++- 7 files changed, 52 insertions(+), 7 deletions(-) diff --git a/packages/apps/dashboard/server/src/main.ts b/packages/apps/dashboard/server/src/main.ts index a23dece527..3f1e4f382f 100644 --- a/packages/apps/dashboard/server/src/main.ts +++ b/packages/apps/dashboard/server/src/main.ts @@ -4,7 +4,10 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; import { EnvironmentConfigService } from './common/config/env-config.service'; -import logger, { nestLoggerOverride } from '@human-protocol/logger'; +import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; + +// Create service-specific logger +const logger = createServiceLogger('dashboard'); async function bootstrap() { const app = await NestFactory.create(AppModule, { diff --git a/packages/apps/fortune/exchange-oracle/server/src/main.ts b/packages/apps/fortune/exchange-oracle/server/src/main.ts index 7ec09c2e8b..17af37d696 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/main.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/main.ts @@ -7,7 +7,10 @@ import { useContainer } from 'class-validator'; import { AppModule } from './app.module'; import { INestApplication, ValidationPipe } from '@nestjs/common'; import { ServerConfigService } from './common/config/server-config.service'; -import logger, { nestLoggerOverride } from '@human-protocol/logger'; +import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; + +// Create service-specific logger +const logger = createServiceLogger('fortune-exchange-oracle'); async function bootstrap() { const app = await NestFactory.create(AppModule, { diff --git a/packages/apps/fortune/recording-oracle/src/main.ts b/packages/apps/fortune/recording-oracle/src/main.ts index 2b02b091f4..587b78bc4f 100644 --- a/packages/apps/fortune/recording-oracle/src/main.ts +++ b/packages/apps/fortune/recording-oracle/src/main.ts @@ -8,7 +8,10 @@ import { INestApplication } from '@nestjs/common'; import { AppModule } from './app.module'; import { ServerConfigService } from './common/config/server-config.service'; import { ConfigService } from '@nestjs/config'; -import logger, { nestLoggerOverride } from '@human-protocol/logger'; +import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; + +// Create service-specific logger +const logger = createServiceLogger('fortune-recording-oracle'); async function bootstrap() { const app = await NestFactory.create(AppModule, { diff --git a/packages/apps/human-app/server/src/main.ts b/packages/apps/human-app/server/src/main.ts index e0ad759d0e..834ef13703 100644 --- a/packages/apps/human-app/server/src/main.ts +++ b/packages/apps/human-app/server/src/main.ts @@ -7,7 +7,10 @@ import { EnvironmentConfigService } from './common/config/environment-config.ser import { GlobalExceptionsFilter } from './common/filter/global-exceptions.filter'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; -import Logger, { nestLoggerOverride } from '@human-protocol/logger'; +import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; + +// Create service-specific logger +const Logger = createServiceLogger('human-app'); async function bootstrap() { const app = await NestFactory.create(AppModule, { diff --git a/packages/apps/job-launcher/server/src/main.ts b/packages/apps/job-launcher/server/src/main.ts index 093250b6ec..2ac695e13d 100644 --- a/packages/apps/job-launcher/server/src/main.ts +++ b/packages/apps/job-launcher/server/src/main.ts @@ -8,7 +8,10 @@ import { useContainer } from 'class-validator'; import helmet from 'helmet'; import { AppModule } from './app.module'; import { ServerConfigService } from './common/config/server-config.service'; -import logger, { nestLoggerOverride } from '@human-protocol/logger'; +import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; + +// Create service-specific logger +const logger = createServiceLogger('job-launcher'); async function bootstrap() { const app = await NestFactory.create(AppModule, { diff --git a/packages/apps/reputation-oracle/server/src/main.ts b/packages/apps/reputation-oracle/server/src/main.ts index ad9e768fe3..da63a8bd8a 100644 --- a/packages/apps/reputation-oracle/server/src/main.ts +++ b/packages/apps/reputation-oracle/server/src/main.ts @@ -9,7 +9,10 @@ import { IncomingMessage, ServerResponse } from 'http'; import { AppModule } from './app.module'; import { ServerConfigService } from './config'; -import logger, { nestLoggerOverride } from '@human-protocol/logger'; +import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; + +// Create service-specific logger +const logger = createServiceLogger('reputation-oracle'); function rawBodyMiddleware( req: any, diff --git a/packages/libs/logger/src/index.ts b/packages/libs/logger/src/index.ts index 5f4a77a5e0..748b660a10 100644 --- a/packages/libs/logger/src/index.ts +++ b/packages/libs/logger/src/index.ts @@ -1,6 +1,6 @@ import { createLogger } from './pino-logger'; import NestLogger from './nest-logger'; -import { LogLevel } from './types'; +import { LogLevel, LoggerOptions } from './types'; // Environment detection similar to reputation oracle enum EnvironmentName { @@ -49,5 +49,32 @@ export const nestLoggerOverride = new NestLogger( defaultLogger.child({ name: 'NestLogger' }) ); +/** + * Creates a logger instance for a specific service + * @param serviceName - The name of the service (e.g., 'job-launcher', 'reputation-oracle') + * @param options - Optional logger configuration + * @returns A logger instance configured for the specified service + */ +export function createServiceLogger( + serviceName: string, + options: Partial = {} +): typeof defaultLogger { + const isDevelopment = Environment.isDevelopment(); + + return createLogger( + { + name: `${serviceName}Logger`, + level: isDevelopment ? LogLevel.DEBUG : LogLevel.INFO, + pretty: isDevelopment, + disabled: Environment.isTest(), + ...options, + }, + { + environment: Environment.envName, + service: serviceName, + } + ); +} + // Export the default logger as the main export export default defaultLogger; From e26bdda025d13c4e61b590dd10304473c14583ea Mon Sep 17 00:00:00 2001 From: Nikolai Muhhin Date: Wed, 25 Jun 2025 18:50:52 +0300 Subject: [PATCH 11/13] Code cleanup --- packages/apps/fortune/recording-oracle/src/main.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/apps/fortune/recording-oracle/src/main.ts b/packages/apps/fortune/recording-oracle/src/main.ts index 587b78bc4f..c800175a5d 100644 --- a/packages/apps/fortune/recording-oracle/src/main.ts +++ b/packages/apps/fortune/recording-oracle/src/main.ts @@ -8,7 +8,10 @@ import { INestApplication } from '@nestjs/common'; import { AppModule } from './app.module'; import { ServerConfigService } from './common/config/server-config.service'; import { ConfigService } from '@nestjs/config'; -import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; +import { + createServiceLogger, + nestLoggerOverride, +} from '@human-protocol/logger'; // Create service-specific logger const logger = createServiceLogger('fortune-recording-oracle'); From a609a07407242d234852a08f02a879d2f87525b6 Mon Sep 17 00:00:00 2001 From: portuu3 Date: Thu, 3 Jul 2025 18:18:41 +0200 Subject: [PATCH 12/13] delete unuseful comments and lint --- packages/apps/dashboard/server/src/main.ts | 6 ++++-- packages/apps/fortune/exchange-oracle/server/src/main.ts | 1 - packages/apps/fortune/recording-oracle/src/main.ts | 1 - packages/apps/human-app/server/src/main.ts | 1 - packages/apps/job-launcher/server/src/main.ts | 6 ++++-- packages/apps/reputation-oracle/server/src/main.ts | 6 ++++-- packages/libs/logger/src/index.ts | 2 +- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/apps/dashboard/server/src/main.ts b/packages/apps/dashboard/server/src/main.ts index 3f1e4f382f..6d2f8c5465 100644 --- a/packages/apps/dashboard/server/src/main.ts +++ b/packages/apps/dashboard/server/src/main.ts @@ -4,9 +4,11 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; import { EnvironmentConfigService } from './common/config/env-config.service'; -import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; +import { + createServiceLogger, + nestLoggerOverride, +} from '@human-protocol/logger'; -// Create service-specific logger const logger = createServiceLogger('dashboard'); async function bootstrap() { diff --git a/packages/apps/fortune/exchange-oracle/server/src/main.ts b/packages/apps/fortune/exchange-oracle/server/src/main.ts index 17af37d696..38fdf31d04 100644 --- a/packages/apps/fortune/exchange-oracle/server/src/main.ts +++ b/packages/apps/fortune/exchange-oracle/server/src/main.ts @@ -9,7 +9,6 @@ import { INestApplication, ValidationPipe } from '@nestjs/common'; import { ServerConfigService } from './common/config/server-config.service'; import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; -// Create service-specific logger const logger = createServiceLogger('fortune-exchange-oracle'); async function bootstrap() { diff --git a/packages/apps/fortune/recording-oracle/src/main.ts b/packages/apps/fortune/recording-oracle/src/main.ts index c800175a5d..e0f8eff5a5 100644 --- a/packages/apps/fortune/recording-oracle/src/main.ts +++ b/packages/apps/fortune/recording-oracle/src/main.ts @@ -13,7 +13,6 @@ import { nestLoggerOverride, } from '@human-protocol/logger'; -// Create service-specific logger const logger = createServiceLogger('fortune-recording-oracle'); async function bootstrap() { diff --git a/packages/apps/human-app/server/src/main.ts b/packages/apps/human-app/server/src/main.ts index 834ef13703..6226d5c0ac 100644 --- a/packages/apps/human-app/server/src/main.ts +++ b/packages/apps/human-app/server/src/main.ts @@ -9,7 +9,6 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; -// Create service-specific logger const Logger = createServiceLogger('human-app'); async function bootstrap() { diff --git a/packages/apps/job-launcher/server/src/main.ts b/packages/apps/job-launcher/server/src/main.ts index 2ac695e13d..b59d7d938a 100644 --- a/packages/apps/job-launcher/server/src/main.ts +++ b/packages/apps/job-launcher/server/src/main.ts @@ -8,9 +8,11 @@ import { useContainer } from 'class-validator'; import helmet from 'helmet'; import { AppModule } from './app.module'; import { ServerConfigService } from './common/config/server-config.service'; -import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; +import { + createServiceLogger, + nestLoggerOverride, +} from '@human-protocol/logger'; -// Create service-specific logger const logger = createServiceLogger('job-launcher'); async function bootstrap() { diff --git a/packages/apps/reputation-oracle/server/src/main.ts b/packages/apps/reputation-oracle/server/src/main.ts index da63a8bd8a..f444ed3192 100644 --- a/packages/apps/reputation-oracle/server/src/main.ts +++ b/packages/apps/reputation-oracle/server/src/main.ts @@ -9,9 +9,11 @@ import { IncomingMessage, ServerResponse } from 'http'; import { AppModule } from './app.module'; import { ServerConfigService } from './config'; -import { createServiceLogger, nestLoggerOverride } from '@human-protocol/logger'; +import { + createServiceLogger, + nestLoggerOverride, +} from '@human-protocol/logger'; -// Create service-specific logger const logger = createServiceLogger('reputation-oracle'); function rawBodyMiddleware( diff --git a/packages/libs/logger/src/index.ts b/packages/libs/logger/src/index.ts index 748b660a10..19c8c2fd70 100644 --- a/packages/libs/logger/src/index.ts +++ b/packages/libs/logger/src/index.ts @@ -60,7 +60,7 @@ export function createServiceLogger( options: Partial = {} ): typeof defaultLogger { const isDevelopment = Environment.isDevelopment(); - + return createLogger( { name: `${serviceName}Logger`, From 01906276b9ab569e37cd7deb60e7e29d942381c9 Mon Sep 17 00:00:00 2001 From: portuu3 Date: Thu, 3 Jul 2025 18:30:50 +0200 Subject: [PATCH 13/13] fix stripe service --- .../payment/providers/payment-provider.abstract.ts | 7 +++++-- .../payment/providers/stripe/stripe.service.ts | 6 +++--- yarn.lock | 11 +---------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/packages/apps/job-launcher/server/src/modules/payment/providers/payment-provider.abstract.ts b/packages/apps/job-launcher/server/src/modules/payment/providers/payment-provider.abstract.ts index 6adca84442..72c71994ac 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/providers/payment-provider.abstract.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/providers/payment-provider.abstract.ts @@ -6,11 +6,14 @@ import { PaymentMethod, } from '../payment.interface'; import { BillingInfoDto } from '../payment.dto'; -import { Injectable, Logger } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; +import Logger from '@human-protocol/logger'; @Injectable() export abstract class PaymentProvider { - protected readonly logger: Logger = new Logger(this.constructor.name); + protected readonly logger = Logger.child({ + context: PaymentProvider.name, + }); /** * Create a new customer in the payment provider system diff --git a/packages/apps/job-launcher/server/src/modules/payment/providers/stripe/stripe.service.ts b/packages/apps/job-launcher/server/src/modules/payment/providers/stripe/stripe.service.ts index b40a39d655..e26c5a0b87 100644 --- a/packages/apps/job-launcher/server/src/modules/payment/providers/stripe/stripe.service.ts +++ b/packages/apps/job-launcher/server/src/modules/payment/providers/stripe/stripe.service.ts @@ -43,7 +43,7 @@ export class StripeService extends PaymentProvider { const customer = await this.stripe.customers.create({ email }); return customer.id; } catch (error) { - this.logger.log(error.message, StripeService.name); + this.logger.error(error.message, StripeService.name); throw new ServerError(ErrorPayment.CustomerNotCreated); } } @@ -57,12 +57,12 @@ export class StripeService extends PaymentProvider { customer: customerId ?? undefined, }); } catch (error) { - this.logger.log(error.message, StripeService.name); + this.logger.error(error.message, StripeService.name); throw new ServerError(ErrorPayment.CardNotAssigned); } if (!setupIntent?.client_secret) { - this.logger.log( + this.logger.error( ErrorPayment.ClientSecretDoesNotExist, StripeService.name, ); diff --git a/yarn.lock b/yarn.lock index ffa6fd84b8..ea494d8e79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26297,7 +26297,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.7.2": +"semver@npm:7.7.2, semver@npm:^7.7.2": version: 7.7.2 resolution: "semver@npm:7.7.2" bin: @@ -26324,15 +26324,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.7.2": - version: 7.7.2 - resolution: "semver@npm:7.7.2" - bin: - semver: bin/semver.js - checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea - languageName: node - linkType: hard - "send@npm:0.19.0": version: 0.19.0 resolution: "send@npm:0.19.0"