chore(event formatter): add event formatter to sentry backend#119250
chore(event formatter): add event formatter to sentry backend#119250shayna-ch wants to merge 19 commits into
Conversation
|
bugbot run |
|
bugbot run |
|
bugbot run |
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7328e65. Configure here.
| ) | ||
|
|
||
|
|
||
| def _breadcrumb(v: Mapping[str, Any]) -> Breadcrumb: |
There was a problem hiding this comment.
do we really need so many helpers? a lot of these helpers seem to be parsing unknown Anys, which is helpful, but all the types are fully optional anyways, so it doesn't provide much information.
There was a problem hiding this comment.
true, removed the ones that didn't have extra logic and moved to aliases
| ) | ||
|
|
||
| # Enables the shared issue/event formatter module (markdown/xml output for LLMs). | ||
| register( |
There was a problem hiding this comment.
just so i can test locally while I implement the surfaces. eventually I will prob move it to a feature flag
| ] | ||
|
|
||
|
|
||
| def format_issue( |
There was a problem hiding this comment.
i'm having trouble reviewing this since it's hard to tell how this is going to be used (e.g. are we really taking in a fully unknown Mapping[str, Any] every time we use this?). do you have an example of where we'd be calling format_issue?
| def field(self, key: str, value: str) -> str: | ||
| tag = slug(key) | ||
| return f"<{tag}>{value}</{tag}>" | ||
|
|
||
| def code_block(self, text: str) -> str: | ||
| return f"<code>{text}</code>" |
There was a problem hiding this comment.
Bug: The XmlFormatter does not escape special characters like < and > in event data, producing invalid XML for stack traces with generics.
Severity: HIGH
Suggested Fix
Apply an XML escaping function, such as xml.sax.saxutils.escape, to all dynamic content before it is embedded within XML tags in the XmlFormatter's field(), code_block(), and block() methods.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/issues/formatting/formatter.py#L67-L72
Potential issue: The `XmlFormatter` class does not escape special XML characters like
`<`, `>`, and `&`. When formatting event data that contains these characters, such as
stack traces from languages like Java or C++ that use generic types (e.g., `Map<String,
List<Integer>>`), the formatter produces syntactically invalid XML. This will cause
parsing errors for downstream consumers that expect valid XML, such as the intended LLM
integration. The issue affects the `field()`, `code_block()`, and `block()` methods.
| package: str | None = None | ||
| line_no: int | None = Field(None, alias="lineNo") | ||
| col_no: int | None = Field(None, alias="colNo") | ||
| context: list[tuple[int, str | None]] = [] # [(line_no, source_line), ...] |
There was a problem hiding this comment.
Bug: The Frame.context field is not optional, but serialized events can contain "context": null. This will cause a ValidationError and crash the issue formatting process.
Severity: HIGH
Suggested Fix
Modify the Frame.context field definition to allow None. Change context: list[tuple[int, str | None]] = [] to context: list[tuple[int, str | None]] | None = None. This will make Pydantic correctly handle null values for this field during deserialization.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/sentry/issues/formatting/models.py#L27
Potential issue: The `Frame.context` field in `src/sentry/issues/formatting/models.py`
is defined as a non-optional list. However, Sentry events can contain frames where the
`context` is `null`, especially for code without available source context (e.g.,
minified JavaScript or native code). When `format_issue()` attempts to parse such an
event, Pydantic will raise a `ValidationError` because `null` is not a valid list. Since
there is no error handling around the model parsing in `event_response_to_model()`, this
exception will propagate uncaught, causing the entire issue formatting pipeline to crash
for that event.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b4b49a0. Configure here.

Adds event formatter module to sentry backend.
how it works: serialized event → adapter → model → formatter → text
adapter.pyformatter.pylimits.pymodels.pysections.pyExample Formatted Outputs
Markdown:
XML:
resolves ID-1699