1
1
"use client" ;
2
2
3
- import { Card } from "chakra/card" ;
4
- import { Heading } from "chakra/heading" ;
5
- import { Text } from "chakra/text" ;
6
- import { ChartAreaIcon , InfoIcon } from "lucide-react" ;
7
- import { Spinner } from "@/components/ui/Spinner/Spinner" ;
3
+ import { CircleAlertIcon } from "lucide-react" ;
4
+ import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage" ;
5
+ import { Alert , AlertDescription , AlertTitle } from "@/components/ui/alert" ;
8
6
import { UnderlineLink } from "@/components/ui/UnderlineLink" ;
9
7
import {
10
8
type EngineInstance ,
@@ -15,19 +13,17 @@ import { ErrorRate } from "./ErrorRate";
15
13
import { Healthcheck } from "./Healthcheck" ;
16
14
import { StatusCodes } from "./StatusCodes" ;
17
15
18
- interface EngineStatusProps {
19
- instance : EngineInstance ;
20
- teamSlug : string ;
21
- projectSlug : string ;
22
- authToken : string ;
23
- }
24
-
25
- export const EngineSystemMetrics : React . FC < EngineStatusProps > = ( {
16
+ export function EngineSystemMetrics ( {
26
17
instance,
27
18
teamSlug,
28
19
projectSlug,
29
20
authToken,
30
- } ) => {
21
+ } : {
22
+ instance : EngineInstance ;
23
+ teamSlug : string ;
24
+ projectSlug : string ;
25
+ authToken : string ;
26
+ } ) {
31
27
const systemMetricsQuery = useEngineSystemMetrics (
32
28
instance . id ,
33
29
teamSlug ,
@@ -39,58 +35,54 @@ export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
39
35
pollInterval : 10_000 ,
40
36
} ) ;
41
37
42
- let systemMetricsPanel = < Spinner className = "h-4 w-4" /> ;
38
+ let systemMetricsPanel = < GenericLoadingPage /> ;
43
39
if ( ! systemMetricsQuery . data || systemMetricsQuery . isError ) {
44
40
systemMetricsPanel = (
45
- < Card p = { 8 } >
46
- < div className = "flex flex-col gap-4" >
47
- < div className = "flex flex-row items-center gap-2" >
48
- < InfoIcon className = "size-4" />
49
- < Heading size = "title.xs" >
50
- System metrics are unavailable for self-hosted Engine.
51
- </ Heading >
52
- </ div >
53
- < Text >
41
+ < div >
42
+ < h2 className = "text-2xl font-semibold tracking-tight mb-4" >
43
+ System Metrics
44
+ </ h2 >
45
+
46
+ < Alert variant = "warning" >
47
+ < CircleAlertIcon className = "size-5" />
48
+ < AlertTitle >
49
+ System metrics are not available for self-hosted Engine
50
+ </ AlertTitle >
51
+ < AlertDescription className = "text-muted-foreground text-sm" >
54
52
Upgrade to a{ " " }
55
53
< UnderlineLink
56
- color = "blue.500"
57
54
href = { `/team/${ teamSlug } /${ projectSlug } /engine/dedicated/create` }
58
55
rel = "noopener noreferrer"
59
56
target = "_blank"
60
57
>
61
58
Engine instance managed by thirdweb
62
59
</ UnderlineLink > { " " }
63
- to view these metrics.
64
- </ Text >
65
- </ div >
66
- </ Card >
60
+ to view system metrics
61
+ </ AlertDescription >
62
+ </ Alert >
63
+ </ div >
67
64
) ;
68
65
} else {
69
66
systemMetricsPanel = (
70
- < Card p = { 16 } >
71
- < div className = "flex flex-col gap-4" >
72
- < div className = "-mb-2 flex flex-row items-center gap-2" >
73
- < ChartAreaIcon className = "size-4" />
74
- < Heading size = "title.md" > System Metrics</ Heading >
75
- </ div >
67
+ < div >
68
+ < div className = "flex items-center gap-3 mb-4" >
69
+ < h2 className = "text-2xl font-semibold tracking-tight" >
70
+ System Metrics
71
+ </ h2 >
72
+ < Healthcheck instance = { instance } />
73
+ </ div >
76
74
77
- < div className = "mt-10 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3" >
78
- < Healthcheck instance = { instance } />
79
- </ div >
75
+ < div className = "space-y-8" >
80
76
< StatusCodes
81
77
datapoints = { systemMetricsQuery . data . result . statusCodes }
82
78
/>
83
79
< ErrorRate datapoints = { systemMetricsQuery . data . result . errorRate } />
84
80
</ div >
85
- </ Card >
81
+ </ div >
86
82
) ;
87
83
}
88
84
89
- let queueMetricsPanel = (
90
- < div className = "flex min-h-[200px] items-center justify-center rounded-lg border border-border" >
91
- < Spinner className = "size-6" />
92
- </ div >
93
- ) ;
85
+ let queueMetricsPanel = < GenericLoadingPage /> ;
94
86
95
87
if (
96
88
! queueMetricsQuery . isPending &&
@@ -108,43 +100,39 @@ export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
108
100
const msToMine = queueMetricsQuery . data . result . latency ?. msToMine ;
109
101
110
102
queueMetricsPanel = (
111
- < Card p = { 8 } >
112
- < div className = "flex flex-col gap-6" >
113
- < div className = "flex flex-row items-center gap-2" >
114
- < Heading size = "title.md" > Queue Metrics</ Heading >
115
- </ div >
103
+ < div className = "bg-card p-4 rounded-lg border lg:p-6" >
104
+ < h2 className = "text-lg tracking-tight font-semibold mb-3" >
105
+ Queue Metrics
106
+ </ h2 >
116
107
117
- < div className = "flex flex-col gap-6 lg:flex-row lg:gap-12" >
118
- < div className = "flex-col gap-y-4" >
119
- < h2 className = "font-semibold" > Queued</ h2 >
120
- < p className = "text-muted-foreground" > { numQueued } </ p >
121
- </ div >
122
- < div className = "flex-col gap-y-4" >
123
- < h2 className = "font-semibold" > Pending</ h2 >
124
- < p className = "text-muted-foreground" > { numPending } </ p >
125
- </ div >
108
+ < div className = "space-y-2" >
109
+ < MetricRow label = "Queued" value = { numQueued } />
110
+ < MetricRow label = "Pending" value = { numPending } />
126
111
127
- { msToSend && (
128
- < div className = "flex-col gap-y-4" >
129
- < h2 className = "font-semibold" > Time to send</ h2 >
130
- < p className = "text-muted-foreground" >
112
+ { msToSend && (
113
+ < MetricRow
114
+ label = "Time to send"
115
+ value = {
116
+ < span >
131
117
p50 { ( msToSend . p50 / 1000 ) . toFixed ( 2 ) } s, p90{ " " }
132
118
{ ( msToSend . p90 / 1000 ) . toFixed ( 2 ) } s
133
- </ p >
134
- </ div >
135
- ) }
136
- { msToMine && (
137
- < div className = "flex-col gap-y-4" >
138
- < h2 className = "font-semibold" > Time to mine</ h2 >
139
- < p className = "text-muted-foreground" >
119
+ </ span >
120
+ }
121
+ />
122
+ ) }
123
+ { msToMine && (
124
+ < MetricRow
125
+ label = "Time to mine"
126
+ value = {
127
+ < span >
140
128
p50 { ( msToMine . p50 / 1000 ) . toFixed ( 2 ) } s, p90{ " " }
141
129
{ ( msToMine . p90 / 1000 ) . toFixed ( 2 ) } s
142
- </ p >
143
- </ div >
144
- ) }
145
- </ div >
130
+ </ span >
131
+ }
132
+ />
133
+ ) }
146
134
</ div >
147
- </ Card >
135
+ </ div >
148
136
) ;
149
137
}
150
138
@@ -154,4 +142,19 @@ export const EngineSystemMetrics: React.FC<EngineStatusProps> = ({
154
142
{ queueMetricsPanel }
155
143
</ div >
156
144
) ;
157
- } ;
145
+ }
146
+
147
+ function MetricRow ( {
148
+ label,
149
+ value,
150
+ } : {
151
+ label : string ;
152
+ value : React . ReactNode ;
153
+ } ) {
154
+ return (
155
+ < div className = "grid grid-cols-2 w-[400px]" >
156
+ < h3 className = "text-sm font-medium" > { label } </ h3 >
157
+ < p className = "text-sm text-foreground" > { value } </ p >
158
+ </ div >
159
+ ) ;
160
+ }
0 commit comments