@lwrjs/o11y 0.6.0-alpha.8 → 0.6.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";class e{constructor(t){this.marks={},this.instrumentation=t}track(){this.trackExistingMarks(),this.setupObserver()}trackExistingMarks(){const t=performance.getEntriesByType("mark").filter((t=>t.name.startsWith("lwr.bootstrap.")));for(const r of t){const{name:t}=r;this.marks[t]=r,performance.clearMarks(t)}}setupObserver(){let t=0;new PerformanceObserver((r=>{const e=[];r.getEntries().forEach((r=>{const{name:s,entryType:a}=r;"mark"===a&&s.startsWith("lwr.")&&e.push(r),"lwr.bootstrap.end"===s&&(this.marks[s]=r),"lwr.bootstrap.error"===s&&(t+=1)})),void 0!==this.marks["lwr.bootstrap.end"]&&(this.instrumentation.trackValue("lwr.bootstrap.duration",this.marks["lwr.bootstrap.end"].startTime),this.instrumentation.trackValue("lwr.bootstrap.availability",1/(1+t)*100),delete this.marks["lwr.bootstrap.end"]);const s=e.reduce(((t,r)=>r.name.startsWith("lwr.loader.module.fetch")?t+1:t),0);s>0&&this.instrumentation.incrementCounter("lwr.loader.module.fetch.count",s);const a=e.reduce(((t,r)=>r.name.startsWith("lwr.loader.mappings.fetch")?t+1:t),0);a>0&&this.instrumentation.incrementCounter("lwr.loader.mappings.fetch.count",a),e.forEach((t=>performance.clearMarks(t.name)))})).observe({entryTypes:["mark"]})}}r(e,{fields:["marks"]});const s=void 0!==globalThis.performance&&"function"==typeof globalThis.performance.mark,a={track:()=>{}};function o(r){const o=t("lwrjs.instrumentation");(s?new e(o):a).track()}export default o;
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;
@@ -10,12 +10,13 @@ const noop = () => {// noop
10
10
  const noopSink = {
11
11
  track: noop
12
12
  };
13
+ const NAMESPACE = 'lwrjs';
13
14
  /**
14
15
  * Sets up o11y instrumentation instance.
15
16
  */
16
17
 
17
- export default function hookO11yClient(loaderServices) {
18
- const instrumentation = getInstrumentation('lwrjs.instrumentation');
18
+ export default function hookO11yClient(serviceApi) {
19
+ const instrumentation = getInstrumentation(NAMESPACE);
19
20
  const sink = isPerfSupported ? new PerformanceApiSink(instrumentation) : noopSink;
20
21
  sink.track();
21
22
  }
@@ -1,13 +1,4 @@
1
- // TODO: import constants from shared util module
2
- const BOOTSTRAP_MARK = 'lwr.bootstrap.';
3
- const BOOTSTRAP_END_MARK = 'lwr.bootstrap.end';
4
- const BOOTSTRAP_ERROR_MARK = 'lwr.bootstrap.error';
5
- const BOOTSTRAP_DURATION_OP = 'lwr.bootstrap.duration';
6
- const BOOTSTRAP_AVAILABILITY_OP = 'lwr.bootstrap.availability';
7
- const LOADER_MODULE_FETCH = 'lwr.loader.module.fetch';
8
- const LOADER_MODULE_FETCH_COUNT = 'lwr.loader.module.fetch.count';
9
- const LOADER_MAPPING_FETCH = 'lwr.loader.mappings.fetch';
10
- const LOADER_MAPPING_FETCH_COUNT = 'lwr.loader.mappings.fetch.count';
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';
11
2
  export class PerformanceApiSink {
12
3
  marks = {};
13
4
 
@@ -18,23 +9,29 @@ export class PerformanceApiSink {
18
9
  track() {
19
10
  this.trackExistingMarks();
20
11
  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);
21
19
  } // Retrieve existing metrics to this point
22
20
 
23
21
 
24
22
  trackExistingMarks() {
25
23
  /**
26
- * Bootstrap marks prior to service bootstrap:
27
- * - lwr.bootstrap.init
28
- * - lwr.bootstrap.application
24
+ * Loader define marks prior to service bootstrap
29
25
  */
30
- const marks = performance.getEntriesByType('mark').filter(e => e.name.startsWith(BOOTSTRAP_MARK)); // TODO: saved these marks for now, but do we have real usages for them?
31
-
32
- for (const mark of marks) {
33
- const {
34
- name
35
- } = mark;
36
- this.marks[name] = mark;
37
- performance.clearMarks(name);
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
+ // - required modules
29
+ // - preload modules
30
+ // - the application bootstrap module
31
+ // - the loader module itself
32
+
33
+ if (marks.length > 0) {
34
+ this.instrumentation.incrementCounter(MODULE_DEFINE_COUNT, marks.length);
38
35
  }
39
36
  } // Add observer to log future metrics
40
37
  // observe lwr client runtime performance metrics
@@ -42,65 +39,88 @@ export class PerformanceApiSink {
42
39
 
43
40
  setupObserver() {
44
41
  let bootstrapErrorCount = 0;
42
+ let loaderModuleErrorCount = 0;
43
+ let loaderMappingsErrorcount = 0;
45
44
  const observer = new PerformanceObserver(list => {
46
45
  // grab the lwr performance marks
47
46
  const marks = [];
48
47
  /**
49
- * Bootstrap marks after to service bootstrap:
50
- * - lwr.bootstrap.end
51
- * - lwr.bootstrap.error
52
- * Loader marks
53
- * - lwr.loader.*
48
+ * Bootstrap and Loader marks
54
49
  */
55
50
 
56
51
  list.getEntries().forEach(entry => {
57
52
  const {
58
53
  name,
59
- entryType
54
+ entryType,
55
+ duration
60
56
  } = entry;
61
57
 
62
58
  if (entryType === 'mark' && name.startsWith('lwr.')) {
63
59
  marks.push(entry);
64
60
  }
65
61
 
66
- if (name === BOOTSTRAP_END_MARK) {
62
+ if (name === BOOTSTRAP_END) {
67
63
  this.marks[name] = entry;
68
64
  }
69
65
 
70
- if (name === BOOTSTRAP_ERROR_MARK) {
66
+ if (name === BOOTSTRAP_ERROR) {
71
67
  bootstrapErrorCount += 1;
72
68
  }
69
+
70
+ if (name === MODULE_ERROR) {
71
+ loaderModuleErrorCount += 1;
72
+ }
73
+
74
+ if (name === MAPPINGS_ERROR) {
75
+ loaderMappingsErrorcount += 1;
76
+ }
77
+
78
+ if (name.startsWith(MODULE_FETCH_DURATION) || name.startsWith(MAPPINGS_FETCH_DURATION)) {
79
+ this.instrumentation.trackValue(name, duration);
80
+ }
73
81
  });
74
82
 
75
- if (this.marks[BOOTSTRAP_END_MARK] !== undefined) {
76
- this.instrumentation.trackValue(BOOTSTRAP_DURATION_OP, this.marks[BOOTSTRAP_END_MARK].startTime);
77
- this.instrumentation.trackValue(BOOTSTRAP_AVAILABILITY_OP, 1 / (1 + bootstrapErrorCount) * 100); // reset to prevent multiple reports
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
+
87
+ delete this.marks[BOOTSTRAP_END];
88
+ } // count how many modules were defined and report the count
89
+
78
90
 
79
- delete this.marks[BOOTSTRAP_END_MARK];
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);
80
97
  } // count how many modules were loaded and report the count
81
98
 
82
99
 
83
100
  const moduleLoadCount = marks.reduce((count, mark) => {
84
- return mark.name.startsWith(LOADER_MODULE_FETCH) ? count + 1 : count;
101
+ return mark.name.startsWith(MODULE_FETCH) ? count + 1 : count;
85
102
  }, 0);
86
103
 
87
104
  if (moduleLoadCount > 0) {
88
- this.instrumentation.incrementCounter(LOADER_MODULE_FETCH_COUNT, moduleLoadCount);
105
+ this.instrumentation.incrementCounter(MODULE_FETCH_COUNT, moduleLoadCount);
106
+ this.instrumentation.trackValue(MODULE_AVAILABILITY, moduleLoadCount / (moduleLoadCount + loaderModuleErrorCount) * 100);
89
107
  } // count how many mapping resources were loaded and report the count
90
108
 
91
109
 
92
110
  const mappingLoadCount = marks.reduce((count, mark) => {
93
- return mark.name.startsWith(LOADER_MAPPING_FETCH) ? count + 1 : count;
111
+ return mark.name.startsWith(MAPPINGS_FETCH) ? count + 1 : count;
94
112
  }, 0);
95
113
 
96
114
  if (mappingLoadCount > 0) {
97
- this.instrumentation.incrementCounter(LOADER_MAPPING_FETCH_COUNT, mappingLoadCount);
98
- }
115
+ this.instrumentation.incrementCounter(MAPPINGS_FETCH_COUNT, mappingLoadCount);
116
+ this.instrumentation.trackValue(MAPPINGS_AVAILABILITY, mappingLoadCount / (mappingLoadCount + loaderMappingsErrorcount) * 100);
117
+ } // remove clearable marks
118
+
99
119
 
100
- marks.forEach(mark => performance.clearMarks(mark.name));
120
+ marks.forEach(mark => this.isClearable(mark.name) && performance.clearMarks(mark.name));
101
121
  });
102
122
  observer.observe({
103
- entryTypes: ['mark']
123
+ entryTypes: ['mark', 'measure']
104
124
  });
105
125
  }
106
126
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.6.0-alpha.8",
7
+ "version": "0.6.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.0-alpha.8",
28
- "o11y": "238.1.2"
27
+ "@lwrjs/shared-utils": "0.6.1",
28
+ "o11y": "238.1.4"
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": "f57b843b079ef42fdd1e727521e5a88e70bf850a"
49
+ "gitHead": "4d7c44dfae958fe24ef1c94b0f60aa2b15e12f24"
50
50
  }