@finos/legend-application-query 13.8.52 → 13.8.54

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 (127) hide show
  1. package/lib/__lib__/LegendQueryAgentChatTelemetryHelper.d.ts +23 -4
  2. package/lib/__lib__/LegendQueryAgentChatTelemetryHelper.d.ts.map +1 -1
  3. package/lib/__lib__/LegendQueryAgentChatTelemetryHelper.js +15 -10
  4. package/lib/__lib__/LegendQueryAgentChatTelemetryHelper.js.map +1 -1
  5. package/lib/__lib__/LegendQueryEvent.d.ts +19 -0
  6. package/lib/__lib__/LegendQueryEvent.d.ts.map +1 -1
  7. package/lib/__lib__/LegendQueryEvent.js +22 -0
  8. package/lib/__lib__/LegendQueryEvent.js.map +1 -1
  9. package/lib/__lib__/LegendQueryLifecycleTelemetry.d.ts +58 -0
  10. package/lib/__lib__/LegendQueryLifecycleTelemetry.d.ts.map +1 -0
  11. package/lib/__lib__/LegendQueryLifecycleTelemetry.js +90 -0
  12. package/lib/__lib__/LegendQueryLifecycleTelemetry.js.map +1 -0
  13. package/lib/__lib__/LegendQueryNavigation.d.ts +3 -3
  14. package/lib/__lib__/LegendQueryNavigation.d.ts.map +1 -1
  15. package/lib/__lib__/LegendQueryNavigation.js +13 -3
  16. package/lib/__lib__/LegendQueryNavigation.js.map +1 -1
  17. package/lib/__lib__/LegendQuerySourceInfo.d.ts +137 -0
  18. package/lib/__lib__/LegendQuerySourceInfo.d.ts.map +1 -0
  19. package/lib/__lib__/LegendQuerySourceInfo.js +33 -0
  20. package/lib/__lib__/LegendQuerySourceInfo.js.map +1 -0
  21. package/lib/__lib__/LegendQueryTelemetryHelper.d.ts +127 -1
  22. package/lib/__lib__/LegendQueryTelemetryHelper.d.ts.map +1 -1
  23. package/lib/__lib__/LegendQueryTelemetryHelper.js +63 -0
  24. package/lib/__lib__/LegendQueryTelemetryHelper.js.map +1 -1
  25. package/lib/application/LegendQueryApplicationConfig.d.ts +4 -4
  26. package/lib/application/LegendQueryApplicationConfig.d.ts.map +1 -1
  27. package/lib/application/LegendQueryApplicationConfig.js +4 -5
  28. package/lib/application/LegendQueryApplicationConfig.js.map +1 -1
  29. package/lib/components/Core_LegendQueryApplicationPlugin.d.ts.map +1 -1
  30. package/lib/components/Core_LegendQueryApplicationPlugin.js +21 -3
  31. package/lib/components/Core_LegendQueryApplicationPlugin.js.map +1 -1
  32. package/lib/components/QueryEditor.d.ts.map +1 -1
  33. package/lib/components/QueryEditor.js +21 -6
  34. package/lib/components/QueryEditor.js.map +1 -1
  35. package/lib/components/data-space/DataSpaceInfo.js +6 -6
  36. package/lib/components/data-space/DataSpaceInfo.js.map +1 -1
  37. package/lib/components/data-space/DataSpaceQuerySetup.d.ts.map +1 -1
  38. package/lib/components/data-space/DataSpaceQuerySetup.js +19 -0
  39. package/lib/components/data-space/DataSpaceQuerySetup.js.map +1 -1
  40. package/lib/components/data-space/LegendQueryDataSpaceQueryBuilder.d.ts.map +1 -1
  41. package/lib/components/data-space/LegendQueryDataSpaceQueryBuilder.js +19 -0
  42. package/lib/components/data-space/LegendQueryDataSpaceQueryBuilder.js.map +1 -1
  43. package/lib/index.css +1 -1
  44. package/lib/index.d.ts +2 -1
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +2 -1
  47. package/lib/index.js.map +1 -1
  48. package/lib/light-mode.css +1 -1
  49. package/lib/package.json +1 -1
  50. package/lib/stores/EditExistingQuerySetupStore.d.ts.map +1 -1
  51. package/lib/stores/EditExistingQuerySetupStore.js +4 -13
  52. package/lib/stores/EditExistingQuerySetupStore.js.map +1 -1
  53. package/lib/stores/LegendQueryApplicationPlugin.d.ts +2 -1
  54. package/lib/stores/LegendQueryApplicationPlugin.d.ts.map +1 -1
  55. package/lib/stores/LegendQueryApplicationPlugin.js +23 -0
  56. package/lib/stores/LegendQueryApplicationPlugin.js.map +1 -1
  57. package/lib/stores/QueryEditorStore.d.ts +50 -2
  58. package/lib/stores/QueryEditorStore.d.ts.map +1 -1
  59. package/lib/stores/QueryEditorStore.js +195 -82
  60. package/lib/stores/QueryEditorStore.js.map +1 -1
  61. package/lib/stores/QueryProductionizerSetupStore.d.ts.map +1 -1
  62. package/lib/stores/QueryProductionizerSetupStore.js +17 -13
  63. package/lib/stores/QueryProductionizerSetupStore.js.map +1 -1
  64. package/lib/stores/QuerySetupStore.d.ts.map +1 -1
  65. package/lib/stores/QuerySetupStore.js +2 -0
  66. package/lib/stores/QuerySetupStore.js.map +1 -1
  67. package/lib/stores/__test-utils__/LegendQueryApplicationTestUtils.d.ts.map +1 -1
  68. package/lib/stores/__test-utils__/LegendQueryApplicationTestUtils.js +0 -3
  69. package/lib/stores/__test-utils__/LegendQueryApplicationTestUtils.js.map +1 -1
  70. package/lib/stores/data-cube/ExistingQueryDataCubeViewer.d.ts.map +1 -1
  71. package/lib/stores/data-cube/ExistingQueryDataCubeViewer.js +1 -0
  72. package/lib/stores/data-cube/ExistingQueryDataCubeViewer.js.map +1 -1
  73. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.d.ts +2 -0
  74. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.d.ts.map +1 -1
  75. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.js +12 -1
  76. package/lib/stores/data-product/DataProductSampleQueryCreatorStore.js.map +1 -1
  77. package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts +10 -0
  78. package/lib/stores/data-space/DataProductQueryCreatorStore.d.ts.map +1 -1
  79. package/lib/stores/data-space/DataProductQueryCreatorStore.js +63 -19
  80. package/lib/stores/data-space/DataProductQueryCreatorStore.js.map +1 -1
  81. package/lib/stores/data-space/DataProductSelectorState.d.ts +4 -2
  82. package/lib/stores/data-space/DataProductSelectorState.d.ts.map +1 -1
  83. package/lib/stores/data-space/DataProductSelectorState.js +30 -9
  84. package/lib/stores/data-space/DataProductSelectorState.js.map +1 -1
  85. package/lib/stores/data-space/DataSpaceQueryBuilderHelper.d.ts.map +1 -1
  86. package/lib/stores/data-space/DataSpaceQueryBuilderHelper.js +5 -1
  87. package/lib/stores/data-space/DataSpaceQueryBuilderHelper.js.map +1 -1
  88. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts +2 -0
  89. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.d.ts.map +1 -1
  90. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js +13 -7
  91. package/lib/stores/data-space/DataSpaceTemplateQueryCreatorStore.js.map +1 -1
  92. package/lib/stores/data-space/LegendQueryBareQueryBuilderState.d.ts.map +1 -1
  93. package/lib/stores/data-space/LegendQueryBareQueryBuilderState.js +1 -1
  94. package/lib/stores/data-space/LegendQueryBareQueryBuilderState.js.map +1 -1
  95. package/lib/stores/ingest/IngestQueryCreatorStore.d.ts +2 -0
  96. package/lib/stores/ingest/IngestQueryCreatorStore.d.ts.map +1 -1
  97. package/lib/stores/ingest/IngestQueryCreatorStore.js +10 -3
  98. package/lib/stores/ingest/IngestQueryCreatorStore.js.map +1 -1
  99. package/package.json +13 -13
  100. package/src/__lib__/LegendQueryAgentChatTelemetryHelper.ts +66 -10
  101. package/src/__lib__/LegendQueryEvent.ts +25 -0
  102. package/src/__lib__/LegendQueryLifecycleTelemetry.ts +132 -0
  103. package/src/__lib__/LegendQueryNavigation.ts +24 -5
  104. package/src/__lib__/LegendQuerySourceInfo.ts +162 -0
  105. package/src/__lib__/LegendQueryTelemetryHelper.ts +277 -1
  106. package/src/application/LegendQueryApplicationConfig.ts +12 -12
  107. package/src/components/Core_LegendQueryApplicationPlugin.tsx +47 -4
  108. package/src/components/QueryEditor.tsx +30 -2
  109. package/src/components/data-space/DataSpaceInfo.tsx +8 -8
  110. package/src/components/data-space/DataSpaceQuerySetup.tsx +25 -0
  111. package/src/components/data-space/LegendQueryDataSpaceQueryBuilder.tsx +25 -0
  112. package/src/index.ts +6 -1
  113. package/src/stores/EditExistingQuerySetupStore.ts +8 -20
  114. package/src/stores/LegendQueryApplicationPlugin.tsx +38 -0
  115. package/src/stores/QueryEditorStore.ts +269 -95
  116. package/src/stores/QueryProductionizerSetupStore.ts +24 -20
  117. package/src/stores/QuerySetupStore.ts +3 -0
  118. package/src/stores/__test-utils__/LegendQueryApplicationTestUtils.ts +0 -3
  119. package/src/stores/data-cube/ExistingQueryDataCubeViewer.ts +1 -0
  120. package/src/stores/data-product/DataProductSampleQueryCreatorStore.ts +17 -0
  121. package/src/stores/data-space/DataProductQueryCreatorStore.ts +99 -33
  122. package/src/stores/data-space/DataProductSelectorState.ts +58 -13
  123. package/src/stores/data-space/DataSpaceQueryBuilderHelper.ts +6 -1
  124. package/src/stores/data-space/DataSpaceTemplateQueryCreatorStore.ts +17 -6
  125. package/src/stores/data-space/LegendQueryBareQueryBuilderState.ts +5 -1
  126. package/src/stores/ingest/IngestQueryCreatorStore.ts +16 -5
  127. package/tsconfig.json +2 -0
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { action, computed, flow, flowResult, makeObservable, observable, override, } from 'mobx';
17
- import { LogEvent, assertErrorThrown, uuid, assertType, guaranteeNonNullable, ActionState, StopWatch, guaranteeType, quantifyList, assertNonNullable, returnUndefOnError, UnsupportedOperationError, filterByType, } from '@finos/legend-shared';
17
+ import { LogEvent, assertErrorThrown, uuid, assertType, guaranteeNonNullable, ActionState, StopWatch, guaranteeType, quantifyList, assertNonNullable, returnUndefOnError, UnsupportedOperationError, filterByType, buildTelemetryErrorFields, } from '@finos/legend-shared';
18
18
  import { PackageableRuntime, createPath, GraphManagerState, Query, PureExecution, PackageableElementExplicitReference, RuntimePointer, GRAPH_MANAGER_EVENT, extractElementNameFromPath, Mapping, createGraphBuilderReport, LegendSDLC, QuerySearchSpecification, toLightQuery, QueryParameterValue, reportGraphAnalytics, cloneQueryStereotype, cloneQueryTaggedValue, QueryProjectCoordinates, CORE_PURE_PATH, INTERNAL_ELEMENT_PATH, isValidFullPath, QUERY_PROFILE_PATH, QueryDataSpaceExecutionContextInfo, QueryExplicitExecutionContextInfo, QueryDataProductNativeExecutionContextInfo, QueryDataProductModelAccessExecutionContextInfo, QueryDataProductLakehouseExecutionContextInfo, QueryIngestExecutionContextInfo, ModelAccessPointGroup, IngestDefinition, LakehouseRuntime, V1_DATA_PRODUCT_ELEMENT_PROTOCOL_TYPE, V1_DataProductArtifact, V1_ModelAccessPointGroupInfo, DataProductAccessType, LakehouseAccessPoint, } from '@finos/legend-graph';
