Skip to content

Commit

Permalink
[OPIK-624] [FE] Add duration chart to Metrics tab (#929)
Browse files Browse the repository at this point in the history
  • Loading branch information
andriidudar authored Dec 19, 2024
1 parent 17a8bbf commit 179d90d
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const ExperimentChartContainer: React.FC<ExperimentChartContainerProps> = ({
width: tickWidth,
ticks,
domain,
tickFormatter,
yTickFormatter,
interval: tickInterval,
} = useChartTickDefaultConfig(values, {
tickPrecision: 2,
Expand Down Expand Up @@ -120,7 +120,7 @@ const ExperimentChartContainer: React.FC<ExperimentChartContainerProps> = ({
<ChartContainer config={config} className="h-32 w-full">
<LineChart
data={chartData.data}
margin={{ top: 5, bottom: 5, left: 0, right: 0 }}
margin={{ top: 5, bottom: 5, left: 5, right: 0 }}
>
<CartesianGrid vertical={false} />
<YAxis
Expand All @@ -130,7 +130,7 @@ const ExperimentChartContainer: React.FC<ExperimentChartContainerProps> = ({
tick={DEFAULT_CHART_TICK}
interval={tickInterval}
ticks={ticks}
tickFormatter={tickFormatter}
tickFormatter={yTickFormatter}
domain={domain}
/>
<ChartTooltip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ import ChartTooltipContent, {
ChartTooltipRenderValueArguments,
} from "@/components/shared/ChartTooltipContent/ChartTooltipContent";
import { formatDate } from "@/lib/date";
import { formatCost } from "@/lib/money";
import { ValueType } from "recharts/types/component/DefaultTooltipContent";
import useChartTickDefaultConfig from "@/hooks/charts/useChartTickDefaultConfig";

const renderTooltipValue = ({ value }: ChartTooltipRenderValueArguments) =>
value;

interface MetricChartProps {
name: string;
projectId: string;
Expand All @@ -34,6 +37,9 @@ interface MetricChartProps {
intervalEnd: string;
disableLoadingData: boolean;
metricName: METRIC_NAME_TYPE;
renderValue?: (data: ChartTooltipRenderValueArguments) => ValueType;
labelsMap?: Record<string, string>;
customYTickFormatter?: (value: number, maxDecimalLength?: number) => string;
}

type TransformedDataValueType = null | number | string;
Expand All @@ -47,6 +53,9 @@ const MetricChart = ({
intervalStart,
intervalEnd,
disableLoadingData,
renderValue = renderTooltipValue,
labelsMap,
customYTickFormatter,
}: MetricChartProps) => {
const { data: traces, isPending } = useProjectMetric(
{
Expand Down Expand Up @@ -83,20 +92,22 @@ const MetricChart = ({
});
});

return [transformedData, lines, values];
return [transformedData, lines.sort(), values];
}, [traces]);

const config = useMemo(() => {
return getDefaultHashedColorsChartConfig(lines);
}, [lines]);
return getDefaultHashedColorsChartConfig(lines, labelsMap);
}, [lines, labelsMap]);

const {
width: yTickWidth,
ticks,
tickFormatter: yTickFormatter,
domain,
interval: yTickInterval,
} = useChartTickDefaultConfig(values);
yTickFormatter,
} = useChartTickDefaultConfig(values, {
tickFormatter: customYTickFormatter,
});

const renderChartTooltipHeader = useCallback(
({ payload }: ChartTooltipRenderHeaderArguments) => {
Expand All @@ -109,17 +120,6 @@ const MetricChart = ({
[],
);

const renderTooltipValue = useCallback(
({ value }: ChartTooltipRenderValueArguments) => {
if (metricName === METRIC_NAME_TYPE.COST) {
return formatCost(value as number);
}

return value;
},
[metricName],
);

const xTickFormatter = useCallback(
(val: string) => {
if (interval === INTERVAL_TYPE.HOURLY) {
Expand Down Expand Up @@ -178,7 +178,7 @@ const MetricChart = ({
content={
<ChartTooltipContent
renderHeader={renderChartTooltipHeader}
renderValue={renderTooltipValue}
renderValue={renderValue}
/>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import useTracesOrSpansList, {
TRACE_DATA_TYPE,
} from "@/hooks/useTracesOrSpansList";
import NoTracesPage from "@/components/pages/TracesPage/NoTracesPage";
import { ChartTooltipRenderValueArguments } from "@/components/shared/ChartTooltipContent/ChartTooltipContent";
import { formatCost } from "@/lib/money";
import { formatDuration } from "@/lib/date";

enum DAYS_OPTION_TYPE {
ONE_DAY = "1",
Expand Down Expand Up @@ -41,12 +44,27 @@ const DAYS_OPTIONS = [
},
];

const DURATION_LABELS_MAP = {
"duration.p50": "Percentile 50",
"duration.p90": "Percentile 90",
"duration.p99": "Percentile 99",
};

const POSSIBLE_DAYS_OPTIONS = Object.values(DAYS_OPTION_TYPE);
const DEFAULT_DAYS_VALUE = DAYS_OPTION_TYPE.THIRTY_DAYS;

const nowUTC = dayjs().utc();
const intervalEnd = nowUTC.format();

const renderCostTooltipValue = ({ value }: ChartTooltipRenderValueArguments) =>
formatCost(value as number);

const renderDurationTooltipValue = ({
value,
}: ChartTooltipRenderValueArguments) => formatDuration(value as number);

const durationYTickFormatter = (value: number) => formatDuration(value);

interface MetricsTabProps {
projectId: string;
}
Expand Down Expand Up @@ -151,6 +169,21 @@ const MetricsTab = ({ projectId }: MetricsTabProps) => {
</div>

<div className="flex flex-col gap-4 md:flex-row">
<div className="flex-1">
<MetricChart
name="Duration"
metricName={METRIC_NAME_TYPE.DURATION}
interval={interval}
intervalStart={intervalStart}
intervalEnd={intervalEnd}
projectId={projectId}
disableLoadingData={!isValidDays}
renderValue={renderDurationTooltipValue}
labelsMap={DURATION_LABELS_MAP}
customYTickFormatter={durationYTickFormatter}
/>
</div>

<div className="flex-1">
<MetricChart
name="Token usage"
Expand All @@ -162,7 +195,8 @@ const MetricsTab = ({ projectId }: MetricsTabProps) => {
disableLoadingData={!isValidDays}
/>
</div>

</div>
<div className="flex flex-col gap-4 md:flex-row">
<div className="flex-1">
<MetricChart
name="Estimated cost"
Expand All @@ -172,6 +206,7 @@ const MetricsTab = ({ projectId }: MetricsTabProps) => {
intervalEnd={intervalEnd}
projectId={projectId}
disableLoadingData={!isValidDays}
renderValue={renderCostTooltipValue}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ import FeedbackScoreCell from "@/components/shared/DataTableCells/FeedbackScoreC
import FeedbackScoreHeader from "@/components/shared/DataTableHeaders/FeedbackScoreHeader";
import TraceDetailsPanel from "@/components/shared/TraceDetailsPanel/TraceDetailsPanel";
import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper";
import { formatDate } from "@/lib/date";
import { millisecondsToSeconds } from "@/lib/utils";
import { formatDate, formatDuration } from "@/lib/date";
import useTracesOrSpansStatistic from "@/hooks/useTracesOrSpansStatistic";
import { useDynamicColumnsCache } from "@/hooks/useDynamicColumnsCache";

Expand Down Expand Up @@ -102,8 +101,7 @@ const SHARED_COLUMNS: ColumnData<BaseTraceData>[] = [
label: "Duration",
type: COLUMN_TYPE.duration,
cell: DurationCell as never,
statisticDataFormater: (value: number) =>
isNaN(value) ? "NA" : `${millisecondsToSeconds(value)}s`,
statisticDataFormater: formatDuration,
},
{
id: "metadata",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CellContext } from "@tanstack/react-table";
import CellWrapper from "@/components/shared/DataTableCells/CellWrapper";
import { millisecondsToSeconds } from "@/lib/utils";
import { formatDuration } from "@/lib/date";

const DurationCell = <TData,>(context: CellContext<TData, number>) => {
const value = context.getValue();
Expand All @@ -10,7 +10,7 @@ const DurationCell = <TData,>(context: CellContext<TData, number>) => {
metadata={context.column.columnDef.meta}
tableMetadata={context.table.options.meta}
>
{isNaN(value) ? "NA" : `${millisecondsToSeconds(value)}s`}
{formatDuration(value)}
</CellWrapper>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import AgentGraphTab from "./AgentGraphTab";
import ErrorTab from "./ErrorTab";
import { Button } from "@/components/ui/button";
import { useToast } from "@/components/ui/use-toast";
import { millisecondsToSeconds } from "@/lib/utils";
import { formatDuration } from "@/lib/date";
import { isObjectSpan } from "@/lib/traces";
import isUndefined from "lodash/isUndefined";
import { formatCost } from "@/lib/money";
Expand Down Expand Up @@ -114,9 +114,7 @@ const TraceDataViewer: React.FunctionComponent<TraceDataViewerProps> = ({
className="flex items-center gap-2 px-1"
>
<Clock className="size-4 shrink-0" />
{isNaN(data.duration)
? "NA"
: `${millisecondsToSeconds(data.duration)} seconds`}
{formatDuration(data.duration)}
</div>
</TooltipWrapper>
{isNumber(tokens) && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from "react";
import isEmpty from "lodash/isEmpty";
import isNumber from "lodash/isNumber";
import isNull from "lodash/isNull";
import isUndefined from "lodash/isUndefined";
import { TreeRenderProps } from "react-complex-tree";
import {
Expand All @@ -12,9 +11,10 @@ import {
Hash,
PenLine,
} from "lucide-react";
import { cn, millisecondsToSeconds } from "@/lib/utils";
import { BASE_TRACE_DATA_TYPE } from "@/types/traces";
import { cn } from "@/lib/utils";
import { formatDuration } from "@/lib/date";
import { formatCost } from "@/lib/money";
import { BASE_TRACE_DATA_TYPE } from "@/types/traces";
import BaseTraceDataTypeIcon from "../BaseTraceDataTypeIcon";
import TooltipWrapper from "@/components/shared/TooltipWrapper/TooltipWrapper";
import styles from "./TraceTreeViewer.module.scss";
Expand Down Expand Up @@ -62,12 +62,7 @@ export const treeRenderers: TreeRenderProps = {
0,
);

const duration =
isNaN(props.item.data.duration) ||
isUndefined(props.item.data.duration) ||
isNull(props.item.data.duration)
? "NA"
: `${millisecondsToSeconds(props.item.data.duration)}s`;
const duration = formatDuration(props.item.data.duration);

const name = props.item.data.name || "NA";
const tokens = props.item.data.tokens;
Expand Down
Loading

0 comments on commit 179d90d

Please sign in to comment.