deepctl-telemetry 0.0.4__tar.gz → 0.0.6__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.
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/PKG-INFO +1 -1
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/pyproject.toml +1 -1
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry/__init__.py +1 -1
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry/client.py +53 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/PKG-INFO +1 -1
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/README.md +0 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/setup.cfg +0 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry/notice.py +0 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/SOURCES.txt +0 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/dependency_links.txt +0 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/requires.txt +0 -0
- {deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deepctl-telemetry"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.6" # x-release-please-version
|
|
8
8
|
description = "Opt-out phone-home telemetry for deepctl"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -103,13 +103,66 @@ def _read_cli_version() -> str:
|
|
|
103
103
|
return importlib.metadata.version("deepctl")
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
_MCP_NOISE_LOGGERS = frozenset(
|
|
107
|
+
{
|
|
108
|
+
"mcp.client.streamable_http",
|
|
109
|
+
"mcp.server.lowlevel.server",
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _is_mcp_transient_noise(event: Event) -> bool:
|
|
115
|
+
"""Identify log events from the MCP SDK that are not actionable bugs.
|
|
116
|
+
|
|
117
|
+
`dg mcp` embeds the upstream `mcp` Python SDK, which logs to Sentry via
|
|
118
|
+
the logging integration whenever the upstream MCP server returns 5xx
|
|
119
|
+
(handled by the client) or the stdio peer closes mid-message (handled by
|
|
120
|
+
the server). Both are recovered internally. Surfacing them as Sentry
|
|
121
|
+
issues just creates triage cost for the DX team and hides real CLI bugs.
|
|
122
|
+
|
|
123
|
+
Any unhandled exception is kept regardless of logger.
|
|
124
|
+
"""
|
|
125
|
+
if (event.get("logger") or "") not in _MCP_NOISE_LOGGERS:
|
|
126
|
+
return False
|
|
127
|
+
for exc in (event.get("exception") or {}).get("values") or []:
|
|
128
|
+
mechanism = exc.get("mechanism") or {}
|
|
129
|
+
if mechanism.get("handled") is False:
|
|
130
|
+
return False
|
|
131
|
+
return True
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _is_broken_pipe(event: Event) -> bool:
|
|
135
|
+
"""Identify events caused by writing to a closed/broken output stream.
|
|
136
|
+
|
|
137
|
+
When `dg mcp` runs as an MCP server, the host can close stdio while the
|
|
138
|
+
CLI is still finishing up. Any residual write (an advisory notification, a
|
|
139
|
+
console error message) then raises ``BrokenPipeError`` — or rich's
|
|
140
|
+
``ValueError: I/O operation on closed file`` when the underlying stream is
|
|
141
|
+
already closed. Neither is an actionable CLI bug, so drop them rather than
|
|
142
|
+
page the DX team.
|
|
143
|
+
"""
|
|
144
|
+
for exc in (event.get("exception") or {}).get("values") or []:
|
|
145
|
+
exc_type = exc.get("type") or ""
|
|
146
|
+
if exc_type == "BrokenPipeError":
|
|
147
|
+
return True
|
|
148
|
+
if exc_type == "ValueError" and "closed file" in (exc.get("value") or ""):
|
|
149
|
+
return True
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
|
|
106
153
|
def _scrub_event(event: Event, _hint: Hint) -> Event | None:
|
|
107
154
|
"""Drop request bodies, headers, and any user-identifying data.
|
|
108
155
|
|
|
109
156
|
Sentry SDK already filters most PII via send_default_pii=False, but
|
|
110
157
|
Auth tokens, project IDs, and file paths can still leak through
|
|
111
158
|
breadcrumbs and exception messages. This is a defense-in-depth scrub.
|
|
159
|
+
|
|
160
|
+
Also drops known-noise events (see ``_is_mcp_transient_noise`` and
|
|
161
|
+
``_is_broken_pipe``).
|
|
112
162
|
"""
|
|
163
|
+
if _is_mcp_transient_noise(event) or _is_broken_pipe(event):
|
|
164
|
+
return None
|
|
165
|
+
|
|
113
166
|
request: dict[str, Any] = event.get("request") or {}
|
|
114
167
|
if "headers" in request:
|
|
115
168
|
request["headers"] = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/requires.txt
RENAMED
|
File without changes
|
{deepctl_telemetry-0.0.4 → deepctl_telemetry-0.0.6}/src/deepctl_telemetry.egg-info/top_level.txt
RENAMED
|
File without changes
|