(im->symbol != ' ' ? " %c" : ""));
}
} else { /* classic rrd grid */
+ double grid_scaled;
+ double label_step;
+ double maxabs;
+ int int_digits;
+ int needed;
+
for (i = 0; ylab[i].grid > 0; i++) {
pixel = im->ysize / (scaledrange / ylab[i].grid);
gridind = i;
}
im->ygrid_scale.gridstep = ylab[gridind].grid * im->magfact;
+
+ /* If the label step is sub-integer, draw_horizontal_grid will
+ * format labels with one fractional digit (%4.1f) to keep
+ * neighbouring labels distinct (issue #1326). Make sure the
+ * vertical label column is wide enough to hold them. */
+ grid_scaled = ylab[gridind].grid * im->viewfactor;
+ label_step = grid_scaled * (double) im->ygrid_scale.labfact;
+ maxabs = max(fabs(im->maxval), fabs(im->minval))
+ * im->viewfactor / im->magfact;
+ if (maxabs < 10) {
+ int_digits = 1;
+ } else {
+ int_digits = (int) ceil(log10(maxabs + 0.5));
+ }
+ if (label_step < 1 || maxabs < 10) {
+ /* digits + '.' + 1 fractional digit */
+ needed = int_digits + 2;
+ } else {
+ needed = int_digits;
+ }
+ if (im->minval < 0) {
+ needed += 1; /* sign */
+ }
+ if (im->symbol != ' ') {
+ needed += 2; /* " <SI>" suffix */
+ }
+ if (im->unitslength < needed) {
+ im->unitslength = needed;
+ }
}
} else {
im->ygrid_scale.gridstep = im->ygridstep;
im->ygrid_scale.labfmt,
scaledstep * (double) i);
} else {
- if (MaxY < 10) {
+ if (MaxY < 10
+ || scaledstep *
+ (double) im->ygrid_scale.labfact < 1) {
snprintf(graph_label, sizeof graph_label,
"%4.1f",
scaledstep * (double) i);
im->ygrid_scale.labfmt,
scaledstep * (double) i, sisym);
} else {
- if (MaxY < 10) {
+ if (MaxY < 10
+ || scaledstep *
+ (double) im->ygrid_scale.labfact < 1) {
snprintf(graph_label, sizeof graph_label,
"%4.1f %c",
scaledstep * (double) i, sisym);
}
sval /= second_axis_magfact;
- if (MaxY < 10) {
- snprintf(graph_label_right,
- sizeof graph_label_right, "%5.1f %s",
- sval, second_axis_symb);
- } else {
- snprintf(graph_label_right,
- sizeof graph_label_right, "%5.0f %s",
- sval, second_axis_symb);
+ {
+ double right_step =
+ im->ygrid_scale.gridstep *
+ im->second_axis_scale /
+ second_axis_magfact *
+ (double) im->ygrid_scale.labfact;
+
+ if (MaxY < 10 || fabs(right_step) < 1) {
+ snprintf(graph_label_right,
+ sizeof graph_label_right,
+ "%5.1f %s", sval,
+ second_axis_symb);
+ } else {
+ snprintf(graph_label_right,
+ sizeof graph_label_right,
+ "%5.0f %s", sval,
+ second_axis_symb);
+ }
}
} else {
snprintf(graph_label_right,
create-with-source-1 create-with-source-2 create-with-source-3 \
create-with-source-4 create-with-source-and-mapping-1 \
create-from-template-1 dcounter1 vformatter1 xport1 xport2 xport3 list1 \
- pdp-calc1 graph3
+ pdp-calc1 graph3 graph4
EXTRA_DIST = Makefile.am \
functions $(TESTS) \
tune1-testa-mod1.dump tune1-testa-mod2.dump tune1-testorg.dump \
tune2-testa-mod1.dump tune2-testorg.dump \
valgrind-supressions dcounter1 dcounter1.output graph1.output graph2.output vformatter1 rpn1.output rpn2.output \
- xport1.json.output xport1.xml.output xport2 xport3 graph3 \
+ xport1.json.output xport1.xml.output xport2 xport3 graph3 graph4 \
pdp-calc1 pdp-calc1-1-avg-60.output pdp-calc1-1-avg-300.output pdp-calc1-1-max-300.output
# NB: AM_TESTS_ENVIRONMENT not available until automake 1.12
CLEANFILES = *.rrd \
ct.out dur.out graph1.output.out graph2.output.out \
+ graph4.pdf \
modify5-testa1-mod.dump modify5-testa2-mod.dump \
modify5-testa1-mod.dump.tmp modify5-testa2-mod.dump.tmp \
rpn1.out rpn1.output.out
--- /dev/null
+#!/bin/bash
+
+. $(dirname $0)/functions
+
+if [ -n "$MSYSTEM" ]; then
+ BUILD=graph4
+else
+ BUILD=$BUILDDIR/graph4
+fi
+
+# Issue #1326: With Y-axis values in the 10G+ range and a tall graph,
+# the gridstep becomes fractional (e.g. 0.1 G) after SI scaling, but the
+# legacy formatter chose %4.0f whenever MaxY >= 10, rounding 10.2, 10.4,
+# 10.6 all to "10" and producing duplicate Y-axis labels.
+
+$RRDTOOL create ${BUILD}.rrd \
+ --start 1748087640 --step 60 \
+ DS:value:GAUGE:120:U:U \
+ RRA:AVERAGE:0.5:1:60
+report "create"
+
+is_cached && exit 0
+
+# Populate with 10.1G .. 11.5G in 0.1G increments
+for i in $(seq 1 15); do
+ t=$((1748087640 + i*60))
+ v=$(awk -v i="$i" 'BEGIN { printf "%.0f", 10e9 + i*1e8 }')
+ $RRDTOOL update ${BUILD}.rrd ${t}:${v}
+done
+report "update"
+
+# Generate a tall graph so the autoscaler picks a small gridstep
+$RRDTOOL graph ${BUILD}.pdf --imgformat PDF \
+ --start 1748087700 --end 1748088600 --height 1000 \
+ DEF:v=${BUILD}.rrd:value:AVERAGE \
+ LINE1:v#000000 > /dev/null
+report "graph"
+
+# If pdftotext is available, verify Y-axis labels are unique
+if command -v pdftotext > /dev/null; then
+ LABELS=$(pdftotext ${BUILD}.pdf - | grep -E '^[0-9]+\.[0-9]+ G$')
+ UNIQUE=$(echo "$LABELS" | sort -u | wc -l)
+ TOTAL=$(echo "$LABELS" | wc -l)
+ if [ "$UNIQUE" = "$TOTAL" ] && [ "$TOTAL" -ge 10 ]; then
+ ok "Y-axis labels are unique ($TOTAL distinct labels)"
+ else
+ fail 1 "Y-axis labels are duplicated (got $UNIQUE distinct out of $TOTAL)"
+ fi
+else
+ ok "pdftotext not available, skipping label uniqueness check"
+fi