Перейти до основного вмісту

LogMediator

У Ditsmod-застосунках можна підмінити дефолтний логер на свій логер, і це дасть вам змогу у свій спосіб записувати навіть ті повідомлення, що видаються у @ditsmod/core. Але підміна логера не дозволяє змінювати текст самих повідомлень та рівень логування (trace, debug, info, warn, error). Для цього використовується LogMediator (або його дочірній клас SystemLogMediator). Звичайно ж, якщо ви маєте безпосередній доступ до коду, де логер записує певне повідомлення, то ви тут же на місці зможете це повідомлення змінити і без LogMediator. А якщо повідомлення видає сам фреймворк Ditsmod або його модулі, без LogMediator не обійтись.

Якщо ви захочете написати модуль для застосунку Ditsmod, щоб опублікувати його, наприклад, на npmjs.com, то рекомендується використовувати саме LogMediator замість Logger, оскільки користувачі зможуть змінювати повідомлення, які пише ваш модуль.

У репозиторії Ditsmod є приклад 11-override-core-log-messages, де продемонстровано декілька варіантів використання LogMediator. Щоб спробувати даний приклад, необхідно спочатку клонувати репозиторій та встановити залежності:

git clone https://github.com/ditsmod/ditsmod.git
cd ditsmod
npm i
cd examples/11-override-core-log-messages
npm start

Після чого ви зможете у своєму редакторі безпосередньо проглядати та експериментувати з даним прикладом.

Розширення класу LogMediator

Оскільки у цьому прикладі розширюється клас, тут використовується рекомендоване налаштування TypeScript у tsconfig.json:

{
"compilerOptions": {
// ...
"noImplicitOverride": true
// ...
}
// ...
}

Ця фіча стала доступною у TypeScript починаючи з версії 4.3, вона дозволяє робити ваш код більш читабельним, оскільки не дозволяє переписувати властивості та методи батьківського класу без слова override. З іншого боку, якщо у батьківському класі зникне метод, який у дочірньому класі позначено override, то TypeScript також кине помилку з відповідною підказкою.

Тепер давайте проглянемо на MyLogMediator:

import { SystemLogMediator, InputLogFilter } from '@ditsmod/core';

export class MyLogMediator extends SystemLogMediator {
/**
* Here host: "${host}", and here port: "${port}"
*/
override serverListen(self: object, host: string, port: number) {
const className = self.constructor.name;
const inputLogFilter = new InputLogFilter();
inputLogFilter.className = className;
this.setLog('info', inputLogFilter, `Here host: "${host}", and here port: "${port}"`);
}
}

Як бачите, MyLogMediator розширює SystemLogMediator, а метод serverListen() позначено ключовим словом override, оскільки тут переписується батьківський метод з точно такою назвою. У коментарях до методу написано текст повідомлення, що буде записуватись у логи. Майже в усі методи SystemLogMediator першим аргументом передається this того інстансу класу, де використовується SystemLogMediator, щоб можна було легко отримати ім'я того класу. Решта аргументів є довільною, усе залежить від контексту використання цих методів.

Результат можна побачити, якщо запустити застосунок командою npm start, після чого вам повинно видатись саме те повідомлення, яке сформовано у даному методі.

Підміна LogMediator на рівні застосунку

Якщо проглянути AppModule, можна побачити як підміняється SystemLogMediator на MyLogMediator:

import { SystemLogMediator, rootModule } from '@ditsmod/core';

import { MyLogMediator } from './my-log-mediator.js';

@rootModule({
// ...
providersPerApp: [
{ token: SystemLogMediator, useClass: MyLogMediator },
MyLogMediator,
],
})
export class AppModule {}

У даному разі, перший елемент масиву providersPerApp дозволить використовувати MyLogMediator у коді Ditsmod core, другий елемент - дозволить запитувати інстанс MyLogMediator у конструкторах контролерів чи сервісів вашого застосунку.

Майте на увазі, що така підміна на рівні застосунку працює без додаткових налаштувань тільки в кореневому модулі. Якщо ж ви це зробите не в кореневому модулі, вам додатково прийдеться вирішувати колізію провайдерів в кореневому модулі (хоча це і робиться досить просто).

Підміна LogMediator на рівні модуля

Як було сказано на початку, якщо ви плануєте публікувати ваш модуль для інших користувачів, рекомендується використовувати LogMediator замість Logger. В такому разі користувачі зможуть змінювати повідомлення, які пише ваш модуль.

Щоб змінити повідомлення із зовнішнього сервісу, у OtherModule розширено SomeLogMediator та переписано той метод, що працює у SomeService. Після цього зроблену підміну SomeLogMediator на OtherLogMediator:

import { featureModule } from '@ditsmod/core';

import { SomeModule } from '../some/some.module.js';
import { SomeLogMediator } from '../some/some-log-mediator.js';
import { OtherController } from './other.controller.js';
import { OtherLogMediator } from './other-log-mediator.js';

@featureModule({
imports: [SomeModule],
controllers: [OtherController],
providersPerMod: [{ token: SomeLogMediator, useClass: OtherLogMediator }],
})
export class OtherModule {}