@xh/hoist 73.0.0-SNAPSHOT.1744206740883 → 73.0.0-SNAPSHOT.1744228975863

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.
@@ -4,10 +4,11 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {HoistService, PlainObject, XH} from '@xh/hoist/core';
7
+ import {HoistService, PageState, PlainObject, XH} from '@xh/hoist/core';
8
8
  import {Timer} from '@xh/hoist/utils/async';
9
9
  import {MINUTES} from '@xh/hoist/utils/datetime';
10
- import {find, isPlainObject, pick, round} from 'lodash';
10
+ import {withFormattedTimestamps} from '@xh/hoist/format';
11
+ import {pick, round} from 'lodash';
11
12
 
12
13
  /**
13
14
  * Service for gathering data about client health.
@@ -31,19 +32,22 @@ export class ClientHealthService extends HoistService {
31
32
  }
32
33
 
33
34
  /**
34
- * Main Entry report. Return a default report of client health.
35
+ * Main entry point. Return a default report of client health.
35
36
  */
36
37
  getReport(): ClientHealthReport {
37
38
  return {
38
- session: this.getSession(),
39
- ...this.getCustom(),
39
+ general: this.getGeneral(),
40
40
  memory: this.getMemory(),
41
41
  connection: this.getConnection(),
42
- window: this.getWindow(),
43
- screen: this.getScreen()
42
+ ...this.getCustom()
44
43
  };
45
44
  }
46
45
 
46
+ /** Get report, suitable for viewing in console. **/
47
+ getFormattedReport(): PlainObject {
48
+ return withFormattedTimestamps(this.getReport());
49
+ }
50
+
47
51
  /**
48
52
  * Register a new source for client health report data. No-op if background health report is
49
53
  * not generally enabled via `xhActivityTrackingConfig.clientHealthReport.intervalMins`.
@@ -63,11 +67,16 @@ export class ClientHealthService extends HoistService {
63
67
  // -----------------------------------
64
68
  // Generate individual report sections
65
69
  //------------------------------------
66
- getSession(): SessionData {
67
- const {loadStarted} = XH.appContainerModel.appStateModel;
70
+ getGeneral(): GeneralData {
71
+ const startTime = XH.appContainerModel.appStateModel.loadStarted,
72
+ elapsedMins = (ts: number) => round((Date.now() - ts) / 60_000, 1);
73
+
68
74
  return {
69
- startTime: loadStarted,
70
- durationMins: round((Date.now() - loadStarted) / 60_000, 1)
75
+ startTime,
76
+ durationMins: elapsedMins(startTime),
77
+ idleMins: elapsedMins(XH.lastActivityMs),
78
+ pageState: XH.pageState,
79
+ webSocket: XH.webSocketService.channelKey
71
80
  };
72
81
  }
73
82
 
@@ -89,44 +98,12 @@ export class ClientHealthService extends HoistService {
89
98
 
90
99
  const {jsHeapSizeLimit: limit, usedJSHeapSize: used} = ret;
91
100
  if (limit && used) {
92
- ret.usedPctLimit = round((used / limit) * 100, 1);
101
+ ret.usedPctLimit = round((used / limit) * 100);
93
102
  }
94
103
 
95
104
  return ret;
96
105
  }
97
106
 
98
- getScreen(): ScreenData {
99
- const screen = window.screen as any;
100
- if (!screen) return null;
101
-
102
- const ret: ScreenData = pick(screen, [
103
- 'availWidth',
104
- 'availHeight',
105
- 'width',
106
- 'height',
107
- 'colorDepth',
108
- 'pixelDepth',
109
- 'availLeft',
110
- 'availTop'
111
- ]);
112
- if (screen.orientation) {
113
- ret.orientation = pick(screen.orientation, ['angle', 'type']);
114
- }
115
- return ret;
116
- }
117
-
118
- getWindow(): WindowData {
119
- return pick(window, [
120
- 'devicePixelRatio',
121
- 'screenX',
122
- 'screenY',
123
- 'innerWidth',
124
- 'innerHeight',
125
- 'outerWidth',
126
- 'outerHeight'
127
- ]);
128
- }
129
-
130
107
  getCustom(): PlainObject {
131
108
  const ret = {};
132
109
  this.sources.forEach((cb, k) => {
@@ -144,31 +121,27 @@ export class ClientHealthService extends HoistService {
144
121
  // Implementation
145
122
  //------------------
146
123
  private sendReport() {
147
- const {
148
- intervalMins,
149
- severity: defaultSeverity,
150
- ...rest
151
- } = XH.trackService.conf.clientHealthReport ?? {};
152
-
153
- const rpt = this.getReport();
154
- let severity = defaultSeverity ?? 'INFO';
155
- if (find(rpt, (v: any) => isPlainObject(v) && v.severity === 'WARN')) {
156
- severity = 'WARN';
157
- }
124
+ const {intervalMins, ...rest} = XH.trackService.conf.clientHealthReport ?? {};
158
125
 
159
126
  XH.track({
160
127
  category: 'App',
161
128
  message: 'Submitted health report',
162
- severity,
163
129
  ...rest,
164
- data: rpt
130
+ data: {
131
+ clientId: XH.clientId,
132
+ sessionId: XH.sessionId,
133
+ ...this.getReport()
134
+ }
165
135
  });
166
136
  }
167
137
  }
168
138
 
169
- export interface SessionData {
139
+ export interface GeneralData {
170
140
  startTime: number;
171
141
  durationMins: number;
142
+ idleMins: number;
143
+ pageState: PageState;
144
+ webSocket: string;
172
145
  }
173
146
 
174
147
  export interface ConnectionData {
@@ -185,35 +158,8 @@ export interface MemoryData {
185
158
  usedJSHeapSize?: number;
186
159
  }
187
160
 
188
- export interface WindowData {
189
- devicePixelRatio: number;
190
- screenX: number;
191
- screenY: number;
192
- innerWidth: number;
193
- innerHeight: number;
194
- outerWidth: number;
195
- outerHeight: number;
196
- }
197
-
198
- export interface ScreenData {
199
- availWidth: number;
200
- availHeight: number;
201
- width: number;
202
- height: number;
203
- colorDepth: number;
204
- pixelDepth: number;
205
- availLeft: number;
206
- availTop: number;
207
- orientation?: {
208
- angle: number;
209
- type: string;
210
- };
211
- }
212
-
213
161
  export interface ClientHealthReport {
214
- session: SessionData;
162
+ general: GeneralData;
215
163
  connection: ConnectionData;
216
164
  memory: MemoryData;
217
- window: WindowData;
218
- screen: ScreenData;
219
165
  }