Skip to content

Commit d5a6726

Browse files
authored
feat: Send metrics no panorama API as a fallback (#96)
1 parent 877ec32 commit d5a6726

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

src/internal/base-component/__tests__/metrics.test.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,20 @@ describe('Client Metrics support', () => {
5555
});
5656

5757
test('does nothing when window.AWSC.Clog is undefined', () => {
58-
window.AWSC = undefined;
58+
window.AWSC = {};
5959
metrics.sendMetric('name', 0); // only proves no exception thrown
6060
});
6161

62+
test('uses panorama API as fallback when AWSC.Clog.log is unavailable', () => {
63+
delete window.AWSC;
64+
metrics.sendMetric('name', 0);
65+
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
66+
eventName: 'name',
67+
eventValue: '0',
68+
timestamp: expect.any(Number),
69+
});
70+
});
71+
6272
test('does nothing when window.AWSC.Clog.log is undefined', () => {
6373
window.AWSC = {
6474
Clog: undefined,
@@ -68,10 +78,15 @@ describe('Client Metrics support', () => {
6878

6979
describe('within an iframe', () => {
7080
mockConsoleError();
81+
const originalWindowParent = Object.getOwnPropertyDescriptor(window, 'parent')!;
82+
83+
afterEach(() => {
84+
Object.defineProperty(window, 'parent', originalWindowParent);
85+
expect(window.parent.AWSC).toBeUndefined();
86+
});
87+
7188
const setupIframe = () => {
72-
const parentWindow = { ...window };
73-
Object.defineProperty(window, 'parent', { value: parentWindow });
74-
Object.defineProperty(parentWindow, 'parent', { value: parentWindow });
89+
Object.defineProperty(window, 'parent', { configurable: true, writable: true, value: { parent: {} } });
7590
};
7691

7792
test('does nothing when AWSC is not defined in the parent iframe', () => {
@@ -91,6 +106,8 @@ describe('Client Metrics support', () => {
91106
},
92107
};
93108
jest.spyOn(window.parent.AWSC.Clog, 'log');
109+
expect(window.AWSC).toBeUndefined();
110+
expect(window.parent.AWSC).toBeDefined();
94111

95112
metrics.sendMetric('name', 0, undefined);
96113
expect(window.parent.AWSC.Clog.log).toHaveBeenCalledWith('name', 0, undefined);
@@ -173,6 +190,17 @@ describe('Client Metrics support', () => {
173190
});
174191

175192
describe('sendMetricObject', () => {
193+
test('uses panorama API as fallback when AWSC.Clog.log is unavailable', () => {
194+
window.AWSC = undefined;
195+
metrics.sendMetricObject({ source: 'pkg', action: 'used', version: '5.0' }, 1);
196+
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
197+
eventDetail: '{"o":"main","s":"pkg","t":"default","a":"used","f":"react","v":"5.0"}',
198+
eventName: 'awsui_pkg_d50',
199+
eventValue: '1',
200+
timestamp: expect.any(Number),
201+
});
202+
});
203+
176204
describe('correctly maps input object to metric name', () => {
177205
test('applies default values for theme (default) and framework (react)', () => {
178206
metrics.sendMetricObject(

src/internal/base-component/__tests__/panorama-metrics.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ describe('PanoramaClient', () => {
5656
expect(consoleSpy).toHaveBeenCalledWith(`Event type for metric is too long: ${eventType}`);
5757
});
5858

59+
test('prints an error when event name is too long', () => {
60+
const eventName = 'a'.repeat(1001);
61+
panorama.sendMetric({ eventName });
62+
63+
expect(window.panorama).not.toHaveBeenCalled();
64+
expect(consoleSpy).toHaveBeenCalledWith(`Event name for metric is too long: ${eventName}`);
65+
});
66+
5967
test('prints an error when event value is too long', () => {
6068
const eventValue = 'a'.repeat(4001);
6169
panorama.sendMetric({ eventValue });

src/internal/base-component/metrics/log-clients.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface MetricsWindow extends Window {
1111
}
1212

1313
export interface MetricsV2EventItem {
14+
eventName?: string;
1415
eventType?: string;
1516
eventContext?: string;
1617
eventDetail?: string | Record<string, string | number | boolean>;
@@ -45,6 +46,13 @@ export class CLogClient {
4546
const AWSC = this.findAWSC(window);
4647
if (typeof AWSC === 'object' && typeof AWSC.Clog === 'object' && typeof AWSC.Clog.log === 'function') {
4748
AWSC.Clog.log(metricName, value, detail);
49+
} else {
50+
new PanoramaClient().sendMetric({
51+
eventName: metricName,
52+
eventDetail: detail,
53+
eventValue: `${value}`,
54+
timestamp: Date.now(),
55+
});
4856
}
4957
}
5058

@@ -81,6 +89,10 @@ export class PanoramaClient {
8189
if (typeof metric.eventValue === 'object') {
8290
metric.eventValue = JSON.stringify(metric.eventValue);
8391
}
92+
if (!validateLength(metric.eventName, 1000)) {
93+
console.error(`Event name for metric is too long: ${metric.eventName}`);
94+
return;
95+
}
8496
if (!validateLength(metric.eventDetail, 4000)) {
8597
console.error(`Event detail for metric is too long: ${metric.eventDetail}`);
8698
return;

0 commit comments

Comments
 (0)