From 2f059cccdf950e305d8f8caa59577802a52b462f Mon Sep 17 00:00:00 2001 From: bmtheo <31310846+bmtheo@users.noreply.github.com> Date: Sat, 13 Feb 2021 16:45:17 +0100 Subject: [PATCH 1/2] avoids fail on complex structure when logging fix #177 by removing the prepareMessage (JSON.stringify) call when logging The prepareMessage call is still needed for server logging thus complex structure don't working with server logging --- projects/demo/src/app/app.component.html | 2 +- projects/demo/src/app/app.component.ts | 7 +++++++ projects/demo/src/app/app.module.ts | 3 ++- .../app/log-config/log-config.component.html | 1 + .../app/log-config/log-config.component.scss | 4 ++++ .../app/log-config/log-config.component.ts | 7 +++++++ .../logger-form/logger-form.component.html | 1 + .../app/logger-form/logger-form.component.ts | 16 ++++++++++++--- src/lib/logger.service.spec.ts | 20 +++++++++++++++++++ src/lib/logger.service.ts | 2 +- 10 files changed, 57 insertions(+), 6 deletions(-) diff --git a/projects/demo/src/app/app.component.html b/projects/demo/src/app/app.component.html index 0b81d29..d23b0de 100644 --- a/projects/demo/src/app/app.component.html +++ b/projects/demo/src/app/app.component.html @@ -2,5 +2,5 @@

Please open your console to see the output of the demo

- +
diff --git a/projects/demo/src/app/app.component.ts b/projects/demo/src/app/app.component.ts index 9dbd548..a36f571 100644 --- a/projects/demo/src/app/app.component.ts +++ b/projects/demo/src/app/app.component.ts @@ -19,6 +19,7 @@ export class AppComponent { handleLogLevelChange(newLevel: NgxLoggerLevel) { const updatedConfig = this.logger.getConfigSnapshot(); updatedConfig.level = newLevel; + updatedConfig.serverLogLevel = newLevel; this.logger.updateConfig(updatedConfig); } @@ -57,4 +58,10 @@ export class AppComponent { updatedConfig.disableFileDetails = disableFileDetails; this.logger.updateConfig(updatedConfig); } + + serverLogging(enabled: boolean) { + const updatedConfig = this.logger.getConfigSnapshot(); + updatedConfig.serverLoggingUrl = enabled ? '/dummyURL' : null; + this.logger.updateConfig(updatedConfig); + } } diff --git a/projects/demo/src/app/app.module.ts b/projects/demo/src/app/app.module.ts index 1651f65..7398920 100644 --- a/projects/demo/src/app/app.module.ts +++ b/projects/demo/src/app/app.module.ts @@ -13,7 +13,7 @@ import { MatSlideToggleModule, MatTooltipModule, } from '@angular/material'; -import { LoggerModule, NgxLoggerLevel } from 'ngx-logger'; +import { LoggerModule, NGXLogger, NgxLoggerLevel } from 'ngx-logger'; import { AppComponent } from './app.component'; import { LogConfigComponent } from './log-config/log-config.component'; @@ -29,6 +29,7 @@ import { HttpClientModule } from '@angular/common/http'; ReactiveFormsModule, LoggerModule.forRoot({ level: NgxLoggerLevel.DEBUG, + serverLogLevel: NgxLoggerLevel.DEBUG, }), MatButtonModule, MatCardModule, diff --git a/projects/demo/src/app/log-config/log-config.component.html b/projects/demo/src/app/log-config/log-config.component.html index 5fc43fb..1604f86 100644 --- a/projects/demo/src/app/log-config/log-config.component.html +++ b/projects/demo/src/app/log-config/log-config.component.html @@ -33,6 +33,7 @@

Logger Configuration


