Skip to content

docs: document exported metric names and coverage gaps - #2111

Open
HayimShaul wants to merge 1 commit into
mainfrom
1745_document_token_sdk_metrics_and_gaps
Open

docs: document exported metric names and coverage gaps#2111
HayimShaul wants to merge 1 commit into
mainfrom
1745_document_token_sdk_metrics_and_gaps

Conversation

@HayimShaul

@HayimShaul HayimShaul commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #1745

Problem

Panurus exports 54 metrics and documented none of them under the name Prometheus actually serves.

Nothing in the SDK spells those names out. The fully-qualified name is assembled at registration time
from the Go package of the caller, and the TMS-scoped provider in token/core/common/metrics adds a
stack frame — so metrics created through it are exported under that package, not their own. Docs
written from the bare Name field therefore list names no query matches. That is why #1749 was closed.

What this PR does

1. Documents the exported namesdocs/development/metrics.md: how a name is derived, one table
per subsystem (exported name, type, labels, meaning, source), PromQL examples, and a ranked
## Coverage gaps section on what a node still cannot report.

2. Guards the pagetoken/services/metricsdoc instantiates all 16 metrics constructors the way
production wires them, reads the names back out of a Prometheus registry, and checks them against
testdata/metrics.golden and against the page in both directions. It also pins the wiring the names
depend on: the two token drivers are asserted to be the only places a TMS-scoped provider is built, so
dropping that wrapper fails the build instead of silently renaming 21 metrics.

3. Adds a Grafana dashboarddocs/monitoring/grafana/token-sdk.json, revived from #1749 with the
correct names, plus a row for the four identity_* metrics that had no panel. All 54 metrics covered,
19 panels over 9 rows. Its queries are guarded too: every metric must be registered, every name must
carry its package prefix, every label filtered or grouped on must be declared, every $variable must
exist. These are the failures Grafana renders as "No data" rather than as an error.

4. Corrects docs/drivers/metrics.md, which listed declared names as if they were queryable, and
makes docs/development/monitoring.md the entry point.

NewMetrics/NewClientMetrics are exported in the auditor, certification and Fabric-X queue packages
so the guard can build their instrumentation without constructing the surrounding service.

Verification

  • All 54 names read out of a live Prometheus registry, not transcribed from source.
  • Each guard check proven to fire by mutating the source: renamed metric, dropped TMS wrapper, stale
    wiring entry, truncated name in the page, absent label, undeclared variable.
  • Run against docs: add Token SDK metrics reference and identify coverage gaps #1749's original dashboard, the query guard reports 53 findings — that PR's defect would
    have failed the build.
  • make checks and make lint exit 0; package green under -count=3 -race -shuffle=on.

Known limitation

The dashboard guard checks names, not rendering. PromQL is not parsed (it would need a new
dependency, the exprs contain Grafana variables that are not valid PromQL, and it is the one failure
mode Grafana surfaces itself), and the file has not been imported into a live Grafana against a live
Prometheus — so panel presentation is unverified.

Follow-up

The metric-hygiene items in the gap analysis (package attribution, stuttering names, missing
network/channel/namespace labels) all change exported names, so they belong in a single
deliberate follow-up with a release note rather than here.

@HayimShaul HayimShaul added this to the Q3/26 milestone Aug 3, 2026
@HayimShaul HayimShaul added the documentation Improvements or additions to documentation label Aug 3, 2026
@HayimShaul HayimShaul self-assigned this Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

📊 Token Validation Benchmark

Comparison of this PR against the base branch. 🟢 improvement · 🔴 regression · ➖ within ±1.0% noise.

Variant Benchmark Params Workers TPS (base → PR) Δ TPS
csp BenchmarkAPIGRPC f=1, nc=4, w=token-validation-service 4 117 → 117 ➖ -0.1%
csp BenchmarkLocalTokenValidation out-tokens=2in-tokens=2 4 170 → 172 ➖ +0.8%
ipa BenchmarkAPIGRPC f=1, nc=4, w=token-validation-service 4 90 → 91 ➖ +0.1%
ipa BenchmarkLocalTokenValidation out-tokens=2in-tokens=2 4 76 → 76 ➖ +0.2%

@AkramBitar
AkramBitar force-pushed the 1745_document_token_sdk_metrics_and_gaps branch from 27da803 to 5dc2e0a Compare August 3, 2026 15:00
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

📊 Token Validation Benchmark

Comparison of this PR against the base branch. 🟢 improvement · 🔴 regression · ➖ within ±1.0% noise.

Variant Benchmark Params Workers TPS (base → PR) Δ TPS
csp BenchmarkAPIGRPC f=1, nc=4, w=token-validation-service 4 117 → 117 ➖ +0.1%
csp BenchmarkLocalTokenValidation out-tokens=2in-tokens=2 4 104 → 104 ➖ +0.0%
ipa BenchmarkAPIGRPC f=1, nc=4, w=token-validation-service 4 70 → 70 ➖ +0.0%
ipa BenchmarkLocalTokenValidation out-tokens=2in-tokens=2 4 81 → 81 ➖ +0.2%

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

📊 Token Validation Benchmark

Comparison of this PR against the base branch. 🟢 improvement · 🔴 regression · ➖ within ±1.0% noise.

Variant Benchmark Params Workers TPS (base → PR) Δ TPS
csp BenchmarkAPIGRPC f=1, nc=4, w=token-validation-service 4 117 → 118 ➖ +0.1%
csp BenchmarkLocalTokenValidation out-tokens=2in-tokens=2 4 103 → 104 ➖ +0.2%
ipa BenchmarkAPIGRPC f=1, nc=4, w=token-validation-service 4 78 → 78 ➖ -0.0%
ipa BenchmarkLocalTokenValidation out-tokens=2in-tokens=2 4 76 → 76 ➖ -0.2%

@AkramBitar
AkramBitar marked this pull request as ready for review August 6, 2026 07:35

@AkramBitar AkramBitar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the docs against the code: the content is accurate. Every metric name, label value and scope claim matches production wiring today (traced the NewTMSProvider wrapper in token/core/{fabtoken,zkatdlog}/v1/driver/driver.go through ws.go into identity/role/idemix, and the DI-container providers for ttx / auditor / sherdlock / certifier / fabricx). All 15 files that declare metric opts are covered by the group list, the 54 table rows match the 54 golden lines, the monitoring.md URL change fixes a real 404, and go vet / gofmt / goimports / misspell / golangci-lint plus go test -count=3 -race -shuffle=on are clean.

The comments below are all about the new reference_test.go guard rather than the documentation. Two of them I'd suggest addressing before merge:

  • The guard cannot detect the one change that would actually invalidate the whole page (the scope field is unverified metadata).
  • The unconditional histogram-suffix trim will fail on a correct page as soon as someone adds a metric whose name ends in _count, _sum or _bucket.

The remaining four are polish — confusing failure output, a gap in the reverse check, a dead field, and a global that is only safe while the tests stay sequential.

Comment thread token/services/metricsdoc/reference_test.go
Comment thread token/services/metricsdoc/reference_test.go Outdated
Comment thread token/services/metricsdoc/reference_test.go Outdated
Comment thread token/services/metricsdoc/reference_test.go Outdated
Comment thread token/services/metricsdoc/reference_test.go Outdated
Comment thread token/services/metricsdoc/reference_test.go
@AkramBitar

Copy link
Copy Markdown
Contributor

Follow-up: bring back token-sdk.json, with the names this PR pins.

#1749 shipped a Grafana dashboard next to its metrics doc — https://github.com/LFDT-Panurus/panurus/pull/1749/files (permalink) — 17 panels over 9 rows, with network/channel/namespace/method template variables. The panel layout and label filters are sound; the one defect is the one I flagged there: #1749 (comment) — every expr used the bare option name from the Go source, so no query matched anything in a real Prometheus.

That PR closed unmerged, and docs/monitoring/ is in neither this PR nor main, so the dashboard went with it. Worth reviving, because this PR's testdata/metrics.golden is exactly the input needed to fix it — the substitution is mechanical:

expr in #1749's dashboard Correct name
issue_service_operations_total panurus_core_common_metrics_issue_service_operations_total
endorsed_transactions panurus_services_ttx_endorsed_transactions
finality_listener_confirmed_total panurus_services_ttx_finality_finality_listener_confirmed_total
ttx_envelope_sent_total panurus_services_utils_json_session_ttx_envelope_sent_total
auditor_audit_duration_seconds panurus_services_auditor_auditor_audit_duration_seconds
unspent_tokens_invocations panurus_services_selector_sherdlock_unspent_tokens_invocations
certified_tokens panurus_services_certifier_interactive_certified_tokens
cache_level panurus_core_common_metrics_cache_level
finality_queue_pending_events panurus_services_network_fabricx_finality_queue_finality_queue_pending_events

Two things beyond the rename:

Do we want the dashboard in this PR, or as a follow-up? I have no strong preference. Adding it here keeps the dashboard and the names it depends on in one changeset, which is nice for review — but this PR is already sizeable and purely documentation, so a separate PR is equally reasonable. A follow-up would need to be based on this branch rather than main, since the metricsdoc guard package doesn't exist on main yet. Happy either way — let me know which you prefer and I can open an issue to track it.

@HayimShaul
HayimShaul force-pushed the 1745_document_token_sdk_metrics_and_gaps branch from 5dc2e0a to 6a96c03 Compare August 6, 2026 11:22
@AkramBitar
AkramBitar force-pushed the 1745_document_token_sdk_metrics_and_gaps branch from ccb3c91 to 83d60d7 Compare August 11, 2026 10:39
@AkramBitar
AkramBitar dismissed their stale review August 11, 2026 13:55

Dismissing my own review: all six findings are fixed in 83d60d7 and each thread is answered and resolved.

Not converting this to an approval on purpose — I wrote most of the code now (the guard hardening and the Grafana dashboard), so approving it would be a self-review. This PR still wants a fresh pair of eyes from another maintainer.

@AkramBitar

Copy link
Copy Markdown
Contributor

@HayimShaul will be out of the office for the next two weeks. I'll be covering for him during that time, so I won't be able to continue reviewing this PR. Someone else will need to take over the review.

@AkramBitar AkramBitar self-assigned this Aug 11, 2026
@AkramBitar
AkramBitar force-pushed the 1745_document_token_sdk_metrics_and_gaps branch from 83d60d7 to 4e4c4a0 Compare August 11, 2026 15:08
@HayimShaul
HayimShaul force-pushed the 1745_document_token_sdk_metrics_and_gaps branch from 4e4c4a0 to e0c7c29 Compare August 18, 2026 09:28
The SDK never spells out the metric names Prometheus exports. The
fully-qualified name is assembled at registration time from the Go package
of the caller, and the TMS-scoped provider in token/core/common/metrics adds
a stack frame, so metrics created through it are exported under that
package rather than their own. Documentation written from the bare Name
field of the options therefore lists names no query matches.

Add docs/development/metrics.md: the derivation rules, every metric under
the name Prometheus actually serves, its type, labels, meaning and source,
example queries, and a ranked analysis of what a node still cannot report.

Guard the page with token/services/metricsdoc, which instantiates every
metrics constructor the way production wires it, reads the resulting names
back out of a Prometheus registry, and compares them against a golden file
and against the page itself. Renaming, adding or relocating a metric fails
the test until the documentation is updated.

Which provider a constructor receives is as much a part of the exported
name as the opts are, so it is checked rather than assumed. The token
drivers are pinned as the only files in the repository that build a
TMS-scoped provider, and as building it from the container's provider, so
the scope of each group follows by exhaustion; dropping the wrapper fails
the test instead of quietly renaming twenty-one metrics. Every production
call site a group claims must also still contain that call.

Two ways the guard could reject a correct page are fixed: the PromQL suffix
fold now applies only onto registered histogram families, so a metric whose
own name ends in _count, _sum or _bucket survives it; and the reverse check
uses an explicit prose allowlist rather than accepting any documented name
that is a prefix of a registered one, which had let truncations through.
Each group is instantiated against its own provider and registry, so the
declared and exported metrics cannot be mispaired by the provider's
deduplication, and a genuine clash is reported by name.

Add the Grafana overview dashboard, revived from #1749 with the names this
change pins. That dashboard closed unmerged because every one of its 51
panel queries and 4 variable queries named the bare Name field from the Go
source and so matched nothing. The substitution here is derived from the
golden file rather than transcribed. A row is added for the four identity
signer-resolution metrics that had no panel, so every exported metric is
now covered.

The dashboard's queries are guarded too. Each check covers a failure
Grafana does not report as an error - it renders "No data", which is
indistinguishable from an idle node: every metric named must be registered,
every name must carry its package prefix, every label filtered or grouped
on must be declared by that metric, and every variable must be a Grafana
built-in or declared by the dashboard. Run against #1749's original file,
the guard reports 53 findings. PromQL syntax is deliberately not parsed: it
would need a new dependency, the exprs contain Grafana variables that are
not valid PromQL, and it is the one failure mode Grafana surfaces itself.
The guard checks names, not rendering; the file has not been imported into
a live Grafana, so panel presentation is unverified.

Export NewMetrics/NewClientMetrics in the auditor, certification and
Fabric-X queue packages so the guard can build their instrumentation
without constructing the surrounding service.

Correct docs/drivers/metrics.md, which listed declared names as if they
were queryable, and make docs/development/monitoring.md the entry point.

Signed-off-by: Hayim.Shaul@ibm.com <hayimsha@fhe03.vpc.cloud9.ibm.com>
Signed-off-by: AkramBitar <akram@il.ibm.com>
Signed-off-by: Hayim.Shaul@ibm.com <hayimsha@fhe03.vpc.cloud9.ibm.com>
@AkramBitar
AkramBitar force-pushed the 1745_document_token_sdk_metrics_and_gaps branch from e0c7c29 to 086b1d4 Compare August 18, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document Token SDK Monitoring Metrics and Identify Missing Metrics

2 participants