Skip to content

Commit 50c62ad

Browse files
committed
createBrowserRouter auto instrumentation
1 parent 3f8d8df commit 50c62ad

File tree

11 files changed

+155
-33
lines changed

11 files changed

+155
-33
lines changed

packages/core/src/types.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,18 @@ export type BundlerReport = {
7474
version: string;
7575
};
7676

77-
export type ToInjectItem = { type: 'file' | 'code'; value: string; fallback?: ToInjectItem };
77+
export type InjectedValue = string | (() => Promise<string>);
78+
export enum InjectPosition {
79+
BEFORE,
80+
MIDDLE,
81+
AFTER,
82+
}
83+
export type ToInjectItem = {
84+
type: 'file' | 'code';
85+
value: InjectedValue;
86+
position?: InjectPosition;
87+
fallback?: ToInjectItem;
88+
};
7889

7990
export type GetLogger = (name: string) => Logger;
8091
export type Logger = {
@@ -133,7 +144,7 @@ export interface Options extends BaseOptions {
133144
customPlugins?: GetCustomPlugins;
134145
}
135146

136-
export type GetPluginsOptions = Required<BaseOptions>;
147+
export type GetPluginsOptions = BaseOptions;
137148
export type OptionsWithDefaults = Assign<Options, GetPluginsOptions>;
138149

139150
export type PluginName = `datadog-${Lowercase<string>}-plugin`;

packages/plugins/rum/src/index.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,37 @@ export const getPlugins: GetPlugins<OptionsWithRum> = (
2222
log: Logger,
2323
) => {
2424
// Verify configuration.
25+
<<<<<<< HEAD
2526
const rumOptions = validateOptions(opts, log);
27+
=======
28+
const options = validateOptions(opts, log);
29+
30+
if (options.sdk) {
31+
// Inject the SDK from the CDN.
32+
context.inject({
33+
type: 'file',
34+
position: InjectPosition.BEFORE,
35+
value: 'https://www.datadoghq-browser-agent.com/us1/v5/datadog-rum.js',
36+
});
37+
38+
if (options.react) {
39+
// Inject the rum-react-plugin.
40+
// NOTE: These files are built from "@dd/tools/rollupConfig.mjs" and available in the distributed package.
41+
context.inject({
42+
type: 'file',
43+
position: InjectPosition.MIDDLE,
44+
value: path.join(__dirname, './rum-react-plugin.js'),
45+
});
46+
}
47+
48+
context.inject({
49+
type: 'code',
50+
position: InjectPosition.MIDDLE,
51+
value: getInjectionValue(options as RumOptionsWithSdk, context),
52+
});
53+
}
54+
55+
>>>>>>> 2aae126 (createBrowserRouter auto instrumentation)
2656
return [
2757
{
2858
name: 'datadog-rum-sourcemaps-plugin',
@@ -64,7 +94,11 @@ export const getPlugins: GetPlugins<OptionsWithRum> = (
6494
return updatedCode;
6595
},
6696
transformInclude(id) {
67-
return id.match(new RegExp(/.*\.(js|jsx|ts|tsx)$/)) !== null;
97+
return (
98+
// @ts-ignore
99+
options?.react?.router === true &&
100+
id.match(new RegExp(/.*\.(js|jsx|ts|tsx)$/)) !== null
101+
);
68102
},
69103
},
70104
];

packages/plugins/rum/src/sdk.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License.
2+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
3+
// Copyright 2019-Present Datadog, Inc.
4+
5+
import { doRequest } from '@dd/core/helpers';
6+
import type { GlobalContext, InjectedValue } from '@dd/core/types';
7+
8+
import type { RumOptionsWithDefaults, RumOptionsWithSdk } from './types';
9+
10+
type RumAppResponse = {
11+
data: {
12+
attributes: {
13+
client_token: string;
14+
};
15+
};
16+
};
17+
18+
const getContent = (opts: RumOptionsWithDefaults) => {
19+
const pluginContent = opts.react
20+
? // @ts-ignore
21+
`, plugins: [reactPlugin({router: ${opts.react.router}})]`
22+
: '';
23+
const sessionReplayStartCommand = opts.startSessionReplayRecording
24+
? 'DD_RUM.startSessionReplayRecording();\n'
25+
: '';
26+
27+
return `DD_RUM.init({${JSON.stringify(opts.sdk).replace(/(^{|}$)/g, '')}${pluginContent}});${sessionReplayStartCommand}
28+
`;
29+
};
30+
31+
export const getInjectionValue = (
32+
options: RumOptionsWithSdk,
33+
context: GlobalContext,
34+
): InjectedValue => {
35+
const sdkOpts = options.sdk;
36+
// We already have the clientToken, we can inject it directly.
37+
if (sdkOpts.clientToken) {
38+
return getContent(options);
39+
}
40+
41+
// Let's fetch the clientToken from the API.
42+
if (!context.auth?.apiKey || !context.auth?.appKey) {
43+
throw new Error('Missing auth.apiKey and/or auth.appKey to fetch clientToken.');
44+
}
45+
46+
let clientToken: string;
47+
48+
return async () => {
49+
try {
50+
// Fetch the client token from the API.
51+
const appResponse = await doRequest<RumAppResponse>({
52+
url: `https://api.datadoghq.com/api/v2/rum/applications/${sdkOpts.applicationId}`,
53+
type: 'json',
54+
auth: context.auth,
55+
});
56+
57+
clientToken = appResponse.data?.attributes?.client_token;
58+
} catch (e: any) {
59+
// Could not fetch the clientToken.
60+
// Let's crash the build.
61+
throw new Error(`Could not fetch the clientToken: ${e.message}`);
62+
}
63+
64+
// Still no clientToken.
65+
if (!clientToken) {
66+
throw new Error('Missing clientToken in the API response.');
67+
}
68+
69+
return getContent({
70+
...options,
71+
sdk: {
72+
clientToken,
73+
...sdkOpts,
74+
},
75+
});
76+
};
77+
};

packages/plugins/rum/src/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,26 @@ export type RumSourcemapsOptions = {
2020

2121
export type RumOptions = {
2222
disabled?: boolean;
23+
<<<<<<< HEAD
2324
sourcemaps?: RumSourcemapsOptions;
25+
=======
26+
sdk?: SDKOptions;
27+
react?: ReactOptions;
28+
startSessionReplayRecording?: boolean;
29+
>>>>>>> 2aae126 (createBrowserRouter auto instrumentation)
2430
};
2531

2632
export type RumSourcemapsOptionsWithDefaults = Required<RumSourcemapsOptions>;
2733

2834
export type RumOptionsWithDefaults = {
2935
disabled?: boolean;
36+
<<<<<<< HEAD
3037
sourcemaps?: RumSourcemapsOptionsWithDefaults;
38+
=======
39+
sdk?: SDKOptionsWithDefaults;
40+
react?: ReactOptionsWithDefaults;
41+
startSessionReplayRecording?: boolean;
42+
>>>>>>> 2aae126 (createBrowserRouter auto instrumentation)
3143
};
3244

3345
export type RumOptionsWithSourcemaps = {

packages/published/esbuild-plugin/package.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
"main": "./dist/src/index.js",
2222
"module": "./dist/src/index.mjs",
2323
"exports": {
24-
"./package.json": "./package.json",
25-
".": {
26-
"import": "./dist/src/index.mjs",
27-
"require": "./dist/src/index.js",
28-
"types": "./dist/src/index.d.ts"
29-
}
24+
".": "./src/index.ts"
3025
},
3126
"publishConfig": {
3227
"access": "public",

packages/published/rollup-plugin/package.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
"main": "./dist/src/index.js",
2222
"module": "./dist/src/index.mjs",
2323
"exports": {
24-
"./package.json": "./package.json",
25-
".": {
26-
"import": "./dist/src/index.mjs",
27-
"require": "./dist/src/index.js",
28-
"types": "./dist/src/index.d.ts"
29-
}
24+
".": "./src/index.ts"
3025
},
3126
"publishConfig": {
3227
"access": "public",

packages/published/rspack-plugin/package.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
"main": "./dist/src/index.js",
2222
"module": "./dist/src/index.mjs",
2323
"exports": {
24-
"./package.json": "./package.json",
25-
".": {
26-
"import": "./dist/src/index.mjs",
27-
"require": "./dist/src/index.js",
28-
"types": "./dist/src/index.d.ts"
29-
}
24+
".": "./src/index.ts"
3025
},
3126
"publishConfig": {
3227
"access": "public",

packages/published/vite-plugin/package.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
"main": "./dist/src/index.js",
2222
"module": "./dist/src/index.mjs",
2323
"exports": {
24-
"./package.json": "./package.json",
25-
".": {
26-
"import": "./dist/src/index.mjs",
27-
"require": "./dist/src/index.js",
28-
"types": "./dist/src/index.d.ts"
29-
}
24+
".": "./src/index.ts"
3025
},
3126
"publishConfig": {
3227
"access": "public",

packages/published/webpack-plugin/package.json

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
"main": "./dist/src/index.js",
2222
"module": "./dist/src/index.mjs",
2323
"exports": {
24-
"./package.json": "./package.json",
25-
".": {
26-
"import": "./dist/src/index.mjs",
27-
"require": "./dist/src/index.js",
28-
"types": "./dist/src/index.d.ts"
29-
}
24+
".": "./src/index.ts"
3025
},
3126
"publishConfig": {
3227
"access": "public",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { createBrowserRouter } from '@datadog/browser-rum-react/react-router-v6';
2+
import { reactPlugin } from '@datadog/browser-rum-react';
3+
4+
(() => {
5+
const globalAny: any = global;
6+
globalAny.DD_RUM = globalAny.DD_RUM || {};
7+
globalAny.reactPlugin = reactPlugin;
8+
globalAny.DD_RUM.createBrowserRouter = createBrowserRouter;
9+
})();

0 commit comments

Comments
 (0)