-
[OPIK-3920] [BE][FE] Add experiments column and filter to Traces tab (#4806)
发布于
2026-02-02 11:17:22 +00:00 -
[OPIK-3920] [BE][FE] Add experiment column and filter to Traces tab
-
Revision 2: Add experiment column sorting support
-
Revision 3: Add experiment_name filter with partial matching support
-
Revision 4: Add Experiment ID column to traces table
-
Revision 5: Add sorting support for Experiment ID column
-
Revision 6: Add ExperimentSelectBox for smart experiment name filter
-
[OPIK-3920] [BE] Remove unused ExperimentDAO code
-
Revision 7: Fix experiment.id sorting - skip dynamic null handling for mapped fields
-
Revision 8: Fix experiment.id sorting - exclude mapped fields from dynamic key binding
-
Revision 9: Simplify experiment_id sorting - use underscore instead of dot to avoid dynamic field treatment
-
Revision 10: Use equals operator for experiment_name filter instead of contains
-
Revision 11: Rename experiment column id to experiment_name for consistency
-
Revision 12: Sort experiments by name in ExperimentSelectBox filter
-
Revision 13: Use experiment_id filter for both name dropdown and ID input
-
Revision 14: Remove table prefix from experiment_id filter field
-
Revision 15: Fix duplicate filter issue by using separate IDs with transform function
-
Revision 16: Fix - dropdown on Experiment name, text input on Experiment ID
-
Revision 17: Remove duplicate customMeta, add transform to stats hook
-
Revision 18: Use ResourceCell for experiment columns, add datasetId to ExperimentReference for navigation
-
Revision 11: Simplify to single Experiment column and filter (remove Experiment ID)
-
Revision 12: Use experiment_id consistently, remove transform function
-
Revision 13: Remove unused overloaded hasDynamicKeys and bindDynamicKeys methods
-
Revision 14: Use anyMatch instead of findAny().isPresent() for better readability
-
Revision 15: Remove unused isMappedField check
-
Revision 16: Use named tuple elements and extract field mapping to static constant
-
Revision 17: Flatten experiment tuple into separate columns for cleaner mapping
-
Revision 18: Extract experiment_id to COLUMN_EXPERIMENT_ID constant in shared types
-
Revision 19: Add experiment to IGNORED_FIELDS_TRACES in test assertions
-
Revision 20: Add comprehensive tests for experiment reference, sorting, and filtering
-
Revision 21: Move FilterOperator and TraceField imports to top of file
-
Revision 22: Fix filter operator to use Operator.EQUAL instead of FilterOperator.EQUALS
-
Revision 23: Add Dataset, Experiment, ExperimentItem imports and remove fully qualified class names
-
Revision 24: Remove remaining fully qualified class names from test code
-
Revision 25: Use TraceFilter.builder() instead of Filter.builder() and pass TraceField directly
-
Revision 26: Extract common test setup and parameterize sorting test
-
Revision 27: Fix test failures - add EXPERIMENT to EXCLUDE_FUNCTIONS and use unique experiment names
-
Revision 28: Add unique suffix to experiment names in filtering test
-
Revision 29: Use separate random suffixes for each experiment in filtering test
-
Revision 30: Use separate random suffixes for each experiment in sorting test
-
Revision 31: Use createPartialExperiment() for all experiment tests to avoid 409 conflicts
-
Revision 32: Remove unused Experiment import
-
Revision 33: Use datasetName instead of datasetId when creating experiments (datasetId is read-only)
-
Revision 35: Add projectId filter to ExperimentsSelectBox
-
Revision 36: Remove unnecessary INNER JOIN and fix deduplication in experiment_filters subquery
-
Revision 37: Address PR review comments - fix deduplication, optimize performance, and improve code quality
Critical fixes:
- Revert LIMIT 1 BY trace_id to LIMIT 1 BY id in experiment_filters subqueries (3 locations)
The correct deduplication for experiment_items is by id, not trace_id - Remove unnecessary LIMIT 1 BY ei.trace_id in experiments_agg CTE
trace_id is part of the primary key and doesn't need deduplication, use DISTINCT instead
Performance optimizations:
- Filter experiments early by only selecting experiments referenced in current query scope
Prevents retrieving all workspace experiments when only a subset is needed - Use full primary key ORDER BY (workspace_id, dataset_id, id) in experiments subquery
Improves ClickHouse query performance
Code quality improvements:
- Fix mapExperiment null check to only validate key fields (experimentId, experimentDatasetId)
experimentName is editable and its absence doesn't indicate missing data - Read UUID fields directly from DB instead of String conversion
Avoids unnecessary UUID.fromString() calls - Move EXPERIMENT_FIELD_MAPPING constant to TraceSortingFactory
Better organization and encapsulation of sorting-related constants
Addresses comments from andrescrz in PR #4806
- Revision 38: Remove redundant experiment filtering in experiments_agg CTE
The id IN (SELECT DISTINCT experiment_id FROM experiment_items ...) filter
is redundant because the INNER JOIN on ei.experiment_id = e.id already
ensures we only get experiments that exist in the filtered experiment_items.The join naturally limits to only experiments referenced in the ei subquery,
which is already filtered by workspace_id and time range.- Revision 39: Remove unnecessary table alias in experiment_filters subqueries
Since there's only one table (experiment_items) in these subqueries,
the ei. alias prefix is unnecessary and makes the code more verbose.Simplified across all 3 occurrences of the experiment_filters subquery.
- Revision 40: Add builder pattern to ExperimentReference and TestContext records
Added @Builder(toBuilder = true) to both records for better maintainability
and readability, as suggested in code review.Changes:
- Added @Builder(toBuilder = true) to ExperimentReference record
- Updated mapExperiment() to use builder pattern instead of constructor
- Added @Builder(toBuilder = true) to TestContext test record
- Updated setupWorkspaceProjectDataset() to use builder pattern
- Added lombok.Builder import to TracesResourceTest
This makes the code more maintainable and follows the builder pattern
convention used throughout the codebase.- Revision 41: Fix ClickHouse UUID null handling in mapExperiment
- Read experiment UUID fields as String instead of UUID to handle ClickHouse R2DBC driver quirks
- Add check for CLICKHOUSE_FIXED_STRING_UUID_FIELD_NULL_VALUE (36 null characters)
- ClickHouse returns \u0000 repeated 36 times for NULL UUID FixedString fields
- Convert to UUID using UUID.fromString() after validation
- This prevents IllegalArgumentException when LEFT JOIN experiments_agg doesn't match
- Revision 42: Optimize experiments_agg CTE to only build when needed
- Wrap experiments_agg CTE in conditional: <if(sort_has_experiment || !exclude_experiment)>
- CTE is now only built when:
- Sorting by experiment_id (sort_has_experiment=true), OR
- Experiment field is NOT excluded (!exclude_experiment=true)
- Performance improvement: Skip expensive CTE and JOINs when experiment column is hidden
- Frontend will pass exclude=experiment when column is not visible
- Backend already prevents excluding fields used in sorting (line 3015)
- Revision 42: Add exclude parameter to optimize experiment data fetching
Frontend changes:
- Add exclude parameter to useTracesList hook to pass excluded fields to backend
- Update useTracesOrSpansList to support exclude parameter
- Compute excludeFields in TracesSpansTab based on visible columns
- Exclude experiment field when COLUMN_EXPERIMENT_ID is not in selectedColumns
- Automatically refetch when column visibility changes (via useMemo dependency)
Backend optimization:
- Frontend passes exclude=experiment when column is hidden
- Backend skips building experiments_agg CTE when excluded
- Significant performance improvement for traces queries without experiment column
Note: Backend already prevents excluding fields used in sorting (line 3015 in TraceDAO.java)
-
Revision 43: Only exclude experiment field for traces, not spans
-
Revision 44: Fix experiments_agg JOIN in final SELECT to include sorting condition
- Changed condition from
<if(!exclude_experiment)>to<if(sort_has_experiment || !exclude_experiment)> - Ensures experiments_agg is joined when sorting by experiment, even if excluded
- Fixes "Unknown expression identifier
eaag.experiment_name" error when sorting by experiment - Matches the conditional logic used in traces_final CTE (line 1090)
下载附件
-