Skip to content

Commit f36fa20

Browse files
gtamanahaalexs-mparticle
authored andcommitted
refactor(logging): Move sendLogToServer method from APIClient to ReportingLogger for better encapsulation and update related tests
1 parent 217c652 commit f36fa20

File tree

4 files changed

+66
-171
lines changed

4 files changed

+66
-171
lines changed

src/apiClient.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ export interface IAPIClient {
2828
forwarder: MPForwarder,
2929
event: IUploadObject
3030
) => void;
31-
sendLogToServer: (log: LogRequest) => void;
3231
}
3332

3433
export interface IForwardingStatsData {
@@ -233,25 +232,4 @@ export default function APIClient(
233232
}
234233
}
235234
};
236-
237-
this.sendLogToServer = function(logRequest: LogRequest) {
238-
const baseUrl = mpInstance._Helpers.createServiceUrl(
239-
mpInstance._Store.SDKConfig.v2SecureServiceUrl,
240-
mpInstance._Store.devToken
241-
);
242-
243-
const uploadUrl = `${baseUrl}/v1/log`;
244-
const uploader = window.fetch
245-
? new FetchUploader(uploadUrl)
246-
: new XHRUploader(uploadUrl);
247-
248-
uploader.upload({
249-
method: 'POST',
250-
headers: {
251-
Accept: 'text/plain;charset=UTF-8',
252-
'Content-Type': 'text/plain;charset=UTF-8',
253-
},
254-
body: JSON.stringify(logRequest),
255-
});
256-
};
257235
}

src/logging/reportingLogger.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { IAPIClient } from "../apiClient";
2+
import { IMParticleWebSDKInstance } from "../mp-instance";
23
import { ErrorCodes } from "./errorCodes";
34
import { LogRequest, LogRequestSeverity } from "./logRequest";
5+
import { FetchUploader, XHRUploader } from "../uploaders";
46

