@zendesk/react-measure-timing-hooks
Version:
react hooks for measuring time to interactive and time to render of components
444 lines • 17 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const hooks_1 = require("./hooks");
const match = __importStar(require("./matchSpan"));
const TraceManager_1 = require("./TraceManager");
const mockSpanWithoutRelation = {
name: 'some-span',
duration: 0,
type: 'mark',
attributes: {},
startTime: { now: 0, epoch: 0 },
};
(0, vitest_1.describe)('type tests', () => {
const traceManager = new TraceManager_1.TraceManager({
relationSchemas: {
global: {},
ticket: { ticketId: String },
user: { userId: String },
tickedField: { ticketId: String, customFieldId: String },
custom: { customId: String, customOtherId: String },
ticketEvent: { ticketId: String, eventId: String },
},
generateId: () => 'id',
reportFn: (trace) => {
if (!trace.relatedTo)
return;
if ('ticketId' in trace.relatedTo) {
// valid
(0, vitest_1.expect)(trace.relatedTo.ticketId).toBeDefined();
// @ts-expect-error invalid relatedTo
(0, vitest_1.expect)(trace.relatedTo.userId).toBeDefined();
}
if ('eventId' in trace.relatedTo) {
// valid
(0, vitest_1.expect)(trace.relatedTo.eventId).toBeDefined();
(0, vitest_1.expect)(trace.relatedTo.ticketId).toBeDefined();
// @ts-expect-error invalid relatedTo
(0, vitest_1.expect)(trace.relatedTo.userId).toBeDefined();
}
if ('userId' in trace.relatedTo) {
// valid
(0, vitest_1.expect)(trace.relatedTo.userId).toBeDefined();
// @ts-expect-error invalid relatedTo
(0, vitest_1.expect)(trace.relatedTo.ticketId).toBeDefined();
}
// valid
if ('customFieldId' in trace.relatedTo) {
(0, vitest_1.expect)(trace.relatedTo.customFieldId).toBeDefined();
}
},
reportErrorFn: (error) => {
console.error(error);
},
});
const useBeacon = (0, hooks_1.generateUseBeacon)(traceManager);
const useBeaconWithRequiredAttributes = (0, hooks_1.generateUseBeacon)(traceManager);
(0, vitest_1.it)('works', () => {
// invalid:
const invalidTraceManager = new TraceManager_1.TraceManager({
generateId: () => 'id',
reportFn: () => { },
reportErrorFn: () => { },
relationSchemas: {
// @ts-expect-error because in the matcher functions, we cannot compare objects (due to object equality comparison)
something: { blah: { test: String } },
},
});
// valid beacon
useBeacon({
name: 'OmniLog',
renderedOutput: 'content',
relatedTo: { ticketId: '123', customFieldId: '123' },
});
// valid beacon
useBeacon({
name: 'UserPage',
renderedOutput: 'content',
relatedTo: { userId: '123' },
});
// invalid
useBeacon({
name: 'UserPage',
renderedOutput: 'content',
// @ts-expect-error invalid relatedTo
relatedTo: { invalid: '123' },
});
// valid beacon
useBeacon({
name: 'OmniLog',
renderedOutput: 'content',
// @ts-expect-error invalid: missing ticketId
relatedTo: { customFieldId: '123' },
});
// valid beacon with only required attributes
useBeaconWithRequiredAttributes({
name: 'UserPage',
renderedOutput: 'content',
relatedTo: { userId: '123' },
attributes: { team: 'test' },
});
// valid beacon required attributes and additional attributes
useBeaconWithRequiredAttributes({
name: 'UserPage',
renderedOutput: 'content',
relatedTo: { userId: '123' },
attributes: { randoKey: 'test', team: 'test' },
});
// invalid beacon missing required attributes
useBeaconWithRequiredAttributes({
name: 'UserPage',
renderedOutput: 'content',
relatedTo: { userId: '123' },
// @ts-expect-error attributes require a team key
attributes: { randoKey: 'test' },
});
// valid definition
const ticketActivationTracer = traceManager.createTracer({
name: 'ticket.activated',
relationSchemaName: 'ticket',
variants: {
origin: { timeout: 5_000 },
another_origin: { timeout: 10_000 },
},
requiredSpans: [{ matchingRelations: ['ticketId'] }],
});
const ticketActivationTracer2 = traceManager.createTracer({
name: 'ticket.activated',
relationSchemaName: 'custom',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [
match.withAllConditions(match.withName((name, relations) => name === `${relations?.customId}.end`), match.withName('end'), match.withMatchingRelations(['customId'])),
match.withName((name, relatedTo) => name === `${relatedTo?.customId}.end`),
match.withName('customFieldId'),
match.withMatchingRelations(['customId']),
// @ts-expect-error invalid relatedTo
match.withMatchingRelations(['typoId']),
],
});
// valid definition
const userPageTracer = traceManager.createTracer({
name: 'user.activation',
relationSchemaName: 'user',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [{ matchingRelations: ['userId'] }],
});
// valid definition
const customFieldDropdownTracer = traceManager.createTracer({
name: 'ticket.custom_field',
relationSchemaName: 'tickedField',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [{ matchingRelations: ['ticketId'] }],
});
// invalid definition. relatedTo match but not included in AllPossibleScopes
const invalidTracer = traceManager.createTracer({
name: 'ticket.activated',
variants: {
origin: { timeout: 5_000 },
},
// @ts-expect-error invalid relatedTo
relationSchemaName: ['invalid'],
requiredSpans: [
{
// @ts-expect-error invalid relatedTo
matchingRelations: ['invalid'],
},
],
});
// invalid definition. userId given in requiredSpans isn't one of the relatedTo the tracer says it can have
const shouldErrorTrace = traceManager.createTracer({
name: 'ticket.should_error',
relationSchemaName: 'tickedField',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [
{
// @ts-expect-error invalid relatedTo
matchingRelations: ['userId'],
},
],
});
// valid definition
const ticketActivationWithFnTracer = traceManager.createTracer({
name: 'ticket.activated',
relationSchemaName: 'ticket',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [
{ matchingRelations: ['ticketId'] },
({ span }) => span.relatedTo?.ticketId === '123',
],
});
// valid start
ticketActivationTracer.start({
relatedTo: { ticketId: '123' },
variant: 'origin',
});
// valid start
ticketActivationTracer.start({
relatedTo: { ticketId: '999' },
variant: 'another_origin',
});
// invalid start - wrong variant
ticketActivationTracer.start({
relatedTo: { ticketId: '123' },
// @ts-expect-error invalid variant
variant: 'origin_wrong',
});
// invalid start (errors)
ticketActivationTracer.start({
// @ts-expect-error invalid relatedTo
relatedTo: { whatever: '123' },
});
// invalid start (errors)
ticketActivationTracer.start({
// @ts-expect-error invalid relatedTo
relatedTo: { userId: '123' },
variant: 'origin',
});
// valid - excess relatedTo
traceManager.processSpan({
...mockSpanWithoutRelation,
relatedTo: { ticketId: '123', customFieldId: '123', userId: '123' },
});
// valid
traceManager.processSpan({
...mockSpanWithoutRelation,
relatedTo: { ticketId: '123' },
});
// valid - multiple relatedTo simultaneously
traceManager.processSpan({
...mockSpanWithoutRelation,
relatedTo: {
ticketId: '123',
customFieldId: '123',
},
});
// invalid
traceManager.processSpan({
...mockSpanWithoutRelation,
relatedTo: {
// @ts-expect-error bad relatedTo
bad: '123',
},
});
// invalid
traceManager.processSpan({
...mockSpanWithoutRelation,
relatedTo: {
// @ts-expect-error bad relatedTo
ticketId: 123,
},
});
ticketActivationTracer.addRequirementsToCurrentTraceOnly({
additionalRequiredSpans: [
{ name: 'end', matchingRelations: ['ticketId'] },
],
});
});
(0, vitest_1.it)('does not allow to include invalid relatedTo value', () => {
const tracer = traceManager.createTracer({
name: 'ticket.relatedTo-operation',
type: 'operation',
relationSchemaName: 'ticket',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [{ name: 'end', matchingRelations: true }],
});
const traceId = tracer.start({
relatedTo: {
// @ts-expect-error number should not be assignable to string
ticketId: 4,
},
variant: 'origin',
});
(0, vitest_1.assertType)(traceId);
});
(0, vitest_1.it)('mixed relatedTo', () => {
const tracer = traceManager.createTracer({
name: 'ticket.relatedTo-operation',
type: 'operation',
relationSchemaName: 'tickedField',
requiredSpans: [{ name: 'end', matchingRelations: true }],
variants: { default: { timeout: 5_000 } },
});
const traceId = tracer.start({
variant: 'default',
relatedTo: {
customFieldId: '3',
ticketId: '4',
},
});
});
(0, vitest_1.it)('redaction example', () => {
const tracer = traceManager.createTracer({
name: 'ticket.event.redacted',
type: 'operation',
relationSchemaName: 'ticketEvent',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [{ name: 'OmniLogEvent', matchingRelations: true }],
debounceOnSpans: [{ name: 'OmniLog', matchingRelations: ['ticketId'] }],
});
const traceId = tracer.start({
relatedTo: {
ticketId: '4',
eventId: '3',
},
variant: 'origin',
});
(0, vitest_1.assertType)(traceId);
});
(0, vitest_1.it)('redaction invalid example', () => {
const tracer = traceManager.createTracer({
name: 'ticket.event.redacted',
type: 'operation',
// @ts-expect-error enforce a complete set of keys of a given relatedTo
relationSchemaName: ['eventId'],
timeout: 5_000,
requiredSpans: [{ name: 'OmniLogEvent', matchingRelations: true }],
});
const correctTracer = traceManager.createTracer({
name: 'ticket.event.redacted',
type: 'operation',
relationSchemaName: 'ticketEvent',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [{ name: 'OmniLogEvent', matchingRelations: true }],
});
const traceId = correctTracer.start({
relatedTo: {
ticketId: '4',
// @ts-expect-error trying to start trace with invalid relatedTo combination
customFieldId: 'werwer',
},
variant: 'origin',
});
});
(0, vitest_1.it)('does not allow to include invalid relatedTo key', () => {
const tracer = traceManager.createTracer({
name: 'ticket.relatedTo-operation',
type: 'operation',
relationSchemaName: 'ticket',
variants: {
origin: { timeout: 5_000 },
},
requiredSpans: [{ name: 'end', matchingRelations: true }],
});
const traceId = tracer.start({
variant: 'origin',
relatedTo: {
// @ts-expect-error invalid relatedTo key
userId: '3',
},
});
(0, vitest_1.assertType)(traceId);
});
(0, vitest_1.it)('maps schema to types', () => {
const testSchema = {
a: String,
b: Number,
c: Boolean,
d: ['union', 'of', 'things', 2],
};
(0, vitest_1.assertType)({});
});
(0, vitest_1.it)('maps computedValueDefinitions', () => {
const tracer = traceManager.createTracer({
name: 'ticket.multiple-computed-values',
type: 'operation',
relationSchemaName: 'global',
requiredSpans: [{ name: 'end' }],
variants: {
cold_boot: { timeout: 10_000 },
},
computedValueDefinitions: {
'valid-feature-count': {
matches: [{ name: 'feature' }, { name: 'feature-2' }],
computeValueFromMatches: (feature, feature2) => feature.length + feature2.length,
},
'invalid-feature-count': {
matches: [{ name: 'feature' }, { name: 'feature-2' }],
// @ts-expect-error invalid number of arguments
computeValueFromMatches: (feature, feature2, invalid) => 0,
},
'error-count': {
matches: [{ name: (name) => name.startsWith('error') }],
computeValueFromMatches: (errors) => errors.length,
},
another: {
matches: [(name) => name.span.name.startsWith('error')],
computeValueFromMatches: (errors) => errors.length,
},
// TODO: adding a function breaks the type for some odd reason
// https://github.com/microsoft/TypeScript/issues/61228
},
});
});
});
//# sourceMappingURL=types.test-d.js.map