Skip to content

Commit 819da60

Browse files
authored
Merge pull request #109 from DataDog/yoann/refactor-logger
[refactor] Better integrated logger.
2 parents b7f0408 + 0956b29 commit 819da60

File tree

39 files changed

+404
-197
lines changed

39 files changed

+404
-197
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ stateDiagram-v2
114114
}
115115
116116
state core {
117-
getLogger()
118117
sharedHelpers
119118
sharedConstants
120119
types
@@ -163,7 +162,7 @@ Bootstrapping all the files you'll need to start coding.
163162
yarn cli create-plugin
164163
```
165164

166-
Then learn more about what you can use from [the ecosystem](/packages/core).
165+
Then learn more about what you can use from [the ecosystem](/packages/factory).
167166

168167
## Tests
169168

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ type GlobalContext = {
372372
writeDuration?: number;
373373
};
374374
cwd: string;
375+
getLogger: (name: string) => [Logger](/packages/factory/src/helpers.ts);
375376
// Added in `buildStart`.
376377
git?: {
377378
hash: string;

packages/core/src/log.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.

packages/core/src/types.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export type SerializedOutput = Assign<Output, { inputs: string[] }>;
4141
export type BuildReport = {
4242
errors: string[];
4343
warnings: string[];
44+
logs: { pluginName: string; type: LogLevel; message: string; time: number }[];
4445
entries?: Entry[];
4546
inputs?: Input[];
4647
outputs?: Output[];
@@ -73,12 +74,20 @@ export type BundlerReport = {
7374

7475
export type ToInjectItem = { type: 'file' | 'code'; value: string; fallback?: ToInjectItem };
7576

77+
export type Logger = {
78+
error: (text: any) => void;
79+
warn: (text: any) => void;
80+
info: (text: any) => void;
81+
debug: (text: any) => void;
82+
};
83+
export type GetLogger = (name: string) => Logger;
7684
export type GlobalContext = {
7785
auth?: AuthOptions;
7886
inject: (item: ToInjectItem) => void;
7987
bundler: BundlerReport;
8088
build: BuildReport;
8189
cwd: string;
90+
getLogger: GetLogger;
8291
git?: RepositoryData;
8392
pluginNames: string[];
8493
start: number;
@@ -103,13 +112,13 @@ export type AuthOptions = {
103112
apiKey?: string;
104113
};
105114

106-
export interface GetPluginsOptions {
115+
export interface BaseOptions {
107116
auth?: AuthOptions;
108117
disableGit?: boolean;
109118
logLevel?: LogLevel;
110119
}
111120

112-
export interface Options extends GetPluginsOptions {
121+
export interface Options extends BaseOptions {
113122
// Each product should have a unique entry.
114123
// #types-injection-marker
115124
[rum.CONFIG_KEY]?: RumOptions;
@@ -118,6 +127,9 @@ export interface Options extends GetPluginsOptions {
118127
customPlugins?: GetCustomPlugins;
119128
}
120129

130+
export type GetPluginsOptions = Required<BaseOptions>;
131+
export type OptionsWithDefaults = Assign<Options, GetPluginsOptions>;
132+
121133
export type PluginName = `datadog-${Lowercase<string>}-plugin`;
122134

123135
type Data = { data: BodyInit; headers?: Record<string, string> };

packages/factory/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This is used to aggregate all the plugins and expose them to the bundler.
1313
- [Bundler Report](#bundler-report)
1414
- [Git](#git)
1515
- [Injection](#injection)
16+
- [Logger](#logger)
1617
- [Global Context](#global-context)
1718
<!-- #toc -->
1819

@@ -49,6 +50,29 @@ Most of the time they will interact via the global context.
4950
<kbd>[📝 Full documentation ➡️](/packages/plugins/injection#readme)</kbd>
5051
<!-- #internal-plugins-list -->
5152

53+
## Logger
54+
55+
If you need to log anything into the console you'll have to use the global Logger.
56+
Simply instantiate your logger in your plugin's initialization.
57+
58+
```typescript
59+
// ./packages/plugins/my-plugin/index.ts
60+
[...]
61+
62+
export const getMyPlugins = (context: GlobalContext) => {
63+
const logger = context.getLogger('my-plugin');
64+
};
65+
```
66+
67+
Then you can either use one of the level logger methods:
68+
69+
```typescript
70+
logger.warn('This is also a warning');
71+
logger.error('This is an error');
72+
logger.info('This is an info');
73+
logger.debug('This is a debug message');
74+
```
75+
5276
## Global Context
5377

5478
A global, shared context within the build plugins ecosystem.<br/>
@@ -106,6 +130,7 @@ type GlobalContext = {
106130
writeDuration?: number;
107131
};
108132
cwd: string;
133+
getLogger: (name: string) => [Logger](/packages/factory/src/helpers.ts);
109134
// Added in `buildStart`.
110135
git?: {
111136
hash: string;

packages/factory/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@dd/internal-injection-plugin": "workspace:*",
2424
"@dd/rum-plugin": "workspace:*",
2525
"@dd/telemetry-plugin": "workspace:*",
26+
"chalk": "2.3.1",
2627
"unplugin": "1.16.0"
2728
}
2829
}

packages/factory/src/helpers.ts

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,95 @@
33
// Copyright 2019-Present Datadog, Inc.
44

55
import type {
6+
BuildReport,
67
BundlerFullName,
78
BundlerName,
89
FactoryMeta,
10+
GetLogger,
911
GlobalContext,
12+
LogLevel,
1013
Options,
14+
OptionsWithDefaults,
1115
ToInjectItem,
1216
} from '@dd/core/types';
17+
import c from 'chalk';
18+
19+
const logPriority: Record<LogLevel, number> = {
20+
debug: 0,
21+
info: 1,
22+
warn: 2,
23+
error: 3,
24+
none: 4,
25+
};
26+
27+
// Exported for testing.
28+
export const getLoggerFactory =
29+
(build: BuildReport, logLevel: LogLevel = 'warn'): GetLogger =>
30+
(name) => {
31+
const log = (text: any, type: LogLevel = 'debug') => {
32+
// By default (debug) we print dimmed.
33+
let color = c.dim;
34+
let logFn = console.log;
35+
36+
if (type === 'error') {
37+
color = c.red;
38+
logFn = console.error;
39+
} else if (type === 'warn') {
40+
color = c.yellow;
41+
logFn = console.warn;
42+
} else if (type === 'info') {
43+
color = c.cyan;
44+
logFn = console.log;
45+
}
46+
47+
const prefix = `[${type}|${name}]`;
48+
49+
// Keep a trace of the log in the build report.
50+
const content = typeof text === 'string' ? text : JSON.stringify(text, null, 2);
51+
build.logs.push({ pluginName: name, type, message: content, time: Date.now() });
52+
if (type === 'error') {
53+
build.errors.push(content);
54+
}
55+
if (type === 'warn') {
56+
build.warnings.push(content);
57+
}
58+
59+
// Only log if the log level is high enough.
60+
if (logPriority[type] >= logPriority[logLevel]) {
61+
logFn(`${color(prefix)} ${content}`);
62+
}
63+
};
64+
65+
return {
66+
error: (text: any) => log(text, 'error'),
67+
warn: (text: any) => log(text, 'warn'),
68+
info: (text: any) => log(text, 'info'),
69+
debug: (text: any) => log(text, 'debug'),
70+
};
71+
};
1372

1473
export const getContext = ({
15-
auth,
74+
options,
1675
bundlerName,
1776
bundlerVersion,
1877
injections,
1978
version,
2079
}: {
21-
auth: Options['auth'];
80+
options: OptionsWithDefaults;
2281
bundlerName: BundlerName;
2382
bundlerVersion: string;
2483
injections: ToInjectItem[];
2584
version: FactoryMeta['version'];
2685
}): GlobalContext => {
2786
const cwd = process.cwd();
2887
const variant = bundlerName === 'webpack' ? bundlerVersion.split('.')[0] : '';
29-
88+
const build: BuildReport = {
89+
errors: [],
90+
warnings: [],
91+
logs: [],
92+
};
3093
const context: GlobalContext = {
31-
auth,
94+
auth: options.auth,
3295
pluginNames: [],
3396
bundler: {
3497
name: bundlerName,
@@ -37,22 +100,20 @@ export const getContext = ({
37100
outDir: cwd,
38101
version: bundlerVersion,
39102
},
40-
build: {
41-
errors: [],
42-
warnings: [],
43-
},
103+
build,
44104
cwd,
45105
inject: (item: ToInjectItem) => {
46106
injections.push(item);
47107
},
108+
getLogger: getLoggerFactory(build, options.logLevel),
48109
start: Date.now(),
49110
version,
50111
};
51112

52113
return context;
53114
};
54115

55-
export const validateOptions = (options: Options = {}): Options => {
116+
export const validateOptions = (options: Options = {}): OptionsWithDefaults => {
56117
return {
57118
auth: {},
58119
disableGit: false,

packages/factory/src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
FactoryMeta,
1717
GlobalContext,
1818
Options,
19+
OptionsWithDefaults,
1920
PluginOptions,
2021
ToInjectItem,
2122
} from '@dd/core/types';
@@ -59,7 +60,7 @@ export const buildPluginFactory = ({
5960
// TODO: Validate API Key and endpoint.
6061
// TODO: Inject a metric logger into the global context.
6162

62-
const options = validateOptions(opts);
63+
const options: OptionsWithDefaults = validateOptions(opts);
6364

6465
// Set the host name for the esbuild plugin.
6566
if (unpluginMetaContext.framework === 'esbuild') {
@@ -69,7 +70,7 @@ export const buildPluginFactory = ({
6970
// Create the global context.
7071
const injections: ToInjectItem[] = [];
7172
const context: GlobalContext = getContext({
72-
auth: options.auth,
73+
options,
7374
bundlerVersion: bundler.version || bundler.VERSION,
7475
bundlerName: unpluginMetaContext.framework as BundlerName,
7576
injections,
@@ -83,10 +84,10 @@ export const buildPluginFactory = ({
8384
const plugins: (PluginOptions | UnpluginOptions)[] = [
8485
// Prefill with our internal plugins.
8586
// #internal-plugins-injection-marker
86-
...getBuildReportPlugins(options, context),
87+
...getBuildReportPlugins(context),
8788
...getBundlerReportPlugins(context),
8889
...getGitPlugins(options, context),
89-
...getInjectionPlugins(bundler, options, context, injections),
90+
...getInjectionPlugins(bundler, context, injections),
9091
// #internal-plugins-injection-marker
9192
];
9293

packages/plugins/build-report/src/esbuild.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
// Copyright 2019-Present Datadog, Inc.
44

55
import { getResolvedPath, isInjectionFile } from '@dd/core/helpers';
6-
import type { Logger } from '@dd/core/log';
7-
import type { Entry, GlobalContext, Input, Output, PluginOptions } from '@dd/core/types';
6+
import type { Logger, Entry, GlobalContext, Input, Output, PluginOptions } from '@dd/core/types';
87
import { glob } from 'glob';
98

109
import { cleanName, getAbsolutePath, getType } from './helpers';
@@ -68,12 +67,16 @@ export const getEsbuildPlugin = (context: GlobalContext, log: Logger): PluginOpt
6867
const entryNames = getEntryNames(entrypoints, context);
6968

7069
build.onEnd((result) => {
71-
context.build.errors = result.errors.map((err) => err.text);
72-
context.build.warnings = result.warnings.map((err) => err.text);
70+
for (const error of result.errors) {
71+
context.build.errors.push(error.text);
72+
}
73+
for (const warning of result.warnings) {
74+
context.build.warnings.push(warning.text);
75+
}
7376

7477
const warn = (warning: string) => {
7578
context.build.warnings.push(warning);
76-
log(warning, 'warn');
79+
log.warn(warning);
7780
};
7881

7982
if (!result.metafile) {

packages/plugins/build-report/src/helpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const serializeBuildReport = (report: BuildReport): SerializedBuildReport
5151
const jsonReport: SerializedBuildReport = {
5252
errors: report.errors,
5353
warnings: report.warnings,
54+
logs: report.logs,
5455
start: report.start,
5556
end: report.end,
5657
duration: report.duration,
@@ -103,6 +104,7 @@ export const unserializeBuildReport = (report: SerializedBuildReport): BuildRepo
103104
const buildReport: BuildReport = {
104105
errors: report.errors,
105106
warnings: report.warnings,
107+
logs: report.logs,
106108
start: report.start,
107109
end: report.end,
108110
duration: report.duration,

0 commit comments

Comments
 (0)