diff --git a/install.sh b/install.sh index c2911cf..5b42c97 100644 --- a/install.sh +++ b/install.sh @@ -79,12 +79,16 @@ web: port: 8080 socket_path: ${SOCKET_PATH} static_dir: ${INSTALL_DIR}/dist - console_log: true admin: username: admin password: admin session_secret: "" session_secure: false +console_log: + web: true + mqtt: true + llm: true + sql: true EOF chown "${SERVICE_USER}:${SERVICE_USER}" "${CONFIG_DIR}/config.yaml" chmod 0640 "${CONFIG_DIR}/config.yaml" diff --git a/internal/config/config.go b/internal/config/config.go index c0e6027..b92a3a2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -23,7 +23,7 @@ type Config struct { Database DatabaseConfig `yaml:"database"` Web WebConfig `yaml:"web"` AI AIConfig `yaml:"ai"` - DataDir string `yaml:"data_dir"` + ConsoleLog ConsoleLogConfig `yaml:"console_log"` Key []byte `yaml:"-"` } @@ -66,7 +66,6 @@ type WebConfig struct { SocketPath string `yaml:"socket_path"` StaticDir string `yaml:"static_dir"` MapTileCacheDir string `yaml:"map_tile_cache_dir"` - ConsoleLog bool `yaml:"console_log"` Admin WebAdminConfig `yaml:"admin"` } @@ -78,7 +77,16 @@ type WebAdminConfig struct { } type AIConfig struct { - Enabled bool `yaml:"enabled"` + Enabled bool `yaml:"enabled"` + DataDir string `yaml:"data_dir"` +} + +// ConsoleLogConfig 控制各模块是否在控制台打印日志。后续若新增模块,按需扩展。 +type ConsoleLogConfig struct { + Web bool `yaml:"web"` + MQTT bool `yaml:"mqtt"` + LLM bool `yaml:"llm"` + SQL bool `yaml:"sql"` } type rawConfig struct { @@ -87,11 +95,19 @@ type rawConfig struct { Database *rawDatabaseConfig `yaml:"database"` Web *rawWebConfig `yaml:"web"` AI *rawAIConfig `yaml:"ai"` - DataDir *string `yaml:"data_dir"` + ConsoleLog *rawConsoleLogConfig `yaml:"console_log"` +} + +type rawConsoleLogConfig struct { + Web *bool `yaml:"web"` + MQTT *bool `yaml:"mqtt"` + LLM *bool `yaml:"llm"` + SQL *bool `yaml:"sql"` } type rawAIConfig struct { - Enabled *bool `yaml:"enabled"` + Enabled *bool `yaml:"enabled"` + DataDir *string `yaml:"data_dir"` } type rawMQTTConfig struct { @@ -133,7 +149,6 @@ type rawWebConfig struct { SocketPath *string `yaml:"socket_path"` StaticDir *string `yaml:"static_dir"` MapTileCacheDir *string `yaml:"map_tile_cache_dir"` - ConsoleLog *bool `yaml:"console_log"` Admin *rawWebAdminConfig `yaml:"admin"` } @@ -173,7 +188,6 @@ func Default() *Config { SocketPath: defaultWebSocketPath(), StaticDir: "./dist", MapTileCacheDir: defaultMapTileCacheDir(), - ConsoleLog: true, Admin: WebAdminConfig{ Username: "admin", Password: "admin", @@ -183,8 +197,14 @@ func Default() *Config { }, AI: AIConfig{ Enabled: false, + DataDir: defaultDataDir(), + }, + ConsoleLog: ConsoleLogConfig{ + Web: true, + MQTT: true, + LLM: true, + SQL: true, }, - DataDir: defaultDataDir(), } } @@ -431,11 +451,6 @@ func normalize(raw rawConfig) (*Config, bool) { } else { cfg.Web.MapTileCacheDir = *raw.Web.MapTileCacheDir } - if raw.Web.ConsoleLog == nil { - changed = true - } else { - cfg.Web.ConsoleLog = *raw.Web.ConsoleLog - } if raw.Web.Admin == nil { changed = true } else { @@ -470,12 +485,36 @@ func normalize(raw rawConfig) (*Config, bool) { } else { cfg.AI.Enabled = *raw.AI.Enabled } + if raw.AI.DataDir == nil { + changed = true + } else { + cfg.AI.DataDir = *raw.AI.DataDir + } } - if raw.DataDir == nil { + if raw.ConsoleLog == nil { changed = true } else { - cfg.DataDir = *raw.DataDir + if raw.ConsoleLog.Web == nil { + changed = true + } else { + cfg.ConsoleLog.Web = *raw.ConsoleLog.Web + } + if raw.ConsoleLog.MQTT == nil { + changed = true + } else { + cfg.ConsoleLog.MQTT = *raw.ConsoleLog.MQTT + } + if raw.ConsoleLog.LLM == nil { + changed = true + } else { + cfg.ConsoleLog.LLM = *raw.ConsoleLog.LLM + } + if raw.ConsoleLog.SQL == nil { + changed = true + } else { + cfg.ConsoleLog.SQL = *raw.ConsoleLog.SQL + } } return cfg, changed diff --git a/internal/store/db.go b/internal/store/db.go index da85517..ea7eafc 100644 --- a/internal/store/db.go +++ b/internal/store/db.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "log" "os" "path/filepath" "time" @@ -11,6 +12,7 @@ import ( "github.com/glebarez/sqlite" "gorm.io/driver/mysql" "gorm.io/gorm" + gormlogger "gorm.io/gorm/logger" "meshtastic_mqtt_server/internal/config" ) @@ -571,7 +573,7 @@ func (TracerouteRecord) TableName() string { return "traceroute" } -func OpenStore(cfg config.DatabaseConfig) (*Store, error) { +func OpenStore(cfg config.DatabaseConfig, consoleLog bool) (*Store, error) { var dialector gorm.Dialector switch cfg.Driver { case config.DriverSQLite: @@ -585,7 +587,18 @@ func OpenStore(cfg config.DatabaseConfig) (*Store, error) { return nil, fmt.Errorf("unsupported database driver %q", cfg.Driver) } - db, err := gorm.Open(dialector, &gorm.Config{}) + logLevel := gormlogger.Warn + if !consoleLog { + logLevel = gormlogger.Silent + } + db, err := gorm.Open(dialector, &gorm.Config{ + Logger: gormlogger.New(log.New(os.Stderr, "\r\n", log.LstdFlags), gormlogger.Config{ + SlowThreshold: 200 * time.Millisecond, + LogLevel: logLevel, + IgnoreRecordNotFoundError: true, + Colorful: false, + }), + }) if err != nil { return nil, fmt.Errorf("open %s database: %w", cfg.Driver, err) } diff --git a/internal/store/db_test.go b/internal/store/db_test.go index b4b6778..75ddde7 100644 --- a/internal/store/db_test.go +++ b/internal/store/db_test.go @@ -978,7 +978,7 @@ func openTestStore(t *testing.T) *Store { st, err := OpenStore(config.DatabaseConfig{ Driver: config.DriverSQLite, SQLite: config.SQLiteConfig{Path: filepath.Join(t.TempDir(), "mesh_mqtt_go.db")}, - }) + }, false) if err != nil { t.Fatalf("OpenStore() error = %v", err) } diff --git a/internal/store/testutil/testutil.go b/internal/store/testutil/testutil.go index 2cca1f9..dcc3ed5 100644 --- a/internal/store/testutil/testutil.go +++ b/internal/store/testutil/testutil.go @@ -19,7 +19,7 @@ func OpenStore(t *testing.T) *store.Store { st, err := store.OpenStore(config.DatabaseConfig{ Driver: config.DriverSQLite, SQLite: config.SQLiteConfig{Path: filepath.Join(t.TempDir(), "mesh_mqtt_go.db")}, - }) + }, false) if err != nil { t.Fatalf("OpenStore() error = %v", err) } diff --git a/internal/web/map_tile_proxy_routes_test.go b/internal/web/map_tile_proxy_routes_test.go index 4dca24b..77d7bcc 100644 --- a/internal/web/map_tile_proxy_routes_test.go +++ b/internal/web/map_tile_proxy_routes_test.go @@ -38,7 +38,7 @@ func TestMapTileProxyFetchesAndCaches(t *testing.T) { } cacheDir := t.TempDir() - router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: cacheDir}, st, nil, nil, nil, nil, nil, nil) + router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: cacheDir}, false, st, nil, nil, nil, nil, nil, nil) url := "/api/map/" + row.URLTemplateHash + "?x=1&y=2&z=3" for i := 0; i < 2; i++ { @@ -75,7 +75,7 @@ func TestMapTileProxyRejectsInvalidCoordinates(t *testing.T) { t.Fatalf("CreateMapTileSource() error = %v", err) } - router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil, nil) + router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, false, st, nil, nil, nil, nil, nil, nil) cases := []string{ "/api/map/" + row.URLTemplateHash + "?y=0&z=0", @@ -106,7 +106,7 @@ func TestMapTileProxyUnknownAndDisabledSource(t *testing.T) { t.Fatalf("CreateMapTileSource(proxy disabled) error = %v", err) } - router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil, nil) + router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, false, st, nil, nil, nil, nil, nil, nil) cases := []string{ "/api/map/not-a-hash?x=0&y=0&z=0", @@ -147,7 +147,7 @@ func TestMapTileProxyUpstreamStatus(t *testing.T) { t.Fatalf("CreateMapTileSource(500) error = %v", err) } - router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil, nil) + router := NewRouter(configpkg.WebConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, false, st, nil, nil, nil, nil, nil, nil) cases := []struct { url string diff --git a/internal/web/web.go b/internal/web/web.go index 6a6a8fa..deb4ac3 100644 --- a/internal/web/web.go +++ b/internal/web/web.go @@ -27,10 +27,10 @@ import ( "meshtastic_mqtt_server/internal/webutil" ) -func NewHTTPServer(cfg configpkg.WebConfig, store *storepkg.Store, sessions *auth.Manager, mqttStatus MQTTStatusProvider, blocking *blockingpkg.Cache, forwarder mqttforwardpkg.Reloader, settings *rspkg.Cache, botSender botpkg.TextSender) *http.Server { +func NewHTTPServer(cfg configpkg.WebConfig, consoleLog bool, store *storepkg.Store, sessions *auth.Manager, mqttStatus MQTTStatusProvider, blocking *blockingpkg.Cache, forwarder mqttforwardpkg.Reloader, settings *rspkg.Cache, botSender botpkg.TextSender) *http.Server { return &http.Server{ Addr: net.JoinHostPort(cfg.Host, strconv.Itoa(cfg.Port)), - Handler: NewRouter(cfg, store, sessions, mqttStatus, blocking, forwarder, settings, botSender), + Handler: NewRouter(cfg, consoleLog, store, sessions, mqttStatus, blocking, forwarder, settings, botSender), } } @@ -60,9 +60,9 @@ func ServeUnixSocket(server *http.Server, socketPath string) error { return server.Serve(listener) } -func NewRouter(cfg configpkg.WebConfig, store *storepkg.Store, sessions *auth.Manager, mqttStatus MQTTStatusProvider, blocking *blockingpkg.Cache, forwarder mqttforwardpkg.Reloader, settings *rspkg.Cache, botSender botpkg.TextSender) *gin.Engine { +func NewRouter(cfg configpkg.WebConfig, consoleLog bool, store *storepkg.Store, sessions *auth.Manager, mqttStatus MQTTStatusProvider, blocking *blockingpkg.Cache, forwarder mqttforwardpkg.Reloader, settings *rspkg.Cache, botSender botpkg.TextSender) *gin.Engine { r := gin.New() - if cfg.ConsoleLog { + if consoleLog { r.Use(gin.Logger(), gin.Recovery()) } else { r.Use(gin.Recovery()) diff --git a/main.go b/main.go index 0032522..fff149a 100644 --- a/main.go +++ b/main.go @@ -221,7 +221,7 @@ func parseArgs() (*configpkg.Config, error) { // run 创建 MQTT broker 和 Web 服务,并阻塞等待退出信号。 func run(cfg *configpkg.Config) error { - store, err := storepkg.OpenStore(cfg.Database) + store, err := storepkg.OpenStore(cfg.Database, cfg.ConsoleLog.SQL) if err != nil { return err } @@ -306,7 +306,7 @@ func run(cfg *configpkg.Config) error { aiService, err = ai.NewService(ai.Config{ LLMProviders: providerConfigs, - DataDir: cfg.DataDir, + DataDir: cfg.AI.DataDir, Enabled: cfg.AI.Enabled, ToolConfigStore: store, }, store.DB(), botSenderAdapter) @@ -332,7 +332,7 @@ func run(cfg *configpkg.Config) error { return err } mqttStatus := webpkg.MQTTRuntimeStatus{Server: server, Address: mqttAddr, TLS: cfg.MQTT.TLS.Enabled, Stats: messageStats, DBQueue: dbQueue} - handler := webpkg.NewRouter(cfg.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender) + handler := webpkg.NewRouter(cfg.Web, cfg.ConsoleLog.Web, store, sessions, mqttStatus, blocking, forwardManager, settings, botSender) webAddresses := []string{} if cfg.Web.PortEnabled { httpServer := &http.Server{