Skip to content

Commit

Permalink
feat(config): add logLevel option to suppress ionic warnings and erro…
Browse files Browse the repository at this point in the history
…rs (#30015)

resolves #29814

---------

- Developers can assign a value to `logLevel` in the Ionic config to control the log level that Ionic Framework will produce logs for.
  - `OFF` will completely disable all warnings and errors from Ionic
  - `WARN` will log warnings and errors
  - `ERROR` will log only errors
- Default behavior is that developers receive both Ionic warnings and errors
- Configuration only applies to usages of `printIonWarning` and `printIonError`

---------

Co-authored-by: Brandy Smith <[email protected]>
  • Loading branch information
sean-perkins and brandyscarney authored Jan 20, 2025
1 parent 3f8346e commit efd3e0f
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 4 deletions.
10 changes: 10 additions & 0 deletions core/src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { SpinnerTypes } from '../components/spinner/spinner-configs';
import type { TabButtonLayout } from '../components/tab-bar/tab-bar-interface';
import type { AnimationBuilder, Mode } from '../interface';

import type { LogLevel } from './logging';
import type { PlatformConfig } from './platform';

export interface IonicConfig {
Expand Down Expand Up @@ -220,6 +221,15 @@ export interface IonicConfig {
*/
experimentalCloseWatcher?: boolean;

/**
* Configures the logging level for Ionic Framework:
*
* - `'OFF'`: No errors or warnings are logged.
* - `'ERROR'`: Logs only errors.
* - `'WARN'`: Logs errors and warnings.
*/
logLevel?: LogLevel;

// PRIVATE configs
keyboardHeight?: number;
inputShims?: boolean;
Expand Down
22 changes: 18 additions & 4 deletions core/src/utils/logging/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
import { config } from '@global/config';

export const enum LogLevel {
OFF = 'OFF',
ERROR = 'ERROR',
WARN = 'WARN',
}

/**
* Logs a warning to the console with an Ionic prefix
* to indicate the library that is warning the developer.
*
* @param message - The string message to be logged to the console.
*/
export const printIonWarning = (message: string, ...params: any[]) => {
return console.warn(`[Ionic Warning]: ${message}`, ...params);
const logLevel = config.get('logLevel', LogLevel.WARN);
if ([LogLevel.WARN].includes(logLevel)) {
return console.warn(`[Ionic Warning]: ${message}`, ...params);
}
};

/*
/**
* Logs an error to the console with an Ionic prefix
* to indicate the library that is warning the developer.
*
* @param message - The string message to be logged to the console.
* @param params - Additional arguments to supply to the console.error.
*/
export const printIonError = (message: string, ...params: any) => {
return console.error(`[Ionic Error]: ${message}`, ...params);
export const printIonError = (message: string, ...params: any[]) => {
const logLevel = config.get('logLevel', LogLevel.ERROR);
if ([LogLevel.ERROR, LogLevel.WARN].includes(logLevel)) {
return console.error(`[Ionic Error]: ${message}`, ...params);
}
};

/**
Expand Down
114 changes: 114 additions & 0 deletions core/src/utils/logging/test/logging.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { config } from '@global/config';
import { LogLevel } from '../index';

import { printIonError, printIonWarning } from '../index';

describe('Logging', () => {
describe('#printIonWarning', () => {
let consoleWarnSpy: jest.SpyInstance;

beforeEach(() => {
consoleWarnSpy = jest.spyOn(console, 'warn');
// Suppress console.warn output from polluting the test output
consoleWarnSpy.mockImplementation(() => {});
});

afterEach(() => {
consoleWarnSpy.mockRestore();
});

describe('when the logLevel configuration is not set', () => {
it('logs a warning to the console', () => {
config.set('logLevel', undefined);

printIonWarning('This is a warning message');

expect(consoleWarnSpy).toHaveBeenCalledWith('[Ionic Warning]: This is a warning message');
});
});

describe("when the logLevel configuration is set to 'WARN'", () => {
it('logs a warning to the console', () => {
config.set('logLevel', LogLevel.WARN);

printIonWarning('This is a warning message');

expect(consoleWarnSpy).toHaveBeenCalledWith('[Ionic Warning]: This is a warning message');
});
});

describe("when the logLevel configuration is set to 'ERROR'", () => {
it('does not log a warning to the console', () => {
config.set('logLevel', LogLevel.ERROR);

printIonWarning('This is a warning message');

expect(consoleWarnSpy).not.toHaveBeenCalled();
});
});

describe("when the logLevel configuration is set to 'OFF'", () => {
it('does not log a warning to the console', () => {
config.set('logLevel', LogLevel.OFF);

printIonWarning('This is a warning message');

expect(consoleWarnSpy).not.toHaveBeenCalled();
});
});
});

describe('#printIonError', () => {
let consoleErrorSpy: jest.SpyInstance;

beforeEach(() => {
consoleErrorSpy = jest.spyOn(console, 'error');
// Suppress console.error output from polluting the test output
consoleErrorSpy.mockImplementation(() => {});
});

afterEach(() => {
consoleErrorSpy.mockRestore();
});

describe('when the logLevel configuration is not set', () => {
it('logs an error to the console', () => {
config.set('logLevel', undefined);

printIonError('This is an error message');

expect(consoleErrorSpy).toHaveBeenCalledWith('[Ionic Error]: This is an error message');
});
});

describe("when the logLevel configuration is set to 'ERROR'", () => {
it('logs an error to the console', () => {
config.set('logLevel', LogLevel.ERROR);

printIonError('This is an error message');

expect(consoleErrorSpy).toHaveBeenCalledWith('[Ionic Error]: This is an error message');
});
});

describe("when the logLevel configuration is set to 'WARN'", () => {
it('logs an error to the console', () => {
config.set('logLevel', LogLevel.WARN);

printIonError('This is an error message');

expect(consoleErrorSpy).toHaveBeenCalledWith('[Ionic Error]: This is an error message');
});
});

describe("when the logLevel configuration is set to 'OFF'", () => {
it('does not log an error to the console', () => {
config.set('logLevel', LogLevel.OFF);

printIonError('This is an error message');

expect(consoleErrorSpy).not.toHaveBeenCalled();
});
});
});
});

0 comments on commit efd3e0f

Please sign in to comment.