ngx-logger
Version:
[](https://www.npmjs.com/package/ngx-logger)
876 lines (852 loc) • 41.9 kB
JavaScript
import { HttpRequest, HttpResponse, HttpBackend, HttpHeaders, HttpParams } from '@angular/common/http';
import { ɵɵinject, ɵɵdefineInjectable, ɵsetClassMetadata, Injectable, Optional, PLATFORM_ID, Inject, ɵɵdefineNgModule, ɵɵdefineInjector, ɵɵsetNgModuleScope, NgModule } from '@angular/core';
import { of, throwError } from 'rxjs';
import { filter, map, retry, shareReplay, catchError, take } from 'rxjs/operators';
import { decode } from 'vlq';
import { DatePipe, isPlatformBrowser, CommonModule } from '@angular/common';
/**
* Injection token of logger config
*/
const TOKEN_LOGGER_CONFIG = 'TOKEN_LOGGER_CONFIG';
class NGXLoggerConfigEngine {
constructor(config) {
this.config = this._clone(config);
}
/** Get a readonly access to the level configured for the NGXLogger */
get level() {
return this.config.level;
}
/** Get a readonly access to the serverLogLevel configured for the NGXLogger */
get serverLogLevel() {
return this.config.serverLogLevel;
}
updateConfig(config) {
this.config = this._clone(config);
}
getConfig() {
return this._clone(this.config);
}
// TODO: This is a shallow clone, If the config ever becomes hierarchical we must make this a deep clone
_clone(object) {
const cloneConfig = { level: null };
Object.keys(object).forEach((key) => {
cloneConfig[key] = object[key];
});
return cloneConfig;
}
}
/**
* Injection token of logger config engine factory
*/
const TOKEN_LOGGER_CONFIG_ENGINE_FACTORY = 'TOKEN_LOGGER_CONFIG_ENGINE_FACTORY';
class NGXLoggerConfigEngineFactory {
provideConfigEngine(config) {
return new NGXLoggerConfigEngine(config);
}
}
/**
* Injection token of logger mapper service
*/
const TOKEN_LOGGER_MAPPER_SERVICE = 'TOKEN_LOGGER_MAPPER_SERVICE';
class NGXLoggerMapperService {
constructor(httpBackend) {
this.httpBackend = httpBackend;
/** cache for source maps, key is source map location, ie. 'http://localhost:4200/main.js.map' */
this.sourceMapCache = new Map();
/** cache for specific log position, key is the dist position, ie 'main.js:339:21' */
this.logPositionCache = new Map();
}
/**
* Returns the log position of the caller
* If sourceMaps are enabled, it attemps to get the source map from the server, and use that to parse the position
* @param config
* @param metadata
* @returns
*/
getLogPosition(config, metadata) {
const stackLine = this.getStackLine(config);
// if we were not able to parse the stackLine, just return an empty Log Position
if (!stackLine) {
return of({ fileName: '', lineNumber: 0, columnNumber: 0 });
}
const logPosition = this.getLocalPosition(stackLine);
if (!config.enableSourceMaps) {
return of(logPosition);
}
const sourceMapLocation = this.getSourceMapLocation(stackLine);
return this.getSourceMap(sourceMapLocation, logPosition);
}
/**
* Get the stackline of the original caller
* @param config
* @returns null if stackline was not found
*/
getStackLine(config) {
const error = new Error();
try {
// noinspection ExceptionCaughtLocallyJS
throw error;
}
catch (e) {
try {
// Here are different examples of stacktrace
// Firefox (last line is the user code, the 4 first are ours):
// getStackLine@http://localhost:4200/main.js:358:23
// getCallerDetails@http://localhost:4200/main.js:557:44
// _log@http://localhost:4200/main.js:830:28
// debug@http://localhost:4200/main.js:652:14
// handleLog@http://localhost:4200/main.js:1158:29
// Chrome and Edge (last line is the user code):
// Error
// at Function.getStackLine (ngx-logger.js:329)
// at NGXMapperService.getCallerDetails (ngx-logger.js:528)
// at NGXLogger._log (ngx-logger.js:801)
// at NGXLogger.info (ngx-logger.js:631)
// at AppComponent.handleLog (app.component.ts:38)
let defaultProxy = 4; // We make 4 functions call before getting here
const firstStackLine = error.stack.split('\n')[0];
if (!firstStackLine.includes('.js:')) {
// The stacktrace starts with no function call (example in Chrome or Edge)
defaultProxy = defaultProxy + 1;
}
return error.stack.split('\n')[(defaultProxy + (config.proxiedSteps || 0))];
}
catch (e) {
return null;
}
}
}
/**
* Get position of caller without using sourceMaps
* @param stackLine
* @returns
*/
getLocalPosition(stackLine) {
// strip base path, then parse filename, line, and column, stackline looks like this :
// Firefox
// handleLog@http://localhost:4200/main.js:1158:29
// Chrome and Edge
// at AppComponent.handleLog (app.component.ts:38)
const positionStartIndex = stackLine.lastIndexOf('\/');
let positionEndIndex = stackLine.indexOf(')');
if (positionEndIndex < 0) {
positionEndIndex = undefined;
}
const position = stackLine.substring(positionStartIndex + 1, positionEndIndex);
const dataArray = position.split(':');
if (dataArray.length === 3) {
return { fileName: dataArray[0], lineNumber: +dataArray[1], columnNumber: +dataArray[2] };
}
return { fileName: 'unknown', lineNumber: 0, columnNumber: 0 };
}
getTranspileLocation(stackLine) {
// Example stackLine:
// Firefox : getStackLine@http://localhost:4200/main.js:358:23
// Chrome and Edge : at Function.getStackLine (ngx-logger.js:329)
let locationStartIndex = stackLine.indexOf('(');
if (locationStartIndex < 0) {
locationStartIndex = stackLine.lastIndexOf('@');
if (locationStartIndex < 0) {
locationStartIndex = stackLine.lastIndexOf(' ');
}
}
let locationEndIndex = stackLine.indexOf(')');
if (locationEndIndex < 0) {
locationEndIndex = undefined;
}
return stackLine.substring(locationStartIndex + 1, locationEndIndex);
}
/**
* Gets the URL of the sourcemap (the URL can be relative or absolute, it is browser dependant)
* @param stackLine
* @returns
*/
getSourceMapLocation(stackLine) {
const file = this.getTranspileLocation(stackLine);
const mapFullPath = file.substring(0, file.lastIndexOf(':'));
return mapFullPath.substring(0, mapFullPath.lastIndexOf(':')) + '.map';
}
getMapping(sourceMap, position) {
// => ';' indicates end of a line
// => ',' separates mappings in a line
// decoded mapping => [ generatedCodeColumn, sourceFileIndex, sourceCodeLine, sourceCodeColumn, nameIndex ]
let sourceFileIndex = 0, // second field
sourceCodeLine = 0, // third field
sourceCodeColumn = 0; // fourth field
const lines = sourceMap.mappings.split(';');
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
// reset column position to 0 after each line
let generatedCodeColumn = 0;
// decode sections in line
const columns = lines[lineIndex].split(',');
for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {
const decodedSection = decode(columns[columnIndex]);
if (decodedSection.length >= 4) {
// update relative positions
generatedCodeColumn += decodedSection[0];
sourceFileIndex += decodedSection[1];
sourceCodeLine += decodedSection[2];
sourceCodeColumn += decodedSection[3];
}
// check if matching map
if (lineIndex === position.lineNumber) {
if (generatedCodeColumn === position.columnNumber) {
// matching column and line found
return { fileName: sourceMap.sources[sourceFileIndex], lineNumber: sourceCodeLine, columnNumber: sourceCodeColumn };
}
else if (columnIndex + 1 === columns.length) {
// matching column not found, but line is correct
return { fileName: sourceMap.sources[sourceFileIndex], lineNumber: sourceCodeLine, columnNumber: 0 };
}
}
}
}
// failed if reached
return { fileName: 'unknown', lineNumber: 0, columnNumber: 0 };
}
/**
* does the http get request to get the source map
* @param sourceMapLocation
* @param distPosition
*/
getSourceMap(sourceMapLocation, distPosition) {
const req = new HttpRequest('GET', sourceMapLocation);
const distPositionKey = `${distPosition.fileName}:${distPosition.lineNumber}:${distPosition.columnNumber}`;
// if the specific log position is already in cache return it
if (this.logPositionCache.has(distPositionKey)) {
return this.logPositionCache.get(distPositionKey);
}
// otherwise check if the source map is already cached for given source map location
if (!this.sourceMapCache.has(sourceMapLocation)) {
if (!this.httpBackend) {
console.error('NGXLogger : Can\'t get sourcemap because HttpBackend is not provided. You need to import HttpClientModule');
this.sourceMapCache.set(sourceMapLocation, of(null));
}
else {
// obtain the source map if not cached
this.sourceMapCache.set(sourceMapLocation, this.httpBackend.handle(req).pipe(filter((e) => e instanceof HttpResponse), map((httpResponse) => httpResponse.body), retry(3), shareReplay(1)));
}
}
// at this point the source map is cached, use it to get specific log position mapping
const logPosition$ = this.sourceMapCache.get(sourceMapLocation).pipe(map((sourceMap) => {
// sourceMap can be null if HttpBackend is not provided for example
if (!sourceMap) {
return distPosition;
}
// map generated position to source position
return this.getMapping(sourceMap, distPosition);
}), catchError(() => of(distPosition)), shareReplay(1));
// store specific log position in cache for given dest position and return it
this.logPositionCache.set(distPositionKey, logPosition$);
return logPosition$;
}
}
/** @nocollapse */ NGXLoggerMapperService.ɵfac = function NGXLoggerMapperService_Factory(t) { return new (t || NGXLoggerMapperService)(ɵɵinject(HttpBackend, 8)); };
/** @nocollapse */ NGXLoggerMapperService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerMapperService, factory: NGXLoggerMapperService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerMapperService, [{
type: Injectable
}], function () { return [{ type: HttpBackend, decorators: [{
type: Optional
}] }]; }, null); })();
/**
* Injection token of logger metadata service
*/
const TOKEN_LOGGER_METADATA_SERVICE = 'TOKEN_LOGGER_METADATA_SERVICE';
class NGXLoggerMetadataService {
constructor(datePipe) {
this.datePipe = datePipe;
}
computeTimestamp(config) {
const defaultTimestamp = () => new Date().toISOString();
if (config.timestampFormat) {
if (!this.datePipe) {
console.error('NGXLogger : Can\'t use timeStampFormat because DatePipe is not provided. You need to provide DatePipe');
return defaultTimestamp();
}
else {
return this.datePipe.transform(new Date(), config.timestampFormat);
}
}
return defaultTimestamp();
}
getMetadata(level, config, message, additional) {
const metadata = {
level: level,
additional: additional,
};
// The user can send a function
// This is useful in order to compute string concatenation only when the log will actually be written
if (message && typeof message === 'function') {
metadata.message = message();
}
else {
metadata.message = message;
}
metadata.timestamp = this.computeTimestamp(config);
return metadata;
}
}
/** @nocollapse */ NGXLoggerMetadataService.ɵfac = function NGXLoggerMetadataService_Factory(t) { return new (t || NGXLoggerMetadataService)(ɵɵinject(DatePipe, 8)); };
/** @nocollapse */ NGXLoggerMetadataService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerMetadataService, factory: NGXLoggerMetadataService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerMetadataService, [{
type: Injectable
}], function () { return [{ type: DatePipe, decorators: [{
type: Optional
}] }]; }, null); })();
// I kept this class alive only to avoid a breaking change with the old version
// This class does not implement anything so it is useless and the interface is enough
/**
* @deprecated this class does not implement anything thus being useless, you should rather implements @see INGXLoggerMonitor
*/
class NGXLoggerMonitor {
}
/**
* Injection token of logger metadata service
*/
const TOKEN_LOGGER_RULES_SERVICE = 'TOKEN_LOGGER_RULES_SERVICE';
class NGXLoggerRulesService {
shouldCallWriter(level, config, message, additional) {
return !config.disableConsoleLogging && level >= config.level;
}
shouldCallServer(level, config, message, additional) {
return !!config.serverLoggingUrl && level >= config.serverLogLevel;
}
shouldCallMonitor(level, config, message, additional) {
// The default behavior is to call the monitor only if the writer or the server is called
return this.shouldCallWriter(level, config, message, additional) || this.shouldCallServer(level, config, message, additional);
}
}
/** @nocollapse */ NGXLoggerRulesService.ɵfac = function NGXLoggerRulesService_Factory(t) { return new (t || NGXLoggerRulesService)(); };
/** @nocollapse */ NGXLoggerRulesService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerRulesService, factory: NGXLoggerRulesService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerRulesService, [{
type: Injectable
}], null, null); })();
/**
* Injection token of logger server service
*/
const TOKEN_LOGGER_SERVER_SERVICE = 'TOKEN_LOGGER_SERVER_SERVICE';
class NGXLoggerServerService {
constructor(httpBackend) {
this.httpBackend = httpBackend;
}
/**
* Transforms an error object into a readable string (taking only the stack)
* This is needed because JSON.stringify would return "{}"
* @param err the error object
* @returns The stack of the error
*/
secureErrorObject(err) {
return err === null || err === void 0 ? void 0 : err.stack;
}
/**
* Transforms the additional parameters to avoid any json error when sending the data to the server
* Basically it just replaces unstringifiable object to a string mentioning an error
* @param additional The additional data to be sent
* @returns The additional data secured
*/
secureAdditionalParameters(additional) {
if (additional === null || additional === undefined) {
return null;
}
return additional.map((next, idx) => {
try {
if (next instanceof Error) {
return this.secureErrorObject(next);
}
// We just want to make sure the JSON can be parsed, we do not want to actually change the type
if (typeof next === 'object') {
JSON.stringify(next);
}
return next;
}
catch (e) {
return `The additional[${idx}] value could not be parsed using JSON.stringify().`;
}
});
}
/**
* Transforms the message so that it can be sent to the server
* @param message the message to be sent
* @returns the message secured
*/
secureMessage(message) {
try {
if (message instanceof Error) {
return this.secureErrorObject(message);
}
if (typeof message !== 'string') {
message = JSON.stringify(message, null, 2);
}
}
catch (e) {
message = 'The provided "message" value could not be parsed with JSON.stringify().';
}
return message;
}
logOnServer(url, logContent, options) {
// HttpBackend skips all HttpInterceptors
// They may log errors using this service causing circular calls
const req = new HttpRequest('POST', url, logContent, options || {});
if (!this.httpBackend) {
console.error('NGXLogger : Can\'t log on server because HttpBackend is not provided. You need to import HttpClientModule');
return of(null);
}
return this.httpBackend.handle(req).pipe(filter(e => e instanceof HttpResponse), map((httpResponse) => httpResponse.body));
}
/**
* Customise the data sent to the API
* @param metadata the data provided by NGXLogger
* @returns the data that will be sent to the API in the body
*/
customiseRequestBody(metadata) {
// In our API the body is not customised
return metadata;
}
sendToServer(metadata, config) {
// Copying metadata locally because we don't want to change the object for the caller
const localMetadata = Object.assign({}, metadata);
localMetadata.additional = this.secureAdditionalParameters(localMetadata.additional);
localMetadata.message = this.secureMessage(localMetadata.message);
// Allow users to customise the data sent to the API
const requestBody = this.customiseRequestBody(localMetadata);
const headers = config.customHttpHeaders || new HttpHeaders();
if (!headers.has('Content-Type')) {
headers.set('Content-Type', 'application/json');
}
this.logOnServer(config.serverLoggingUrl, requestBody, {
headers,
params: config.customHttpParams || new HttpParams(),
responseType: config.httpResponseType || 'json',
withCredentials: config.withCredentials || false,
}).pipe(catchError(err => {
// Do not use NGXLogger here because this could cause an infinite loop
console.error('NGXLogger: Failed to log on server', err);
return throwError(err);
})).subscribe();
}
}
/** @nocollapse */ NGXLoggerServerService.ɵfac = function NGXLoggerServerService_Factory(t) { return new (t || NGXLoggerServerService)(ɵɵinject(HttpBackend, 8)); };
/** @nocollapse */ NGXLoggerServerService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerServerService, factory: NGXLoggerServerService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerServerService, [{
type: Injectable
}], function () { return [{ type: HttpBackend, decorators: [{
type: Optional
}] }]; }, null); })();
/**
* Injection token of logger writer service
*/
const TOKEN_LOGGER_WRITER_SERVICE = 'TOKEN_LOGGER_WRITER_SERVICE';
var NgxLoggerLevel;
(function (NgxLoggerLevel) {
NgxLoggerLevel[NgxLoggerLevel["TRACE"] = 0] = "TRACE";
NgxLoggerLevel[NgxLoggerLevel["DEBUG"] = 1] = "DEBUG";
NgxLoggerLevel[NgxLoggerLevel["INFO"] = 2] = "INFO";
NgxLoggerLevel[NgxLoggerLevel["LOG"] = 3] = "LOG";
NgxLoggerLevel[NgxLoggerLevel["WARN"] = 4] = "WARN";
NgxLoggerLevel[NgxLoggerLevel["ERROR"] = 5] = "ERROR";
NgxLoggerLevel[NgxLoggerLevel["FATAL"] = 6] = "FATAL";
NgxLoggerLevel[NgxLoggerLevel["OFF"] = 7] = "OFF";
})(NgxLoggerLevel || (NgxLoggerLevel = {}));
const DEFAULT_COLOR_SCHEME = [
'purple',
'teal',
'gray',
'gray',
'red',
'red',
'red'
];
class NGXLoggerWriterService {
constructor(platformId) {
this.platformId = platformId;
this.isIE = isPlatformBrowser(platformId) && navigator && navigator.userAgent &&
!!(navigator.userAgent.indexOf('MSIE') !== -1 || navigator.userAgent.match(/Trident\//) || navigator.userAgent.match(/Edge\//));
this.logFunc = this.isIE ? this.logIE.bind(this) : this.logModern.bind(this);
}
/** Generate a "meta" string that is displayed before the content sent to the log function */
prepareMetaString(metadata, config) {
const fileDetails = config.disableFileDetails === true ? '' : `[${metadata.fileName}:${metadata.lineNumber}:${metadata.columnNumber}]`;
return `${metadata.timestamp} ${NgxLoggerLevel[metadata.level]} ${fileDetails}`;
}
/** Get the color to use when writing to console */
getColor(metadata, config) {
var _a;
const configColorScheme = (_a = config.colorScheme) !== null && _a !== void 0 ? _a : DEFAULT_COLOR_SCHEME;
// this is needed to avoid a build error
if (metadata.level === NgxLoggerLevel.OFF) {
return undefined;
}
return configColorScheme[metadata.level];
}
/** Log to the console specifically for IE */
logIE(metadata, config, metaString) {
// Coloring doesn't work in IE
// make sure additional isn't null or undefined so that ...additional doesn't error
const additional = metadata.additional || [];
switch (metadata.level) {
case NgxLoggerLevel.WARN:
console.warn(`${metaString} `, metadata.message, ...additional);
break;
case NgxLoggerLevel.ERROR:
case NgxLoggerLevel.FATAL:
console.error(`${metaString} `, metadata.message, ...additional);
break;
case NgxLoggerLevel.INFO:
console.info(`${metaString} `, metadata.message, ...additional);
break;
default:
console.log(`${metaString} `, metadata.message, ...additional);
}
}
/** Log to the console */
logModern(metadata, config, metaString) {
const color = this.getColor(metadata, config);
// make sure additional isn't null or undefined so that ...additional doesn't error
const additional = metadata.additional || [];
switch (metadata.level) {
case NgxLoggerLevel.WARN:
console.warn(`%c${metaString}`, `color:${color}`, metadata.message, ...additional);
break;
case NgxLoggerLevel.ERROR:
case NgxLoggerLevel.FATAL:
console.error(`%c${metaString}`, `color:${color}`, metadata.message, ...additional);
break;
case NgxLoggerLevel.INFO:
console.info(`%c${metaString}`, `color:${color}`, metadata.message, ...additional);
break;
// Disabling console.trace since the stack trace is not helpful. it is showing the stack trace of
// the console.trace statement
// case NgxLoggerLevel.TRACE:
// console.trace(`%c${metaString}`, `color:${color}`, message, ...additional);
// break;
case NgxLoggerLevel.DEBUG:
console.debug(`%c${metaString}`, `color:${color}`, metadata.message, ...additional);
break;
default:
console.log(`%c${metaString}`, `color:${color}`, metadata.message, ...additional);
}
}
/** Write the content sent to the log function to the console */
writeMessage(metadata, config) {
const metaString = this.prepareMetaString(metadata, config);
this.logFunc(metadata, config, metaString);
}
}
/** @nocollapse */ NGXLoggerWriterService.ɵfac = function NGXLoggerWriterService_Factory(t) { return new (t || NGXLoggerWriterService)(ɵɵinject(PLATFORM_ID)); };
/** @nocollapse */ NGXLoggerWriterService.ɵprov = ɵɵdefineInjectable({ token: NGXLoggerWriterService, factory: NGXLoggerWriterService.ɵfac });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLoggerWriterService, [{
type: Injectable
}], function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }]; }, null); })();
class NGXLogger {
constructor(config, configEngineFactory, metadataService, ruleService, mapperService, writerService, serverService) {
this.metadataService = metadataService;
this.ruleService = ruleService;
this.mapperService = mapperService;
this.writerService = writerService;
this.serverService = serverService;
this.configEngine = configEngineFactory.provideConfigEngine(config);
}
/** Get a readonly access to the level configured for the NGXLogger */
get level() {
return this.configEngine.level;
}
/** Get a readonly access to the serverLogLevel configured for the NGXLogger */
get serverLogLevel() {
return this.configEngine.serverLogLevel;
}
trace(message, ...additional) {
this._log(NgxLoggerLevel.TRACE, message, additional);
}
debug(message, ...additional) {
this._log(NgxLoggerLevel.DEBUG, message, additional);
}
info(message, ...additional) {
this._log(NgxLoggerLevel.INFO, message, additional);
}
log(message, ...additional) {
this._log(NgxLoggerLevel.LOG, message, additional);
}
warn(message, ...additional) {
this._log(NgxLoggerLevel.WARN, message, additional);
}
error(message, ...additional) {
this._log(NgxLoggerLevel.ERROR, message, additional);
}
fatal(message, ...additional) {
this._log(NgxLoggerLevel.FATAL, message, additional);
}
/** @deprecated customHttpHeaders is now part of the config, this should be updated via @see updateConfig */
setCustomHttpHeaders(headers) {
const config = this.getConfigSnapshot();
config.customHttpHeaders = headers;
this.updateConfig(config);
}
/** @deprecated customHttpParams is now part of the config, this should be updated via @see updateConfig */
setCustomParams(params) {
const config = this.getConfigSnapshot();
config.customHttpParams = params;
this.updateConfig(config);
}
/** @deprecated withCredentials is now part of the config, this should be updated via @see updateConfig */
setWithCredentialsOptionValue(withCredentials) {
const config = this.getConfigSnapshot();
config.withCredentials = withCredentials;
this.updateConfig(config);
}
/**
* Register a INGXLoggerMonitor that will be trigger when a log is either written or sent to server
*
* There is only one monitor, registering one will overwrite the last one if there was one
* @param monitor
*/
registerMonitor(monitor) {
this._loggerMonitor = monitor;
}
/** Set config of logger
*
* Warning : This overwrites all the config, if you want to update only one property, you should use @see getConfigSnapshot before
*/
updateConfig(config) {
this.configEngine.updateConfig(config);
}
/** Get config of logger */
getConfigSnapshot() {
return this.configEngine.getConfig();
}
_log(level, message, additional = []) {
const config = this.configEngine.getConfig();
const shouldCallWriter = this.ruleService.shouldCallWriter(level, config, message, additional);
const shouldCallServer = this.ruleService.shouldCallServer(level, config, message, additional);
const shouldCallMonitor = this.ruleService.shouldCallMonitor(level, config, message, additional);
if (!shouldCallWriter && !shouldCallServer && !shouldCallMonitor) {
// If nothing is to be called we return
return;
}
const metadata = this.metadataService.getMetadata(level, config, message, additional);
this.mapperService.getLogPosition(config, metadata).pipe(take(1)).subscribe(logPosition => {
if (logPosition) {
metadata.fileName = logPosition.fileName;
metadata.lineNumber = logPosition.lineNumber;
metadata.columnNumber = logPosition.columnNumber;
}
if (shouldCallMonitor && this._loggerMonitor) {
this._loggerMonitor.onLog(metadata, config);
}
if (shouldCallWriter) {
this.writerService.writeMessage(metadata, config);
}
if (shouldCallServer) {
this.serverService.sendToServer(metadata, config);
}
});
}
}
/** @nocollapse */ NGXLogger.ɵfac = function NGXLogger_Factory(t) { return new (t || NGXLogger)(ɵɵinject(TOKEN_LOGGER_CONFIG), ɵɵinject(TOKEN_LOGGER_CONFIG_ENGINE_FACTORY), ɵɵinject(TOKEN_LOGGER_METADATA_SERVICE), ɵɵinject(TOKEN_LOGGER_RULES_SERVICE), ɵɵinject(TOKEN_LOGGER_MAPPER_SERVICE), ɵɵinject(TOKEN_LOGGER_WRITER_SERVICE), ɵɵinject(TOKEN_LOGGER_SERVER_SERVICE)); };
/** @nocollapse */ NGXLogger.ɵprov = ɵɵdefineInjectable({ token: NGXLogger, factory: NGXLogger.ɵfac, providedIn: 'root' });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(NGXLogger, [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_CONFIG]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_CONFIG_ENGINE_FACTORY]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_METADATA_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_RULES_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_MAPPER_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_WRITER_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_SERVER_SERVICE]
}] }]; }, null); })();
// Keeping this to avoid any breaking change for now, this class should be removed later
/**
* CustomNGXLoggerService is designed to allow users to get a new instance of a logger
* @deprecated The logger is now fully customisable so this class is now useless
*/
class CustomNGXLoggerService {
constructor(configEngineFactory, metadataService, ruleService, mapperService, writerService, serverService) {
this.configEngineFactory = configEngineFactory;
this.metadataService = metadataService;
this.ruleService = ruleService;
this.mapperService = mapperService;
this.writerService = writerService;
this.serverService = serverService;
}
/**
* Create an instance of a logger
* @deprecated The logger is now fully customisable so this function is now useless, if you want a specific instance of NGXLogger, either use the new keyword or Angular dependency injection
* @param config
* @param serverService
* @param logMonitor
* @param mapperService
* @returns
*/
create(config, serverService, logMonitor, mapperService) {
const logger = new NGXLogger(config, this.configEngineFactory, this.metadataService, this.ruleService, mapperService || this.mapperService, this.writerService, serverService || this.serverService);
if (logMonitor) {
logger.registerMonitor(logMonitor);
}
return logger;
}
}
/** @nocollapse */ CustomNGXLoggerService.ɵfac = function CustomNGXLoggerService_Factory(t) { return new (t || CustomNGXLoggerService)(ɵɵinject(TOKEN_LOGGER_CONFIG_ENGINE_FACTORY), ɵɵinject(TOKEN_LOGGER_METADATA_SERVICE), ɵɵinject(TOKEN_LOGGER_RULES_SERVICE), ɵɵinject(TOKEN_LOGGER_MAPPER_SERVICE), ɵɵinject(TOKEN_LOGGER_WRITER_SERVICE), ɵɵinject(TOKEN_LOGGER_SERVER_SERVICE)); };
/** @nocollapse */ CustomNGXLoggerService.ɵprov = ɵɵdefineInjectable({ token: CustomNGXLoggerService, factory: CustomNGXLoggerService.ɵfac, providedIn: 'root' });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(CustomNGXLoggerService, [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_CONFIG_ENGINE_FACTORY]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_METADATA_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_RULES_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_MAPPER_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_WRITER_SERVICE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [TOKEN_LOGGER_SERVER_SERVICE]
}] }]; }, null); })();
class LoggerModule {
static forRoot(config, customProvider) {
if (!customProvider) {
customProvider = {};
}
// default config provider
if (!customProvider.configProvider) {
customProvider.configProvider = { provide: TOKEN_LOGGER_CONFIG, useValue: config || {} };
}
else {
// if the user provided its own config, we just make sure the injection token is correct
if (customProvider.configProvider.provide !== TOKEN_LOGGER_CONFIG) {
throw new Error(`Wrong injection token for configProvider, it should be ${TOKEN_LOGGER_CONFIG} and you used ${customProvider.configProvider.provide}`);
}
}
// default configEngine provider
if (!customProvider.configEngineFactoryProvider) {
customProvider.configEngineFactoryProvider = { provide: TOKEN_LOGGER_CONFIG_ENGINE_FACTORY, useClass: NGXLoggerConfigEngineFactory };
}
else {
// if the user provided its own configEngineFactory, we just make sure the injection token is correct
if (customProvider.configEngineFactoryProvider.provide !== TOKEN_LOGGER_CONFIG_ENGINE_FACTORY) {
throw new Error(`Wrong injection token for configEngineFactoryProvider, it should be '${TOKEN_LOGGER_CONFIG_ENGINE_FACTORY}' and you used '${customProvider.configEngineFactoryProvider.provide}'`);
}
}
// default metadata provider
if (!customProvider.metadataProvider) {
customProvider.metadataProvider = { provide: TOKEN_LOGGER_METADATA_SERVICE, useClass: NGXLoggerMetadataService };
}
else {
// if the user provided its own metadataService, we just make sure the injection token is correct
if (customProvider.metadataProvider.provide !== TOKEN_LOGGER_METADATA_SERVICE) {
throw new Error(`Wrong injection token for metadataProvider, it should be '${TOKEN_LOGGER_METADATA_SERVICE}' and you used '${customProvider.metadataProvider.provide}'`);
}
}
// default rule provider
if (!customProvider.ruleProvider) {
customProvider.ruleProvider = { provide: TOKEN_LOGGER_RULES_SERVICE, useClass: NGXLoggerRulesService };
}
else {
// if the user provided its own ruleService, we just make sure the injection token is correct
if (customProvider.ruleProvider.provide !== TOKEN_LOGGER_RULES_SERVICE) {
throw new Error(`Wrong injection token for ruleProvider, it should be '${TOKEN_LOGGER_RULES_SERVICE}' and you used '${customProvider.ruleProvider.provide}'`);
}
}
// default mapper provider
if (!customProvider.mapperProvider) {
customProvider.mapperProvider = { provide: TOKEN_LOGGER_MAPPER_SERVICE, useClass: NGXLoggerMapperService };
}
else {
// if the user provided its own mapperService, we just make sure the injection token is correct
if (customProvider.mapperProvider.provide !== TOKEN_LOGGER_MAPPER_SERVICE) {
throw new Error(`Wrong injection token for mapperProvider, it should be '${TOKEN_LOGGER_MAPPER_SERVICE}' and you used '${customProvider.mapperProvider.provide}'`);
}
}
// default writer provider
if (!customProvider.writerProvider) {
customProvider.writerProvider = { provide: TOKEN_LOGGER_WRITER_SERVICE, useClass: NGXLoggerWriterService };
}
else {
// if the user provided its own writerService, we just make sure the injection token is correct
if (customProvider.writerProvider.provide !== TOKEN_LOGGER_WRITER_SERVICE) {
throw new Error(`Wrong injection token for writerProvider, it should be '${TOKEN_LOGGER_WRITER_SERVICE}' and you used '${customProvider.writerProvider.provide}'`);
}
}
// default server provider
if (!customProvider.serverProvider) {
customProvider.serverProvider = { provide: TOKEN_LOGGER_SERVER_SERVICE, useClass: NGXLoggerServerService };
}
else {
// if the user provided its own serverService, we just make sure the injection token is correct
if (customProvider.serverProvider.provide !== TOKEN_LOGGER_SERVER_SERVICE) {
throw new Error(`Wrong injection token for serverProvider, it should be '${TOKEN_LOGGER_SERVER_SERVICE}' and you used '${customProvider.writerProvider.provide}'`);
}
}
return {
ngModule: LoggerModule,
providers: [
NGXLogger,
customProvider.configProvider,
customProvider.configEngineFactoryProvider,
customProvider.metadataProvider,
customProvider.ruleProvider,
customProvider.mapperProvider,
customProvider.writerProvider,
customProvider.serverProvider,
CustomNGXLoggerService,
]
};
}
static forChild() {
// todo : this forChild is useless for now because nothing is different from forRoot.
// This should be implemented so that user can change the providers in the forChild
return {
ngModule: LoggerModule,
};
}
}
/** @nocollapse */ LoggerModule.ɵfac = function LoggerModule_Factory(t) { return new (t || LoggerModule)(); };
/** @nocollapse */ LoggerModule.ɵmod = ɵɵdefineNgModule({ type: LoggerModule });
/** @nocollapse */ LoggerModule.ɵinj = ɵɵdefineInjector({ imports: [[
CommonModule
]] });
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && ɵɵsetNgModuleScope(LoggerModule, { imports: [CommonModule] }); })();
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && ɵsetClassMetadata(LoggerModule, [{
type: NgModule,
args: [{
imports: [
CommonModule
],
}]
}], null, null); })();
/*
* Public API Surface of ngx-logger
*/
/**
* Generated bundle index. Do not edit.
*/
export { CustomNGXLoggerService, DEFAULT_COLOR_SCHEME, LoggerModule, NGXLogger, NGXLoggerConfigEngine, NGXLoggerConfigEngineFactory, NGXLoggerMapperService, NGXLoggerMetadataService, NGXLoggerMonitor, NGXLoggerRulesService, NGXLoggerServerService, NGXLoggerWriterService, NgxLoggerLevel, TOKEN_LOGGER_CONFIG, TOKEN_LOGGER_CONFIG_ENGINE_FACTORY, TOKEN_LOGGER_MAPPER_SERVICE, TOKEN_LOGGER_METADATA_SERVICE, TOKEN_LOGGER_RULES_SERVICE, TOKEN_LOGGER_SERVER_SERVICE, TOKEN_LOGGER_WRITER_SERVICE };
//# sourceMappingURL=ngx-logger.js.map