Skip to content

Commit

Permalink
Merge pull request #81 from DataDog/yoann/move-telemetry
Browse files Browse the repository at this point in the history
[telemetry] Move telemetry plugins
  • Loading branch information
yoannmoinet authored Jun 10, 2024
2 parents b7466b3 + 5efe3a0 commit 85330b7
Show file tree
Hide file tree
Showing 32 changed files with 585 additions and 518 deletions.
4 changes: 0 additions & 4 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,10 @@
},
"dependencies": {
"chalk": "2.3.1",
"esbuild": "0.20.2",
"fs-extra": "7.0.1",
"pretty-bytes": "5.6.0",
"unplugin": "1.10.1"
},
"devDependencies": {
"@types/chalk": "2.2.0",
"@types/fs-extra": "8.1.0",
"@types/node": "18.15.3",
"typescript": "5.4.3"
}
Expand Down
105 changes: 0 additions & 105 deletions packages/core/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,96 +2,6 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2019-Present Datadog, Inc.

import { outputFile } from 'fs-extra';

import type { Module, Compilation, Context } from './types';

export const getPluginName = (opts: string | { name: string }) =>
typeof opts === 'string' ? opts : opts.name;

// We want to ensure context ends with a slash.
export const formatContext = (context: string = ''): string => {
return context.endsWith('/') ? context : `${context}/`;
};