Disable file details + Server logging diff --git a/projects/demo/src/app/log-config/log-config.component.scss b/projects/demo/src/app/log-config/log-config.component.scss index bbf91f8..fdd41ac 100644 --- a/projects/demo/src/app/log-config/log-config.component.scss +++ b/projects/demo/src/app/log-config/log-config.component.scss @@ -10,3 +10,7 @@ button { display: flex; justify-content: center; } + +.server-logging { + margin-left: 16px; +} \ No newline at end of file diff --git a/projects/demo/src/app/log-config/log-config.component.ts b/projects/demo/src/app/log-config/log-config.component.ts index 053a0c0..27cd391 100644 --- a/projects/demo/src/app/log-config/log-config.component.ts +++ b/projects/demo/src/app/log-config/log-config.component.ts @@ -20,6 +20,9 @@ export class LogConfigComponent { @Output() disableFileDetails: EventEmitter = new EventEmitter(); + @Output() + serverLogging: EventEmitter = new EventEmitter(); + /** * Get the chip color based on the current logger level configuration */ @@ -56,4 +59,8 @@ export class LogConfigComponent { disableFileDetailsChange(change: MatSlideToggleChange) { this.disableFileDetails.emit(change.checked); } + + serverLoggingChange(change: MatSlideToggleChange) { + this.serverLogging.emit(change.checked); + } } diff --git a/projects/demo/src/app/logger-form/logger-form.component.html b/projects/demo/src/app/logger-form/logger-form.component.html index 2fad3fd..331b6eb 100644 --- a/projects/demo/src/app/logger-form/logger-form.component.html +++ b/projects/demo/src/app/logger-form/logger-form.component.html @@ -15,6 +15,7 @@ + diff --git a/projects/demo/src/app/logger-form/logger-form.component.ts b/projects/demo/src/app/logger-form/logger-form.component.ts index 8f21521..a47d288 100644 --- a/projects/demo/src/app/logger-form/logger-form.component.ts +++ b/projects/demo/src/app/logger-form/logger-form.component.ts @@ -1,6 +1,6 @@ import {Component, OnInit, Output, EventEmitter} from '@angular/core'; -import {Validators, FormBuilder} from '@angular/forms'; -import {NgxLoggerLevel} from 'ngx-logger'; +import {Validators, FormBuilder, FormGroup} from '@angular/forms'; +import {NGXLogger, NgxLoggerLevel} from 'ngx-logger'; import {LogEvent} from '../models/log-event.model'; @@ -36,7 +36,10 @@ export class LoggerFormComponent implements OnInit { {value: NgxLoggerLevel.ERROR, viewValue: 'Error'} ]; - constructor(private fb: FormBuilder) { + constructor( + private fb: FormBuilder, + private logger: NGXLogger + ) { } ngOnInit() { @@ -48,4 +51,11 @@ export class LoggerFormComponent implements OnInit { handleFormSubmission() { this.logToConsole.emit(this.loggerForm.value); } + + logComplex() { + const complexStructure = new FormGroup({ sub: new FormGroup({}) }); + this.logger.error('Test complex', complexStructure); + this.logger.error(complexStructure); + } + } diff --git a/src/lib/logger.service.spec.ts b/src/lib/logger.service.spec.ts index c2a7894..be91b9d 100644 --- a/src/lib/logger.service.spec.ts +++ b/src/lib/logger.service.spec.ts @@ -7,6 +7,7 @@ import {NGXMapperService} from './mapper.service'; import {NGXMapperServiceMock} from '../../testing/src/lib/mapper.service.mock'; import {LoggerConfig} from './logger.config'; import {NgxLoggerLevel} from './types/logger-level.enum'; +import { FormGroup } from '@angular/forms'; describe('NGXLogger', () => { beforeEach(() => { @@ -42,6 +43,25 @@ describe('NGXLogger', () => { } )); + it('should handle complex circular structures', inject( + [NGXLogger], + (logger: NGXLogger) => { + // This structure is not "stringifyable" this make sure anything can be logged + // Before that we used JSON.stringify and it was not working + const complexStructure = new FormGroup({ sub: new FormGroup({}) }); + + spyOn(console, 'error'); + + logger.error('error', complexStructure); + + expect(console.error).toHaveBeenCalledWith(jasmine.anything(), jasmine.anything(), jasmine.anything(), complexStructure); + + logger.error(complexStructure); + + expect(console.error).toHaveBeenCalledWith(jasmine.anything(), jasmine.anything(), complexStructure); + } + )); + describe('trace', () => { it('should call _log with trace', inject( [NGXLogger], diff --git a/src/lib/logger.service.ts b/src/lib/logger.service.ts index f7ba70b..f9c0dad 100644 --- a/src/lib/logger.service.ts +++ b/src/lib/logger.service.ts @@ -167,7 +167,6 @@ export class NGXLogger { const logLevelString = Levels[level]; message = typeof message === 'function' ? message() : message; - message = NGXLoggerUtils.prepareMessage(message); // only use validated parameters for HTTP requests const validatedAdditionalParameters = NGXLoggerUtils.prepareAdditionalParameters(additional); @@ -192,6 +191,7 @@ export class NGXLogger { } if (isLog2Server) { + message = NGXLoggerUtils.prepareMessage(message); // make sure the stack gets sent to the server message = message instanceof Error ? message.stack : message; logObject.message = message; From 989a9107d0c3013f4ebd9994be8c6050414afe88 Mon Sep 17 00:00:00 2001 From: bmtheo <31310846+bmtheo@users.noreply.github.com> Date: Sat, 13 Feb 2021 18:05:00 +0100 Subject: [PATCH 2/2] fix behavior when manipulating message respect NGXLogInterface with string type for message do the same processing it used to have for server logging without altering the data for console logging --- src/lib/logger.service.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib/logger.service.ts b/src/lib/logger.service.ts index f9c0dad..1d444da 100644 --- a/src/lib/logger.service.ts +++ b/src/lib/logger.service.ts @@ -178,7 +178,10 @@ export class NGXLogger { // const callerDetails = NGXLoggerUtils.getCallerDetails(); this.mapperService.getCallerDetails(config.enableSourceMaps).subscribe((callerDetails: LogPosition) => { const logObject: NGXLogInterface = { - message: message, + // prepareMessage is needed to match NGXLogInterface + // Even though I think message should be of type any (same as console.xxx signature) + // I'm not doing this right now as this would be a breaking change + message: NGXLoggerUtils.prepareMessage(message), additional: validatedAdditionalParameters, level: level, timestamp: timestamp, @@ -191,10 +194,9 @@ export class NGXLogger { } if (isLog2Server) { - message = NGXLoggerUtils.prepareMessage(message); - // make sure the stack gets sent to the server - message = message instanceof Error ? message.stack : message; - logObject.message = message; + // make sure the stack gets sent to the server (without altering the message for console logging) + logObject.message = message instanceof Error ? message.stack : message; + logObject.message = NGXLoggerUtils.prepareMessage(logObject.message); const headers = this._customHttpHeaders || new HttpHeaders(); headers.set('Content-Type', 'application/json');