@shuvi/service 1.0.29 → 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,11 @@
1
- import { IPluginContext, Telemetry } from '../core';
1
+ import { IPluginContext } from '../core';
2
+ import { RecordObject, TelemetryEvent } from '@shuvi/reporters';
3
+ interface Telemetry {
4
+ record(events: TelemetryEvent | TelemetryEvent[]): Promise<RecordObject>;
5
+ flush(): Promise<void>;
6
+ }
2
7
  export declare const analysis: ({ context, telemetry }: {
3
8
  context: IPluginContext;
4
- telemetry: Telemetry;
9
+ telemetry?: Telemetry | undefined;
5
10
  }) => Promise<void>;
11
+ export {};
package/lib/core/api.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { Telemetry as TelemetryImpl, RecordObject, TelemetryEvent } from '@shuvi/telemetry';
2
1
  import { FileOptionWithId } from '../project';
3
2
  import { Bundler } from '../bundler';
4
3
  import { ServerPluginInstance } from '../server';
@@ -13,17 +12,12 @@ interface IApiOPtions {
13
12
  plugins?: IPluginConfig[];
14
13
  presets?: IPresetConfig[];
15
14
  normalizePlatformConfig?: (rawConfig: ShuviConfig) => ShuviConfig;
16
- telemetry?: TelemetryImpl;
17
15
  }
18
16
  interface ServerConfigs {
19
17
  serverPlugins: ServerPluginInstance[];
20
18
  getMiddlewares: IPlatformContent['getMiddlewares'];
21
19
  getMiddlewaresBeforeDevMiddlewares: IPlatformContent['getMiddlewaresBeforeDevMiddlewares'];
22
20
  }
