ragleap-trace 0.1.0 is a small Python library that records what your code does as spans and writes them to memory or to a local file. It uses only the standard library, and it is built so that content is not recorded by accident. Source: its README and changelog at the 0.1.0 tag.
What is ragleap-trace?
A tracer with spans, a context manager and a @traced decorator for sync and async code, two exporters (InMemoryExporter and JsonlExporter), and an adapter for ragleap-rag’s observability hooks. Install it with pip install ragleap-trace. It needs Python 3.10 or newer and has no runtime dependencies.
How do I use it?
This is the first example from the README:
from ragleap_trace import Tracer, JsonlExporter, traced
tracer = Tracer([JsonlExporter("traces.jsonl")])
with tracer.span("retrieve", top_k=5) as s:
s.set_attribute("hits", 4)
@traced(tracer)
async def answer(...): ...
How do I trace a ragleap-rag app?
The adapter’s hooks() returns one-item lists keyed on_ingest, on_query and on_answer, because ragleap-rag takes a list of callables for each. Pass them with RagLeap(..., **adapter.hooks()) or merge them into your own lists. The spans are rag.ingest, rag.query and rag.answer. This is the second README example:
from ragleap_trace import Tracer, JsonlExporter, RagTraceAdapter
tracer = Tracer([JsonlExporter("traces.jsonl")])
adapter = RagTraceAdapter(tracer)
hooks = adapter.hooks() # lists keyed on_ingest / on_query / on_answer
What does it never record?
- Only the exception class name is recorded, never its message.
- Only
str,int,floatandboolattribute values are kept; objects are dropped, never printed. - Keys such as
prompt,answer,query,file_name,passwordandtokenare never recorded. - The ragleap-rag adapter copies only counts, booleans, the provider name, token numbers and the query length. Query text, answer text and file names are never copied.
- Limits: name 128, key 64, 32 attributes per span, strings cut at 256 characters.
How was it tested?
Different measures, kept apart. Our Tests page counts 2 test files and 47 test functions on the main branch (a count, not a pass count). The changelog records: the core 34 tests and 24 of 24 deliberate breaks caught, and the adapter 63 tests and 42 of 42 breaks, both on the VPS (Python 3.10.12) and in CI on 3.10 and 3.12; and 9 integration tests and 12 of 12 breaks against a real RagLeap (Postgres 16 with pgvector, a fake embedder and a fake generator), in CI on Python 3.11. Not verified: real LLM providers, vector backends other than pgvector, spans handed between threads and Windows file permissions.
What does it not do?
- The key denylist is defense in depth, not a guarantee: a value under an innocent key is recorded as you give it. Do not put secrets or personal data in attributes.
- No retention or rotation: the JSONL file grows until you remove it, and it is not encrypted.
- No opt-in content capture, no sampling, no network exporters and no multi-tenant tagging.
- Exporters run in the caller’s thread, so a slow exporter slows the caller. Events are paired per thread and per asyncio task, so two streams interleaved in one thread or task can pair an answer with the wrong query.
More: the library page, the release notes and the source.