Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(llm-o): connect Session replay to LLM Observability #29224

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

k11kirky
Copy link
Contributor

Problem

Not easy to connect LLM events and replys

Changes

  • Enhance UI for LLM events in session reply and add link to LLM trace.
  • If session id exisits in LLM event add link in trace back to replay
Screenshot 2025-02-25 at 2 35 26 PM Screenshot 2025-02-25 at 2 35 49 PM

@k11kirky k11kirky requested a review from pauldambra February 25, 2025 22:37
@k11kirky k11kirky changed the title itemEvent feat(llm-o): connect Session replay to LLM Observability Feb 25, 2025
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

PR Summary

Enhanced UI for LLM events in session recordings with bidirectional linking between session replays and LLM traces, providing better context for AI-related activities.

  • Added AIEventItems.tsx with AIEventExpanded and AIAIEventSummary components to display AI event details and error states
  • Modified ItemEvent.tsx to support AI events ($ai_generation, $ai_span, $ai_trace) with a dedicated "Conversation" tab and "View LLM Trace" button
  • Added hasSessionID and getSessionID utility functions in utils.ts to enable navigation between LLM traces and session recordings
  • Updated cost definitions for new AI models including 'claude-3.7-sonnet:thinking', 'deepseek-chat', and 'gemini-2.0-flash-lite-001'

7 file(s) reviewed, 5 comment(s)
Edit PR Review Bot Settings | Greptile

Comment on lines +9 to +15
let input = event.properties.$ai_input_state
let output = event.properties.$ai_output_state ?? event.properties.$ai_error
let raisedError = event.properties.$ai_is_error
if (event.event === '$ai_generation') {
input = event.properties.$ai_input
output = event.properties.$ai_output_choices ?? event.properties.$ai_output
raisedError = event.properties.$ai_is_error
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Redundant reassignment of raisedError on line 15 since it's already set on line 11 with the same value

Suggested change
let input = event.properties.$ai_input_state
let output = event.properties.$ai_output_state ?? event.properties.$ai_error
let raisedError = event.properties.$ai_is_error
if (event.event === '$ai_generation') {
input = event.properties.$ai_input
output = event.properties.$ai_output_choices ?? event.properties.$ai_output
raisedError = event.properties.$ai_is_error
let input = event.properties.$ai_input_state
let output = event.properties.$ai_output_state ?? event.properties.$ai_error
let raisedError = event.properties.$ai_is_error
if (event.event === '$ai_generation') {
input = event.properties.$ai_input
output = event.properties.$ai_output_choices ?? event.properties.$ai_output

@@ -92,9 +97,20 @@ export function ItemEvent({ item }: ItemEventProps): JSX.Element {
}

export function ItemEventDetail({ item }: ItemEventProps): JSX.Element {
// // Check if this is an LLM-related event
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: There's an extra comment slash here that should be removed

Suggested change
// // Check if this is an LLM-related event
// Check if this is an LLM-related event

Comment on lines +391 to +394
<Link to={urls.replay(undefined, undefined, getSessionID(event) ?? '')}>
<IconOpenInNew />
View session recording
</Link>
Copy link
Contributor

Choose a reason for hiding this comment

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

style: The icon and text should be wrapped in a flex container with proper alignment and spacing for better visual consistency with other links in the UI.

Copy link
Member

Choose a reason for hiding this comment

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

Could be a and would get pretty much the same styling but with gap between icon and text

Comment on lines +53 to +54
}
return '$session_id' in event
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Redundant check for 'properties' in event since isLLMTraceEvent already confirms this property exists

Suggested change
}
return '$session_id' in event
return typeof event.properties.$session_id === 'string'
return '$session_id' in event

Copy link
Contributor

github-actions bot commented Feb 25, 2025

Size Change: +2.48 kB (+0.03%)

Total Size: 9.72 MB

Filename Size Change
frontend/dist/toolbar.js 9.72 MB +2.48 kB (+0.03%)

compressed-size-action

k11kirky and others added 2 commits February 25, 2025 22:57
…ents/AIEventItems.tsx

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@@ -145,6 +147,14 @@ export function EventDetails({ event, tableProps }: EventDetailsProps): JSX.Elem
label: 'Conversation',
content: (
<div className="mx-3 -mt-2 mb-2 space-y-2">
{event.properties.$session_id ? (
<div className="flex flex-row items-center gap-2">
<Link to={urls.replay(undefined, undefined, event.properties.$session_id)}>
Copy link
Member

Choose a reason for hiding this comment

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

commented elsewhere this could be a lemon button

@@ -145,6 +147,14 @@ export function EventDetails({ event, tableProps }: EventDetailsProps): JSX.Elem
label: 'Conversation',
content: (
<div className="mx-3 -mt-2 mb-2 space-y-2">
{event.properties.$session_id ? (
Copy link
Member

Choose a reason for hiding this comment

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

if you know it's a web event you can gate on recording being active

in error tracking

issueProperties['$session_id'] && issueProperties['$recording_status'] === 'active'

but that's not essential - we just can't guarantee that the presence of a session id means there will be a recording.

Comment on lines +101 to +102
const isAIEvent =
item.data.event === '$ai_generation' || item.data.event === '$ai_span' || item.data.event === '$ai_trace'
Copy link
Member

Choose a reason for hiding this comment

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

nit-picking we could put this in taxonomy.ts but am only imagineering

) : item.data.event === '$ai_generation' ||
item.data.event === '$ai_span' ||
item.data.event === '$ai_trace' ? (
<AIEventSummary event={item.data} />
Copy link
Member

Choose a reason for hiding this comment

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

ah, i think you need eager loading of the properties for the error flag in here to work...

here we subscribe to web vitals events and preload their event properties

webVitalsEvents: (value: RecordingEventType[]) => {
you can copy that

we delay loading properties in the inspector list until expanded otherwise

Copy link
Member

@pauldambra pauldambra left a comment

Choose a reason for hiding this comment

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

a note on preloading but that could even be a follow-up

this is great!

Comment on lines +150 to +157
{event.properties.$session_id ? (
<div className="flex flex-row items-center gap-2">
<Link to={urls.replay(undefined, undefined, event.properties.$session_id)}>
<IconOpenInNew />
View session recording
</Link>
</div>
) : null}
Copy link
Contributor

Choose a reason for hiding this comment

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

What Paul is suggesting would basically look like this:

Suggested change
{event.properties.$session_id ? (
<div className="flex flex-row items-center gap-2">
<Link to={urls.replay(undefined, undefined, event.properties.$session_id)}>
<IconOpenInNew />
View session recording
</Link>
</div>
) : null}
{mightHaveRecording(event.properties) && (
<ViewRecordingButton sessionId={event.properties.$session_id} />
)}

Comment on lines +389 to +396
{hasSessionID(event) && (
<div className="flex flex-row items-center gap-2">
<Link to={urls.replay(undefined, undefined, getSessionID(event) ?? '')}>
<IconOpenInNew />
View session recording
</Link>
</div>
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as my comment above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants