@next-core/easyops-runtime 0.6.67 → 0.7.1

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.
@@ -8,33 +8,21 @@ exports.earlyFinishPageView = earlyFinishPageView;
8
8
  exports.finishPageView = finishPageView;
9
9
  exports.initialize = initialize;
10
10
  exports.pushApiMetric = pushApiMetric;
11
+ var _transport = require("./transport.js");
11
12
  let initialized = false;
13
+ let transport;
12
14
  let pageState = null;
13
15
  let isFirstPageView = true;
14
16
  const stashedApiMetrics = [];
15
- const allMetrics = [];
16
- function initialize(api) {
17
+ function initialize(api, options = {}) {
17
18
  if (initialized) {
18
19
  return;
19
20
  }
20
21
  initialized = true;
21
- function upload() {
22
- if (allMetrics.length === 0) {
23
- return;
24
- }
25
- const headers = {
26
- type: "application/json"
27
- };
28
- const data = {
29
- model: "easyops.FRONTEND_STAT",
30
- columns: ["_ver", "st", "et", "lt", "size", "time", "traceId", "code", "duration", "page", "uid", "username", "api", "type", "msg", "status", "pageId", "route", "apiCount", "maxApiTimeCost", "apiSizeCost", "pageTitle"],
31
- data: allMetrics
32
- };
33
- const blob = new Blob([JSON.stringify(data)], headers);
34
- allMetrics.length = 0;
35
- window.navigator.sendBeacon(api, blob);
22
+ if (!transport) {
23
+ transport = (0, _transport.createTransport)(api, options);
24
+ transport.sendOnExit();
36
25
  }
37
- window.addEventListener("beforeunload", upload, false);
38
26
  }
39
27
  function createPageView() {
40
28
  stashedApiMetrics.length = 0;
@@ -51,7 +39,7 @@ function finishPageView(metric) {
51
39
  route,
52
40
  pageId
53
41
  };
54
- allMetrics.push({
42
+ _transport.events.push({
55
43
  ...metric,
56
44
  pageId,
57
45
  apiCount: stashedApiMetrics.length,
@@ -59,20 +47,21 @@ function finishPageView(metric) {
59
47
  size: stashedApiMetrics.map(api => api.size).filter(size => size > 0).reduce((prev, current) => prev + current, 0)
60
48
  });
61
49
  for (const item of stashedApiMetrics) {
62
- allMetrics.push({
50
+ _transport.events.push({
63
51
  ...item,
64
52
  ...pageState
65
53
  });
66
54
  }
67
55
  stashedApiMetrics.length = 0;
56
+ transport.emit();
68
57
  }
69
58
  function earlyFinishPageView() {
70
- allMetrics.push(...stashedApiMetrics);
59
+ _transport.events.push(...stashedApiMetrics);
71
60
  stashedApiMetrics.length = 0;
72
61
  }
73
62
  function pushApiMetric(metric) {
74
63
  if (pageState) {
75
- allMetrics.push({
64
+ _transport.events.push({
76
65
  ...metric,
77
66
  type: "apiRequest",
78
67
  ...pageState
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.js","names":["initialized","pageState","isFirstPageView","stashedApiMetrics","allMetrics","initialize","api","upload","length","headers","type","data","model","columns","blob","Blob","JSON","stringify","window","navigator","sendBeacon","addEventListener","createPageView","finishPageView","metric","pageId","generateUUID","lt","route","push","apiCount","maxApiTimeCost","Math","max","map","duration","size","filter","reduce","prev","current","item","earlyFinishPageView","pushApiMetric","url","URL","createObjectURL","uuid","substring","lastIndexOf","revokeObjectURL"],"sources":["../../../src/analytics/analytics.ts"],"sourcesContent":["import type {\n ApiMetric,\n ApiPageState,\n PageViewMetric,\n PartialPageViewMetric,\n} from \"./interfaces.js\";\n\nlet initialized = false;\nlet pageState: ApiPageState | null = null;\nlet isFirstPageView = true;\nconst stashedApiMetrics: ApiMetric[] = [];\n\nconst allMetrics: (ApiMetric | PageViewMetric)[] = [];\n\nexport function initialize(api: string) {\n if (initialized) {\n return;\n }\n initialized = true;\n\n function upload() {\n if (allMetrics.length === 0) {\n return;\n }\n const headers = {\n type: \"application/json\",\n };\n const data = {\n model: \"easyops.FRONTEND_STAT\",\n columns: [\n \"_ver\",\n \"st\",\n \"et\",\n \"lt\",\n \"size\",\n \"time\",\n \"traceId\",\n \"code\",\n \"duration\",\n \"page\",\n \"uid\",\n \"username\",\n \"api\",\n \"type\",\n \"msg\",\n \"status\",\n \"pageId\",\n \"route\",\n \"apiCount\",\n \"maxApiTimeCost\",\n \"apiSizeCost\",\n \"pageTitle\",\n ],\n data: allMetrics,\n };\n const blob = new Blob([JSON.stringify(data)], headers);\n allMetrics.length = 0;\n\n window.navigator.sendBeacon(api, blob);\n }\n\n window.addEventListener(\"beforeunload\", upload, false);\n}\n\nexport function createPageView() {\n stashedApiMetrics.length = 0;\n pageState = null;\n}\n\nexport function finishPageView(metric: PartialPageViewMetric) {\n const pageId = generateUUID();\n const { lt, route } = metric;\n pageState = { lt, route, pageId };\n\n allMetrics.push({\n ...metric,\n pageId,\n apiCount: stashedApiMetrics.length,\n maxApiTimeCost: Math.max(\n 0,\n ...stashedApiMetrics.map((api) => api.duration)\n ),\n size: stashedApiMetrics\n .map((api) => api.size)\n .filter((size) => size > 0)\n .reduce((prev, current) => prev + current, 0),\n });\n\n for (const item of stashedApiMetrics) {\n allMetrics.push({\n ...item,\n ...pageState,\n });\n }\n stashedApiMetrics.length = 0;\n}\n\nexport function earlyFinishPageView() {\n allMetrics.push(...stashedApiMetrics);\n stashedApiMetrics.length = 0;\n}\n\nexport function pushApiMetric(metric: ApiMetric) {\n if (pageState) {\n allMetrics.push({\n ...metric,\n type: \"apiRequest\",\n ...pageState,\n });\n } else {\n stashedApiMetrics.push(metric);\n }\n}\n\n// Ref https://medium.com/teads-engineering/generating-uuids-at-scale-on-the-web-2877f529d2a2\nfunction generateUUID() {\n const url = URL.createObjectURL(new Blob([]));\n let uuid = url.substring(url.lastIndexOf(\"/\") + 1);\n URL.revokeObjectURL(url);\n // 第一次渲染加上特殊标记\n if (isFirstPageView) {\n uuid = \"88-\" + uuid;\n isFirstPageView = false;\n }\n return uuid;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"analytics.js","names":["_transport","require","initialized","transport","pageState","isFirstPageView","stashedApiMetrics","initialize","api","options","createTransport","sendOnExit","createPageView","length","finishPageView","metric","pageId","generateUUID","lt","route","events","push","apiCount","maxApiTimeCost","Math","max","map","duration","size","filter","reduce","prev","current","item","emit","earlyFinishPageView","pushApiMetric","type","url","URL","createObjectURL","Blob","uuid","substring","lastIndexOf","revokeObjectURL"],"sources":["../../../src/analytics/analytics.ts"],"sourcesContent":["import type {\n ApiMetric,\n ApiPageState,\n PartialPageViewMetric,\n} from \"./interfaces.js\";\nimport { createTransport, events, TransportOptions } from \"./transport.js\";\n\nlet initialized = false;\nlet transport: ReturnType<typeof createTransport>;\nlet pageState: ApiPageState | null = null;\nlet isFirstPageView = true;\nconst stashedApiMetrics: ApiMetric[] = [];\n\ntype Options = Partial<TransportOptions>;\n\nexport function initialize(api: string, options: Options = {}) {\n if (initialized) {\n return;\n }\n initialized = true;\n if (!transport) {\n transport = createTransport(api, options);\n transport.sendOnExit();\n }\n}\n\nexport function createPageView() {\n stashedApiMetrics.length = 0;\n pageState = null;\n}\n\nexport function finishPageView(metric: PartialPageViewMetric) {\n const pageId = generateUUID();\n const { lt, route } = metric;\n pageState = { lt, route, pageId };\n\n events.push({\n ...metric,\n pageId,\n apiCount: stashedApiMetrics.length,\n maxApiTimeCost: Math.max(\n 0,\n ...stashedApiMetrics.map((api) => api.duration)\n ),\n size: stashedApiMetrics\n .map((api) => api.size)\n .filter((size) => size > 0)\n .reduce((prev, current) => prev + current, 0),\n });\n\n for (const item of stashedApiMetrics) {\n events.push({\n ...item,\n ...pageState,\n });\n }\n stashedApiMetrics.length = 0;\n\n transport.emit();\n}\n\nexport function earlyFinishPageView() {\n events.push(...stashedApiMetrics);\n stashedApiMetrics.length = 0;\n}\n\nexport function pushApiMetric(metric: ApiMetric) {\n if (pageState) {\n events.push({\n ...metric,\n type: \"apiRequest\",\n ...pageState,\n });\n } else {\n stashedApiMetrics.push(metric);\n }\n}\n\n// Ref https://medium.com/teads-engineering/generating-uuids-at-scale-on-the-web-2877f529d2a2\nfunction generateUUID() {\n const url = URL.createObjectURL(new Blob([]));\n let uuid = url.substring(url.lastIndexOf(\"/\") + 1);\n URL.revokeObjectURL(url);\n // 第一次渲染加上特殊标记\n if (isFirstPageView) {\n uuid = \"88-\" + uuid;\n isFirstPageView = false;\n }\n return uuid;\n}\n"],"mappings":";;;;;;;;;;AAKA,IAAAA,UAAA,GAAAC,OAAA;AAEA,IAAIC,WAAW,GAAG,KAAK;AACvB,IAAIC,SAA6C;AACjD,IAAIC,SAA8B,GAAG,IAAI;AACzC,IAAIC,eAAe,GAAG,IAAI;AAC1B,MAAMC,iBAA8B,GAAG,EAAE;AAIlC,SAASC,UAAUA,CAACC,GAAW,EAAEC,OAAgB,GAAG,CAAC,CAAC,EAAE;EAC7D,IAAIP,WAAW,EAAE;IACf;EACF;EACAA,WAAW,GAAG,IAAI;EAClB,IAAI,CAACC,SAAS,EAAE;IACdA,SAAS,GAAG,IAAAO,0BAAe,EAACF,GAAG,EAAEC,OAAO,CAAC;IACzCN,SAAS,CAACQ,UAAU,CAAC,CAAC;EACxB;AACF;AAEO,SAASC,cAAcA,CAAA,EAAG;EAC/BN,iBAAiB,CAACO,MAAM,GAAG,CAAC;EAC5BT,SAAS,GAAG,IAAI;AAClB;AAEO,SAASU,cAAcA,CAACC,MAA6B,EAAE;EAC5D,MAAMC,MAAM,GAAGC,YAAY,CAAC,CAAC;EAC7B,MAAM;IAAEC,EAAE;IAAEC;EAAM,CAAC,GAAGJ,MAAM;EAC5BX,SAAS,GAAG;IAAEc,EAAE;IAAEC,KAAK;IAAEH;EAAO,CAAC;EAEjCI,iBAAM,CAACC,IAAI,CAAC;IACV,GAAGN,MAAM;IACTC,MAAM;IACNM,QAAQ,EAAEhB,iBAAiB,CAACO,MAAM;IAClCU,cAAc,EAAEC,IAAI,CAACC,GAAG,CACtB,CAAC,EACD,GAAGnB,iBAAiB,CAACoB,GAAG,CAAElB,GAAG,IAAKA,GAAG,CAACmB,QAAQ,CAChD,CAAC;IACDC,IAAI,EAAEtB,iBAAiB,CACpBoB,GAAG,CAAElB,GAAG,IAAKA,GAAG,CAACoB,IAAI,CAAC,CACtBC,MAAM,CAAED,IAAI,IAAKA,IAAI,GAAG,CAAC,CAAC,CAC1BE,MAAM,CAAC,CAACC,IAAI,EAAEC,OAAO,KAAKD,IAAI,GAAGC,OAAO,EAAE,CAAC;EAChD,CAAC,CAAC;EAEF,KAAK,MAAMC,IAAI,IAAI3B,iBAAiB,EAAE;IACpCc,iBAAM,CAACC,IAAI,CAAC;MACV,GAAGY,IAAI;MACP,GAAG7B;IACL,CAAC,CAAC;EACJ;EACAE,iBAAiB,CAACO,MAAM,GAAG,CAAC;EAE5BV,SAAS,CAAC+B,IAAI,CAAC,CAAC;AAClB;AAEO,SAASC,mBAAmBA,CAAA,EAAG;EACpCf,iBAAM,CAACC,IAAI,CAAC,GAAGf,iBAAiB,CAAC;EACjCA,iBAAiB,CAACO,MAAM,GAAG,CAAC;AAC9B;AAEO,SAASuB,aAAaA,CAACrB,MAAiB,EAAE;EAC/C,IAAIX,SAAS,EAAE;IACbgB,iBAAM,CAACC,IAAI,CAAC;MACV,GAAGN,MAAM;MACTsB,IAAI,EAAE,YAAY;MAClB,GAAGjC;IACL,CAAC,CAAC;EACJ,CAAC,MAAM;IACLE,iBAAiB,CAACe,IAAI,CAACN,MAAM,CAAC;EAChC;AACF;;AAEA;AACA,SAASE,YAAYA,CAAA,EAAG;EACtB,MAAMqB,GAAG,GAAGC,GAAG,CAACC,eAAe,CAAC,IAAIC,IAAI,CAAC,EAAE,CAAC,CAAC;EAC7C,IAAIC,IAAI,GAAGJ,GAAG,CAACK,SAAS,CAACL,GAAG,CAACM,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;EAClDL,GAAG,CAACM,eAAe,CAACP,GAAG,CAAC;EACxB;EACA,IAAIjC,eAAe,EAAE;IACnBqC,IAAI,GAAG,KAAK,GAAGA,IAAI;IACnBrC,eAAe,GAAG,KAAK;EACzB;EACA,OAAOqC,IAAI;AACb"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createTransport = createTransport;
7
+ exports.transportOptions = exports.events = void 0;
8
+ const events = exports.events = [];
9
+ const MAXIMUM_WAITING_TIME = 5 * 1000;
10
+ const MAXIMUM_LOGGED_EVENTS = 10;
11
+ let timer = null;
12
+ const transportOptions = exports.transportOptions = {
13
+ maxWaitingTime: MAXIMUM_WAITING_TIME,
14
+ maxLoggedEvents: MAXIMUM_LOGGED_EVENTS
15
+ };
16
+ function createTransport(api, options) {
17
+ Object.assign(transportOptions, {
18
+ ...options,
19
+ api
20
+ });
21
+ return {
22
+ sendOnExit,
23
+ emit
24
+ };
25
+ }
26
+ function nextTime(callback) {
27
+ return (window.requestIdleCallback || window.requestAnimationFrame || (cb => setTimeout(cb, 17)))(callback);
28
+ }
29
+ function emit() {
30
+ clearTimeout(timer);
31
+ events.length > transportOptions.maxLoggedEvents ? send() : timer = setTimeout(send, transportOptions.maxWaitingTime);
32
+ }
33
+ function send() {
34
+ if (events.length === 0) {
35
+ return;
36
+ }
37
+ const transportEvents = events.splice(0, transportOptions.maxLoggedEvents);
38
+ const transportData = buildTransportData(transportEvents);
39
+ sendBeacon(transportOptions.api, transportData);
40
+ events.length && nextTime(send);
41
+ }
42
+ function sendBeacon(requestUrl, data) {
43
+ const headers = {
44
+ type: "application/json"
45
+ };
46
+ const blob = new Blob([JSON.stringify(data)], headers);
47
+ window.navigator.sendBeacon(requestUrl, blob);
48
+ }
49
+ function sendOnExit() {
50
+ window.addEventListener("beforeunload", send, false);
51
+ }
52
+ function buildTransportData(data) {
53
+ return {
54
+ model: "easyops.FRONTEND_STAT",
55
+ columns: ["_ver", "st", "et", "lt", "size", "time", "traceId", "code", "duration", "page", "uid", "username", "api", "type", "msg", "status", "pageId", "route", "apiCount", "maxApiTimeCost", "apiSizeCost", "pageTitle"],
56
+ data
57
+ };
58
+ }
59
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","names":["events","exports","MAXIMUM_WAITING_TIME","MAXIMUM_LOGGED_EVENTS","timer","transportOptions","maxWaitingTime","maxLoggedEvents","createTransport","api","options","Object","assign","sendOnExit","emit","nextTime","callback","window","requestIdleCallback","requestAnimationFrame","cb","setTimeout","clearTimeout","length","send","transportEvents","splice","transportData","buildTransportData","sendBeacon","requestUrl","data","headers","type","blob","Blob","JSON","stringify","navigator","addEventListener","model","columns"],"sources":["../../../src/analytics/transport.ts"],"sourcesContent":["import { ApiMetric, PageViewMetric } from \"./interfaces.js\";\n\nexport const events: (ApiMetric | PageViewMetric)[] = [];\n\nconst MAXIMUM_WAITING_TIME = 5 * 1000;\nconst MAXIMUM_LOGGED_EVENTS = 10;\nlet timer: any = null;\n\nexport const transportOptions = {\n maxWaitingTime: MAXIMUM_WAITING_TIME,\n maxLoggedEvents: MAXIMUM_LOGGED_EVENTS,\n} as TransportOptions;\n\ntype TransportData = {\n model: string;\n columns: string[];\n data: (ApiMetric | PageViewMetric)[];\n};\n\nexport interface TransportOptions {\n api: string;\n maxWaitingTime: number;\n maxLoggedEvents: number;\n}\n\nexport function createTransport(\n api: string,\n options: Partial<TransportOptions>\n) {\n Object.assign(transportOptions, { ...options, api });\n return {\n sendOnExit,\n emit,\n };\n}\n\nfunction nextTime(callback: (data: unknown) => void): unknown {\n return (\n window.requestIdleCallback ||\n window.requestAnimationFrame ||\n ((cb: (data: Record<string, any>) => void) => setTimeout(cb, 17))\n )(callback);\n}\n\nfunction emit() {\n clearTimeout(timer);\n events.length > transportOptions.maxLoggedEvents\n ? send()\n : (timer = setTimeout(send, transportOptions.maxWaitingTime));\n}\n\nfunction send() {\n if (events.length === 0) {\n return;\n }\n const transportEvents = events.splice(0, transportOptions.maxLoggedEvents);\n const transportData = buildTransportData(transportEvents);\n\n sendBeacon(transportOptions.api, transportData);\n\n events.length && nextTime(send);\n}\n\nfunction sendBeacon(requestUrl: string, data: TransportData) {\n const headers = {\n type: \"application/json\",\n };\n\n const blob = new Blob([JSON.stringify(data)], headers);\n window.navigator.sendBeacon(requestUrl, blob);\n}\n\nfunction sendOnExit() {\n window.addEventListener(\"beforeunload\", send, false);\n}\n\nfunction buildTransportData(data: (ApiMetric | PageViewMetric)[]) {\n return {\n model: \"easyops.FRONTEND_STAT\",\n columns: [\n \"_ver\",\n \"st\",\n \"et\",\n \"lt\",\n \"size\",\n \"time\",\n \"traceId\",\n \"code\",\n \"duration\",\n \"page\",\n \"uid\",\n \"username\",\n \"api\",\n \"type\",\n \"msg\",\n \"status\",\n \"pageId\",\n \"route\",\n \"apiCount\",\n \"maxApiTimeCost\",\n \"apiSizeCost\",\n \"pageTitle\",\n ],\n data,\n };\n}\n"],"mappings":";;;;;;;AAEO,MAAMA,MAAsC,GAAAC,OAAA,CAAAD,MAAA,GAAG,EAAE;AAExD,MAAME,oBAAoB,GAAG,CAAC,GAAG,IAAI;AACrC,MAAMC,qBAAqB,GAAG,EAAE;AAChC,IAAIC,KAAU,GAAG,IAAI;AAEd,MAAMC,gBAAgB,GAAAJ,OAAA,CAAAI,gBAAA,GAAG;EAC9BC,cAAc,EAAEJ,oBAAoB;EACpCK,eAAe,EAAEJ;AACnB,CAAqB;AAcd,SAASK,eAAeA,CAC7BC,GAAW,EACXC,OAAkC,EAClC;EACAC,MAAM,CAACC,MAAM,CAACP,gBAAgB,EAAE;IAAE,GAAGK,OAAO;IAAED;EAAI,CAAC,CAAC;EACpD,OAAO;IACLI,UAAU;IACVC;EACF,CAAC;AACH;AAEA,SAASC,QAAQA,CAACC,QAAiC,EAAW;EAC5D,OAAO,CACLC,MAAM,CAACC,mBAAmB,IAC1BD,MAAM,CAACE,qBAAqB,KAC1BC,EAAuC,IAAKC,UAAU,CAACD,EAAE,EAAE,EAAE,CAAC,CAAC,EACjEJ,QAAQ,CAAC;AACb;AAEA,SAASF,IAAIA,CAAA,EAAG;EACdQ,YAAY,CAAClB,KAAK,CAAC;EACnBJ,MAAM,CAACuB,MAAM,GAAGlB,gBAAgB,CAACE,eAAe,GAC5CiB,IAAI,CAAC,CAAC,GACLpB,KAAK,GAAGiB,UAAU,CAACG,IAAI,EAAEnB,gBAAgB,CAACC,cAAc,CAAE;AACjE;AAEA,SAASkB,IAAIA,CAAA,EAAG;EACd,IAAIxB,MAAM,CAACuB,MAAM,KAAK,CAAC,EAAE;IACvB;EACF;EACA,MAAME,eAAe,GAAGzB,MAAM,CAAC0B,MAAM,CAAC,CAAC,EAAErB,gBAAgB,CAACE,eAAe,CAAC;EAC1E,MAAMoB,aAAa,GAAGC,kBAAkB,CAACH,eAAe,CAAC;EAEzDI,UAAU,CAACxB,gBAAgB,CAACI,GAAG,EAAEkB,aAAa,CAAC;EAE/C3B,MAAM,CAACuB,MAAM,IAAIR,QAAQ,CAACS,IAAI,CAAC;AACjC;AAEA,SAASK,UAAUA,CAACC,UAAkB,EAAEC,IAAmB,EAAE;EAC3D,MAAMC,OAAO,GAAG;IACdC,IAAI,EAAE;EACR,CAAC;EAED,MAAMC,IAAI,GAAG,IAAIC,IAAI,CAAC,CAACC,IAAI,CAACC,SAAS,CAACN,IAAI,CAAC,CAAC,EAAEC,OAAO,CAAC;EACtDf,MAAM,CAACqB,SAAS,CAACT,UAAU,CAACC,UAAU,EAAEI,IAAI,CAAC;AAC/C;AAEA,SAASrB,UAAUA,CAAA,EAAG;EACpBI,MAAM,CAACsB,gBAAgB,CAAC,cAAc,EAAEf,IAAI,EAAE,KAAK,CAAC;AACtD;AAEA,SAASI,kBAAkBA,CAACG,IAAoC,EAAE;EAChE,OAAO;IACLS,KAAK,EAAE,uBAAuB;IAC9BC,OAAO,EAAE,CACP,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,MAAM,EACN,SAAS,EACT,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,UAAU,EACV,KAAK,EACL,MAAM,EACN,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,CACZ;IACDV;EACF,CAAC;AACH"}
@@ -1,31 +1,20 @@
1
1
  import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ import { createTransport, events } from "./transport.js";
2
3
  var initialized = false;
4
+ var transport;
3
5
  var pageState = null;
4
6
  var isFirstPageView = true;
5
7
  var stashedApiMetrics = [];
6
- var allMetrics = [];
7
8
  export function initialize(api) {
9
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8
10
  if (initialized) {
9
11
  return;
10
12
  }
11
13
  initialized = true;
12
- function upload() {
13
- if (allMetrics.length === 0) {
14
- return;
15
- }
16
- var headers = {
17
- type: "application/json"
18
- };
19
- var data = {
20
- model: "easyops.FRONTEND_STAT",
21
- columns: ["_ver", "st", "et", "lt", "size", "time", "traceId", "code", "duration", "page", "uid", "username", "api", "type", "msg", "status", "pageId", "route", "apiCount", "maxApiTimeCost", "apiSizeCost", "pageTitle"],
22
- data: allMetrics
23
- };
24
- var blob = new Blob([JSON.stringify(data)], headers);
25
- allMetrics.length = 0;
26
- window.navigator.sendBeacon(api, blob);
14
+ if (!transport) {
15
+ transport = createTransport(api, options);
16
+ transport.sendOnExit();
27
17
  }
28
- window.addEventListener("beforeunload", upload, false);
29
18
  }
30
19
  export function createPageView() {
31
20
  stashedApiMetrics.length = 0;
@@ -42,24 +31,25 @@ export function finishPageView(metric) {
42
31
  route,
43
32
  pageId
44
33
  };
45
- allMetrics.push(_objectSpread(_objectSpread({}, metric), {}, {
34
+ events.push(_objectSpread(_objectSpread({}, metric), {}, {
46
35
  pageId,
47
36
  apiCount: stashedApiMetrics.length,
48
37
  maxApiTimeCost: Math.max(0, ...stashedApiMetrics.map(api => api.duration)),
49
38
  size: stashedApiMetrics.map(api => api.size).filter(size => size > 0).reduce((prev, current) => prev + current, 0)
50
39
  }));
51
40
  for (var item of stashedApiMetrics) {
52
- allMetrics.push(_objectSpread(_objectSpread({}, item), pageState));
41
+ events.push(_objectSpread(_objectSpread({}, item), pageState));
53
42
  }
54
43
  stashedApiMetrics.length = 0;
44
+ transport.emit();
55
45
  }
56
46
  export function earlyFinishPageView() {
57
- allMetrics.push(...stashedApiMetrics);
47
+ events.push(...stashedApiMetrics);
58
48
  stashedApiMetrics.length = 0;
59
49
  }
60
50
  export function pushApiMetric(metric) {
61
51
  if (pageState) {
62
- allMetrics.push(_objectSpread(_objectSpread({}, metric), {}, {
52
+ events.push(_objectSpread(_objectSpread({}, metric), {}, {
63
53
  type: "apiRequest"
64
54
  }, pageState));
65
55
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.js","names":["initialized","pageState","isFirstPageView","stashedApiMetrics","allMetrics","initialize","api","upload","length","headers","type","data","model","columns","blob","Blob","JSON","stringify","window","navigator","sendBeacon","addEventListener","createPageView","finishPageView","metric","pageId","generateUUID","lt","route","push","_objectSpread","apiCount","maxApiTimeCost","Math","max","map","duration","size","filter","reduce","prev","current","item","earlyFinishPageView","pushApiMetric","url","URL","createObjectURL","uuid","substring","lastIndexOf","revokeObjectURL"],"sources":["../../../src/analytics/analytics.ts"],"sourcesContent":["import type {\n ApiMetric,\n ApiPageState,\n PageViewMetric,\n PartialPageViewMetric,\n} from \"./interfaces.js\";\n\nlet initialized = false;\nlet pageState: ApiPageState | null = null;\nlet isFirstPageView = true;\nconst stashedApiMetrics: ApiMetric[] = [];\n\nconst allMetrics: (ApiMetric | PageViewMetric)[] = [];\n\nexport function initialize(api: string) {\n if (initialized) {\n return;\n }\n initialized = true;\n\n function upload() {\n if (allMetrics.length === 0) {\n return;\n }\n const headers = {\n type: \"application/json\",\n };\n const data = {\n model: \"easyops.FRONTEND_STAT\",\n columns: [\n \"_ver\",\n \"st\",\n \"et\",\n \"lt\",\n \"size\",\n \"time\",\n \"traceId\",\n \"code\",\n \"duration\",\n \"page\",\n \"uid\",\n \"username\",\n \"api\",\n \"type\",\n \"msg\",\n \"status\",\n \"pageId\",\n \"route\",\n \"apiCount\",\n \"maxApiTimeCost\",\n \"apiSizeCost\",\n \"pageTitle\",\n ],\n data: allMetrics,\n };\n const blob = new Blob([JSON.stringify(data)], headers);\n allMetrics.length = 0;\n\n window.navigator.sendBeacon(api, blob);\n }\n\n window.addEventListener(\"beforeunload\", upload, false);\n}\n\nexport function createPageView() {\n stashedApiMetrics.length = 0;\n pageState = null;\n}\n\nexport function finishPageView(metric: PartialPageViewMetric) {\n const pageId = generateUUID();\n const { lt, route } = metric;\n pageState = { lt, route, pageId };\n\n allMetrics.push({\n ...metric,\n pageId,\n apiCount: stashedApiMetrics.length,\n maxApiTimeCost: Math.max(\n 0,\n ...stashedApiMetrics.map((api) => api.duration)\n ),\n size: stashedApiMetrics\n .map((api) => api.size)\n .filter((size) => size > 0)\n .reduce((prev, current) => prev + current, 0),\n });\n\n for (const item of stashedApiMetrics) {\n allMetrics.push({\n ...item,\n ...pageState,\n });\n }\n stashedApiMetrics.length = 0;\n}\n\nexport function earlyFinishPageView() {\n allMetrics.push(...stashedApiMetrics);\n stashedApiMetrics.length = 0;\n}\n\nexport function pushApiMetric(metric: ApiMetric) {\n if (pageState) {\n allMetrics.push({\n ...metric,\n type: \"apiRequest\",\n ...pageState,\n });\n } else {\n stashedApiMetrics.push(metric);\n }\n}\n\n// Ref https://medium.com/teads-engineering/generating-uuids-at-scale-on-the-web-2877f529d2a2\nfunction generateUUID() {\n const url = URL.createObjectURL(new Blob([]));\n let uuid = url.substring(url.lastIndexOf(\"/\") + 1);\n URL.revokeObjectURL(url);\n // 第一次渲染加上特殊标记\n if (isFirstPageView) {\n uuid = \"88-\" + uuid;\n isFirstPageView = false;\n }\n return uuid;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"analytics.js","names":["createTransport","events","initialized","transport","pageState","isFirstPageView","stashedApiMetrics","initialize","api","options","arguments","length","undefined","sendOnExit","createPageView","finishPageView","metric","pageId","generateUUID","lt","route","push","_objectSpread","apiCount","maxApiTimeCost","Math","max","map","duration","size","filter","reduce","prev","current","item","emit","earlyFinishPageView","pushApiMetric","type","url","URL","createObjectURL","Blob","uuid","substring","lastIndexOf","revokeObjectURL"],"sources":["../../../src/analytics/analytics.ts"],"sourcesContent":["import type {\n ApiMetric,\n ApiPageState,\n PartialPageViewMetric,\n} from \"./interfaces.js\";\nimport { createTransport, events, TransportOptions } from \"./transport.js\";\n\nlet initialized = false;\nlet transport: ReturnType<typeof createTransport>;\nlet pageState: ApiPageState | null = null;\nlet isFirstPageView = true;\nconst stashedApiMetrics: ApiMetric[] = [];\n\ntype Options = Partial<TransportOptions>;\n\nexport function initialize(api: string, options: Options = {}) {\n if (initialized) {\n return;\n }\n initialized = true;\n if (!transport) {\n transport = createTransport(api, options);\n transport.sendOnExit();\n }\n}\n\nexport function createPageView() {\n stashedApiMetrics.length = 0;\n pageState = null;\n}\n\nexport function finishPageView(metric: PartialPageViewMetric) {\n const pageId = generateUUID();\n const { lt, route } = metric;\n pageState = { lt, route, pageId };\n\n events.push({\n ...metric,\n pageId,\n apiCount: stashedApiMetrics.length,\n maxApiTimeCost: Math.max(\n 0,\n ...stashedApiMetrics.map((api) => api.duration)\n ),\n size: stashedApiMetrics\n .map((api) => api.size)\n .filter((size) => size > 0)\n .reduce((prev, current) => prev + current, 0),\n });\n\n for (const item of stashedApiMetrics) {\n events.push({\n ...item,\n ...pageState,\n });\n }\n stashedApiMetrics.length = 0;\n\n transport.emit();\n}\n\nexport function earlyFinishPageView() {\n events.push(...stashedApiMetrics);\n stashedApiMetrics.length = 0;\n}\n\nexport function pushApiMetric(metric: ApiMetric) {\n if (pageState) {\n events.push({\n ...metric,\n type: \"apiRequest\",\n ...pageState,\n });\n } else {\n stashedApiMetrics.push(metric);\n }\n}\n\n// Ref https://medium.com/teads-engineering/generating-uuids-at-scale-on-the-web-2877f529d2a2\nfunction generateUUID() {\n const url = URL.createObjectURL(new Blob([]));\n let uuid = url.substring(url.lastIndexOf(\"/\") + 1);\n URL.revokeObjectURL(url);\n // 第一次渲染加上特殊标记\n if (isFirstPageView) {\n uuid = \"88-\" + uuid;\n isFirstPageView = false;\n }\n return uuid;\n}\n"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import _objectSpread from "@babel/runtime/helpers/objectSpread2";
2
+ export var events = [];
3
+ var MAXIMUM_WAITING_TIME = 5 * 1000;
4
+ var MAXIMUM_LOGGED_EVENTS = 10;
5
+ var timer = null;
6
+ export var transportOptions = {
7
+ maxWaitingTime: MAXIMUM_WAITING_TIME,
8
+ maxLoggedEvents: MAXIMUM_LOGGED_EVENTS
9
+ };
10
+ export function createTransport(api, options) {
11
+ Object.assign(transportOptions, _objectSpread(_objectSpread({}, options), {}, {
12
+ api
13
+ }));
14
+ return {
15
+ sendOnExit,
16
+ emit
17
+ };
18
+ }
19
+ function nextTime(callback) {
20
+ return (window.requestIdleCallback || window.requestAnimationFrame || (cb => setTimeout(cb, 17)))(callback);
21
+ }
22
+ function emit() {
23
+ clearTimeout(timer);
24
+ events.length > transportOptions.maxLoggedEvents ? send() : timer = setTimeout(send, transportOptions.maxWaitingTime);
25
+ }
26
+ function send() {
27
+ if (events.length === 0) {
28
+ return;
29
+ }
30
+ var transportEvents = events.splice(0, transportOptions.maxLoggedEvents);
31
+ var transportData = buildTransportData(transportEvents);
32
+ sendBeacon(transportOptions.api, transportData);
33
+ events.length && nextTime(send);
34
+ }
35
+ function sendBeacon(requestUrl, data) {
36
+ var headers = {
37
+ type: "application/json"
38
+ };
39
+ var blob = new Blob([JSON.stringify(data)], headers);
40
+ window.navigator.sendBeacon(requestUrl, blob);
41
+ }
42
+ function sendOnExit() {
43
+ window.addEventListener("beforeunload", send, false);
44
+ }
45
+ function buildTransportData(data) {
46
+ return {
47
+ model: "easyops.FRONTEND_STAT",
48
+ columns: ["_ver", "st", "et", "lt", "size", "time", "traceId", "code", "duration", "page", "uid", "username", "api", "type", "msg", "status", "pageId", "route", "apiCount", "maxApiTimeCost", "apiSizeCost", "pageTitle"],
49
+ data
50
+ };
51
+ }
52
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","names":["events","MAXIMUM_WAITING_TIME","MAXIMUM_LOGGED_EVENTS","timer","transportOptions","maxWaitingTime","maxLoggedEvents","createTransport","api","options","Object","assign","_objectSpread","sendOnExit","emit","nextTime","callback","window","requestIdleCallback","requestAnimationFrame","cb","setTimeout","clearTimeout","length","send","transportEvents","splice","transportData","buildTransportData","sendBeacon","requestUrl","data","headers","type","blob","Blob","JSON","stringify","navigator","addEventListener","model","columns"],"sources":["../../../src/analytics/transport.ts"],"sourcesContent":["import { ApiMetric, PageViewMetric } from \"./interfaces.js\";\n\nexport const events: (ApiMetric | PageViewMetric)[] = [];\n\nconst MAXIMUM_WAITING_TIME = 5 * 1000;\nconst MAXIMUM_LOGGED_EVENTS = 10;\nlet timer: any = null;\n\nexport const transportOptions = {\n maxWaitingTime: MAXIMUM_WAITING_TIME,\n maxLoggedEvents: MAXIMUM_LOGGED_EVENTS,\n} as TransportOptions;\n\ntype TransportData = {\n model: string;\n columns: string[];\n data: (ApiMetric | PageViewMetric)[];\n};\n\nexport interface TransportOptions {\n api: string;\n maxWaitingTime: number;\n maxLoggedEvents: number;\n}\n\nexport function createTransport(\n api: string,\n options: Partial<TransportOptions>\n) {\n Object.assign(transportOptions, { ...options, api });\n return {\n sendOnExit,\n emit,\n };\n}\n\nfunction nextTime(callback: (data: unknown) => void): unknown {\n return (\n window.requestIdleCallback ||\n window.requestAnimationFrame ||\n ((cb: (data: Record<string, any>) => void) => setTimeout(cb, 17))\n )(callback);\n}\n\nfunction emit() {\n clearTimeout(timer);\n events.length > transportOptions.maxLoggedEvents\n ? send()\n : (timer = setTimeout(send, transportOptions.maxWaitingTime));\n}\n\nfunction send() {\n if (events.length === 0) {\n return;\n }\n const transportEvents = events.splice(0, transportOptions.maxLoggedEvents);\n const transportData = buildTransportData(transportEvents);\n\n sendBeacon(transportOptions.api, transportData);\n\n events.length && nextTime(send);\n}\n\nfunction sendBeacon(requestUrl: string, data: TransportData) {\n const headers = {\n type: \"application/json\",\n };\n\n const blob = new Blob([JSON.stringify(data)], headers);\n window.navigator.sendBeacon(requestUrl, blob);\n}\n\nfunction sendOnExit() {\n window.addEventListener(\"beforeunload\", send, false);\n}\n\nfunction buildTransportData(data: (ApiMetric | PageViewMetric)[]) {\n return {\n model: \"easyops.FRONTEND_STAT\",\n columns: [\n \"_ver\",\n \"st\",\n \"et\",\n \"lt\",\n \"size\",\n \"time\",\n \"traceId\",\n \"code\",\n \"duration\",\n \"page\",\n \"uid\",\n \"username\",\n \"api\",\n \"type\",\n \"msg\",\n \"status\",\n \"pageId\",\n \"route\",\n \"apiCount\",\n \"maxApiTimeCost\",\n \"apiSizeCost\",\n \"pageTitle\",\n ],\n data,\n };\n}\n"],"mappings":";AAEA,OAAO,IAAMA,MAAsC,GAAG,EAAE;AAExD,IAAMC,oBAAoB,GAAG,CAAC,GAAG,IAAI;AACrC,IAAMC,qBAAqB,GAAG,EAAE;AAChC,IAAIC,KAAU,GAAG,IAAI;AAErB,OAAO,IAAMC,gBAAgB,GAAG;EAC9BC,cAAc,EAAEJ,oBAAoB;EACpCK,eAAe,EAAEJ;AACnB,CAAqB;AAcrB,OAAO,SAASK,eAAeA,CAC7BC,GAAW,EACXC,OAAkC,EAClC;EACAC,MAAM,CAACC,MAAM,CAACP,gBAAgB,EAAAQ,aAAA,CAAAA,aAAA,KAAOH,OAAO;IAAED;EAAG,EAAE,CAAC;EACpD,OAAO;IACLK,UAAU;IACVC;EACF,CAAC;AACH;AAEA,SAASC,QAAQA,CAACC,QAAiC,EAAW;EAC5D,OAAO,CACLC,MAAM,CAACC,mBAAmB,IAC1BD,MAAM,CAACE,qBAAqB,KAC1BC,EAAuC,IAAKC,UAAU,CAACD,EAAE,EAAE,EAAE,CAAC,CAAC,EACjEJ,QAAQ,CAAC;AACb;AAEA,SAASF,IAAIA,CAAA,EAAG;EACdQ,YAAY,CAACnB,KAAK,CAAC;EACnBH,MAAM,CAACuB,MAAM,GAAGnB,gBAAgB,CAACE,eAAe,GAC5CkB,IAAI,CAAC,CAAC,GACLrB,KAAK,GAAGkB,UAAU,CAACG,IAAI,EAAEpB,gBAAgB,CAACC,cAAc,CAAE;AACjE;AAEA,SAASmB,IAAIA,CAAA,EAAG;EACd,IAAIxB,MAAM,CAACuB,MAAM,KAAK,CAAC,EAAE;IACvB;EACF;EACA,IAAME,eAAe,GAAGzB,MAAM,CAAC0B,MAAM,CAAC,CAAC,EAAEtB,gBAAgB,CAACE,eAAe,CAAC;EAC1E,IAAMqB,aAAa,GAAGC,kBAAkB,CAACH,eAAe,CAAC;EAEzDI,UAAU,CAACzB,gBAAgB,CAACI,GAAG,EAAEmB,aAAa,CAAC;EAE/C3B,MAAM,CAACuB,MAAM,IAAIR,QAAQ,CAACS,IAAI,CAAC;AACjC;AAEA,SAASK,UAAUA,CAACC,UAAkB,EAAEC,IAAmB,EAAE;EAC3D,IAAMC,OAAO,GAAG;IACdC,IAAI,EAAE;EACR,CAAC;EAED,IAAMC,IAAI,GAAG,IAAIC,IAAI,CAAC,CAACC,IAAI,CAACC,SAAS,CAACN,IAAI,CAAC,CAAC,EAAEC,OAAO,CAAC;EACtDf,MAAM,CAACqB,SAAS,CAACT,UAAU,CAACC,UAAU,EAAEI,IAAI,CAAC;AAC/C;AAEA,SAASrB,UAAUA,CAAA,EAAG;EACpBI,MAAM,CAACsB,gBAAgB,CAAC,cAAc,EAAEf,IAAI,EAAE,KAAK,CAAC;AACtD;AAEA,SAASI,kBAAkBA,CAACG,IAAoC,EAAE;EAChE,OAAO;IACLS,KAAK,EAAE,uBAAuB;IAC9BC,OAAO,EAAE,CACP,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,MAAM,EACN,SAAS,EACT,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,UAAU,EACV,KAAK,EACL,MAAM,EACN,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,CACZ;IACDV;EACF,CAAC;AACH"}
@@ -1,6 +1,9 @@
1
1
  import type { ApiMetric, PartialPageViewMetric } from "./interfaces.js";
2
- export declare function initialize(api: string): void;
2
+ import { TransportOptions } from "./transport.js";
3
+ type Options = Partial<TransportOptions>;
4
+ export declare function initialize(api: string, options?: Options): void;
3
5
  export declare function createPageView(): void;
4
6
  export declare function finishPageView(metric: PartialPageViewMetric): void;
5
7
  export declare function earlyFinishPageView(): void;
6
8
  export declare function pushApiMetric(metric: ApiMetric): void;
9
+ export {};
@@ -0,0 +1,15 @@
1
+ import { ApiMetric, PageViewMetric } from "./interfaces.js";
2
+ export declare const events: (ApiMetric | PageViewMetric)[];
3
+ export declare const transportOptions: TransportOptions;
4
+ export interface TransportOptions {
5
+ api: string;
6
+ maxWaitingTime: number;
7
+ maxLoggedEvents: number;
8
+ }
9
+ export declare function createTransport(api: string, options: Partial<TransportOptions>): {
10
+ sendOnExit: typeof sendOnExit;
11
+ emit: typeof emit;
12
+ };
13
+ declare function emit(): void;
14
+ declare function sendOnExit(): void;
15
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-core/easyops-runtime",
3
- "version": "0.6.67",
3
+ "version": "0.7.1",
4
4
  "homepage": "https://github.com/easyops-cn/next-core/tree/v3/packages/easyops-runtime",
5
5
  "license": "GPL-3.0",
6
6
  "repository": {
@@ -47,7 +47,7 @@
47
47
  "@next-core/cook": "^2.2.11",
48
48
  "@next-core/http": "^1.1.8",
49
49
  "@next-core/pipes": "^2.0.15",
50
- "@next-core/runtime": "^1.30.0",
50
+ "@next-core/runtime": "^1.30.1",
51
51
  "@next-core/types": "^1.8.0",
52
52
  "@next-core/utils": "^1.6.9",
53
53
  "js-yaml": "^3.14.1",
@@ -59,5 +59,5 @@
59
59
  "jest-websocket-mock": "^2.5.0",
60
60
  "whatwg-fetch": "^3.6.20"
61
61
  },
62
- "gitHead": "e95c6b5b0bffa483cdbb8304afe9535da25da53f"
62
+ "gitHead": "f8cedf07d4238ea959f13e3ee42ee6e3bb300506"
63
63
  }