19
19
  import { generateExistingQueryEditorRoute, generateMappingQueryCreatorRoute, generateServiceQueryCreatorRoute, } from '../__lib__/LegendQueryNavigation.js';
20
20
  import { LEGEND_QUERY_APP_EVENT } from '../__lib__/LegendQueryEvent.js';
@@ -22,9 +22,11 @@ import { parseGACoordinates, StoredFileGeneration, } from '@finos/legend-storage
22
22
  import { resolveVersion, StoreProjectData, LATEST_VERSION_ALIAS, VersionedProjectData, retrieveProjectEntitiesWithClassifier, isSnapshotVersion, SNAPSHOT_VERSION_ALIAS, } from '@finos/legend-server-depot';
23
23
  import { ActionAlertActionType, ActionAlertType, DEFAULT_TAB_SIZE, DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH, } from '@finos/legend-application';
24
24
  import { LegendQueryEventHelper } from '../__lib__/LegendQueryEventHelper.js';
25
- import { ClassQueryBuilderState, MappingQueryBuilderState, ServiceQueryBuilderState, QueryLoaderState, QueryBuilderDataBrowserWorkflow, QueryBuilderActionConfig, QUERY_LOADER_DEFAULT_QUERY_SEARCH_LIMIT, ModelAccessPointDataProductExecutionState, LakehouseDataProductExecutionState, resolveDataProductAccessor, } from '@finos/legend-query-builder';
25
+ import { ClassQueryBuilderState, MappingQueryBuilderState, ServiceQueryBuilderState, QueryLoaderState, QueryBuilderDataBrowserWorkflow, QueryBuilderActionConfig, QUERY_LOADER_DEFAULT_QUERY_SEARCH_LIMIT, ModelAccessPointDataProductExecutionState, LakehouseDataProductExecutionState, resolveDataProductAccessor, QUERY_BUILDER_OPENED_FROM, } from '@finos/legend-query-builder';
26
26
  import { LegendQueryUserDataHelper } from '../__lib__/LegendQueryUserDataHelper.js';
