Skip to content

feat(workflow_engine): Add evaluation logs to detectors - #121908

Draft
saponifi3d wants to merge 1 commit into
jcallender/wfe-evals/move-workflow-to-loggerfrom
jcallender/wfe-evals/log-detectors
Draft

feat(workflow_engine): Add evaluation logs to detectors#121908
saponifi3d wants to merge 1 commit into
jcallender/wfe-evals/move-workflow-to-loggerfrom
jcallender/wfe-evals/log-detectors

Conversation

@saponifi3d

Copy link
Copy Markdown
Contributor

Description

Use the DetectorEvaluation to log the results of each detector. This was previously only done for cases when we had a next step (trigger or resolve the detector), now we log every evaluation.

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Aug 13, 2026
from sentry.workflow_engine.models.detector_group import DetectorGroup
from sentry.workflow_engine.processors import DetectorEvaluation
from sentry.workflow_engine.processors import DetectorEvaluation, ProcessDetectorsResult
from sentry.workflow_engine.processors.evaluation_logging import emit_detector_evaluation_logs

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.

Detector batch processing aborts on stale organization reference

The new emit_detector_evaluation_logs call in process_detectors uses _get_detector_organization without exception handling, causing the detector loop to abort on stale references or invalid config.

Evidence
  • Line 26 imports emit_detector_evaluation_logs, enabling the new logging path in process_detectors.
  • At line 310, emit_detector_evaluation_logs receives _get_detector_organization(detector) as its organization argument.
  • _get_detector_organization (line 276) accesses detector.linked_project.organization, which raises Project.DoesNotExist if the project was deleted.
  • For organization-scoped detectors it calls Organization.objects.get_from_cache(id=organization_id) (line 283), which raises Organization.DoesNotExist when the organization was deleted.
  • It also explicitly raises ValueError at line 282 when organization_id is missing or not an integer.
  • Because these exceptions are unhandled inside the for detector in detectors: loop, a single bad detector causes process_detectors to abort, skipping all remaining detectors and never creating issue platform payloads for them.
Also found at 1 additional location
  • src/sentry/workflow_engine/processors/detector.py:282

Identified by Warden · sentry-backend-bugs · DQ2-XJ4

@saponifi3d saponifi3d left a comment

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.

quick review / notes for the end of the day.

event_data: dict[str, Any] | None # TODO - improve this typing, for now migrating


class DetectorEvaluationOutcome(StrEnum):

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.

ERROR also seems like a valid outcome to this evaluation.


@property
def outcome(self) -> DetectorEvaluationOutcome:
if self.evaluations:

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.

if the evaluation has an error in it, we should proxy that error up to this status as well.

Comment on lines +73 to +79
def to_artifact(self) -> dict[str, object]:
return {
"detector_id": self.detector_id,
"detector_type": self.detector_type,
"project_id": self.project_id,
"outcome": self.outcome,
}

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.

this should use artifact_data and then invoke to_artifact to layer in the errors as well.


organization_id = detector.config.get("organization_id")
if not isinstance(organization_id, int):
raise ValueError("Organization-scoped detector is missing organization_id")

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.

We should raise a DetectorProcessing exception here instead of a value error, then catch it in process_detectors. the except block should then create an Error evaluation for it, and leave the message as the error message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant