export default function History()

in spring-ai-alibaba-studio/ui/src/pages/traces/index.tsx [46:215]


export default function History() {
  const [data, setData] = useState<TraceInfo[]>([]);
  const [openTraceDetail, setOpenTraceDetail] = useState(false);
  const [traceDetail, setTraceDetail] = useState({} as any);
  const columns: TableProps<TraceInfo>['columns'] = [
    {
      title: 'id',
      dataIndex: 'id',
      key: 'id',
      fixed: 'left',
      width: 100,
      ellipsis: true,
      render: (text, record) => (
        <div style={{ width: 100 }}>
          <a
            onClick={() => {
              setTraceDetail(record);
              setOpenTraceDetail(true);
            }}
            style={{
              whiteSpace: 'nowrap',
              overflow: 'hidden',
              textOverflow: 'ellipsis',
            }}
          >
            {text}
          </a>
          ...
        </div>
      ),
    },
    {
      title: 'timestamp',
      dataIndex: 'timestamp',
      key: 'timestamp',
      ellipsis: true,
      // sorter: (a, b) => a.timestamp - b.timestamp,
      width: 100,
    },
    {
      title: 'name',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: 'model',
      dataIndex: 'model',
      filters: [
        {
          text: 'gpt系列模型',
          value: 'gpt',
        },
        {
          text: 'Claude系列',
          value: 'claude',
        },
      ],
      key: 'model',
      onFilter: (value, record) => record.model.startsWith(value as string),
    },
    {
      title: 'latency',
      key: 'latencyMilliseconds',
      dataIndex: 'latencyMilliseconds',
      render: (_, { latencyMilliseconds }) => (
        <div>{latencyMilliseconds} ms</div>
      ),
    },
    {
      title: 'usageDetails',
      dataIndex: 'usageDetails',
      key: 'usageDetails',
      render: (_, { usageDetails }) => (
        <span>{`${usageDetails?.input} → ${usageDetails?.output} (∑ ${usageDetails?.total})`}</span>
      ),
    },
    {
      title: 'Total Cost',
      dataIndex: 'costDetails',
      key: 'costDetails',
      render: (_, { costDetails }) => <span>{`${costDetails?.total}$`}</span>,
    },
    {
      title: 'tags',
      key: 'tags',
      dataIndex: 'tags',
      render: (_, { tags }) => (
        <>
          {tags.map((tag) => {
            let color = tag.length > 5 ? 'geekblue' : 'green';
            if (tag === 'loser') {
              color = 'volcano';
            }
            return (
              <Tag color={color} key={tag}>
                {tag.toUpperCase()}
              </Tag>
            );
          })}
        </>
      ),
    },
    {
      title: 'calculatedTotalCost',
      key: 'calculatedTotalCost',
      dataIndex: 'calculatedTotalCost',
    },
    {
      title: 'calculatedInputCost',
      key: 'calculatedInputCost',
      dataIndex: 'calculatedInputCost',
    },
    {
      title: 'calculatedOutputCost',
      key: 'calculatedOutputCost',
      dataIndex: 'calculatedOutputCost',
    },
    {
      title: 'Action',
      key: 'operation',
      fixed: 'right',
      width: 100,
      render: () => <a>查看详情</a>,
    },
  ];

  const { styles } = useStyle();
  const handleGetTraceData = async () => {
    const traceList = await traceClient.getTraceDetailClient();
    console.log(traceList);
    setData(
      traceList
        .map((trace) => {
          const traceInfo = convertToTraceInfo(trace);
          console.log(traceInfo);
          return traceInfo;
        })
        .filter((trace) => trace !== null),
    );
    // const temp = tableList.result.data.json.traces;
    // temp.forEach((trace) => {
    //   // @ts-ignore
    //   trace.model = Math.random() > 0.5 ? 'gpt-4o' : 'claude-3-5-sonnet';
    // });
    // @ts-ignore
    // setData(traceDetailList.map((trace) => { const traceInfo = convertToTraceInfo(trace); console.log(traceInfo); return traceInfo; }).filter(trace => trace !== null));
  };

  useEffect(() => {
    handleGetTraceData();
  }, []);
  return (
    <div>
      <Card title={'Traces'}>
        <Table
          className={styles.customTable}
          columns={columns}
          dataSource={data}
          scroll={{ x: 'max-content' }}
          rowKey={(recode) => recode.id}
        />
        <TraceDetailComp
          record={traceDetail}
          open={openTraceDetail}
          setOpen={setOpenTraceDetail}
        />
      </Card>
    </div>
  );
}