Conversation
jat255
marked this pull request as draft
September 2, 2026 02:32
jat255
added this pull request to stack #332
September 10, 2026 03:53
jat255
force-pushed
the
jat255/vxv8-exporter
branch
from
September 10, 2026 04:01
bad6ea0 to
6921d36
Compare
Contributor
|
Preview deployed to Connect ( Deployed from commit ad148b5. |
Contributor
|
Preview deployed to Connect ( Deployed from commit ad148b5. |
jat255
force-pushed
the
jat255/vxv8-exporter
branch
from
September 10, 2026 04:43
6921d36 to
57bf17f
Compare
`enable_trajectory_tracing(log=True)` turns on GenAI content capture and, when nobody has installed a tracer provider, installs one that writes spans to a local file. It reports whether commons will emit conversation spans into a configured provider. Where a provider the caller installed sends them is the caller's to know, so commons does not inspect it. Two things do not carry over from R, both checked against opentelemetry-exporter-otlp-json-file rather than assumed. The Python file exporter appends to one path: no `%N` template, no `trace-latest.jsonl` hardlink, and it ignores `OTEL_EXPORTER_OTLP_TRACES_FILE`. So commons picks the filename, claiming it with an exclusive create, and sets the variable after the provider is installed, because a reader uses it to find the directory and must not be sent to a file nothing writes to. And nothing in Python reads `OTEL_TRACES_EXPORTER` outside auto-instrumentation, so respecting an explicit exporter means checking that variable and the installed provider by hand. A trace file holds whole conversations, so the default directory is created per process, readable only by this user, and the files are `0600`. Leaving them at a predictable path under the shared temporary directory would let other local users read them. `COMMONS_TRACES_DIR` still points somewhere durable, and is what another process needs to read them back. An installed no-op provider counts as configured, not as absent, so commons leaves it alone. `set_tracer_provider` refuses to replace it anyway, and treating it as absent would claim a file and repoint the variable while the provider silently stayed no-op. Installation holds a lock, reads both the exporter variable and the provider under it, and confirms the provider it built became the global one, so a caller configuring tracing from another thread is not overridden and cannot leave the variable naming an empty file. The default directory has its own lock, because installation resolves the directory while holding the setup one. Which files a reader picks up is shared with the R package, since one writes them and the other reads them, and a name outside the set fails silently: the reader finds nothing. `tests/shared/traces.json` pins it, R checks `local_traces_pattern()` against the cases, and Python checks that every name it chooses satisfies them. The rest of the trace contract, the span names and attributes, belongs in that file too and arrives with the code that emits them (kata 4frb). Spans are written as each one ends rather than batched, because a batch is lost when the process dies and the last turn of a conversation is the worst span to lose. Part of kata bvcv (M7).
jat255
force-pushed
the
jat255/vxv8-exporter
branch
from
September 10, 2026 04:44
57bf17f to
ad148b5
Compare
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.
Third piece of M7 tracing (kata
vxv8). Stacked on #246, and this base moves tomainonce that merges.enable_trajectory_tracing(log=True)turns on GenAI content capture, and installs a file-writing tracer provider when nobody else has installed one. It returns whether commons will emit conversation spans at all. Where a provider the caller installed sends them is the caller's to know, so commons does not inspect it. A trace file holds whole conversations, so the default directory is per process and readable only by this user.Which file names a reader picks up is shared with the R package, since Python writes the files and R reads them.
tests/shared/traces.jsonpins that set. Span names and attributes belong there too and arrive with the code that emits them (kata4frb).Worth a look: the concurrency handling in
_tracing.py. Installation holds a lock, reads both the exporter variable and the current provider under it, and confirms its own provider became the global one before pointing the variable at its file. Two tests hold each window open.Design notes (agent-written)
Two things do not carry across from the R implementation, both checked against the Python exporter rather than assumed.
FileSpanExporterappends to one path: no%Ntemplate, notrace-latest.jsonlhardlink, and it ignoresOTEL_EXPORTER_OTLP_TRACES_FILE. So commons picks the file name and sets that variable itself, because a reader uses it to find the directory. And nothing in Python readsOTEL_TRACES_EXPORTERoutside auto-instrumentation, so respecting an explicitly configured exporter is a check commons has to make.The private default directory is where the packages differ in a way that is easy to miss. R's default sits under
tempdir(), which R already makes private per session. Python'stempfile.gettempdir()is/tmp, so a predictable path there would let other local users read whole conversations.COMMONS_TRACES_DIRstill points somewhere durable, and is what another process needs to read the files back.The default directory has a lock of its own, separate from the setup lock, because installation resolves the directory while already holding that one.
R changes
No R source changed, and no R behaviour differs. One test was added to
test-trajectories.R, runninglocal_traces_pattern()against the shared naming cases. No hand-written R test was deleted or replaced.It is here rather than in a later PR because this is the first time anything outside R writes files that
read_local_spans()has to find. The pattern was previously exercised only incidentally, by two tests that writetrace-0.jsonlandtrace-latest.jsonlinto a directory and count what comes back. Those still stand. This adds a direct check of the accept and reject set, includingtrace.jsonl,trace-1.jsonl.bakandtraces-1.jsonl, which nothing covered before.Blast radius is one test file, and no call site of an R function changes. Evidence that the fixture drives the R suite rather than sitting beside it: mutating a case in the synced copy fails the test, and
test-trajectories.Rgives 177 passing with 1 skipped, the skip being the one that needs a Connect vanity URL.Worth your scrutiny: whether
trace.jsonl, with no number, should be read at all. The R pattern accepts it today and I pinned current behaviour rather than changing it, but nothing commons writes produces that name, so it may be an accident worth removing on the R side.pkg-r/tests/testthat/fixtures/shared/traces.jsonis generated byscripts/sync-shared.sh, so skip it in review.