diff --git a/UPGRADING.md b/UPGRADING.md index 22abfddd..b147ec1f 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,5 +1,18 @@ # Upgrading Guide +## Upgrading
`core` `17.0.0` -> `18.0.0`
`sqs` `17.0.0` -> `18.0.0`
`sns` `18.0.0` -> `19.0.0`
`amqp` `16.0.0` -> `17.0.0` + +### Description of Breaking Changes +- `logger` injectable dependency interface was replaced by `CommonLogger` from `@lokalise/node-core` package. It is compatible with `pino` logger (https://github.com/pinojs/pino) + +### Migration steps +- If you are using `pino` logger, or any other logger compatible with `CommonLogger` interface, you don't need to do anything +- Otherwise, there are serveral properties that need to be provided compared to the old interface: + - `level` - string defining configured minimal logging level + - `isLevelEnabled` - utility method for determining if a given log level will write to the destination. + - `child` - method for generating child logger instance with predefined properties + - `silent` - method used for logging when `silent` level is selected + ## Upgrading from `12.0.0` to `13.0.0` ### Description of Breaking Change diff --git a/packages/amqp/lib/AmqpConnectionManager.ts b/packages/amqp/lib/AmqpConnectionManager.ts index ab7861d2..9fe2cec1 100644 --- a/packages/amqp/lib/AmqpConnectionManager.ts +++ b/packages/amqp/lib/AmqpConnectionManager.ts @@ -1,6 +1,6 @@ -import type { Logger } from '@message-queue-toolkit/core' import type { Connection } from 'amqplib' +import type { CommonLogger } from '@lokalise/node-core' import type { AmqpConfig } from './amqpConnectionResolver' import { resolveAmqpConnection } from './amqpConnectionResolver' @@ -11,14 +11,14 @@ export type ConnectionReceiver = { export class AmqpConnectionManager { private readonly config: AmqpConfig - private readonly logger: Logger + private readonly logger: CommonLogger private readonly connectionReceivers: ConnectionReceiver[] private connection?: Connection public reconnectsActive: boolean public isReconnecting: boolean - constructor(config: AmqpConfig, logger: Logger) { + constructor(config: AmqpConfig, logger: CommonLogger) { this.config = config this.connectionReceivers = [] this.reconnectsActive = true diff --git a/packages/amqp/package.json b/packages/amqp/package.json index cae51a3f..5e91ce4e 100644 --- a/packages/amqp/package.json +++ b/packages/amqp/package.json @@ -1,6 +1,6 @@ { "name": "@message-queue-toolkit/amqp", - "version": "16.2.0", + "version": "17.0.0", "private": false, "license": "MIT", "description": "AMQP adapter for message-queue-toolkit", @@ -25,7 +25,7 @@ "prepublishOnly": "npm run build:release" }, "dependencies": { - "@lokalise/node-core": "^13.1.0", + "@lokalise/node-core": "^13.3.0", "zod": "^3.23.8" }, "peerDependencies": { diff --git a/packages/amqp/test/fakes/FakeLogger.ts b/packages/amqp/test/fakes/FakeLogger.ts index bd6dfc97..537ce47b 100644 --- a/packages/amqp/test/fakes/FakeLogger.ts +++ b/packages/amqp/test/fakes/FakeLogger.ts @@ -1,10 +1,15 @@ -import { deepClone } from '@lokalise/node-core' -import type { Logger } from '@message-queue-toolkit/core' +import { type CommonLogger, deepClone } from '@lokalise/node-core' +import type { Bindings, ChildLoggerOptions } from 'pino' +import type pino from 'pino' -export class FakeLogger implements Logger { +export class FakeLogger implements CommonLogger { public readonly loggedMessages: unknown[] = [] - public readonly loggedWarnings: unknown[] = [] - public readonly loggedErrors: unknown[] = [] + + public level: pino.LevelWithSilentOrString + + constructor(level: pino.LevelWithSilentOrString = 'debug') { + this.level = level + } debug(obj: unknown) { this.saveLog(obj) @@ -24,6 +29,19 @@ export class FakeLogger implements Logger { warn(obj: unknown) { this.saveLog(obj) } + silent(_obj: unknown) { + return + } + + // Child has no effect for FakeLogger + child(_bindings: Bindings, _options?: ChildLoggerOptions): CommonLogger { + return this + } + + isLevelEnabled(_: pino.LevelWithSilentOrString): boolean { + // For FakeLogger we want to track all logs + return true + } private saveLog(obj: unknown) { this.loggedMessages.push(typeof obj === 'object' ? deepClone(obj) : obj) diff --git a/packages/amqp/test/utils/testContext.ts b/packages/amqp/test/utils/testContext.ts index 25b35696..f38a6e6d 100644 --- a/packages/amqp/test/utils/testContext.ts +++ b/packages/amqp/test/utils/testContext.ts @@ -1,5 +1,5 @@ -import type { ErrorReporter, ErrorResolver } from '@lokalise/node-core' -import type { Logger, TransactionObservabilityManager } from '@message-queue-toolkit/core' +import type { CommonLogger, ErrorReporter, ErrorResolver } from '@lokalise/node-core' +import type { TransactionObservabilityManager } from '@message-queue-toolkit/core' import { CommonMetadataFiller, EventRegistry, @@ -81,7 +81,7 @@ export type TestEventsType = (typeof TestEvents)[keyof typeof TestEvents][] export type TestEventPublishPayloadsType = z.infer // @ts-ignore -const TestLogger: Logger = console +const TestLogger: CommonLogger = console export async function registerDependencies( config: AmqpConfig, @@ -202,7 +202,7 @@ export async function registerDependencies( type DiConfig = NameAndRegistrationPair export interface Dependencies { - logger: Logger + logger: CommonLogger amqpConnectionManager: AmqpConnectionManager awilixManager: AwilixManager diff --git a/packages/core/index.ts b/packages/core/index.ts index 02613391..8473ec1f 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -3,8 +3,6 @@ export type { AsyncPublisher, SyncPublisher, TransactionObservabilityManager, - Logger, - LogFn, SchemaMap, ExtraParams, } from './lib/types/MessageQueueTypes' diff --git a/packages/core/lib/events/DomainEventEmitter.ts b/packages/core/lib/events/DomainEventEmitter.ts index f177c668..ebc80c1b 100644 --- a/packages/core/lib/events/DomainEventEmitter.ts +++ b/packages/core/lib/events/DomainEventEmitter.ts @@ -1,4 +1,5 @@ import { + type CommonLogger, type ErrorReporter, InternalError, type TransactionObservabilityManager, @@ -11,7 +12,6 @@ import { resolveHandlerSpy } from '../queues/HandlerSpy' import { randomUUID } from 'node:crypto' import type { ConsumerMessageMetadataType } from '@message-queue-toolkit/schemas' -import type { Logger } from '../types/MessageQueueTypes' import type { EventRegistry } from './EventRegistry' import type { AnyEventHandler, @@ -26,7 +26,7 @@ import type { export type DomainEventEmitterDependencies = { eventRegistry: EventRegistry metadataFiller: MetadataFiller - logger: Logger + logger: CommonLogger errorReporter?: ErrorReporter transactionObservabilityManager?: TransactionObservabilityManager } @@ -39,7 +39,7 @@ type Handlers = { export class DomainEventEmitter { private readonly eventRegistry: EventRegistry private readonly metadataFiller: MetadataFiller - private readonly logger: Logger + private readonly logger: CommonLogger private readonly errorReporter?: ErrorReporter private readonly transactionObservabilityManager?: TransactionObservabilityManager private readonly _handlerSpy?: HandlerSpy< diff --git a/packages/core/lib/queues/AbstractQueueService.ts b/packages/core/lib/queues/AbstractQueueService.ts index 8f55ac9c..5224de28 100644 --- a/packages/core/lib/queues/AbstractQueueService.ts +++ b/packages/core/lib/queues/AbstractQueueService.ts @@ -1,6 +1,6 @@ import { types } from 'node:util' -import type { Either, ErrorReporter, ErrorResolver } from '@lokalise/node-core' +import type { CommonLogger, Either, ErrorReporter, ErrorResolver } from '@lokalise/node-core' import { resolveGlobalErrorLogObject } from '@lokalise/node-core' import type { CommonEventDefinition } from '@message-queue-toolkit/schemas' import type { ZodSchema, ZodType } from 'zod' @@ -11,7 +11,7 @@ import { OFFLOADED_PAYLOAD_POINTER_PAYLOAD_SCHEMA } from '../payload-store/offlo import type { OffloadedPayloadPointerPayload } from '../payload-store/offloadedPayloadMessageSchemas' import type { PayloadStoreConfig } from '../payload-store/payloadStoreTypes' import { isDestroyable } from '../payload-store/payloadStoreTypes' -import type { Logger, MessageProcessingResult } from '../types/MessageQueueTypes' +import type { MessageProcessingResult } from '../types/MessageQueueTypes' import type { DeletionConfig, QueueDependencies, QueueOptions } from '../types/queueOptionsTypes' import { isRetryDateExceeded } from '../utils/dateUtils' import { streamWithKnownSizeToString } from '../utils/streamUtils' @@ -69,7 +69,7 @@ export abstract class AbstractQueueService< protected readonly messageTimestampField: string protected readonly errorReporter: ErrorReporter - public readonly logger: Logger + public readonly logger: CommonLogger protected readonly messageIdField: string protected readonly messageTypeField: string protected readonly logMessages: boolean @@ -169,6 +169,10 @@ export abstract class AbstractQueueService< processingResult: MessageProcessingResult, messageId?: string, ) { + if (!this.logger.isLevelEnabled('debug')) { + return + } + const messageTimestamp = message ? this.tryToExtractTimestamp(message) : undefined const messageProcessingMilliseconds = messageTimestamp ? Date.now() - messageTimestamp.getTime() diff --git a/packages/core/lib/types/MessageQueueTypes.ts b/packages/core/lib/types/MessageQueueTypes.ts index 46b80df5..f41a00ee 100644 --- a/packages/core/lib/types/MessageQueueTypes.ts +++ b/packages/core/lib/types/MessageQueueTypes.ts @@ -1,4 +1,4 @@ -import type { TransactionObservabilityManager } from '@lokalise/node-core' +import type { CommonLogger, TransactionObservabilityManager } from '@lokalise/node-core' import type { ZodSchema } from 'zod' import type { PublicHandlerSpy } from '../queues/HandlerSpy' @@ -27,26 +27,8 @@ export interface AsyncPublisher(obj: T, msg?: string, ...args: any[]): void - // biome-ignore lint/suspicious/noExplicitAny: This is expected - (obj: unknown, msg?: string, ...args: any[]): void - // biome-ignore lint/suspicious/noExplicitAny: This is expected - (msg: string, ...args: any[]): void -} - export type ExtraParams = { - logger?: Logger -} - -export type Logger = { - error: LogFn - info: LogFn - warn: LogFn - debug: LogFn - trace: LogFn - fatal: LogFn + logger?: CommonLogger } export type SchemaMap = Record< diff --git a/packages/core/lib/types/queueOptionsTypes.ts b/packages/core/lib/types/queueOptionsTypes.ts index 04ba85ff..062fc890 100644 --- a/packages/core/lib/types/queueOptionsTypes.ts +++ b/packages/core/lib/types/queueOptionsTypes.ts @@ -1,15 +1,15 @@ -import type { ErrorReporter, ErrorResolver } from '@lokalise/node-core' +import type { CommonLogger, ErrorReporter, ErrorResolver } from '@lokalise/node-core' import type { ZodSchema } from 'zod' import type { PayloadStoreConfig } from '../payload-store/payloadStoreTypes' import type { MessageHandlerConfig } from '../queues/HandlerContainer' import type { HandlerSpy, HandlerSpyParams } from '../queues/HandlerSpy' -import type { Logger, TransactionObservabilityManager } from './MessageQueueTypes' +import type { TransactionObservabilityManager } from './MessageQueueTypes' export type QueueDependencies = { errorReporter: ErrorReporter - logger: Logger + logger: CommonLogger } export type QueueConsumerDependencies = { diff --git a/packages/core/package.json b/packages/core/package.json index 642a35a0..27c50e1d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@message-queue-toolkit/core", - "version": "17.2.3", + "version": "18.0.0", "private": false, "license": "MIT", "description": "Useful utilities, interfaces and base classes for message queue handling. Supports AMQP and SQS with a common abstraction on top currently", @@ -25,7 +25,7 @@ "prepublishOnly": "npm run build:release" }, "dependencies": { - "@lokalise/node-core": "^13.0.1", + "@lokalise/node-core": "^13.3.0", "@message-queue-toolkit/schemas": "^4.0.0", "fast-equals": "^5.0.1", "json-stream-stringify": "^3.1.6", diff --git a/packages/core/test/fakes/FakeLogger.ts b/packages/core/test/fakes/FakeLogger.ts deleted file mode 100644 index fe7f5a16..00000000 --- a/packages/core/test/fakes/FakeLogger.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Logger } from '../../lib/types/MessageQueueTypes' - -export class FakeLogger implements Logger { - public readonly loggedMessages: unknown[] = [] - public readonly loggedWarnings: unknown[] = [] - public readonly loggedErrors: unknown[] = [] - - debug(obj: unknown) { - this.loggedMessages.push(obj) - } - error(obj: unknown) { - this.loggedErrors.push(obj) - } - fatal(obj: unknown) { - this.loggedErrors.push(obj) - } - info(obj: unknown) { - this.loggedMessages.push(obj) - } - trace(obj: unknown) { - this.loggedMessages.push(obj) - } - warn(obj: unknown) { - this.loggedWarnings.push(obj) - } -} diff --git a/packages/core/test/fakes/FakeTransactionObservabilityManager.ts b/packages/core/test/fakes/FakeTransactionObservabilityManager.ts index 74d1ea03..a5298ca4 100644 --- a/packages/core/test/fakes/FakeTransactionObservabilityManager.ts +++ b/packages/core/test/fakes/FakeTransactionObservabilityManager.ts @@ -6,4 +6,6 @@ export class FakeTransactionObservabilityManager implements TransactionObservabi startWithGroup() {} stop() {} + + addCustomAttributes() {} } diff --git a/packages/core/test/testContext.ts b/packages/core/test/testContext.ts index 7f37ee62..37305d36 100644 --- a/packages/core/test/testContext.ts +++ b/packages/core/test/testContext.ts @@ -1,8 +1,7 @@ -import type { ErrorReporter } from '@lokalise/node-core' +import type { CommonLogger, ErrorReporter } from '@lokalise/node-core' import { type Resolver, asClass } from 'awilix' import { Lifetime, asFunction, createContainer } from 'awilix' import { AwilixManager } from 'awilix-manager' -import type { Logger } from 'pino' import pino from 'pino' import { z } from 'zod' @@ -19,7 +18,7 @@ export const SINGLETON_CONFIG = { lifetime: Lifetime.SINGLETON } export type DependencyOverrides = Partial -const TestLogger: Logger = pino() +const TestLogger: CommonLogger = pino() export const TestEvents = { created: { @@ -100,7 +99,7 @@ export async function registerDependencies(dependencyOverrides: DependencyOverri type DiConfig = Record> export interface Dependencies { - logger: Logger + logger: CommonLogger awilixManager: AwilixManager // vendor-specific dependencies diff --git a/packages/sns/package.json b/packages/sns/package.json index b9f14a1d..d100c64d 100644 --- a/packages/sns/package.json +++ b/packages/sns/package.json @@ -1,6 +1,6 @@ { "name": "@message-queue-toolkit/sns", - "version": "18.1.0", + "version": "19.0.0", "private": false, "license": "MIT", "description": "SNS adapter for message-queue-toolkit", @@ -25,7 +25,7 @@ "prepublishOnly": "npm run build:release" }, "dependencies": { - "@lokalise/node-core": "^13.0.1", + "@lokalise/node-core": "^13.3.0", "sqs-consumer": "^11.1.0", "zod": "^3.23.8" }, diff --git a/packages/sns/test/fakes/FakeLogger.ts b/packages/sns/test/fakes/FakeLogger.ts index d93fb7f0..abc6028c 100644 --- a/packages/sns/test/fakes/FakeLogger.ts +++ b/packages/sns/test/fakes/FakeLogger.ts @@ -1,10 +1,18 @@ -import type { Logger } from '@message-queue-toolkit/core' +import type { CommonLogger } from '@lokalise/node-core' +import type { Bindings, ChildLoggerOptions } from 'pino' +import type pino from 'pino' -export class FakeLogger implements Logger { +export class FakeLogger implements CommonLogger { public readonly loggedMessages: unknown[] = [] public readonly loggedWarnings: unknown[] = [] public readonly loggedErrors: unknown[] = [] + public readonly level: pino.LevelWithSilentOrString + + constructor(level: pino.LevelWithSilentOrString = 'debug') { + this.level = level + } + debug(obj: unknown) { this.loggedMessages.push(obj) } @@ -23,4 +31,18 @@ export class FakeLogger implements Logger { warn(obj: unknown) { this.loggedWarnings.push(obj) } + // Noop function + silent(_obj: unknown) { + return + } + + // Child has no effect for FakeLogger + child(_bindings: Bindings, _options?: ChildLoggerOptions): CommonLogger { + return this + } + + isLevelEnabled(_level: string): boolean { + // For FakeLogger we want to track all logs + return true + } } diff --git a/packages/sns/test/utils/testContext.ts b/packages/sns/test/utils/testContext.ts index bbc803ab..cbaa02ec 100644 --- a/packages/sns/test/utils/testContext.ts +++ b/packages/sns/test/utils/testContext.ts @@ -1,8 +1,8 @@ import { S3 } from '@aws-sdk/client-s3' import { SNSClient } from '@aws-sdk/client-sns' import { SQSClient } from '@aws-sdk/client-sqs' -import type { ErrorReporter, ErrorResolver } from '@lokalise/node-core' -import type { Logger, TransactionObservabilityManager } from '@message-queue-toolkit/core' +import type { CommonLogger, ErrorReporter, ErrorResolver } from '@lokalise/node-core' +import type { TransactionObservabilityManager } from '@message-queue-toolkit/core' import { CommonMetadataFiller, EventRegistry, @@ -30,7 +30,7 @@ export const SINGLETON_CONFIG = { lifetime: Lifetime.SINGLETON } export type DependencyOverrides = Partial // @ts-ignore -const TestLogger: Logger = console +const TestLogger: CommonLogger = console export const TestEvents = { created: { @@ -188,7 +188,7 @@ export async function registerDependencies( type DiConfig = Record> export interface Dependencies { - logger: Logger + logger: CommonLogger sqsClient: SQSClient snsClient: SNSClient stsClient: STSClient diff --git a/packages/sqs/package.json b/packages/sqs/package.json index 8f8bea5d..5f4fe209 100644 --- a/packages/sqs/package.json +++ b/packages/sqs/package.json @@ -1,6 +1,6 @@ { "name": "@message-queue-toolkit/sqs", - "version": "17.3.0", + "version": "18.0.0", "private": false, "license": "MIT", "description": "SQS adapter for message-queue-toolkit", @@ -25,7 +25,7 @@ "prepublishOnly": "npm run build:release" }, "dependencies": { - "@lokalise/node-core": "^13.0.1", + "@lokalise/node-core": "^13.3.0", "sqs-consumer": "^11.1.0", "zod": "^3.23.8" }, diff --git a/packages/sqs/test/fakes/FakeLogger.ts b/packages/sqs/test/fakes/FakeLogger.ts index d93fb7f0..b9eb8bd3 100644 --- a/packages/sqs/test/fakes/FakeLogger.ts +++ b/packages/sqs/test/fakes/FakeLogger.ts @@ -1,10 +1,18 @@ -import type { Logger } from '@message-queue-toolkit/core' +import type { CommonLogger } from '@lokalise/node-core' +import type { Bindings, ChildLoggerOptions } from 'pino' +import type pino from 'pino' -export class FakeLogger implements Logger { +export class FakeLogger implements CommonLogger { public readonly loggedMessages: unknown[] = [] public readonly loggedWarnings: unknown[] = [] public readonly loggedErrors: unknown[] = [] + public readonly level: pino.LevelWithSilentOrString + + constructor(level: pino.LevelWithSilentOrString = 'debug') { + this.level = level + } + debug(obj: unknown) { this.loggedMessages.push(obj) } @@ -23,4 +31,18 @@ export class FakeLogger implements Logger { warn(obj: unknown) { this.loggedWarnings.push(obj) } + // Noop function + silent(_obj: unknown) { + return + } + + // Child has no effect for FakeLogger + child(_bindings: Bindings, _options?: ChildLoggerOptions): CommonLogger { + return this + } + + isLevelEnabled(_level: pino.LevelWithSilentOrString): boolean { + // For FakeLogger we want to track all logs + return true + } } diff --git a/packages/sqs/test/utils/testContext.ts b/packages/sqs/test/utils/testContext.ts index 0bad3f5b..f4609ebe 100644 --- a/packages/sqs/test/utils/testContext.ts +++ b/packages/sqs/test/utils/testContext.ts @@ -1,7 +1,7 @@ import { S3 } from '@aws-sdk/client-s3' import { SQSClient } from '@aws-sdk/client-sqs' -import type { ErrorReporter, ErrorResolver } from '@lokalise/node-core' -import type { Logger, TransactionObservabilityManager } from '@message-queue-toolkit/core' +import type { CommonLogger, ErrorReporter, ErrorResolver } from '@lokalise/node-core' +import type { TransactionObservabilityManager } from '@message-queue-toolkit/core' import type { Resolver } from 'awilix' import { Lifetime, asClass, asFunction, createContainer } from 'awilix' import { AwilixManager } from 'awilix-manager' @@ -17,7 +17,7 @@ export const SINGLETON_CONFIG = { lifetime: Lifetime.SINGLETON } export type DependencyOverrides = Partial // @ts-ignore -const TestLogger: Logger = console +const TestLogger: CommonLogger = console export async function registerDependencies(dependencyOverrides: DependencyOverrides = {}) { const diContainer = createContainer({ @@ -92,7 +92,7 @@ export async function registerDependencies(dependencyOverrides: DependencyOverri type DiConfig = Record> export interface Dependencies { - logger: Logger + logger: CommonLogger sqsClient: SQSClient s3: S3 awilixManager: AwilixManager