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 700f3a9..d652d0c 100644
--- a/src/lib/logger.service.spec.ts
+++ b/src/lib/logger.service.spec.ts
@@ -10,6 +10,7 @@ import { NgxLoggerLevel } from './types/logger-level.enum';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { LogPosition } from 'dist/ngx-logger/lib/types/log-position';
import { of } from 'rxjs';
+import { FormGroup } from '@angular/forms';
describe('NGXLogger', () => {
beforeEach(() => {
@@ -45,6 +46,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 35eaeb8..7ee6ed8 100644
--- a/src/lib/logger.service.ts
+++ b/src/lib/logger.service.ts
@@ -176,7 +176,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);
@@ -187,7 +186,10 @@ export class NGXLogger {
this.mapperService.getCallerDetails(config.enableSourceMaps, config.proxiedSteps).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,
@@ -200,9 +202,9 @@ export class NGXLogger {
}
if (isLog2Server) {
- // 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');