27
- import { LegendQueryTelemetryHelper } from '../__lib__/LegendQueryTelemetryHelper.js';
27
+ import { buildQueryCreateFailureData, buildQueryIdentity, buildQueryLifecycleFailureData, buildQueryLoaderLifecycleTelemetryHandlers, } from '../__lib__/LegendQueryLifecycleTelemetry.js';
28
+ import { LegendQueryTelemetryHelper, } from '../__lib__/LegendQueryTelemetryHelper.js';
29
+ import { LegendQuerySourceType, } from '../__lib__/LegendQuerySourceInfo.js';
28
30
  import {} from '@finos/legend-extension-dsl-data-space/application';
29
31
  import { DSL_DataSpace_getGraphManagerExtension, getOwnDataSpace, QUERY_PROFILE_TAG_DATA_SPACE, resolveExecutionContextMapping, retrieveAnalyticsResultCache, retrieveDataspaceArtifactsCache, } from '@finos/legend-extension-dsl-data-space/graph';
30
32
  import { generateDataSpaceQueryCreatorRoute } from '../__lib__/DSL_DataSpace_LegendQueryNavigation.js';
@@ -98,13 +100,7 @@ export class QueryCreatorState {
98
100
  this.editorStore.applicationStore.notificationService.notifySuccess(`Successfully created query!`);
99
101
  LegendQueryEventHelper.notify_QueryCreateSucceeded(this.editorStore.applicationStore.eventService, { queryId: newQuery.id });
100
102
  LegendQueryTelemetryHelper.logEvent_CreateQuerySucceeded(this.editorStore.applicationStore.telemetryService, {
101
- query: {
102
- id: query.id,
103
- name: query.name,
104
- groupId: query.groupId,
105
- artifactId: query.artifactId,
106
- versionId: query.versionId,
107
- },
103
+ ...buildQueryIdentity(query),
108
104
  ...queryBuilderState.getExtraTelemetryMetadata(),
109
105
  });
110
106
  queryBuilderState.changeDetectionState.initialize(rawLambda);
@@ -117,6 +113,7 @@ export class QueryCreatorState {
117
113
  assertErrorThrown(error);
118
114
  this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE), error);
