feat(instrument): Langfuse adapter closure — sample + doc + LayerLens alias (lifecycle_preview → mature)#110
Closed
mmercuri wants to merge 1 commit into
Conversation
… alias (lifecycle_preview → mature) Closes the Langfuse framework adapter to commercial-grade ``mature`` status. The adapter source itself was already structurally complete (1,795 LOC across 7 files, 12-test unit suite green). This PR adds the three deliverables required to graduate it from ``lifecycle_preview``: 1. Runnable mocked sample (``samples/instrument/langfuse/``) 2. Reference doc (``docs/adapters/frameworks-langfuse.md``) 3. STRATIX → LayerLens deprecation alias on the adapter package …and relabels the manifest entry accordingly. Sample ------ ``samples/instrument/langfuse/main.py`` is a fully-mocked end-to-end demo of ``import_traces``, ``export_traces``, and ``sync(direction= BIDIRECTIONAL)``. It stands in for ``LangfuseAPIClient`` with an in-process fixture that returns two synthetic Langfuse traces (one with a ``GENERATION`` observation, one with a ``TOOL`` ``SPAN``) and records every batch ingested by the export path. The sample never touches the network and exits 0 in CI; an optional ``LANGFUSE_*`` env-var path additionally exercises a single live ``connect()`` smoke when credentials are present. Doc --- ``docs/adapters/frameworks-langfuse.md`` covers install, quick-start, the import / export pipeline architecture, the bidirectional event mapping (Langfuse ↔ LayerLens canonical events), the capability matrix, version compatibility (Pydantic v2-only, Langfuse public-API forward-compat, no Langfuse Python SDK dependency), capture-config patterns, BYOK posture, replay semantics, the backward-compatibility aliases, and operational notes (rate limits, cursor persistence, quarantine). LayerLens rename + back-compat alias ------------------------------------ * ``STRATIXLangfuseAdapter`` is now a deprecated module alias for ``LangfuseAdapter``, resolved via PEP 562 ``__getattr__`` with a ``DeprecationWarning`` and slated for removal in v2.0. * All ``STRATIX`` mentions in adapter docstrings have been swept to ``LayerLens``; the legacy name is preserved in one place per file where it documents the back-compat alias. * The adapter ``AdapterInfo`` now reports ``author='LayerLens Team'`` and ``description='Bidirectional trace sync between LayerLens and Langfuse'``. * Exported traces are tagged with **both** ``layerlens-exported`` (canonical) and ``stratix-exported`` (legacy alias) so a deployment upgrade does not double-import previously-exported traces. The importer recognises both tags for loop prevention. Manifest -------- ``scripts/emit_adapter_manifest.py`` now lists ``langfuse`` in ``_MATURE`` so the atlas-app catalog labels the adapter ``mature`` instead of ``smoke_only``. The full manifest entry resolves with ``class_name='LangfuseAdapter'``, ``capabilities=['trace_tools', 'trace_models', 'replay']``, ``requires_pydantic='v2_only'``, ``extras=['langfuse-importer']``. Acceptance ---------- * ``uv run pytest tests/instrument/adapters/frameworks/test_langfuse_adapter.py -x`` → **12 passed** * ``uv run mypy --strict src/layerlens/instrument/adapters/frameworks/langfuse`` → **Success: no issues found in 8 source files** * ``uv run ruff check src/.../langfuse tests/.../test_langfuse_adapter.py`` → **All checks passed** * ``python -m samples.instrument.langfuse.main`` → exit 0, prints all three labeled flows + summary * ``uv run pytest tests/instrument/test_default_install.py tests/instrument/test_lazy_imports.py`` → **6 passed** (default-install + lazy-import guards intact; the ``[langfuse-importer]`` extra is empty so the default install set is unchanged) Stacks on --------- ``feat/instrument-base-foundation`` (M1.A) — required for the ``BaseAdapter`` surface this adapter consumes. Closes the langfuse leg of the lifecycle_preview → mature audit.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the Langfuse framework adapter to commercial-grade
maturestatus. It was the closest of the 13
lifecycle_previewadapters ataudit time — the source itself was already structurally complete
(1,795 LOC across 7 files, 12-test unit suite green) — so this PR
ships only the closure deltas:
samples/instrument/langfuse/docs/adapters/frameworks-langfuse.mdSTRATIX → LayerLensdeprecation alias on the packagelangfuse→matureinscripts/emit_adapter_manifest.pySTRATIXreferences rewritten toLayerLens, with the legacy name preserved exactly once per concept (back-compat alias mention + loop-prevention tag)The adapter source files are copied unchanged from the orchestration
batch (
feat/instrument-frameworks-orchestration→ PR #96) and rebasedonto
feat/instrument-base-foundation, identical to how the other M2closure PRs (#101, #104, #108, etc.) are structured.
Sample
samples/instrument/langfuse/main.pyis a fully-mocked end-to-end demo.A small in-process
_MockLangfuseClientreturns two synthetic Langfusetraces (one with a
GENERATIONobservation, one with aTOOLSPAN)and records every batch the export path ingests. The sample exercises
three labeled flows and exits 0:
The optional
LANGFUSE_PUBLIC_KEY/LANGFUSE_SECRET_KEYenv varsadditionally trigger a single live
connect()smoke (just the healthcheck) when present. Defaults to fully offline.
Doc
docs/adapters/frameworks-langfuse.md(321 lines) covers:GENERATION→model.invoke+cost.record,SPANwithmetadata.type=TOOL→tool.call, etc.)urllib)CaptureConfigpatternsserialize_for_replay())STRATIX → LayerLens deprecation alias
The package now exposes
STRATIXLangfuseAdaptervia a PEP 562module-level
__getattr__:The alias resolves to
LangfuseAdapterand is listed in__all__.Unknown attribute access still raises
AttributeErroras expected.Loop-prevention tags are now emitted as both
layerlens-exported(canonical) and
stratix-exported(legacy alias). The importerrecognises both, so a deployment upgrade does not double-import any
trace previously exported by an older release.
Manifest
_MATURE: set = { "openai", ... "smolagents", + # Frameworks promoted from ``lifecycle_preview`` once they ship a + # dedicated unit-test suite, a reference doc in ``docs/adapters/``, + # and a runnable mocked sample under ``samples/instrument/``. + "langfuse", }python scripts/emit_adapter_manifest.py --stdoutnow emits, for thelangfuseentry:{ "key": "langfuse", "framework": "langfuse", "category": "framework", "class_name": "LangfuseAdapter", "version": "0.1.0", "extras": ["langfuse-importer"], "maturity": "mature", "requires_pydantic": "v2_only", "capabilities": ["trace_tools", "trace_models", "replay"], "description": "Bidirectional trace sync between LayerLens and Langfuse" }Acceptance
uv run pytest tests/instrument/adapters/frameworks/test_langfuse_adapter.py -x→ 12 passeduv run mypy --strict src/layerlens/instrument/adapters/frameworks/langfuse→ Success: no issues found in 8 source filesuv run ruff check src/.../langfuse tests/.../test_langfuse_adapter.py→ All checks passedpython -m samples.instrument.langfuse.main→ exit 0, all three labeled flows + summaryuv run pytest tests/instrument/test_default_install.py tests/instrument/test_lazy_imports.py→ 6 passed (default-install + lazy-import guards intact;[langfuse-importer]extra is empty so the defaultpip install layerlensset is unchanged)uv run mypy --strict src(whole src tree) → Success: no issues found in 99 source filesStacks on
feat/instrument-base-foundation(M1.A, PR #93) — required for theBaseAdaptersurface this adapter consumes.Test plan
mypy --strictclean on the new packageruff checkclean on the new package + testpytestgreen on the 12-test langfuse adapter suitelangfuse-importerextra adds zero depsdocs/adapters/frameworks-langfuse.mdend-to-end against the Langfuse public API docs__getattr__deprecation pattern matches the rename convention adopted elsewhere in the M2 batch (cf.to_stratix_policyin agentforce)layerlens-exported(new) andstratix-exported(legacy)