From 64d26cffd69b2227a7dd0d3c5ba0113c27aa4cea Mon Sep 17 00:00:00 2001 From: Yoann Moinet Date: Fri, 7 Jun 2024 16:21:30 +0200 Subject: [PATCH] Add RUM Plugin --- .github/CODEOWNERS | 4 ++ README.md | 10 +++ packages/plugins/rum/README.md | 21 ++++++ packages/plugins/rum/package.json | 26 ++++++++ packages/plugins/rum/src/constants.ts | 8 +++ packages/plugins/rum/src/index.ts | 69 ++++++++++++++++++++ packages/plugins/rum/src/types.ts | 26 ++++++++ packages/plugins/rum/tsconfig.json | 10 +++ packages/tests/src/plugins/rum/index.test.ts | 51 +++++++++++++++ 9 files changed, 225 insertions(+) create mode 100644 packages/plugins/rum/README.md create mode 100644 packages/plugins/rum/package.json create mode 100644 packages/plugins/rum/src/constants.ts create mode 100644 packages/plugins/rum/src/index.ts create mode 100644 packages/plugins/rum/src/types.ts create mode 100644 packages/plugins/rum/tsconfig.json create mode 100644 packages/tests/src/plugins/rum/index.test.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3a7f4cde..5eebde04 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,3 +6,7 @@ # Telemetry packages/plugins/telemetry @DataDog/frontend-devx @yoannmoinet packages/tests/src/plugins/telemetry @DataDog/frontend-devx @yoannmoinet + +# Rum +packages/plugins/rum @DataDog/rum @yoannmoinet +packages/tests/src/plugins/rum @DataDog/rum @yoannmoinet \ No newline at end of file diff --git a/README.md b/README.md index 50414bd1..6fe2be8f 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ A set of plugins to interact with Datadog directly from your builds. - [Plugins](#plugins) + - [`rum` RUM Plugin](#rum-rum-plugin) - [`telemetry` Telemetry Plugin](#telemetry-telemetry-plugin) - [Configuration](#configuration) - [`auth.apiKey`](#authapikey) @@ -32,6 +33,12 @@ A set of plugins to interact with Datadog directly from your builds. ## Plugins +### `rum` RUM Plugin + +> Interact with our Real User Monitoring product (RUM) in Datadog directly from your build system. + +[📝 Full documentation ➡️](./packages/plugins/rum#readme) + ### `telemetry` Telemetry Plugin > Display and send telemetry data as metrics to Datadog. @@ -52,6 +59,9 @@ A set of plugins to interact with Datadog directly from your builds. endPoint?: string; }; logLevel?: 'debug' | 'warn' | 'error' | 'none'; + rum?: { + disabled?: boolean; + }; telemetry?: { disabled?: boolean; output?: boolean diff --git a/packages/plugins/rum/README.md b/packages/plugins/rum/README.md new file mode 100644 index 00000000..a6d3198e --- /dev/null +++ b/packages/plugins/rum/README.md @@ -0,0 +1,21 @@ +# RUM Plugin + +Interact with our Real User Monitoring product (RUM) in Datadog directly from your build system. + + + +## Table of content + + + + +- [Configuration](#configuration) + + +## Configuration + +```ts +rum?: { + disabled?: boolean; +} +``` diff --git a/packages/plugins/rum/package.json b/packages/plugins/rum/package.json new file mode 100644 index 00000000..cf8b94fb --- /dev/null +++ b/packages/plugins/rum/package.json @@ -0,0 +1,26 @@ +{ + "name": "@dd/rum-plugins", + "packageManager": "yarn@4.0.2", + "license": "MIT", + "private": true, + "author": "Datadog", + "description": "Interact with our Real User Monitoring product (RUM) in Datadog directly from your build system.", + "homepage": "https://github.com/DataDog/build-plugins/tree/main/packages/plugins/rum#readme", + "repository": { + "type": "git", + "url": "https://github.com/DataDog/build-plugins", + "directory": "packages/plugins/rum" + }, + "exports": { + ".": "./src/index.ts", + "./*": "./src/*.ts" + }, + "scripts": { + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@dd/core": "workspace:*", + "chalk": "2.3.1", + "unplugin": "1.10.1" + } +} diff --git a/packages/plugins/rum/src/constants.ts b/packages/plugins/rum/src/constants.ts new file mode 100644 index 00000000..a27b7a17 --- /dev/null +++ b/packages/plugins/rum/src/constants.ts @@ -0,0 +1,8 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +import type { PluginName } from '@dd/core/types'; + +export const CONFIG_KEY = 'rum' as const; +export const PLUGIN_NAME: PluginName = 'datadog-rum-plugin' as const; diff --git a/packages/plugins/rum/src/index.ts b/packages/plugins/rum/src/index.ts new file mode 100644 index 00000000..368b9b32 --- /dev/null +++ b/packages/plugins/rum/src/index.ts @@ -0,0 +1,69 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +import { getLogFn } from '@dd/core/log'; +import type { Context } from '@dd/core/plugins'; +import type { GetPlugins } from '@dd/core/types'; +import chalk from 'chalk'; + +import { PLUGIN_NAME, CONFIG_KEY } from './constants'; +import type { OptionsWithRumEnabled, RumOptions, RumOptionsEnabled } from './types'; + +export { CONFIG_KEY, PLUGIN_NAME } from './constants'; + +export const helpers = { + // Add the helpers you'd like to expose here. +}; + +export type types = { + // Add the types you'd like to expose here. + RumOptions: RumOptions; + OptionsWithRumEnabled: OptionsWithRumEnabled; +}; + +// Deal with validation and defaults here. +export const validateOptions = (config: Partial): RumOptionsEnabled => { + const red = chalk.bold.red; + const errors = []; + const validatedOptions: RumOptionsEnabled = config[CONFIG_KEY] || {}; + + if (validatedOptions.sourcemaps) { + if (!validatedOptions.sourcemaps.basePath) { + errors.push(`${red('sourcemaps.basePath')} is required.`); + } + if (!validatedOptions.sourcemaps.releaseVersion) { + errors.push(`${red('sourcemaps.releaseVersion')} is required.`); + } + } + + if (errors.length) { + throw new Error(`Invalid configuration for ${PLUGIN_NAME}:\n ${errors.join('\n ')}`); + } + + return validatedOptions; +}; + +export const getPlugins: GetPlugins = ( + opts: OptionsWithRumEnabled, + context: Context, +) => { + return [ + { + name: PLUGIN_NAME, + async writeBundle() { + const rumOptions = opts[CONFIG_KEY]; + if (rumOptions.disabled || !rumOptions.sourcemaps) { + return; + } + const log = getLogFn(opts.logLevel, PLUGIN_NAME); + log(`Uploading sourcemaps.`); + + // Verify configuration. + // Gather the sourcemaps files using glob. + // Build payloads (with git info from context plugin). + // Upload the sourcemaps. + }, + }, + ]; +}; diff --git a/packages/plugins/rum/src/types.ts b/packages/plugins/rum/src/types.ts new file mode 100644 index 00000000..b53d8e23 --- /dev/null +++ b/packages/plugins/rum/src/types.ts @@ -0,0 +1,26 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +import type { GetPluginsOptionsWithCWD } from '@dd/core/types'; + +import type { CONFIG_KEY } from './constants'; + +export type RumOptions = { + disabled?: boolean; + sourcemaps?: { + basePath: string; + dryRun?: boolean; + maxConcurrency?: number; + minifiedPathPrefix?: string; + releaseVersion: string; + }; +}; + +export interface RumOptionsEnabled extends RumOptions { + disabled?: false; +} + +export interface OptionsWithRumEnabled extends GetPluginsOptionsWithCWD { + [CONFIG_KEY]: RumOptionsEnabled; +} diff --git a/packages/plugins/rum/tsconfig.json b/packages/plugins/rum/tsconfig.json new file mode 100644 index 00000000..6c1d3065 --- /dev/null +++ b/packages/plugins/rum/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "baseUrl": "./", + "rootDir": "./", + "outDir": "./dist" + }, + "include": ["**/*"], + "exclude": ["dist", "node_modules"] +} \ No newline at end of file diff --git a/packages/tests/src/plugins/rum/index.test.ts b/packages/tests/src/plugins/rum/index.test.ts new file mode 100644 index 00000000..d897f427 --- /dev/null +++ b/packages/tests/src/plugins/rum/index.test.ts @@ -0,0 +1,51 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +import fs from 'fs'; +import path from 'path'; + +import { runBundlers } from '../../helpers'; + +// Mock log function. +const logFn = jest.fn((originalLogFn, ...args: any[]) => { + const [text, ...rest] = args; + originalLogFn(`[MOCKED] ${text}`, ...rest); +}); + +jest.mock('@dd/core/log', () => { + return { + getLogFn: (...args: any[]) => { + const { getLogFn: original } = jest.requireActual('@dd/core/log'); + return (...argsLogs: any[]) => { + logFn(original(...args), ...argsLogs); + }; + }, + }; +}); + +// Some paths. +const entry = path.resolve(__dirname, './fixtures/index.js'); +const destination = path.resolve(__dirname, './fixtures/dist'); + +describe('RUM Plugin', () => { + afterAll(() => { + // Clean files + fs.rmSync(destination, { + recursive: true, + force: true, + }); + }); + + test('It should log at the end of the build', async () => { + // Build everything. + const results = await runBundlers({ entry, destination }, { rum: { sourcemaps: {} } }); + + // Assert logs. + expect(logFn).toHaveBeenNthCalledWith( + results.length, + expect.any(Function), + expect.any(String), + ); + }); +});