// Format a module name by trimming the user's specific part out.
export const getDisplayName = (name: string, context?: string) => {
let toReturn: string = name;
const nameSplit: string[] = name.split(formatContext(context));
if (context && nameSplit.length) {
toReturn = nameSplit.pop()!;
}

return (
toReturn
// Remove loaders query
.split('!')
.pop()!
// Remove everything in front of /node_modules
.replace(/(.*)?\/node_modules\//, '/node_modules/')
// Remove any prefixing ../
.replace(/^((\.)*\/)+/, '')
);
};

export const formatModuleName = (name: string, context?: string) =>
name
// Remove loaders query
.split('!')
.pop()!
// Webpack store its modules with a relative path
// let's do the same so we can integrate better with it.
.replace(formatContext(context), './');

export const getModulePath = (module: Module, compilation: Compilation) => {
let path: string | undefined = module.userRequest;
if (!path) {
let issuer;
if (compilation.moduleGraph && typeof compilation.moduleGraph.getIssuer === 'function') {
issuer = compilation.moduleGraph.getIssuer(module);
} else {
issuer = module.issuer;
}

path = issuer?.userRequest;

if (!path) {
// eslint-disable-next-line no-underscore-dangle
path = module._identifier?.split('!').pop();
}
}
return path || 'unknown';
};

// Find the module name and format it the same way as webpack.
export const getModuleName = (module: Module, compilation: Compilation, context?: string) => {
let name: string = module.name || module.userRequest;
if (!name) {
name = getModulePath(module, compilation);
}
return formatModuleName(name || 'no-name', context);
};

export const getModuleSize = (module: Module): number => {
if (!module) {
return 0;
}

if (typeof module.size === 'function') {
return module.size();
}
return module.size;
};

// Format the loader's name by extracting it from the query.
// "[...]/node_modules/babel-loader/lib/index.js" => babel-loader
export const formatLoaderName = (loader: string) =>
loader.replace(/^.*\/node_modules\/(@[a-z0-9][\w-.]+\/[a-z0-9][\w-.]*|[^/]+).*$/, '$1');

// Find a module's loaders names and format them.
export const getLoaderNames = (module: Module) =>
(module.loaders || []).map((l: any) => l.loader || l).map(formatLoaderName);

// Format a duration 0h 0m 0s 0ms
export const formatDuration = (duration: number) => {
const days = Math.floor(duration / 1000 / 60 / 60 / 24);
Expand All @@ -105,18 +15,3 @@ export const formatDuration = (duration: number) => {
seconds ? `${seconds}s ` : ''
}${milliseconds}ms`.trim();
};

// Make it so if JSON.stringify fails it rejects the promise and not the whole process.
export const writeFile = (filePath: string, content: any) => {
return new Promise((resolve) => {
return outputFile(filePath, JSON.stringify(content, null, 4)).then(resolve);
});
};

export const getContext = (args: any[]): Context[] => {
return args.map((arg) => ({
type: arg?.constructor?.name ?? typeof arg,
name: arg?.name,
value: typeof arg === 'string' ? arg : undefined,
}));
};
226 changes: 0 additions & 226 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,236 +2,10 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2019-Present Datadog, Inc.

import type { Metafile, Message, BuildOptions } from 'esbuild';
import type { UnpluginOptions } from 'unplugin';

import type { Context as PluginsContext } from './plugins';

export interface EsbuildIndexedObject {
entryNames: Map<string, string>;
inputsDependencies: { [key: string]: Set<string> };
outputsDependencies: { [key: string]: Set<string> };
}

export interface WebpackIndexedObject {
modulesPerName: { [key: string]: Module };
chunksPerId: { [key: string]: Chunk };
entriesPerChunkId: { [key: string]: Entry };
}

export interface ModuleGraph {
getModule(dependency: Dependency): Module;
getIssuer(module: Module): Module;
issuer: Module;
}

export interface Compilation {
options: {
context: string;
};
moduleGraph?: ModuleGraph;
chunkGraph?: { getModuleChunks: (module: any) => Set<Chunk> };
hooks: {
buildModule: { tap(opts: any, callback: (module: any) => void): void };
succeedModule: { tap(opts: any, callback: (module: any) => void): void };
afterOptimizeTree: {
tap(opts: any, callback: (chunks: any[], modules: any[]) => void): void;
};
};
}

export interface Stats {
toJson(opts: { children: boolean }): StatsJson;
endTime: number;
startTime: number;
compilation: {
assets: { [key: string]: { size: number } };
fileDependencies: Set<any>;
emittedAssets: Set<any>;
warnings: string[];
modules: Set<Module> | Module[];
chunks: Set<Chunk> | Chunk[];
entries: any[] | Map<string, any>;
};
}

export interface Chunk {
id: string;
size: number;
modules: any[];
files: string[];
names: string[];
parents: string[];
}

export interface Asset {
name: string;
size: number;
chunks: string[];
}

export interface Entry {
name: string;
chunks: string[];
}

export interface Entries {
[key: string]: Entry;
}

export interface StatsJson {
entrypoints: {
[key: string]: Entry;
};
chunks: Chunk[];
modules: Module[];
assets: Asset[];
warnings: string[];
errors: string[];
time: number;
}

export interface Hook {
tap?: Tap;
tapAsync?: TapAsync;
tapPromise?: TapPromise;
}

export interface Tapable {
constructor: { name: string };
hooks: {
[key: string]: Hook;
};
}

export interface Compiler extends Tapable {
options: {};
hooks: {
thisCompilation: { tap(opts: any, callback: (compilation: Compilation) => void): void };
done: {
tap(opts: any, callback: (stats: Stats) => void): void;
tapPromise(opts: any, callback: (stats: Stats) => void): Promise<any>;
};
};
}

export type TAP_TYPES = 'default' | 'async' | 'promise';

export interface TimingsReport {
tapables?: TimingsMap;
loaders?: TimingsMap;
modules?: TimingsMap;
}

export interface Report {
timings: TimingsReport;
dependencies: LocalModules;
}

export interface EsbuildStats extends Metafile {
warnings: Message[];
errors: Message[];
entrypoints: BuildOptions['entryPoints'];
duration: number;
}

export interface BundlerStats {
webpack?: Stats;
esbuild?: EsbuildStats;
}

export interface Context {
type: string;
name: string;
value?: string;
}

export interface Value {
start: number;
end: number;
duration: number;
context?: Context[];
type?: TAP_TYPES; // Only for webpack.
}

export interface Timing {
name: string;
duration: number;
increment: number;
events: {
[key: string]: {
name: string;
values: Value[];
};
};
}

export type TimingsMap = Map<string, Timing>;

export interface MonitoredTaps {
[key: string]: any;
}

export interface TapablesResult {
monitoredTaps: MonitoredTaps;
tapables: Tapable[];
hooks: Hooks;
timings: TimingsMap;
}

export type TapAsync = (...args: any[]) => void;
export type Tap = (...args: any[]) => any;
export type TapPromise = (...args: any[]) => Promise<any>;

export interface Hooks {
[key: string]: string[];
}

export interface Dependency {
module: Module;
}

export interface Module {
name: string;
userRequest: string;
issuer?: {
userRequest: string;
};
_identifier?: string;
identifier?: string;
modules?: Module[];
moduleGraph?: ModuleGraph;
size: (() => number) | number;
loaders: {
loader: string;
}[];
chunks: string[];
_chunks: Set<Chunk>;
dependencies: Dependency[];
}

export interface Event {
module: string;
timings: Value;
loaders: string[];
}

export interface LocalModule {
name: string;
size: number;
chunkNames: string[];
dependencies: string[];
dependents: string[];
}

export interface LocalModules {
[key: string]: LocalModule;
}

export interface ModulesResult {
modules: LocalModules;
}

export type GetPlugins<T> = (options: T, context: PluginsContext) => UnpluginOptions[];

export type LogLevel = 'debug' | 'warn' | 'error' | 'none';
Expand Down
4 changes: 3 additions & 1 deletion packages/plugins/telemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@
"@dd/core": "workspace:*",
"chalk": "2.3.1",
"esbuild": "0.20.2",
"fs-extra": "7.0.1",
"pretty-bytes": "5.6.0",
"unplugin": "1.10.1",
"webpack": "5.49.0"
},
"devDependencies": {
"@types/chalk": "2.2.0"
"@types/chalk": "2.2.0",
"@types/fs-extra": "8.1.0"
},
"peerDependencies": {
"esbuild": ">=0.x",
Expand Down
Loading

0 comments on commit 85330b7

Please sign in to comment.