@lwrjs/o11y 0.6.2 → 0.7.0-alpha.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.
@@ -1 +1 @@
1
- import{getInstrumentation as t}from"o11y/client";import{registerDecorators as r}from"lwc";import{MODULE_FETCH as e,MAPPINGS_FETCH as s,MODULE_DEFINE as n,MODULE_DEFINE_COUNT as i,BOOTSTRAP_END as a,MODULE_FETCH_DURATION as o,MAPPINGS_FETCH_DURATION as m,BOOTSTRAP_DURATION as c,BOOTSTRAP_AVAILABILITY as h,MODULE_FETCH_COUNT as u,MODULE_AVAILABILITY as l,MAPPINGS_FETCH_COUNT as k,MAPPINGS_AVAILABILITY as f,BOOTSTRAP_ERROR as p,MODULE_ERROR as d,MAPPINGS_ERROR as W}from"lwr/metrics";class b{constructor(t){this.marks={},this.instrumentation=t}track(){this.trackExistingMarks(),this.setupObserver()}isClearable(t){return!t.startsWith(e)&&!t.startsWith(s)}trackExistingMarks(){const t=performance.getEntriesByType("mark").filter((t=>t.name.startsWith(n)));t.length>0&&this.instrumentation.incrementCounter(i,t.length)}setupObserver(){let t=0,r=0,b=0;new PerformanceObserver((g=>{const y=[];g.getEntries().forEach((e=>{const{name:s,entryType:n,duration:i}=e;"mark"===n&&s.startsWith("lwr.")&&y.push(e),s===a&&(this.marks[s]=e),s===p&&(t+=1),s===d&&(r+=1),s===W&&(b+=1),(s.startsWith(o)||s.startsWith(m))&&this.instrumentation.trackValue(s,i)})),void 0!==this.marks[a]&&(this.instrumentation.trackValue(c,this.marks[a].startTime),this.instrumentation.trackValue(h,1/(1+t)*100),delete this.marks[a]);const v=y.reduce(((t,r)=>r.name.startsWith(n)?t+1:t),0);v>0&&this.instrumentation.incrementCounter(i,v);const w=y.reduce(((t,r)=>r.name.startsWith(e)?t+1:t),0);w>0&&(this.instrumentation.incrementCounter(u,w),this.instrumentation.trackValue(l,w/(w+r)*100));const C=y.reduce(((t,r)=>r.name.startsWith(s)?t+1:t),0);C>0&&(this.instrumentation.incrementCounter(k,C),this.instrumentation.trackValue(f,C/(C+b)*100)),y.forEach((t=>this.isClearable(t.name)&&performance.clearMarks(t.name)))})).observe({entryTypes:["mark","measure"]})}}r(b,{fields:["marks"]});const g=void 0!==globalThis.performance&&"function"==typeof globalThis.performance.mark,y={track:()=>{}};function v(r){const e=t("lwrjs");(g?new b(e):y).track()}export default v;
1
+ import{getInstrumentation as t}from"o11y/client";import{MODULE_DEFINE as e,MODULE_DEFINE_COUNT as r,BOOTSTRAP_END as n,BOOTSTRAP_DURATION as s,MODULE_FETCH_DURATION as i,MAPPINGS_FETCH_DURATION as a,MODULE_FETCH as o,MAPPINGS_FETCH as c,ROUTER_NAV as m,ROUTER_VIEW as h,ROUTER_NAV_DURATION as l,ROUTER_VIEW_DURATION as u,BOOTSTRAP_ERROR as f,BOOTSTRAP_ERROR_COUNT as k,MODULE_FETCH_COUNT as g,MODULE_ERROR as p,MODULE_ERROR_COUNT as b,MAPPINGS_FETCH_COUNT as T,MAPPINGS_ERROR as y,MAPPINGS_ERROR_COUNT as W,ROUTER_NAV_COUNT as d,ROUTER_ERROR as v,ROUTER_ERROR_COUNT as E}from"lwr/metrics";const M=[o,c,m,h],w=[l,u],O={[f]:k,[e]:r,[o]:g,[p]:b,[c]:T,[y]:W,[m]:d,[v]:E},V=Object.keys(O);class x{constructor(t,e){this.config=e||{},this.instrumentation=t}track(){this.trackExistingMarks(),this.setupObserver()}trackExistingMarks(){const t=performance.getEntriesByType("mark").filter((t=>t.name.startsWith(e)));t.length>0&&this.instrumentation.incrementCounter(r,t.length)}setupObserver(){new PerformanceObserver((t=>{t.getEntries().forEach((t=>{const{name:e,duration:r,startTime:o}=t;e===n&&this.instrumentation.trackValue(s,o);const c=V.find((t=>e.startsWith(t)));c&&this.instrumentation.incrementCounter(O[c],1),this.config.enableModuleFetchTracking&&e.startsWith(i)&&this.instrumentation.trackValue(e,r),this.config.enableMappingFetchTracking&&e.startsWith(a)&&this.instrumentation.trackValue(e,r),w.some((t=>e.startsWith(t)))&&this.instrumentation.trackValue(e,r),M.some((t=>e.startsWith(t)))||performance.clearMarks(e)}))})).observe({entryTypes:["mark","measure"]})}}const C=void 0!==globalThis.performance&&"function"==typeof globalThis.performance.mark,j=globalThis.LWR,F={track:()=>{}};function B(e){const r=t("lwrjs"),n=j.metricsConfig||{};(C?new x(r,n):F).track()}export default B;
@@ -3,6 +3,7 @@ import { PerformanceApiSink } from './performanceApiSink'; // Check if the Perfo
3
3
  // e.g. JSDom (used in Jest) doesn't implement these