119
115
  this.editorStore.applicationStore.notificationService.notifyError(error);
116
+ LegendQueryTelemetryHelper.logEvent_CreateQueryFailed(this.editorStore.applicationStore.telemetryService, buildQueryCreateFailureData(this.queryName, error));
120
117
  }
121
118
  finally {
122
119
  this.createQueryState.reset();
@@ -205,18 +202,9 @@ export class QueryEditorStore {
205
202
  generateDefaultQueriesSummaryText: (queries) => queries.length
206
203
  ? `Showing ${quantifyList(queries, 'recently viewed query', 'recently viewed queries')}`
207
204
  : `No recently viewed queries`,
208
- onQueryDeleted: (queryId) => LegendQueryUserDataHelper.removeRecentlyViewedQuery(this.applicationStore.userDataService, queryId),
209
- onQueryRenamed: (query) => {
210
- LegendQueryTelemetryHelper.logEvent_RenameQuerySucceeded(applicationStore.telemetryService, {
211
- query: {
212
- id: query.id,
213
- name: query.name,
214
- groupId: query.groupId,
215
- artifactId: query.artifactId,
216
- versionId: query.versionId,
217
- },
218
- });
219
- },
205
+ ...buildQueryLoaderLifecycleTelemetryHandlers(this.applicationStore, {
206
+ onQueryDeleted: (queryId) => LegendQueryUserDataHelper.removeRecentlyViewedQuery(this.applicationStore.userDataService, queryId),
207
+ }),
220
208
  handleFetchDefaultQueriesFailure: () => LegendQueryUserDataHelper.removeRecentlyViewedQueries(this.applicationStore.userDataService),
221
209
  });
222
210
  this.queryCreatorState = new QueryCreatorState(this, undefined);
@@ -315,9 +303,9 @@ export class QueryEditorStore {
315
303
  this.enableMinialGraphForDataSpaceLoadingPerformance) {
316
304
  return;
317
305
  }
306
+ const stopWatch = new StopWatch();
318
307
  try {
319
308
  this.initState.inProgress();
320
- const stopWatch = new StopWatch();
321
309
  // TODO: when we genericize the way to initialize an application page
322
310
  this.applicationStore.assistantService.setIsHidden(true);
323
311
  // initialize the graph manager
@@ -327,21 +315,48 @@ export class QueryEditorStore {
327
315
  clientConfig: {
328
316
  baseUrl: this.applicationStore.config.engineServerUrl,
329
317
  queryBaseUrl: this.applicationStore.config.engineQueryServerUrl,
318
+ queryClientName: this.applicationStore.config.engineQueryClientName,
330
319
  enableCompression: true,
320
+ useCookieAuthOnly: this.applicationStore.config.engineUseCookieAuthOnly,
331
321
  },
332
322
  }, {
333
323
  tracerService: this.applicationStore.tracerService,
334
324
  });
335
325
  yield this.setUpEditorState();
336
- yield flowResult(this.buildGraph());
337
- this.queryBuilderState = (yield this.initializeQueryBuilderState(stopWatch));
326
+ try {
327
+ yield flowResult(this.buildGraph());
328
+ }
329
+ catch (error) {
330
+ assertErrorThrown(error);
331
+ this.logBuildGraphFailure(error);
332
+ throw error;
333
+ }
334
+ try {
335
+ this.queryBuilderState = (yield this.initializeQueryBuilderState(stopWatch));
336
+ }
337
+ catch (error) {
338
+ assertErrorThrown(error);
339
+ this.logInitializeQueryBuilderStateFailure(error);
340
+ throw error;
341
+ }
338
342
  this.queryLoaderState.initialize(this.queryBuilderState);
339
343
  this.initState.pass();
344
+ // the canonical "a query builder is loaded" signal, emitted for every
345
+ // route — creator and saved alike. Reported here rather than from each
346
+ // route's own load event so that counting opens does not require a union
347
+ // of differently shaped, half-covering events.
348
+ this.queryBuilderState.logOpened(this.getOpenedFrom(), {
349
+ ...this.getInitializeTelemetrySource(),
350
+ timings: this.applicationStore.timeService.finalizeTimingsRecord(stopWatch),
351
+ });
340
352
  }
341
353
  catch (error) {
342
354
  assertErrorThrown(error);
343
355
  this.applicationStore.logService.error(LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE), error);
344
356
  this.applicationStore.notificationService.notifyError(error);
357
+ // NOTE: log before handling the failure, which may reset the editor
358
+ // state that the telemetry source is derived from
359
+ this.logInitializeFailureMetrics(stopWatch, error);
345
360
  this.onInitializeFailure();
346
361
  this.initState.fail();
347
362
  }
