Commit Graph

13 Commits

Author SHA1 Message Date
Pratik Mankawde
f8e0a19b9f fix(telemetry): correct the childSpan doc examples and make Rule D tests real
Review feedback on the RPC integration PR.

The childSpan examples could not work as written. childSpan() takes its parent
from the ambient context and uses impl_ only as a liveness gate, so an unscoped
SpanGuard parent produced two siblings rather than a parent and child. The parent
is now a ScopedSpanGuard, the child no longer reuses the parent's name, and the
examples pass a full dotted constant because childSpan() takes the name verbatim.

Five of the ten Rule D tests could not fail. Four passed an empty L1 key set,
which makes the rule skip validation altogether; the fifth asserted an empty
result against an escaped-quote selector that extracted no labels at all. Each
now passes a nonempty L1 set and carries a known-bad label in the same
expression, so it asserts both that the intended labels are accepted and that
Rule D ran. Verified by disabling the rule: the old tests stay green, the new
ones all fail.

Span kind is not fixed here. categoryToSpanKind and the span factories belong to
the telemetry library, so the role parameter is routed to that branch, and the
two call sites here follow once it exists.
2026-09-07 13:25:22 +01:00
Pratik Mankawde
8d83751011 ci(telemetry): recognize external-infra identity labels in otel-naming Rule D
xrpl_branch and xrpl_node_role are stamped by the perf-iac harness --
infrastructure outside this repo's OTel code -- so they have no L1
(*SpanNames.h), L2 (collector config), or L6 (MetricsRegistry.cpp) source
Rule D can derive them from. Unlike the generic builtins set (Prometheus/
Grafana mechanics every OTel setup has), these are repo-specific and
narrow, so they get their own EXTERNAL_INFRA_LABELS constant: a visible,
documented, deliberately narrow exception to the 'no hardcoded allowlist'
design principle, not a silent workaround. Add test coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 17:54:30 +01:00
Pratik Mankawde
c5f419121f Revert "ci(telemetry): recognize perf-iac identity labels in otel-naming Rule D"
This reverts commit 48747bab4c.
2026-07-20 17:50:19 +01:00
Pratik Mankawde
48747bab4c ci(telemetry): recognize perf-iac identity labels in otel-naming Rule D
xrpl_branch and xrpl_node_role are collector/infra-injected resource
labels used by perf-iac dashboards to identify the build under test and
its role in the perf cluster. They have no L1 span-attribute source or
L6 native-metric-label source (like the existing job/instance/job_type
builtins), so Rule D flagged them across every perf-iac dashboard.
Register them in the builtins set, matching the existing pattern for
infra-level dashboard labels. Add test coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 17:49:44 +01:00
Pratik Mankawde
57efffff44 ci(telemetry): teach otel-naming checker the SpanGuard::rootSpan factory
rootSpan has the same (cat, prefix, name) signature as span(), so its
prefix/name arguments must be *SpanNames.h constants under Rule F/H. Add
rootSpan to the CALLSITE regex and CONSTANT_ARG_POSITIONS ({1,2}), update
the enumerating docstrings/README, and add two regression tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 22:12:42 +01:00
Pratik Mankawde
282aec4367 ci: Fix OTel naming check blind spot for dotted span attrs
Rule A silently missed a dotted span attribute (xrpl.ledger.hash) because of
two interacting bugs:

1. attr_keys_from_header resolved each constant via a flat global symbol table
   keyed by bare name, so a later header defining a same-named constant (e.g.
   consensus attr::ledgerHash = "ledger_hash") clobbered the base header's
   attr::ledgerHash = "xrpl.ledger.hash", erasing the real dotted key from L1.
   Now each constant is resolved against its own header (the global table only
   seeds seg::/join() cross-file references); using-re-exports still resolve
   globally.

2. derive_dotted_resource_keys allowlisted any dotted key declared in the base
   SpanNames.h. Now it allowlists only the keys actually passed to
   Resource::Create() in Telemetry.cpp (semconv service.* + the attr:: constants
   set there, e.g. xrpl.network.*). A dotted key declared in a header but never
   set as a resource attr is a Rule-A violation.

Adds 4 regression tests (collision, using-re-export, allowlist scope, brace
matching). No allowlist exception is added — the check now catches the
violation so the offending code can be fixed.
2026-06-11 22:41:08 +01:00
Pratik Mankawde
2644179a42 ci: Rule C — read Grafana tempo datasource, enforce span-scope filter tags
Rule C was reading docker/telemetry/tempo.yaml (the Tempo server config), which
has no filter tags, so it always SKIPped — L3 was silently unenforced. The
trace-search filter tags actually live in the Grafana datasource provisioning
file (docker/telemetry/grafana/provisioning/datasources/tempo.yaml) as
search.filters[].{tag,scope}. Point Rule C there (server file as fallback),
pair each tag with its scope, validate only span-scope tags against L1 (resource/
intrinsic tags like service.*/name/status/duration are exempt), and strip the
TraceQL span. prefix.

