File size: 3,629 Bytes
c40c75a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import React, { useState } from 'react';
import { LogEntry } from './columns';
import { DataTable } from './table';
import { columns } from './columns';
import { Card, Title, Text, Metric, AreaChart } from '@tremor/react';
import { RequestViewer } from './index';

interface SessionViewProps {
  sessionId: string;
  logs: LogEntry[];
  onBack: () => void;
}

export const SessionView: React.FC<SessionViewProps> = ({ sessionId, logs, onBack }) => {
  // Track which log row is expanded
  const [expandedRequestId, setExpandedRequestId] = useState<string | null>(null);
  // Calculate session metrics
  const totalCost = logs.reduce((sum, log) => sum + (log.spend || 0), 0);
  const totalTokens = logs.reduce((sum, log) => sum + (log.total_tokens || 0), 0);
  const startTime = logs.length > 0 ? new Date(logs[0].startTime) : new Date();
  const endTime = logs.length > 0 ? new Date(logs[logs.length - 1].endTime) : new Date();
  const durationMs = endTime.getTime() - startTime.getTime();
  const durationSec = (durationMs / 1000).toFixed(2);
  
  // Prepare data for the timeline chart
  const timelineData = logs.map(log => ({
    time: new Date(log.startTime).toISOString(),
    tokens: log.total_tokens || 0,
    cost: log.spend || 0,
  }));

  return (
    <div className="space-y-6">
      {/* Header with back button */}
      <div className="mb-8">
        <div className="flex items-center space-x-4">
          <button
            onClick={onBack}
            className="flex items-center text-gray-600 hover:text-gray-900 transition-colors"
          >
            <svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
            </svg>
            Back to All Logs
          </button>
        </div>
        <div className="mt-4">
          <h1 className="text-2xl font-semibold text-gray-900">Session Details</h1>
          <div className="space-y-2">
            <p className="text-sm text-gray-500 font-mono">{sessionId}</p>
            <a 
              href="https://docs.litellm.ai/docs/proxy/ui_logs_sessions" 
              target="_blank" 
              rel="noopener noreferrer" 
              className="text-sm text-blue-600 hover:text-blue-800 flex items-center gap-1"
            >
              Get started with session management here
              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
              </svg>
            </a>
          </div>
        </div>
      </div>

      {/* Session Overview Cards */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        <Card>
          <Text>Total Requests</Text>
          <Metric>{logs.length}</Metric>
        </Card>
        <Card>
          <Text>Total Cost</Text>
          <Metric>${totalCost.toFixed(4)}</Metric>
        </Card>
        <Card>
          <Text>Total Tokens</Text>
          <Metric>{totalTokens}</Metric>
        </Card>
      </div>
      {/* Request Timeline */}
          <Title>Session Logs</Title>
          <div className="mt-4">
            <DataTable
              columns={columns}
              data={logs}
              renderSubComponent={RequestViewer}
              getRowCanExpand={() => true}
              expandedRequestId={expandedRequestId}
              onRowExpand={setExpandedRequestId}
            />
          </div>
    </div>
  );
};