1515 */
1616
1717import React from "react"
18- import { Chart , ChartAxis , ChartArea } from "@patternfly/react-charts"
18+ import { Chart , ChartAxis , ChartArea , ChartAreaProps , ChartAxisProps } from "@patternfly/react-charts"
1919import { Log } from "../types"
2020
2121import "../../web/scss/components/Dashboard/Charts.scss"
@@ -24,111 +24,144 @@ type Props = {
2424 logs : Log [ ]
2525}
2626
27- const generateXFormat = ( logs : Log [ ] ) => {
28- return [
29- ...new Set (
30- logs
31- . filter ( ( item ) => item . utilizationGPU > 0 )
32- . map ( ( item ) => `${ new Date ( item . timestamp ) . getHours ( ) } :${ new Date ( item . timestamp ) . getMinutes ( ) } ` )
33- ) ,
27+ export default class GPUChart extends React . PureComponent < Props > {
28+ private readonly colors = [
29+ "var(--color-base04)" ,
30+ "var(--color-latency-3)" ,
31+ "var(--color-latency-1)" ,
32+ "var(--color-latency-4)" ,
3433 ]
35- }
34+ private readonly labelColor = "var(--color-text-01)"
35+ private readonly fontFamily = "var(--font-sans-serif)"
3636
37- const generateXValues = ( logs : Log [ ] ) => {
38- return [ ...new Set ( logs . filter ( ( item ) => item . utilizationGPU > 0 ) . map ( ( item ) => item . timestamp ) ) ]
39- }
37+ private readonly axisStyle : ChartAxisProps [ "style" ] = {
38+ tickLabels : { fontSize : 9 , fontFamily : this . fontFamily , fill : this . labelColor } ,
39+ axisLabel : { fontSize : 11 , fontFamily : this . fontFamily , fill : this . labelColor } ,
40+ }
4041
41- const axisStyle = { tickLabels : { fontSize : 9 } }
42- const yTickValues = [ 0 , 25 , 50 , 75 , 100 ]
43- const yTickLabels = yTickValues . map ( ( _ ) => ` ${ _ } %` )
42+ private axisStyleWithGrid : ChartAxisProps [ "style" ] = Object . assign ( { } , this . axisStyle , {
43+ grid : { strokeWidth : 1 , stroke : this . colors [ 0 ] } ,
44+ } )
4445
45- const styles = {
46- memory : { data : { fill : "var(--color-chart-0)" } } ,
47- gpu : { data : { fill : "var(--color-chart-1)" } } ,
48- }
46+ private readonly padding = {
47+ bottom : 25 ,
48+ left : 60 ,
49+ right : 25 ,
50+ top : 10 ,
51+ }
4952
50- const GPUChart = ( props : Props ) => {
51- const { logs } = props
52- return (
53- < div style = { { height : "auto" , width : "100%" , display : "flex" , flexDirection : "column" } } >
54- < Chart
55- ariaTitle = "GPU Utilization"
56- ariaDesc = "Chart showing GPU utilization over time"
57- height = { 135 }
58- width = { 1000 }
59- maxDomain = { { y : 100 } }
60- minDomain = { { y : 0 } }
61- padding = { {
62- bottom : 25 ,
63- left : 60 ,
64- right : 5 ,
65- top : 10 ,
66- } }
67- >
68- < ChartAxis
69- label = "GPU"
70- dependentAxis
71- showGrid
72- style = { axisStyle }
73- tickValues = { yTickValues }
74- tickFormat = { yTickLabels }
75- />
76- < ChartAxis
77- scale = "time"
78- style = { axisStyle }
79- tickValues = { generateXValues ( logs ) }
80- tickFormat = { generateXFormat ( logs ) }
81- tickCount = { generateXFormat ( logs ) . length }
82- />
83- < ChartArea
84- style = { styles . gpu }
85- data = { logs . map ( ( log ) => ( {
86- name : log . gpuType ,
87- x : log . timestamp ,
88- y : log . utilizationGPU ,
89- } ) ) }
90- />
91- </ Chart >
53+ private readonly styles = {
54+ utilizationMemory : this . style ( this . colors [ 1 ] ) ,
55+ utilizationGPU : this . style ( this . colors [ 2 ] ) ,
56+ temperatureGPU : this . style ( this . colors [ 3 ] ) ,
57+ cluster : undefined ,
58+ timestamp : undefined ,
59+ gpuType : undefined ,
60+ totalMemory : undefined ,
61+ }
62+
63+ private readonly dimensions = {
64+ width : 400 ,
65+ height : 90 ,
66+ }
67+
68+ private readonly formatters = {
69+ celsius : ( value : number ) => value + "C" ,
70+ percentage : ( value : number ) => value + "%" ,
71+ timestamp : ( timestamp : number ) => `${ new Date ( timestamp ) . getHours ( ) } :${ new Date ( timestamp ) . getMinutes ( ) } ` ,
72+ }
73+
74+ private readonly minDomain = {
75+ percentage : { y : 0 } ,
76+ celsius : undefined ,
77+ timestamp : undefined ,
78+ }
79+ private readonly maxDomain = {
80+ percentage : { y : 100 } ,
81+ celsius : undefined ,
82+ timestamp : undefined ,
83+ }
84+
85+ private xAxis ( ) {
86+ return (
87+ < ChartAxis
88+ scale = "time"
89+ style = { this . axisStyle }
90+ tickValues = { this . props . logs . map ( ( item ) => item . timestamp ) }
91+ tickFormat = { this . formatters . timestamp }
92+ tickCount = { 5 }
93+ />
94+ )
95+ }
96+
97+ private style ( color : string ) : ChartAreaProps [ "style" ] {
98+ return { data : { stroke : color , fill : color } }
99+ }
100+
101+ private chart (
102+ title : string ,
103+ desc : string ,
104+ label : string ,
105+ formatter : keyof typeof this . formatters ,
106+ series : keyof Log ,
107+ tickCount ?: number
108+ ) {
109+ return (
92110 < Chart
93- ariaTitle = "GPU Memory Utilization"
94- ariaDesc = "Chart showing GPU memory utilization over time"
95- height = { 135 }
96- width = { 1000 }
97- maxDomain = { { y : 100 } }
98- minDomain = { { y : 0 } }
99- padding = { {
100- bottom : 25 ,
101- left : 60 ,
102- right : 5 ,
103- top : 10 ,
104- } }
111+ ariaTitle = { title }
112+ ariaDesc = { desc }
113+ height = { this . dimensions . height }
114+ width = { this . dimensions . width }
115+ maxDomain = { this . maxDomain [ formatter ] }
116+ minDomain = { this . minDomain [ formatter ] }
117+ padding = { this . padding }
105118 >
106119 < ChartAxis
107- label = "Memory"
120+ label = { label }
108121 dependentAxis
109- showGrid
110- style = { axisStyle }
111- tickValues = { yTickValues }
112- tickFormat = { yTickLabels }
113- />
114- < ChartAxis
115- scale = "time"
116- style = { axisStyle }
117- tickValues = { generateXValues ( logs ) }
118- tickFormat = { generateXFormat ( logs ) }
119- tickCount = { generateXFormat ( logs ) . length }
122+ style = { this . axisStyleWithGrid }
123+ tickFormat = { this . formatters [ formatter ] }
124+ tickCount = { tickCount }
120125 />
126+ { this . xAxis ( ) }
121127 < ChartArea
122- style = { styles . memory }
123- data = { logs . map ( ( log ) => ( {
128+ style = { this . styles [ series ] }
129+ data = { this . props . logs . map ( ( log ) => ( {
124130 name : log . gpuType ,
125131 x : log . timestamp ,
126- y : log . utilizationMemory ,
132+ y : log [ series ] ,
127133 } ) ) }
128134 />
129135 </ Chart >
130- </ div >
131- )
132- }
136+ )
137+ }
133138
134- export default GPUChart
139+ public render ( ) {
140+ return (
141+ < div className = "codeflare-chart-container" >
142+ { this . chart (
143+ "GPU Utilization" ,
144+ "Chart showing GPU utilization over time" ,
145+ "Utilization" ,
146+ "percentage" ,
147+ "utilizationGPU"
148+ ) }
149+ { this . chart (
150+ "GPU Memory Utilization" ,
151+ "Chart showing GPU memory utilization over time" ,
152+ "Memory" ,
153+ "percentage" ,
154+ "utilizationMemory"
155+ ) }
156+ { this . chart (
157+ "GPU Temperature" ,
158+ "Chart showing GPU temperature over time" ,
159+ "Temperature" ,
160+ "celsius" ,
161+ "temperatureGPU" ,
162+ 3
163+ ) }
164+ </ div >
165+ )
166+ }
167+ }
0 commit comments