-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[plugin] RUM plugin #78
Changes from 4 commits
30871ce
fb56bc8
e824eef
263640f
19e3862
38bc7d7
e69c1b8
8d90ef3
9271c7c
a9ce05f
afb82ea
65eea4a
12508da
7d6f49d
5766384
07af3f4
19fd428
d98411a
b1ceafe
1b54c59
f36076c
f4c6b67
78d4c25
794287b
7b75f29
62e986b
08ad0d4
9412e71
62511af
b7ac51c
6b38aa0
7a0a011
f7aa680
0ca8c30
14d5160
94439e3
e7e87c3
7bc1843
5b2192e
b8a4b48
5fc71c0
8fe118c
22db40c
35aa4a6
54ab14b
b61d5b5
48bf921
92f7158
b99b3c9
f86c49e
0a37000
69bcdc5
08b9010
8865781
5952bad
b2ca98d
a92830f
d6aaea2
872ab89
500f410
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# RUM Plugin <!-- #omit in toc --> | ||
|
||
Interact with our Real User Monitoring product (RUM) in Datadog directly from your build system. | ||
|
||
<!-- The title and the following line will both be added to the root README.md --> | ||
|
||
## Table of content <!-- #omit in toc --> | ||
|
||
<!-- This is auto generated with yarn cli integrity --> | ||
|
||
<!-- #toc --> | ||
- [Configuration](#configuration) | ||
<!-- #toc --> | ||
|
||
## Configuration | ||
|
||
```ts | ||
rum?: { | ||
disabled?: boolean; | ||
sourcemaps?: { | ||
basePath: string; | ||
dryRun?: boolean; | ||
maxConcurrency?: number; | ||
minifiedPathPrefix?: string; | ||
releaseVersion: string; | ||
service: string; | ||
}; | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"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", | ||
"./sourcemaps/*": "./src/sourcemaps/*.ts", | ||
"./*": "./src/*.ts" | ||
}, | ||
"scripts": { | ||
"typecheck": "tsc --noEmit" | ||
}, | ||
"dependencies": { | ||
"@dd/core": "workspace:*", | ||
"async-retry": "1.3.3", | ||
"chalk": "2.3.1", | ||
"form-data": "4.0.0", | ||
"glob": "7.1.6", | ||
"outdent": "0.8.0", | ||
"p-queue": "6.6.2", | ||
"unplugin": "1.10.1" | ||
}, | ||
"devDependencies": { | ||
"@types/async-retry": "1.4.8" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// 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 { getLogger } from '@dd/core/log'; | ||
import type { GlobalContext, GetPlugins } from '@dd/core/types'; | ||
|
||
import { PLUGIN_NAME } from './constants'; | ||
import { uploadSourcemaps } from './sourcemaps'; | ||
import type { OptionsWithRum, RumOptions, RumOptionsWithSourcemaps } from './types'; | ||
import { validateOptions } from './validate'; | ||
|
||
export { CONFIG_KEY, PLUGIN_NAME } from './constants'; | ||
|
||
export const helpers = { | ||
// Add the helpers you'd like to expose here. | ||
}; | ||
Comment on lines
+15
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we remove this? It seems like it's not used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Haha, I was just thinking of this, I think right now we can't remove it, as the publish script expect all the plugins to have this. |
||
|
||
export type types = { | ||
// Add the types you'd like to expose here. | ||
RumOptions: RumOptions; | ||
OptionsWithRum: OptionsWithRum; | ||
}; | ||
|
||
export const getPlugins: GetPlugins<OptionsWithRum> = ( | ||
opts: OptionsWithRum, | ||
context: GlobalContext, | ||
) => { | ||
// Verify configuration. | ||
const rumOptions = validateOptions(opts); | ||
return [ | ||
{ | ||
name: PLUGIN_NAME, | ||
async writeBundle() { | ||
if (rumOptions.disabled) { | ||
return; | ||
} | ||
|
||
const log = getLogger(opts.logLevel, PLUGIN_NAME); | ||
if (rumOptions.sourcemaps) { | ||
// Need the "as" because Typescript doesn't understand that we've already checked for sourcemaps. | ||
await uploadSourcemaps(rumOptions as RumOptionsWithSourcemaps, context, log); | ||
} | ||
}, | ||
}, | ||
]; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// 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 chalk from 'chalk'; | ||
import glob from 'glob'; | ||
import path from 'path'; | ||
|
||
import type { RumSourcemapsOptionsWithDefaults, Sourcemap } from '../types'; | ||
|
||
type PartialSourcemap = Pick<Sourcemap, 'minifiedFilePath' | 'minifiedUrl' | 'relativePath'>; | ||
|
||
const getGlobPattern = (basePath: string) => { | ||
// Normalizing the basePath to resolve .. and . | ||
// Always using the posix version to avoid \ on Windows. | ||
const newPath = path.posix.normalize(basePath); | ||
return path.join(newPath, '**/*.@(js|mjs).map'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: Should the pattern be configurable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I followed I prefer to cross that bridge when we get there for simplicity's sake. |
||
}; | ||
|
||
const decomposePath = ( | ||
options: RumSourcemapsOptionsWithDefaults, | ||
sourcemapFilePath: string, | ||
): PartialSourcemap => { | ||
if (path.extname(sourcemapFilePath) !== '.map') { | ||
throw new Error(`The file ${chalk.green.bold(sourcemapFilePath)} is not a sourcemap.`); | ||
} | ||
|
||
const minifiedFilePath = sourcemapFilePath.replace(/\.map$/, ''); | ||
const relativePath = minifiedFilePath.replace(options.basePath, ''); | ||
const minifiedUrl = options.minifiedPathPrefix | ||
? path.join(options.minifiedPathPrefix, relativePath) | ||
: relativePath; | ||
|
||
return { | ||
minifiedFilePath, | ||
minifiedUrl, | ||
relativePath, | ||
}; | ||
}; | ||
|
||
export const getSourcemapsFiles = (options: RumSourcemapsOptionsWithDefaults): Sourcemap[] => { | ||
const globPattern = getGlobPattern(options.basePath); | ||
const sourcemapFilesList = glob.sync(globPattern); | ||
const sourcemapFiles = sourcemapFilesList.map((sourcemapFilePath) => { | ||
return { | ||
...decomposePath(options, sourcemapFilePath), | ||
sourcemapFilePath, | ||
minifiedPathPrefix: options.minifiedPathPrefix, | ||
}; | ||
}); | ||
|
||
return sourcemapFiles; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// 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 { Logger } from '@dd/core/log'; | ||
import type { GlobalContext } from '@dd/core/types'; | ||
import chalk from 'chalk'; | ||
import { outdent } from 'outdent'; | ||
|
||
import type { RumOptionsWithSourcemaps } from '../types'; | ||
|
||
import { getSourcemapsFiles } from './files'; | ||
import { sendSourcemaps } from './sender'; | ||
|
||
export const uploadSourcemaps = async ( | ||
options: RumOptionsWithSourcemaps, | ||
context: GlobalContext, | ||
log: Logger, | ||
) => { | ||
// Show a pretty summary of the configuration. | ||
const green = chalk.green.bold; | ||
const configurationString = Object.entries(options.sourcemaps) | ||
.map(([key, value]) => ` - ${key}: ${green(value.toString())}`) | ||
.join('\n'); | ||
|
||
const summary = outdent` | ||
Uploading sourcemap with this configuration: | ||
${configurationString} | ||
`; | ||
|
||
log(summary); | ||
|
||
// Gather the sourcemaps files. | ||
const sourcemaps = getSourcemapsFiles(options.sourcemaps); | ||
// Send everything. | ||
await sendSourcemaps(sourcemaps, options.sourcemaps, context, log); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably fix these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we have a good team to add for RUM?
This one seemed a bit too wide maybe.