Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ interface TraceDrawerContentProps {
}

const SessionDrawerContent = ({onClose, onToggleWidth, isExpanded}: TraceDrawerContentProps) => {
const [selected, setSelected] = useState<string>("")
// Default-select the "Session" root node so the tree opens with a selection
// instead of nothing highlighted. The root node's key is always "root", and
// selecting it is a no-op in handleSelect (it early-returns for "root").
const [selected, setSelected] = useState<string>("root")
const {isLoading} = useSessionDrawer()
if (isLoading) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {Tag} from "antd"
export const SessionIdCell = ({sessionId}: {sessionId: string}) => {
return (
<TooltipWithCopyAction copyText={sessionId || ""} title="Copy session id">
<Tag className="font-mono bg-[var(--ag-c-0517290F)] w-fit truncate" bordered={false}>
<Tag
className="font-mono bg-[var(--ag-c-0517290F)] max-w-full truncate inline-block align-middle"
bordered={false}
>
# {sessionId}
</Tag>
</TooltipWithCopyAction>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {useCallback, useEffect, useMemo, useState} from "react"

import {InfiniteVirtualTableFeatureShell} from "@agenta/ui/table"
import type {TableFeaturePagination, TableScopeConfig} from "@agenta/ui/table"
import {useAtomValue, useSetAtom} from "jotai"
import {useAtomValue, useSetAtom, useStore} from "jotai"
import dynamic from "next/dynamic"

import {SessionDrawer} from "@/oss/components/SharedDrawers/SessionDrawer"
Expand Down Expand Up @@ -49,6 +49,14 @@ const SessionsTable: React.FC = () => {
resetSessionPages,
} = useSessions()

// The per-session cells (Traces count, First input, metrics, …) read their
// data from page-level atoms keyed by session id (e.g. `sessionsSpansAtom`).
// Without this, the table mounts its rows inside an isolated Jotai store
// (`useIsolatedStore` when no `store` is passed), where those atoms are empty
// — so every cell renders 0/"-" even though the data is loaded in the page
// store. Sharing the page store lets the cells resolve the real data.
const store = useStore()

const isNewUser = useAtomValue(isNewUserAtom)
const onboardingStorageUserId = useAtomValue(onboardingStorageUserIdAtom)
const openDrawer = useSetAtom(openSessionDrawerWithUrlAtom)
Expand Down Expand Up @@ -111,7 +119,7 @@ const SessionsTable: React.FC = () => {
const isEmptyState = sessionIds.length === 0 && !isLoading

return (
<div className="flex flex-col gap-6">
<div className="flex flex-col h-full gap-2 min-h-0">
<ObservabilityHeader
columns={columns}
componentType="sessions"
Expand All @@ -128,11 +136,11 @@ const SessionsTable: React.FC = () => {
<EmptySessions showOnboarding={showOnboarding} />
) : (
<InfiniteVirtualTableFeatureShell<SessionRow>
store={store}
tableScope={tableScope}
columns={columns}
rowKey="session_id"
pagination={pagination}
autoHeight={false}
resizableColumns
enableExport={false}
useSettingsDropdown={false}
Expand Down
13 changes: 8 additions & 5 deletions web/oss/src/state/newObservability/atoms/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,15 +509,18 @@ export const sessionTraceCountAtomFamily = atomFamily((sessionId: string) =>
}),
)

// Sorted traces are required for time-based metrics (Start/End/Duration)
// We memoize this to avoid re-sorting for every time-related cell
// Sorted traces are required for time-based metrics (Start/End/Duration) and for
// the First input / Last output cells. Sort by `start_time` (falling back to
// `created_at`) to match the Session drawer's tree ordering
// (SessionTree sorts its "Trace N" nodes by start_time). Sorting by a different
// key here made the table's first/last trace diverge from the drawer's.
const sessionSortedTracesAtomFamily = atomFamily((sessionId: string) =>
atom((get) => {
const traces = get(sessionTracesAtomFamily(sessionId))
if (!traces.length) return []
return [...traces].sort(
(a, b) => new Date(a.created_at || 0).getTime() - new Date(b.created_at || 0).getTime(),
)
const sortKey = (t: (typeof traces)[number]) =>
new Date(t.start_time || t.created_at || 0).getTime()
return [...traces].sort((a, b) => sortKey(a) - sortKey(b))
Comment on lines +521 to +523

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Compute session end from max end_time

When a session contains overlapping traces, this start-time ordering is also reused by sessionTimeRangeAtomFamily to take sorted[sorted.length - 1].end_time, so the latest-starting trace is treated as the session end. If an earlier trace runs longer than a later trace, the Sessions table now shows an End time and Duration that are too early; compute the range with independent min start and max end values instead of relying on this order.

Useful? React with 👍 / 👎.

}),
)

Expand Down
Loading