4
4
 
5
5
  const isPerfSupported = typeof globalThis.performance !== 'undefined' && typeof globalThis.performance.mark === 'function';
6
+ const clientBootstrapConfig = globalThis.LWR;
6
7
 
7
8
  const noop = () => {// noop
8
9
  };
@@ -17,6 +18,7 @@ const NAMESPACE = 'lwrjs';
17
18
 
18
19
  export default function hookO11yClient(serviceApi) {
19
20
  const instrumentation = getInstrumentation(NAMESPACE);
20
- const sink = isPerfSupported ? new PerformanceApiSink(instrumentation) : noopSink;
21
+ const metricsConfig = clientBootstrapConfig.metricsConfig || {};
22
+ const sink = isPerfSupported ? new PerformanceApiSink(instrumentation, metricsConfig) : noopSink;
21
23
  sink.track();
22
24
  }
@@ -1,123 +1,82 @@
1
- import { BOOTSTRAP_AVAILABILITY, BOOTSTRAP_DURATION, BOOTSTRAP_END, BOOTSTRAP_ERROR, MAPPINGS_AVAILABILITY, MAPPINGS_ERROR, MAPPINGS_FETCH, MAPPINGS_FETCH_COUNT, MAPPINGS_FETCH_DURATION, MODULE_AVAILABILITY, MODULE_DEFINE, MODULE_DEFINE_COUNT, MODULE_ERROR, MODULE_FETCH, MODULE_FETCH_COUNT, MODULE_FETCH_DURATION } from 'lwr/metrics';
1
+ import { BOOTSTRAP_DURATION, BOOTSTRAP_END, BOOTSTRAP_ERROR, BOOTSTRAP_ERROR_COUNT, MAPPINGS_ERROR, MAPPINGS_ERROR_COUNT, MAPPINGS_FETCH, MAPPINGS_FETCH_COUNT, MAPPINGS_FETCH_DURATION, MODULE_DEFINE, MODULE_DEFINE_COUNT, MODULE_ERROR, MODULE_ERROR_COUNT, MODULE_FETCH, MODULE_FETCH_COUNT, MODULE_FETCH_DURATION, ROUTER_ERROR, ROUTER_ERROR_COUNT, ROUTER_NAV, ROUTER_NAV_COUNT, ROUTER_NAV_DURATION, ROUTER_VIEW, ROUTER_VIEW_DURATION } from 'lwr/metrics';
2
+ const doNotClear = [MODULE_FETCH, MAPPINGS_FETCH, ROUTER_NAV, ROUTER_VIEW];
3
+ const durationMetrics = [ROUTER_NAV_DURATION, ROUTER_VIEW_DURATION];
4
+ const countMap = {
5
+ [BOOTSTRAP_ERROR]: BOOTSTRAP_ERROR_COUNT,
6
+ [MODULE_DEFINE]: MODULE_DEFINE_COUNT,
7
+ [MODULE_FETCH]: MODULE_FETCH_COUNT,
8
+ [MODULE_ERROR]: MODULE_ERROR_COUNT,
9
+ [MAPPINGS_FETCH]: MAPPINGS_FETCH_COUNT,
10
+ [MAPPINGS_ERROR]: MAPPINGS_ERROR_COUNT,
11
+ [ROUTER_NAV]: ROUTER_NAV_COUNT,
12
+ [ROUTER_ERROR]: ROUTER_ERROR_COUNT
13
+ };
14
+ const metricsToCount = Object.keys(countMap);
2
15
  export class PerformanceApiSink {
3
- marks = {};
4
-
5
- constructor(instrumentation) {
16
+ constructor(instrumentation, config) {
17
+ this.config = config || {};
6
18
  this.instrumentation = instrumentation;
7
19
  }
8
20
 
9
21
  track() {
10
22
  this.trackExistingMarks();
11
23
  this.setupObserver();
12
- } // Return true if the mark is clearable
13
- // logOperationEnd clears the marks and measures passed to it, so these are NOT clearable
14
- // As of now, only "lwr.loader.*.fetch" metrics have durations (i.e. are not clearable)
15
-
16
-
17
- isClearable(name) {
18
- return !name.startsWith(MODULE_FETCH) && !name.startsWith(MAPPINGS_FETCH);
19
- } // Retrieve existing metrics to this point
24
+ } // Retrieve existing loader define metrics to this point
20
25
 
21
26
 
22
27
  trackExistingMarks() {
23
- /**
24
- * Loader define marks prior to service bootstrap
25
- */
26
- const marks = performance.getEntriesByType('mark').filter(e => e.name.startsWith(MODULE_DEFINE)); // initialize the module define count
27
- // at this point in time, the count will include modules NOT fetched by the loader:
28
+ const defineMarks = performance.getEntriesByType('mark').filter(e => e.name.startsWith(MODULE_DEFINE)); // Initialize the module define count
29
+ // At this point in time, the count will include modules NOT fetched by the loader:
28
30
  // - required modules
29
31
  // - preload modules
30
32
  // - the application bootstrap module
31
33
  // - the loader module itself
32
34
 
33
- if (marks.length > 0) {
34
- this.instrumentation.incrementCounter(MODULE_DEFINE_COUNT, marks.length);
35
+ if (defineMarks.length > 0) {
36
+ this.instrumentation.incrementCounter(MODULE_DEFINE_COUNT, defineMarks.length);
35
37
  }
36
38
  } // Add observer to log future metrics
37
- // observe lwr client runtime performance metrics
38
39
 
39
40
 
40
41
  setupObserver() {
41
- let bootstrapErrorCount = 0;
42
- let loaderModuleErrorCount = 0;
43
- let loaderMappingsErrorcount = 0;
44
42
  const observer = new PerformanceObserver(list => {
45
- // grab the lwr performance marks
46
- const marks = [];
47
- /**
48
- * Bootstrap and Loader marks
49
- */
50
-
51
43
  list.getEntries().forEach(entry => {
52
44
  const {
53
45
  name,
54
- entryType,
55
- duration
56
- } = entry;
57
-
58
- if (entryType === 'mark' && name.startsWith('lwr.')) {
59
- marks.push(entry);
60
- }
46
+ duration,
47
+ startTime
48
+ } = entry; // Track the bootstrap duration from navigation.start to lwr.bootstrap.end
61
49
 
62
50
  if (name === BOOTSTRAP_END) {
63
- this.marks[name] = entry;
64
- }
51
+ this.instrumentation.trackValue(BOOTSTRAP_DURATION, startTime);
52
+ } // Increment count metrics
65
53
 
66
- if (name === BOOTSTRAP_ERROR) {
67
- bootstrapErrorCount += 1;
68
- }
69
54
 
70
- if (name === MODULE_ERROR) {
71
- loaderModuleErrorCount += 1;
72
- }
55
+ const metricToCount = metricsToCount.find(c => name.startsWith(c));
73
56
 
74
- if (name === MAPPINGS_ERROR) {
75
- loaderMappingsErrorcount += 1;
76
- }
57
+ if (metricToCount) {
58
+ this.instrumentation.incrementCounter(countMap[metricToCount], 1);
59
+ } // Record duration metrics
77
60
 
78
- if (name.startsWith(MODULE_FETCH_DURATION) || name.startsWith(MAPPINGS_FETCH_DURATION)) {
61
+
62
+ if (this.config.enableModuleFetchTracking && name.startsWith(MODULE_FETCH_DURATION)) {
79
63
  this.instrumentation.trackValue(name, duration);
80
64
  }
81
- });
82
-
83
- if (this.marks[BOOTSTRAP_END] !== undefined) {
84
- this.instrumentation.trackValue(BOOTSTRAP_DURATION, this.marks[BOOTSTRAP_END].startTime);
85
- this.instrumentation.trackValue(BOOTSTRAP_AVAILABILITY, 1 / (1 + bootstrapErrorCount) * 100); // reset to prevent multiple reports
86
65
 
87
- delete this.marks[BOOTSTRAP_END];
88
- } // count how many modules were defined and report the count
89
-
90
-
91
- const moduleDefineCount = marks.reduce((count, mark) => {
92
- return mark.name.startsWith(MODULE_DEFINE) ? count + 1 : count;
93
- }, 0);
94
-
95
- if (moduleDefineCount > 0) {
96
- this.instrumentation.incrementCounter(MODULE_DEFINE_COUNT, moduleDefineCount);
97
- } // count how many modules were loaded and report the count
98
-
99
-
100
- const moduleLoadCount = marks.reduce((count, mark) => {
101
- return mark.name.startsWith(MODULE_FETCH) ? count + 1 : count;
102
- }, 0);
103
-
104
- if (moduleLoadCount > 0) {
105
- this.instrumentation.incrementCounter(MODULE_FETCH_COUNT, moduleLoadCount);
106
- this.instrumentation.trackValue(MODULE_AVAILABILITY, moduleLoadCount / (moduleLoadCount + loaderModuleErrorCount) * 100);
107
- } // count how many mapping resources were loaded and report the count
108
-
109
-
110
- const mappingLoadCount = marks.reduce((count, mark) => {
111
- return mark.name.startsWith(MAPPINGS_FETCH) ? count + 1 : count;
112
- }, 0);
66
+ if (this.config.enableMappingFetchTracking && name.startsWith(MAPPINGS_FETCH_DURATION)) {
67
+ this.instrumentation.trackValue(name, duration);
68
+ }
113
69
 
114
- if (mappingLoadCount > 0) {
115
- this.instrumentation.incrementCounter(MAPPINGS_FETCH_COUNT, mappingLoadCount);
116
- this.instrumentation.trackValue(MAPPINGS_AVAILABILITY, mappingLoadCount / (mappingLoadCount + loaderMappingsErrorcount) * 100);
117
- } // remove clearable marks
70
+ if (durationMetrics.some(d => name.startsWith(d))) {
71
+ this.instrumentation.trackValue(name, duration);
72
+ } // Remove clearable marks
73
+ // A mark is clearable if it does not have a corresponding logOperationEnd / measure
118
74
 
119
75
 
120
- marks.forEach(mark => this.isClearable(mark.name) && performance.clearMarks(mark.name));
76
+ if (!doNotClear.some(m => name.startsWith(m))) {
77
+ performance.clearMarks(name);
78
+ }
79
+ });
121
80
  });
122
81
  observer.observe({
123
82
  entryTypes: ['mark', 'measure']
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.6.2",
7
+ "version": "0.7.0-alpha.1",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -24,8 +24,8 @@
24
24
  "build:bundle": "rollup --config scripts/rollup.moduleBundle.config.cjs"
25
25
  },
26
26
  "dependencies": {
27
- "@lwrjs/shared-utils": "0.6.2",
28
- "o11y": "238.1.4"
27
+ "@lwrjs/shared-utils": "0.7.0-alpha.1",
28
+ "o11y": "238.9.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "rollup-plugin-terser": "^7.0.2"
@@ -46,5 +46,5 @@
46
46
  "engines": {
47
47
  "node": ">=14.15.4 <17"
48
48
  },
49
- "gitHead": "ef85bdc48adde58b7c648561d67acbb408bbe189"
49
+ "gitHead": "24245670d6908d37e465f2316f92385df63d22aa"
50
50
  }