logger.info('ServiceName.methodName.')
およびlogger.info('ServiceName.methodName -> done.')
を書くのにまだ飽きていますか? たぶん、あなたは、私のように、このビジネスを自動化することを繰り返し考えましたか? この記事では、2つのデコレーターだけで問題を解決するためのオプションの1つとして、 クラスロガーについて説明します。
なぜ必要なのでしょうか?
すべての完璧主義者がエンジニアではありませんが、すべてのエンジニアは完璧主義者です(まあ、ほぼ)。 美しい簡潔な抽象が好きです。 私たちはワニのセットの美しさを見て、人は準備ができておらず、読むことができません。 私たちは神のように感じ、私たちのルールに従って生きるミクロの宇宙を作りたいと思っています。 おそらく、これらすべての資質は私たちの計り知れない怠に起因しています。 いいえ、エンジニアはクラスとして働くことを恐れていませんが、彼の腕が自動化のために到達する日常的な反復アクションを激しく嫌っています。
ロギングのみを目的とした数千行のコードを記述した後、通常、メッセージを記述するための独自のパターンと標準を作成します。 残念ながら、これらのパターンを手動で適用する必要があります。 クラスロガーの主な「理由」は、クラスを作成してそのメソッドを呼び出すときに、テンプレートメッセージを簡単に記録する宣言的で構成可能な方法を提供することです。
チェッカーがむき出しになっています!
さまようことなく、コードに直行しましょう。
import { LogClass, Log } from 'class-logger' @LogClass() class ServiceCats { @Log() eat(food: string) { return 'purr' } }
このサービスは3つのログエントリを作成します。
- コンストラクターに渡される引数のリストで作成する前。
- 引数のリストを指定して
eat
を呼び出す前に。 - 引数のリストと実行結果で
eat
を呼び出した後。
コードの言葉で:
// ServiceCats // `ServiceCats.construct. Args: [].` const serviceCats = new ServiceCats() // `eat` // `ServiceCats.eat. Args: [milk].` serviceCats.eat('milk') // `eat` // `ServiceCats.eat -> done. Args: [milk]. Res: purr.`
ライブ突く 。
誓約できるイベントの完全なリスト:
- クラスを作成する前。
- 同期メソッドと非同期メソッド、および静的および非静的の両方の機能プロパティを呼び出す前。
- 同期および非同期のメソッドと、静的および非静的の両方の機能プロパティを呼び出した後。
- 同期および非同期のメソッドと機能プロパティ(静的および非静的の両方)の呼び出しにおけるエラー。
機能プロパティは、プロパティに割り当てられた矢印関数です( class ServiceCats { private meow = () => null }
)。 実行コンテキストを維持するために最もよく使用されます( this
)。
「設定可能な」ロギング方法が約束されました
クラスロガーの構成階層の3つのレベル:
各メソッドを呼び出すと、3つのレベルすべてがマージされます。 このライブラリは、妥当なグローバルなデフォルト設定を提供するため、事前の設定なしで使用できます。
グローバル設定
アプリケーション全体に対して作成されます。 setConfig
でオーバーライドできます。
import { setConfig } from 'class-logger' setConfig({ log: console.info, })
クラス構成
クラスごとに一意であり、このクラスのすべてのメソッドに適用されます。 グローバル設定を上書きする場合があります。
import { LogClass } from 'class-logger' setConfig({ log: console.info, }) @LogClass({ // log: console.debug, }) class ServiceCats {}
メソッド構成
メソッド自体に対してのみ機能します。 クラス構成およびグローバル構成よりも優先されます。
import { LogClass } from 'class-logger' setConfig({ log: console.info, }) @LogClass({ // log: console.debug, }) class ServiceCats { private energy = 100 @Log({ // log: console.warn, }) eat(food: string) { return 'purr' } // `console.debug` sleep() { this.energy += 100 } }
突くライブ
何を設定できますか?
構成を変更する方法を検討しましたが、変更内容を正確に把握することはまだできていません。
ここでは、さまざまなケースの構成オブジェクトの多くの例を見つけることができます 。
TypeScriptをよく理解している場合は、インターフェイスにリンクしてください。 ロシア人より:)
構成オブジェクトには次のプロパティがあります。
ログ
これは、実際にロギングを処理する関数です。 入力時に文字列として書式設定されたメッセージを受け取ります。 次のイベントを記録するために使用されます。
- クラスを作成する前。
- 同期メソッドと非同期メソッド、および静的および非静的の両方の機能プロパティを呼び出す前。
- 同期および非同期のメソッドと、静的および非静的の両方の機能プロパティを呼び出した後。
デフォルトでは、 console.log
。
logError
これはロギングも処理する機能ですが、エラーメッセージのみです。 彼女はまた、フォーマットされたメッセージを文字列として受け取ります。 次のイベントを記録するために使用されます。
- 同期および非同期のメソッドと機能プロパティ(静的および非静的の両方)の呼び出しにおけるエラー。
デフォルトはconsole.error
です。
これは、 start
とend
2つのメソッドを持つオブジェクトです。 これらのメソッドは、同じフォーマットのメッセージを作成します。
start
は、次のイベントのメッセージを作成します。
- クラスを作成する前。
- 同期メソッドと非同期メソッド、および静的および非静的の両方の機能プロパティを呼び出す前。
end
は、次のイベントのメッセージを生成します。
- 同期および非同期のメソッドと、静的および非静的の両方の機能プロパティを呼び出した後。
- 同期および非同期のメソッドと機能プロパティ(静的および非静的の両方)の呼び出しにおけるエラー。
デフォルトでは、 new ClassLoggerFormatterService()
。
含む
最終メッセージに含めるべきものの構成。
args
ブール値またはオブジェクトのいずれかです。
boolean
場合、すべてのメッセージ( start
およびend
)に引数のリストを含めるかどうかを設定します( Args: [milk]
?を思い出してください)。
オブジェクトの場合、2つのブール型プロパティstart
およびend
です。 start
は、 start
メッセージに引数リストを含め、 end
メッセージにend
を含めるかどうかを指定します。
デフォルトはtrue
です。
構築する
これは、クラスの作成を記録するかどうかを制御するboolean
です。
デフォルトはtrue
です。
結果
これは、メソッドからの戻り値のロギングを制御するboolean
値です。 戻り値は、実行が成功したときにメソッドが返すものであるだけでなく、実行が失敗した場合にスローするエラーでもあることに注意してください。 Res: purr
覚えていますか? このフラグがfalse
場合、 Res: purr
はありません。
デフォルトはtrue
です。
classInstance
ブール値またはオブジェクトのいずれかです。 概念はinclude.args
と同じです。
クラスのシリアル化されたインスタンスビューを投稿に追加します。 つまり、クラスにプロパティがある場合、JSONでシリアル化されてログに追加されます。
すべてのプロパティがシリアル化できるわけではありません。 クラスロガーは次のロジックを使用します:
- インタンサの独自の(プロトタイプに含まれない)プロパティをすべて使用します。
- なんで? プロトタイプが動的に変更されることはほとんどないため、その内容を記録することはほとんど意味がありません。
- それらからすべて
function
型を捨てfunction
。
- なんで? ほとんどの場合、
function
型のプロパティは、コンテキストを維持するために従来の方法では作成されない単なる矢印関数です( this
)。 動的な性質を持つことはめったにないため、ログに記録しても意味がありません。
- それらから、単純なオブジェクトではないすべてのオブジェクトを捨てます。
- これらの単純なオブジェクトは何ですか?
ClassLoggerFormatterService
は、プロトタイプがObject.prototype
場合、オブジェクトを単純とObject.prototype
ます。 - なんで? 多くの場合、他のサービスクラスのインスタンスはプロパティとして機能します。 シリアル化を開始すると、ログは最もmostい方法で膨らみます。
- 残っているすべてをJSON文字列でシリアル化します。
class ServiceA {} @LogClass({ include: { classInstance: true, }, }) class Test { private serviceA = new ServiceA() private prop1 = 42 private prop2 = { test: 42 } private method1 = () => null @Log() public method2() { return 42 } } // `Test` // 'Test.construct. Args: []. Class instance: {"prop1":42,"prop2":{"test":42}}.' const test = new Test() // `method2` // 'Test.method2. Args: []. Class instance: {"prop1":42,"prop2":{"test":42}}.' test.method2() // `method2` // 'Test.method2 -> done. Args: []. Class instance: {"prop1":42,"prop2":{"test":42}}. Res: 42.'
デフォルトはfalse
です。
アイデアが好きなのに、美しいというアイデアが別のメッセージ行形式を主張している場合はどうでしょうか? 独自のフォーマッターを渡すことで、メッセージのフォーマットを完全に制御できます。
独自のフォーマッタを最初から作成できます。 もちろん。 ただし、このオプションはこのフレームワークではカバーされません(この特定のオプションに興味がある場合は、READMEの「フォーマット」セクションを参照してください)。
書式設定をオーバーライドする最も速く簡単な方法は、デフォルトのフォーマッタであるClassLoggerFormatterService
からフォーマッタを継承することです。
ClassLoggerFormatterService
は、最終メッセージの小さなブロックを作成する次のprotected
メソッドがあります。
base
- クラス名とメソッド名を返します。 例:
ServiceCats.eat
operation
- メソッドが正常に完了したかどうかに応じて、
-> done
または-> error
返します。
args
classInstance
- クラスのシリアル化されたインスタンスを返します。 例:
. Class instance: {"prop1":42,"prop2":{"test":42}}
configにinclude.classInstance
を含めたが、何らかの理由でロギング時にインスタンス自体が使用できない場合(たとえば、静的メソッドの場合やクラスを作成する前)、 N/A
返しますN/A
result
- シリアル化された実行結果またはシリアル化されたエラーを返します。 内部のオブジェクトにfast-safe-stringifyを使用します。 シリアル化されたエラーには、次のプロパティが含まれます。
- エラーの作成に使用されたクラス(関数)の名前(
error.constructor.name
)。 - コード(
error.code
)。 - メッセージ(
error.message
)。 - 名前(
error.name
)。 - スタックトレース(
error.stack
)。
final
start
メッセージは次のもので構成されます。
base
args
classInstance
final
end
メッセージは次のもので構成されます。
base
operation
args
classInstance
result
final
必要な基本メソッドのみをオーバーライドできます。
すべての投稿にタイムスタンプを追加する方法を見てみましょう。
これは実際のプロジェクトで行うべきだと言っているのではありません。 pino 、 winston、および他のほとんどのロガーは、自分でこれを行うことができます。 この例は、教育目的のみです。
import { ClassLoggerFormatterService, IClassLoggerFormatterStartData, setConfig, } from 'class-logger' class ClassLoggerTimestampFormatterService extends ClassLoggerFormatterService { protected base(data: IClassLoggerFormatterStartData) { const baseSuper = super.base(data) const timestamp = Date.now() const baseWithTimestamp = `${timestamp}:${baseSuper}` return baseWithTimestamp } } setConfig({ formatter: new ClassLoggerTimestampFormatterService(), })
突くライブ
おわりに
プロジェクトでこのライブラリを使用する前に、インストール手順に従って要件を必ずお読みください。
あなたが時間を無駄にしないことを願っています。そして、この記事は少なくともあなたにとって有用でした。 蹴って批判してください。 一緒にコードを改善する方法を学びます。