Skip to content

[OPIK-5303] [BE] feat: add source filter support to GET /projects/stats#5929

Open
thiagohora wants to merge 1 commit intomainfrom
thiaghora/OPIK-5303-add-source-filter-to-project-stats
Open

[OPIK-5303] [BE] feat: add source filter support to GET /projects/stats#5929
thiagohora wants to merge 1 commit intomainfrom
thiaghora/OPIK-5303-add-source-filter-to-project-stats

Conversation

@thiagohora
Copy link
Copy Markdown
Contributor

Details

Add filters query parameter support to GET /projects/stats endpoint so callers can filter the aggregated project statistics by trace source. This allows excluding non-SDK traces (experiment, playground, optimization) from project stats, which is useful for displaying clean user-initiated statistics in the v2 Projects page.

Changes:

  • Added filters query param (String) to GET /projects/stats REST endpoint
  • Updated ProjectCriteria record to hold List<? extends Filter> instead of a single source field
  • Updated ProjectService.getProjectStats to pass filters through to the DAO
  • Updated TraceDAO.getStatsByProjectIds to accept and apply List<TraceFilter> using the existing FilterQueryBuilder / FilterStrategy.TRACE mechanism
  • Added integration test getProjectStats__whenSourceFilterApplied__thenExcludeNonSdkTraces inside ProjectErrorCountTests

Change checklist

  • User facing
  • Documentation update

Issues

  • Resolves #
  • OPIK-5303

AI-WATERMARK

AI-WATERMARK: yes

  • If yes:
    • Tools: Claude Code
    • Model(s): claude-sonnet-4-6
    • Scope: full implementation
    • Human verification: code review + manual testing

Testing

  • mvn test -Dtest="ProjectsResourceTest#getProjectStats__whenSourceFilterApplied__thenExcludeNonSdkTraces" — passes ✅
  • mvn spotless:check — passes ✅
  • Scenarios validated:
    • SDK-only filter correctly excludes experiment, playground, and optimization traces from stats
    • No filter returns all traces (backwards compatible)
    • Filter is passed via URL-encoded JSON filters query param matching existing filter API conventions

Documentation

N/A — internal API change, no user-facing docs needed.

Wire List<TraceFilter> filters through ProjectCriteria → ProjectService → TraceDAO
so callers can exclude non-SDK traces (experiment, playground, optimization)
from aggregated project statistics.

- Added `filters` query param to GET /projects/stats endpoint
- Updated ProjectCriteria to hold List<? extends Filter>
- Updated ProjectService.getProjectStats to pass filters to DAO
- Updated TraceDAO.getStatsByProjectIds to accept and apply TraceFilters
- Added integration test covering source=sdk filter behavior

Implements OPIK-5303
@github-actions github-actions bot added java Pull requests that update Java code Backend tests Including test files, or tests related like configuration. labels Mar 27, 2026
Comment on lines +1960 to +1963
@Test
@DisplayName("when source filter is applied, then exclude non-SDK traces from stats")
void getProjectStats__whenSourceFilterApplied__thenExcludeNonSdkTraces() {
String workspaceName = UUID.randomUUID().toString();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getProjectStats__whenSourceFilterApplied__thenExcludeNonSdkTraces uses underscores and violates the test-naming rules, should we rename it to camelCase like whenSourceFilterAppliedThenExcludeNonSdkTraces?

Finding type: AI Coding Guidelines | Severity: 🟢 Low


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

Before applying, verify this suggestion against the current code. In
apps/opik-backend/src/test/java/com/comet/opik/api/resources/v1/priv/ProjectsResourceTest.java
around lines 1960-1963, the test method
getProjectStats__whenSourceFilterApplied__thenExcludeNonSdkTraces uses underscores and
violates the project testing naming rules. Rename the method to camelCase scenario
style, e.g. whenSourceFilterAppliedThenExcludeNonSdkTraces, updating the method
declaration accordingly (keep the existing @DisplayName as-is). Ensure there are no
other references to the old name in the file and run tests to confirm no breakage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping — the naming convention getProjectStats__whenSourceFilterApplied__thenExcludeNonSdkTraces is consistent with other existing tests in this class and across the backend test suite.

🤖 Reply posted via /address-github-pr-comments

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for clarifying the existing naming convention—I'll keep this in mind and save it to memory once the PR is merged.

@NonNull String workspaceId, List<? extends Filter> filters) {

if (projectIds.isEmpty()) {
return Mono.just(Map.of());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!CollectionUtils.isEmpty(filters)) { FilterQueryBuilder.toAnalyticsDbFilters(...FilterStrategy.TRACE) duplicates ProjectMetricsDAO's traceFilters(); should we extract a shared helper like applyTraceFilters(template, statement, filters)?

if (!CollectionUtils.isEmpty(filters)) { FilterQueryBuilder.toAnalyticsDbFilters(...FilterStrategy.TRACE) => applyTraceFilters(template, statement, filters)

Finding type: Code Dedup and Conventions | Severity: 🟢 Low


Want Baz to fix this for you? Activate Fixer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping — extracting a shared helper for two call sites would be premature abstraction. The pattern is straightforward and the duplication is minimal.

🤖 Reply posted via /address-github-pr-comments

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, that makes sense—avoiding premature abstraction here is reasonable. I’ll remember this preference for similar code dedup suggestions after the PR is merged.

Comment on lines 343 to 347
@QueryParam("page") @Min(1) @DefaultValue("1") int page,
@QueryParam("size") @Min(1) @DefaultValue(PAGE_SIZE) int size,
@QueryParam("name") @Schema(description = "Filter projects by name (partial match, case insensitive)") String name,
@QueryParam("filters") String filters,
@QueryParam("sorting") String sorting) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filters query param is undocumented in both @Schema annotation and openapi.yaml — should we add @Schema metadata (description, example, pattern) and update the OpenAPI spec so SDK regeneration picks it up?

Finding types: API design consistency Breaking Changes | Severity: 🟠 Medium


Want Baz to fix this for you? Activate Fixer

Other fix methods

Fix in Cursor

Prompt for AI Agents:

Before applying, verify this suggestion against the current code. In
apps/opik-backend/src/main/java/com/comet/opik/api/resources/v1/priv/ProjectsResource.java
around lines 343-347, the getProjectStats method adds a @QueryParam("filters") String
filters parameter but it has no OpenAPI/Schema metadata and is missing from the OpenAPI
spec. First, annotate this parameter with @Schema describing the expected format and
semantics (for example: whether it is a JSON-encoded filter object, a comma-separated
list, or a DSL), include an example (and a pattern if applicable), and keep the existing
parameter name and type (String). Ensure the new annotation follows the style of the
existing @Schema on the 'name' parameter. Second, update
sdks/code_generation/fern/openapi/openapi.yaml to add a new query parameter named
"filters" to the GET /v1/private/projects/stats operation with type string and a brief
description (e.g. "Serialized filters for project stats (format documented)"). Also add
a developer note in the OpenAPI file or repo docs indicating that SDKs and generated
clients must be regenerated after this change and run API compatibility tests; then run
the OpenAPI validation/linting and regenerate the SDKs to ensure the spec and clients
stay in sync.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping — the OpenAPI spec and SDK bindings will be updated automatically once the Fern automation runs after merge.

🤖 Reply posted via /address-github-pr-comments

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for clarifying that Fern automation will handle the OpenAPI spec and SDK updates—makes sense to skip manual changes here.

@thiagohora thiagohora marked this pull request as ready for review March 27, 2026 17:53
@thiagohora thiagohora requested a review from a team as a code owner March 27, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend java Pull requests that update Java code tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants