Skip to content

Commit cdbd040

Browse files
committed
Merge branch 'master' into congyao/add-sourcemaps-and-telemetry
2 parents 92fd9fb + cb65ff9 commit cdbd040

27 files changed

Lines changed: 918 additions & 403 deletions

File tree

.github/CODEOWNERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ packages/plugins/custom-hooks @yoannmoin
3333

3434
# True End
3535
packages/plugins/true-end @yoannmoinet
36+
37+
# Async Queue
38+
packages/plugins/async-queue @yoannmoinet

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ type GlobalContext = {
206206
// The list of all the plugin instances that are currently running in the ecosystem.
207207
plugins: Plugin[];
208208
// Send a log to Datadog.
209-
sendLog: (message: string, context?: Record<string, string>) => Promise<void>;
209+
sendLog: ({ message: string, context?: Record<string, string> }) => Promise<void>;
210210
// The start time of the build.
211211
start: number;
212212
// The version of the plugin.

packages/core/src/helpers/log.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 { HOST_NAME } from '../constants';
6+
import type { GlobalData, DdLogOptions } from '../types';
7+
8+
import { doRequest } from './request';
9+
10+
export const INTAKE_PATH = 'v1/input/pub44d5f4eb86e1392037b7501f7adc540e';
11+
export const INTAKE_HOST = 'browser-http-intake.logs.datadoghq.com';
12+
13+
export const getSendLog =
14+
(data: GlobalData) =>
15+
({ message, context }: DdLogOptions): Promise<void> => {
16+
return doRequest({
17+
// Don't delay the build too much on error.
18+
retries: 2,
19+
minTimeout: 100,
20+
url: `https://${INTAKE_HOST}/${INTAKE_PATH}`,
21+
method: 'POST',
22+
type: 'json',
23+
getData: async () => {
24+
const payload = {
25+
ddsource: data.packageName || HOST_NAME,
26+
message,
27+
service: 'build-plugins',
28+
team: 'language-foundations',
29+
env: data.env,
30+
version: data.version,
31+
bundler: {
32+
name: data.bundler.name,
33+
version: data.bundler.version,
34+
},
35+
metadata: data.metadata,
36+
...context,
37+
};
38+
return {
39+
data: JSON.stringify(payload),
40+
headers: {
41+
'Content-Type': 'application/json',
42+
},
43+
};
44+
},
45+
});
46+
};

packages/core/src/types.ts

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ export type SerializedEntry = Assign<Entry, { inputs: string[]; outputs: string[
5656
export type SerializedInput = Assign<Input, { dependencies: string[]; dependents: string[] }>;
5757
export type SerializedOutput = Assign<Output, { inputs: string[] }>;
5858

59+
export type Log = {
60+
bundler?: BundlerFullName;
61+
pluginName: string;
62+
type: LogLevel;
63+
message: string;
64+
time: number;
65+
};
5966
export type LogTags = string[];
6067
export type Timer = {
6168
label: string;
@@ -71,18 +78,12 @@ export type BuildMetadata = {
7178
};
7279

7380
export type BuildReport = {
74-
bundler: Omit<BundlerReport, 'outDir' | 'rawConfig'>;
75-
errors: string[];
76-
warnings: string[];
77-
logs: {
78-
bundler: BundlerFullName;
79-
pluginName: string;
80-
type: LogLevel;
81-
message: string;
82-
time: number;
83-
}[];
84-
metadata: BuildMetadata;
85-
timings: Timer[];
81+
bundler: GlobalData['bundler'];
82+
errors: GlobalStores['errors'];
83+
warnings: GlobalStores['warnings'];
84+
logs: GlobalStores['logs'];
85+
timings: GlobalStores['timings'];
86+
metadata: GlobalData['metadata'];
8687
entries?: Entry[];
8788
inputs?: Input[];
8889
outputs?: Output[];
@@ -104,13 +105,9 @@ export type SerializedBuildReport = Assign<
104105

105106
export type BundlerFullName = (typeof FULL_NAME_BUNDLERS)[number];
106107
export type BundlerName = (typeof SUPPORTED_BUNDLERS)[number];
107-
export type BundlerReport = {
108-
name: BundlerName;
109-
fullName: BundlerFullName;
108+
export type BundlerReport = GlobalData['bundler'] & {
110109
outDir: string;
111110
rawConfig?: any;
112-
variant?: string; // e.g. Major version of the bundler (webpack 4, webpack 5)
113-
version: string;
114111
};
115112

116113
export type InjectedValue = string | (() => Promise<string>);
@@ -140,13 +137,21 @@ export type TimeLog = (
140137
opts?: { level?: LogLevel; start?: boolean | number; log?: boolean; tags?: LogTags },
141138
) => TimeLogger;
142139
export type GetLogger = (name: string) => Logger;
140+
export type LogOptions = { forward?: boolean };
141+
export type LoggerFn = (text: any, opts?: LogOptions) => void;
143142
export type Logger = {
144143
getLogger: GetLogger;
145144
time: TimeLog;
146-
error: (text: any) => void;
147-
warn: (text: any) => void;
148-
info: (text: any) => void;
149-
debug: (text: any) => void;
145+
error: LoggerFn;
146+
warn: LoggerFn;
147+
info: LoggerFn;
148+
debug: LoggerFn;
149+
};
150+
type RestContext = string | string[] | number | boolean;
151+
export type LogData = Record<string, RestContext | Record<string, RestContext>>;
152+
export type DdLogOptions = {
153+
message: string;
154+
context?: LogData;
150155
};
151156
export type Env = (typeof ALL_ENVS)[number];
152157
export type TriggerHook<R> = <K extends keyof CustomHooks>(
@@ -159,16 +164,17 @@ export type GlobalContext = {
159164
build: BuildReport;
160165
bundler: BundlerReport;
161166
cwd: string;
162-
env: Env;
167+
env: GlobalData['env'];
163168
getLogger: GetLogger;
164169
git?: RepositoryData;
165170
hook: TriggerHook<void>;
166171
inject: (item: ToInjectItem) => void;
167172
pluginNames: string[];
168173
plugins: (PluginOptions | CustomPluginOptions)[];
169-
sendLog: (message: string, ctx?: any) => Promise<void>;
174+
queue: (promise: Promise<any>) => void;
175+
sendLog: (args: DdLogOptions) => Promise<void>;
170176
start: number;
171-
version: string;
177+
version: GlobalData['version'];
172178
};
173179

174180
export type FactoryMeta = {
@@ -206,6 +212,8 @@ export type GetPluginsArg = {
206212
bundler: any;
207213
context: GlobalContext;
208214
options: Options;
215+
data: GlobalData;
216+
stores: GlobalStores;
209217
};
210218
export type GetPlugins = (arg: GetPluginsArg) => PluginOptions[];
211219
export type GetCustomPlugins = (arg: GetPluginsArg) => CustomPluginOptions[];
@@ -265,3 +273,24 @@ export type FileValidity = {
265273
empty: boolean;
266274
exists: boolean;
267275
};
276+
277+
export type GlobalData = {
278+
bundler: {
279+
name: BundlerName;
280+
fullName: BundlerFullName;
281+
variant: string; // e.g. Major version of the bundler (webpack 4, webpack 5)
282+
version: string;
283+
};
284+
env: Env;
285+
metadata: BuildMetadata;
286+
packageName: string;
287+
version: string;
288+
};
289+
290+
export type GlobalStores = {
291+
errors: string[];
292+
logs: Log[];
293+
queue: Promise<any>[];
294+
timings: Timer[];
295+
warnings: string[];
296+
};

packages/factory/README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This is used to aggregate all the plugins and expose them to the bundler.
1010
<!-- #toc -->
1111
- [Internal Plugins](#internal-plugins)
1212
- [Analytics](#analytics)
13+
- [Async Queue](#async-queue)
1314
- [Build Report](#build-report)
1415
- [Bundler Report](#bundler-report)
1516
- [Custom Hooks](#custom-hooks)
@@ -35,11 +36,18 @@ Most of the time they will interact via the global context.
3536

3637
> Send some analytics data to Datadog internally.
3738
> <br/>
38-
> It gives you acces to the `context.sendLog()` function.
39+
> Will send a log at the beginning of a build.
3940
4041
#### [📝 Full documentation ➡️](/packages/plugins/analytics#readme)
4142

4243

44+
### Async Queue
45+
46+
> An internal queue for async actions that we want to finish before quitting the build.
47+
48+
#### [📝 Full documentation ➡️](/packages/plugins/async-queue#readme)
49+
50+
4351
### Build Report
4452

4553
> This will populate `context.build` with a bunch of data coming from the build.
@@ -271,7 +279,7 @@ type GlobalContext = {
271279
// The list of all the plugin instances that are currently running in the ecosystem.
272280
plugins: Plugin[];
273281
// Send a log to Datadog.
274-
sendLog: (message: string, context?: Record<string, string>) => Promise<void>;
282+
sendLog: ({ message: string, context?: Record<string, string> }) => Promise<void>;
275283
// The start time of the build.
276284
start: number;
277285
// The version of the plugin.
@@ -281,7 +289,7 @@ type GlobalContext = {
281289

282290
> [!NOTE]
283291
> Some parts of the context are only available after certain hooks:
284-
> - all the helper functions, `asyncHook`, `getLogger`, `hook`, `inject`, `sendLog`, are available in the `init` hook.
292+
> - some helper functions, `asyncHook`, `hook`, `inject` and `queue` are available in the `init` hook.
285293
> - `cwd` is available in the `cwd` hook.
286294
> - `context.bundler.rawConfig` is available in the `bundlerReport` hook.
287295
> - `context.build.*` is available in the `buildReport` hook.

packages/factory/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@dd/core": "workspace:*",
2323
"@dd/error-tracking-plugin": "workspace:*",
2424
"@dd/internal-analytics-plugin": "workspace:*",
25+
"@dd/internal-async-queue-plugin": "workspace:*",
2526
"@dd/internal-build-report-plugin": "workspace:*",
2627
"@dd/internal-bundler-report-plugin": "workspace:*",
2728
"@dd/internal-custom-hooks-plugin": "workspace:*",

packages/factory/src/helpers/context.ts

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
// This product includes software developed at Datadog (https://www.datadoghq.com/).
33
// Copyright 2019-Present Datadog, Inc.
44

5-
import { ALL_ENVS } from '@dd/core/constants';
5+
import { getSendLog } from '@dd/core/helpers/log';
66
import type {
77
BuildReport,
8-
BundlerFullName,
9-
BundlerName,
10-
Env,
11-
FactoryMeta,
128
GlobalContext,
9+
GlobalData,
10+
GlobalStores,
1311
OptionsWithDefaults,
1412
} from '@dd/core/types';
1513

@@ -18,36 +16,23 @@ import { getLoggerFactory } from './logger';
1816
export const getContext = ({
1917
start,
2018
options,
21-
bundlerName,
22-
bundlerVersion,
23-
version,
19+
data,
20+
stores,
2421
}: {
2522
start: number;
2623
options: OptionsWithDefaults;
27-
bundlerName: BundlerName;
28-
bundlerVersion: string;
29-
version: FactoryMeta['version'];
24+
data: GlobalData;
25+
stores: GlobalStores;
3026
}): GlobalContext => {
3127
const cwd = process.cwd();
32-
const variant = bundlerName === 'webpack' ? bundlerVersion.split('.')[0] : '';
3328
const build: BuildReport = {
34-
errors: [],
35-
warnings: [],
36-
logs: [],
37-
metadata: options.metadata || {},
38-
timings: [],
39-
bundler: {
40-
name: bundlerName,
41-
fullName: `${bundlerName}${variant}` as BundlerFullName,
42-
variant,
43-
version: bundlerVersion,
44-
},
29+
errors: stores.errors,
30+
warnings: stores.warnings,
31+
logs: stores.logs,
32+
metadata: data.metadata,
33+
timings: stores.timings,
34+
bundler: data.bundler,
4535
};
46-
47-
// Use "production" if there is no env passed.
48-
const passedEnv: Env = (process.env.BUILD_PLUGINS_ENV as Env) || 'production';
49-
// Fallback to "development" if the passed env is wrong.
50-
const env: Env = ALL_ENVS.includes(passedEnv) ? passedEnv : 'development';
5136
const context: GlobalContext = {
5237
auth: options.auth,
5338
pluginNames: [],
@@ -59,8 +44,8 @@ export const getContext = ({
5944
build,
6045
// This will be updated in the bundler-report plugin once we have the configuration.
6146
cwd,
62-
env,
63-
getLogger: getLoggerFactory(build, options.logLevel),
47+
env: data.env,
48+
getLogger: getLoggerFactory(data, stores, options.logLevel),
6449
// This will be updated in the injection plugin on initialization.
6550
asyncHook: () => {
6651
throw new Error('AsyncHook function called before it was initialized.');
@@ -72,12 +57,14 @@ export const getContext = ({
7257
inject: () => {
7358
throw new Error('Inject function called before it was initialized.');
7459
},
75-
sendLog: () => {
76-
throw new Error('SendLog function called before it was initialized.');
77-
},
7860
plugins: [],
61+
// This will be updated in the async-queue plugin on initialization.
62+
queue: () => {
63+
throw new Error('Queue function called before it was initialized.');
64+
},
65+
sendLog: getSendLog(data),
7966
start,
80-
version,
67+
version: data.version,
8168
};
8269

8370
return context;

0 commit comments

Comments
 (0)