@zohodesk/i18n 1.0.0-beta.33 → 1.0.0-beta.35-murphy
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/README.md +4 -0
- package/docs/murphy/01-MURPHY_OVERVIEW.md +148 -0
- package/docs/murphy/02-MURPHY_ARCHITECTURE.md +283 -0
- package/docs/murphy/03-MURPHY_BACKEND_CONFIG.md +337 -0
- package/docs/murphy/04-MURPHY_FRONTEND_INIT.md +437 -0
- package/docs/murphy/05-MURPHY_DESK_CLIENT_USAGE.md +467 -0
- package/docs/murphy/06-MURPHY_I18N_INTEGRATION.md +402 -0
- package/docs/murphy/07-MURPHY_WHY_I18N_APPROACH.md +391 -0
- package/es/components/DateTimeDiffFormat.js +5 -19
- package/es/components/FormatText.js +2 -2
- package/es/components/HOCI18N.js +32 -43
- package/es/components/I18N.js +2 -13
- package/es/components/I18NProvider.js +0 -9
- package/es/components/PluralFormat.js +3 -5
- package/es/components/UserTimeDiffFormat.js +5 -9
- package/es/components/__tests__/DateTimeDiffFormat.spec.js +157 -221
- package/es/components/__tests__/FormatText.spec.js +2 -2
- package/es/components/__tests__/HOCI18N.spec.js +2 -4
- package/es/components/__tests__/I18N.spec.js +6 -4
- package/es/components/__tests__/I18NProvider.spec.js +4 -4
- package/es/components/__tests__/PluralFormat.spec.js +2 -2
- package/es/components/__tests__/UserTimeDiffFormat.spec.js +249 -348
- package/es/index.js +2 -0
- package/es/utils/__tests__/jsxTranslations.spec.js +3 -7
- package/es/utils/errorReporter.js +31 -0
- package/es/utils/index.js +42 -92
- package/es/utils/jsxTranslations.js +53 -61
- package/lib/I18NContext.js +2 -7
- package/lib/components/DateTimeDiffFormat.js +46 -87
- package/lib/components/FormatText.js +18 -41
- package/lib/components/HOCI18N.js +24 -59
- package/lib/components/I18N.js +27 -64
- package/lib/components/I18NProvider.js +27 -63
- package/lib/components/PluralFormat.js +24 -50
- package/lib/components/UserTimeDiffFormat.js +43 -72
- package/lib/components/__tests__/DateTimeDiffFormat.spec.js +95 -165
- package/lib/components/__tests__/FormatText.spec.js +3 -10
- package/lib/components/__tests__/HOCI18N.spec.js +3 -14
- package/lib/components/__tests__/I18N.spec.js +4 -12
- package/lib/components/__tests__/I18NProvider.spec.js +8 -23
- package/lib/components/__tests__/PluralFormat.spec.js +3 -11
- package/lib/components/__tests__/UserTimeDiffFormat.spec.js +157 -225
- package/lib/index.js +32 -22
- package/lib/utils/__tests__/jsxTranslations.spec.js +1 -12
- package/lib/utils/errorReporter.js +39 -0
- package/lib/utils/index.js +49 -125
- package/lib/utils/jsxTranslations.js +79 -105
- package/package.json +1 -1
- package/src/index.js +6 -0
- package/src/utils/errorReporter.js +36 -0
- package/src/utils/index.js +8 -1
- package/src/utils/jsxTranslations.js +31 -12
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
# Murphy Frontend Initialization
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Murphy SDK is loaded from CDN and initialized on the client side using configuration injected from the backend.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Initialization Timeline
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
+-------------------------------------------------------------------+
|
|
13
|
+
| MURPHY INITIALIZATION TIMELINE |
|
|
14
|
+
+-------------------------------------------------------------------+
|
|
15
|
+
| |
|
|
16
|
+
| 1. HTML Document Loads |
|
|
17
|
+
| +----------------------------------------------------------+ |
|
|
18
|
+
| | <script nonce="..."> | |
|
|
19
|
+
| | var desk_urls = { | |
|
|
20
|
+
| | murphyAppKey: "755747375", | |
|
|
21
|
+
| | murphyAppDomain: "murphy.zoho.com", | |
|
|
22
|
+
| | murphyAuthKey: "..." | |
|
|
23
|
+
| | }; | |
|
|
24
|
+
| | </script> | |
|
|
25
|
+
| +----------------------------------------------------------+ |
|
|
26
|
+
| | |
|
|
27
|
+
| v |
|
|
28
|
+
| 2. InitMurphy() Called |
|
|
29
|
+
| +----------------------------------------------------------+ |
|
|
30
|
+
| | - Checks if Murphy is enabled | |
|
|
31
|
+
| | - Fetches build release JSON (for version info) | |
|
|
32
|
+
| | - Loads Murphy SDK from CDN | |
|
|
33
|
+
| +----------------------------------------------------------+ |
|
|
34
|
+
| | |
|
|
35
|
+
| v |
|
|
36
|
+
| 3. Murphy SDK Loaded from CDN |
|
|
37
|
+
| +----------------------------------------------------------+ |
|
|
38
|
+
| | URL: {staticDomain}/murphysdk/3.0.0/murphy.min.js | |
|
|
39
|
+
| | | |
|
|
40
|
+
| | Creates global: window.murphy | |
|
|
41
|
+
| +----------------------------------------------------------+ |
|
|
42
|
+
| | |
|
|
43
|
+
| v |
|
|
44
|
+
| 4. Wait for desk_urls (retry mechanism) |
|
|
45
|
+
| +----------------------------------------------------------+ |
|
|
46
|
+
| | - Checks isInitialDataPresent() | |
|
|
47
|
+
| | - Retries up to 100 times with 10ms delay | |
|
|
48
|
+
| | - Ensures desk_urls has Murphy credentials | |
|
|
49
|
+
| +----------------------------------------------------------+ |
|
|
50
|
+
| | |
|
|
51
|
+
| v |
|
|
52
|
+
| 5. murphyInit() Configures SDK |
|
|
53
|
+
| +----------------------------------------------------------+ |
|
|
54
|
+
| | murphy.install({ | |
|
|
55
|
+
| | config: { appKey, appDomain, authKey, ... } | |
|
|
56
|
+
| | }); | |
|
|
57
|
+
| +----------------------------------------------------------+ |
|
|
58
|
+
| | |
|
|
59
|
+
| v |
|
|
60
|
+
| 6. Client Metrics Installed |
|
|
61
|
+
| +----------------------------------------------------------+ |
|
|
62
|
+
| | murphy.clientmetrics.install(config) | |
|
|
63
|
+
| | - Performance monitoring enabled | |
|
|
64
|
+
| | - Time to Interactive tracking | |
|
|
65
|
+
| | - Soft navigation tracking | |
|
|
66
|
+
| +----------------------------------------------------------+ |
|
|
67
|
+
| | |
|
|
68
|
+
| v |
|
|
69
|
+
| 7. Global murphy Object Ready! |
|
|
70
|
+
| +----------------------------------------------------------+ |
|
|
71
|
+
| | murphy.error(...) -> Track errors | |
|
|
72
|
+
| | murphy.appLog(...) -> Application logs | |
|
|
73
|
+
| | murphy.clientmetrics -> Performance metrics | |
|
|
74
|
+
| | murphy.telemetry -> User behavior tracking | |
|
|
75
|
+
| +----------------------------------------------------------+ |
|
|
76
|
+
| |
|
|
77
|
+
+-------------------------------------------------------------------+
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Key Files
|
|
83
|
+
|
|
84
|
+
### 1. initial_html/index.js - Entry Point
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
// Path: src/library/murphy/initial_html/index.js
|
|
88
|
+
|
|
89
|
+
import { loadResource } from '../../../_utils/loadResource.js';
|
|
90
|
+
import { isMurphyEnabled, murphyIntegrationName } from './constants.js';
|
|
91
|
+
import { murphySDKUrl } from './Urls.js';
|
|
92
|
+
import {
|
|
93
|
+
fetchReleaseJson,
|
|
94
|
+
installMurphyClientMetrics,
|
|
95
|
+
isClientMetricsSupported,
|
|
96
|
+
isInitialDataPresent,
|
|
97
|
+
murphyInit
|
|
98
|
+
} from './utils.js';
|
|
99
|
+
|
|
100
|
+
export default function InitMurphy() {
|
|
101
|
+
// Guard: Check if Murphy is enabled
|
|
102
|
+
if (!isMurphyEnabled || !murphySDKUrl) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let initialDataCheckCount = 0;
|
|
107
|
+
const max_iterations = 100;
|
|
108
|
+
|
|
109
|
+
// Load Murphy SDK and build info in parallel
|
|
110
|
+
Promise.all([
|
|
111
|
+
isDevMode ? Promise.resolve() : fetchReleaseJson(),
|
|
112
|
+
loadResource(murphySDKUrl, 'js', murphyIntegrationName, null, false)
|
|
113
|
+
]).then(function murphyCb(responseArr) {
|
|
114
|
+
let [releaseJson = {}] = responseArr;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
// Prevent infinite loop
|
|
118
|
+
if (initialDataCheckCount >= max_iterations) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Wait for desk_urls to be populated
|
|
123
|
+
if (isInitialDataPresent()) {
|
|
124
|
+
murphyInit(releaseJson);
|
|
125
|
+
InitMurphyClientMetrics(releaseJson);
|
|
126
|
+
} else {
|
|
127
|
+
// Retry after 10ms
|
|
128
|
+
setTimeout(() => murphyCb(responseArr), 10);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
initialDataCheckCount += 1;
|
|
132
|
+
} catch (ex) {
|
|
133
|
+
console.log('Init Murphy Error', ex);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Auto-execute on load
|
|
139
|
+
InitMurphy();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 2. initial_html/utils.js - Core Functions
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// Path: src/library/murphy/initial_html/utils.js
|
|
146
|
+
|
|
147
|
+
import {
|
|
148
|
+
enableTracking,
|
|
149
|
+
envi,
|
|
150
|
+
maxTrackData,
|
|
151
|
+
pushLogs
|
|
152
|
+
} from './constants';
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Check if desk_urls has Murphy configuration
|
|
156
|
+
*/
|
|
157
|
+
export function isInitialDataPresent() {
|
|
158
|
+
return (
|
|
159
|
+
globalThis.desk_urls &&
|
|
160
|
+
typeof globalThis.desk_urls === 'object' &&
|
|
161
|
+
Boolean(Object.keys(getInitialData()).length)
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Extract Murphy config from desk_urls
|
|
167
|
+
*/
|
|
168
|
+
function getInitialData() {
|
|
169
|
+
const appDomain = globalThis.desk_urls.murphyAppDomain;
|
|
170
|
+
const appKey = globalThis.desk_urls.murphyAppKey;
|
|
171
|
+
const authKey = globalThis.desk_urls.murphyAuthKey;
|
|
172
|
+
return { appDomain, appKey, authKey };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Initialize Murphy SDK with configuration
|
|
177
|
+
*/
|
|
178
|
+
export function murphyInit(buildInfoJson = {}) {
|
|
179
|
+
const { appDomain, appKey, authKey } = getInitialData();
|
|
180
|
+
|
|
181
|
+
murphy.install({
|
|
182
|
+
config: {
|
|
183
|
+
appKey, // Application identifier
|
|
184
|
+
appDomain, // Murphy server domain
|
|
185
|
+
environment: envi, // Environment (prod/dev)
|
|
186
|
+
pushLogs, // Enable log pushing
|
|
187
|
+
enableTracking, // Enable tracking
|
|
188
|
+
maxTrackData, // Max tracking data size
|
|
189
|
+
authKey, // Authentication key
|
|
190
|
+
|
|
191
|
+
// Rage click detection
|
|
192
|
+
rageClick: {
|
|
193
|
+
enable: true,
|
|
194
|
+
tokenLimit: 5
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
// Rage request detection
|
|
198
|
+
rageRequest: {
|
|
199
|
+
enable: true
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
// User behavior telemetry
|
|
203
|
+
telemetry: {
|
|
204
|
+
enable: true
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
// Tags attached to all errors
|
|
209
|
+
setTags() {
|
|
210
|
+
return {
|
|
211
|
+
buildId: agentClientVersion,
|
|
212
|
+
zuid: userInfo.zuid,
|
|
213
|
+
zgid: currentOrg.id,
|
|
214
|
+
releaseDetails: {
|
|
215
|
+
releaseName: buildInfoJson.BuildLabel,
|
|
216
|
+
releaseRevision: buildInfoJson.Source_Changeset
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Configuration Options
|
|
227
|
+
|
|
228
|
+
### murphy.install() Config
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
+-------------------------------------------------------------------+
|
|
232
|
+
| MURPHY.INSTALL() CONFIGURATION OPTIONS |
|
|
233
|
+
+-------------------------------------------------------------------+
|
|
234
|
+
| |
|
|
235
|
+
| Required: |
|
|
236
|
+
| +---------------------------------------------------------------+ |
|
|
237
|
+
| | appKey | Application ID from Murphy dashboard | |
|
|
238
|
+
| | appDomain | Murphy server URL (murphy.zoho.com) | |
|
|
239
|
+
| | authKey | Authentication token | |
|
|
240
|
+
| +---------------------------------------------------------------+ |
|
|
241
|
+
| |
|
|
242
|
+
| Optional: |
|
|
243
|
+
| +---------------------------------------------------------------+ |
|
|
244
|
+
| | environment | 'production' or 'development' | |
|
|
245
|
+
| | pushLogs | Enable sending logs to server (boolean) | |
|
|
246
|
+
| | maxTrackData| Maximum size of tracking data | |
|
|
247
|
+
| +---------------------------------------------------------------+ |
|
|
248
|
+
| |
|
|
249
|
+
| Feature Flags: |
|
|
250
|
+
| +---------------------------------------------------------------+ |
|
|
251
|
+
| | rageClick | { enable: true, tokenLimit: 5 } | |
|
|
252
|
+
| | | Detects frustrated clicking | |
|
|
253
|
+
| +---------------------------------------------------------------+ |
|
|
254
|
+
| | rageRequest | { enable: true } | |
|
|
255
|
+
| | | Detects repeated failed API calls | |
|
|
256
|
+
| +---------------------------------------------------------------+ |
|
|
257
|
+
| | telemetry | { enable: true } | |
|
|
258
|
+
| | | Tracks user behavior patterns | |
|
|
259
|
+
| +---------------------------------------------------------------+ |
|
|
260
|
+
| |
|
|
261
|
+
+-------------------------------------------------------------------+
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### setTags() - Custom Tags
|
|
265
|
+
|
|
266
|
+
```javascript
|
|
267
|
+
setTags() {
|
|
268
|
+
return {
|
|
269
|
+
// Build identification
|
|
270
|
+
buildId: agentClientVersion, // e.g., "2024.01.15.1"
|
|
271
|
+
|
|
272
|
+
// User identification
|
|
273
|
+
zuid: userInfo.zuid, // Zoho User ID
|
|
274
|
+
zgid: currentOrg.id, // Organization ID
|
|
275
|
+
|
|
276
|
+
// Release information
|
|
277
|
+
releaseDetails: {
|
|
278
|
+
releaseName: buildInfoJson.BuildLabel,
|
|
279
|
+
releaseRevision: buildInfoJson.Source_Changeset
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Client Metrics Installation
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
/**
|
|
291
|
+
* Install performance monitoring capabilities
|
|
292
|
+
*/
|
|
293
|
+
export function installMurphyClientMetrics(buildInfoJson) {
|
|
294
|
+
// Set custom tags for all metrics
|
|
295
|
+
murphy.clientmetrics.setCustomTags({
|
|
296
|
+
buildId: agentClientVersion,
|
|
297
|
+
zuid: userInfo.zuid,
|
|
298
|
+
zgid: currentOrg.id
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// Set release info for tracking
|
|
302
|
+
murphy.clientmetrics.setUserEnvInfo({
|
|
303
|
+
releaseDetails: {
|
|
304
|
+
buildId: agentClientVersion,
|
|
305
|
+
releaseName: buildInfoJson.BuildLabel,
|
|
306
|
+
releaseRevision: buildInfoJson.Source_Changeset
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Configure and install
|
|
311
|
+
let config = murphy.sendUserInfo();
|
|
312
|
+
config.isMonitoringEnabled = isMonitoringEnabled();
|
|
313
|
+
config.clientmetricsWorkerUrl = getWorkerObjectUrl();
|
|
314
|
+
config.isTimeToInteractiveEnabled = true;
|
|
315
|
+
config.isClientMetricsSoftNavigationEnabled = true;
|
|
316
|
+
config.isInterruptionMonitoringEnabled = true;
|
|
317
|
+
|
|
318
|
+
murphy.clientmetrics.install(config);
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Retry Mechanism
|
|
325
|
+
|
|
326
|
+
The initialization includes a retry mechanism to handle race conditions:
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
+-------------------------------------------------------------------+
|
|
330
|
+
| RETRY MECHANISM |
|
|
331
|
+
+-------------------------------------------------------------------+
|
|
332
|
+
| |
|
|
333
|
+
| Problem: desk_urls may not be populated when InitMurphy runs |
|
|
334
|
+
| |
|
|
335
|
+
| Solution: |
|
|
336
|
+
| |
|
|
337
|
+
| +------------------+ No +------------------------+ |
|
|
338
|
+
| | isInitialData | ----------> | Wait 10ms | |
|
|
339
|
+
| | Present()? | | Increment counter | |
|
|
340
|
+
| +------------------+ | Retry (max 100 times) | |
|
|
341
|
+
| | +------------------------+ |
|
|
342
|
+
| | Yes | |
|
|
343
|
+
| v | |
|
|
344
|
+
| +------------------+ | |
|
|
345
|
+
| | murphyInit() | | |
|
|
346
|
+
| | Initialize SDK | <----------------------+ |
|
|
347
|
+
| +------------------+ |
|
|
348
|
+
| |
|
|
349
|
+
| Max Wait Time: 100 * 10ms = 1 second |
|
|
350
|
+
| |
|
|
351
|
+
+-------------------------------------------------------------------+
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## SDK Loading
|
|
357
|
+
|
|
358
|
+
### CDN URL Pattern
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
// URL is constructed dynamically based on datacenter
|
|
362
|
+
const murphySDKUrl = `${desk_urls.staticDomain}/murphysdk/3.0.0/murphy.min.js`;
|
|
363
|
+
|
|
364
|
+
// Examples:
|
|
365
|
+
// US: https://static.zohocdn.com/murphysdk/3.0.0/murphy.min.js
|
|
366
|
+
// EU: https://static.zohocdn.eu/murphysdk/3.0.0/murphy.min.js
|
|
367
|
+
// IN: https://static.zohocdn.in/murphysdk/3.0.0/murphy.min.js
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### loadResource() Utility
|
|
371
|
+
|
|
372
|
+
```javascript
|
|
373
|
+
// Loads JavaScript file from CDN
|
|
374
|
+
loadResource(murphySDKUrl, 'js', murphyIntegrationName, null, false);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Global Murphy Object
|
|
380
|
+
|
|
381
|
+
After initialization, the global `murphy` object is available:
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
// Check if Murphy is available
|
|
385
|
+
if (typeof murphy !== 'undefined') {
|
|
386
|
+
// Error tracking
|
|
387
|
+
murphy.error(error, undefined, { customTags: {...} });
|
|
388
|
+
|
|
389
|
+
// Application logging
|
|
390
|
+
murphy.appLog('INFO', 'User action completed', { userId: 123 });
|
|
391
|
+
|
|
392
|
+
// Custom tracking
|
|
393
|
+
murphy.addCustomTracking({ event: 'feature_used' });
|
|
394
|
+
|
|
395
|
+
// Performance metrics
|
|
396
|
+
murphy.clientmetrics.setTimeToInteractive();
|
|
397
|
+
murphy.clientmetrics.startSoftNavigation({ from_url, to_url });
|
|
398
|
+
murphy.clientmetrics.endSoftNavigation();
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Summary
|
|
405
|
+
|
|
406
|
+
```
|
|
407
|
+
+-------------------------------------------------------------------+
|
|
408
|
+
| FRONTEND INIT SUMMARY |
|
|
409
|
+
+-------------------------------------------------------------------+
|
|
410
|
+
| |
|
|
411
|
+
| Entry Point: InitMurphy() |
|
|
412
|
+
| +-- Loads SDK from CDN |
|
|
413
|
+
| +-- Waits for desk_urls |
|
|
414
|
+
| +-- Initializes with murphyInit() |
|
|
415
|
+
| |
|
|
416
|
+
| Configuration Source: globalThis.desk_urls |
|
|
417
|
+
| +-- murphyAppKey |
|
|
418
|
+
| +-- murphyAppDomain |
|
|
419
|
+
| +-- murphyAuthKey |
|
|
420
|
+
| |
|
|
421
|
+
| Result: Global murphy object with: |
|
|
422
|
+
| +-- murphy.error() -> Error tracking |
|
|
423
|
+
| +-- murphy.appLog() -> Application logs |
|
|
424
|
+
| +-- murphy.addCustomTracking() -> Custom events |
|
|
425
|
+
| +-- murphy.clientmetrics -> Performance monitoring |
|
|
426
|
+
| +-- murphy.telemetry -> User behavior |
|
|
427
|
+
| |
|
|
428
|
+
+-------------------------------------------------------------------+
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Related Documents
|
|
434
|
+
|
|
435
|
+
- [02-MURPHY_ARCHITECTURE.md](./02-MURPHY_ARCHITECTURE.md) - Full architecture
|
|
436
|
+
- [03-MURPHY_BACKEND_CONFIG.md](./03-MURPHY_BACKEND_CONFIG.md) - Backend configuration
|
|
437
|
+
- [05-MURPHY_DESK_CLIENT_USAGE.md](./05-MURPHY_DESK_CLIENT_USAGE.md) - Usage in desk client
|