Skip to content

Changelog

All notable changes to this project are documented here.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

Changed

  • BREAKING: five inventory gauges lose the _total suffix, which Prometheus reserves for counters. Update dashboards, alerts and recording rules that reference them:
Old name New name
powerscale_nfs_exports_total powerscale_nfs_exports
powerscale_smb_shares_total powerscale_smb_shares
powerscale_snapshots_total powerscale_snapshots
powerscale_node_drives_total powerscale_node_drives
powerscale_node_power_supplies_total powerscale_node_power_supplies

Values, labels and units are unchanged. The shipped Grafana boards (powerscale-overview, powerscale-advanced) and deploy/prometheus/pscale.rules.yml are updated; board uids are unchanged. No alias is emitted for the old names.

Added

  • powerscale_quota_application_usage_bytes from usage.applogical (#54). Always emitted, as 0 when the quota API version does not return the field. powerscale_quota_usage_bytes is unchanged.

0.20.1 - 2026-10-25

Changed

  • No code change. CHANGELOG realigned with the tags: the Go 1.27.2 security bump is now recorded under 0.20.0 (which shipped it), and the missing 0.19.0 / 0.19.1 entries are backfilled.

0.20.0 - 2026-10-25

Added

  • OneFS 9.15 support, gated on the cluster's negotiated API version so older clusters keep quota v8 / protocol v3: powerscale_quota_reduction_ratio (quota API v25) and powerscale_protocol_latency_stage_microseconds{stage} (protocol API v26; stages auth, export, fha_blocking, fiber_block_quota, kernel, spark_dispatch, total_elapsed). Both are derived from the 9.15 OpenAPI spec, not yet validated on a live 9.15 cluster.
  • OneFS Advanced dashboard: collapsed OneFS 9.15 row (protocol latency by stage, top-10 quota reduction ratio).

Changed

  • Schema-drift guard and make schemas now use the OneFS 9.15 spec (all existing endpoint schemas are identical to 9.14) and also cover the quota v25 / protocol v26 schemas.

Security

  • Go 1.27.1 -> 1.27.2 (go directive, Dockerfile builder image), fixing the stdlib vulnerabilities GO-2026-6603, GO-2026-6605, GO-2026-6607, GO-2026-6608, GO-2026-6610, GO-2026-6611, GO-2026-6613 and GO-2026-6617.
  • Dependencies updated with go get -u ./...: golang.org/x/net 0.59.0 -> 0.60.0, golang.org/x/sys 0.48.0 -> 0.49.0, golang.org/x/sync 0.23.0 -> 0.24.0, google.golang.org/grpc 1.83.2 -> 1.84.0, prometheus/client_golang 1.24.1 -> 1.25.0, grpc-gateway/v2 2.30.0 -> 2.31.0, go.opentelemetry.io/proto/otlp 1.11.0 -> 1.11.1, and related indirect modules.
  • Makefile: golangci-lint v2.13.2 -> v2.14.0, which can type-check against the Go 1.27.2 standard library.

0.19.3 - 2026-10-03

Added

  • CI: security workflow added, calling the shared go-security reusable workflow from fjacquet/ci.

Changed

  • Go 1.26.6 -> 1.27.1 (go directive in go.mod, Dockerfile builder image).
  • Makefile tool pins: golangci-lint v2.12.2 -> v2.13.2, goreleaser v2.16.0 -> v2.18.0, govulncheck latest -> v1.8.0.
  • Dependencies refreshed with go get -u ./...: github.com/dell/gopowerscale 1.22.0 -> 1.23.0, OpenTelemetry 1.46.0 -> 1.47.0, prometheus/common 0.71.0 -> 0.72.0.
  • google.golang.org/grpc kept at 1.83.2: 1.84.0 is affected by GO-2026-6443.

[0.19.2] - 2026-09-13

Security

  • google.golang.org/grpc 1.83.0 -> 1.83.2, fixing GHSA-vp52-pcj8-j9qc and GHSA-2v4p-qf9q-27wj (HIGH), pulled in with an otel 1.45.0 -> 1.46.0 refresh.

0.19.1 - 2026-08-19

Security

  • Go dependencies refreshed with go get -u for security fixes: logrus 1.9.4 -> 1.10.0, grpc-gateway/v2 2.29.0 -> 2.30.0, golang.org/x/net 0.57.0 -> 0.58.0, golang.org/x/text 0.40.0 -> 0.41.0, google.golang.org/protobuf 1.36.11 -> 1.36.12.

0.19.0 - 2026-08-14

Added

  • Prometheus scrapes cee-exporter and its dashboard is provisioned alongside the PowerScale boards (local test stack).

[0.18.0] - 2026-08-14

Security

  • Go toolchain bumped to 1.26.6, fixing three stdlib CVEs flagged by govulncheck (net/url quadratic-complexity resolvePath, html/template JS-context tracking, and a third fixed alongside them). Applies to the go.mod go directive and the from-source Dockerfile build stage.

Changed

  • Grafana dashboards provision into folders instead of one flat General list: json/PowerScale/ → PowerScale, json/Infrastructure/ → Infrastructure (the third-party Node Exporter board), via foldersFromFilesStructure: true. Adding a board is now a copy into the right directory. Titles lose the redundant PowerScale / prefix the folder now supplies — OneFS Overview, OneFS Advanced, OneFS Capacity & SLA, OneFS Workloads. Every uid is unchanged, so existing links and bookmarks resolve.
  • The four boards are cross-linked. Each carries a PowerScale dashboards dropdown driven by the powerscale tag — a new tagged board joins every menu automatically — with includeVars/keepTime, so cluster, node and time range follow you across boards. The per-node panels on Overview and Capacity & SLA gained a data link into OneFS Advanced scoped to the clicked node; it targets the uid with no title slug, so renaming a board cannot break it.

Fixed

  • CPU percentages were reported 10× too high. OneFS serves cluster.cpu.{sys,user,idle}.avg and node.cpu.{idle,sys,user}.avg in tenths of a percent (idle + user + sys sums to 1000), and the raw value was passed straight through to metrics named _percent — so an idle cluster read 974 instead of 97.4, pinning the Grafana CPU panels (unit: percent, max: 100) at full scale. The six keys now carry "divisor": 10 in statisticsKeys.json. Found by validating a live cluster against docs/metrics.md; the mock fixture had used a percent-looking 12.5 where a real cluster sends 125, so the tests agreed with the bug.

Added

  • ${VAR:-default} fallbacks in config.yaml env references, with shell / docker-compose semantics: the variable falls back when unset or empty, and such a reference never aborts startup. A bare ${VAR} still fails loudly when the variable is unset; an exported-but-empty one expands to the empty string, as it always has. Credential fields (endpoint, username, password) are stricter: a field written as an env reference that resolves to nothing is now rejected, so a stray PSCALE1_PASSWORD= line fails at startup instead of authenticating with an empty password. The error names only the config field: config-load failures are logged, and every part of a credential field — the variable name included — is potentially sensitive. The shipped config.yaml now uses insecureSkipVerify: "${PSCALE1_SKIP_CERTIFICATE:-false}", so the setting is env-driven out of the box yet starts on a host that never exported the variable.
  • statisticsKeys.json rows accept an optional divisor to rescale a raw OneFS value into the unit its metric name claims. Omitted means pass-through.
  • powerscale_node_hardware_info — an info gauge (always 1) carrying each node's product, series and hwgen. It explains the most confusing thing about running against a virtual cluster: a hypervisor exposes no physical sensors, so the fan, temperature and power-supply metrics are structurally absent. A node counts as virtual on either marker — series="virtual_series" or a hwgen naming the hypervisor (VMware); the OneFS simulator reports both. The exporter also logs the reason once per cluster, naming the affected metrics; a physical cluster where only some nodes go silent gets a different message that does not call them virtual. See docs/troubleshooting.md.

Docs

  • Each dashboard section in docs/dashboards.md now carries a screenshot.

[0.16.0] - 2026-08-01

Added

  • HEALTHCHECK added to the published Docker image, checking /livez. See ADR-0006.

[0.15.0] - 2026-08-01

Added

  • /livez and /readyz: probe endpoints that always answer 200, with no dependency on cluster reachability or the collection cycle. See ADR-0005.

Changed

  • /health always answers 200, never 503, and its body is now JSON (clusters: [{cluster, ok, last_scrape, err}]) instead of plain text. See ADR-0005. Breaking: anything parsing the old plain-text body or gating on the old 503 status needs updating.
  • The chart's default livenessProbe/readinessProbe now point at /livez//readyz instead of /health.

[0.14.0] - 2026-07-13

Added

  • OneFS license status & expiry metrics — two best-effort gauges derived from platform/N/license/licenses: powerscale_license_expiration_timestamp_seconds (Unix-seconds expiry per feature; 0 for perpetual or unlicensed features) and powerscale_license_active{status} (1 when the feature is Licensed/Activated/Evaluation, else 0, carrying the raw OneFS status as a label). docs/metrics.md includes an expiry alert example. (#34, #35)
  • OneFS storage-pool capacity metrics — per-pool/tier capacity labelled pool and type (nodepool | tier): aggregate powerscale_storagepool_{total,used,available}_capacity_bytes plus the media split powerscale_storagepool_{ssd,hdd}_{total,used,available}_capacity_bytes. (#33, #36)
  • OneFS per-workload performance metrics — dataset-dependent per-workload series from the performance dataset: powerscale_workload_operations_per_second, powerscale_workload_{in,out}_bytes_per_second, and powerscale_workload_cpu_microseconds_per_second, labelled by the curated workload identity dimensions (node, zone, protocol, username, system_name, job_type). (#32, #37)
  • Grafana dashboards for the new metrics — a Licensing row (status table + days-to-expiry) on powerscale-overview plus min-days-to-expiry and expired-count license stats on powerscale-capacity-sla; a Storage Pools capacity row (aggregate + SSD/HDD) on powerscale-capacity-sla; and a new powerscale-workloads board (per-workload ops/throughput/CPU with datasource/cluster/zone/protocol/username template variables). Documented in docs/dashboards.md. (#38)

0.13.0 - 2026-07-13

Added

  • Env-driven TLS verification skip (PSCALE1_SKIP_CERTIFICATE) — the per-cluster insecureSkipVerify setting now accepts either a native YAML boolean or a ${VAR} environment reference (e.g. ${PSCALE1_SKIP_CERTIFICATE}), resolved at startup, matching the existing ${PSCALE1_*} pattern. Wired into config.yaml, docker-compose.yml, and .env.example. (#30)

Fixed

  • OneFS cache stat keys — restored the node.ifs. namespace prefix on the six node.ifs.cache.l{1,2,3}.data.read.{hit,miss} keys. Because platform/1/statistics/current is an all-or-nothing batch, the previously invalid keys had been failing the entire request and dropping all current-statistics metrics (CPU, capacity, memory, disk) — not just the cache series. Added unit and end-to-end test coverage so a dropped prefix cannot silently regress. (#30)

Changed

  • Documented the full read-only OneFS privilege set the collectors require: ISI_PRIV_STATISTICS, ISI_PRIV_QUOTA, ISI_PRIV_DEVICES, ISI_PRIV_EVENT, ISI_PRIV_SNAPSHOT, ISI_PRIV_SYNCIQ, ISI_PRIV_SMB, ISI_PRIV_NFS. (#30)
  • Corrected the metrics and dashboard docs' cache failure-mode description (one invalid key fails the whole statistics/current batch — not a silent per-key skip) and fixed a broken docs anchor.

0.12.5 - 2026-07-12

Changed

  • Update dependencies and the Go toolchain to 1.26.5 (builder image bumped to golang:1.26.5).

0.12.4 - 2026-07-03

Added

  • pscale_exporter_build_info metric — an exporter-level gauge (constant 1) exposing the running exporter version and goversion as labels, so a scrape reveals exactly which build is serving /metrics. Standard Prometheus build-info pattern.

0.12.3 - 2026-07-01

Changed

  • Docs: document how to handle special characters in the monitoring password.
  • Docs: use the brand icon as the MkDocs favicon and logo.

0.12.2 - 2026-06-20

Changed

  • CI: migrate to the fjacquet/ci reusable (make-based) workflows; the security job is now advisory to match the central default.

0.12.1 - 2026-06-16

Added

  • Helm chart with lockstep publishing alongside releases.

0.12.0 - 2026-06-14

Added

  • Node Exporter Full (1860) Grafana dashboard.

Changed

  • BREAKING: the canonical metrics port is now 9444.

0.11.0 - 2026-06-14

Changed

  • Polish the Grafana dashboards: RED/USE restructure with per-panel descriptions.

0.10.3 - 2026-06-14

Changed

  • Docs: add an ADR recording the snapshot model, stat-key table, and metric naming.

0.10.2 - 2026-06-14

Added

  • Windows (amd64) binary and .zip archive to the release artifacts.

0.10.1 - 2026-06-14

Fixed

  • Parse the OneFS block-based dedupe-summary into bytes.
  • Parse drive_id and transfer rates from OneFS summary/drive.
  • Read operation_rate from OneFS summary/client.
  • Use the OneFS 9.14.0-documented endpoint versions.

Changed

  • Align node parsing to OneFS 9.14 (drop the dead smartfail.state branch) and drop obsolete provisional caveats now that the schemas are validated.

0.10.0 - 2026-06-13

Changed

  • Change the default metrics port from 2112 to 2115.

0.9.1 - 2026-06-12

Fixed

  • Docker: copy the CA bundle from the builder stage instead of apk add.

0.9.0 - 2026-06-12

Added

  • Load .env natively at startup (no-override semantics).

0.8.0 - 2026-06-11

Added

  • Expand ${ENV} references in username; parameterize the Compose stack via PSCALE1_* variables.

Changed

  • Align .gitignore with the family canonical template.

0.7.0 - 2026-06-11

Added

  • --trace flag and --once --debug sample dump for live-cluster validation.

Changed

  • CI: backport workflow hardening from obs_exporter.

0.6.0 - 2026-06-10

Added

  • Remote-debug observability — designed for diagnosing clusters we never have direct access to:
    • --debug now logs every OneFS request (full URL, parameter count, response size, duration), a per-cluster inventory parse summary (node/quota/sensor/policy/event counts), and a statistics summary naming any curated stat keys the cluster did not return.
    • Parse failures (required and best-effort endpoints) log a bounded payload snippet showing what the API actually returned.
    • The lenient sensor decoders no longer fall back silently: an unrecognized sensors shape or unparseable sensor value is traced at debug level.
    • New --dump-dir DIR flag writes every raw API response verbatim to DIR/<cluster>/<endpoint>.json (0600; bodies carry no credentials) — operators ship the directory back and the files drop straight into testdata/ as fixtures.
  • New Troubleshooting docs page covering the debug workflow.

0.5.4 - 2026-06-10

Fixed

  • Nodes-payload parsing now matches live OneFS 9.x clusters (validated against a OneFS 9.13 virtual PowerScale), while remaining compatible with the older shapes: sensors may be an object wrapping a nested sensors array, state.smartfail may carry per-condition booleans (smartfailed) instead of a state string, and empty drive bays ("present": false) are no longer counted as drives.

Changed

  • Docs: the read-only collection role also needs ISI_PRIV_DEVICES read access — the cluster-nodes inventory endpoint refuses without it.

0.5.3 - 2026-06-05

Changed

  • Bump goreleaser/goreleaser-action v6.4.0 → v7.2.2 (Node 24 runtime), clearing the GitHub Actions Node 20 deprecation warning. No change to how the action is invoked.

0.5.2 - 2026-06-05

Changed

  • Homebrew cask is now macOS-only. Builds and archives are split by OS so the cask references a darwin-only archive; the generated cask no longer emits unusable linux URLs (Homebrew casks don't run on Linux). The GitHub Release still ships all four archives + SBOMs, and the GHCR image is unchanged. Docs clarified accordingly.

0.5.1 - 2026-06-05

The v0.5.0 tag was cut first but its release run failed before publishing anything (a dockers_v2 COPY path bug); v0.5.1 is the first published release of this work.

Added

  • GoReleaser release pipeline (.goreleaser.yaml). A single tool now produces the cross-platform binaries (linux/darwin × amd64/arm64), tar.gz archives, a checksums.txt, a per-archive CycloneDX SBOM (syft), and the multi-arch GHCR image — replacing the bespoke make release loop and the separate docker/build-push-action job.
  • Homebrew cask distribution via github.com/fjacquet/homebrew-tap: brew install fjacquet/tap/pscale_exporter. The post-install hook strips the macOS quarantine bit so the unsigned binary runs without a Gatekeeper prompt.
  • LICENSE file (Apache-2.0). The README already declared Apache-2.0 but the file was missing; it is now present and bundled into every release archive.
  • Changelog (this file) and an Architecture Decision Record documenting the release and supply-chain design (ADR-0001).

Changed

  • All GitHub Actions are pinned to full commit SHAs (with a # vX.Y.Z comment) across ci.yml, release.yml, and docs.yml. The Semgrep CI container is pinned by image digest. This closes the mutable-tag supply-chain vector; Dependabot can still propose bumps.
  • Release is GoReleaser-driven. make release now runs goreleaser release --clean; make release-snapshot runs the full pipeline locally minus publish. make tools installs a pinned GoReleaser.
  • Image SBOM + provenance are still attached to the GHCR image — now produced by GoReleaser's dockers_v2 builder (both on by default) instead of build-push-action.
  • Go toolchain bumped to 1.26.4 — the Dockerfile builder image now matches the go 1.26.4 directive already in go.mod.

0.4.2 - 2026-06-05

  • Baseline prior to the release-pipeline rework. See the GitHub releases for earlier history.