Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

---

## v26.06.106 (2026-06-16)

### Fixed

- **Admin dashboard: the Overview "Thread Count" gauge no longer renders the
thread count as a percentage.** The gauge widget (`createGaugeChart`) was a
fixed 0–100 percentage meter — it clamped its value to 100 and appended a
hard-coded `%` to the centre readout — but the Overview page feeds it the
absolute active-thread count. A process with 8 threads therefore showed
`8%`, and any count above 100 clamped to `100%`. The gauge now accepts a
`max` (the value that fills the arc) and a `unit` (the readout suffix); the
thread gauge passes `unit: ''` and `max: 100`, so it shows the raw count
(`8`, `150`, …) while still acting as a thread-leak indicator (amber past 60,
red past 80). The defaults (`max: 100`, `unit: '%'`) keep every percentage
gauge rendering exactly as before.

---

## v26.06.105 (2026-06-15)

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "pyfly"
# CalVer YY.MM.PATCH — package metadata uses PEP 440 normalized form (26.5.4);
# git tag, GitHub release and human-readable display use leading-zero form
# (v26.05.04) to match the Java/.NET/Go siblings.
version = "26.6.105"
version = "26.6.106"
description = "The official Python implementation of the Firefly Framework — DI, CQRS, EDA, hexagonal architecture, and more."
readme = "README.md"
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/pyfly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
# limitations under the License.
"""PyFly — Enterprise Python Framework."""

__version__ = "26.06.105"
__version__ = "26.06.106"
27 changes: 20 additions & 7 deletions src/pyfly/admin/static/js/charts.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,19 +254,32 @@ export function createDonutChart(canvas, options = {}) {
*/
export function createGaugeChart(canvas, options = {}) {
const thresholds = options.thresholds || { warning: 60, danger: 80 };
let currentValue = Math.max(0, Math.min(100, options.value || 0));
// ``max`` is the value that fills the arc completely; ``unit`` is the suffix
// on the centre readout. The defaults (100 / '%') keep the gauge a
// percentage meter. Pass ``{ max, unit: '' }`` to show an absolute count
// (e.g. thread count, connection count) as a plain number rather than a %.
const max = options.max != null && options.max > 0 ? options.max : 100;
const unit = options.unit != null ? options.unit : '%';
// The displayed value is the raw number (not clamped to 100); only the arc
// fill is bounded to 0-100% of ``max``.
let currentValue = Math.max(0, options.value || 0);

function fill(val) {
return Math.max(0, Math.min(100, (val / max) * 100));
}

function getColor(val) {
if (val >= thresholds.danger) return cssVar('--admin-danger') || '#f43f5e';
if (val >= thresholds.warning) return cssVar('--admin-warning') || '#f59e0b';
const pct = fill(val);
if (pct >= thresholds.danger) return cssVar('--admin-danger') || '#f43f5e';
if (pct >= thresholds.warning) return cssVar('--admin-warning') || '#f59e0b';
return cssVar('--admin-success') || '#10b981';
}

const chart = new Chart(canvas, {
type: 'doughnut',
data: {
datasets: [{
data: [currentValue, 100 - currentValue],
data: [fill(currentValue), 100 - fill(currentValue)],
backgroundColor: [getColor(currentValue), cssVar('--admin-border-subtle') || '#162032'],
borderWidth: 0,
}],
Expand All @@ -293,7 +306,7 @@ export function createGaugeChart(canvas, options = {}) {
ctx.font = `700 ${Math.round(size * 0.2)}px ${cssVar('--admin-font-mono') || 'monospace'}`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(`${Math.round(currentValue)}%`, width / 2, height / 2 - 4);
ctx.fillText(`${Math.round(currentValue)}${unit}`, width / 2, height / 2 - 4);
// Label
if (options.label) {
ctx.fillStyle = cssVar('--admin-text-muted') || '#64748b';
Expand All @@ -307,8 +320,8 @@ export function createGaugeChart(canvas, options = {}) {

return {
update(value) {
currentValue = Math.max(0, Math.min(100, value));
chart.data.datasets[0].data = [currentValue, 100 - currentValue];
currentValue = Math.max(0, value);
chart.data.datasets[0].data = [fill(currentValue), 100 - fill(currentValue)];
chart.data.datasets[0].backgroundColor = [getColor(currentValue), cssVar('--admin-border-subtle') || '#162032'];
chart.update();
},
Expand Down
6 changes: 6 additions & 0 deletions src/pyfly/admin/static/js/views/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,12 @@ export async function render(container, api) {
threadGauge = createGaugeChart(threadCanvas, {
value: 0,
label: 'Threads',
// Thread count is an absolute number, not a percentage: show the
// raw count (unit: '') and scale the arc against a generous ceiling
// so it doubles as a thread-leak indicator (amber past 60, red past
// 80) without ever rendering a misleading ``%``.
unit: '',
max: 100,
thresholds: { warning: 60, danger: 80 },
});

Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading