@finos/legend-application-studio 28.21.45 → 28.21.47

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.
Files changed (209) hide show
  1. package/lib/__lib__/LegendStudioEvent.d.ts +63 -1
  2. package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioEvent.js +90 -0
  4. package/lib/__lib__/LegendStudioEvent.js.map +1 -1
  5. package/lib/__lib__/LegendStudioTelemetryHelper.d.ts +655 -1
  6. package/lib/__lib__/LegendStudioTelemetryHelper.d.ts.map +1 -1
  7. package/lib/__lib__/LegendStudioTelemetryHelper.js +709 -1
  8. package/lib/__lib__/LegendStudioTelemetryHelper.js.map +1 -1
  9. package/lib/components/editor/editor-group/LegendAISuggestTelemetryHooks.d.ts +30 -0
  10. package/lib/components/editor/editor-group/LegendAISuggestTelemetryHooks.d.ts.map +1 -0
  11. package/lib/components/editor/editor-group/LegendAISuggestTelemetryHooks.js +43 -0
  12. package/lib/components/editor/editor-group/LegendAISuggestTelemetryHooks.js.map +1 -0
  13. package/lib/components/editor/editor-group/RuntimeEditor.d.ts +4 -3
  14. package/lib/components/editor/editor-group/RuntimeEditor.d.ts.map +1 -1
  15. package/lib/components/editor/editor-group/RuntimeEditor.js +90 -36
  16. package/lib/components/editor/editor-group/RuntimeEditor.js.map +1 -1
  17. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  18. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +154 -35
  19. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  20. package/lib/components/editor/editor-group/dataProduct/DataProductQueryBuilderHelper.d.ts.map +1 -1
  21. package/lib/components/editor/editor-group/dataProduct/DataProductQueryBuilderHelper.js +4 -6
  22. package/lib/components/editor/editor-group/dataProduct/DataProductQueryBuilderHelper.js.map +1 -1
  23. package/lib/components/editor/editor-group/service-editor/ServiceEditor.d.ts.map +1 -1
  24. package/lib/components/editor/editor-group/service-editor/ServiceEditor.js +31 -7
  25. package/lib/components/editor/editor-group/service-editor/ServiceEditor.js.map +1 -1
  26. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.d.ts.map +1 -1
  27. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.js +4 -8
  28. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.js.map +1 -1
  29. package/lib/components/editor/side-bar/WorkflowManager.d.ts.map +1 -1
  30. package/lib/components/editor/side-bar/WorkflowManager.js +15 -0
  31. package/lib/components/editor/side-bar/WorkflowManager.js.map +1 -1
  32. package/lib/index.css +1 -1
  33. package/lib/index.d.ts +3 -1
  34. package/lib/index.d.ts.map +1 -1
  35. package/lib/index.js +3 -1
  36. package/lib/index.js.map +1 -1
  37. package/lib/package.json +1 -1
  38. package/lib/stores/editor/EditorGraphState.d.ts.map +1 -1
  39. package/lib/stores/editor/EditorGraphState.js +17 -1
  40. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  41. package/lib/stores/editor/EditorStore.d.ts +2 -0
  42. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  43. package/lib/stores/editor/EditorStore.js +12 -0
  44. package/lib/stores/editor/EditorStore.js.map +1 -1
  45. package/lib/stores/editor/EditorTabManagerState.d.ts +18 -1
  46. package/lib/stores/editor/EditorTabManagerState.d.ts.map +1 -1
  47. package/lib/stores/editor/EditorTabManagerState.js +90 -1
  48. package/lib/stores/editor/EditorTabManagerState.js.map +1 -1
  49. package/lib/stores/editor/EditorTabTelemetryHelper.d.ts +31 -0
  50. package/lib/stores/editor/EditorTabTelemetryHelper.d.ts.map +1 -0
  51. package/lib/stores/editor/EditorTabTelemetryHelper.js +55 -0
  52. package/lib/stores/editor/EditorTabTelemetryHelper.js.map +1 -0
  53. package/lib/stores/editor/GraphEditFormModeState.d.ts.map +1 -1
  54. package/lib/stores/editor/GraphEditFormModeState.js +22 -1
  55. package/lib/stores/editor/GraphEditFormModeState.js.map +1 -1
  56. package/lib/stores/editor/LegendAISuggestTelemetry.d.ts +143 -0
  57. package/lib/stores/editor/LegendAISuggestTelemetry.d.ts.map +1 -0
  58. package/lib/stores/editor/LegendAISuggestTelemetry.js +376 -0
  59. package/lib/stores/editor/LegendAISuggestTelemetry.js.map +1 -0
  60. package/lib/stores/editor/LegendSQLStudioPlaygroundState.js +3 -3
  61. package/lib/stores/editor/LegendSQLStudioPlaygroundState.js.map +1 -1
  62. package/lib/stores/editor/editor-state/GraphGenerationState.d.ts +14 -3
  63. package/lib/stores/editor/editor-state/GraphGenerationState.d.ts.map +1 -1
  64. package/lib/stores/editor/editor-state/GraphGenerationState.js +42 -5
  65. package/lib/stores/editor/editor-state/GraphGenerationState.js.map +1 -1
  66. package/lib/stores/editor/editor-state/ModelImporterState.d.ts.map +1 -1
  67. package/lib/stores/editor/editor-state/ModelImporterState.js +2 -1
  68. package/lib/stores/editor/editor-state/ModelImporterState.js.map +1 -1
  69. package/lib/stores/editor/editor-state/element-editor-state/ElementExternalFormatGenerationState.d.ts.map +1 -1
  70. package/lib/stores/editor/editor-state/element-editor-state/ElementExternalFormatGenerationState.js +14 -0
  71. package/lib/stores/editor/editor-state/element-editor-state/ElementExternalFormatGenerationState.js.map +1 -1
  72. package/lib/stores/editor/editor-state/element-editor-state/RuntimeEditorState.d.ts +35 -6
  73. package/lib/stores/editor/editor-state/element-editor-state/RuntimeEditorState.d.ts.map +1 -1
  74. package/lib/stores/editor/editor-state/element-editor-state/RuntimeEditorState.js +74 -29
  75. package/lib/stores/editor/editor-state/element-editor-state/RuntimeEditorState.js.map +1 -1
  76. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.d.ts +5 -0
  77. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.d.ts.map +1 -1
  78. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.js +13 -0
  79. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.js.map +1 -1
  80. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts +1 -0
  81. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts.map +1 -1
  82. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js +5 -5
  83. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js.map +1 -1
  84. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +12 -0
  85. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  86. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +60 -14
  87. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  88. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts +5 -0
  89. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts.map +1 -1
  90. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js +13 -0
  91. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js.map +1 -1
  92. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts +7 -0
  93. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
  94. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +21 -2
  95. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
  96. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.d.ts +5 -0
  97. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.d.ts.map +1 -1
  98. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.js +13 -0
  99. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.js.map +1 -1
  100. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts +7 -0
  101. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.d.ts.map +1 -1
  102. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js +34 -0
  103. package/lib/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.js.map +1 -1
  104. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.d.ts.map +1 -1
  105. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.js +48 -0
  106. package/lib/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.js.map +1 -1
  107. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts +1 -1
  108. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts.map +1 -1
  109. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js +5 -11
  110. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
  111. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts +3 -0
  112. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts.map +1 -1
  113. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js +7 -0
  114. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js.map +1 -1
  115. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.d.ts.map +1 -1
  116. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.js +46 -17
  117. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.js.map +1 -1
  118. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts +7 -0
  119. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.d.ts.map +1 -1
  120. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js +110 -16
  121. package/lib/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.js.map +1 -1
  122. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.d.ts +2 -1
  123. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.d.ts.map +1 -1
  124. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js +10 -4
  125. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js.map +1 -1
  126. package/lib/stores/editor/sidebar-state/BulkServiceRegistrationState.d.ts.map +1 -1
  127. package/lib/stores/editor/sidebar-state/BulkServiceRegistrationState.js +40 -1
  128. package/lib/stores/editor/sidebar-state/BulkServiceRegistrationState.js.map +1 -1
  129. package/lib/stores/editor/sidebar-state/LocalChangesState.d.ts.map +1 -1
  130. package/lib/stores/editor/sidebar-state/LocalChangesState.js +1 -0
  131. package/lib/stores/editor/sidebar-state/LocalChangesState.js.map +1 -1
  132. package/lib/stores/editor/sidebar-state/ProjectOverviewState.d.ts.map +1 -1
  133. package/lib/stores/editor/sidebar-state/ProjectOverviewState.js +51 -0
  134. package/lib/stores/editor/sidebar-state/ProjectOverviewState.js.map +1 -1
  135. package/lib/stores/editor/sidebar-state/WorkflowManagerState.d.ts +14 -0
  136. package/lib/stores/editor/sidebar-state/WorkflowManagerState.d.ts.map +1 -1
  137. package/lib/stores/editor/sidebar-state/WorkflowManagerState.js +132 -27
  138. package/lib/stores/editor/sidebar-state/WorkflowManagerState.js.map +1 -1
  139. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.d.ts.map +1 -1
  140. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js +41 -0
  141. package/lib/stores/editor/sidebar-state/WorkspaceReviewState.js.map +1 -1
  142. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.d.ts.map +1 -1
  143. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.js +71 -9
  144. package/lib/stores/editor/sidebar-state/testable/GlobalTestRunnerState.js.map +1 -1
  145. package/lib/stores/editor/utils/MockDataUtils.d.ts +12 -2
  146. package/lib/stores/editor/utils/MockDataUtils.d.ts.map +1 -1
  147. package/lib/stores/editor/utils/MockDataUtils.js +28 -28
  148. package/lib/stores/editor/utils/MockDataUtils.js.map +1 -1
  149. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts +2 -0
  150. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts.map +1 -1
  151. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js +13 -0
  152. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js.map +1 -1
  153. package/lib/stores/graph-modifier/DSL_LakehouseRuntime_GraphModifierHelper.d.ts +20 -2
  154. package/lib/stores/graph-modifier/DSL_LakehouseRuntime_GraphModifierHelper.d.ts.map +1 -1
  155. package/lib/stores/graph-modifier/DSL_LakehouseRuntime_GraphModifierHelper.js +38 -4
  156. package/lib/stores/graph-modifier/DSL_LakehouseRuntime_GraphModifierHelper.js.map +1 -1
  157. package/lib/stores/project-reviewer/ProjectReviewerStore.d.ts.map +1 -1
  158. package/lib/stores/project-reviewer/ProjectReviewerStore.js +45 -0
  159. package/lib/stores/project-reviewer/ProjectReviewerStore.js.map +1 -1
  160. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts.map +1 -1
  161. package/lib/stores/workspace-setup/WorkspaceSetupStore.js +48 -4
  162. package/lib/stores/workspace-setup/WorkspaceSetupStore.js.map +1 -1
  163. package/package.json +9 -9
  164. package/src/__lib__/LegendStudioEvent.ts +102 -0
  165. package/src/__lib__/LegendStudioTelemetryHelper.ts +1769 -311
  166. package/src/components/editor/editor-group/LegendAISuggestTelemetryHooks.ts +57 -0
  167. package/src/components/editor/editor-group/RuntimeEditor.tsx +282 -132
  168. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +293 -106
  169. package/src/components/editor/editor-group/dataProduct/DataProductQueryBuilderHelper.ts +3 -13
  170. package/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +41 -23
  171. package/src/components/editor/editor-group/service-editor/testable/ServiceTestDataEditor.tsx +5 -11
  172. package/src/components/editor/side-bar/WorkflowManager.tsx +24 -0
  173. package/src/index.ts +17 -1
  174. package/src/stores/editor/EditorGraphState.ts +30 -1
  175. package/src/stores/editor/EditorStore.ts +22 -0
  176. package/src/stores/editor/EditorTabManagerState.ts +128 -1
  177. package/src/stores/editor/EditorTabTelemetryHelper.ts +70 -0
  178. package/src/stores/editor/GraphEditFormModeState.ts +35 -1
  179. package/src/stores/editor/LegendAISuggestTelemetry.ts +592 -0
  180. package/src/stores/editor/LegendSQLStudioPlaygroundState.ts +3 -3
  181. package/src/stores/editor/editor-state/GraphGenerationState.ts +68 -9
  182. package/src/stores/editor/editor-state/ModelImporterState.ts +2 -0
  183. package/src/stores/editor/editor-state/element-editor-state/ElementExternalFormatGenerationState.ts +30 -0
  184. package/src/stores/editor/editor-state/element-editor-state/RuntimeEditorState.ts +92 -31
  185. package/src/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.ts +17 -0
  186. package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts +6 -6
  187. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +75 -17
  188. package/src/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.ts +17 -0
  189. package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +27 -2
  190. package/src/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.ts +17 -0
  191. package/src/stores/editor/editor-state/element-editor-state/mapping/testable/MappingTestableState.ts +57 -0
  192. package/src/stores/editor/editor-state/element-editor-state/service/ServiceRegistrationState.ts +74 -0
  193. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +22 -21
  194. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.ts +9 -0
  195. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestableState.ts +78 -21
  196. package/src/stores/editor/editor-state/element-editor-state/testable/TestableEditorState.ts +205 -18
  197. package/src/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.ts +38 -3
  198. package/src/stores/editor/sidebar-state/BulkServiceRegistrationState.ts +71 -1
  199. package/src/stores/editor/sidebar-state/LocalChangesState.ts +4 -0
  200. package/src/stores/editor/sidebar-state/ProjectOverviewState.ts +114 -0
  201. package/src/stores/editor/sidebar-state/WorkflowManagerState.ts +250 -29
  202. package/src/stores/editor/sidebar-state/WorkspaceReviewState.ts +84 -0
  203. package/src/stores/editor/sidebar-state/testable/GlobalTestRunnerState.ts +124 -17
  204. package/src/stores/editor/utils/MockDataUtils.ts +33 -32
  205. package/src/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.ts +18 -0
  206. package/src/stores/graph-modifier/DSL_LakehouseRuntime_GraphModifierHelper.ts +62 -7
  207. package/src/stores/project-reviewer/ProjectReviewerStore.ts +97 -0
  208. package/src/stores/workspace-setup/WorkspaceSetupStore.ts +87 -4
  209. package/tsconfig.json +3 -0
