Skip to content

Commit

Permalink
chore: Improve metrics format (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
just-boris authored Jan 30, 2025
1 parent 3c08c6f commit 9b48c5e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 69 deletions.
27 changes: 18 additions & 9 deletions src/internal/base-component/__tests__/metrics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ describe('Client Metrics support', () => {

const checkMetric = (metricName: string, detailObject: MetricDetail) => {
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: metricName,
eventType: 'awsui',
eventContext: metricName,
eventDetail: JSON.stringify(detailObject),
eventValue: '1',
timestamp: expect.any(Number),
Expand Down Expand Up @@ -97,7 +98,8 @@ describe('Client Metrics support', () => {

metrics.sendMetric('name', 0, undefined);
expect(window.parent.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'name',
eventType: 'awsui',
eventContext: 'name',
eventValue: '0',
timestamp: expect.any(Number),
});
Expand All @@ -110,7 +112,8 @@ describe('Client Metrics support', () => {
test('delegates to window.panorama when defined', () => {
metrics.sendMetric('name', 0, undefined);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'name',
eventType: 'awsui',
eventContext: 'name',
eventValue: '0',
timestamp: expect.any(Number),
});
Expand All @@ -121,7 +124,8 @@ describe('Client Metrics support', () => {
test(`calls window.panorama when valid metric name used (${metricName})`, () => {
metrics.sendMetric(metricName, 1, 'detail');
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: metricName,
eventType: 'awsui',
eventContext: metricName,
eventValue: '1',
eventDetail: 'detail',
timestamp: expect.any(Number),
Expand Down Expand Up @@ -163,7 +167,8 @@ describe('Client Metrics support', () => {
const validDetail = 'a'.repeat(4000);
metrics.sendMetric('metricName', 1, validDetail);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'metricName',
eventType: 'awsui',
eventContext: 'metricName',
eventValue: '1',
eventDetail: validDetail,
timestamp: expect.any(Number),
Expand All @@ -186,7 +191,8 @@ describe('Client Metrics support', () => {
test('logs a metric name only once', () => {
metrics.sendMetricOnce('my-event', 1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'my-event',
eventType: 'awsui',
eventContext: 'my-event',
eventValue: '1',
timestamp: expect.any(Number),
});
Expand All @@ -200,12 +206,14 @@ describe('Client Metrics support', () => {
metrics.sendMetricOnce('my-event', 1);
metrics.sendMetricOnce('My-Event', 2);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'my-event',
eventType: 'awsui',
eventContext: 'my-event',
eventValue: '1',
timestamp: expect.any(Number),
});
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'My-Event',
eventType: 'awsui',
eventContext: 'My-Event',
eventValue: '2',
timestamp: expect.any(Number),
});
Expand All @@ -218,8 +226,9 @@ describe('Client Metrics support', () => {
window.AWSC = undefined;
metrics.sendMetricObject({ source: 'pkg', action: 'used', version: '5.0' }, 1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventType: 'awsui',
eventContext: 'awsui_pkg_d50',
eventDetail: '{"o":"main","s":"pkg","t":"default","a":"used","f":"react","v":"5.0"}',
eventName: 'awsui_pkg_d50',
eventValue: '1',
timestamp: expect.any(Number),
});
Expand Down
48 changes: 14 additions & 34 deletions src/internal/base-component/__tests__/panorama-metrics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,69 +23,47 @@ describe('PanoramaClient', () => {
});

test('sends simple metrics', () => {
panorama.sendMetric({ eventType: 'custom', eventValue: 'value' });
panorama.sendMetric({ eventValue: 'value' });

expect(window.panorama).toHaveBeenCalledWith(
'trackCustomEvent',
expect.objectContaining({ eventType: 'custom', eventValue: 'value' })
expect.objectContaining({ eventType: 'awsui', eventValue: 'value' })
);
});

test('converts objects to strings', () => {
panorama.sendMetric({ eventType: 'custom', eventValue: { test: 'value' }, eventDetail: { test: 'detail' } });
panorama.sendMetric({ eventValue: { test: 'value' }, eventDetail: { test: 'detail' } });

expect(window.panorama).toHaveBeenCalledWith(
'trackCustomEvent',
expect.objectContaining({ eventType: 'custom', eventValue: '{"test":"value"}', eventDetail: '{"test":"detail"}' })
expect.objectContaining({ eventValue: '{"test":"value"}', eventDetail: '{"test":"detail"}' })
);
});

test('prints an error when event details are too long', () => {
const eventDetail = 'a'.repeat(4001);
panorama.sendMetric({ eventType: 'custom', eventDetail });
panorama.sendMetric({ eventContext: 'custom', eventDetail });

expect(window.panorama).toHaveBeenCalledTimes(1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'awsui-metric-error',
eventType: 'awsui',
eventContext: 'awsui-metric-error',
eventDetail: expect.stringMatching(/Event detail for metric is too long:.*/),
timestamp: expect.any(Number),
});
expect(consoleSpy).toHaveBeenCalledWith(`Event detail for metric is too long: ${eventDetail}`);
});

test('prints an error when event type is too long', () => {
const eventType = 'a'.repeat(51);
const errorMessage = `Event type for metric is too long: ${eventType}`;
panorama.sendMetric({ eventType });

expect(window.panorama).toHaveBeenCalledTimes(1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'awsui-metric-error',
eventDetail: errorMessage,
});
expect(consoleSpy).toHaveBeenCalledWith(errorMessage);
});

test('prints an error when event name is too long', () => {
const eventName = 'a'.repeat(1001);
const errorMessage = `Event name for metric is too long: ${eventName}`;
panorama.sendMetric({ eventName });

expect(window.panorama).toHaveBeenCalledTimes(1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'awsui-metric-error',
eventDetail: errorMessage,
});
expect(consoleSpy).toHaveBeenCalledWith(errorMessage);
});

test('prints an error when event value is too long', () => {
const eventValue = 'a'.repeat(4001);
panorama.sendMetric({ eventValue });

expect(window.panorama).toHaveBeenCalledTimes(1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'awsui-metric-error',
eventType: 'awsui',
eventContext: 'awsui-metric-error',
eventDetail: expect.stringMatching(/Event value for metric is too long:.*/),
timestamp: expect.any(Number),
});
expect(consoleSpy).toHaveBeenCalledWith(`Event value for metric is too long: ${eventValue}`);
});
Expand All @@ -96,8 +74,10 @@ describe('PanoramaClient', () => {

expect(window.panorama).toHaveBeenCalledTimes(1);
expect(window.panorama).toHaveBeenCalledWith('trackCustomEvent', {
eventName: 'awsui-metric-error',
eventType: 'awsui',
eventContext: 'awsui-metric-error',
eventDetail: expect.stringMatching(/Event context for metric is too long:.*/),
timestamp: expect.any(Number),
});
expect(consoleSpy).toHaveBeenCalledWith(`Event context for metric is too long: ${eventContext}`);
});
Expand Down
56 changes: 30 additions & 26 deletions src/internal/base-component/metrics/log-clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@ interface MetricsWindow extends Window {
}

export interface MetricsV2EventItem {
eventName?: string;
eventType?: string;
eventContext?: string;
eventDetail?: string | Record<string, string | number | boolean>;
eventValue?: string | Record<string, string | number | boolean>;
timestamp?: number;
}

type PanoramaFunction = (event: 'trackCustomEvent', data: MetricsV2EventItem) => void;
interface PanoramaMetric {
eventType: string;
eventContext?: string;
eventValue?: string;
eventDetail?: string;
timestamp: number;
}

type PanoramaFunction = (event: 'trackCustomEvent', data: PanoramaMetric) => void;

const AWSUI_EVENT = 'awsui';

function validateLength(value: string | undefined, maxLength: number): boolean {
return !value || value.length <= maxLength;
Expand All @@ -46,7 +54,7 @@ export class CLogClient {
return;
}
const wasSent = new PanoramaClient().sendMetric({
eventName: metricName,
eventContext: metricName,
eventDetail: detail,
eventValue: `${value}`,
timestamp: Date.now(),
Expand Down Expand Up @@ -91,33 +99,27 @@ export class PanoramaClient {
if (!panorama) {
return false;
}
if (typeof metric.eventDetail === 'object') {
metric.eventDetail = JSON.stringify(metric.eventDetail);
}
if (typeof metric.eventValue === 'object') {
metric.eventValue = JSON.stringify(metric.eventValue);
}
if (!validateLength(metric.eventName, 1000)) {
this.onMetricError(`Event name for metric is too long: ${metric.eventName}`);
return true;
}
if (!validateLength(metric.eventDetail, 4000)) {
this.onMetricError(`Event detail for metric is too long: ${metric.eventDetail}`);
return true;
}
if (!validateLength(metric.eventValue, 4000)) {
this.onMetricError(`Event value for metric is too long: ${metric.eventValue}`);
const payload: PanoramaMetric = {
eventType: AWSUI_EVENT,
timestamp: Date.now(),
...metric,
eventDetail: typeof metric.eventDetail === 'object' ? JSON.stringify(metric.eventDetail) : metric.eventDetail,
eventValue: typeof metric.eventValue === 'object' ? JSON.stringify(metric.eventValue) : metric.eventValue,
};

if (!validateLength(payload.eventDetail, 4000)) {
this.onMetricError(`Event detail for metric is too long: ${payload.eventDetail}`);
return true;
}
if (!validateLength(metric.eventContext, 4000)) {
this.onMetricError(`Event context for metric is too long: ${metric.eventContext}`);
if (!validateLength(payload.eventValue, 4000)) {
this.onMetricError(`Event value for metric is too long: ${payload.eventValue}`);
return true;
}
if (!validateLength(metric.eventType, 50)) {
this.onMetricError(`Event type for metric is too long: ${metric.eventType}`);
if (!validateLength(payload.eventContext, 4000)) {
this.onMetricError(`Event context for metric is too long: ${payload.eventContext}`);
return true;
}
panorama('trackCustomEvent', { timestamp: Date.now(), ...metric });
panorama('trackCustomEvent', payload);
return true;
}

Expand All @@ -126,8 +128,10 @@ export class PanoramaClient {
const panorama = this.findPanorama(window);
if (panorama) {
panorama('trackCustomEvent', {
eventName: 'awsui-metric-error',
eventType: AWSUI_EVENT,
eventContext: 'awsui-metric-error',
eventDetail: message.slice(0, 4000),
timestamp: Date.now(),
});
}
}
Expand Down

0 comments on commit 9b48c5e

Please sign in to comment.