@@ -349,6 +364,45 @@ export class QueryEditorStore {
349
364
  onInitializeFailure() {
350
365
  // Do Nothing
351
366
  }
367
+ /**
368
+ * Where the query was started from, used as the source info of the query
369
+ * builder state. Since this is derived from the editor state (e.g. the
370
+ * route) rather than the query builder state, it is also available when
371
+ * the editor fails to initialize.
372
+ */
373
+ getSourceInfo() {
374
+ return undefined;
375
+ }
376
+ /**
377
+ * Which surface opened the query builder, reported as `openedFrom` on
378
+ * `query-builder.opened`. Creator routes inherit this; only
379
+ * `ExistingQueryEditorStore` overrides it.
380
+ *
381
+ * Note this names the surface only — what is being queried is already carried
382
+ * by `getSourceInfo()` on the same payload.
383
+ */
384
+ getOpenedFrom() {
385
+ return QUERY_BUILDER_OPENED_FROM.QUERY_CREATOR;
386
+ }
387
+ /**
388
+ * Where the query was started from, reported when the query creator is
389
+ * initialized
390
+ */
391
+ getInitializeTelemetrySource() {
392
+ return {
393
+ // spread flat, matching how `sourceInfo` is reported on every other query
394
+ // telemetry event — see `QueryBuilderTelemetryContext`
395
+ ...this.getSourceInfo(),
396
+ restoredFromRecent: false,
397
+ };
398
+ }
399
+ logInitializeFailureMetrics(stopWatch, error) {
400
+ LegendQueryTelemetryHelper.logEvent_InitializeQueryCreatorFailed(this.applicationStore.telemetryService, {
401
+ ...this.getInitializeTelemetrySource(),
402
+ ...buildTelemetryErrorFields(error),
403
+ timings: this.applicationStore.timeService.finalizeTimingsRecord(stopWatch),
404
+ });
405
+ }
352
406
  *searchExistingQueryName(searchText) {
353
407
  const isValidSearchString = searchText.length >= DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH;
354
408
  try {
@@ -371,6 +425,28 @@ export class QueryEditorStore {
371
425
  logBuildGraphMetrics(graphBuilderReportData) {
372
426
  LegendQueryTelemetryHelper.logEvent_GraphInitializationSucceeded(this.applicationStore.telemetryService, graphBuilderReportData);
373
427
  }
428
+ /**
429
+ * Failure counterpart of {@link logBuildGraphMetrics}. Fires when the graph
430
+ * build stage of `initialize()` throws. Base emits with only the error
431
+ * dimensions — {@link ExistingQueryEditorStore} overrides to attach the
432
+ * loaded query's identity, mirroring how its success override attaches
433
+ * identity too.
434
+ */
435
+ logBuildGraphFailure(error) {
436
+ LegendQueryTelemetryHelper.logEvent_GraphInitializationFailed(this.applicationStore.telemetryService, buildTelemetryErrorFields(error));
437
+ }
438
+ /**
439
+ * Failure hook for the query builder state initialization stage of
440
+ * `initialize()`. Default is a no-op: creator routes already report a
441
+ * failure here through `INITIALIZE_QUERY_CREATOR__FAILURE`, so emitting a
442
+ * second event would double-count. {@link ExistingQueryEditorStore}
443
+ * overrides this to emit `VIEW_QUERY__FAILURE`, the counterpart of the
444
+ * `VIEW_QUERY__SUCCESS` its `initializeQueryBuilderState` fires on the
445
+ * happy path.
446
+ */
447
+ logInitializeQueryBuilderStateFailure(_error) {
448
+ // no-op by default; overrides on saved-query stores emit failure telemetry
449
+ }
374
450
  *buildFullGraph() {
375
451
  const stopWatch = new StopWatch();
376
452
  const projectInfo = this.getProjectInfo();
@@ -675,7 +751,7 @@ export class QueryEditorStore {
675
751
  * creates `LegendQueryDataProductQueryBuilderState`, and wires in
676
752
  * mapping coverage results.
677
753
  */
678
- async buildDataProductQueryBuilderState(groupId, artifactId, versionId, dataProductPath, artifact, accessId, dataProductAccessType, onDataProductChange, onLegacyDataSpaceChange, productSelectorState) {
754
+ async buildDataProductQueryBuilderState(groupId, artifactId, versionId, dataProductPath, artifact, accessId, dataProductAccessType, onDataProductChange, onLegacyDataSpaceChange, productSelectorState, sourceInfo) {
679
755
  // 3. Build minimal graph and get analysis result
680
756
  const dataProductAnalysisResult = await this.buildGraphAndDataproductAnalyticsResult(groupId, artifactId, versionId, dataProductPath, dataProductAccessType, accessId, artifact);
681
757
  // 4. Get the data product from the built graph
@@ -696,16 +772,18 @@ export class QueryEditorStore {
696
772
  }
697
773
  // 6. Create query builder state
698
774
  const projectInfo = { groupId, artifactId, versionId };
699
- const sourceInfo = {
775
+ const queryBuilderState = new LegendQueryDataProductQueryBuilderState(this.applicationStore, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE,
776
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
777
+ new QueryBuilderActionConfig_QueryApplication(this), dataProduct, artifact, resolvedState, this.depotServerClient, projectInfo, onDataProductChange, (path, gav) => this.createLakehousePackageableRuntime(path, gav), productSelectorState ??
778
+ new DataProductSelectorState(this.depotServerClient, this.applicationStore, this.lakehouseState?.contractServerClient), onLegacyDataSpaceChange, undefined, this.applicationStore.config.options.queryBuilderConfig, sourceInfo ?? {
779
+ sourceType: LegendQuerySourceType.DATA_PRODUCT,
700
780
  groupId,
701
781
  artifactId,
702
782
  versionId,
703
783
  dataProduct: dataProductPath,
704
- };
705
- const queryBuilderState = new LegendQueryDataProductQueryBuilderState(this.applicationStore, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE,
706
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
707
- new QueryBuilderActionConfig_QueryApplication(this), dataProduct, artifact, resolvedState, this.depotServerClient, projectInfo, onDataProductChange, (path, gav) => this.createLakehousePackageableRuntime(path, gav), productSelectorState ??
708
- new DataProductSelectorState(this.depotServerClient, this.applicationStore), onLegacyDataSpaceChange, undefined, this.applicationStore.config.options.queryBuilderConfig, sourceInfo);
784
+ accessType: dataProductAccessType,
785
+ accessId,
786
+ });
709
787
  if (dataProductAnalysisResult.dataProductAnalysis
710
788
  .mappingToMappingCoverageResult) {
711
789
  queryBuilderState.mappingToMappingCoverageResult =
@@ -764,13 +842,18 @@ export class MappingQueryCreatorStore extends QueryEditorStore {
764
842
  versionId: this.versionId,
765
843
  };
766
844
  }
767
- async initializeQueryBuilderState() {
768
- const projectInfo = this.getProjectInfo();
769
- const sourceInfo = {
770
- groupId: projectInfo.groupId,
771
- artifactId: projectInfo.artifactId,
772
- versionId: projectInfo.versionId,
845
+ getSourceInfo() {
846
+ return {
847
+ sourceType: LegendQuerySourceType.MAPPING,
848
+ groupId: this.groupId,
849
+ artifactId: this.artifactId,
850
+ versionId: this.versionId,
851
+ mapping: this.mappingPath,
852
+ runtime: this.runtimePath,
773
853
  };
854
+ }
855
+ async initializeQueryBuilderState() {
856
+ const sourceInfo = this.getSourceInfo();
774
857
  const queryBuilderState = new MappingQueryBuilderState(this.applicationStore, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE, new QueryBuilderActionConfig_QueryApplication(this), (val) => {
775
858
  this.applicationStore.navigationService.navigator.updateCurrentLocation(generateMappingQueryCreatorRoute(this.groupId, this.artifactId, this.versionId, val.path, guaranteeType(queryBuilderState.executionContextState.runtimeValue, RuntimePointer).packageableRuntime.value.path));
776
859
  }, (val) => {
@@ -832,16 +915,19 @@ export class ServiceQueryCreatorStore extends QueryEditorStore {
832
915
  versionId: this.versionId,
833
916
  };
834
917
  }
918
+ getSourceInfo() {
919
+ return {
920
+ sourceType: LegendQuerySourceType.SERVICE,
921
+ groupId: this.groupId,
922
+ artifactId: this.artifactId,
923
+ versionId: this.versionId,
924
+ service: this.servicePath,
925
+ };
926
+ }
835
927
  async initializeQueryBuilderState() {
836
928
  const service = this.graphManagerState.graph.getService(this.servicePath);
837
929
  assertType(service.execution, PureExecution, `Can't process service execution: only Pure execution is supported`);
838
- const projectInfo = this.getProjectInfo();
839
- const sourceInfo = {
840
- groupId: projectInfo.groupId,
841
- artifactId: projectInfo.artifactId,
842
- versionId: projectInfo.versionId,
843
- service: service.path,
844
- };
930
+ const sourceInfo = this.getSourceInfo();
845
931
  const queryBuilderState = new ServiceQueryBuilderState(this.applicationStore, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE, new QueryBuilderActionConfig_QueryApplication(this), service, this.graphManagerState.usableServices, this.executionKey, (val) => {
846
932
  this.applicationStore.navigationService.navigator.goToLocation(generateServiceQueryCreatorRoute(this.groupId, this.artifactId, this.versionId, val.path));
847
933
  }, (val) => {
@@ -971,13 +1057,7 @@ export class ExistingQueryUpdateState {
971
1057
  const updatedQuery = (yield this.editorStore.graphManagerState.graphManager.updateQuery(query, this.editorStore.graphManagerState.graph));
972
1058
  this.editorStore.applicationStore.notificationService.notifySuccess(`Successfully updated query!`);
973
1059
  LegendQueryTelemetryHelper.logEvent_UpdateQuerySucceeded(this.editorStore.applicationStore.telemetryService, {
974
- query: {
975
- id: query.id,
976
- name: query.name,
977
- groupId: query.groupId,
978
- artifactId: query.artifactId,
979
- versionId: query.versionId,
980
- },
1060
+ ...buildQueryIdentity(query),
981
1061
  ...queryBuilderState.getExtraTelemetryMetadata(),
982
1062
  });
983
1063
  config.onQueryUpdate?.(updatedQuery);
@@ -988,6 +1068,7 @@ export class ExistingQueryUpdateState {
988
1068
  assertErrorThrown(error);
989
1069
  this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE), error);
990
1070
  this.editorStore.applicationStore.notificationService.notifyError(error);
1071
+ LegendQueryTelemetryHelper.logEvent_UpdateQueryFailed(this.editorStore.applicationStore.telemetryService, buildQueryLifecycleFailureData(this.editorStore.id, error));
991
1072
  }
992
1073
  finally {
993
1074
  this.updateQueryState.complete();
@@ -1004,13 +1085,7 @@ export class ExistingQueryUpdateState {
1004
1085
  this.editorStore.applicationStore.notificationService.notifySuccess(`Successfully updated query!`);
1005
1086
  const extraTelemetryMetadata = this.editorStore.queryBuilderState?.getExtraTelemetryMetadata() ?? {};
1006
1087
  LegendQueryTelemetryHelper.logEvent_UpdateQuerySucceeded(this.editorStore.applicationStore.telemetryService, {
1007
- query: {
1008
- id: updatedQuery.id,
1009
- name: updatedQuery.name,
1010
- groupId: updatedQuery.groupId,
1011
- artifactId: updatedQuery.artifactId,
1012
- versionId: updatedQuery.versionId,
1013
- },
1088
+ ...buildQueryIdentity(updatedQuery),
1014
1089
  ...extraTelemetryMetadata,
1015
1090
  });
1016
1091
  }
@@ -1018,6 +1093,7 @@ export class ExistingQueryUpdateState {
1018
1093
  assertErrorThrown(error);
1019
1094
  this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE), error);
1020
1095
  this.editorStore.applicationStore.notificationService.notifyError(error);
1096
+ LegendQueryTelemetryHelper.logEvent_UpdateQueryFailed(this.editorStore.applicationStore.telemetryService, buildQueryLifecycleFailureData(queryId, error));
1021
1097
  }
1022
1098
  finally {
1023
1099
  this.updateQueryState.complete();
@@ -1114,15 +1190,33 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1114
1190
  const currentQuery = guaranteeNonNullable(this._lightQuery);
1115
1191
  LegendQueryTelemetryHelper.logEvent_GraphInitializationSucceeded(this.applicationStore.telemetryService, {
1116
1192
  graph: graphBuilderReportData,
1117
- query: {
1118
- id: currentQuery.id,
1119
- name: currentQuery.name,
1120
- groupId: currentQuery.groupId,
1121
- artifactId: currentQuery.artifactId,
1122
- versionId: currentQuery.versionId,
1123
- },
1193
+ ...buildQueryIdentity(currentQuery),
1194
+ });
1195
+ }
1196
+ logBuildGraphFailure(error) {
1197
+ // attach whatever identity is already known — `_lightQuery` is only
1198
+ // populated once the query resolves, which may not have happened yet, so
1199
+ // the route id is the only guaranteed field
1200
+ const currentQuery = this._lightQuery;
1201
+ LegendQueryTelemetryHelper.logEvent_GraphInitializationFailed(this.applicationStore.telemetryService, {
1202
+ ...buildTelemetryErrorFields(error),
1203
+ ...(currentQuery ? buildQueryIdentity(currentQuery) : {}),
1204
+ });
1205
+ }
1206
+ logInitializeQueryBuilderStateFailure(error) {
1207
+ const currentQuery = this._lightQuery;
1208
+ LegendQueryTelemetryHelper.logEvent_ViewQueryFailed(this.applicationStore.telemetryService, {
1209
+ queryId: this.queryId,
1210
+ ...(currentQuery ? buildQueryIdentity(currentQuery) : {}),
1211
+ ...buildTelemetryErrorFields(error),
1124
1212
  });
1125
1213
  }
1214
+ getOpenedFrom() {
1215
+ return QUERY_BUILDER_OPENED_FROM.QUERY_SAVED;
1216
+ }
1217
+ logInitializeFailureMetrics() {
1218
+ // Do nothing: an existing query is not a query creator
1219
+ }
1126
1220
  setLightQuery(val) {
1127
1221
  this._lightQuery = val;
1128
1222
  }
@@ -1207,11 +1301,13 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1207
1301
  const matchingExecutionContext = resolveExecutionContext(dataSpace, exec.executionKey, mapping, runtime);
1208
1302
  if (matchingExecutionContext) {
1209
1303
  const sourceInfo = {
1304
+ sourceType: LegendQuerySourceType.DATA_SPACE,
1210
1305
  groupId: queryInfo.groupId,
1211
1306
  artifactId: queryInfo.artifactId,
1212
1307
  versionId: queryInfo.versionId,
1213
1308
  queryId: queryInfo.id,
1214
1309
  dataSpace: dataSpace.path,
1310
+ executionContext: exec.executionKey,
1215
1311
  };
1216
1312
  const visitedDataSpaces = LegendQueryUserDataHelper.getRecentlyVisitedDataSpaces(this.applicationStore.userDataService);
1217
1313
  const dataSpaceQueryBuilderState = new LegendQueryDataSpaceQueryBuilderState(this.applicationStore, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE, new QueryBuilderActionConfig_QueryApplication(this), dataSpace, matchingExecutionContext, isLightGraphEnabled, this.depotServerClient, {
@@ -1264,7 +1360,7 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1264
1360
  else {
1265
1361
  this.applicationStore.notificationService.notifyWarning(`Can't switch data product: default execution context not specified`);
1266
1362
  }
1267
- }, new DataProductSelectorState(this.depotServerClient, this.applicationStore), () => {
1363
+ }, new DataProductSelectorState(this.depotServerClient, this.applicationStore, this.lakehouseState?.contractServerClient), () => {
1268
1364
  this.applicationStore.notificationService.notifyWarning('Switching data products is not supported from the existing query editor. Please open a new query instead.');
1269
1365
  }, dataSpaceAnalysisResult, undefined, undefined, undefined, this.applicationStore.config.options.queryBuilderConfig, sourceInfo);
1270
1366
  const matchingExecutionContextMapping = resolveExecutionContextMapping(matchingExecutionContext);
@@ -1295,10 +1391,13 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1295
1391
  else if (exec instanceof QueryExplicitExecutionContextInfo) {
1296
1392
  const projectInfo = this.getProjectInfo();
1297
1393
  const sourceInfo = {
1394
+ sourceType: LegendQuerySourceType.MAPPING,
1298
1395
  groupId: projectInfo.groupId,
1299
1396
  artifactId: projectInfo.artifactId,
1300
1397
  versionId: projectInfo.versionId,
1301
1398
  queryId: queryInfo.id,
1399
+ mapping: exec.mapping,
1400
+ runtime: exec.runtime,
1302
1401
  };
1303
1402
  const classQueryBuilderState = new ClassQueryBuilderState(this.applicationStore, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE, this.applicationStore.config.options.queryBuilderConfig, sourceInfo);
1304
1403
  classQueryBuilderState.workflowState.updateActionConfig(new QueryBuilderActionConfig_QueryApplication(this));
@@ -1330,6 +1429,15 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1330
1429
  const artifact = await this.fetchDataProductArtifact(queryInfo.groupId, queryInfo.artifactId, queryInfo.versionId, exec.dataProductPath);
1331
1430
  const queryBuilderState = await this.buildDataProductQueryBuilderState(queryInfo.groupId, queryInfo.artifactId, queryInfo.versionId, exec.dataProductPath, artifact, executionContextId, accessType, async () => {
1332
1431
  this.applicationStore.notificationService.notifyWarning('Switching data products is not supported from the existing query editor. Please open a new query instead.');
1432
+ }, undefined, undefined, {
1433
+ sourceType: LegendQuerySourceType.DATA_PRODUCT,
1434
+ groupId: queryInfo.groupId,
1435
+ artifactId: queryInfo.artifactId,
1436
+ versionId: queryInfo.versionId,
1437
+ queryId: queryInfo.id,
1438
+ dataProduct: exec.dataProductPath,
1439
+ accessType,
1440
+ accessId: executionContextId,
1333
1441
  });
1334
1442
  return queryBuilderState;
1335
1443
  }
@@ -1363,10 +1471,13 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1363
1471
  return next;
1364
1472
  };
1365
1473
  const ingestQueryBuilderState = new IngestLegendQueryBuilderState(this.applicationStore, undefined, this.graphManagerState, QueryBuilderDataBrowserWorkflow.INSTANCE, new QueryBuilderActionConfig_QueryApplication(this), ingestDefinition, Array.from(this._ingestEntitiesByPath.keys()), swapIngest, adhocRuntime, projectInfo, this.applicationStore.config.options.queryBuilderConfig, {
1474
+ sourceType: LegendQuerySourceType.INGEST,
1366
1475
  groupId: projectInfo.groupId,
1367
1476
  artifactId: projectInfo.artifactId,
1368
1477
  versionId: projectInfo.versionId,
1369
1478
  queryId: queryInfo.id,
1479
+ ingestDefinitionPath: exec.ingestDefinitionPath,
1480
+ dataSet: exec.dataSet,
1370
1481
  });
1371
1482
  await ingestQueryBuilderState.changeAccessorOwner(ingestDefinition);
1372
1483
  await ingestQueryBuilderState.changeAccessor({
@@ -1403,7 +1514,21 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1403
1514
  this.applicationStore.logService.error(LogEvent.create(LEGEND_QUERY_APP_EVENT.GENERIC_FAILURE), `Error resolving preset query param values: ${error.message}`);
1404
1515
  }
1405
1516
  }
1406
- queryBuilderState.initializeWithQuery(existingQueryLambda, defaultParameters, query.gridConfig);
1517
+ try {
1518
+ queryBuilderState.initializeWithQuery(existingQueryLambda, defaultParameters, query.gridConfig);
1519
+ }
1520
+ catch (error) {
1521
+ assertErrorThrown(error);
1522
+ // pair with `INITIALIZE_QUERY_STATE__SUCCESS` below — this is the tight
1523
+ // boundary that success wraps, so failure is reported here rather than
1524
+ // in the outer catch (which owns `VIEW_QUERY__FAILURE`)
1525
+ LegendQueryTelemetryHelper.logEvent_InitializeQueryStateFailed(this.applicationStore.telemetryService, {
1526
+ queryId: this.queryId,
1527
+ ...buildQueryIdentity(query),
1528
+ ...buildTelemetryErrorFields(error),
1529
+ });
1530
+ throw error;
1531
+ }
1407
1532
  initailizeQueryStateReport.timings =
1408
1533
  this.applicationStore.timeService.finalizeTimingsRecord(initailizeQueryStateStopWatch, initailizeQueryStateReport.timings);
1409
1534
  const report = reportGraphAnalytics(this.graphManagerState.graph);
@@ -1411,23 +1536,11 @@ export class ExistingQueryEditorStore extends QueryEditorStore {
1411
1536
  // send analytics
1412
1537
  LegendQueryTelemetryHelper.logEvent_InitializeQueryStateSucceeded(this.applicationStore.telemetryService, {
1413
1538
  ...initailizeQueryStateReport,
1414
- query: {
1415
- id: query.id,
1416
- name: query.name,
1417
- groupId: query.groupId,
1418
- artifactId: query.artifactId,
1419
- versionId: query.versionId,
1420
- },
1539
+ ...buildQueryIdentity(query),
1421
1540
  });
1422
1541
  LegendQueryTelemetryHelper.logEvent_ViewQuerySucceeded(this.applicationStore.telemetryService, {
1423
1542
  ...report,
1424
- query: {
1425
- id: query.id,
1426
- name: query.name,
1427
- groupId: query.groupId,
1428
- artifactId: query.artifactId,
1429
- versionId: query.versionId,
1430
- },
1543
+ ...buildQueryIdentity(query),
1431
1544
  });
1432
1545
  return queryBuilderState;
1433
1546
  }