Files
MyGoNavi/internal/app/startup_diagnostics.go
Syngnat 3ea3223749 🐛 fix(query-editor/logging): 修复达梦SQL美化并完善诊断日志
- 为达梦和自定义 DM8 连接启用 SQL 格式化位置占位符
- 记录 SQL 美化方言、作用域、耗时及脱敏错误信息
- 将 Wails 前端日志接入 GoNavi 应用日志文件
- 启动时输出应用版本及实际驱动模块和代理版本
- 补充达梦占位符、日志落盘与启动诊断回归测试
2026-07-30 18:17:08 +08:00

206 lines
6.2 KiB
Go

package app
import (
"fmt"
stdRuntime "runtime"
"runtime/debug"
"sort"
"strings"
"GoNavi-Wails/internal/appdata"
"GoNavi-Wails/internal/logger"
)
type startupDriverVersion struct {
Driver string
Source string
Version string
Module string
AgentRevision string
}
var startupDriverModuleNames = map[string]string{
"gitea.com/kingbase/gokb": "kingbase",
"gitee.com/chunanyong/dm": "dameng",
"github.com/ClickHouse/clickhouse-go/v2": "clickhouse",
"github.com/HuaweiCloudDeveloper/gaussdb-go": "gaussdb",
"github.com/apache/iotdb-client-go": "iotdb",
"github.com/apache/rocketmq-client-go/v2": "rocketmq",
"github.com/caretdev/go-irisnative": "iris",
"github.com/duckdb/duckdb-go/v2": "duckdb",
"github.com/eclipse/paho.mqtt.golang": "mqtt",
"github.com/elastic/go-elasticsearch/v8": "elasticsearch",
"github.com/go-sql-driver/mysql": "mysql-compatible",
"github.com/helingjun/obconnector-go": "oceanbase-oracle",
"github.com/highgo/pq-sm3": "highgo",
"github.com/lib/pq": "postgres-compatible",
"github.com/microsoft/go-mssqldb": "sqlserver",
"github.com/redis/go-redis/v9": "redis",
"github.com/segmentio/kafka-go": "kafka",
"github.com/sijms/go-ora/v2": "oracle",
"github.com/taosdata/driver-go/v3": "tdengine",
"github.com/trinodb/trino-go-client": "trino",
"go.mongodb.org/mongo-driver": "mongodb-v1",
"go.mongodb.org/mongo-driver/v2": "mongodb",
"modernc.org/sqlite": "sqlite",
}
func logStartupDiagnostics(configDir string) {
buildInfo, _ := debug.ReadBuildInfo()
logger.Infof("%s", buildStartupVersionLog(
getCurrentVersion(),
strings.TrimSpace(AppBuildTime),
stdRuntime.GOOS,
stdRuntime.GOARCH,
buildInfo,
))
driverRoot := appdata.DriverRoot(configDir)
versions := collectStartupDriverVersions(buildInfo, driverRoot)
if len(versions) == 0 {
logger.Warnf("数据库驱动版本:未从当前二进制或已安装驱动代理中解析到版本")
return
}
for _, item := range versions {
logger.Infof("%s", formatStartupDriverVersionLog(item))
}
}
func buildStartupVersionLog(version string, buildTime string, goos string, goarch string, buildInfo *debug.BuildInfo) string {
version = strings.TrimSpace(version)
if version == "" {
version = "(unknown)"
}
goVersion := stdRuntime.Version()
if buildInfo != nil && strings.TrimSpace(buildInfo.GoVersion) != "" {
goVersion = strings.TrimSpace(buildInfo.GoVersion)
}
parts := []string{
fmt.Sprintf("version=%s", version),
fmt.Sprintf("go=%s", strings.TrimSpace(goVersion)),
fmt.Sprintf("os=%s", strings.TrimSpace(goos)),
fmt.Sprintf("arch=%s", strings.TrimSpace(goarch)),
}
if buildTime = strings.TrimSpace(buildTime); buildTime != "" {
parts = append(parts, "buildTime="+buildTime)
}
if revision := startupBuildRevision(buildInfo); revision != "" {
parts = append(parts, "revision="+revision)
}
return "GoNavi 启动信息:" + strings.Join(parts, " ")
}
func startupBuildRevision(buildInfo *debug.BuildInfo) string {
if buildInfo == nil {
return ""
}
for _, setting := range buildInfo.Settings {
if setting.Key != "vcs.revision" {
continue
}
revision := strings.TrimSpace(setting.Value)
if len(revision) > 12 {
revision = revision[:12]
}
return revision
}
return ""
}
func collectStartupDriverVersions(buildInfo *debug.BuildInfo, driverRoot string) []startupDriverVersion {
result := make([]startupDriverVersion, 0, len(startupDriverModuleNames))
if buildInfo != nil {
for _, dependency := range buildInfo.Deps {
if dependency == nil {
continue
}
modulePath := strings.TrimSpace(dependency.Path)
driverName, ok := startupDriverModuleNames[modulePath]
if !ok {
continue
}
result = append(result, startupDriverVersion{
Driver: driverName,
Source: "go-module",
Version: startupBuildModuleVersion(dependency),
Module: modulePath,
})
}
}
for _, definition := range allDriverDefinitionsWithPackages(nil) {
if definition.BuiltIn {
continue
}
pkg, ok := readInstalledDriverPackage(driverRoot, definition.Type)
if !ok {
continue
}
version := strings.TrimSpace(pkg.Version)
if version == "" {
version = "(unknown)"
}
result = append(result, startupDriverVersion{
Driver: normalizeDriverType(definition.Type),
Source: "driver-agent",
Version: version,
AgentRevision: strings.TrimSpace(pkg.AgentRevision),
})
}
sort.Slice(result, func(left int, right int) bool {
leftOrder := startupDriverSourceOrder(result[left].Source)
rightOrder := startupDriverSourceOrder(result[right].Source)
if leftOrder != rightOrder {
return leftOrder < rightOrder
}
if result[left].Driver != result[right].Driver {
return result[left].Driver < result[right].Driver
}
return result[left].Module < result[right].Module
})
return result
}
func startupDriverSourceOrder(source string) int {
if source == "go-module" {
return 0
}
return 1
}
func startupBuildModuleVersion(module *debug.Module) string {
if module == nil {
return "(unknown)"
}
version := strings.TrimSpace(module.Version)
if module.Replace != nil {
replacementVersion := strings.TrimSpace(module.Replace.Version)
if replacementVersion != "" && replacementVersion != "(devel)" {
version = replacementVersion
} else if version != "" {
version += "+local-replace"
}
}
if version == "" || version == "(devel)" {
return "(unknown)"
}
return version
}
func formatStartupDriverVersionLog(item startupDriverVersion) string {
parts := []string{
fmt.Sprintf("driver=%s", strings.TrimSpace(item.Driver)),
fmt.Sprintf("source=%s", strings.TrimSpace(item.Source)),
fmt.Sprintf("version=%s", strings.TrimSpace(item.Version)),
}
if modulePath := strings.TrimSpace(item.Module); modulePath != "" {
parts = append(parts, "module="+modulePath)
}
if revision := strings.TrimSpace(item.AgentRevision); revision != "" {
parts = append(parts, "agentRevision="+revision)
}
return "数据库驱动版本:" + strings.Join(parts, " ")
}