botgauge-tracing 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- botgauge_tracing-0.1.0/LICENSE +105 -0
- botgauge_tracing-0.1.0/MANIFEST.in +3 -0
- botgauge_tracing-0.1.0/PKG-INFO +457 -0
- botgauge_tracing-0.1.0/README.md +390 -0
- botgauge_tracing-0.1.0/pyproject.toml +195 -0
- botgauge_tracing-0.1.0/setup.cfg +4 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/__init__.py +239 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_agent.py +34 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_attributes.py +86 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_classify.py +189 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_commands.py +39 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_context.py +162 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_discovery.py +916 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_env.py +31 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_filter_processor.py +284 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_isolation.py +67 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_links.py +49 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_native_producers.py +98 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_privacy.py +3747 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_processor.py +133 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_producer_overlap.py +240 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_propagation.py +77 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_provider.py +1458 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_scope.py +82 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_shutdown.py +271 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_skeleton.py +218 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_topology.py +871 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/_turn.py +133 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/certified_profiles.v1.json +144 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/doctor.py +318 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/launcher/__init__.py +6 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/launcher/_bootstrap.py +375 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/launcher/_cli.py +251 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/launcher/_pythonpath.py +34 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/launcher/sitecustomize.py +47 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/probe.py +98 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/producer_compat.v1.json +170 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/py.typed +0 -0
- botgauge_tracing-0.1.0/src/botgauge/tracing/setup.py +64 -0
- botgauge_tracing-0.1.0/src/botgauge_tracing.egg-info/PKG-INFO +457 -0
- botgauge_tracing-0.1.0/src/botgauge_tracing.egg-info/SOURCES.txt +43 -0
- botgauge_tracing-0.1.0/src/botgauge_tracing.egg-info/dependency_links.txt +1 -0
- botgauge_tracing-0.1.0/src/botgauge_tracing.egg-info/entry_points.txt +8 -0
- botgauge_tracing-0.1.0/src/botgauge_tracing.egg-info/requires.txt +53 -0
- botgauge_tracing-0.1.0/src/botgauge_tracing.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, ALv2 Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-ALv2
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 BotGauge AI Inc.
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available under
|
|
20
|
+
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
+
Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
+
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
+
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
+
means making the Software available to others in a commercial product or
|
|
34
|
+
service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the Software
|
|
39
|
+
that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a licensee
|
|
52
|
+
using the Software in accordance with these Terms and Conditions.
|
|
53
|
+
|
|
54
|
+
### Patents
|
|
55
|
+
|
|
56
|
+
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
+
patents, the license grant above includes a license under our patents. If you
|
|
58
|
+
make a claim against any party that the Software infringes or contributes to
|
|
59
|
+
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
+
immediately.
|
|
61
|
+
|
|
62
|
+
### Redistribution
|
|
63
|
+
|
|
64
|
+
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
+
the Software.
|
|
66
|
+
|
|
67
|
+
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
+
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
+
remove any copyright notices provided in or with the Software.
|
|
70
|
+
|
|
71
|
+
### Disclaimer
|
|
72
|
+
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
+
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
+
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
+
|
|
77
|
+
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
+
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
+
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
+
|
|
81
|
+
### Trademarks
|
|
82
|
+
|
|
83
|
+
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
+
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
+
trademarks, trade names, service marks or product names.
|
|
86
|
+
|
|
87
|
+
## Grant of Future License
|
|
88
|
+
|
|
89
|
+
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
+
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
91
|
+
the date we make the Software available. On or after that date, you may use the
|
|
92
|
+
Software under the Apache License, Version 2.0, in which case the following
|
|
93
|
+
will apply:
|
|
94
|
+
|
|
95
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
96
|
+
this file except in compliance with the License.
|
|
97
|
+
|
|
98
|
+
You may obtain a copy of the License at
|
|
99
|
+
|
|
100
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
101
|
+
|
|
102
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
|
103
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
104
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
105
|
+
specific language governing permissions and limitations under the License.
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: botgauge-tracing
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: BotGauge captures AI-agent traces safely and privately without slowing the customer's application. Manual SDK tracing, zero-code instrumentation, and distributed trace propagation, built on OpenTelemetry.
|
|
5
|
+
Author-email: "BotGauge AI Inc." <support@botgauge.com>
|
|
6
|
+
License-Expression: FSL-1.1-ALv2
|
|
7
|
+
Project-URL: Homepage, https://www.botgauge.com/
|
|
8
|
+
Keywords: opentelemetry,otel,tracing,observability,llm,llm-observability,ai-agents,agents,langchain,openai,crewai,monitoring
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Framework :: OpenTelemetry
|
|
12
|
+
Classifier: Framework :: OpenTelemetry :: Distros
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: System :: Monitoring
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: botgauge-cli==0.1.0
|
|
27
|
+
Requires-Dist: opentelemetry-api>=1.26
|
|
28
|
+
Requires-Dist: opentelemetry-sdk>=1.26
|
|
29
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.26
|
|
30
|
+
Provides-Extra: openai
|
|
31
|
+
Requires-Dist: openinference-instrumentation-openai==0.1.65; extra == "openai"
|
|
32
|
+
Provides-Extra: anthropic
|
|
33
|
+
Requires-Dist: openinference-instrumentation-anthropic==3.0.3; extra == "anthropic"
|
|
34
|
+
Provides-Extra: langchain
|
|
35
|
+
Requires-Dist: openinference-instrumentation-langchain==0.1.79; extra == "langchain"
|
|
36
|
+
Provides-Extra: langgraph
|
|
37
|
+
Requires-Dist: openinference-instrumentation-langchain==0.1.79; extra == "langgraph"
|
|
38
|
+
Provides-Extra: crewai
|
|
39
|
+
Requires-Dist: openinference-instrumentation-crewai==1.1.21; extra == "crewai"
|
|
40
|
+
Requires-Dist: openinference-instrumentation-openai==0.1.65; extra == "crewai"
|
|
41
|
+
Provides-Extra: llamaindex
|
|
42
|
+
Requires-Dist: openinference-instrumentation-llama-index==4.6.0; extra == "llamaindex"
|
|
43
|
+
Provides-Extra: google-adk
|
|
44
|
+
Requires-Dist: openinference-instrumentation-google-adk==1.0.4; extra == "google-adk"
|
|
45
|
+
Provides-Extra: openai-agents
|
|
46
|
+
Requires-Dist: openinference-instrumentation-openai-agents==2.5.3; extra == "openai-agents"
|
|
47
|
+
Provides-Extra: autogen-agentchat
|
|
48
|
+
Requires-Dist: openinference-instrumentation-autogen-agentchat==0.1.22; extra == "autogen-agentchat"
|
|
49
|
+
Provides-Extra: pydantic-ai
|
|
50
|
+
Requires-Dist: openinference-instrumentation-pydantic-ai==0.1.30; extra == "pydantic-ai"
|
|
51
|
+
Provides-Extra: mcp
|
|
52
|
+
Requires-Dist: openinference-instrumentation-mcp==2.0.13; extra == "mcp"
|
|
53
|
+
Provides-Extra: distributed
|
|
54
|
+
Requires-Dist: opentelemetry-instrumentation-requests>=0.40b0; extra == "distributed"
|
|
55
|
+
Requires-Dist: opentelemetry-instrumentation-httpx>=0.40b0; extra == "distributed"
|
|
56
|
+
Requires-Dist: opentelemetry-instrumentation-urllib3>=0.40b0; extra == "distributed"
|
|
57
|
+
Requires-Dist: opentelemetry-instrumentation-asgi>=0.40b0; extra == "distributed"
|
|
58
|
+
Requires-Dist: opentelemetry-instrumentation-wsgi>=0.40b0; extra == "distributed"
|
|
59
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.40b0; extra == "distributed"
|
|
60
|
+
Requires-Dist: opentelemetry-instrumentation-starlette>=0.40b0; extra == "distributed"
|
|
61
|
+
Requires-Dist: opentelemetry-instrumentation-flask>=0.40b0; extra == "distributed"
|
|
62
|
+
Requires-Dist: opentelemetry-instrumentation-django>=0.40b0; extra == "distributed"
|
|
63
|
+
Requires-Dist: opentelemetry-instrumentation-grpc>=0.40b0; extra == "distributed"
|
|
64
|
+
Provides-Extra: frameworks
|
|
65
|
+
Requires-Dist: botgauge-tracing[anthropic,autogen-agentchat,crewai,distributed,google-adk,langchain,llamaindex,mcp,openai,openai-agents,pydantic-ai]; extra == "frameworks"
|
|
66
|
+
Dynamic: license-file
|
|
67
|
+
|
|
68
|
+
# botgauge-tracing
|
|
69
|
+
|
|
70
|
+
**Status: early release (0.x). Public API shapes may still change before 1.0. Every framework in
|
|
71
|
+
`producer_compat.v1.json` has a pinned, isolated certification test; combined or overlapping
|
|
72
|
+
producer profiles are not verified.**
|
|
73
|
+
|
|
74
|
+
> BotGauge captures AI-agent traces safely and privately without slowing the customer's
|
|
75
|
+
> application.
|
|
76
|
+
|
|
77
|
+
This is the `botgauge-tracing` distribution, the BotGauge tracing SDK, built
|
|
78
|
+
on stock OpenTelemetry (`opentelemetry-api`/`-sdk`/`-exporter-otlp-proto-http`; the only BotGauge
|
|
79
|
+
dependency is `botgauge-cli`, which provides the command). Customers install it through the `botgauge` meta-package
|
|
80
|
+
(`pip install botgauge`, extras forwarded: `pip install "botgauge[langchain]"`) and import it as
|
|
81
|
+
`from botgauge import tracing`; `botgauge` is a PEP 420 namespace that other BotGauge packages
|
|
82
|
+
join. Its commands (`instrument`, `doctor`, `probe`, `setup`) run
|
|
83
|
+
through the `botgauge` command, which belongs to `botgauge-cli` (a standard-library-only dependency);
|
|
84
|
+
apart from that it depends only on OpenTelemetry.
|
|
85
|
+
|
|
86
|
+
## What works today
|
|
87
|
+
|
|
88
|
+
### Manual SDK tracing
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from botgauge import tracing
|
|
92
|
+
|
|
93
|
+
tracing.init(api_key="...") # or set BOTGAUGE_API_KEY and call tracing.init()
|
|
94
|
+
|
|
95
|
+
with tracing.turn(session_id="ses_123"):
|
|
96
|
+
with tracing.agent("billing-agent"):
|
|
97
|
+
tracer = tracing.get_tracer()
|
|
98
|
+
with tracer.start_as_current_span("check_balance"):
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
tracing.flush()
|
|
102
|
+
tracing.shutdown()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Streaming generators:** Keep a `turn()` scope within one execution context. Do not
|
|
106
|
+
leave it open across `yield` when a framework may resume each chunk in a fresh
|
|
107
|
+
context (for example, a synchronous generator consumed through Starlette's thread
|
|
108
|
+
pool). Later chunks can lose their turn and parent span, and closing the scope can
|
|
109
|
+
log `Failed to detach context`. Finish traced work before yielding, or keep the
|
|
110
|
+
entire iteration in one context. If chunks run in separate contexts, start and end
|
|
111
|
+
each tracing scope within the context that processes that chunk; preserving one Turn
|
|
112
|
+
across the whole stream requires the application to preserve its context as well.
|
|
113
|
+
|
|
114
|
+
`init()` sends the key as `Authorization: Bearer <key>`, BotGauge's only credential. An
|
|
115
|
+
`Authorization` header passed in `headers=` replaces it. Arguments win over the environment:
|
|
116
|
+
without `api_key=` or `endpoint=`, `init()` reads `BOTGAUGE_API_KEY` / `BOTGAUGE_ENDPOINT`, and a key with no
|
|
117
|
+
endpoint exports to `https://api.botgauge.com/v1/traces`. It never reads `.env` files (load them
|
|
118
|
+
in your app, e.g. with python-dotenv) or `OTEL_EXPORTER_OTLP_*`. The first 401/403 from the
|
|
119
|
+
endpoint logs one `botgauge: BotGauge rejected the API key (...)` line with the server's reason.
|
|
120
|
+
The line names the Authorization header instead when `headers=` supplied it, and says that no
|
|
121
|
+
credential was sent when an endpoint is set without a key.
|
|
122
|
+
|
|
123
|
+
BotGauge disables export when a key or custom headers would be sent to a remote `http://`
|
|
124
|
+
endpoint, or to an endpoint with no `http://` or `https://` scheme. Local HTTP collectors remain
|
|
125
|
+
available. Use `https://` for remote collectors, and add a scheme to an endpoint that has none. If
|
|
126
|
+
you deliberately need remote cleartext HTTP, set `BOTGAUGE_ALLOW_INSECURE_HTTP=true`; BotGauge
|
|
127
|
+
still warns that the connection sends headers without transport encryption. Ambiguous URL
|
|
128
|
+
authorities are treated as remote.
|
|
129
|
+
|
|
130
|
+
With neither a key nor an endpoint, BotGauge emits a configuration notice to stderr and
|
|
131
|
+
discards its exports; it does not print spans. For local development only, set
|
|
132
|
+
`BOTGAUGE_CONSOLE_EXPORT=1` to explicitly send sanitized spans to stdout. A customer-owned
|
|
133
|
+
OTel exporter attached to the same provider continues to operate independently.
|
|
134
|
+
|
|
135
|
+
- One real OTel engine — no custom span class, no custom ID minting, no custom OTLP encoder.
|
|
136
|
+
- Never blocks the calling thread: spans export through a `BatchSpanProcessor`, off-thread.
|
|
137
|
+
- `tracing.agent()`/`tracing.turn()` stamp the frozen, dotted attribute names (see
|
|
138
|
+
`src/botgauge/tracing/_attributes.py`) onto every span created inside them.
|
|
139
|
+
- Attaches to an existing `TracerProvider` (bring-your-own-OTel) rather than replacing it, and
|
|
140
|
+
never creates a second one if one is already active.
|
|
141
|
+
- `flush()`/`shutdown()` enforce a hard deadline — a stuck exporter can't hang your process.
|
|
142
|
+
- A FULL/SKELETON/DROP topology filter keeps generic infrastructure spans (HTTP transport,
|
|
143
|
+
database calls) out of your trace by default, bridging only what's structurally necessary to
|
|
144
|
+
connect Agent→Agent hops (`BOTGAUGE_TRACE_SCOPE=all` to see everything).
|
|
145
|
+
- Privacy: `capture="metadata"|"text"|"full"` and `redacted=True|False`.
|
|
146
|
+
Defaults are `capture="text", redacted=True`: prompts, responses and tool data, but no images,
|
|
147
|
+
audio or embedding vectors (most tracing platforms keep media bytes out of spans by default;
|
|
148
|
+
`capture="full"` exports them inline when you ask for it). `metadata` selects structural attributes
|
|
149
|
+
(IDs, models, timing, usage counts, HTTP/RPC/DB structure); `text` adds readable prompts,
|
|
150
|
+
responses, tools, errors, events, and link attributes while excluding recognized media and
|
|
151
|
+
embedding vectors; `full` captures all supported content. With `redacted=True`, background
|
|
152
|
+
cleaning masks detected PII and credentials only. Harmless SQL, URL parameters/fragments,
|
|
153
|
+
exception details, custom metadata, names, and scope versions remain readable when selected.
|
|
154
|
+
Sensitive values within SQL, DB URLs, URLs, events, and links are cleaned without hiding the
|
|
155
|
+
complete record. The configured key (`api_key=`, or a Bearer token passed in `headers=`) is
|
|
156
|
+
removed from protected export copies.
|
|
157
|
+
To select extra metadata keys, use `capture_allow_keys=["app.tenant_tier", "myco.*"]` or
|
|
158
|
+
`BOTGAUGE_CAPTURE_ALLOW_KEYS=app.tenant_tier,myco.*`; protected values are still cleaned.
|
|
159
|
+
**`redacted=False` overrides capture selection in every mode**: metadata/false, text/false,
|
|
160
|
+
and full/false export the same original supported FULL records, including sensitive data,
|
|
161
|
+
without privacy scanning, masking, or sanitizer truncation. FULL/SKELETON/DROP topology
|
|
162
|
+
filtering still applies; skeletons remain minimal. Raw export cannot recover content already
|
|
163
|
+
discarded by a customer-owned producer or exceed OTel's supported data types and limits.
|
|
164
|
+
BotGauge-owned producers use capture controls matching the resolved policy; raw configuration
|
|
165
|
+
disables BotGauge's own content hiding. Your `OPENINFERENCE_HIDE_*` settings still apply to them
|
|
166
|
+
in every mode and can only hide more. Customer-owned instrumentation and exporters remain intact.
|
|
167
|
+
Privacy patterns do not detect every sensitive fact or credential format. Protected values
|
|
168
|
+
retain documented technical size/work limits. Supported numeric PII is inspected across
|
|
169
|
+
integers, integral floats, numeric strings, and serialized structures. Recognized numeric
|
|
170
|
+
usage, cost, and duration measurements retain their values and types; arbitrary numeric IDs
|
|
171
|
+
still receive PII inspection. A subtree beyond the sanitizer's depth limit is replaced by
|
|
172
|
+
`[omitted: inspection limit]`, indicating a technical omission rather than detected PII.
|
|
173
|
+
Native containers have an 8-level limit and parsed structures a 64-level limit. String caps
|
|
174
|
+
and sequence caps can truncate content separately: a list keeps its first 128 elements, and a
|
|
175
|
+
map its first 128 entries plus an `[omitted: inspection limit]` entry counting the rest. These
|
|
176
|
+
sanitizer limits do not apply with `redacted=False`. Metadata omissions and text media
|
|
177
|
+
exclusions are capture selection, separate from sensitive-value masking.
|
|
178
|
+
Zero-code settings are `BOTGAUGE_CAPTURE=metadata|text|full` and
|
|
179
|
+
`BOTGAUGE_REDACTED=true|false`. Invalid capture values, including the previous `redacted`
|
|
180
|
+
spelling, fall back to protected metadata. Migrate to `capture="text", redacted=True`.
|
|
181
|
+
Invalid boolean environment values enable protection. Reconfigure export policy through
|
|
182
|
+
`shutdown()` and a new `init()`; restart zero-code processes to change producer capture
|
|
183
|
+
controls. Forks preserve both settings. `doctor` reports requested/effective capture
|
|
184
|
+
and protection without payloads or credentials.
|
|
185
|
+
- With a customer `ConcurrentMultiSpanProcessor`, BotGauge runs its own start callbacks
|
|
186
|
+
through a caller-context bridge, preserving Agent/Revision/Session/Turn identity and the
|
|
187
|
+
customer's existing processor chain. The bridge is restored on shutdown; `doctor` reports
|
|
188
|
+
whether it is active.
|
|
189
|
+
- Zero BotGauge baggage, ever. Standard W3C trace-context propagation only — your own propagator
|
|
190
|
+
and baggage are never touched or replaced.
|
|
191
|
+
|
|
192
|
+
### Zero-code instrumentation
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
pip install "botgauge[langchain]" # install only the producer you need
|
|
196
|
+
export BOTGAUGE_API_KEY="..."
|
|
197
|
+
# export BOTGAUGE_ENDPOINT="https://your-collector/v1/traces" # only for a collector other than BotGauge's
|
|
198
|
+
botgauge instrument python your_app.py
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`botg` is a short alias for `botgauge` (`botg instrument python your_app.py`); `botgauge help` lists every
|
|
202
|
+
command the installed BotGauge packages provide.
|
|
203
|
+
|
|
204
|
+
Or keep the settings in a `.env` file: `botgauge instrument --env-file .env python your_app.py`.
|
|
205
|
+
It reads `KEY=VALUE` lines the way `uv run --env-file` and `docker run --env-file` do: comments,
|
|
206
|
+
an optional `export ` prefix, and quotes are handled, and variables aren't expanded. It never
|
|
207
|
+
overrides a variable that is already set, so real deployment settings win. The flag can be
|
|
208
|
+
repeated; an earlier file wins over a later one. Manual `tracing.init()` does not read `.env`;
|
|
209
|
+
load it in your app (e.g. with python-dotenv).
|
|
210
|
+
|
|
211
|
+
Run each capture mode separately with protection enabled. Use the virtual environment containing
|
|
212
|
+
the updated SDK and your application's dependencies, with the endpoint/API-key settings above:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
BOTGAUGE_CAPTURE=metadata BOTGAUGE_REDACTED=true botgauge instrument python your_app.py
|
|
216
|
+
|
|
217
|
+
BOTGAUGE_CAPTURE=text BOTGAUGE_REDACTED=true botgauge instrument python your_app.py
|
|
218
|
+
|
|
219
|
+
BOTGAUGE_CAPTURE=full BOTGAUGE_REDACTED=true botgauge instrument python your_app.py
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Replace `your_app.py` with your script. Each command starts a new process. Metadata selects
|
|
223
|
+
structural content, text adds readable text while excluding recognized media/vectors, and full
|
|
224
|
+
selects all supported content. With `BOTGAUGE_REDACTED=true`, selected content receives sensitive
|
|
225
|
+
value cleaning. Setting `BOTGAUGE_REDACTED=false` enables original supported FULL content in all
|
|
226
|
+
three modes, bypassing their capture exclusions and privacy cleaning.
|
|
227
|
+
|
|
228
|
+
Zero-code export reads only `BOTGAUGE_ENDPOINT` (default `https://api.botgauge.com/v1/traces`
|
|
229
|
+
when `BOTGAUGE_API_KEY` is set) for its destination. Customer
|
|
230
|
+
`OTEL_EXPORTER_OTLP_*` settings are left to the customer's OTel exporters in both
|
|
231
|
+
directions: BotGauge never uses them as a fallback destination for its connection token, and
|
|
232
|
+
BotGauge's own exporter ignores them, so customer collector headers, TLS files, timeout, and
|
|
233
|
+
compression are never applied to BotGauge export (which always uses gzip). With neither
|
|
234
|
+
variable set, BotGauge export is disabled by default and a configuration notice is
|
|
235
|
+
written to stderr; the explicit development-only `BOTGAUGE_CONSOLE_EXPORT=1` setting
|
|
236
|
+
still enables console output.
|
|
237
|
+
|
|
238
|
+
Selects certified framework producers from the versioned compatibility registry and activates
|
|
239
|
+
compatible OTel transport instrumentors via standard `opentelemetry_instrumentor` entry points.
|
|
240
|
+
The registry covers pinned LangChain/LangGraph, direct OpenAI, direct Anthropic,
|
|
241
|
+
LlamaIndex+OpenAI, CrewAI, OpenAI Agents, Google ADK, AutoGen AgentChat and MCP (each with only its own producer).
|
|
242
|
+
Certification records the versions BotGauge verified, as (framework, instrumentor) pairs: a
|
|
243
|
+
framework version is verified only with an instrumentor version it passed certification with. Only
|
|
244
|
+
those exact pairs are verified, never a range: a version older than the oldest verified, between
|
|
245
|
+
two verified versions, newer than the latest verified, or a pre-release is not verified. Verified
|
|
246
|
+
pairs stay verified when newer ones are added. It is not a requirement. An installed framework at
|
|
247
|
+
a version that isn't verified is still traced, and startup logs one line per framework saying why:
|
|
248
|
+
`botgauge: tracing openai at a version BotGauge has not verified: openai 3.40.0 is newer than the
|
|
249
|
+
latest version BotGauge verified (3.35.1); verified: ...`. Inside the app,
|
|
250
|
+
`tracing.doctor.report()["instrumentors"]["not_verified"]` returns them; a separate `botgauge doctor`
|
|
251
|
+
process cannot see the app's activation. Set `BOTGAUGE_VERIFIED_ONLY=1` to trace only verified
|
|
252
|
+
versions. Versions the registry lists as known to break tracing are never traced, and startup says
|
|
253
|
+
why. AI instrumentors that aren't in the registry are still skipped.
|
|
254
|
+
BotGauge checks
|
|
255
|
+
the public OTel already-instrumented marker and supports explicit customer ownership via
|
|
256
|
+
`BOTGAUGE_PRODUCER_OWNER=langchain=customer`. Set `BOTGAUGE_STRICT=1` to make selection failures
|
|
257
|
+
and versions that aren't verified fatal for CI (or use `botgauge instrument --strict python your_app.py`):
|
|
258
|
+
the launcher logs `botgauge: --strict: not starting the application: <reasons>` and exits 1
|
|
259
|
+
before the app runs. Ownership also accepts registered entry-point names such as
|
|
260
|
+
`llama_index=customer` (the canonical target is `llamaindex`); unknown names produce a warning.
|
|
261
|
+
A producer that traces several frameworks (the LangChain instrumentor also traces LangGraph) stays
|
|
262
|
+
off when the customer owns any of them; the others are then not traced by BotGauge, so they are not
|
|
263
|
+
reported as not verified, and importing one logs missing-producer guidance that names that ownership.
|
|
264
|
+
An installed producer extra without its framework is reported as `absent` and does not fail
|
|
265
|
+
strict mode. Resolve actual selection findings or disable strict mode; setting
|
|
266
|
+
`BOTGAUGE_VERIFIED_ONLY=1` alone does not clear strict failures. Strict mode also stops the app
|
|
267
|
+
if the target Python cannot import BotGauge
|
|
268
|
+
or if interpreter options `-I`, `-E`, or `-S` would bypass the startup hook. When an app imports a
|
|
269
|
+
registered framework without an active producer, startup logs one recommendation for the
|
|
270
|
+
BotGauge extra, or points to `botgauge doctor` if the extra is installed but did not activate. Client
|
|
271
|
+
libraries that frameworks import themselves (`openai`, `anthropic`, `mcp`) get no hint while a
|
|
272
|
+
framework producer is active, so `--strict` does not fail a correctly traced framework app;
|
|
273
|
+
importing `langchain_core` (as `langchain_openai` does) counts as importing LangChain. Unknown
|
|
274
|
+
frameworks are not guessed.
|
|
275
|
+
If a missing producer is discovered on a later framework import, strict mode logs the
|
|
276
|
+
guidance and exits the whole process with code 1, including when the import occurs in a
|
|
277
|
+
worker thread; the application may already have started by then.
|
|
278
|
+
Selected instrumentors use the same FULL/SKELETON/DROP filtering and privacy
|
|
279
|
+
pipeline. Works with `python -m pkg`, any `python3.x` binary, sibling imports next to your script,
|
|
280
|
+
and child processes your app spawns (they inherit instrumentation the same way `gunicorn --preload`
|
|
281
|
+
workers would). The directory you run `botgauge instrument` from is importable by the launched app,
|
|
282
|
+
after the standard library and installed packages so it can't shadow them. Unlike
|
|
283
|
+
`opentelemetry-instrument`, it is not put on `PYTHONPATH`: child processes don't inherit it, a
|
|
284
|
+
`sitecustomize.py` in it is never run, and `python -P` or `PYTHONSAFEPATH` keep it off the path.
|
|
285
|
+
|
|
286
|
+
Zero-code mode opens an implicit Turn only at a top-level certified **Agent** span, with no
|
|
287
|
+
active `tracing.turn()` and no inbound remote parent. An app that only runs
|
|
288
|
+
chains or LLM calls (a plain LangChain `prompt | llm`, or a LangGraph graph, whose root span is a
|
|
289
|
+
CHAIN) produces no Agent span, so its spans carry no `botgauge.turn.*` attributes; wrap each
|
|
290
|
+
interaction in `tracing.turn()` to group it. An Agent label set after a span starts is read when a
|
|
291
|
+
nested Agent decides whether it is top-level, but a label set on an outer span only after a nested
|
|
292
|
+
Agent's Turn decision (at its start, or at its end if it was labelled late) cannot move the root back
|
|
293
|
+
to the outer span; set the outer Agent's label at start, or use `tracing.turn()`.
|
|
294
|
+
|
|
295
|
+
Forking servers (`gunicorn --preload`, multiprocessing): under `botgauge instrument`, each forked
|
|
296
|
+
worker rebuilds its own BotGauge pipeline automatically (new exporter connection and batch thread,
|
|
297
|
+
same settings), so the application needs no `post_fork` hook. With manual `tracing.init()`, call
|
|
298
|
+
`init()` again after the fork, as before. Either way, a fork-context `multiprocessing` or billiard worker sends
|
|
299
|
+
its queued spans when it exits normally, waiting at most one second (none when export is already
|
|
300
|
+
failing). A pool closed with `terminate()`, which includes leaving a `with Pool(...) as pool:` block,
|
|
301
|
+
stops its workers before that, so their spans are lost: use `pool.close()` and `pool.join()`, or
|
|
302
|
+
call `tracing.flush()` at the end of each task. On macOS only, a forked worker that makes any HTTP request
|
|
303
|
+
after the parent has started threads is killed by the Objective-C runtime; this affects preload apps
|
|
304
|
+
with or without BotGauge, and not Linux. For local development on macOS, set
|
|
305
|
+
`OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES` in the server's environment.
|
|
306
|
+
|
|
307
|
+
PydanticAI is a zero-code producer at its verified versions (PydanticAI 1.25.1 and 2.57.0 with
|
|
308
|
+
`openinference-instrumentation-pydantic-ai` 0.1.30, and 1.25.1 with 0.1.27). It instruments itself natively and
|
|
309
|
+
OpenInference ships a span processor rather than an instrumentor, so BotGauge activates it
|
|
310
|
+
through its own `botgauge.native_producers` entry point: `botgauge instrument` calls
|
|
311
|
+
`Agent.instrument_all()` on BotGauge's provider (GenAI span names, text content recorded with
|
|
312
|
+
`capture="text"` or `"full"`, and with every raw override) and attaches `OpenInferenceSpanProcessor`. If your application already
|
|
313
|
+
instruments PydanticAI, BotGauge reports a duplicate and leaves it unchanged; set
|
|
314
|
+
`BOTGAUGE_PRODUCER_OWNER=pydantic-ai=customer` to declare that ownership explicitly. The PydanticAI 1.25
|
|
315
|
+
cohort runs on OTel 1.39.1, which conflicts with the currently tested non-PydanticAI multi-extra
|
|
316
|
+
OTel 1.44.0 constraints. A resolver dry-run with only PydanticAI's OTel 1.39.1 constraints
|
|
317
|
+
succeeds for `[frameworks]` (every instrumentor at once), but no installed combined runtime,
|
|
318
|
+
`pip check`, or framework tests have been validated. Do not infer that `[frameworks]` or a mixed
|
|
319
|
+
PydanticAI producer is verified merely
|
|
320
|
+
because the extra resolves.
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
botgauge doctor # read-only report: what's active, what's missing, no side effects
|
|
324
|
+
botgauge doctor --strict # exit 1 for uninitialized tracing, propagation or selection problems
|
|
325
|
+
botgauge doctor --json # the same read-only report as machine-readable JSON
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
`doctor` observes only the current process: running it separately from your app cannot inspect
|
|
329
|
+
the app's activation report. `doctor --strict` does not emit a probe span or mutate instrumentation.
|
|
330
|
+
|
|
331
|
+
`botgauge setup --detect` lists recommended producer extras without importing frameworks or installing anything. `botgauge setup --install` explicitly installs the listed extras with pip; no automatic installation occurs on startup.
|
|
332
|
+
|
|
333
|
+
`tracing.init(sample_ratio=0.5)` enables opt-in head sampling for a provider BotGauge creates; default is record everything, unless `OTEL_TRACES_SAMPLER` is set, in which case BotGauge says so at startup (see [Configuration](#configuration)). With the default sampler and with `sample_ratio` (both parent-based, as in OpenTelemetry), a request that continues a caller's trace follows the caller's sampling decision (the last two characters of its `traceparent`): `-00` is not recorded, and `-01` is recorded whatever `sample_ratio` says. An `OTEL_TRACES_SAMPLER` that isn't parent-based, such as `always_on` or `traceidratio`, decides on its own. For a service with untrusted callers, see [Public edges](#public-edges). After `shutdown()`, re-initialization may specify the same ratio for that BotGauge-created global provider. A different ratio or an existing customer provider is rejected because its sampler cannot be changed. A head-dropped trace can't be recovered downstream, and policy/authority/verifier evidence must never depend on sampling. Protected string attribute values are capped at 4096 characters after secret sanitization (only the first 5120 characters are inspected, so sanitizer cost stays bounded; the rest is discarded); TTFT/streaming fields are reserved in the attributes contract but not automatically measured by these isolated producers.
|
|
334
|
+
|
|
335
|
+
### Explicit ingest diagnostic
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
BOTGAUGE_API_KEY="..." botgauge probe --endpoint https://your-collector/v1/traces
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Unlike `doctor`, **`probe` sends data**: one metadata-only `botgauge.probe` span through the
|
|
342
|
+
BotGauge privacy/filter/batch pipeline to the specified OTLP HTTP endpoint. It requires an
|
|
343
|
+
explicit URL (no console fallback), runs in its own process, and exits nonzero if ingest
|
|
344
|
+
acceptance cannot be confirmed. A success confirms OTLP export was acknowledged, **not** that a
|
|
345
|
+
downstream worker normalized or stored the span. The key is read from the environment, not CLI
|
|
346
|
+
arguments. Never point it at production without authorization; it creates a real trace.
|
|
347
|
+
|
|
348
|
+
## Configuration
|
|
349
|
+
|
|
350
|
+
### BotGauge environment variables
|
|
351
|
+
|
|
352
|
+
Arguments to `tracing.init()` win over these. "Both" means `tracing.init()` and
|
|
353
|
+
`botgauge instrument`; "instrument" means only the zero-code launcher reads it (with `init()`, use
|
|
354
|
+
the matching argument).
|
|
355
|
+
|
|
356
|
+
| Variable | Read by | Default | Effect |
|
|
357
|
+
|---|---|---|---|
|
|
358
|
+
| `BOTGAUGE_API_KEY` | Both | unset | Your BotGauge key, sent only as `Authorization: Bearer <key>`. The one setting you need |
|
|
359
|
+
| `BOTGAUGE_ENDPOINT` | Both | `https://api.botgauge.com/v1/traces` when a key is set | Full OTLP/HTTP traces URL of the collector to send to |
|
|
360
|
+
| `BOTGAUGE_CAPTURE` | instrument | `text` | `metadata`, `text` or `full`; see the privacy notes above |
|
|
361
|
+
| `BOTGAUGE_REDACTED` | instrument | `true` | `false` exports the selected content without masking |
|
|
362
|
+
| `BOTGAUGE_CAPTURE_ALLOW_KEYS` | Both | empty | Comma-separated extra attribute keys to keep, globs allowed (`app.tenant_tier,myco.*`); merged with `capture_allow_keys=` |
|
|
363
|
+
| `BOTGAUGE_TRACE_SCOPE` | Both | filtered | `all` exports infrastructure spans (HTTP, database) in full instead of filtering them |
|
|
364
|
+
| `BOTGAUGE_STRICT` | instrument | off | `1` stops the app from starting on instrumentation problems (same as `--strict`) |
|
|
365
|
+
| `BOTGAUGE_VERIFIED_ONLY` | instrument | off | `1` traces only framework versions BotGauge verified |
|
|
366
|
+
| `BOTGAUGE_PRODUCER_OWNER` | instrument | empty | `langchain=customer` (comma-separated) leaves a framework you already instrument to you |
|
|
367
|
+
| `BOTGAUGE_ALLOW_INSECURE_HTTP` | Both | `false` | `true` allows sending the key to a remote `http://` endpoint. Local addresses need no opt-in |
|
|
368
|
+
| `BOTGAUGE_CONSOLE_EXPORT` | Both | off | `1` prints spans to stdout when no key or endpoint is set. Local development only |
|
|
369
|
+
|
|
370
|
+
### OpenTelemetry environment variables
|
|
371
|
+
|
|
372
|
+
BotGauge is built on the OpenTelemetry SDK, so some standard variables affect it too. Where a row
|
|
373
|
+
says "when BotGauge creates the provider", it applies when you call `tracing.init()` without
|
|
374
|
+
`tracer_provider=` and no provider is set up yet; otherwise your own provider's configuration
|
|
375
|
+
applies.
|
|
376
|
+
|
|
377
|
+
| Variable | Effect on BotGauge |
|
|
378
|
+
|---|---|
|
|
379
|
+
| `OTEL_SDK_DISABLED=true` | **Turns tracing off.** No spans are recorded or exported, with or without your own provider. Use it to disable BotGauge in tests or one environment without changing code |
|
|
380
|
+
| `OTEL_SERVICE_NAME`, `OTEL_RESOURCE_ATTRIBUTES` | Added to the exported resource when BotGauge creates the provider |
|
|
381
|
+
| `OTEL_TRACES_SAMPLER`, `OTEL_TRACES_SAMPLER_ARG` | Apply when BotGauge creates the provider and `sample_ratio=` is not given. A sampler set for another tool therefore samples BotGauge's traces too; BotGauge prints a one-time warning at startup when it will drop traces, and `botgauge doctor` shows the active sampler. Pass `sample_ratio=1.0` to record everything regardless |
|
|
382
|
+
| `OTEL_BSP_SCHEDULE_DELAY`, `OTEL_BSP_MAX_QUEUE_SIZE`, `OTEL_BSP_MAX_EXPORT_BATCH_SIZE`, `OTEL_BSP_EXPORT_TIMEOUT` | Tune the batching of BotGauge's own export. An unusable value is logged once on the `botgauge` logger and OpenTelemetry's default is used |
|
|
383
|
+
| `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT` and the other span limit variables | Apply when BotGauge creates the provider. Protected string values are already capped at 4096 characters |
|
|
384
|
+
| `OTEL_PROPAGATORS` | Which headers carry trace context between services. BotGauge never replaces your propagator. For a service with untrusted callers, see [Public edges](#public-edges). The values for this and the sampler variables are in [OpenTelemetry's SDK configuration](https://opentelemetry.io/docs/languages/sdk-configuration/general/) |
|
|
385
|
+
| `OTEL_EXPORTER_OTLP_*` | **Ignored** by BotGauge's exporter. They stay with your own exporters, which never receive the BotGauge key |
|
|
386
|
+
|
|
387
|
+
### Logs
|
|
388
|
+
|
|
389
|
+
BotGauge reports problems (a rejected key, an invalid setting, an untraced framework) as warnings on
|
|
390
|
+
the standard Python logger named `botgauge`. Route or silence them like any other logger, for
|
|
391
|
+
example `logging.getLogger("botgauge").setLevel(logging.ERROR)`. For a full picture of what is
|
|
392
|
+
active, run `botgauge doctor`, or call `tracing.doctor.report()` inside your app.
|
|
393
|
+
|
|
394
|
+
## Public edges
|
|
395
|
+
|
|
396
|
+
If your application accepts requests from an untrusted or public caller, that caller's own
|
|
397
|
+
`traceparent` header should not be trusted as the real parent span — an attacker could otherwise
|
|
398
|
+
inject an arbitrary trace/span ID with no authority consequences intended.
|
|
399
|
+
|
|
400
|
+
**If the service runs server or MCP instrumentation, turn off incoming trace context for the
|
|
401
|
+
whole process.** That includes `botgauge instrument` and any web framework instrumentation you add
|
|
402
|
+
(Flask, Django, FastAPI and other ASGI/WSGI servers, gRPC). These start the request's span from the
|
|
403
|
+
caller's `traceparent`, and the MCP instrumentation from a request's `_meta` field, over stdio as
|
|
404
|
+
well as HTTP, before your code runs. So the caller decides:
|
|
405
|
+
|
|
406
|
+
- the trace ID of everything the request records;
|
|
407
|
+
- whether the request is recorded at all: with OpenTelemetry's default sampler, a `traceparent`
|
|
408
|
+
ending in `-00` turns recording off for the whole request, and `-01` turns it on whatever
|
|
409
|
+
`sample_ratio` says.
|
|
410
|
+
|
|
411
|
+
`extract_context()` (below) can't undo this, because the caller's context is already current when
|
|
412
|
+
it runs. Turn incoming trace context off instead:
|
|
413
|
+
|
|
414
|
+
- `OTEL_PROPAGATORS=none`, on OpenTelemetry 1.33 or newer. Older versions don't accept `none` and
|
|
415
|
+
stop at startup with "Propagator none not found".
|
|
416
|
+
- On any version, once at startup:
|
|
417
|
+
```python
|
|
418
|
+
from opentelemetry.propagate import set_global_textmap
|
|
419
|
+
from opentelemetry.propagators.composite import CompositePropagator
|
|
420
|
+
|
|
421
|
+
set_global_textmap(CompositePropagator([]))
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Both also stop the service sending trace context to the services it calls, so use them only in
|
|
425
|
+
processes that face untrusted callers. For HTTP only, removing `traceparent`, `tracestate` and
|
|
426
|
+
`baggage` from incoming requests in middleware that runs before the instrumentation also works.
|
|
427
|
+
|
|
428
|
+
**Without server or MCP instrumentation**, where your code reads the headers itself, extract
|
|
429
|
+
context at that specific boundary (e.g. one public-facing route, not your whole process) with
|
|
430
|
+
`trust_incoming_context=False`:
|
|
431
|
+
|
|
432
|
+
```python
|
|
433
|
+
from botgauge import tracing
|
|
434
|
+
|
|
435
|
+
ctx, link = tracing.extract_context(request.headers, trust_incoming_context=False)
|
|
436
|
+
tracer = tracing.get_tracer()
|
|
437
|
+
with tracer.start_as_current_span("handle_request", context=ctx, links=[link] if link else []):
|
|
438
|
+
...
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
With `trust_incoming_context=False`, `extract_context()` retains the current local context for parenting
|
|
442
|
+
and returns a link to a valid incoming span. The example attaches that link with
|
|
443
|
+
`botgauge.link.relation="continuation"`; the untrusted claim is not used as the parent. A new
|
|
444
|
+
trace starts only when no valid local parent is active. Internal/trusted service-to-service
|
|
445
|
+
hops should keep the default (`trust_incoming_context=True`), which is what most calls need.
|
|
446
|
+
|
|
447
|
+
## Known limits
|
|
448
|
+
|
|
449
|
+
- Each framework is verified on its own, at the exact versions the getting-started guide lists.
|
|
450
|
+
Combined or overlapping producer profiles are not verified.
|
|
451
|
+
- A direct OpenAI + Anthropic mixed-producer test covers shared turn context and
|
|
452
|
+
duplicate/ownership handling. With LangChain and direct OpenAI both active, explicit ownership
|
|
453
|
+
emits one LLM span; activating both producers emits two sibling LLM spans on the same client.
|
|
454
|
+
- PydanticAI 1.25.1 needs OpenTelemetry 1.39.1 in an isolated environment, so it is not part of
|
|
455
|
+
the compatible multi-extra set.
|
|
456
|
+
- A nightly job tests the latest framework versions; a passing drift test never expands the
|
|
457
|
+
pinned compatibility registry by itself.
|