Spaces:
Running
Running
| /** | |
| * Trace Overview Section Component | |
| * | |
| * Displays trace statistics, performance metrics, and cost analytics | |
| */ | |
| import React from "react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Card, CardContent } from "@/components/ui/card"; | |
| import { | |
| Tooltip, | |
| TooltipContent, | |
| TooltipTrigger, | |
| } from "@/components/ui/tooltip"; | |
| import { Activity, AlertCircle, Eye, HelpCircle } from "lucide-react"; | |
| import { Trace } from "@/types"; | |
| import { | |
| CompactMetadataCard, | |
| CompactMetadataCardAdd, | |
| type MetadataCardConfig, | |
| } from "@/components/shared/CompactMetadataCard"; | |
| interface TraceOverviewSectionProps { | |
| trace: Trace; | |
| metadataOutdated: boolean; | |
| currentMetadata: any; | |
| enhancedStats: any; | |
| enhancedStatsLoading: boolean; | |
| onOpenTraceContent: () => void; | |
| metadataCards: MetadataCardConfig[]; | |
| onOpenMetadataCardSelector: () => void; | |
| } | |
| export function TraceOverviewSection({ | |
| trace: _trace, | |
| metadataOutdated, | |
| currentMetadata, | |
| enhancedStats, | |
| enhancedStatsLoading, | |
| onOpenTraceContent, | |
| metadataCards, | |
| onOpenMetadataCardSelector, | |
| }: TraceOverviewSectionProps) { | |
| return ( | |
| <div className="h-full"> | |
| {/* Trace Overview Section */} | |
| <div className="border border-border/50 rounded-lg bg-background h-full"> | |
| <div className="p-4 pb-3"> | |
| <div className="flex items-center justify-between"> | |
| <div className="flex items-center gap-2 flex-1 min-w-0"> | |
| <Activity className="h-5 w-5 text-primary" /> | |
| <h4 className="text-lg font-semibold">Trace Overview</h4> | |
| </div> | |
| {/* View Content Button in header */} | |
| <Tooltip> | |
| <TooltipTrigger asChild> | |
| <Button | |
| onClick={onOpenTraceContent} | |
| size="sm" | |
| variant="outline" | |
| className="gap-1" | |
| > | |
| <Eye className="h-4 w-4" /> | |
| <span className="hidden sm:inline">View Content</span> | |
| </Button> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <div className="max-w-sm"> | |
| <p className="font-medium mb-1 text-primary-foreground"> | |
| View Trace Content | |
| </p> | |
| <p className="text-xs text-primary-foreground/80"> | |
| View and edit the raw trace data in a larger window. | |
| </p> | |
| </div> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| {/* Subtitle */} | |
| <p className="text-sm text-muted-foreground"> | |
| Performance metrics and trace analytics | |
| </p> | |
| </div> | |
| {/* Metadata Cards Section */} | |
| <div className="px-4 pb-3"> | |
| <div className="flex items-center gap-2 sm:gap-3 flex-wrap"> | |
| {metadataCards.map((cardConfig) => ( | |
| <CompactMetadataCard key={cardConfig.id} config={cardConfig} /> | |
| ))} | |
| <CompactMetadataCardAdd onClick={onOpenMetadataCardSelector} /> | |
| </div> | |
| </div> | |
| <div className="p-4 space-y-4 flex-1 overflow-hidden"> | |
| {/* Metadata Outdated Warning Banner */} | |
| {metadataOutdated && ( | |
| <div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4"> | |
| <div className="flex items-center justify-between"> | |
| <div className="flex items-center gap-3"> | |
| <AlertCircle className="h-5 w-5 text-yellow-600" /> | |
| <div> | |
| <h4 className="text-sm font-semibold text-yellow-800"> | |
| Trace Statistics May Be Outdated | |
| </h4> | |
| <p className="text-sm text-yellow-700"> | |
| The trace content has been modified since statistics were | |
| generated. Consider updating for accurate metrics. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| <div className="space-y-4"> | |
| {/* Trace Statistics & Performance Section */} | |
| <Card> | |
| <CardContent className="p-3"> | |
| <div className="flex items-center gap-2 mb-3"> | |
| <Activity className="h-4 w-4" /> | |
| <h4 className="text-sm font-semibold"> | |
| Trace Statistics & Performance | |
| </h4> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Key metrics and performance data from the trace analysis | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <div className="grid grid-cols-3 gap-3"> | |
| <div className="bg-muted/30 rounded-lg p-3"> | |
| <div className="flex items-center gap-1 mb-1"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide"> | |
| Tokens | |
| </p> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p>Total input and output tokens used in LLM calls</p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <p className="text-lg font-semibold"> | |
| {(() => { | |
| const tokens = | |
| enhancedStats?.tokens?.total_tokens || | |
| currentMetadata?.schema_analytics?.numerical_overview | |
| ?.token_analytics?.total_tokens; | |
| return tokens ? tokens.toLocaleString() : "N/A"; | |
| })()} | |
| </p> | |
| </div> | |
| <div className="bg-muted/30 rounded-lg p-3"> | |
| <div className="flex items-center gap-1 mb-1"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide"> | |
| Prompts | |
| </p> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Number of LLM prompt calls made during execution | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <p className="text-lg font-semibold"> | |
| {enhancedStats?.prompt_calls?.total_calls || | |
| currentMetadata?.schema_analytics?.prompt_analytics | |
| ?.prompt_calls_detected || | |
| "N/A"} | |
| </p> | |
| </div> | |
| <div className="bg-muted/30 rounded-lg p-3"> | |
| <div className="flex items-center gap-1 mb-1"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide"> | |
| Tools & Functions | |
| </p> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Number of tools, functions, or agent components used | |
| during execution | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <p className="text-lg font-semibold"> | |
| {enhancedStats?.components?.total_components || | |
| currentMetadata?.schema_analytics?.numerical_overview | |
| ?.component_stats?.total_components || | |
| "N/A"} | |
| </p> | |
| </div> | |
| <div className="bg-muted/30 rounded-lg p-3"> | |
| <div className="flex items-center gap-1 mb-1"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide"> | |
| Success Rate | |
| </p> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p>Percentage of successful component executions</p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <p className="text-lg font-semibold"> | |
| {(() => { | |
| const successRate = | |
| enhancedStats?.components?.success_rate || | |
| currentMetadata?.schema_analytics?.numerical_overview | |
| ?.component_stats?.success_rate; | |
| return successRate !== undefined && successRate !== null | |
| ? `${successRate.toFixed(1)}%` | |
| : "N/A"; | |
| })()} | |
| </p> | |
| </div> | |
| <div className="bg-muted/30 rounded-lg p-3"> | |
| <div className="flex items-center gap-1 mb-1"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide"> | |
| Execution Time | |
| </p> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p>Total execution time for the trace</p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <p className="text-lg font-semibold"> | |
| {(() => { | |
| const totalTimeMs = | |
| enhancedStats?.performance?.total_execution_time_ms || | |
| currentMetadata?.schema_analytics?.numerical_overview | |
| ?.timing_analytics?.total_execution_time_ms; | |
| if (totalTimeMs && totalTimeMs > 0) { | |
| if (totalTimeMs >= 1000) { | |
| return `${(totalTimeMs / 1000).toFixed(1)}s`; | |
| } else { | |
| return `${totalTimeMs}ms`; | |
| } | |
| } | |
| return "N/A"; | |
| })()} | |
| </p> | |
| </div> | |
| <div className="bg-muted/30 rounded-lg p-3"> | |
| <div className="flex items-center gap-1 mb-1"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide"> | |
| Call Stack Depth | |
| </p> | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Maximum depth of nested function calls (how many | |
| levels deep the execution goes) | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </div> | |
| <p className="text-lg font-semibold"> | |
| {enhancedStats?.components?.max_depth || | |
| currentMetadata?.schema_analytics?.numerical_overview | |
| ?.component_stats?.max_depth || | |
| "N/A"} | |
| </p> | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {/* Cost & Token Analytics Section */} | |
| {(enhancedStats?.cost || enhancedStats?.tokens) && ( | |
| <Card> | |
| <CardContent className="p-3"> | |
| <h4 className="text-sm font-semibold mb-3 flex items-center gap-2"> | |
| <Activity className="h-4 w-4" /> | |
| Cost & Token Analytics | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <HelpCircle className="h-3 w-3 text-muted-foreground" /> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Cost breakdown and token usage analytics for LLM calls | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| </h4> | |
| {enhancedStats?.cost && ( | |
| <div className="bg-gradient-to-r from-green-50 to-emerald-50 border border-green-200 rounded-lg p-3 mb-3"> | |
| <div className="flex items-start justify-between"> | |
| {/* Left side: Model and Cost */} | |
| <div className="flex-1"> | |
| <p className="text-lg font-bold text-green-800 mb-1"> | |
| {enhancedStats?.cost?.model_used || "gpt-5-mini"} | |
| </p> | |
| <p className="text-base font-semibold text-green-600"> | |
| Avg:{" "} | |
| {enhancedStatsLoading | |
| ? "Loading..." | |
| : enhancedStats?.cost?.avg_cost_per_call_usd | |
| ? `$${enhancedStats.cost.avg_cost_per_call_usd.toFixed( | |
| 6 | |
| )}/call` | |
| : "$0.00/call"} | |
| </p> | |
| </div> | |
| {/* Right side: Model Information */} | |
| {enhancedStats?.cost?.model_metadata && ( | |
| <div className="ml-4 text-xs text-green-700 space-y-1"> | |
| {enhancedStats.cost.model_metadata | |
| .litellm_provider && ( | |
| <div className="flex items-center gap-1"> | |
| <span className="font-medium">Provider:</span> | |
| <span className="capitalize"> | |
| { | |
| enhancedStats.cost.model_metadata | |
| .litellm_provider | |
| } | |
| </span> | |
| </div> | |
| )} | |
| {enhancedStats.cost.model_metadata | |
| .max_input_tokens && ( | |
| <div className="flex items-center gap-1"> | |
| <span className="font-medium">Max Input:</span> | |
| <span> | |
| {enhancedStats.cost.model_metadata.max_input_tokens.toLocaleString()}{" "} | |
| tokens | |
| </span> | |
| </div> | |
| )} | |
| {enhancedStats.cost.model_metadata | |
| .max_output_tokens && ( | |
| <div className="flex items-center gap-1"> | |
| <span className="font-medium">Max Output:</span> | |
| <span> | |
| {enhancedStats.cost.model_metadata.max_output_tokens.toLocaleString()}{" "} | |
| tokens | |
| </span> | |
| </div> | |
| )} | |
| {/* Capabilities */} | |
| <div className="flex flex-wrap gap-1 mt-2"> | |
| {enhancedStats.cost.model_metadata | |
| .supports_function_calling && ( | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <span className="px-1.5 py-0.5 bg-green-200 text-green-800 rounded text-xs cursor-help"> | |
| Functions | |
| </span> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Model supports function calling - can | |
| execute predefined functions and tools | |
| during conversations | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| )} | |
| {enhancedStats.cost.model_metadata | |
| .supports_vision && ( | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <span className="px-1.5 py-0.5 bg-blue-200 text-blue-800 rounded text-xs cursor-help"> | |
| Vision | |
| </span> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Model supports vision capabilities - can | |
| analyze and understand images, charts, and | |
| visual content | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| )} | |
| {enhancedStats.cost.model_metadata | |
| .supports_response_schema && ( | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <span className="px-1.5 py-0.5 bg-purple-200 text-purple-800 rounded text-xs cursor-help"> | |
| Schema | |
| </span> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Model supports structured output schemas - | |
| can return responses in predefined JSON | |
| formats | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| )} | |
| {enhancedStats.cost.model_metadata | |
| .supports_prompt_caching && ( | |
| <Tooltip> | |
| <TooltipTrigger> | |
| <span className="px-1.5 py-0.5 bg-orange-200 text-orange-800 rounded text-xs cursor-help"> | |
| Caching | |
| </span> | |
| </TooltipTrigger> | |
| <TooltipContent> | |
| <p> | |
| Model supports prompt caching - can cache | |
| common prompts to reduce latency and costs | |
| </p> | |
| </TooltipContent> | |
| </Tooltip> | |
| )} | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| )} | |
| <div className="grid grid-cols-3 gap-2"> | |
| {/* Total Tokens & Cost */} | |
| <div className="bg-muted/30 rounded-lg p-2.5"> | |
| <div className="text-center"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide mb-1"> | |
| Total Tokens | |
| </p> | |
| <p className="text-lg font-bold mb-1"> | |
| {enhancedStatsLoading | |
| ? "..." | |
| : enhancedStats?.tokens?.total_tokens?.toLocaleString() || | |
| "N/A"} | |
| </p> | |
| {enhancedStats?.cost && ( | |
| <div className="mt-2 pt-2 border-t border-muted-foreground/20"> | |
| <p className="text-sm font-bold text-green-700"> | |
| {enhancedStatsLoading | |
| ? "..." | |
| : enhancedStats?.cost?.total_cost_usd | |
| ? `$${enhancedStats.cost.total_cost_usd.toFixed( | |
| 6 | |
| )}` | |
| : "$0.00"} | |
| </p> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| {/* Input Tokens & Cost */} | |
| <div className="bg-muted/30 rounded-lg p-2.5"> | |
| <div className="text-center"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide mb-1"> | |
| Input Tokens | |
| </p> | |
| <p className="text-lg font-bold mb-1"> | |
| {enhancedStatsLoading | |
| ? "..." | |
| : enhancedStats?.tokens?.total_prompt_tokens?.toLocaleString() || | |
| "N/A"} | |
| </p> | |
| {enhancedStats?.cost && ( | |
| <div className="mt-2 pt-2 border-t border-muted-foreground/20"> | |
| <p className="text-sm font-bold text-blue-700"> | |
| {enhancedStatsLoading | |
| ? "..." | |
| : enhancedStats?.cost?.input_cost_usd | |
| ? `$${enhancedStats.cost.input_cost_usd.toFixed( | |
| 6 | |
| )}` | |
| : "$0.00"} | |
| </p> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| {/* Output Tokens & Cost */} | |
| <div className="bg-muted/30 rounded-lg p-2.5"> | |
| <div className="text-center"> | |
| <p className="text-xs text-muted-foreground uppercase tracking-wide mb-1"> | |
| Output Tokens | |
| </p> | |
| <p className="text-lg font-bold mb-1"> | |
| {enhancedStatsLoading | |
| ? "..." | |
| : enhancedStats?.tokens?.total_completion_tokens?.toLocaleString() || | |
| "N/A"} | |
| </p> | |
| {enhancedStats?.cost && ( | |
| <div className="mt-2 pt-2 border-t border-muted-foreground/20"> | |
| <p className="text-sm font-bold text-purple-700"> | |
| {enhancedStatsLoading | |
| ? "..." | |
| : enhancedStats?.cost?.output_cost_usd | |
| ? `$${enhancedStats.cost.output_cost_usd.toFixed( | |
| 6 | |
| )}` | |
| : "$0.00"} | |
| </p> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } | |