Skip to content

Commit

Permalink
Feature/line numbers (#56)
Browse files Browse the repository at this point in the history
* Support logging file numbers

* update version
  • Loading branch information
dbfannin authored Apr 12, 2018
1 parent 36196c1 commit ad67193
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 70 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-logger",
"version": "2.1.1",
"version": "2.2.0",
"scripts": {
"build": "gulp build",
"build:watch": "gulp",
Expand Down
8 changes: 8 additions & 0 deletions src/http-meta-data.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {NgxLoggerLevel} from './types/logger-lever.enum';

export class HttpMetaDataInterface {
level: NgxLoggerLevel;
timestamp: string;
fileName: string;
lineNumber: string;
}
9 changes: 6 additions & 3 deletions src/http.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {HttpMetaDataInterface} from './http-meta-data.interface';


@Injectable()
Expand All @@ -9,12 +10,14 @@ export class NGXLoggerHttpService {

}

logOnServer(url: string, message: string, additional: any[], timestamp: string, logLevel: string): Observable<any> {
logOnServer(url: string, message: string, additional: any[], metaData: HttpMetaDataInterface): Observable<any> {
const body = {
level: logLevel,
message: message,
additional: additional,
timestamp: timestamp
level: metaData.level,
timestamp: metaData.timestamp,
fileName: metaData.fileName,
lineNumber: metaData.lineNumber
};

const options = {
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import {NGXLoggerHttpService} from './http.service';
export * from './http.service';
export * from './http.service.mock';

export * from './utils/logger.utils';
export * from './types/logger-lever.enum';
export * from './http-meta-data.interface';

@NgModule({
imports: [
Expand Down
90 changes: 25 additions & 65 deletions src/logger.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {NGXLoggerHttpService} from './http.service';
import {NgxLoggerLevel} from './types/logger-lever.enum';
import {LoggerConfig} from './logger.config';
import {NGXLoggerConfigEngine} from './config.engine';
import {HttpMetaDataInterface} from './http-meta-data.interface';
import {NGXLoggerUtils} from './utils/logger.utils';

export const Levels = [
'TRACE',
Expand Down Expand Up @@ -60,79 +62,54 @@ export class NGXLogger {
this.configService.updateConfig(config);
}

private _logIE(level: NgxLoggerLevel, message: string, additional: any[], timestamp: string): void {
private _logIE(level: NgxLoggerLevel, metaString: string, message: string, additional: any[]): void {

// make sure additional isn't null or undefined so that ...additional doesn't error
additional = additional || [];

switch (level) {
case NgxLoggerLevel.WARN:
console.warn(`${timestamp} [${Levels[level]}] `, message, ...additional);
console.warn(`${metaString} `, message, ...additional);
break;
case NgxLoggerLevel.ERROR:
console.error(`${timestamp} [${Levels[level]}] `, message, ...additional);
console.error(`${metaString} `, message, ...additional);
break;
case NgxLoggerLevel.INFO:
console.info(`${timestamp} [${Levels[level]}] `, message, ...additional);
console.info(`${metaString} `, message, ...additional);
break;
default:
console.log(`${timestamp} [${Levels[level]}] `, message, ...additional);
console.log(`${metaString} `, message, ...additional);
}
}

private _prepareMessage(message) {
try {
if (message instanceof Error) {
message = message.stack;
} else if (typeof message !== 'string') {
message = JSON.stringify(message, null, 2);
}
} catch (e) {
// additional = [message, ...additional];
message = 'The provided "message" value could not be parsed with JSON.stringify().';
}

return message;
}

private _prepareAdditionalParameters(additional: any[]) {
if (additional === null || additional === undefined) {
return null;
}

return additional.map((next, idx) => {
try {
// 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().`
}
});
}

private _log(level: NgxLoggerLevel, message, additional: any[] = [], logOnServer: boolean = true): void {
if (!message) {
return;
}

const logLevelString = Levels[level];

message = this._prepareMessage(message);
message = NGXLoggerUtils.prepareMessage(message);

// only use validated parameters for HTTP requests
const validatedAdditionalParameters = this._prepareAdditionalParameters(additional);
const validatedAdditionalParameters = NGXLoggerUtils.prepareAdditionalParameters(additional);

const timestamp = new Date().toISOString();
const config = this.configService.getConfig();

const callerDetails = NGXLoggerUtils.getCallerDetails();

if (logOnServer && config.serverLoggingUrl && level >= config.serverLogLevel) {

const metaData: HttpMetaDataInterface = {
level: level,
timestamp: timestamp,
fileName: callerDetails.fileName,
lineNumber: callerDetails.lineNumber,
};

// Allow logging on server even if client log level is off
this.httpService.logOnServer(config.serverLoggingUrl, message, validatedAdditionalParameters, timestamp, logLevelString).subscribe((res: any) => {
this.httpService.logOnServer(config.serverLoggingUrl, message, validatedAdditionalParameters, metaData).subscribe((res: any) => {
// I don't think we should do anything on success
},
(error: HttpErrorResponse) => {
Expand All @@ -147,32 +124,15 @@ export class NGXLogger {
return;
}

const metaString = NGXLoggerUtils.prepareMetaString(timestamp, logLevelString, callerDetails.fileName, callerDetails.lineNumber);

// Coloring doesn't work in IE
if (this._isIE) {
return this._logIE(level, message, additional, timestamp);
return this._logIE(level, metaString, message, additional);
}

const color = this._getColor(level);

console.log(`%c${timestamp} [${logLevelString}]`, `color:${color}`, message, ...(additional || []));
}
const color = NGXLoggerUtils.getColor(level);

private _getColor(level: NgxLoggerLevel): 'blue' | 'teal' | 'gray' | 'red' | undefined {
switch (level) {
case NgxLoggerLevel.TRACE:
return 'blue';
case NgxLoggerLevel.DEBUG:
return 'teal';
case NgxLoggerLevel.INFO:
case NgxLoggerLevel.LOG:
return 'gray';
case NgxLoggerLevel.WARN:
case NgxLoggerLevel.ERROR:
return 'red';
case NgxLoggerLevel.OFF:
default:
return;
}
console.log(`%c${metaString}`, `color:${color}`, message, ...(additional || []));
}

}
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-logger",
"version": "2.1.1",
"version": "2.2.0",
"repository": {
"type": "git",
"url": "https://github.com/dbfannin/ngx-logger"
Expand Down
85 changes: 85 additions & 0 deletions src/utils/logger.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {NgxLoggerLevel} from '../types/logger-lever.enum';

export class NGXLoggerUtils {

static prepareMetaString(timestamp: string, logLevel: string, fileName: string, lineNumber: string) {
return `${timestamp} ${logLevel} [${fileName}:${lineNumber}]`;
}

static getColor(level: NgxLoggerLevel): 'blue' | 'teal' | 'gray' | 'red' | undefined {
switch (level) {
case NgxLoggerLevel.TRACE:
return 'blue';
case NgxLoggerLevel.DEBUG:
return 'teal';
case NgxLoggerLevel.INFO:
case NgxLoggerLevel.LOG:
return 'gray';
case NgxLoggerLevel.WARN:
case NgxLoggerLevel.ERROR:
return 'red';
case NgxLoggerLevel.OFF:
default:
return;
}
}



/**
* This allows us to see who called the logger
* @return {string}
* @private
*/
static getCallerDetails(): {lineNumber: string, fileName: string} {
const err = (new Error(''));

// this should produce the line which NGX Logger was called
const callerLine = err.stack.split('\n')[4].split('/');

// returns the file:lineNumber
const fileLineNumber = callerLine[callerLine.length - 1].replace(/[)]/g, '').split(':');

return {
fileName: fileLineNumber[0],
lineNumber: fileLineNumber[1]
}
}

static prepareMessage(message) {
try {
if (message instanceof Error) {
message = message.stack;
} else if (typeof message !== 'string') {
message = JSON.stringify(message, null, 2);
}
} catch (e) {
// additional = [message, ...additional];
message = 'The provided "message" value could not be parsed with JSON.stringify().';
}

return message;
}

static prepareAdditionalParameters(additional: any[]) {
if (additional === null || additional === undefined) {
return null;
}

return additional.map((next, idx) => {
try {
// 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().`
}
});
}


}

0 comments on commit ad67193

Please sign in to comment.