diff --git a/package.json b/package.json index 3646f604..70740b99 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "./packages/hyperion-react", "./packages/hyperion-autologging", "./packages/hyperion-autologging-plugin-eventhash", + "./packages/hyperion-autologging-plugin-network-performance-timing", "./packages/hyperion-autologging-visualizer", "./packages/hyperion-util", "./packages/hyperion-react-testapp", @@ -70,6 +71,7 @@ "hyperion-async-counter": "*", "hyperion-autologging": "*", "hyperion-autologging-plugin-eventhash": "*", + "hyperion-autologging-plugin-network-performance-timing": "*", "hyperion-autologging-visualizer": "*", "hyperion-channel": "*", "hyperion-core": "*", diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/.gitignore b/packages/hyperion-autologging-plugin-network-performance-timing/.gitignore new file mode 100644 index 00000000..11995f85 --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/.gitignore @@ -0,0 +1,7 @@ +*.log +.DS_Store +node_modules +dist +coverage +package-lock.json +test/**/*.js diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/.npmignore b/packages/hyperion-autologging-plugin-network-performance-timing/.npmignore new file mode 100644 index 00000000..17c50f99 --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/.npmignore @@ -0,0 +1,6 @@ +*.log +.DS_Store +coverage +test/**/*.js +jest.config.js +babel.config.js diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/babel.config.js b/packages/hyperion-autologging-plugin-network-performance-timing/babel.config.js new file mode 100644 index 00000000..a933e2ea --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/babel.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('hyperion-devtools/babel.config'); +module.exports = baseConfig; \ No newline at end of file diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/jest.config.js b/packages/hyperion-autologging-plugin-network-performance-timing/jest.config.js new file mode 100644 index 00000000..e5536729 --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/jest.config.js @@ -0,0 +1,6 @@ +const baseConfig = require('hyperion-devtools/jest.config'); +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ +module.exports = baseConfig; diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/package.json b/packages/hyperion-autologging-plugin-network-performance-timing/package.json new file mode 100644 index 00000000..865f51a2 --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/package.json @@ -0,0 +1,41 @@ +{ + "name": "hyperion-autologging-plugin-network-performance-timing", + "description": "plugin for autologging to add performance timing data to network responses", + "version": "0.3.4", + "license": "MIT", + "scripts": { + "build": "tsc", + "build-react": "react-scripts build", + "watch": "npm run build -- --watch", + "start": "npm run watch", + "test": "npm run build & jest" + }, + "workspaces": [ + "../hyperion-devtools", + "../hyperion-globals", + "../hyperion-channel" + ], + "dependencies": { + "hyperion-channel": "*", + "hyperion-globals": "*", + "xxhashjs": "^0.2.2" + }, + "devDependencies": { + "hyperion-devtools": "*", + "@types/jest": "^29.5.14", + "@types/xxhashjs": "^0.2.4" + }, + "eslintConfig": {}, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/src/index.ts b/packages/hyperion-autologging-plugin-network-performance-timing/src/index.ts new file mode 100644 index 00000000..10d6decd --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/src/index.ts @@ -0,0 +1,42 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved. + */ + +'use strict'; +import * as ALEventExtension from "hyperion-autologging/src/ALEventExtension"; +import { ALNetworkResponseEvent } from "hyperion-autologging/src/ALNetworkPublisher"; +import type { ALChannelEvent } from "hyperion-autologging/src/AutoLogging"; +import { Channel } from "hyperion-channel"; +import { assert } from "hyperion-globals"; +import { TimedTrigger } from "hyperion-timed-trigger/src/TimedTrigger"; + +export function init(channel: Channel): void { + + const urls = new Map(); + const observer = new PerformanceObserver((list) => { + for (const entry of list.getEntries()) { + assert(entry.entryType === 'resource', "Unexpected entry type!"); + const url = entry.name; + const response = urls.get(url); + if (response) { + ALEventExtension.setEventExtension(response, 'perf', entry); + urls.delete(url); + } + } + }); + observer.observe({ entryTypes: ['resource'] }); + + const cleaner = new TimedTrigger(() => { + urls.clear(); + }, 1000 * 60); // Clear every minutes + + channel.addListener('al_network_response', eventData => { + urls.set(eventData.requestEvent.url, eventData); + if (cleaner.isDone()) { + cleaner.restart(); + } else { + cleaner.delay(); + } + }); + +} \ No newline at end of file diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/test/index.test.ts b/packages/hyperion-autologging-plugin-network-performance-timing/test/index.test.ts new file mode 100644 index 00000000..e7e80d39 --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/test/index.test.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. All Rights Reserved. + * + * @jest-environment jsdom + */ +'use strict'; + +test("empty test", () => { + expect(0); +}); \ No newline at end of file diff --git a/packages/hyperion-autologging-plugin-network-performance-timing/tsconfig.json b/packages/hyperion-autologging-plugin-network-performance-timing/tsconfig.json new file mode 100644 index 00000000..b92b796f --- /dev/null +++ b/packages/hyperion-autologging-plugin-network-performance-timing/tsconfig.json @@ -0,0 +1,11 @@ +{ + // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs + "extends": "hyperion-devtools", + "compilerOptions": { + // "jsx": "react-jsx", + "jsx": "preserve", + }, + "include": [ + "src", + ], +} \ No newline at end of file diff --git a/packages/hyperion-autologging/src/ALNetworkPublisher.ts b/packages/hyperion-autologging/src/ALNetworkPublisher.ts index 9778c933..56d27101 100644 --- a/packages/hyperion-autologging/src/ALNetworkPublisher.ts +++ b/packages/hyperion-autologging/src/ALNetworkPublisher.ts @@ -11,9 +11,9 @@ import { assert } from "hyperion-globals"; import * as Types from "hyperion-util/src/Types"; import performanceAbsoluteNow from "hyperion-util/src/performanceAbsoluteNow"; import * as ALEventIndex from "./ALEventIndex"; -import { ALLoggableEvent, ALOptionalFlowletEvent, ALSharedInitOptions } from "./ALType"; +import { ALExtensibleEvent, ALLoggableEvent, ALOptionalFlowletEvent, ALSharedInitOptions } from "./ALType"; -type ALNetworkEvent = ALLoggableEvent & ALOptionalFlowletEvent & Readonly<{ +type ALNetworkEvent = ALLoggableEvent & ALOptionalFlowletEvent & ALExtensibleEvent & Readonly<{ initiatorType: "fetch" | "xmlhttprequest"; // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/initiatorType }>; diff --git a/packages/hyperion-react-testapp/package.json b/packages/hyperion-react-testapp/package.json index d82799a7..9a757b61 100644 --- a/packages/hyperion-react-testapp/package.json +++ b/packages/hyperion-react-testapp/package.json @@ -9,7 +9,8 @@ "../hyperion-react", "../hyperion-autologging", "../hyperion-autologging-visualizer", - "../hyperion-autologging-plugin-eventhash" + "../hyperion-autologging-plugin-eventhash", + "../hyperion-autologging-plugin-network-performance-timing" ], "dependencies": { "@testing-library/jest-dom": "^6.6.3", @@ -22,6 +23,8 @@ "@vitejs/plugin-react": "^4.3.4", "hyperion-autologging": "*", "hyperion-autologging-visualizer": "*", + "hyperion-autologging-plugin-eventhash": "*", + "hyperion-autologging-plugin-network-performance-timing": "*", "hyperion-globals": "*", "hyperion-hook": "*", "hyperion-react": "*", @@ -60,4 +63,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/packages/hyperion-react-testapp/src/AutoLoggingWrapper.ts b/packages/hyperion-react-testapp/src/AutoLoggingWrapper.ts index b4a9d543..e0ba8b6c 100644 --- a/packages/hyperion-react-testapp/src/AutoLoggingWrapper.ts +++ b/packages/hyperion-react-testapp/src/AutoLoggingWrapper.ts @@ -19,6 +19,7 @@ import * as Flags from "hyperion-globals/src/Flags"; import "hyperion-autologging/src/reference"; import * as PluginEventHash from "hyperion-autologging-plugin-eventhash/src/index"; import { getSessionFlowID } from "hyperion-autologging/src/ALSessionFlowID"; +import * as PluginNetworkPerformanceTiming from "hyperion-autologging-plugin-network-performance-timing/src/index"; export let interceptionStatus = "disabled"; @@ -69,7 +70,8 @@ export function init() { flowletManager, channel, plugins: [ - PluginEventHash.init + PluginEventHash.init, + PluginNetworkPerformanceTiming.init, ], componentNameValidator: testCompValidator, flowletPublisher: {