Files
MyGoNavi/internal/jvm/connection_error_message.go
Syngnat 6f14e827ab feat(jvm): 完成资源治理与诊断增强
- 新增 JMX/Endpoint/Agent 三种 JVM 连接模式与配置归一化链路
- 支持资源浏览、变更预览、写入应用、审计记录与只读约束
- 接入 AI 结构化写入计划与诊断计划回填能力
- 新增 Agent Bridge、Arthas Tunnel、JMX Helper 诊断传输实现
- 增加诊断控制台、命令模板、输出历史与自动补全交互
- 补齐前后端契约、运行夹具与 JVM 相关回归测试
2026-04-24 16:45:34 +08:00

207 lines
8.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package jvm
import (
"fmt"
"strings"
"GoNavi-Wails/internal/connection"
)
func DescribeConnectionTestError(cfg connection.ConnectionConfig, err error) string {
if err == nil {
return ""
}
raw := strings.TrimSpace(err.Error())
if raw == "" {
return "JVM 连接失败"
}
switch strings.ToLower(strings.TrimSpace(cfg.JVM.PreferredMode)) {
case ModeJMX:
if mapped := describeJMXConnectionError(cfg, raw); mapped != "" {
return mapped
}
case ModeEndpoint:
if mapped := describeEndpointConnectionError(raw); mapped != "" {
return mapped
}
case ModeAgent:
if mapped := describeAgentConnectionError(raw); mapped != "" {
return mapped
}
}
return raw
}
func describeEndpointConnectionError(raw string) string {
lower := strings.ToLower(raw)
switch {
case strings.Contains(lower, "endpoint baseurl is required"):
return "Endpoint 连接失败:未填写 Endpoint Base URL。"
case strings.Contains(lower, "endpoint baseurl is invalid"):
return joinConnectionErrorMessage(
"Endpoint 连接失败Endpoint Base URL 格式不合法。",
"请填写完整的 `http://` 或 `https://` 地址,并指向实现 GoNavi JVM HTTP 合约的管理接口根路径,例如 `http://127.0.0.1:19090/manage/jvm`。",
raw,
)
case strings.Contains(lower, "endpoint scheme is unsupported"):
return joinConnectionErrorMessage(
"Endpoint 连接失败:当前只支持 HTTP 或 HTTPS 协议。",
"请把 Endpoint Base URL 改成 `http://` 或 `https://` 开头的地址。",
raw,
)
case strings.Contains(lower, "unexpected status: 404"), strings.Contains(lower, "request failed: 404"):
return joinConnectionErrorMessage(
"Endpoint 连接失败:目标地址已响应,但没有找到 GoNavi JVM 管理接口。",
"请确认 Base URL 指向的是 JVM 管理接口根路径,而不是普通业务接口、健康检查地址或网关首页。",
raw,
)
case strings.Contains(lower, "connect: connection refused"), strings.Contains(lower, "connection refused"):
return joinConnectionErrorMessage(
"Endpoint 连接失败:目标管理接口未监听,或当前地址不可达。",
"请确认 Base URL 指向实现 GoNavi JVM HTTP 合约的管理接口,并检查服务监听、端口映射和防火墙。",
raw,
)
case strings.Contains(lower, "401 unauthorized"), strings.Contains(lower, "missing or invalid api key"):
return joinConnectionErrorMessage(
"Endpoint 连接失败:目标管理接口已响应,但当前 API Key 无效或缺失。",
"请检查连接中的 Endpoint API Key 是否与目标服务配置一致。",
raw,
)
case strings.Contains(lower, "403 forbidden"):
return joinConnectionErrorMessage(
"Endpoint 连接失败:当前请求被目标管理接口拒绝。",
"请确认当前客户端来源、鉴权配置和访问策略允许 GoNavi 访问该管理接口。",
raw,
)
case strings.Contains(lower, "timed out"), strings.Contains(lower, "timeout"), strings.Contains(lower, "context deadline exceeded"), strings.Contains(lower, "i/o timeout"):
return joinConnectionErrorMessage(
"Endpoint 连接失败:访问目标管理接口超时。",
"请确认 Base URL 可达、目标服务已完成启动,并适当增加连接超时时间。",
raw,
)
default:
return ""
}
}
func describeAgentConnectionError(raw string) string {
lower := strings.ToLower(raw)
switch {
case strings.Contains(lower, "agent baseurl is required"):
return "Agent 连接失败:未填写 Agent Base URL。"
case strings.Contains(lower, "agent baseurl is invalid"):
return joinConnectionErrorMessage(
"Agent 连接失败Agent Base URL 格式不合法。",
"请填写完整的 `http://` 或 `https://` 地址,例如 `http://127.0.0.1:19090/gonavi/agent/jvm`。",
raw,
)
case strings.Contains(lower, "agent scheme is unsupported"):
return joinConnectionErrorMessage(
"Agent 连接失败:当前只支持 HTTP 或 HTTPS 协议。",
"请把 Agent Base URL 改成 `http://` 或 `https://` 开头的地址。",
raw,
)
case strings.Contains(lower, "connect: connection refused"), strings.Contains(lower, "connection refused"):
return joinConnectionErrorMessage(
"Agent 连接失败:目标 Agent 管理端口未监听,或当前地址不可达。",
"请确认 Java 服务已通过 `-javaagent` 启动 GoNavi Agent并检查 Base URL、端口映射和防火墙。",
raw,
)
case strings.Contains(lower, "401 unauthorized"), strings.Contains(lower, "missing or invalid api key"):
return joinConnectionErrorMessage(
"Agent 连接失败Agent 已响应,但当前 API Key 无效或缺失。",
"请检查连接中的 Agent API Key 是否与目标服务启动参数一致。",
raw,
)
case strings.Contains(lower, "403 forbidden"):
return joinConnectionErrorMessage(
"Agent 连接失败:当前请求被 Agent 拒绝。",
"请确认当前客户端来源、鉴权配置和 Agent 访问策略允许 GoNavi 访问。",
raw,
)
case strings.Contains(lower, "timed out"), strings.Contains(lower, "timeout"), strings.Contains(lower, "context deadline exceeded"), strings.Contains(lower, "i/o timeout"):
return joinConnectionErrorMessage(
"Agent 连接失败:访问 Agent 管理端口超时。",
"请确认目标地址可达、Agent 已完成启动,并适当增加连接超时时间。",
raw,
)
default:
return ""
}
}
func describeJMXConnectionError(cfg connection.ConnectionConfig, raw string) string {
lower := strings.ToLower(raw)
target := fmt.Sprintf("%s:%d", resolveJMXHost(cfg), resolveJMXPort(cfg))
switch {
case strings.Contains(lower, "jmx host is required"):
return "JMX 连接失败:未填写主机地址。"
case strings.Contains(lower, "jmx port is invalid"):
return "JMX 连接失败:端口无效,请填写 1-65535 之间的有效端口。"
case strings.Contains(lower, `required jmx helper dependency "java" not found`):
return joinConnectionErrorMessage(
"JMX 连接失败:当前机器未找到 `java` 运行时GoNavi 无法启动 JMX helper。",
"请先安装 JRE/JDK或通过环境变量 `GONAVI_JMX_JAVA_BIN` 指向正确的 `java` 可执行文件。",
raw,
)
case strings.Contains(lower, "non-jrmp server at remote endpoint"):
return joinConnectionErrorMessage(
fmt.Sprintf("JMX 连接失败:%s 不是标准 JMX 远程管理端口,当前更像普通业务端口或 HTTP 端口。", target),
"请改填应用实际暴露的 JMX 端口,而不是业务 `server.port`。如果服务只开启了 `-Dcom.sun.management.jmxremote`,但没有配置 `jmxremote.port`,也无法直接远程连接。",
raw,
)
case strings.Contains(lower, "no such object in table"):
return joinConnectionErrorMessage(
fmt.Sprintf("JMX 连接失败:%s 上虽然有 RMI 服务,但不是可用的 JMX RMIServer 端口。", target),
"这通常意味着填到了 RMI 注册端口、调试端口或其他 Java 服务端口。请检查 `jmxremote.port` 和 `jmxremote.rmi.port` 配置是否正确。",
raw,
)
case strings.Contains(lower, "connection reset"):
return joinConnectionErrorMessage(
fmt.Sprintf("JMX 连接失败:%s 上的服务主动断开了连接,当前端口不是兼容的标准 JMX RMI 端口。", target),
"请确认填写的是 JVM 真正对外暴露的 JMX 端口,而不是业务端口、调试端口或被代理转发的端口。",
raw,
)
case strings.Contains(lower, "connection refused"):
return joinConnectionErrorMessage(
fmt.Sprintf("JMX 连接失败:无法连接到 %s对应端口没有监听或当前网络不可达。", target),
"请确认目标 JVM 已开启远程 JMX并检查主机、防火墙、端口映射和 SSH/代理配置。",
raw,
)
case strings.Contains(lower, "authentication failed"), strings.Contains(lower, "securityexception"):
return joinConnectionErrorMessage(
fmt.Sprintf("JMX 连接失败:%s 需要认证,或当前凭据不可用。", target),
"请确认目标 JMX 是否关闭认证;如果必须认证,需要补充用户名/密码后再连接。",
raw,
)
case strings.Contains(lower, "timed out"), strings.Contains(lower, "timeout"), strings.Contains(lower, "context deadline exceeded"), strings.Contains(lower, "i/o timeout"):
return joinConnectionErrorMessage(
fmt.Sprintf("JMX 连接失败:连接 %s 超时。", target),
"请确认端口可达、网络未被拦截,并适当增加连接超时时间。",
raw,
)
default:
return ""
}
}
func joinConnectionErrorMessage(summary string, suggestion string, raw string) string {
lines := make([]string, 0, 3)
if trimmed := strings.TrimSpace(summary); trimmed != "" {
lines = append(lines, trimmed)
}
if trimmed := strings.TrimSpace(suggestion); trimmed != "" {
lines = append(lines, "建议:"+trimmed)
}
if trimmed := strings.TrimSpace(raw); trimmed != "" {
lines = append(lines, "技术细节:"+trimmed)
}
return strings.Join(lines, "\n")
}