Commit Graph

15 Commits

Author SHA1 Message Date
Pratik Mankawde
10e71224f3 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics 2026-07-20 17:56:02 +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
4908b82077 Merge branch 'pratik/otel-phase6-statsd' into pratik/otel-phase7-native-metrics 2026-07-20 12:19:28 +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
0a373f631c fix(telemetry): resolve otel-naming and UBSAN CI failures
- Add job_type to otel-naming builtins (standard Prometheus label for
  job-queue metrics used in node-health dashboard)
- Add OpenTelemetry SDK to UBSAN suppressions (intentional unsigned
  integer overflow in attributemap_hash.h hash computation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-08 15:25:59 +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