🌻A modular DI, MVC, and Model binding/validation framework for NodeJS and TypeScript or ES6
Dandi’s splits the responsibilities of logging into two primary parts:
Logger
is the primary interface that developers will interact with - implementations of Logger
are used to generate
the log entries themselves, and can draw in contextual metadata about where they are called from. An app will have a
single Logger
instance. If no provider for Logger
is available, the app will use NoopLogger
by default.
LogListener
implementations receive the log data generated by the Logger
. What they do with that data depends on
the implementation - ConsoleLogListener
, for example, formats the log data and sends it to the program’s console
output. Other implementations could store the data locally, or transmit it to a remote API. An app may use any number
of LogListener
implementations simultaneously.
By default, this pattern is implemented using an RxJS Subject
. The Subject
instance is defined using the LogStream
injection token. The Logger
instance calls next()
on the LogStream
for each log entry. LogListener
instances
subscribe to the LogStream
as an Observable
.
Note: The DI system in @dandi/core
uses Logger
internally, which is why Logger
is part of the root @dandi/core
package and not @dandi/core/logging
.
LoggingModule
in @dandi/core/logging// main.ts
import { DandiApplication } from '@dandi/core'
import { LoggingModule } from '@dandi/core/logging' // includes ContextualLogger
const container = new DandiApplication({
providers: [
LoggingModule,
/* other providers */
]
})
// my-service.ts
import { Inject, Injectable, Logger } from '@dandi/core'
@Injectable()
export class MyService {
constructor(@Inject(Logger) private logger: Logger) {
this.logger.debug('Constructed!')
}
}
In the above example, when the instances are created, the ContextualLogger
instance uses the InjectionContext
token
provided by the Dandi DI system to receive a reference to the instance of MyService
that caused it to be created. It
then includes that reference when creating log entries like the call to debug()
.
@dandi/core
NoopLogger
does not generate log entriesWhen no Logger
implementation is configured, NoopLogger
is used by default.
console
Include ConsoleLogListener
by calling the use
method on LoggingModule
.
import { DandiApplication } from '@dandi/core'
import { ConsoleLogListener, LoggingModule } from '@dandi/core/logging'
const container = new DandiApplication({
providers: [
LoggingModule.use(ConsoleLogListener),
/* other providers */
]
})
ConsoleLogListener
can be customized to format the log data as desired.
TODO
TODO
TODO