@@ -18,6 +18,7 @@ type graph struct {
1818 timeLength string // Time length for the graph (e.g., "4h" "1d")
1919 dsName string // RRD data source name (e.g., "latency")
2020 unit string // Unit of measurement (e.g., "ms")
21+ scale int // Divisor to convert raw value to display unit (0 or 1 = no scaling)
2122 consolidationFunction string // Consolidation function (e.g., "AVERAGE" "MAX")
2223 color string // Metric color (e.g., "#FF0001" (red))
2324 comment string // Comment at bottom of graph
@@ -36,12 +37,13 @@ type graph struct {
3637// - dsName: The RRD data source name (e.g., "latency").
3738// - label: The human-readable label for the metric (e.g., "latency").
3839// - unit: The unit of measurement (e.g., "ms").
40+ // - scale: The divisor to convert the raw stored value to display unit (0 or 1 = no scaling).
3941// - logger: The logger instance.
4042//
4143// Returns:
4244// - *Graph: A pointer to the newly created Graph struct.
4345// - error: An error if something went wrong during the initialization.
44- func newGraph (host string , graphDir string , rrdPath string , timeLength string , consolidationFunction string , checkType string , dsName string , label string , unit string , logger * logrus.Logger ) (* graph , error ) {
46+ func newGraph (host string , graphDir string , rrdPath string , timeLength string , consolidationFunction string , checkType string , dsName string , label string , unit string , scale int , logger * logrus.Logger ) (* graph , error ) {
4547
4648 // Define directory and file paths
4749 dirPath := fmt .Sprintf ("%s/imgs/%s" , graphDir , host )
@@ -63,6 +65,7 @@ func newGraph(host string, graphDir string, rrdPath string, timeLength string, c
6365 timeLength : timeLength ,
6466 dsName : dsName ,
6567 unit : unit ,
68+ scale : scale ,
6669 consolidationFunction : consolidationFunction ,
6770 color : GREEN ,
6871 comment : comment ,
@@ -78,6 +81,21 @@ func newGraph(host string, graphDir string, rrdPath string, timeLength string, c
7881 return graph , nil
7982}
8083
84+ // displayVarName returns the RRD variable name used for display.
85+ // When scaling is applied, the variable includes the unit suffix (e.g., "latency_ms").
86+ // When no scaling is needed, it uses the raw variable directly (e.g., "latency_raw").
87+ func (g * graph ) displayVarName () string {
88+ if g .needsScaling () {
89+ return fmt .Sprintf ("%s_%s" , g .dsName , g .unit )
90+ }
91+ return fmt .Sprintf ("%s_raw" , g .dsName )
92+ }
93+
94+ // needsScaling returns true if the raw value needs to be divided by a scale factor for display.
95+ func (g * graph ) needsScaling () bool {
96+ return g .scale > 1
97+ }
98+
8199// draw draws a graph based on the current parameters of the Graph struct.
82100// It returns an error if the graph generation fails.
83101func (g * graph ) draw () error {
@@ -102,33 +120,37 @@ func (g *graph) draw() error {
102120 COMMENT:"\MAX latency over last 4h"
103121 */
104122
105- // Prepare the DEF and CDEF strings for each metric.
106- defs := []string {}
107- def := fmt .Sprintf ("DEF:%s_raw=%s:%s:%s" , g .dsName , g .rrdPath , g .dsName , g .consolidationFunction )
108- defs = append (defs , def )
123+ displayVar := g .displayVarName ()
109124
110- cdefs := []string {}
111- cdef := fmt .Sprintf ("CDEF:%s_%s=%s_raw,1000,/" , g .dsName , g .unit , g .dsName )
112- cdefs = append (cdefs , cdef )
125+ // Prepare the DEF string for the raw data source.
126+ defs := []string {
127+ fmt .Sprintf ("DEF:%s_raw=%s:%s:%s" , g .dsName , g .rrdPath , g .dsName , g .consolidationFunction ),
128+ }
129+
130+ // Prepare the CDEF string: apply scaling if needed, otherwise alias raw to display var.
131+ var cdefs []string
132+ if g .needsScaling () {
133+ cdefs = append (cdefs , fmt .Sprintf ("CDEF:%s=%s_raw,%d,/" , displayVar , g .dsName , g .scale ))
134+ }
135+ // When no scaling is needed, displayVar is already "dsName_raw" which is the DEF name,
136+ // so no CDEF is required.
113137
114138 lines := []string {
115- fmt .Sprintf ("AREA:%s_% s#%s:%s" , g . dsName , g . unit , g .color , g .label ),
139+ fmt .Sprintf ("AREA:%s#%s:%s" , displayVar , g .color , g .label ),
116140 }
117141
118- gprints := []string {}
119142 gfmt := "%.2lf"
120- gprintsMinval := fmt .Sprintf ("Min\\ : %s %s" , gfmt , g .unit )
121- gprints = append (gprints , fmt .Sprintf ("GPRINT:%s_%s:MIN:%s" , g .dsName , g .unit , gprintsMinval ))
122- gprintsMaxval := fmt .Sprintf ("Max\\ : %s %s" , gfmt , g .unit )
123- gprints = append (gprints , fmt .Sprintf ("GPRINT:%s_%s:MAX:%s" , g .dsName , g .unit , gprintsMaxval ))
124- gprintsAverageval := fmt .Sprintf ("Average\\ : %s %s" , gfmt , g .unit )
125- gprints = append (gprints , fmt .Sprintf ("GPRINT:%s_%s:AVERAGE:%s" , g .dsName , g .unit , gprintsAverageval ))
126- gprintsLastval := fmt .Sprintf ("Last\\ : %s %s" , gfmt , g .unit )
127- gprints = append (gprints , fmt .Sprintf ("GPRINT:%s_%s:LAST:%s" , g .dsName , g .unit , gprintsLastval ))
128-
129- commentStrings := []string {}
130- commentStrings = append (commentStrings , "COMMENT:\\ n" )
131- commentStrings = append (commentStrings , fmt .Sprintf ("COMMENT:%s" , g .comment ))
143+ gprints := []string {
144+ fmt .Sprintf ("GPRINT:%s:MIN:Min\\ : %s %s" , displayVar , gfmt , g .unit ),
145+ fmt .Sprintf ("GPRINT:%s:MAX:Max\\ : %s %s" , displayVar , gfmt , g .unit ),
146+ fmt .Sprintf ("GPRINT:%s:AVERAGE:Average\\ : %s %s" , displayVar , gfmt , g .unit ),
147+ fmt .Sprintf ("GPRINT:%s:LAST:Last\\ : %s %s" , displayVar , gfmt , g .unit ),
148+ }
149+
150+ commentStrings := []string {
151+ "COMMENT:\\ n" ,
152+ fmt .Sprintf ("COMMENT:%s" , g .comment ),
153+ }
132154
133155 // Prepare the command for generating the graph.
134156 args := []string {
0 commit comments