On phase-9 this turns "SKIP: C" into "OK: C: 24 tempo span-filter tags all in
L1" — L3 is now genuinely guarded. Adds a RuleCTempo test class (4 cases:
span-tag-not-in-L1 flagged, span-tags-pass, resource/intrinsic ignored, skip
when datasource absent). 83 tests total.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 19:28:24 +01:00
Pratik Mankawde
6c62bfd2ad ci: Rule D — strip TraceQL scope prefix, recognize native-metric labels (L6)
Phase 9 surfaced two Rule D gaps (false positives, not data errors):
- TraceQL `span.<attr>` / `resource.<attr>` references: the bare attribute is
  in L1, but the scope-prefixed form was flagged. Now strip the
  span./resource./event./link/instrumentation_scope. prefix before the L1
  lookup.
- Native OTel metric labels (e.g. `job_type`, `reason`) emitted by
  MetricsRegistry are valid dashboard labels but are not span attributes. Add
  an L6 source: parse `Add(.., {{"label", ...}})` instrument calls and accept
  those label keys alongside L1 and builtins.

Verified against phase-9's real dashboards: 6 prior false positives -> 0.
79 tests (7 new for span-prefix stripping and metric-label extraction).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 19:16:56 +01:00
Pratik Mankawde
6ec60ff52c ci: Add __name__ to OTel naming check Rule D builtins
Rule D (dashboard PromQL labels must exist in L1) flagged `__name__` once the
phase-7 system-*.json dashboards started using `sum by (le, __name__)`.
`__name__` is the Prometheus reserved label for the metric name itself — a
builtin, not a span attribute. Add it to the builtin allowlist and cover it
with a test. (Earlier dashboards only used `__name__` inside `{__name__=~...}`
matchers, which the label regex did not extract, so this surfaced only now.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 18:34:19 +01:00
Pratik Mankawde
59030e5d61 fixed a rule in otel naming check file. added tests for it.
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-06-11 18:21:42 +01:00
Pratik Mankawde
4d044e6254 ci: Harden OTel naming check — unconditional Rule F, test exemption, Rule H
Three robustness fixes to check_otel_naming.py, all on phase-1c where the
script lives:

- Rule F now runs UNCONDITIONALLY. It is a purely syntactic check on the
  call-sites and does not need the L1 key set, so code that calls
  SpanGuard::span/setAttribute directly without ever defining a *SpanNames.h
  is still caught (previously it was silently skipped when no header existed).
- Exempt test files from Rule F (tests pass arbitrary literal keys to exercise
  the API). The call-site matcher now requires a SpanGuard/`.`/`->` receiver,
  so std::span and bare declarations no longer false-positive.
- Add Rule H (warning, non-fatal): a namespace-qualified constant used at a
  telemetry call-site but not defined in any *SpanNames.h is flagged, catching
  constants defined in-place instead of in the proper header. Bare locals and
  std:: names are not warned to avoid noise.

SpanGuard.h / Telemetry.h @code examples updated to reference constants that
exist on this branch. README documents the new behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:10:08 +01:00
Pratik Mankawde
ca7282479f ci: Enforce lower_snake_case attribute keys in OTel naming check
Add Rule G to check_otel_naming.py: every span-attribute key must be
lower_snake_case (^[a-z][a-z0-9_]*$ per dot-separated segment). This catches
camelCase, UPPERCASE, and spaces in keys, which the structural (dotted) and
source (literal) rules did not. Document it in the script README and
CONTRIBUTING.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 15:33:08 +01:00
Pratik Mankawde
134a24d5bc ci: Add OpenTelemetry span-attribute naming check (phase 1c)
Add check_otel_naming.py and wire it into on-pr.yml so every PR validates
that span-attribute names stay consistent across the code, collector, Tempo,
dashboards, and docs.

- The valid key set is derived dynamically from the *SpanNames.h constants and
  the resource attributes the code registers in Telemetry.cpp — no hardcoded
  allowlist to drift.
- Each rule is presence-gated: it runs only when the file it needs is in the
  tree, so the check is correct whether telemetry changes land in one PR or
  several (the collector/Tempo/dashboard/runbook layers arrive in later phases).
- Rule A flags dotted span-attribute keys; Rule F flags string-literal
  attribute keys and span-name arguments (values may be runtime data).
- stdlib-only, mirroring the levelization check (bare `python`, no pip step).
- Telemetry.h / SpanGuard.h @code examples now use *SpanNames.h constants so
  the strict literal check passes.
- CONTRIBUTING.md documents the check and how to run it locally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 15:26:38 +01:00