Skip to content

docs(telemetry): document the hook/plugin span-production rule and enforce it (Epic #929) #1464

Closed

Description

@planetf1

Parent epic: #929
Phase: cross-cutting (do before #1142 starts)
Depends on: nothing
Blocks: #1466

Problem

Mellea has a hard rule about how spans are produced — library code fires a hook,
and a plugin in mellea/telemetry/tracing_plugins.py turns that hook into a
span. Library code never opens spans itself. That rule is nowhere written down,
and nothing enforces it, so it keeps being broken by people acting in good faith.

The history matters, because it explains why "just read the docs" is not
currently an answer:

  1. Until refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 (2026-06-10, refactor(telemetry)!), calling the span helpers
    directly from library code was the pattern. All five backends contained a
    bare span = start_generate_span(...), with the supporting machinery in
    mellea/telemetry/backend_instrumentation.py.
  2. refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 moved span production onto hooks and plugins and deleted that module.
    This was the right change.
  3. refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 rewrote around 97 lines of docs/docs/observability/tracing.md — and
    that page still contains no occurrence of the word "plugin". It documents
    which spans exist and what attributes they carry, never how a span comes to be
    produced.
  4. There is no import contract, so reintroducing the pre-refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 pattern is
    invisible to CI.
  5. The only in-code example of importing telemetry.tracing is
    mellea/stdlib/session.py, which is a deliberate, documented exception
    (OTel Token attach/detach is task-affine). Anyone using it as a template
    copies the exception rather than the pattern.
  6. Six weeks after refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181, docs/dev/adapter_observability.md was written and
    describes the pre-refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 approach, naming start_backend_span /
    start_action_span as the model to mirror.
  7. feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1141 followed that document, and produced spans inline inside
    mellea/backends/. They are being removed in PR feat(backends): LocalFileBinding implements verbs (PEFT/aLoRA path) + from_catalog() (Epic #929 Phase 2) #1454.

Two live consequences:

There is also a structural gap that makes the rule impossible to follow for
adapter functions specifically. ADAPTER_FUNCTION_INVOCATION_COMPLETE and
ADAPTER_FUNCTION_PHASE_COMPLETE are the only HookType family with no
pre/start sibling, so there is no event at which a plugin could open those spans.
Documenting the rule without noting this would set an unmeetable expectation.

Scope

Out of scope

Adding the missing start hooks, and emitting adapter-function spans — both belong
to #1466, which this issue blocks.

Acceptance criteria

  • docs/docs/observability/tracing.md states the hook-fires/plugin-emits rule
    and contains at least one worked reference to tracing_plugins.py
  • The mellea/stdlib/session.py exception is documented as such
  • docs/dev/adapter_observability.md no longer instructs implementers to call
    start_*_span from library code
  • A CI check fails on a new telemetry.tracing import under
    mellea/backends/, with session.py allowlisted
  • The check is verified to fail by temporarily reintroducing such an import
    (evidence in the PR description; the temporary change is not committed)
  • feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) #1142's telemetry acceptance criteria updated
  • npx markdownlint-cli2 passes on every page touched

References

Activity

  1. added
    documentationImprovements or additions to documentation
    area/telemetryOTel spans, metrics, tracing, semconv
    p1High: important bugs (workaround exists) or high-value core features. Do soon, not on fire.
    area/adapter-functionsGranite adapter functions: framework and adaptiers including RAG, Guardian, Core
    on Jul 29, 2026
  2. self-assigned this
    on Aug 10, 2026
  3. planetf1 commented on Aug 11, 2026

    @planetf1
    ContributorAuthor

    The proposed CI boundary is currently green — and the allowlist may be unnecessary

    Checked while finishing PR #1454, so this issue can be picked up knowing whether enforcement lands on existing violations.

    Every importer of mellea/telemetry/tracing across mellea/, identical on upstream/main and on PR #1454's branch:

    File Legitimacy
    mellea/stdlib/session.py the documented exception (OTel Token attach/detach is task-affine)
    mellea/telemetry/tracing_plugins.py correct by design — plugins are the intended consumers

    So there are zero violations today and the check can be added green, rather than needing a cleanup pass first. PR #1454 removed the only ones (_core.py and adapter.py).

    A wrinkle in the suggested rule. This issue proposes: "nothing under mellea/backends/ imports mellea/telemetry/tracing, with mellea/stdlib/session.py as the sole allowlisted exception." But session.py is not under mellea/backends/ — so scoped that narrowly, it needs no allowlist entry at all, and neither does tracing_plugins.py. The allowlist would be dead configuration.

    That leaves a real choice worth making deliberately:

    • Narrow (mellea/backends/ only) — no allowlist needed, trivially green, but does not catch the same defect appearing in mellea/stdlib/ or mellea/formatters/.
    • Repo-wide (all of mellea/ except mellea/telemetry/) — catches the general case, and then needs exactly one allowlist entry: mellea/stdlib/session.py. tracing_plugins.py is excluded by living under mellea/telemetry/.

    I'd lean repo-wide with the single exception, since the failure mode this issue exists to prevent is "library code opens a span", which is not specific to backends — but flagging it as a decision rather than assuming, because the narrow version is what the issue text currently specifies.

  4. ajbozarth commented on Aug 11, 2026

    @ajbozarth
    Member

    The intent is repo-wide, but iirc there are imports for logging telemetry that are also an exception in addition to session, so any language would nee to be specific to metrics and traces telemetry.

  5. planetf1 commented on Aug 12, 2026

    @planetf1
    ContributorAuthor

    Checked — it's mellea/stdlib/tools/_bash_audit.py, importing .context/.metrics.

    No allowlist needed: the issue's already scoped to mellea.telemetry.tracing, so this one isn't caught anyway. Confirms the narrow scoping was right.

  6. added a commit that references this issue on Aug 14, 2026
  7. planetf1 commented on Aug 17, 2026

    @planetf1
    ContributorAuthor

    Reopened after the 2026-08-17 epic audit: PR #1545 closed without merging, and main still lacks both the hook→plugin rule in docs/docs/observability/tracing.md and the import-boundary test. The acceptance criteria remain unmet; #1466 stays formally blocked by this issue.

  8. planetf1 commented on Aug 17, 2026

    @planetf1
    ContributorAuthor

    Correction to my 2026-08-17 reopen comment: #1545 was intentionally closed after review, not abandoned accidentally. Its closing rationale says the relevant source guidance is already in place and that a standalone import guard needs a broader tracing-and-metrics policy. This scope is not being moved to another epic issue; re-closing #1464 and removing its stale blocker edge from #1466.

  9. added 2 commits that reference this issue on Aug 17, 2026
    308ac2c
    04b5d0b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/adapter-functionsGranite adapter functions: framework and adaptiers including RAG, Guardian, Corearea/telemetryOTel spans, metrics, tracing, semconvdocumentationImprovements or additions to documentationp1High: important bugs (workaround exists) or high-value core features. Do soon, not on fire.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions