Skip to content

fix(alerts): accept window_in_seconds as the threshold window - #7927

Open
BetterAndBetterII wants to merge 2 commits into
comet-ml:mainfrom
BetterAndBetterII:cursor/alert-window-in-seconds-alias-908a
Open

fix(alerts): accept window_in_seconds as the threshold window#7927
BetterAndBetterII wants to merge 2 commits into
comet-ml:mainfrom
BetterAndBetterII:cursor/alert-window-in-seconds-alias-908a

Conversation

@BetterAndBetterII

Copy link
Copy Markdown

Summary

Test plan

  • RED then GREEN: window_in_seconds fires the same TRACE_ERRORS webhook as window
  • window still works
  • mvn test -Dtest=MetricsAlertJobTest — 13 passed

cursoragent and others added 2 commits August 20, 2026 08:17
Add a MetricsAlertJob regression for TRACE_ERRORS configs that supply the
documented REST key window_in_seconds instead of the evaluator's window
key, so a silent 201 can no longer hide a missing-window job failure.

Co-authored-by: Yuzhong Zhang <BetterAndBetterII@users.noreply.github.com>
MetricsAlertJob read only the canonical window key. Map the documented
REST alias onto that value so stored threshold:errors configs evaluate
instead of failing every scheduled run.

Co-authored-by: Yuzhong Zhang <BetterAndBetterII@users.noreply.github.com>
@BetterAndBetterII
BetterAndBetterII requested a review from a team as a code owner August 20, 2026 08:21
@github-actions github-actions Bot added java Pull requests that update Java code Backend tests Including test files, or tests related like configuration. 🟢 size/S labels Aug 20, 2026
BigDecimal threshold = new BigDecimal(thresholdString);

var windowString = config.configValue().get(WINDOW_CONFIG_KEY);
var windowString = resolveWindow(config.configValue());

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.

Misleading missing-config diagnostics

resolveWindow(config.configValue()) reports only window when both aliases are absent, so the job failure omits the accepted window_in_seconds spelling and misleads users — should we mention both keys or report the requirement generically?

Severity

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/jobs/MetricsAlertJob.java`
around lines 429-434, update the missing-window validation in `buildTriggerConfig`.
Because `resolveWindow(config.configValue())` accepts both `window` and
`window_in_seconds`, change the `IllegalArgumentException` message to mention both
accepted keys (or describe the resolved window configuration generically) so failures
are accurate.

Comment on lines +46 to +47
// Documented REST alias for WINDOW_CONFIG_KEY; stored configs may use either spelling.
public static final String WINDOW_IN_SECONDS_CONFIG_KEY = "window_in_seconds";

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.

alertTriggersToFormTriggers reads only config_value.window, so alias-only window_in_seconds alerts produce forms without required window; formTriggersToAlertTriggers likewise serializes only window, which can emit trigger_configs: [] and cause AlertService.update to wipe existing configuration — should we resolve window_in_seconds with window taking precedence in both projections? configValue is documented only as Map<String,String>, so REST consumers cannot discover the window_in_seconds alias or its precedence over window_seconds — should we add that to the source-level schema/API docs rather than generated OpenAPI artifacts?

Severity

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/AlertTriggerConfig.java` around
lines 46-59, where `window_in_seconds` is introduced as an alias: 1) Update
`alertTriggersToFormTriggers` and `formTriggersToAlertTriggers` to consistently resolve
`window` first and fall back to `window_in_seconds` (matching `resolveWindow`'s
precedence), applying this to both simple threshold and grouped feedback-score
conditions, and serialize the effective value so alias-backed alerts remain editable and
never collapse into an empty `trigger_configs` list. 2) Document the `window_in_seconds`
alias in the source-level API/schema documentation for `configValue`, explaining that
both `window` and `window_in_seconds` are accepted and that `window` takes precedence
when both are provided; do not manually edit generated OpenAPI artifacts—regenerate
them after merge.

Comment on lines +53 to +55
public static String resolveWindow(Map<String, String> configValue) {
if (configValue == null) {
return null;

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.

Undeclared nullable API contract

resolveWindow accepts a null configValue and returns null, but its annotations expose neither nullable contract to callers or static analysis — should we add the project’s nullable annotations, such as @Nullable Map<String, String> and @Nullable String, while preserving the raw-null behavior?

Severity

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/AlertTriggerConfig.java` around
lines 53-55, update the `resolveWindow` method to document its explicit nullable
contract. Annotate the `configValue` parameter and the `String` return value with the
project’s standard nullable annotation, adding the necessary import, while preserving
the current raw-null behavior.

Comment on lines +57 to +58
String window = configValue.get(WINDOW_CONFIG_KEY);
return window != null ? window : configValue.get(WINDOW_IN_SECONDS_CONFIG_KEY);

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.

Blank canonical window breaks alert evaluation

resolveWindow preserves window: "" because it falls back only when window == null, so MetricsAlertJob.buildTriggerConfig passes a blank value to Long.parseLong(windowString) and alert evaluation fails instead of using window_in_seconds: "300". Should we treat blank/whitespace canonical values as absent and fall back to the alias, or have AlertService reject this invalid combination?

Severity

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/AlertTriggerConfig.java` around
lines 57-58, update `resolveWindow` so blank or whitespace-only `window` values do not
take precedence over a valid `window_in_seconds` alias. Trim and validate the canonical
value before returning it, then fall back to the alias when the canonical value is
blank; alternatively, explicitly reject the combination if that is the established
config contract, and ensure the behavior prevents `Long.parseLong` from receiving an
empty value.

Comment on lines +234 to +245
@ParameterizedTest
@MethodSource("windowConfigKeys")
void firesTraceErrorsWhenWindowProvidedUnderCanonicalOrDocumentedAlias(String windowKey) {
Alert alert = alertWithErrorThreshold(windowKey, "2", "300");

when(projectMetricsDAO.getTotalTraceErrors(anyList(), any(Instant.class), any(Instant.class)))
.thenReturn(Mono.just(new BigDecimal("3")));
when(alertService.findAllByWorkspaceAndEventTypes(null,
MetricsAlertJob.SUPPORTED_EVENT_TYPES)).thenReturn(List.of(alert));

job.doJob(null);

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.

Four metric aliases remain unverified

windowConfigKeys() covers only TRACE_ERRORS, so regressions in the window_in_seconds alias path for the four other supported event types can go undetected while tests pass — should we extend the behavior-focused matrix or integration coverage to assert each expected interval calculation, per .agents/skills/opik-backend/testing.md?

Severity

Want Baz to fix this for you? Activate Fixer You can also update your AI coding guidelines based on this comment by apply pr to [branch name]

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/jobs/MetricsAlertJobTest.java
around lines 234-245, expand
`firesTraceErrorsWhenWindowProvidedUnderCanonicalOrDocumentedAlias` beyond the
`TRACE_ERRORS` fixture to cover `TRACE_COST`, `TRACE_LATENCY`, `TRACE_FEEDBACK_SCORE`,
and `TRACE_THREAD_FEEDBACK_SCORE`. Update the parameter matrix and test fixture/mocks
with the required event-specific threshold configuration and metric branches, then
assert that each case uses the alias to calculate the expected interval and emits the
correct payload.

Comment on lines +306 to +315
private static Alert alertWithErrorThreshold(String windowKey, String threshold, String window) {
AlertTrigger trigger = AlertTrigger.builder()
.id(UUID.randomUUID())
.eventType(AlertEventType.TRACE_ERRORS)
.triggerConfigs(List.of(AlertTriggerConfig.builder()
.id(UUID.randomUUID())
.type(AlertTriggerConfigType.THRESHOLD_ERRORS)
.configValue(Map.of(
THRESHOLD_CONFIG_KEY, threshold,
windowKey, window))

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.

Window alias precedence is untested

The fixture sets exactly one window key, so its cases never exercise resolveWindow's precedence and a regression favoring window_in_seconds would still pass — should we add a focused case with both values different and assert the webhook uses window?

Severity

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/jobs/MetricsAlertJobTest.java`
around lines 306-315, update the `alertWithErrorThreshold` fixture and related
parameterized tests to cover configurations containing both `window` and
`window_in_seconds` with different values. Add a focused assertion that the webhook
payload uses the canonical `window` value, ensuring regressions that prefer the
documented alias are caught.

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 🟢 size/S tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants