Skip to content

Commit 9aeb98c

Browse files
committed
feat: Migrate Logger to Typescript
1 parent 3cb1319 commit 9aeb98c

File tree

5 files changed

+199
-3
lines changed

5 files changed

+199
-3
lines changed

src/logger.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { LogLevelType, SDKInitConfig, SDKLoggerApi } from './sdkRuntimeModels';
2+
3+
export type ILoggerConfig = Pick<SDKInitConfig, 'logLevel' | 'logger'>;
4+
export type IConsoleLogger = Partial<Pick<SDKLoggerApi, 'error' | 'warning' | 'verbose'>>;
5+
6+
export default class Logger {
7+
private logLevel: LogLevelType;
8+
private logger: IConsoleLogger;
9+
10+
constructor(config: ILoggerConfig) {
11+
this.logLevel = config.logLevel || LogLevelType.Warning;
12+
this.logger = config.logger || new ConsoleLogger();
13+
}
14+
15+
public verbose(msg: string): void {
16+
if (this.logLevel !== LogLevelType.None) {
17+
if (this.logger.verbose && this.logLevel === LogLevelType.Verbose) {
18+
this.logger.verbose(msg);
19+
}
20+
}
21+
}
22+
23+
public warning(msg: string): void {
24+
if (this.logLevel !== LogLevelType.None) {
25+
if (
26+
this.logger.warning &&
27+
(this.logLevel === LogLevelType.Verbose || this.logLevel === LogLevelType.Warning)
28+
) {
29+
this.logger.warning(msg);
30+
}
31+
}
32+
}
33+
34+
public error(msg: string): void {
35+
if (this.logLevel !== LogLevelType.None) {
36+
if (this.logger.error) {
37+
this.logger.error(msg);
38+
}
39+
}
40+
}
41+
42+
public setLogLevel(newLogLevel: LogLevelType): void {
43+
this.logLevel = newLogLevel;
44+
}
45+
}
46+
47+
export class ConsoleLogger implements IConsoleLogger {
48+
public verbose(msg: string): void {
49+
if (console && console.info) {
50+
console.info(msg);
51+
}
52+
}
53+
54+
public error(msg: string): void {
55+
if (console && console.error) {
56+
console.error(msg);
57+
}
58+
}
59+
60+
public warning(msg: string): void {
61+
if (console && console.warn) {
62+
console.warn(msg);
63+
}
64+
}
65+
}

src/sdkRuntimeModels.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { SDKECommerceAPI } from './ecommerce.interfaces';
4040
import { IErrorLogMessage, IMParticleWebSDKInstance, IntegrationDelays } from './mp-instance';
4141
import Constants from './constants';
4242
import RoktManager, { IRoktLauncherOptions } from './roktManager';
43+
import { IConsoleLogger } from './logger';
4344

4445
// TODO: Resolve this with version in @mparticle/web-sdk
4546
export type SDKEventCustomFlags = Dictionary<any>;
@@ -259,7 +260,13 @@ export interface IMParticleInstanceManager extends MParticleWebSDK {
259260
export type BooleanStringLowerCase = 'false' | 'true';
260261
export type BooleanStringTitleCase = 'False' | 'True';
261262

262-
export type LogLevelType = 'none' | 'verbose' | 'warning' | 'error';
263+
export type LogLevelType = (typeof LogLevelType)[keyof typeof LogLevelType];
264+
export const LogLevelType = {
265+
None: 'none',
266+
Verbose: 'verbose',
267+
Warning: 'warning',
268+
Error: 'error',
269+
} as const;
263270

264271
// TODO: This should eventually be moved into wherever init logic lives
265272
// TODO: Replace/Merge this with MPConfiguration in @types/mparticle__web-sdk
@@ -309,6 +316,7 @@ export interface SDKInitConfig
309316
launcherOptions?: IRoktLauncherOptions;
310317

311318
rq?: Function[] | any[];
319+
logger?: IConsoleLogger;
312320
}
313321