23
- export interface Telemetry {
24
- record(events: TelemetryEvent | TelemetryEvent[]): Promise<RecordObject>;
25
- flush(): Promise<void>;
26
- }
27
21
  declare class Api {
28
22
  private _inited;
29
23
  private _cwd;
@@ -39,8 +33,6 @@ declare class Api {
39
33
  private _config;
40
34
  private _plugins;
41
35
  private _presets;
42
- private _telemetryImpl?;
43
- private _telemetry;
44
36
  private _platform?;
45
37
  private _normalizePlatformConfig?;
46
38
  private _serverConfigs;
@@ -49,13 +41,12 @@ declare class Api {
49
41
  private _pluginContext;
50
42
  /** will be included by @shuvi/swc-loader */
51
43
  private _runtimePluginDirs;
52
- constructor({ cwd, mode, config, configFile, presets, plugins, phase, platform, normalizePlatformConfig, telemetry }: IApiOPtions);
44
+ constructor({ cwd, mode, config, configFile, presets, plugins, phase, platform, normalizePlatformConfig }: IApiOPtions);
53
45
  get cwd(): string;
54
46
  get mode(): IServiceMode;
55
47
  get pluginManager(): import("@shuvi/hook").HookManager<import("./plugin").PluginHooks, IPluginContext>;
56
48
  get pluginContext(): IPluginContext;
57
49
  get serverConfigs(): ServerConfigs;
58
- get telemetry(): Telemetry;
59
50
  init(): Promise<void>;
60
51
  getBundler(): Promise<Bundler>;
61
52
  get assetPublicPath(): string;
package/lib/core/api.js CHANGED
@@ -40,7 +40,6 @@ const hook_1 = require("@shuvi/hook");
40
40
  const deepmerge_1 = require("@shuvi/utils/deepmerge");
41
41
  const string_1 = require("@shuvi/utils/string");
42
42
  const logger_1 = __importDefault(require("@shuvi/utils/logger"));
43
- const trace_1 = require("@shuvi/trace");
44
43
  const rimraf_1 = __importDefault(require("rimraf"));
45
44
  const path = __importStar(require("path"));
46
45
  const project_1 = require("../project");
@@ -56,7 +55,7 @@ const webpack_watch_wait_for_file_builder_plugin_1 = __importDefault(require("..
56
55
  const config_2 = require("../config");
57
56
  const ServiceModes = ['development', 'production'];
58
57
  class Api {
59
- constructor({ cwd, mode, config, configFile, presets, plugins, phase, platform, normalizePlatformConfig, telemetry }) {
58
+ constructor({ cwd, mode, config, configFile, presets, plugins, phase, platform, normalizePlatformConfig }) {
60
59
  this._inited = false;
61
60
  this._plugins = [];
62
61
  this._presets = [];
@@ -71,7 +70,6 @@ class Api {
71
70
  this._customConfig = config || {};
72
71
  this._customPresets = presets || [];
73
72
  this._customPlugins = plugins || [];
74
- this._telemetryImpl = telemetry;
75
73
  this._pluginManager = (0, plugin_1.getManager)();
76
74
  this._pluginManager.clear();
77
75
  this._projectBuilder = new project_1.ProjectBuilder();
@@ -92,28 +90,6 @@ class Api {
92
90
  get serverConfigs() {
93
91
  return this._serverConfigs;
94
92
  }
95
- get telemetry() {
96
- if (!this._telemetry) {
97
- this._telemetry = {
98
- record: (events) => {
99
- if (!this._telemetryImpl) {
100
- return Promise.resolve({
101
- isFulfilled: true,
102
- isRejected: true
103
- });
104
- }
105
- return this._telemetryImpl.record(events);
106
- },
107
- flush: () => {
108
- if (!this._telemetryImpl) {
109
- return Promise.resolve();
110
- }
111
- return this._telemetryImpl.flush();
112
- }
113
- };
114
- }
115
- return this._telemetry;
116
- }
117
93
  init() {
118
94
  return __awaiter(this, void 0, void 0, function* () {
119
95
  if (this._inited) {
@@ -201,9 +177,6 @@ class Api {
201
177
  platformPresetRuntimeFiles.forEach(file => {
202
178
  this.addInternalRuntimeFile(file);
203
179
  });
204
- (0, trace_1.setGlobal)('buildDir', this._paths.buildDir);
205
- (0, trace_1.setGlobal)('phase', constants_1.PHASE_DEVELOPMENT_SERVER);
206
- (0, trace_1.setGlobal)('telemetry', this._telemetryImpl);
207
180
  this._inited = true;
208
181
  });
209
182
  }
@@ -401,8 +374,7 @@ function getApi(options = {}) {
401
374
  platform: options.platform,
402
375
  presets: options.presets,
403
376
  plugins: options.plugins,
404
- normalizePlatformConfig: options.normalizePlatformConfig,
405
- telemetry: options.telemetry
377
+ normalizePlatformConfig: options.normalizePlatformConfig
406
378
  });
407
379
  try {
408
380
  yield api.init();
@@ -1,4 +1,4 @@
1
- export type { Api, Telemetry } from './api';
1
+ export type { Api } from './api';
2
2
  export { getApi } from './api';
3
3
  export { resolvePlugin } from './getPlugins';
4
4
  export * from './apiTypes';
package/lib/index.d.ts CHANGED
@@ -4,4 +4,4 @@ export { Bundler } from './bundler';
4
4
  export { ProjectBuilder } from './project';
5
5
  export { analysis } from './analysis';
6
6
  export { IShuviServer, ShuviRequest, ShuviResponse, IServerPluginContext, ShuviRequestHandler, ServerPluginConstructor, ServerPluginInstance, IServerMiddleware, createShuviServer, createServerPlugin, createServerPluginBefore, createServerPluginAfter } from './server';
7
- export { Api, Telemetry, IPaths, ShuviConfig, IServicePhase, IServiceMode, IPluginConfig, IPresetConfig, PresetFunction, IPresetContent, NormalizedShuviConfig, IPluginContext, IPlatform, IPlatformContent, CorePluginConstructor, CorePluginInstance, getApi, createPlugin, createPluginBefore, createPluginAfter, ResolvedPlugin } from './core';
7
+ export { Api, IPaths, ShuviConfig, IServicePhase, IServiceMode, IPluginConfig, IPresetConfig, PresetFunction, IPresetContent, NormalizedShuviConfig, IPluginContext, IPlatform, IPlatformContent, CorePluginConstructor, CorePluginInstance, getApi, createPlugin, createPluginBefore, createPluginAfter, ResolvedPlugin } from './core';
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.WebpackHotMiddleware = void 0;
10
10
  const module_replace_plugin_1 = __importDefault(require("@shuvi/toolpack/lib/webpack/plugins/module-replace-plugin"));
11
11
  const constants_1 = require("@shuvi/shared/constants");
12
- const trace_1 = require("@shuvi/trace");
12
+ const trace_1 = require("../../../trace");
13
13
  //@ts-ignore
14
14
  const package_json_1 = __importDefault(require("../../../../package.json"));
15
15
  const modulesActivity = new Map();
@@ -35,7 +35,6 @@ class WebpackHotMiddleware {
35
35
  this.latestStats = statsResult;
36
36
  this.publishStats('built', this.latestStats);
37
37
  // Ensure traces are flushed after each compile in development mode
38
- (0, trace_1.flushAllTraces)();
39
38
  };
40
39
  this.onHMR = (client) => {
41
40
  if (this.closed)
@@ -63,8 +62,8 @@ class WebpackHotMiddleware {
63
62
  case 'client-hmr-latency': {
64
63
  traceChild = {
65
64
  name: parsedData.event,
66
- startTime: BigInt(parsedData.startTime) * BigInt(1000 * 1000),
67
- endTime: BigInt(parsedData.endTime) * BigInt(1000 * 1000)
65
+ startTime: parsedData.startTime,
66
+ endTime: parsedData.endTime
68
67
  };
69
68
  break;
70
69
  }
@@ -72,8 +71,8 @@ class WebpackHotMiddleware {
72
71
  break;
73
72
  }
74
73
  }
75
- if (traceChild) {
76
- this.hotMiddlewareSpan.manualTraceChild(traceChild.name, traceChild.startTime || process.hrtime.bigint(), traceChild.endTime || process.hrtime.bigint(), Object.assign({}, traceChild.attrs));
74
+ if (traceChild && traceChild.startTime && traceChild.endTime) {
75
+ this.hotMiddlewareSpan.manualTraceChild(traceChild.name, traceChild.startTime, traceChild.endTime, Object.assign({}, traceChild.attrs));
77
76
  }
78
77
  }
79
78
  catch (_) { }
@@ -117,7 +116,7 @@ class WebpackHotMiddleware {
117
116
  });
118
117
  // Ensure the hotMiddlewareSpan is flushed immediately as it's the parentSpan for all processing
119
118
  // of the current `shuvi dev` invocation.
120
- this.hotMiddlewareSpan.stop();
119
+ // this.hotMiddlewareSpan.stop();
121
120
  }
122
121
  updateModuleActivity(matchRoutes, page) {
123
122
  if (matchRoutes.length < 1 || !page)
@@ -1,9 +1,14 @@
1
1
  import { IPluginInstance, IPluginHandlers, HookMap } from '@shuvi/hook';
2
2
  import { IPluginContext } from '../core';
3
3
  import { CustomServerPluginHooks } from './pluginTypes';
4
+ import { Span } from '../trace';
4
5
  export * from './pluginTypes';
5
6
  export interface IServerPluginContext extends IPluginContext {
6
7
  serverPluginRunner: PluginManager['runner'];
8
+ traces: {
9
+ serverCreateAppTrace: Span;
10
+ serverRequestTrace: Span;
11
+ };
7
12
  }
8
13
  export declare type PluginManager = ReturnType<typeof getManager>;
9
14
  export declare type PluginRunner = PluginManager['runner'];
@@ -18,6 +18,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.initServerPlugins = exports.createServerPluginAfter = exports.createServerPlugin = exports.createServerPluginBefore = exports.getManager = void 0;
19
19
  const hook_1 = require("@shuvi/hook");
20
20
  const plugins_1 = require("@shuvi/shared/plugins");
21
+ const trace_1 = require("@shuvi/shared/constants/trace");
22
+ const trace_2 = require("../trace");
21
23
  __exportStar(require("./pluginTypes"), exports);
22
24
  const listen = (0, hook_1.createAsyncParallelHook)();
23
25
  const internalHooks = {
@@ -27,7 +29,13 @@ const getManager = () => (0, hook_1.createHookManager)(internalHooks);
27
29
  exports.getManager = getManager;
28
30
  _a = (0, plugins_1.createPluginCreator)(), exports.createServerPluginBefore = _a.createPluginBefore, exports.createServerPlugin = _a.createPlugin, exports.createServerPluginAfter = _a.createPluginAfter;
29
31
  const initServerPlugins = (manager, serverPlugins, pluginContext) => {
30
- const serverContext = Object.assign({ serverPluginRunner: manager.runner }, pluginContext);
32
+ const serverContext = Object.assign({
33
+ serverPluginRunner: manager.runner,
34
+ traces: {
35
+ serverCreateAppTrace: (0, trace_2.trace)(trace_1.SERVER_CREATE_APP.name),
36
+ serverRequestTrace: (0, trace_2.trace)(trace_1.SERVER_REQUEST.name)
37
+ }
38
+ }, pluginContext);
31
39
  manager.setContext(serverContext);
32
40
  serverPlugins.forEach(plugin => {
33
41
  manager.usePlugin(plugin);
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.ShuviServer = void 0;
13
+ const trace_1 = require("@shuvi/shared/constants/trace");
13
14
  const string_1 = require("@shuvi/utils/string");
14
15
  const serverMiddleware_1 = require("./serverMiddleware");
15
16
  const http_server_1 = require("./http-server");
@@ -39,6 +40,9 @@ class ShuviServer {
39
40
  return __awaiter(this, void 0, void 0, function* () {
40
41
  const { _serverContext: context, _server: server } = this;
41
42
  server.use(((req, resp, next) => {
43
+ context.traces.serverRequestTrace
44
+ .traceChild(trace_1.SERVER_REQUEST.events.SHUVI_SERVER_HANDLE_REQUEST_START.name)
45
+ .stop();
42
46
  this._normalizeReq(req);
43
47
  this._normalizeResp(resp);
44
48
  next();
@@ -0,0 +1,33 @@
1
+ import type { SpanId, Reporter } from '@shuvi/shared/reporter';
2
+ export declare enum SpanStatus {
3
+ Started = 0,
4
+ Stopped = 1
5
+ }
6
+ export declare let reporter: Reporter | undefined;
7
+ export declare function setReporter(r: Reporter): void;
8
+ export declare class Span {
9
+ private _name;
10
+ private _id;
11
+ private _parentId?;
12
+ private _attrs;
13
+ private _status;
14
+ private _now;
15
+ private _start;
16
+ constructor({ name, parentId, attrs, startTime }: {
17
+ name: string;
18
+ parentId?: SpanId;
19
+ startTime?: number;
20
+ attrs?: Record<string, any>;
21
+ });
22
+ get status(): SpanStatus;
23
+ stop(stopTime?: number): void;
24
+ traceChild(name: string, attrs?: Object): Span;
25
+ manualTraceChild(name: string, startTime: number, stopTime: number, attrs?: Object): void;
26
+ setAttribute(key: string, value: any): void;
27
+ setAttributes(attrs: Record<string, any>): void;
28
+ traceFn<T>(fn: (span: Span) => T): T;
29
+ traceAsyncFn<T>(fn: (span: Span) => T | Promise<T>): Promise<T>;
30
+ }
31
+ export declare const trace: (name: string, parentId?: SpanId, attrs?: {
32
+ [key: string]: string;
33
+ } | undefined) => Span;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ // This package 'trace' is a modified version of the Next.js that can be found here:
3
+ // https://github.com/vercel/next.js/tree/canary/packages/next/src/trace
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.trace = exports.Span = exports.setReporter = exports.reporter = exports.SpanStatus = void 0;
15
+ let count = 0;
16
+ const getId = () => {
17
+ count++;
18
+ return count;
19
+ };
20
+ // eslint typescript has a bug with TS enums
21
+ /* eslint-disable no-shadow */
22
+ var SpanStatus;
23
+ (function (SpanStatus) {
24
+ SpanStatus[SpanStatus["Started"] = 0] = "Started";
25
+ SpanStatus[SpanStatus["Stopped"] = 1] = "Stopped";
26
+ })(SpanStatus = exports.SpanStatus || (exports.SpanStatus = {}));
27
+ exports.reporter = undefined;
28
+ function setReporter(r) {
29
+ if (exports.reporter) {
30
+ throw new Error('Reporter already set !');
31
+ return;
32
+ }
33
+ exports.reporter = r;
34
+ }
35
+ exports.setReporter = setReporter;
36
+ class Span {
37
+ constructor({ name, parentId, attrs, startTime }) {
38
+ this._name = name;
39
+ this._parentId = parentId;
40
+ this._attrs = attrs ? Object.assign({}, attrs) : {};
41
+ this._status = SpanStatus.Started;
42
+ this._id = getId();
43
+ const now = Date.now();
44
+ this._start = startTime || now;
45
+ // Capturing current datetime as additional metadata for external reconstruction.
46
+ this._now = now;
47
+ }
48
+ get status() {
49
+ return this._status;
50
+ }
51
+ // Durations are reported as microseconds.
52
+ // of something like Date.now(), which reports in milliseconds.
53
+ // Additionally, ~285 years can be safely represented as microseconds as
54
+ // a float64 in both JSON and JavaScript.
55
+ stop(stopTime) {
56
+ if (!exports.reporter) {
57
+ return;
58
+ }
59
+ const end = stopTime || Date.now();
60
+ const duration = end - this._start;
61
+ this._status = SpanStatus.Stopped;
62
+ if (duration > Number.MAX_SAFE_INTEGER) {
63
+ console.warn(`Duration is too long to express as float64: ${duration}`);
64
+ }
65
+ (0, exports.reporter)({
66
+ timestamp: this._now,
67
+ name: this._name,
68
+ duration,
69
+ startTime: this._start,
70
+ endTime: end,
71
+ id: this._id,
72
+ parentId: this._parentId,
73
+ attrs: this._attrs
74
+ });
75
+ }
76
+ traceChild(name, attrs) {
77
+ return new Span({ name, parentId: this._id, attrs });
78
+ }
79
+ manualTraceChild(name, startTime, stopTime, attrs) {
80
+ const span = new Span({ name, parentId: this._id, attrs, startTime });
81
+ span.stop(stopTime);
82
+ }
83
+ setAttribute(key, value) {
84
+ this._attrs[key] = String(value);
85
+ }
86
+ setAttributes(attrs) {
87
+ Object.keys(attrs).forEach(key => {
88
+ this.setAttribute(key, attrs[key]);
89
+ });
90
+ }
91
+ traceFn(fn) {
92
+ try {
93
+ return fn(this);
94
+ }
95
+ finally {
96
+ this.stop();
97
+ }
98
+ }
99
+ traceAsyncFn(fn) {
100
+ return __awaiter(this, void 0, void 0, function* () {
101
+ try {
102
+ return yield fn(this);
103
+ }
104
+ finally {
105
+ this.stop();
106
+ }
107
+ });
108
+ }
109
+ }
110
+ exports.Span = Span;
111
+ const trace = (name, parentId, attrs) => {
112
+ return new Span({ name, parentId, attrs });
113
+ };
114
+ exports.trace = trace;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuvi/service",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/shuvijs/shuvi.git",
@@ -29,15 +29,14 @@
29
29
  "@babel/generator": "7.14.5",
30
30
  "@babel/parser": "7.14.7",
31
31
  "@babel/traverse": "7.14.7",
32
- "@shuvi/hook": "1.0.29",
33
- "@shuvi/router": "1.0.29",
34
- "@shuvi/runtime": "1.0.29",
35
- "@shuvi/shared": "1.0.29",
36
- "@shuvi/toolpack": "1.0.29",
37
- "@shuvi/utils": "1.0.29",
38
- "@shuvi/error-overlay": "1.0.29",
39
- "@shuvi/telemetry": "1.0.29",
40
- "@shuvi/trace": "1.0.29",
32
+ "@shuvi/hook": "1.0.30",
33
+ "@shuvi/router": "1.0.30",
34
+ "@shuvi/runtime": "1.0.30",
35
+ "@shuvi/shared": "1.0.30",
36
+ "@shuvi/toolpack": "1.0.30",
37
+ "@shuvi/utils": "1.0.30",
38
+ "@shuvi/error-overlay": "1.0.30",
39
+ "@shuvi/reporters": "1.0.30",
41
40
  "commander": "5.1.0",
42
41
  "comment-json": "4.2.2",
43
42
  "cross-spawn": "7.0.3",