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
_totalsuffix, 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_bytesfromusage.applogical(#54). Always emitted, as 0 when the quota API version does not return the field.powerscale_quota_usage_bytesis 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) andpowerscale_protocol_latency_stage_microseconds{stage}(protocol API v26; stagesauth,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 schemasnow 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 (
godirective, 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/net0.59.0 -> 0.60.0,golang.org/x/sys0.48.0 -> 0.49.0,golang.org/x/sync0.23.0 -> 0.24.0,google.golang.org/grpc1.83.2 -> 1.84.0,prometheus/client_golang1.24.1 -> 1.25.0,grpc-gateway/v22.30.0 -> 2.31.0,go.opentelemetry.io/proto/otlp1.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-securityreusable workflow fromfjacquet/ci.
Changed
- Go 1.26.6 -> 1.27.1 (
godirective ingo.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/gopowerscale1.22.0 -> 1.23.0, OpenTelemetry 1.46.0 -> 1.47.0,prometheus/common0.71.0 -> 0.72.0. google.golang.org/grpckept at 1.83.2: 1.84.0 is affected by GO-2026-6443.
[0.19.2] - 2026-09-13
Security
google.golang.org/grpc1.83.0 -> 1.83.2, fixing GHSA-vp52-pcj8-j9qc and GHSA-2v4p-qf9q-27wj (HIGH), pulled in with anotel1.45.0 -> 1.46.0 refresh.
0.19.1 - 2026-08-19
Security
- Go dependencies refreshed with
go get -ufor security fixes:logrus1.9.4 -> 1.10.0,grpc-gateway/v22.29.0 -> 2.30.0,golang.org/x/net0.57.0 -> 0.58.0,golang.org/x/text0.40.0 -> 0.41.0,google.golang.org/protobuf1.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/urlquadratic-complexity resolvePath,html/templateJS-context tracking, and a third fixed alongside them). Applies to thego.modgodirective and the from-sourceDockerfilebuild 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), viafoldersFromFilesStructure: true. Adding a board is now a copy into the right directory. Titles lose the redundantPowerScale /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
powerscaletag — a new tagged board joins every menu automatically — withincludeVars/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}.avgandnode.cpu.{idle,sys,user}.avgin tenths of a percent (idle+user+syssums to 1000), and the raw value was passed straight through to metrics named_percent— so an idle cluster read974instead of97.4, pinning the Grafana CPU panels (unit: percent,max: 100) at full scale. The six keys now carry"divisor": 10instatisticsKeys.json. Found by validating a live cluster againstdocs/metrics.md; the mock fixture had used a percent-looking12.5where a real cluster sends125, so the tests agreed with the bug.
Added
${VAR:-default}fallbacks inconfig.yamlenv 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 strayPSCALE1_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 shippedconfig.yamlnow usesinsecureSkipVerify: "${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.jsonrows accept an optionaldivisorto 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'sproduct,seriesandhwgen. 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 ahwgennaming 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. Seedocs/troubleshooting.md.
Docs
- Each dashboard section in
docs/dashboards.mdnow carries a screenshot.
[0.16.0] - 2026-08-01
Added
HEALTHCHECKadded to the published Docker image, checking/livez. See ADR-0006.
[0.15.0] - 2026-08-01
Added
/livezand/readyz: probe endpoints that always answer 200, with no dependency on cluster reachability or the collection cycle. See ADR-0005.
Changed
/healthalways 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/readinessProbenow point at/livez//readyzinstead 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;0for perpetual or unlicensed features) andpowerscale_license_active{status}(1when the feature is Licensed/Activated/Evaluation, else0, carrying the raw OneFS status as a label).docs/metrics.mdincludes an expiry alert example. (#34, #35) - OneFS storage-pool capacity metrics — per-pool/tier capacity labelled
poolandtype(nodepool|tier): aggregatepowerscale_storagepool_{total,used,available}_capacity_bytesplus the media splitpowerscale_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, andpowerscale_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-overviewplus min-days-to-expiry and expired-count license stats onpowerscale-capacity-sla; a Storage Pools capacity row (aggregate + SSD/HDD) onpowerscale-capacity-sla; and a newpowerscale-workloadsboard (per-workload ops/throughput/CPU with datasource/cluster/zone/protocol/username template variables). Documented indocs/dashboards.md. (#38)
0.13.0 - 2026-07-13
Added
- Env-driven TLS verification skip (
PSCALE1_SKIP_CERTIFICATE) — the per-clusterinsecureSkipVerifysetting 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 intoconfig.yaml,docker-compose.yml, and.env.example. (#30)
Fixed
- OneFS cache stat keys — restored the
node.ifs.namespace prefix on the sixnode.ifs.cache.l{1,2,3}.data.read.{hit,miss}keys. Becauseplatform/1/statistics/currentis 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/currentbatch — 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_infometric — an exporter-level gauge (constant1) exposing the running exporterversionandgoversionas 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/cireusable (make-based) workflows; thesecurityjob 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
.ziparchive to the release artifacts.
0.10.1 - 2026-06-14
Fixed
- Parse the OneFS block-based dedupe-summary into bytes.
- Parse
drive_idand transfer rates from OneFSsummary/drive. - Read
operation_ratefrom OneFSsummary/client. - Use the OneFS 9.14.0-documented endpoint versions.
Changed
- Align node parsing to OneFS 9.14 (drop the dead
smartfail.statebranch) and drop obsolete provisional caveats now that the schemas are validated.
0.10.0 - 2026-06-13
Changed
- Change the default metrics port from
2112to2115.
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
.envnatively at startup (no-override semantics).
0.8.0 - 2026-06-11
Added
- Expand
${ENV}references inusername; parameterize the Compose stack viaPSCALE1_*variables.
Changed
- Align
.gitignorewith the family canonical template.
0.7.0 - 2026-06-11
Added
--traceflag and--once --debugsample 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:
--debugnow 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
sensorsshape or unparseable sensor value is traced at debug level. - New
--dump-dir DIRflag writes every raw API response verbatim toDIR/<cluster>/<endpoint>.json(0600; bodies carry no credentials) — operators ship the directory back and the files drop straight intotestdata/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:
sensorsmay be an object wrapping a nestedsensorsarray,state.smartfailmay 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_DEVICESread access — the cluster-nodes inventory endpoint refuses without it.
0.5.3 - 2026-06-05
Changed
- Bump
goreleaser/goreleaser-actionv6.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
linuxURLs (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.0tag was cut first but its release run failed before publishing anything (adockers_v2COPYpath bug);v0.5.1is 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.gzarchives, achecksums.txt, a per-archive CycloneDX SBOM (syft), and the multi-arch GHCR image — replacing the bespokemake releaseloop and the separatedocker/build-push-actionjob. - 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. LICENSEfile (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.Zcomment) acrossci.yml,release.yml, anddocs.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 releasenow runsgoreleaser release --clean;make release-snapshotruns the full pipeline locally minus publish.make toolsinstalls a pinned GoReleaser. - Image SBOM + provenance are still attached to the GHCR image — now produced by
GoReleaser's
dockers_v2builder (both on by default) instead ofbuild-push-action. - Go toolchain bumped to 1.26.4 — the
Dockerfilebuilder image now matches thego 1.26.4directive already ingo.mod.
0.4.2 - 2026-06-05
- Baseline prior to the release-pipeline rework. See the GitHub releases for earlier history.