Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
ProjectPageHeader.tsx7.23 kB
import { ReactNode, startTransition, useEffect } from "react"; import { Focusable } from "react-aria"; import { graphql, useRefetchableFragment } from "react-relay"; import { css } from "@emotion/react"; import { ErrorBoundary, Flex, RichTooltip, Text, TextErrorBoundaryFallback, TooltipArrow, TooltipTrigger, View, } from "@phoenix/components"; import { useCategoryChartColors } from "@phoenix/components/chart/colors"; import { RichTokenBreakdown } from "@phoenix/components/RichTokenCostBreakdown"; import { LatencyText } from "@phoenix/components/trace/LatencyText"; import { useStreamState } from "@phoenix/contexts/StreamStateContext"; import { costFormatter, intFormatter } from "@phoenix/utils/numberFormatUtils"; import { ProjectPageHeader_stats$key } from "./__generated__/ProjectPageHeader_stats.graphql"; import { ProjectPageHeaderQuery } from "./__generated__/ProjectPageHeaderQuery.graphql"; import { AnnotationSummary } from "./AnnotationSummary"; import { DocumentEvaluationSummary } from "./DocumentEvaluationSummary"; export function ProjectPageHeader(props: { project: ProjectPageHeader_stats$key; /** * the extra component displayed on the right side of the header */ extra: ReactNode; }) { const { extra } = props; const { fetchKey } = useStreamState(); const [data, refetch] = useRefetchableFragment< ProjectPageHeaderQuery, ProjectPageHeader_stats$key >( graphql` fragment ProjectPageHeader_stats on Project @refetchable(queryName: "ProjectPageHeaderQuery") { traceCount(timeRange: $timeRange) costSummary(timeRange: $timeRange) { total { cost } prompt { cost } completion { cost } } latencyMsP50: latencyMsQuantile( probability: 0.50 timeRange: $timeRange ) latencyMsP99: latencyMsQuantile( probability: 0.99 timeRange: $timeRange ) spanAnnotationNames documentEvaluationNames } `, props.project ); // Refetch the count of traces if the fetchKey changes useEffect(() => { startTransition(() => { refetch({}, { fetchPolicy: "store-and-network" }); }); }, [fetchKey, refetch]); const latencyMsP50 = data?.latencyMsP50; const latencyMsP99 = data?.latencyMsP99; const spanAnnotationNames = data?.spanAnnotationNames?.filter( (name) => name !== "note" ); const documentEvaluationNames = data?.documentEvaluationNames; const colors = useCategoryChartColors(); return ( <View paddingStart="size-200" paddingEnd="size-200" paddingTop="size-200" paddingBottom="size-50" flex="none" > <Flex direction="row" justifyContent="space-between" alignItems="center"> <div css={css` overflow-x: auto; overflow-y: hidden; flex: 1 1 auto; background-image: linear-gradient( to right, var(--ac-global-color-grey-75), var(--ac-global-color-grey-75) ), linear-gradient( to right, var(--ac-global-color-grey-75), var(--ac-global-color-grey-75) ), linear-gradient( to right, rgba(var(--ac-global-color-grey-300-rgb), 0.9), rgba(var(--ac-global-color-grey-300-rgb), 0) ), linear-gradient( to left, rgba(var(--ac-global-color-grey-300-rgb), 0.9), rgba(var(--ac-global-color-grey-300-rgb), 0) ); background-repeat: no-repeat; background-size: 32px 100%, 32px 100%, 32px 100%, 32px 100%; background-position: left center, right center, left center, right center; background-attachment: local, local, scroll, scroll; `} > <Flex direction="row" gap="size-400" alignItems="center"> <Flex direction="column" flex="none"> <Text elementType="h3" size="S" color="text-700"> Total Traces </Text> <Text size="L" fontFamily="mono"> {intFormatter(data?.traceCount)} </Text> </Flex> <Flex direction="column" flex="none"> <Text elementType="h3" size="S" color="text-700"> Total Cost </Text> <TooltipTrigger delay={0}> <Focusable> <Text size="L" role="button" fontFamily="mono"> {costFormatter(data?.costSummary?.total?.cost ?? 0)} </Text> </Focusable> <RichTooltip placement="bottom"> <TooltipArrow /> <View width="size-3600"> <RichTokenBreakdown valueLabel="cost" totalValue={data?.costSummary?.total?.cost ?? 0} formatter={costFormatter} segments={[ { name: "Prompt", value: data?.costSummary?.prompt?.cost ?? 0, color: colors.category1, }, { name: "Completion", value: data?.costSummary?.completion?.cost ?? 0, color: colors.category2, }, ]} /> </View> </RichTooltip> </TooltipTrigger> </Flex> <Flex direction="column" flex="none"> <Text elementType="h3" size="S" color="text-700"> Latency P50 </Text> {latencyMsP50 != null ? ( <LatencyText latencyMs={latencyMsP50} size="L" /> ) : ( <Text size="L">--</Text> )} </Flex> <Flex direction="column" flex="none"> <Text elementType="h3" size="S" color="text-700"> Latency P99 </Text> {latencyMsP99 != null ? ( <LatencyText latencyMs={latencyMsP99} size="L" /> ) : ( <Text size="L">--</Text> )} </Flex> {spanAnnotationNames.map((name) => ( <ErrorBoundary key={name} fallback={TextErrorBoundaryFallback}> <AnnotationSummary key={name} annotationName={name} /> </ErrorBoundary> ))} {documentEvaluationNames.map((name) => ( <DocumentEvaluationSummary key={`document-${name}`} evaluationName={name} /> ))} </Flex> </div> <View flex="none" paddingStart="size-100"> {extra} </View> </Flex> </View> ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Arize-ai/phoenix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server