@@ -71,6 +71,7 @@ import {
71
71
  validate_ServicePattern,
72
72
  validate_ServiceMcpServer,
73
73
  DeploymentOwnership,
74
+ Service,
74
75
  UserListOwnership,
75
76
  } from '@finos/legend-graph';
76
77
  import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
@@ -78,7 +79,11 @@ import { ServiceTestableEditor } from './testable/ServiceTestableEditor.js';
78
79
  import { flowResult } from 'mobx';
79
80
  import { ServicePostValidationsEditor } from './ServicePostValidationEditor.js';
80
81
  import type { DSL_Service_LegendStudioApplicationPlugin_Extension } from '../../../../stores/extensions/DSL_Service_LegendStudioApplicationPlugin_Extension.js';
81
- import { LegendStudioTelemetryHelper } from '../../../../__lib__/LegendStudioTelemetryHelper.js';
82
+ import {
83
+ LEGENDAI_SUGGEST_STAGE,
84
+ LEGENDAI_SUGGEST_SURFACE,
85
+ } from '../../../../__lib__/LegendStudioTelemetryHelper.js';
86
+ import { useLegendAISuggestTelemetry } from '../LegendAISuggestTelemetryHooks.js';
82
87
  import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../../../__lib__/LegendStudioDocumentation.js';
83
88
  import { DocumentationLink } from '@finos/legend-lego/application';
84
89
 
@@ -267,32 +272,42 @@ const ServiceGeneralEditor = observer(() => {
267
272
  const [aiDocSuggestion, setAIDocSuggestion] = useState<string | undefined>(
268
273
  undefined,
269
274
  );
275
+ const aiSuggestTelemetry = useLegendAISuggestTelemetry(
276
+ editorStore,
277
+ { surface: LEGENDAI_SUGGEST_SURFACE.SERVICE, elementPath: service.path },
278
+ { legendAIUrl, available: Boolean(aiDocSuggester), isReadOnly },
279
+ );
270
280
  const suggestDocumentationWithAI = async (): Promise<void> => {
271
281
  if (!aiDocSuggester || !legendAIUrl) {
272
282
  return;
273
283
  }
274
- LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestLaunched(
275
- applicationStore.telemetryService,
276
- service.path,
277
- editorStore.editorMode.getSourceInfo(),
278
- );
284
+ const request = aiSuggestTelemetry.launch({
285
+ existingText: service.documentation,
286
+ });
279
287
  setIsSuggestingWithAI(true);
280
288
  setAIDocSuggestion(undefined);
289
+ let stage = LEGENDAI_SUGGEST_STAGE.SERIALIZE;
281
290
  try {
282
291
  const serviceGrammar =
283
292
  await editorStore.graphManagerState.graphManager.elementsToPureCode([
284
293
  service,
285
294
  ]);
295
+ stage = LEGENDAI_SUGGEST_STAGE.REQUEST;
286
296
  const suggestion = await aiDocSuggester(serviceGrammar, legendAIUrl);
287
- setAIDocSuggestion(suggestion);
297
+ const shouldShow = aiSuggestTelemetry.succeed(request, {
298
+ suggestionText: suggestion,
299
+ definitionsLength: serviceGrammar.length,
300
+ currentText: service.documentation,
301
+ });
302
+ if (!shouldShow) {
303
+ applicationStore.notificationService.notifyWarning(
304
+ 'LegendAI did not return a documentation suggestion for this service',
305
+ );
306
+ }
307
+ setAIDocSuggestion(shouldShow ? suggestion : undefined);
288
308
  } catch (error) {
289
309
  assertErrorThrown(error);
290
- LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestFailure(
291
- applicationStore.telemetryService,
292
- service.path,
293
- error.message,
294
- editorStore.editorMode.getSourceInfo(),
295
- );
310
+ aiSuggestTelemetry.fail(request, error, stage);
296
311
  if (
297
312
  error instanceof NetworkClientError &&
298
313
  (error.response.status === HttpStatus.UNAUTHORIZED ||
@@ -314,20 +329,23 @@ const ServiceGeneralEditor = observer(() => {
314
329
  if (!aiDocSuggestion) {
315
330
  return;
316
331
  }
317
- LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestApplied(
318
- applicationStore.telemetryService,
319
- service.path,
320
- editorStore.editorMode.getSourceInfo(),
321
- );
332
+ const servicePath = service.path;
333
+ aiSuggestTelemetry.apply({
334
+ existingText: service.documentation,
335
+ appliedText: aiDocSuggestion,
336
+ readCurrentText: (store) => {
337
+ const element =
338
+ store.graphManagerState.graph.getNullableElement(servicePath);
339
+ return element instanceof Service
340
+ ? { found: true, text: element.documentation }
341
+ : { found: false };
342
+ },
343
+ });
322
344
  service_setDocumentation(service, aiDocSuggestion);
323
345
  setAIDocSuggestion(undefined);
324
346
  };
325
347
  const discardAIDocSuggestion = (): void => {
326
- LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestDiscarded(
327
- applicationStore.telemetryService,
328
- service.path,
329
- editorStore.editorMode.getSourceInfo(),
330
- );
348
+ aiSuggestTelemetry.discard();
331
349
  setAIDocSuggestion(undefined);
332
350
  };
333
351
 
@@ -113,10 +113,8 @@ export const RowIdentifierEditor = observer(
113
113
  tableRowIdentifierState.connectionTestDataState.editorStore
114
114
  .changeDetectionState.observerContext,
115
115
  );
116
- if (valueSpec) {
117
- rowIdentifierState.updateRowIdentifierValue(valueSpec);
118
- rowIdentifierState.updateRowIdentifierColumn(val.value);
119
- }
116
+ rowIdentifierState.updateRowIdentifierValue(valueSpec);
117
+ rowIdentifierState.updateRowIdentifierColumn(val.value);
120
118
  }
121
119
  };
122
120
 
@@ -129,9 +127,7 @@ export const RowIdentifierEditor = observer(
129
127
  tableRowIdentifierState.connectionTestDataState.editorStore
130
128
  .changeDetectionState.observerContext,
131
129
  );
132
- if (valueSpec) {
133
- rowIdentifierState.updateRowIdentifierValue(valueSpec);
134
- }
130
+ rowIdentifierState.updateRowIdentifierValue(valueSpec);
135
131
  };
136
132
 
137
133
  return (
@@ -166,10 +162,8 @@ export const RowIdentifierEditor = observer(
166
162
  .changeDetectionState.observerContext
167
163
  }
168
164
  typeCheckOption={{
169
- expectedType: guaranteeNonNullable(
170
- getPrimitiveTypeFromRelationalType(
171
- guaranteeNonNullable(rowIdentifierState.column.type),
172
- ),
165
+ expectedType: getPrimitiveTypeFromRelationalType(
166
+ guaranteeNonNullable(rowIdentifierState.column.type),
173
167
  ),
174
168
  }}
175
169
  resetValue={resetNode}
@@ -64,6 +64,7 @@ import {
64
64
  } from '@finos/legend-shared';
65
65
  import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
66
66
  import { CodeEditor } from '@finos/legend-lego/code-editor';
67
+ import { LegendStudioTelemetryHelper } from '../../../__lib__/LegendStudioTelemetryHelper.js';
67
68
 
68
69
  const getWorkflowStatusIcon = (
69
70
  workflowStatus: WorkflowStatus,
@@ -501,6 +502,29 @@ export const WorkflowManager = observer(
501
502
  );
502
503
  }, [applicationStore, workflowManagerState]);
503
504
 
505
+ // Panel open / close telemetry — anchors a dwell time so we can measure
506
+ // engagement per surface. The mount emits `panel.open` and the cleanup
507
+ // emits `panel.close` with `dwellMs`.
508
+ useEffect(() => {
509
+ const openedAt = Date.now();
510
+ const editorStore = workflowManagerState.editorStore;
511
+ LegendStudioTelemetryHelper.logEvent_WorkflowManagerPanelOpened(
512
+ editorStore.applicationStore.telemetryService,
513
+ editorStore.editorMode.getSourceInfo(),
514
+ { scope: workflowManagerState.scope },
515
+ );
516
+ return () => {
517
+ LegendStudioTelemetryHelper.logEvent_WorkflowManagerPanelClosed(
518
+ editorStore.applicationStore.telemetryService,
519
+ editorStore.editorMode.getSourceInfo(),
520
+ {
521
+ scope: workflowManagerState.scope,
522
+ dwellMs: Date.now() - openedAt,
523
+ },
524
+ );
525
+ };
526
+ }, [workflowManagerState]);
527
+
504
528
  return (
505
529
  <div className="panel workflow-manager">
506
530
  <div className="panel__header side-bar__header">
package/src/index.ts CHANGED
@@ -70,11 +70,27 @@ export * from './stores/extensions/DSL_Data_LegendStudioApplicationPlugin_Extens
70
70
  export { DataProductEditorState } from './stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js';
71
71
  export { ComputeEditorState } from './stores/editor/editor-state/element-editor-state/compute/ComputeEditorState.js';
72
72
  export { LEGEND_STUDIO_DOCUMENTATION_KEY } from './__lib__/LegendStudioDocumentation.js';
73
- export { LegendStudioTelemetryHelper } from './__lib__/LegendStudioTelemetryHelper.js';
73
+ export {
74
+ LegendStudioTelemetryHelper,
75
+ SERVICE_REGISTRATION_TRIGGER,
76
+ LEGENDAI_SUGGEST_SURFACE,
77
+ LEGENDAI_SUGGEST_STAGE,
78
+ LEGENDAI_SUGGEST_ERROR_KIND,
79
+ LEGENDAI_SUGGEST_ABANDON_PHASE,
80
+ LEGENDAI_SUGGEST_RETENTION,
81
+ LEGENDAI_SUGGEST_MATCH_STRATEGY,
82
+ type LegendAISuggestTarget,
83
+ } from './__lib__/LegendStudioTelemetryHelper.js';
84
+ export {
85
+ LegendAISuggestTelemetryTracker,
86
+ type LegendAISuggestRequest,
87
+ type LegendAIAppliedTextReader,
88
+ } from './stores/editor/LegendAISuggestTelemetry.js';
74
89
 
75
90
  // components
76
91
  export { queryClass } from './components/editor/editor-group/uml-editor/ClassQueryBuilder.js';
77
92
  export * from './components/editor/EditorStoreProvider.js';
93
+ export { useLegendAISuggestTelemetry } from './components/editor/editor-group/LegendAISuggestTelemetryHooks.js';
78
94
  export { ActivityBarMenu } from './components/editor/ActivityBar.js';
79
95
  export * from './components/workspace-setup/ProjectSelectorUtils.js';
80
96
  export * from './components/workspace-setup/WorkspaceSelectorUtils.js';
@@ -101,7 +101,10 @@ import { CONFIGURATION_EDITOR_TAB } from './editor-state/project-configuration-e
101
101
  import { PACKAGEABLE_ELEMENT_TYPE } from './utils/ModelClassifierUtils.js';
102
102
  import { LEGEND_STUDIO_APP_EVENT } from '../../__lib__/LegendStudioEvent.js';
103
103
  import { LEGEND_STUDIO_SETTING_KEY } from '../../__lib__/LegendStudioSetting.js';
104
- import { LegendStudioTelemetryHelper } from '../../__lib__/LegendStudioTelemetryHelper.js';
104
+ import {
105
+ LegendStudioTelemetryHelper,
106
+ GRAPH_INITIALIZATION_ERROR_KIND,
107
+ } from '../../__lib__/LegendStudioTelemetryHelper.js';
105
108
 
106
109
  export enum GraphBuilderStatus {
107
110
  SUCCEEDED = 'SUCCEEDED',
@@ -328,6 +331,10 @@ export class EditorGraphState {
328
331
  }
329
332
 
330
333
  *buildGraph(entities: Entity[]): GeneratorFn<GraphBuilderResult> {
334
+ LegendStudioTelemetryHelper.logEvent_GraphInitializationLaunched(
335
+ this.editorStore.applicationStore.telemetryService,
336
+ this.editorStore.editorMode.getSourceInfo(),
337
+ );
331
338
  try {
332
339
  this.isInitializingGraph = true;
333
340
  const stopWatch = new StopWatch();
@@ -430,6 +437,28 @@ export class EditorGraphState {
430
437
  LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE),
431
438
  error,
432
439
  );
440
+ const errorKind =
441
+ error instanceof DependencyGraphBuilderError
442
+ ? GRAPH_INITIALIZATION_ERROR_KIND.DEPENDENCY
443
+ : error instanceof GraphDataDeserializationError
444
+ ? GRAPH_INITIALIZATION_ERROR_KIND.DESERIALIZATION
445
+ : error instanceof NetworkClientError
446
+ ? GRAPH_INITIALIZATION_ERROR_KIND.NETWORK
447
+ : GRAPH_INITIALIZATION_ERROR_KIND.OTHER;
448
+ const fallbackToTextMode = !(
449
+ error instanceof DependencyGraphBuilderError ||
450
+ error instanceof GraphDataDeserializationError ||
451
+ error instanceof NetworkClientError
452
+ );
453
+ LegendStudioTelemetryHelper.logEvent_GraphInitializationFailure(
454
+ this.editorStore.applicationStore.telemetryService,
455
+ this.editorStore.editorMode.getSourceInfo(),
456
+ {
457
+ errorKind,
458
+ errorMessage: error.message,
459
+ fallbackToTextMode,
460
+ },
461
+ );
433
462
  if (error instanceof DependencyGraphBuilderError) {
434
463
  this.editorStore.graphManagerState.graphBuildState.fail();
435
464
  // no recovery if dependency models cannot be built, this makes assumption that all dependencies models are compiled successfully
@@ -23,6 +23,7 @@ import {
23
23
  observable,
24
24
  } from 'mobx';
25
25
  import { ExplorerTreeState } from './ExplorerTreeState.js';
26
+ import { LegendAIAppliedSuggestionRegistry } from './LegendAISuggestTelemetry.js';
26
27
  import {
27
28
  ACTIVITY_MODE,
28
29
  PANEL_MODE,
@@ -222,6 +223,8 @@ export class EditorStore implements CommandRegistrar {
222
223
  readonly showcasePanelDisplayState: PanelDisplayState;
223
224
  readonly showcaseDefaultSize = 500;
224
225
  readonly tabManagerState = new EditorTabManagerState(this);
226
+ readonly legendAIAppliedSuggestionRegistry =
227
+ new LegendAIAppliedSuggestionRegistry();
225
228
  supportedElementTypesWithCategory: Map<string, string[]>;
226
229
 
227
230
  lazyTextEditorStore = new LazyTextEditorStore(this);
@@ -769,6 +772,17 @@ export class EditorStore implements CommandRegistrar {
769
772
  // - view project
770
773
  // - back to the setup page
771
774
  const createWorkspaceAndRelaunch = async (): Promise<void> => {
775
+ const startTime = Date.now();
776
+ const identity = {
777
+ projectId,
778
+ workspaceId,
779
+ workspaceType: workspaceType.toString(),
780
+ hasPatchReleaseVersion: patchReleaseVersionId !== undefined,
781
+ };
782
+ LegendStudioTelemetryHelper.logEvent_SdlcWorkspaceCreateLaunched(
783
+ this.applicationStore.telemetryService,
784
+ identity,
785
+ );
772
786
  try {
773
787
  this.applicationStore.alertService.setBlockingAlert({
774
788
  message: 'Creating workspace...',
@@ -784,6 +798,10 @@ export class EditorStore implements CommandRegistrar {
784
798
  this.applicationStore.notificationService.notifySuccess(
785
799
  `Workspace '${workspace.workspaceId}' is succesfully created. Reloading application...`,
786
800
  );
801
+ LegendStudioTelemetryHelper.logEvent_SdlcWorkspaceCreateSucceeded(
802
+ this.applicationStore.telemetryService,
803
+ { ...identity, durationMs: Date.now() - startTime },
804
+ );
787
805
  this.applicationStore.navigationService.navigator.reload();
788
806
  } catch (error) {
789
807
  assertErrorThrown(error);
@@ -791,6 +809,10 @@ export class EditorStore implements CommandRegistrar {
791
809
  LogEvent.create(LEGEND_STUDIO_APP_EVENT.WORKSPACE_SETUP_FAILURE),
792
810
  error,
793
811
  );
812
+ LegendStudioTelemetryHelper.logEvent_SdlcWorkspaceCreateFailure(
813
+ this.applicationStore.telemetryService,
814
+ { ...identity, errorMessage: error.message },
815
+ );
794
816
  this.applicationStore.notificationService.notifyError(error);
795
817
  }
796
818
  };
@@ -78,6 +78,12 @@ import { IngestDefinitionEditorState } from './editor-state/element-editor-state
78
78
  import { AvailabilityEditorState } from './editor-state/element-editor-state/availability/AvailabilityEditorState.js';
79
79
  import { ComputeEditorState } from './editor-state/element-editor-state/compute/ComputeEditorState.js';
80
80
  import type { EditorInitialConfiguration } from './editor-state/element-editor-state/ElementEditorInitialConfiguration.js';
81
+ import {
82
+ EDITOR_TAB_CLOSE_TRIGGER,
83
+ EDITOR_TAB_OPEN_TRIGGER,
84
+ LegendStudioTelemetryHelper,
85
+ } from '../../__lib__/LegendStudioTelemetryHelper.js';
86
+ import { getEditorTabTelemetryData } from './EditorTabTelemetryHelper.js';
81
87
 
82
88
  export class EditorTabManagerState extends TabManagerState {
83
89
  readonly editorStore: EditorStore;
@@ -106,6 +112,115 @@ export class EditorTabManagerState extends TabManagerState {
106
112
  this.editorStore = editorStore;
107
113
  }
108
114
 
115
+ /**
116
+ * Per-tab dwell accounting for {@link EDITOR_TAB__CLOSE} telemetry.
117
+ * Keyed by `TabState.uuid`. `activeSince` is set when the tab becomes the
118
+ * current tab and cleared on switch away; `accumulatedMs` is the total time
119
+ * the tab held focus. On close we flush any live `activeSince` and emit
120
+ * the total. The map is pruned on close so it does not leak.
121
+ */
122
+ private tabDwell = new Map<
123
+ string,
124
+ { activeSince: number | undefined; accumulatedMs: number }
125
+ >();
126
+
127
+ private startDwell(tab: TabState): void {
128
+ const entry = this.tabDwell.get(tab.uuid);
129
+ const now = Date.now();
130
+ if (entry) {
131
+ entry.activeSince = now;
132
+ } else {
133
+ this.tabDwell.set(tab.uuid, { activeSince: now, accumulatedMs: 0 });
134
+ }
135
+ }
136
+
137
+ private flushDwell(tab: TabState): number {
138
+ const entry = this.tabDwell.get(tab.uuid);
139
+ if (!entry) {
140
+ return 0;
141
+ }
142
+ if (entry.activeSince !== undefined) {
143
+ entry.accumulatedMs += Date.now() - entry.activeSince;
144
+ entry.activeSince = undefined;
145
+ }
146
+ return entry.accumulatedMs;
147
+ }
148
+
149
+ private emitTabClose(tab: TabState, trigger: EDITOR_TAB_CLOSE_TRIGGER): void {
150
+ const dwellMs = this.flushDwell(tab);
151
+ this.tabDwell.delete(tab.uuid);
152
+ LegendStudioTelemetryHelper.logEvent_EditorTabClosed(
153
+ this.editorStore.applicationStore.telemetryService,
154
+ this.editorStore.editorMode.getSourceInfo(),
155
+ {
156
+ ...getEditorTabTelemetryData(tab, this.editorStore),
157
+ dwellMs,
158
+ trigger,
159
+ },
160
+ );
161
+ }
162
+
163
+ override setCurrentTab(val: TabState | undefined): void {
164
+ const prev = this.currentTab;
165
+ if (prev && prev !== val) {
166
+ this.flushDwell(prev);
167
+ }
168
+ super.setCurrentTab(val);
169
+ if (val && val !== prev) {
170
+ this.startDwell(val);
171
+ }
172
+ }
173
+
174
+ override openTab(
175
+ tab: TabState,
176
+ trigger: EDITOR_TAB_OPEN_TRIGGER = EDITOR_TAB_OPEN_TRIGGER.PROGRAMMATIC,
177
+ ): void {
178
+ const isNew = !this.tabs.some((t) => t.match(tab));
179
+ super.openTab(tab);
180
+ if (isNew) {
181
+ LegendStudioTelemetryHelper.logEvent_EditorTabOpened(
182
+ this.editorStore.applicationStore.telemetryService,
183
+ this.editorStore.editorMode.getSourceInfo(),
184
+ {
185
+ ...getEditorTabTelemetryData(tab, this.editorStore),
186
+ trigger,
187
+ },
188
+ );
189
+ }
190
+ }
191
+
192
+ override closeTab(
193
+ tab: TabState,
194
+ trigger: EDITOR_TAB_CLOSE_TRIGGER = EDITOR_TAB_CLOSE_TRIGGER.USER_CLOSE,
195
+ ): void {
196
+ if (tab.isPinned) {
197
+ return;
198
+ }
199
+ // Emit before super so the tab is still known and dwell can be flushed.
200
+ this.emitTabClose(tab, trigger);
201
+ super.closeTab(tab);
202
+ }
203
+
204
+ override closeAllTabs(
205
+ trigger: EDITOR_TAB_CLOSE_TRIGGER = EDITOR_TAB_CLOSE_TRIGGER.CLOSE_ALL,
206
+ ): void {
207
+ // Only non-pinned tabs are actually closed by the base implementation.
208
+ this.tabs
209
+ .filter((tab) => !tab.isPinned)
210
+ .forEach((tab) => this.emitTabClose(tab, trigger));
211
+ super.closeAllTabs();
212
+ }
213
+
214
+ override closeAllOtherTabs(
215
+ tab: TabState,
216
+ trigger: EDITOR_TAB_CLOSE_TRIGGER = EDITOR_TAB_CLOSE_TRIGGER.CLOSE_OTHERS,
217
+ ): void {
218
+ this.tabs
219
+ .filter((t) => !t.isPinned && t !== tab)
220
+ .forEach((t) => this.emitTabClose(t, trigger));
221
+ super.closeAllOtherTabs(tab);
222
+ }
223
+
109
224
  get dndType(): string {
110
225
  return 'editor.tab-manager.tab';
111
226
  }
@@ -141,7 +256,7 @@ export class EditorTabManagerState extends TabManagerState {
141
256
  currentTabState,
142
257
  currentTabElementPath,
143
258
  };
144
- this.closeAllTabs();
259
+ this.closeAllTabs(EDITOR_TAB_CLOSE_TRIGGER.NAVIGATE_AWAY);
145
260
  }
146
261
 
147
262
  clearTabCache(): void {
@@ -273,6 +388,18 @@ export class EditorTabManagerState extends TabManagerState {
273
388
  return undefined;
274
389
  })
275
390
  .filter(isNonNullable);
391
+ // Emit OPEN telemetry for each restored tab so dwell tracking + dashboards
392
+ // treat cache-recovery as a first-class open (with trigger=restore).
393
+ this.tabs.forEach((tab) => {
394
+ LegendStudioTelemetryHelper.logEvent_EditorTabOpened(
395
+ this.editorStore.applicationStore.telemetryService,
396
+ this.editorStore.editorMode.getSourceInfo(),
397
+ {
398
+ ...getEditorTabTelemetryData(tab, this.editorStore),
399
+ trigger: EDITOR_TAB_OPEN_TRIGGER.RESTORE,
400
+ },
401
+ );
402
+ });
276
403
  this.setCurrentTab(
277
404
  this.findCurrentTab(
278
405
  this.cachedTabs.currentTabState,
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Copyright (c) 2026-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import type { TabState } from '@finos/legend-lego/application';
18
+ import {
19
+ type EditorElementKind,
20
+ EDITOR_TAB_KIND,
21
+ } from '../../__lib__/LegendStudioTelemetryHelper.js';
22
+ import { ArtifactGenerationViewerState } from './editor-state/ArtifactGenerationViewerState.js';
23
+ import { EditorDiffViewerState } from './editor-state/diff-viewer-state/EditorDiffViewerState.js';
24
+ import { ElementEditorState } from './editor-state/element-editor-state/ElementEditorState.js';
25
+ import { EndToEndWorkflowEditorState } from './editor-state/end-to-end-workflow-state/EndToEndWorkflowEditorState.js';
26
+ import { ModelImporterState } from './editor-state/ModelImporterState.js';
27
+ import { ProjectConfigurationEditorState } from './editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js';
28
+ import type { EditorStore } from './EditorStore.js';
29
+
30
+ /**
31
+ * Classifies a Studio editor {@link TabState} for telemetry.
32
+ * Returns a `tabKind` bucket and, when the tab is an element editor, the
33
+ * `elementKind` (via `EditorGraphState.getPackageableElementType`, which is
34
+ * plugin-aware and so covers extension-provided element kinds) and
35
+ * `elementPath` of the underlying packageable element.
36
+ */
37
+ export const getEditorTabTelemetryData = (
38
+ tab: TabState,
39
+ editorStore: EditorStore,
40
+ ): {
41
+ tabKind: EDITOR_TAB_KIND;
42
+ elementKind?: EditorElementKind | undefined;
43
+ elementPath?: string | undefined;
44
+ } => {
45
+ if (tab instanceof ElementEditorState) {
46
+ return {
47
+ tabKind: EDITOR_TAB_KIND.ELEMENT,
48
+ elementKind: editorStore.graphState.getPackageableElementType(
49
+ tab.element,
50
+ ),
51
+ elementPath: tab.elementPath,
52
+ };
53
+ }
54
+ if (tab instanceof EditorDiffViewerState) {
55
+ return { tabKind: EDITOR_TAB_KIND.ENTITY_DIFF };
56
+ }
57
+ if (tab instanceof ArtifactGenerationViewerState) {
58
+ return { tabKind: EDITOR_TAB_KIND.ARTIFACT_GENERATION };
59
+ }
60
+ if (tab instanceof ModelImporterState) {
61
+ return { tabKind: EDITOR_TAB_KIND.MODEL_IMPORTER };
62
+ }
63
+ if (tab instanceof ProjectConfigurationEditorState) {
64
+ return { tabKind: EDITOR_TAB_KIND.PROJECT_CONFIGURATION };
65
+ }
66
+ if (tab instanceof EndToEndWorkflowEditorState) {
67
+ return { tabKind: EDITOR_TAB_KIND.END_TO_END_WORKFLOW };
68
+ }
69
+ return { tabKind: EDITOR_TAB_KIND.OTHER };
70
+ };
@@ -52,7 +52,10 @@ import {
52
52
  graph_renameElement,
53
53
  } from '../graph-modifier/GraphModifierHelper.js';
54
54
  import { ElementEditorState } from './editor-state/element-editor-state/ElementEditorState.js';
55
- import { LegendStudioTelemetryHelper } from '../../__lib__/LegendStudioTelemetryHelper.js';
55
+ import {
56
+ FORM_MODE_COMPILATION_ERROR_KIND,
57
+ LegendStudioTelemetryHelper,
58
+ } from '../../__lib__/LegendStudioTelemetryHelper.js';
56
59
  import { GraphEditorMode } from './GraphEditorMode.js';
57
60
  import { GlobalBulkServiceRegistrationState } from './sidebar-state/BulkServiceRegistrationState.js';
58
61
  import type { EditorInitialConfiguration } from './editor-state/element-editor-state/ElementEditorInitialConfiguration.js';
@@ -481,6 +484,19 @@ export class GraphEditFormModeState extends GraphEditorMode {
481
484
  );
482
485
  } catch (error) {
483
486
  assertErrorThrown(error);
487
+ if (!(error instanceof EngineError)) {
488
+ // Non-engine errors (e.g. network) are re-thrown below by `assertType`;
489
+ // still close out the `launch` emitted above so it has a terminal event.
490
+ LegendStudioTelemetryHelper.logEvent_GraphCompilationFailure(
491
+ this.editorStore.applicationStore.telemetryService,
492
+ this.editorStore.editorMode.getSourceInfo(),
493
+ {
494
+ errorKind: FORM_MODE_COMPILATION_ERROR_KIND.OTHER,
495
+ errorMessage: error.message,
496
+ fallbackToTextMode: false,
497
+ },
498
+ );
499
+ }
484
500
  // TODO: we probably should make this pattern of error the handling for all other exceptions in the codebase
485
501
  // i.e. there should be a catch-all handler (we can use if-else construct to check error types)
486
502
  assertType(error, EngineError, `Unhandled exception:\n${error}`);
@@ -523,6 +539,24 @@ export class GraphEditFormModeState extends GraphEditorMode {
523
539
  }
524
540
  }
525
541
 
542
+ // NOTE: the `assertType(error, EngineError, ...)` above guarantees
543
+ // `error` is an `EngineError` here, so the classification only needs
544
+ // to distinguish `CompilationError` from other `EngineError`s.
545
+ // Emitted before the (potentially slow, potentially throwing) switch to
546
+ // text mode so the failure is always recorded with an accurate timestamp.
547
+ LegendStudioTelemetryHelper.logEvent_GraphCompilationFailure(
548
+ this.editorStore.applicationStore.telemetryService,
549
+ this.editorStore.editorMode.getSourceInfo(),
550
+ {
551
+ errorKind:
552
+ error instanceof CompilationError
553
+ ? FORM_MODE_COMPILATION_ERROR_KIND.COMPILATION
554
+ : FORM_MODE_COMPILATION_ERROR_KIND.ENGINE,
555
+ errorMessage: error.message,
556
+ fallbackToTextMode: fallbackToTextModeForDebugging,
557
+ },
558
+ );
559
+
526
560
  // decide if we need to fall back to text mode for debugging
527
561
  if (fallbackToTextModeForDebugging) {
528
562
  // TODO: when we support showing multiple notifications, we can split this into 2