feat(code): surface tracing in doctor and config show (#4163)

`dcode doctor` now reports a tracing summary, and `dcode config
show`/`list` group tracing options under a dedicated `Tracing` section.

---

Makes LangSmith tracing configuration easy to inspect from the CLI
without digging through env vars.

`dcode doctor` gains a brief `Tracing` section reporting whether tracing
is enabled, whether credentials are configured (presence only — the API
key value is never read or printed), the resolved project, and any
custom endpoint or replica project. It stays fully offline and flags a
problem only when tracing is enabled without a key *and* without a
custom endpoint, mirroring the existing orphaned-tracing guard (a
keyless self-hosted endpoint is a valid, healthy setup). The detection
lives in a new offline `get_tracing_status` helper so it is
independently testable.

The `tracing.*` options move into their own `Tracing` group so `config
show` and `config list` render them as a dedicated section instead of
burying them under `Models`. Grouping is first-seen order, so the new
section appears right after `Models` with no other changes.

## Test Plan
- [ ] `dcode doctor` shows a `Tracing` section; with
`LANGSMITH_TRACING=true` but no key/endpoint, the `Credentials` item is
flagged unhealthy.
- [ ] `dcode config show` lists a `Tracing` group.

Made by [Open
SWE](https://openswe.vercel.app/agents/b0ab8323-a16c-9185-e910-a4de6bdc11ae)

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Mason Daugherty
2026-06-23 01:47:32 -04:00
committed by GitHub
parent 9e21c346a6
commit 2bb3e44243
6 changed files with 613 additions and 14 deletions
+200 -7
View File
@@ -351,7 +351,9 @@ def _quiet_sdk_tracing_logging() -> None:
sdk_logger.addHandler(logging.NullHandler())
def _load_langsmith_profile_config() -> _LangSmithProfileConfig | None:
def _load_langsmith_profile_config(
env: dict[str, str] | None = None,
) -> _LangSmithProfileConfig | None:
"""Return the active LangSmith profile client config, if available."""
try:
client_module = importlib.import_module("langsmith.client")
@@ -362,12 +364,18 @@ def _load_langsmith_profile_config() -> _LangSmithProfileConfig | None:
if profiles is None:
return None
return profiles.load_profile_client_config()
if env is None:
return profiles.load_profile_client_config()
from unittest.mock import patch
with patch.dict(os.environ, env, clear=True):
return profiles.load_profile_client_config()
def _has_langsmith_profile_credentials() -> bool:
def _has_langsmith_profile_credentials(env: dict[str, str] | None = None) -> bool:
"""Return whether the LangSmith profile config has usable auth material."""
config = _load_langsmith_profile_config()
config = _load_langsmith_profile_config(env)
if config is None:
return False
@@ -376,9 +384,9 @@ def _has_langsmith_profile_credentials() -> bool:
)
def _has_langsmith_profile_custom_endpoint() -> bool:
def _has_langsmith_profile_custom_endpoint(env: dict[str, str] | None = None) -> bool:
"""Return whether the LangSmith profile points at a custom endpoint."""
config = _load_langsmith_profile_config()
config = _load_langsmith_profile_config(env)
if config is None:
return False
@@ -2456,12 +2464,24 @@ def get_langsmith_replica_projects() -> list[str]:
Parses `DEEPAGENTS_CODE_LANGSMITH_REPLICA_PROJECTS` (comma-separated) into a
de-duplicated, order-preserving list.
Returns:
Project names, or `[]` when the env var is unset or empty.
"""
return _get_langsmith_replica_projects_from(dict(os.environ))
def _get_langsmith_replica_projects_from(env: dict[str, str]) -> list[str]:
"""Parse replica project names from an environment snapshot.
Args:
env: Environment mapping to read.
Returns:
Project names, or `[]` when the env var is unset or empty.
"""
from deepagents_code._env_vars import LANGSMITH_REPLICA_PROJECTS
raw = os.environ.get(LANGSMITH_REPLICA_PROJECTS)
raw = env.get(LANGSMITH_REPLICA_PROJECTS)
if not raw:
return []
return list(dict.fromkeys(p.strip() for p in raw.split(",") if p.strip()))
@@ -2489,6 +2509,18 @@ def get_langsmith_replica_project() -> str | None:
The first configured replica project name, or `None` when none are set.
"""
extras = get_langsmith_replica_projects()
return _get_first_langsmith_replica_project(extras)
def _get_first_langsmith_replica_project(extras: list[str]) -> str | None:
"""Return the first configured LangSmith replica project, if any.
Args:
extras: Parsed replica project names.
Returns:
The first configured replica project name, or `None` when none are set.
"""
if not extras:
return None
if len(extras) > 1:
@@ -2503,6 +2535,167 @@ def get_langsmith_replica_project() -> str | None:
return extras[0]
_TRACING_BRIDGED_ENABLE_ENV_VARS = ("LANGSMITH_TRACING", "LANGCHAIN_TRACING_V2")
"""Tracing flags bootstrap propagates from a `DEEPAGENTS_CODE_` prefix.
`dcode doctor` runs before `_ensure_bootstrap` bridges these to their canonical
names, so it must resolve them prefix-aware (via `resolve_env_var`) to predict
the runtime's effective state. The remaining flags in `_TRACING_ENABLE_ENV_VARS`
are not bridged, so only their canonical form takes effect.
"""
def _tracing_enabled_from(env: dict[str, str]) -> bool:
"""Return whether tracing is (or will be) enabled, prefix-aware.
Mirrors the runtime: `DEEPAGENTS_CODE_`-prefixed forms of the bridged flags
count (bootstrap propagates them), while the non-bridged flags are honored
only in their canonical form.
Args:
env: Environment mapping to read.
"""
from deepagents_code._env_vars import classify_env_bool
for var in _TRACING_BRIDGED_ENABLE_ENV_VARS:
raw = _resolve_env_var_from(env, var)
if raw is not None and classify_env_bool(raw):
return True
return any(
classify_env_bool(env[var])
for var in _TRACING_ENABLE_ENV_VARS
if var not in _TRACING_BRIDGED_ENABLE_ENV_VARS and var in env
)
def _tracing_enabled() -> bool:
"""Return whether tracing is (or will be) enabled, prefix-aware."""
return _tracing_enabled_from(dict(os.environ))
def _tracing_has_credentials_from(env: dict[str, str]) -> bool:
"""Return whether a LangSmith API key (env or active profile) is available.
Both API-key vars are bridged from a `DEEPAGENTS_CODE_` prefix at bootstrap,
so resolve them prefix-aware to match what the runtime will see.
Args:
env: Environment mapping to read.
"""
has_key = any(_resolve_env_var_from(env, var) for var in _TRACING_API_KEY_ENV_VARS)
return has_key or _has_langsmith_profile_credentials(env)
def _tracing_endpoint_from(env: dict[str, str]) -> str | None:
"""Return a custom tracing endpoint (env or active profile), if configured.
The endpoint vars are not bridged from a `DEEPAGENTS_CODE_` prefix and the
LangSmith SDK reads them canonically, so only the canonical names (plus the
active profile's `api_url`) are consulted here.
Args:
env: Environment mapping to read.
"""
for var in _TRACING_ENDPOINT_ENV_VARS:
value = (env.get(var) or "").strip()
if value:
return value
config = _load_langsmith_profile_config(env)
if config is not None:
api_url = (config.api_url or "").strip()
if api_url:
return api_url
return None
def _resolve_tracing_project_from(env: dict[str, str]) -> str:
"""Resolve the project agent traces would route to, without bootstrap.
The reported project matches the `tracing.langsmith_project` manifest
option's env precedence: the prefixed `DEEPAGENTS_CODE_LANGSMITH_PROJECT`
(skipped when empty), then bare `LANGSMITH_PROJECT`, then the default.
Unlike `resolve_env_var`, an empty prefixed value does not shadow a real
`LANGSMITH_PROJECT`.
Args:
env: Environment mapping to read.
Returns:
The resolved project name, or the default when none is configured.
"""
from deepagents_code._env_vars import LANGSMITH_PROJECT
from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
for name in (LANGSMITH_PROJECT, "LANGSMITH_PROJECT"):
value = env.get(name)
if value:
return value
return LANGSMITH_PROJECT_DEFAULT
def _tracing_diagnostic_env() -> dict[str, str]:
"""Return the dotenv-aware environment snapshot for tracing diagnostics.
Returns:
Environment mapping with project/global dotenv values applied using the
same precedence as bootstrap, without mutating `os.environ`.
"""
from deepagents_code.project_utils import get_server_project_context
ctx = get_server_project_context()
return _preview_dotenv_environ(start_path=ctx.user_cwd if ctx else None)
@dataclass
class TracingStatus:
"""Offline snapshot of LangSmith tracing configuration for diagnostics.
Carries only presence/identity facts — never API keys or other secret
values — so it is safe to render in `dcode doctor` output.
"""
enabled: bool
"""Whether a tracing flag is truthy in the environment."""
has_credentials: bool
"""Whether an API key or profile credential is resolvable."""
endpoint: str | None
"""Custom (self-hosted/proxied) endpoint URL, if one is configured."""
project: str | None
"""Resolved configured project name, independent of active trace ingestion."""
replica_project: str | None
"""Extra project agent runs are mirrored to, if configured."""
def get_tracing_status() -> TracingStatus:
"""Summarize LangSmith tracing configuration for diagnostics.
Reads only the local environment and the active LangSmith profile; never
contacts the network and never exposes secret values. All fields are
resolved prefix-/profile-aware so the report matches what the runtime does
after bootstrap, even though `dcode doctor` runs before it.
Returns:
A `TracingStatus` snapshot describing the current tracing setup.
"""
env = _tracing_diagnostic_env()
enabled = _tracing_enabled_from(env)
has_credentials = _tracing_has_credentials_from(env)
endpoint = _tracing_endpoint_from(env)
return TracingStatus(
enabled=enabled,
has_credentials=has_credentials,
endpoint=endpoint,
project=_resolve_tracing_project_from(env),
replica_project=_get_first_langsmith_replica_project(
_get_langsmith_replica_projects_from(env)
),
)
class LangSmithLookupError(Exception):
"""Base class for typed LangSmith project URL lookup failures.
+5 -4
View File
@@ -840,7 +840,7 @@ _STATIC_OPTIONS: tuple[ConfigOption, ...] = (
default=False,
env_var=_env_vars.NO_TERMINAL_ESCAPE,
),
# --- Models / Tracing ----------------------------------------------
# --- Models --------------------------------------------------------
ConfigOption(
key="models.default",
group="Models",
@@ -856,9 +856,10 @@ _STATIC_OPTIONS: tuple[ConfigOption, ...] = (
kind=OptionKind.STR,
toml_keys=("models", "recent"),
),
# --- Tracing -------------------------------------------------------
ConfigOption(
key="tracing.langsmith_project",
group="Models",
group="Tracing",
summary="LangSmith project name for deepagents agent traces.",
kind=OptionKind.STR,
default=LANGSMITH_PROJECT_DEFAULT,
@@ -868,14 +869,14 @@ _STATIC_OPTIONS: tuple[ConfigOption, ...] = (
),
ConfigOption(
key="tracing.user_id",
group="Models",
group="Tracing",
summary="User identifier attached to LangSmith trace metadata.",
kind=OptionKind.STR,
env_var=_env_vars.USER_ID,
),
ConfigOption(
key="tracing.langsmith_replica_projects",
group="Models",
group="Tracing",
summary=(
"Extra LangSmith project to also write agent traces to. "
"Comma-separated for forward-compatibility, but only the first "
+74
View File
@@ -16,6 +16,7 @@ import platform
import sys
from dataclasses import dataclass, field
from typing import TYPE_CHECKING
from urllib.parse import urlsplit
from deepagents_code.output import write_json
@@ -186,6 +187,65 @@ def _collect_updates() -> DiagnosticSection:
return DiagnosticSection(title="Updates", items=items)
def _sanitize_endpoint(endpoint: str) -> str:
"""Return a paste-safe custom endpoint identifier.
Args:
endpoint: Configured endpoint URL.
Returns:
The endpoint origin when parseable, otherwise a generic configured
marker that does not include user-controlled URL contents.
"""
parsed = urlsplit(endpoint.strip())
if not parsed.scheme or not parsed.hostname:
return "(custom endpoint configured)"
host = parsed.hostname
if ":" in host and not host.startswith("["):
host = f"[{host}]"
try:
port = parsed.port
except ValueError:
port = None
netloc = f"{host}:{port}" if port is not None else host
return f"{parsed.scheme}://{netloc}"
def _collect_tracing() -> DiagnosticSection:
"""Collect LangSmith tracing status from env and profile (offline).
Credentials are reported as configured/not configured only — the API key
value is never read or printed. The `Credentials` item is flagged as a
problem only when tracing is enabled without a key and without a custom
endpoint, mirroring the runtime's orphaned-tracing guard (a keyless
self-hosted endpoint is a valid, healthy setup).
Returns:
The `Tracing` section.
"""
from deepagents_code.config import get_tracing_status
status = get_tracing_status()
creds_required = status.enabled and status.endpoint is None
items = [
DiagnosticItem("Tracing", "enabled" if status.enabled else "disabled"),
DiagnosticItem(
"Credentials",
"configured" if status.has_credentials else "not configured",
ok=status.has_credentials or not creds_required,
),
DiagnosticItem("Project", status.project or "(unset)"),
]
if status.endpoint:
items.append(DiagnosticItem("Endpoint", _sanitize_endpoint(status.endpoint)))
if status.replica_project:
items.append(DiagnosticItem("Replica project", status.replica_project))
return DiagnosticSection(title="Tracing", items=items)
def _path_status(label: str, path: object) -> DiagnosticItem:
"""Build an item reporting a path and whether it exists on disk.
@@ -245,6 +305,7 @@ def collect_sections() -> list[DiagnosticSection]:
return [
_collect_diagnostics(),
_collect_updates(),
_collect_tracing(),
_collect_configuration(),
]
@@ -286,6 +347,19 @@ def _render_text(sections: list[DiagnosticSection]) -> None:
)
console.print()
console.print(
" Tip: Run `dcode config show` or `dcode config get <key>` "
"to drill into config details.",
style=theme.MUTED,
highlight=False,
)
console.print(
" Run `dcode --version` (or `dcode -v`) for dependency versions.",
style=theme.MUTED,
highlight=False,
)
console.print()
def run_doctor_command(args: argparse.Namespace) -> int:
"""Run `dcode doctor`, printing diagnostics as text or JSON.
+12
View File
@@ -477,6 +477,18 @@ def show_doctor_help() -> None:
console.print(" dcode doctor")
console.print(" dcode doctor --json")
console.print()
console.print(
"Tip: Run `dcode config show` or `dcode config get <key>` "
"to drill into config details.",
style=theme.MUTED,
highlight=False,
)
console.print(
" Run `dcode --version` (or `dcode -v`) for dependency versions.",
style=theme.MUTED,
highlight=False,
)
console.print()
def _print_mcp_discovery_paths() -> None:
+229 -1
View File
@@ -4,7 +4,7 @@ import logging
import time
from collections.abc import Iterator
from pathlib import Path
from typing import Any
from typing import Any, ClassVar
from unittest.mock import Mock, patch
import pytest
@@ -2109,6 +2109,234 @@ class TestDisableOrphanedTracing:
assert os.environ["LANGSMITH_TRACING"] == "false"
class TestGetTracingStatus:
"""Tests for get_tracing_status()."""
_CLEAN: ClassVar[dict[str, str]] = {
"LANGSMITH_TRACING_V2": "",
"LANGCHAIN_TRACING_V2": "",
"LANGSMITH_TRACING": "",
"LANGCHAIN_TRACING": "",
"LANGSMITH_API_KEY": "",
"LANGCHAIN_API_KEY": "",
"LANGSMITH_ENDPOINT": "",
"LANGCHAIN_ENDPOINT": "",
"LANGSMITH_PROJECT": "",
"DEEPAGENTS_CODE_LANGSMITH_PROJECT": "",
"DEEPAGENTS_CODE_LANGSMITH_TRACING": "",
"DEEPAGENTS_CODE_LANGCHAIN_TRACING_V2": "",
"DEEPAGENTS_CODE_LANGSMITH_API_KEY": "",
"DEEPAGENTS_CODE_LANGCHAIN_API_KEY": "",
"LANGSMITH_REPLICA_PROJECTS": "",
"DEEPAGENTS_CODE_LANGSMITH_REPLICA_PROJECTS": "",
"LANGSMITH_PROFILE": "",
"LANGSMITH_CONFIG_FILE": "/__deepagents_missing_langsmith_config__.json",
}
def test_disabled_when_no_flags(self) -> None:
"""A clean environment reports tracing off with configured project metadata."""
from deepagents_code.config import get_tracing_status
from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
with patch.dict("os.environ", self._CLEAN, clear=False):
status = get_tracing_status()
assert status.enabled is False
assert status.has_credentials is False
assert status.endpoint is None
assert status.project == LANGSMITH_PROJECT_DEFAULT
assert status.replica_project is None
def test_prefixed_flag_and_key_are_detected(self) -> None:
"""`DEEPAGENTS_CODE_`-prefixed tracing/key vars resolve like the runtime.
`dcode doctor` runs before bootstrap bridges these to canonical names,
so a user with only the supported prefixed vars must still read as
enabled/configured with the prefixed project resolved.
"""
from deepagents_code.config import get_tracing_status
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_TRACING"] = "true"
env["DEEPAGENTS_CODE_LANGSMITH_API_KEY"] = "lsv2_test"
env["DEEPAGENTS_CODE_LANGSMITH_PROJECT"] = "prefixed-proj"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.enabled is True
assert status.has_credentials is True
assert status.project == "prefixed-proj"
def test_dotenv_values_are_detected(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Doctor tracing status sees the same dotenv values as bootstrap."""
import deepagents_code.config as config_mod
project = tmp_path / "project"
project.mkdir()
(project / ".env").write_text(
"DEEPAGENTS_CODE_LANGSMITH_TRACING=true\n"
"DEEPAGENTS_CODE_LANGSMITH_API_KEY=lsv2_dotenv\n"
"DEEPAGENTS_CODE_LANGSMITH_PROJECT=dotenv-proj\n"
"DEEPAGENTS_CODE_LANGSMITH_REPLICA_PROJECTS=replica\n",
encoding="utf-8",
)
monkeypatch.chdir(project)
monkeypatch.setattr(
config_mod,
"_GLOBAL_DOTENV_PATH",
tmp_path / "missing-global.env",
)
config_mod._dotenv_loaded_values.clear()
with patch.dict("os.environ", {}, clear=True):
status = config_mod.get_tracing_status()
assert status.enabled is True
assert status.has_credentials is True
assert status.project == "dotenv-proj"
assert status.replica_project == "replica"
def test_dotenv_profile_credentials_are_detected(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
"""Doctor tracing status uses dotenv profile selectors for credentials."""
import deepagents_code.config as config_mod
langsmith = tmp_path / "langsmith.json"
langsmith.write_text(
"{"
'"current_profile":"default",'
'"profiles":{'
'"default":{},'
'"dotenv":{"api_key":"lsv2_profile","api_url":"http://localhost:1984"}'
"}"
"}",
encoding="utf-8",
)
project = tmp_path / "project"
project.mkdir()
(project / ".env").write_text(
"DEEPAGENTS_CODE_LANGSMITH_TRACING=true\n"
f"LANGSMITH_CONFIG_FILE={langsmith}\n"
"LANGSMITH_PROFILE=dotenv\n",
encoding="utf-8",
)
monkeypatch.chdir(project)
monkeypatch.setattr(
config_mod,
"_GLOBAL_DOTENV_PATH",
tmp_path / "missing-global.env",
)
config_mod._dotenv_loaded_values.clear()
with patch.dict("os.environ", {}, clear=True):
status = config_mod.get_tracing_status()
assert status.enabled is True
assert status.has_credentials is True
assert status.endpoint == "http://localhost:1984"
def test_empty_prefixed_flag_shadows_canonical(self) -> None:
"""An empty `DEEPAGENTS_CODE_` flag suppresses the canonical one.
Mirrors `resolve_env_var`/bootstrap: a present-but-empty prefixed var
disables tracing even when the canonical flag is truthy.
"""
from deepagents_code.config import get_tracing_status
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_TRACING"] = ""
env["LANGSMITH_TRACING"] = "true"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.enabled is False
def test_canonical_non_bridged_flag_enables(self) -> None:
"""A canonical, non-bridged flag (`LANGSMITH_TRACING_V2`) enables tracing."""
from deepagents_code.config import get_tracing_status
env = dict(self._CLEAN)
env["LANGSMITH_TRACING_V2"] = "true"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.enabled is True
def test_keyless_custom_endpoint_resolves_project(self) -> None:
"""A keyless custom endpoint counts as active and resolves the project."""
from deepagents_code.config import get_tracing_status
from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_TRACING"] = "true"
env["LANGSMITH_ENDPOINT"] = "http://localhost:1984"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.enabled is True
assert status.has_credentials is False
assert status.endpoint == "http://localhost:1984"
assert status.project == LANGSMITH_PROJECT_DEFAULT
def test_profile_credentials_are_detected(self, tmp_path: Path) -> None:
"""A LangSmith profile API key counts as credentials (no env key needed)."""
from deepagents_code.config import get_tracing_status
from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
config = tmp_path / "config.json"
config.write_text(
'{"current_profile":"default","profiles":{"default":{"api_key":"lsv2_profile"}}}',
encoding="utf-8",
)
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_TRACING"] = "true"
env["LANGSMITH_CONFIG_FILE"] = str(config)
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.enabled is True
assert status.has_credentials is True
assert status.project == LANGSMITH_PROJECT_DEFAULT
def test_project_resolved_when_enabled_without_auth(self) -> None:
"""Tracing auth state does not hide configured project metadata."""
from deepagents_code.config import get_tracing_status
from deepagents_code.config_manifest import LANGSMITH_PROJECT_DEFAULT
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_TRACING"] = "true"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.enabled is True
assert status.has_credentials is False
assert status.project == LANGSMITH_PROJECT_DEFAULT
def test_empty_prefixed_project_falls_through_to_canonical(self) -> None:
"""An empty prefixed project must not shadow a real `LANGSMITH_PROJECT`.
Mirrors the manifest/runtime contract: `resolve_scalar` skips an empty
`DEEPAGENTS_CODE_LANGSMITH_PROJECT` and uses bare `LANGSMITH_PROJECT`,
unlike `resolve_env_var`, which would shadow it and report the default.
"""
from deepagents_code.config import get_tracing_status
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_TRACING"] = "true"
env["DEEPAGENTS_CODE_LANGSMITH_API_KEY"] = "lsv2_test"
env["DEEPAGENTS_CODE_LANGSMITH_PROJECT"] = ""
env["LANGSMITH_PROJECT"] = "prod"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.project == "prod"
def test_reports_first_replica_project(self) -> None:
"""Only the first replica project is reported (server mirrors one)."""
from deepagents_code.config import get_tracing_status
env = dict(self._CLEAN)
env["DEEPAGENTS_CODE_LANGSMITH_REPLICA_PROJECTS"] = "replica-a, replica-b"
with patch.dict("os.environ", env, clear=False):
status = get_tracing_status()
assert status.replica_project == "replica-a"
class TestQuietSdkTracingLogging:
"""Tests for _quiet_sdk_tracing_logging()."""
+93 -2
View File
@@ -61,11 +61,12 @@ class TestCollectSections:
"""Tests for the diagnostic data collection."""
def test_section_titles(self) -> None:
"""All three sections are collected in display order."""
"""All sections are collected in display order."""
sections = collect_sections()
assert [s.title for s in sections] == [
"Diagnostics",
"Updates",
"Tracing",
"Configuration",
]
@@ -82,6 +83,87 @@ class TestCollectSections:
assert "Install method" in labels
class TestCollectTracing:
"""Tests for the Tracing diagnostic section."""
def _section(self, **kwargs: object) -> DiagnosticSection:
from deepagents_code.config import TracingStatus
from deepagents_code.doctor import _collect_tracing
defaults: dict[str, object] = {
"enabled": False,
"has_credentials": False,
"endpoint": None,
"project": None,
"replica_project": None,
}
defaults.update(kwargs)
status = TracingStatus(**defaults) # type: ignore[arg-type]
with patch("deepagents_code.config.get_tracing_status", return_value=status):
return _collect_tracing()
def test_disabled_is_healthy(self) -> None:
"""A disabled, keyless setup is informational, not a failure."""
section = self._section(enabled=False, project="deepagents-code")
assert section.title == "Tracing"
assert section.ok is True
labels = {item.label: item.value for item in section.items}
assert labels["Tracing"] == "disabled"
assert labels["Credentials"] == "not configured"
assert labels["Project"] == "deepagents-code"
def test_enabled_without_credentials_is_unhealthy(self) -> None:
"""Tracing on with no key and no endpoint is a genuine problem."""
section = self._section(enabled=True, has_credentials=False)
assert section.ok is False
creds = next(i for i in section.items if i.label == "Credentials")
assert creds.ok is False
def test_enabled_with_credentials_is_healthy(self) -> None:
"""A configured key keeps the section healthy and reports the project."""
section = self._section(enabled=True, has_credentials=True, project="my-proj")
assert section.ok is True
labels = {item.label: item.value for item in section.items}
assert labels["Tracing"] == "enabled"
assert labels["Credentials"] == "configured"
assert labels["Project"] == "my-proj"
def test_keyless_custom_endpoint_is_healthy(self) -> None:
"""A custom endpoint is a valid keyless setup, so it stays healthy."""
section = self._section(
enabled=True,
has_credentials=False,
endpoint="http://localhost:1984",
)
assert section.ok is True
labels = {item.label: item.value for item in section.items}
assert labels["Endpoint"] == "http://localhost:1984"
def test_endpoint_is_sanitized(self) -> None:
"""Endpoint diagnostics redact userinfo, path, query, and fragment."""
section = self._section(
enabled=True,
has_credentials=False,
endpoint=(
"https://user:secret@example.com:8443/trace?api_key=secret-token#frag"
),
)
labels = {item.label: item.value for item in section.items}
assert labels["Endpoint"] == "https://example.com:8443"
assert "secret" not in labels["Endpoint"]
assert "api_key" not in labels["Endpoint"]
def test_replica_project_listed_when_set(self) -> None:
"""A configured replica project is surfaced as its own item."""
section = self._section(
enabled=True,
has_credentials=True,
replica_project="replica",
)
labels = {item.label: item.value for item in section.items}
assert labels["Replica project"] == "replica"
class TestCommitHash:
"""Tests for git commit hash detection."""
@@ -132,8 +214,13 @@ class TestRunDoctorCommand:
assert code == 0
assert "Diagnostics" in output
assert "Updates" in output
assert "Tracing" in output
assert "Configuration" in output
assert "deepagents-code" in output
assert "dcode config show" in output
assert "dcode config get <key>" in output
assert "dcode --version" in output
assert "dcode -v" in output
def test_json_output_envelope(self, capsys) -> None:
"""JSON output is a stable envelope with section data."""
@@ -148,7 +235,7 @@ class TestRunDoctorCommand:
data = envelope["data"]
assert data["healthy"] is True
titles = [section["title"] for section in data["sections"]]
assert titles == ["Diagnostics", "Updates", "Configuration"]
assert titles == ["Diagnostics", "Updates", "Tracing", "Configuration"]
def test_unhealthy_returns_nonzero(self) -> None:
"""An unhealthy section yields a non-zero exit code."""
@@ -220,3 +307,7 @@ class TestDoctorHelp:
output = buf.getvalue()
assert "dcode doctor [options]" in output
assert "Usage:" in output
assert "dcode config show" in output
assert "dcode config get <key>" in output
assert "dcode --version" in output
assert "dcode -v" in output