@xh/hoist 73.0.0-SNAPSHOT.1744147015222 → 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.
- package/CHANGELOG.md +10 -1
- package/admin/AdminUtils.ts +1 -18
- package/admin/tabs/activity/tracking/detail/ActivityDetailModel.ts +3 -3
- package/admin/tabs/cluster/instances/services/DetailsPanel.ts +2 -3
- package/admin/tabs/cluster/objects/DetailModel.ts +2 -3
- package/admin/tabs/cluster/objects/DetailPanel.ts +2 -3
- package/appcontainer/AppStateModel.ts +40 -7
- package/build/types/admin/AdminUtils.d.ts +0 -4
- package/build/types/appcontainer/AppStateModel.d.ts +2 -0
- package/build/types/cmp/viewmanager/ViewManagerModel.d.ts +7 -0
- package/build/types/core/XH.d.ts +9 -0
- package/build/types/format/FormatDate.d.ts +22 -1
- package/build/types/security/Types.d.ts +3 -3
- package/build/types/security/msal/MsalClient.d.ts +2 -0
- package/build/types/svc/ClientHealthService.d.ts +10 -32
- package/cmp/viewmanager/ViewManagerModel.ts +10 -1
- package/core/XH.ts +23 -0
- package/desktop/cmp/viewmanager/ViewMenu.ts +11 -9
- package/format/FormatDate.ts +45 -3
- package/package.json +1 -1
- package/security/Types.ts +3 -3
- package/security/msal/MsalClient.ts +11 -7
- package/svc/ClientHealthService.ts +32 -86
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -14,9 +14,10 @@ import {
|
|
|
14
14
|
PopupRequest,
|
|
15
15
|
SilentRequest
|
|
16
16
|
} from '@azure/msal-browser';
|
|
17
|
-
import {XH} from '@xh/hoist/core';
|
|
17
|
+
import {AppState, PlainObject, XH} from '@xh/hoist/core';
|
|
18
18
|
import {Token} from '@xh/hoist/security/Token';
|
|
19
19
|
import {logDebug, logError, logInfo, logWarn, mergeDeep, throwIf} from '@xh/hoist/utils/js';
|
|
20
|
+
import {withFormattedTimestamps} from '@xh/hoist/format';
|
|
20
21
|
import {flatMap, union, uniq} from 'lodash';
|
|
21
22
|
import {BaseOAuthClient, BaseOAuthClientConfig} from '../BaseOAuthClient';
|
|
22
23
|
import {AccessTokenSpec, TelemetryResults, TokenMap} from '../Types';
|
|
@@ -266,9 +267,13 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
266
267
|
//------------------------
|
|
267
268
|
// Telemetry
|
|
268
269
|
//------------------------
|
|
270
|
+
getFormattedTelemetry(): PlainObject {
|
|
271
|
+
return withFormattedTimestamps(this.telemetryResults);
|
|
272
|
+
}
|
|
273
|
+
|
|
269
274
|
enableTelemetry(): void {
|
|
270
275
|
if (this._telemetryCbHandle) {
|
|
271
|
-
this.logInfo('Telemetry already enabled', this.
|
|
276
|
+
this.logInfo('Telemetry already enabled', this.getFormattedTelemetry());
|
|
272
277
|
return;
|
|
273
278
|
}
|
|
274
279
|
|
|
@@ -279,7 +284,7 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
279
284
|
try {
|
|
280
285
|
const {events} = this.telemetryResults,
|
|
281
286
|
{name, startTimeMs, durationMs, success, errorName, errorCode} = e,
|
|
282
|
-
eTime = startTimeMs
|
|
287
|
+
eTime = startTimeMs ?? Date.now();
|
|
283
288
|
|
|
284
289
|
const eResult = (events[name] ??= {
|
|
285
290
|
firstTime: eTime,
|
|
@@ -316,10 +321,9 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
316
321
|
});
|
|
317
322
|
});
|
|
318
323
|
|
|
319
|
-
//
|
|
320
|
-
// Handle TrackService not yet initialized (common, this client likely initialized before.)
|
|
324
|
+
// Wait for clientHealthService (this client likely initialized during earlier AUTHENTICATING.)
|
|
321
325
|
this.addReaction({
|
|
322
|
-
when: () => XH.
|
|
326
|
+
when: () => XH.appState === AppState.INITIALIZING_APP,
|
|
323
327
|
run: () => XH.clientHealthService.addSource('msalClient', () => this.telemetryResults)
|
|
324
328
|
});
|
|
325
329
|
|
|
@@ -336,7 +340,7 @@ export class MsalClient extends BaseOAuthClient<MsalClientConfig, MsalTokenSpec>
|
|
|
336
340
|
this._telemetryCbHandle = null;
|
|
337
341
|
|
|
338
342
|
XH.clientHealthService.removeSource('msalClient');
|
|
339
|
-
this.logInfo('Telemetry disabled', this.
|
|
343
|
+
this.logInfo('Telemetry disabled', this.getFormattedTelemetry());
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
//------------------------
|
|
@@ -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 {
|
|
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
|
|
35
|
+
* Main entry point. Return a default report of client health.
|
|
35
36
|
*/
|
|
36
37
|
getReport(): ClientHealthReport {
|
|
37
38
|
return {
|
|
38
|
-
|
|
39
|
-
...this.getCustom(),
|
|
39
|
+
general: this.getGeneral(),
|
|
40
40
|
memory: this.getMemory(),
|
|
41
41
|
connection: this.getConnection(),
|
|
42
|
-
|
|
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
|
-
|
|
67
|
-
const
|
|
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
|
|
70
|
-
durationMins:
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
|
|
162
|
+
general: GeneralData;
|
|
215
163
|
connection: ConnectionData;
|
|
216
164
|
memory: MemoryData;
|
|
217
|
-
window: WindowData;
|
|
218
|
-
screen: ScreenData;
|
|
219
165
|
}
|