Skip to content

Commit 89e8836

Browse files
wislapLocalBuilder
andauthored
chore(plugin): improve config write diagnostics (#1675)
Co-authored-by: LocalBuilder <local@builder>
1 parent 64d8c71 commit 89e8836

7 files changed

Lines changed: 508 additions & 56 deletions

File tree

plugin/plugins/mcp_adapter/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,10 @@ async def add_server(
20822082
try:
20832083
await self._persist_servers_config(servers_config)
20842084
except Exception as exc:
2085+
self.ctx.logger.exception(
2086+
f"Failed to persist MCP server config while adding server '{name}' "
2087+
f"(transport={transport}): {exc}"
2088+
)
20852089
return Err(SdkError(f"Failed to save server config: {exc}"))
20862090

20872091
# 缓存配置
@@ -2154,6 +2158,10 @@ async def remove_servers(self, server_names: List[str], **_):
21542158
try:
21552159
await self._persist_servers_config(dict(servers_config))
21562160
except Exception as exc:
2161+
self.ctx.logger.exception(
2162+
"Failed to persist MCP server config while removing servers "
2163+
f"(requested={len(server_names)}, removed={len(removed)}): {exc}"
2164+
)
21572165
return Err(SdkError(f"Failed to save server config: {exc}"))
21582166
self._servers_config = servers_config
21592167

plugin/server/application/plugins/ui_query_service.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pathlib import Path
77

88
from plugin.core.state import state
9+
from plugin._types.exceptions import PluginExecutionError
910
from plugin._types.models import PluginUiSurface, PluginUiWarning
1011
from plugin.logging_config import get_logger
1112
from plugin.core.ui_manifest import (
@@ -910,7 +911,32 @@ async def call_surface_action(
910911
details={"plugin_id": plugin_id, "kind": kind, "surface_id": surface_id, "action_id": action_id},
911912
)
912913

913-
result = await host.trigger(resolved_action_id, dict(args or {}))
914+
try:
915+
result = await host.trigger(resolved_action_id, dict(args or {}))
916+
except PluginExecutionError as exc:
917+
message = exc.error if isinstance(exc.error, str) and exc.error else str(exc)
918+
logger.warning(
919+
"Hosted UI action failed in plugin entry: plugin_id={}, surface={}:{}, action_id={}, entry_id={}, err={}",
920+
plugin_id,
921+
kind,
922+
surface_id,
923+
action_id,
924+
resolved_action_id,
925+
message,
926+
)
927+
raise ServerDomainError(
928+
code="PLUGIN_UI_ACTION_FAILED",
929+
message=message,
930+
status_code=500,
931+
details={
932+
"plugin_id": plugin_id,
933+
"kind": kind,
934+
"surface_id": surface_id,
935+
"action_id": action_id,
936+
"entry_id": resolved_action_id,
937+
"error_type": type(exc).__name__,
938+
},
939+
) from exc
914940
return {
915941
"plugin_id": plugin_id,
916942
"action_id": resolved_action_id,

plugin/server/infrastructure/config_paths.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
from fastapi import HTTPException
77

88
from plugin.core.state import state
9+
from plugin.logging_config import get_logger
910
from plugin.settings import PLUGIN_CONFIG_ROOTS
1011

12+
logger = get_logger("server.infrastructure.config_paths")
13+
1114

1215
def _resolve_registered_plugin_config_path(plugin_id: str) -> Path | None:
1316
candidates: list[object] = []
@@ -29,10 +32,30 @@ def _resolve_registered_plugin_config_path(plugin_id: str) -> Path | None:
2932
continue
3033
try:
3134
path = Path(candidate).resolve()
32-
except (TypeError, ValueError, OSError, RuntimeError):
35+
except (TypeError, ValueError, OSError, RuntimeError) as exc:
36+
logger.warning(
37+
"Plugin config registered path ignored: plugin_id={}, candidate_type={}, err_type={}, err={}",
38+
plugin_id,
39+
type(candidate).__name__,
40+
type(exc).__name__,
41+
str(exc),
42+
)
3343
continue
3444
if path.is_file() and path.name == "plugin.toml":
45+
logger.debug(
46+
"Plugin config path resolved from registered metadata: plugin_id={}, config_path={}",
47+
plugin_id,
48+
path,
49+
)
3550
return path
51+
logger.warning(
52+
"Plugin config registered path ignored: plugin_id={}, config_path={}, exists={}, is_file={}, name={}",
53+
plugin_id,
54+
path,
55+
path.exists(),
56+
path.is_file(),
57+
path.name,
58+
)
3659

3760
return None
3861

@@ -72,6 +95,12 @@ def get_plugin_config_path(plugin_id: str) -> Path:
7295
continue
7396

7497
if config_file.exists():
98+
logger.debug(
99+
"Plugin config path resolved from config root: plugin_id={}, root={}, config_path={}",
100+
plugin_id,
101+
root,
102+
config_file,
103+
)
75104
return config_file
76105

77106
raise HTTPException(

plugin/server/infrastructure/config_storage.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,40 @@ def atomic_write_bytes(*, target: Path, payload: bytes, prefix: str) -> None:
3232
dir=str(target.parent),
3333
)
3434
except OSError as exc:
35+
logger.exception(
36+
"Failed to create temporary config file: target={}, parent={}, prefix={}, err_type={}, err={}",
37+
target,
38+
target.parent,
39+
prefix,
40+
type(exc).__name__,
41+
str(exc),
42+
)
3543
raise HTTPException(
3644
status_code=500,
37-
detail=f"Failed to create temporary file for {target}",
45+
detail=f"Failed to create temporary file for {target}: {type(exc).__name__}: {exc}",
3846
) from exc
3947

4048
temp_file_path = Path(temp_path)
49+
stage = "write_temp"
4150
try:
4251
with os.fdopen(temp_fd, "wb") as temp_file:
4352
temp_file.write(payload)
4453
temp_file.flush()
4554
os.fsync(temp_file.fileno())
4655

56+
stage = "replace"
4757
os.replace(temp_file_path, target)
58+
stage = "fsync_parent"
4859
_fsync_parent_dir(target)
4960
except (OSError, RuntimeError, ValueError, TypeError) as exc:
61+
logger.exception(
62+
"Failed to persist config file: target={}, temp_path={}, stage={}, err_type={}, err={}",
63+
target,
64+
temp_file_path,
65+
stage,
66+
type(exc).__name__,
67+
str(exc),
68+
)
5069
try:
5170
if temp_file_path.exists():
5271
temp_file_path.unlink()
@@ -58,7 +77,7 @@ def atomic_write_bytes(*, target: Path, payload: bytes, prefix: str) -> None:
5877
)
5978
raise HTTPException(
6079
status_code=500,
61-
detail=f"Failed to persist config file {target}",
80+
detail=f"Failed to persist config file {target} while {stage}: {type(exc).__name__}: {exc}",
6281
) from exc
6382

6483

0 commit comments

Comments
 (0)