57
export interface IReportingLogger {
68
error(msg: string, code?: ErrorCodes, stackTrace?: string): void;
@@ -9,18 +11,18 @@ export interface IReportingLogger {
911

1012
export class ReportingLogger implements IReportingLogger {
1113
private readonly isEnabled: boolean;
12-
private readonly apiClient: IAPIClient;
1314
private readonly reporter: string = 'mp-wsdk';
1415
private readonly integration: string = 'mp-wsdk';
1516
private readonly rateLimiter: IRateLimiter;
17+
private readonly mpInstance: IMParticleWebSDKInstance;
1618

1719
constructor(
18-
apiClient: IAPIClient,
20+
mpInstance: IMParticleWebSDKInstance,
1921
private readonly sdkVersion: string,
2022
rateLimiter?: IRateLimiter,
2123
) {
24+
this.mpInstance = mpInstance;
2225
this.isEnabled = this.isReportingEnabled();
23-
this.apiClient = apiClient;
2426
this.rateLimiter = rateLimiter ?? new RateLimiter();
2527
}
2628

@@ -55,7 +57,7 @@ export class ReportingLogger implements IReportingLogger {
5557
integration: this.integration,
5658
};
5759

58-
this.apiClient.sendLogToServer(logRequest);
60+
this.sendLogToServer(logRequest);
5961
}
6062

6163
private isReportingEnabled(): boolean {
@@ -102,6 +104,27 @@ export class ReportingLogger implements IReportingLogger {
102104
private getUserAgent(): string {
103105
return window.navigator.userAgent;
104106
}
107+
108+
private sendLogToServer(logRequest: LogRequest) {
109+
const baseUrl = this.mpInstance._Helpers.createServiceUrl(
110+
this.mpInstance._Store.SDKConfig.v2SecureServiceUrl,
111+
this.mpInstance._Store.devToken
112+
);
113+
114+
const uploadUrl = `${baseUrl}/v1/log`;
115+
const uploader = window.fetch
116+
? new FetchUploader(uploadUrl)
117+
: new XHRUploader(uploadUrl);
118+
119+
uploader.upload({
120+
method: 'POST',
121+
headers: {
122+
Accept: 'text/plain;charset=UTF-8',
123+
'Content-Type': 'text/plain;charset=UTF-8',
124+
},
125+
body: JSON.stringify(logRequest),
126+
});
127+
};
105128
}
106129

107130
export interface IRateLimiter {

test/jest/apiClient.spec.ts

Lines changed: 0 additions & 129 deletions
This file was deleted.

test/jest/reportingLogger.spec.ts

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,26 @@ import { LogRequestSeverity } from '../../src/logging/logRequest';
33
import { ErrorCodes } from '../../src/logging/errorCodes';
44

55
describe('ReportingLogger', () => {
6-
let apiClient: any;
6+
let mpInstance: any;
77
let logger: ReportingLogger;
88
const sdkVersion = '1.2.3';
9+
let mockFetch: jest.Mock;
910

1011
beforeEach(() => {
11-
apiClient = { sendLogToServer: jest.fn() };
12+
mockFetch = jest.fn().mockResolvedValue({ ok: true });
13+
global.fetch = mockFetch;
14+
15+
mpInstance = {
16+
_Helpers: {
17+
createServiceUrl: jest.fn().mockReturnValue('https://test-url.com')
18+
},
19+
_Store: {
20+
SDKConfig: {
21+
v2SecureServiceUrl: 'https://secure-service.com'
22+
},
23+
devToken: 'test-token'
24+
}
25+
};
1226

1327
delete (globalThis as any).location;
1428
(globalThis as any).location = {
@@ -19,9 +33,10 @@ describe('ReportingLogger', () => {
1933
Object.assign(globalThis, {
2034
navigator: { userAgent: 'ua' },
2135
mParticle: { config: { isWebSdkLoggingEnabled: true } },
22-
ROKT_DOMAIN: 'set'
36+
ROKT_DOMAIN: 'set',
37+
fetch: mockFetch
2338
});
24-
logger = new ReportingLogger(apiClient, sdkVersion);
39+
logger = new ReportingLogger(mpInstance, sdkVersion);
2540
});
2641

2742
afterEach(() => {
@@ -32,41 +47,49 @@ describe('ReportingLogger', () => {
3247

3348
it('sends error logs with correct params', () => {
3449
logger.error('msg', ErrorCodes.UNHANDLED_EXCEPTION, 'stack');
35-
expect(apiClient.sendLogToServer).toHaveBeenCalledWith(expect.objectContaining({
50+
expect(mockFetch).toHaveBeenCalled();
51+
const fetchCall = mockFetch.mock.calls[0];
52+
expect(fetchCall[0]).toContain('/v1/log');
53+
const body = JSON.parse(fetchCall[1].body);
54+
expect(body).toMatchObject({
3655
severity: LogRequestSeverity.Error,
3756
code: ErrorCodes.UNHANDLED_EXCEPTION,
3857
stackTrace: 'stack'
39-
}));
58+
});
4059
});
4160

4261
it('sends warning logs with correct params', () => {
4362
logger.warning('warn');
44-
expect(apiClient.sendLogToServer).toHaveBeenCalledWith(expect.objectContaining({
63+
expect(mockFetch).toHaveBeenCalled();
64+
const fetchCall = mockFetch.mock.calls[0];
65+
expect(fetchCall[0]).toContain('/v1/log');
66+
const body = JSON.parse(fetchCall[1].body);
67+
expect(body).toMatchObject({
4568
severity: LogRequestSeverity.Warning
46-
}));
69+
});
4770
});
4871

4972
it('does not log if ROKT_DOMAIN missing', () => {
5073
delete (globalThis as any).ROKT_DOMAIN;
51-
logger = new ReportingLogger(apiClient, sdkVersion);
74+
logger = new ReportingLogger(mpInstance, sdkVersion);
5275
logger.error('x');
53-
expect(apiClient.sendLogToServer).not.toHaveBeenCalled();
76+
expect(mockFetch).not.toHaveBeenCalled();
5477
});
5578

5679
it('does not log if feature flag and debug mode off', () => {
5780
window.mParticle.config.isWebSdkLoggingEnabled = false;
5881
window.location.search = '';
59-
logger = new ReportingLogger(apiClient, sdkVersion);
82+
logger = new ReportingLogger(mpInstance, sdkVersion);
6083
logger.error('x');
61-
expect(apiClient.sendLogToServer).not.toHaveBeenCalled();
84+
expect(mockFetch).not.toHaveBeenCalled();
6285
});
6386

6487
it('logs if debug mode on even if feature flag off', () => {
6588
window.mParticle.config.isWebSdkLoggingEnabled = false;
6689
window.location.search = '?mp_enable_logging=true';
67-
logger = new ReportingLogger(apiClient, sdkVersion);
90+
logger = new ReportingLogger(mpInstance, sdkVersion);
6891
logger.error('x');
69-
expect(apiClient.sendLogToServer).toHaveBeenCalled();
92+
expect(mockFetch).toHaveBeenCalled();
7093
});
7194

7295
it('rate limits after 3 errors', () => {
@@ -76,10 +99,10 @@ describe('ReportingLogger', () => {
7699
return ++count > 3;
77100
}),
78101
};
79-
logger = new ReportingLogger(apiClient, sdkVersion, mockRateLimiter);
102+
logger = new ReportingLogger(mpInstance, sdkVersion, mockRateLimiter);
80103

81104
for (let i = 0; i < 5; i++) logger.error('err');
82-
expect(apiClient.sendLogToServer).toHaveBeenCalledTimes(3);
105+
expect(mockFetch).toHaveBeenCalledTimes(3);
83106
});
84107
});
85108

0 commit comments

Comments
 (0)