314322
export interface DataPlanConfig {

test/jest/logger.spec.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import Logger, { ConsoleLogger } from '../../src/logger';
2+
3+
describe('Logger', () => {
4+
let mockConsole: any;
5+
let logger: Logger;
6+
7+
beforeEach(() => {
8+
mockConsole = {
9+
info: jest.fn(),
10+
warn: jest.fn(),
11+
error: jest.fn()
12+
};
13+
(global as any).console = mockConsole;
14+
});
15+
16+
afterEach(() => {
17+
jest.clearAllMocks();
18+
});
19+
20+
it('should call verbose, warning, and error methods on ConsoleLogger at correct log levels', () => {
21+
logger = new Logger({ logLevel: 'verbose' as any });
22+
23+
logger.verbose('message1');
24+
logger.warning('message2');
25+
logger.error('message3');
26+
27+
expect(mockConsole.info).toHaveBeenCalledWith('message1');
28+
expect(mockConsole.warn).toHaveBeenCalledWith('message2');
29+
expect(mockConsole.error).toHaveBeenCalledWith('message3');
30+
});
31+
32+
it('should only call warning and error at warning log level', () => {
33+
logger = new Logger({ logLevel: 'warning' as any });
34+
35+
logger.verbose('message1');
36+
logger.warning('message2');
37+
logger.error('message3');
38+
39+
expect(mockConsole.info).not.toHaveBeenCalled();
40+
expect(mockConsole.warn).toHaveBeenCalledWith('message2');
41+
expect(mockConsole.error).toHaveBeenCalledWith('message3');
42+
});
43+
44+
it('should only call error at none log level', () => {
45+
logger = new Logger({ logLevel: 'none' as any });
46+
47+
logger.verbose('message1');
48+
logger.warning('message2');
49+
logger.error('message3');
50+
51+
expect(mockConsole.info).not.toHaveBeenCalled();
52+
expect(mockConsole.warn).not.toHaveBeenCalled();
53+
expect(mockConsole.error).not.toHaveBeenCalled();
54+
});
55+
56+
it('should allow providing a custom logger', () => {
57+
const customLogger = {
58+
verbose: jest.fn(),
59+
warning: jest.fn(),
60+
error: jest.fn()
61+
};
62+
63+
logger = new Logger({ logLevel: 'verbose' as any, logger: customLogger });
64+
65+
logger.verbose('test-verbose');
66+
logger.warning('test-warning');
67+
logger.error('test-error');
68+
69+
expect(customLogger.verbose).toHaveBeenCalledWith('test-verbose');
70+
expect(customLogger.warning).toHaveBeenCalledWith('test-warning');
71+
expect(customLogger.error).toHaveBeenCalledWith('test-error');
72+
});
73+
74+
it('should change log level with setLogLevel', () => {
75+
logger = new Logger({ logLevel: 'none' as any });
76+
77+
logger.verbose('one');
78+
logger.warning('two');
79+
logger.error('three');
80+
expect(mockConsole.info).not.toHaveBeenCalled();
81+
expect(mockConsole.warn).not.toHaveBeenCalled();
82+
expect(mockConsole.error).not.toHaveBeenCalled();
83+
84+
logger.setLogLevel('verbose' as any);
85+
86+
logger.verbose('a');
87+
logger.warning('b');
88+
logger.error('c');
89+
expect(mockConsole.info).toHaveBeenCalledWith('a');
90+
expect(mockConsole.warn).toHaveBeenCalledWith('b');
91+
expect(mockConsole.error).toHaveBeenCalledWith('c');
92+
});
93+
});
94+
95+
describe('ConsoleLogger', () => {
96+
let mockConsole: any;
97+
let consoleLogger: ConsoleLogger;
98+
99+
beforeEach(() => {
100+
mockConsole = {
101+
info: jest.fn(),
102+
warn: jest.fn(),
103+
error: jest.fn()
104+
};
105+
(global as any).console = mockConsole;
106+
consoleLogger = new ConsoleLogger();
107+
});
108+
109+
it('should use console.info for verbose', () => {
110+
consoleLogger.verbose('hi');
111+
expect(mockConsole.info).toHaveBeenCalledWith('hi');
112+
});
113+
114+
it('should use console.warn for warning', () => {
115+
consoleLogger.warning('warn msg');
116+
expect(mockConsole.warn).toHaveBeenCalledWith('warn msg');
117+
});
118+
119+
it('should use console.error for error', () => {
120+
consoleLogger.error('err');
121+
expect(mockConsole.error).toHaveBeenCalledWith('err');
122+
});
123+
});

test/src/tests-audience-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { IMParticleInstanceManager, SDKLoggerApi } from '../../src/sdkRuntimeMod
77
import AudienceManager, {
88
IAudienceMemberships, IAudienceMembershipsServerResponse
99
} from '../../src/audienceManager';
10-
import Logger from '../../src/logger.js';
10+
import Logger from '../../src/logger';
1111
import Utils from './config/utils';
1212
const { fetchMockSuccess } = Utils;
1313

test/src/tests-batchUploader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Utils from './config/utils';
1010
import { BatchUploader } from '../../src/batchUploader';
1111
import { expect } from 'chai';
1212
import _BatchValidator from '../../src/mockBatchCreator';
13-
import Logger from '../../src/logger.js';
13+
import Logger from '../../src/logger';
1414
import { event0, event1, event2, event3 } from '../fixtures/events';
1515
import fetchMock from 'fetch-mock/esm/client';
1616
const {

0 commit comments

Comments
 (0)