EdgeFunctionInvocationsChart.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { Rocket } from 'lucide-react'
  2. import { useMemo } from 'react'
  3. import {
  4. Bar,
  5. CartesianGrid,
  6. BarChart as RechartBarChart,
  7. ReferenceLine,
  8. XAxis,
  9. YAxis,
  10. } from 'recharts'
  11. import { ChartContainer, ChartTooltip, ChartTooltipContent } from 'ui'
  12. import {
  13. formatChartTimestamp,
  14. getChartTimeRangeLabels,
  15. INVOCATION_CHART_CONFIG,
  16. } from './EdgeFunctionOverview.utils'
  17. import type { InvocationChartDatum, InvocationUpdateAnnotation } from './EdgeFunctionOverview.utils'
  18. interface EdgeFunctionInvocationsChartProps {
  19. chartData: InvocationChartDatum[]
  20. dateTimeFormat: string
  21. onChartClick: () => void
  22. updateAnnotation?: InvocationUpdateAnnotation
  23. }
  24. export const EdgeFunctionInvocationsChart = ({
  25. chartData,
  26. dateTimeFormat,
  27. onChartClick,
  28. updateAnnotation,
  29. }: EdgeFunctionInvocationsChartProps) => {
  30. const timeRangeLabels = useMemo(
  31. () => getChartTimeRangeLabels(chartData, dateTimeFormat),
  32. [chartData, dateTimeFormat]
  33. )
  34. return (
  35. <div className="flex flex-col gap-1">
  36. <div className="relative h-40 w-full overflow-visible">
  37. <ChartContainer config={INVOCATION_CHART_CONFIG} className="aspect-auto! h-full! w-full!">
  38. <RechartBarChart
  39. data={chartData}
  40. margin={{ top: 0, right: 0, left: 0, bottom: 0 }}
  41. onClick={onChartClick}
  42. >
  43. <CartesianGrid vertical={false} />
  44. <YAxis hide width={0} />
  45. <XAxis
  46. dataKey="timestamp"
  47. tickLine={false}
  48. axisLine={false}
  49. tick={false}
  50. minTickGap={32}
  51. />
  52. <ChartTooltip
  53. cursor={false}
  54. content={
  55. <ChartTooltipContent
  56. className="text-foreground-light"
  57. labelFormatter={(value) =>
  58. formatChartTimestamp(value as string | number | undefined, dateTimeFormat)
  59. }
  60. indicator="dot"
  61. />
  62. }
  63. />
  64. <Bar
  65. dataKey="error_count"
  66. stackId="invocations"
  67. fill="var(--color-error_count)"
  68. maxBarSize={24}
  69. />
  70. <Bar
  71. dataKey="warning_count"
  72. stackId="invocations"
  73. fill="var(--color-warning_count)"
  74. maxBarSize={24}
  75. />
  76. <Bar
  77. dataKey="ok_count"
  78. stackId="invocations"
  79. fill="var(--color-ok_count)"
  80. maxBarSize={24}
  81. />
  82. {updateAnnotation && (
  83. <ReferenceLine
  84. x={updateAnnotation.timestamp}
  85. stroke="hsl(var(--foreground-default))"
  86. strokeDasharray="4 4"
  87. strokeWidth={1.5}
  88. />
  89. )}
  90. </RechartBarChart>
  91. </ChartContainer>
  92. {updateAnnotation && (
  93. <span
  94. className="pointer-events-none absolute bottom-0 z-10 flex h-6 w-6 -translate-x-1/2 translate-y-1/2 items-center justify-center rounded-full border border-foreground/20 bg-background text-foreground shadow-xs"
  95. style={{ left: `${updateAnnotation.position}%` }}
  96. title={`Updated ${formatChartTimestamp(updateAnnotation.updatedAt, dateTimeFormat)}`}
  97. >
  98. <Rocket size={12} strokeWidth={1.75} />
  99. </span>
  100. )}
  101. </div>
  102. {timeRangeLabels && (
  103. <div className="-mt-6 flex items-center justify-between text-[10px] font-mono text-foreground-lighter">
  104. <span>{timeRangeLabels.start}</span>
  105. <span>{timeRangeLabels.end}</span>
  106. </div>
  107. )}
  108. </div>
  109. )
  110. }