◆ NFRGate / Rule Reference

T2 — Spans carry useful attributes

medium 🔍 traces · both

Each such span includes target service/host, operation name, and outcome (success/error) - not a bare unnamed span.

Python Implementation

T2: each span includes target service/host, operation name, and outcome
(success/error) — not a bare unnamed span. rubric_store/definitions/
traces.yaml tags this `both`; the static half checks the two cleanly
syntactic pieces: does start_as_current_span(...) get a name argument at
all, and does the span's own with-block call set_attribute(...) anywhere
(a proxy for "attributes beyond just a name are being set" — it can't
verify *which* attributes, e.g. that target-service specifically is one of
them, without semantic understanding of what was passed).

Java Implementation

T2 for Java: each span includes target service/host, operation name, and
outcome attributes — not a bare span. Not a straight port of the Python
version: Java's OTel API requires a name at span creation
(`tracer.spanBuilder("name").startSpan()` — there is no way to call
spanBuilder() without one), so the "bare unnamed span" failure mode Python
checks for structurally can't happen in Java. This rule is scoped to what
can actually vary: whether `.setAttribute(...)` is ever called on the
resulting span, checked presence-anywhere in the enclosing method (Java's
span isn't a Python-style single with-block the attribute call must nest
inside — it's commonly set after `startSpan()` returns, before or inside
the try-with-resources), same "presence-anywhere" tradeoff
has_nearby_timeout_call already makes for R1.

Go Implementation

T2 for Go: each span includes target service/host, operation name, and
outcome attributes. Not a straight port: Go's `tracer.Start(ctx, "name")`
always requires a name argument (same as Java's spanBuilder), so the "bare
unnamed span" failure mode doesn't apply here either — this only checks
whether `.SetAttributes(...)` is ever called on the resulting span,
presence-anywhere in the enclosing function (Go's span isn't block-scoped,
same reasoning is_wrapped_in_span/has_timeout_context already use for
T1/R1).
← All rules