Skip to content

Commit

Permalink
feat: add log design
Browse files Browse the repository at this point in the history
Signed-off-by: Xinwei Xiong <3293172751NSS@gmail.com>
  • Loading branch information
cubxxw committed Oct 28, 2024
1 parent 76897a4 commit da48f1d
Show file tree
Hide file tree
Showing 24 changed files with 1,271 additions and 186 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ GIT_COMMIT:=$(shell git rev-parse HEAD)

IMG ?= ghcr.io/telepace/voiceflow:latest

BUILDFILE = "./main.go"
BUILDFILE = "./voiceflow.go"
BUILDAPP = "$(OUTPUT_DIR)/"

# Define the directory you want to copyright
Expand Down Expand Up @@ -145,7 +145,7 @@ ifeq ($(origin GOBIN), undefined)
GOBIN := $(GOPATH)/bin
endif

COMMANDS ?= $(filter-out %.md, $(wildcard ${ROOT_DIR}/cmd/*/*.go))
COMMANDS ?= $(filter-out %.md, $(wildcard ${ROOT_DIR}/cmd/voiceflow/voiceflow.go))
BINS ?= $(foreach cmd,${COMMANDS},$(notdir ${cmd}))

ifeq (${COMMANDS},)
Expand Down
190 changes: 127 additions & 63 deletions cmd/voiceflow/root.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package main

import (
"context"
"fmt"
"log"
"github.com/telepace/voiceflow/pkg/config"
"net/http"
"os"
"strings"
"time"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/telepace/voiceflow/internal/config"
"github.com/telepace/voiceflow/internal/server"
"github.com/telepace/voiceflow/pkg/logger"
)
Expand All @@ -21,106 +22,169 @@ var rootCmd = &cobra.Command{
Use: "voiceflow",
Short: "VoiceFlow is a voice processing server",
Long: `VoiceFlow is a server application for processing voice data.`,
Run: func(cmd *cobra.Command, args []string) {
// 初始化配置
cfg := config.GetConfig()

// 初始化日志
logger.Init(cfg.Logging.Level)

// 创建一个新的 ServeMux
mux := http.NewServeMux()

// 提供静态文件服务
mux.Handle("/", http.FileServer(http.Dir("./web")))
mux.Handle("/audio_files/", http.StripPrefix("/audio_files/", http.FileServer(http.Dir("./audio_files"))))

// 初始化服务器并设置路由
wsServer := server.NewServer()
wsServer.SetupRoutes(mux)

// 启动服务器
addr := fmt.Sprintf(":%d", cfg.Server.Port)
log.Printf("Server started on %s", addr)
if err := http.ListenAndServe(addr, mux); err != nil {
log.Fatalf("Server error: %v", err)
}
},
RunE: run,
}

func run(cmd *cobra.Command, args []string) error {
ctx := context.Background()

// 初始化日志配置
logCfg := logger.Config{
Level: viper.GetString("logging.level"),
Format: viper.GetString("logging.format"),
Filename: viper.GetString("logging.filename"),
MaxSize: viper.GetInt("logging.max_size"),
MaxBackups: viper.GetInt("logging.max_backups"),
MaxAge: viper.GetInt("logging.max_age"),
Compress: viper.GetBool("logging.compress"),
ReportCaller: true,
}

// 服务标识信息
fields := logger.StandardFields{
ServiceID: "voiceflow",
InstanceID: fmt.Sprintf("instance-%d", time.Now().Unix()),
}

// 初始化日志系统
if err := logger.Init(logCfg, fields); err != nil {
return fmt.Errorf("failed to initialize logger: %w", err)
}

// 记录启动信息
logger.Info(ctx, "Starting VoiceFlow server")

// 初始化配置
cfg, err := config.GetConfig()
if err != nil {
logger.Error(ctx, "Failed to load configuration", "error", err)
return fmt.Errorf("failed to get config: %w", err)
}

// 记录配置信息
logger.Info(ctx, "Configuration loaded",
"server_port", cfg.Server.Port,
"enable_tls", cfg.Server.EnableTLS,
)

// 创建服务器实例
mux := http.NewServeMux()

// 注册路由处理器
logger.Debug(ctx, "Registering HTTP handlers")
mux.Handle("/", http.FileServer(http.Dir("./web")))
mux.Handle("/audio_files/", http.StripPrefix("/audio_files/", http.FileServer(http.Dir("./audio_files"))))

// 初始化 WebSocket 服务器
wsServer := server.NewServer()
wsServer.SetupRoutes(mux)

// 创建 HTTP 服务器
srv := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.Server.Port),
Handler: loggingMiddleware(mux),
}

// 启动服务器
logger.Info(ctx, "Server starting", "address", srv.Addr)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Error(ctx, "Server failed to start", "error", err)
return fmt.Errorf("server error: %w", err)
}

return nil
}

// 简单的日志中间件
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
start := time.Now()

logger.Info(ctx, "Request started",
"method", r.Method,
"path", r.URL.Path,
"remote_addr", r.RemoteAddr,
)

next.ServeHTTP(w, r)

logger.Info(ctx, "Request completed",
"method", r.Method,
"path", r.URL.Path,
"duration", time.Since(start).String(),
)
})
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
logger.Error(context.Background(), "Command execution failed", "error", err)
os.Exit(1)
}
}

func init() {
cobra.OnInitialize(initConfig)

// 定义持久化标志(全局)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件 (默认查找路径: ./config.yaml)")
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file path")

// 基础配置项
rootCmd.PersistentFlags().Int("server.port", 18080, "server port")
rootCmd.PersistentFlags().Bool("server.enable_tls", false, "enable TLS")

// 绑定常用标志
rootCmd.PersistentFlags().Int("server.port", 18080, "服务器端口")
rootCmd.PersistentFlags().Bool("server.enable_tls", false, "是否启用 TLS")
rootCmd.PersistentFlags().String("logging.level", "info", "日志级别")
// 日志相关配置项
rootCmd.PersistentFlags().String("logging.level", "info", "log level")
rootCmd.PersistentFlags().String("logging.format", "json", "log format (json/text)")
rootCmd.PersistentFlags().String("logging.filename", "", "log file path")

// 绑定标志到 Viper 配置
viper.BindPFlag("server.port", rootCmd.PersistentFlags().Lookup("server.port"))
viper.BindPFlag("server.enable_tls", rootCmd.PersistentFlags().Lookup("server.enable_tls"))
viper.BindPFlag("logging.level", rootCmd.PersistentFlags().Lookup("logging.level"))
// 绑定到 viper
viper.BindPFlags(rootCmd.PersistentFlags())
}

func initConfig() {
//ctx := context.Background()

if cfgFile != "" {
// 使用命令行标志指定的配置文件
viper.SetConfigFile(cfgFile)
} else if os.Getenv("VOICEFLOW_CONFIG") != "" {
// 使用环境变量指定的配置文件
viper.SetConfigFile(os.Getenv("VOICEFLOW_CONFIG"))
} else {
// 默认配置文件路径
viper.SetConfigName("config")
viper.AddConfigPath("/etc/voiceflow/")
viper.AddConfigPath("$HOME/.voiceflow")
viper.AddConfigPath(".")
viper.AddConfigPath("./configs") // 添加项目的 configs 目录
viper.AddConfigPath("./configs")
}

viper.SetEnvPrefix("VOICEFLOW")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv() // 自动读取匹配的环境变量
viper.AutomaticEnv()

// 读取配置文件
if err := viper.ReadInConfig(); err == nil {
fmt.Println("使用的配置文件:", viper.ConfigFileUsed())
fmt.Printf("Using config file: %s\n", viper.ConfigFileUsed())
} else {
fmt.Println("未找到配置文件,使用默认配置")
fmt.Println("No config file found, using defaults")
}

// 设置默认值
setDefaults()
}

func setDefaults() {
// 服务器默认配置
viper.SetDefault("server.port", 18080)
viper.SetDefault("server.enable_tls", false)

// 日志默认配置
viper.SetDefault("logging.level", "info")
viper.SetDefault("logging.format", "json")
viper.SetDefault("logging.filename", "") // 默认输出到标准输出
viper.SetDefault("logging.max_size", 100)
viper.SetDefault("logging.max_backups", 3)
viper.SetDefault("logging.max_age", 28)
viper.SetDefault("logging.compress", true)

// 其他服务配置...
viper.SetDefault("web.port", 18090)
viper.SetDefault("minio.enabled", true)
viper.SetDefault("minio.endpoint", "localhost:9000")
viper.SetDefault("minio.access_key", "minioadmin")
viper.SetDefault("minio.secret_key", "minioadmin")
viper.SetDefault("minio.bucket_name", "telepace-pipeline")
viper.SetDefault("minio.secure", true)
viper.SetDefault("stt.provider", "azure")
viper.SetDefault("tts.provider", "google")
viper.SetDefault("llm.provider", "openai")
viper.SetDefault("azure.stt_key", "your_azure_stt_key")
viper.SetDefault("azure.tts_key", "your_azure_tts_key")
viper.SetDefault("azure.region", "eastus")
viper.SetDefault("google.stt_key", "your_google_stt_key")
viper.SetDefault("google.tts_key", "your_google_tts_key")
viper.SetDefault("openai.api_key", "your_openai_api_key")
viper.SetDefault("logging.level", "debug")
// ... 其他配置项
}
7 changes: 5 additions & 2 deletions configs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ minio:
secure: true # 如果需要使用 HTTPS 连接,设置为 true

stt:
provider: azure # 可选值:azure、google、local
provider: assemblyai # 可选值:azure、google、local、assemblyai

tts:
provider: google # 可选值:azure、google、local
Expand All @@ -35,4 +35,7 @@ openai:
api_key: "your_openai_api_key"

logging:
level: debug
level: Debug

assemblyai:
api_key: "your_assemblyai_api_key"
73 changes: 73 additions & 0 deletions examples/log/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// // example/main.go
package main

//
//import (
// "context"
// "errors"
// "io"
// "os"
//
// "github.com/telepace/voiceflow/pkg/logger"
//)
//
//func main() {
// // 创建文件输出
// fileOutput := logger.NewFileOutput(logger.FileOutputConfig{
// Filename: "_output/log/app.log",
// MaxSize: 100,
// MaxBackups: 3,
// MaxAge: 28,
// Compress: true,
// })
//
// // 创建日志实例
// log, err := logger.NewLogger(logger.Config{
// Level: "info",
// Format: "json",
// Outputs: []io.Writer{
// os.Stdout,
// fileOutput,
// },
// ServiceInfo: logger.ServiceInfo{
// ServiceID: "order-service",
// InstanceID: "instance-1",
// Extra: logger.Fields{
// "region": "us-west",
// "env": "production",
// },
// },
// ReportCaller: true,
// CallerSkip: 0,
// })
// if err != nil {
// panic(err)
// }
//
// // 基础用法
// log.Info("service starting...")
// log.Infof("listening on port %d", 8080)
//
// // 带ctx的用法
// ctx := context.Background()
// log.InfoContext(ctx, "handling request")
// log.InfoContextf(ctx, "processing order %s", "ORD-123")
//
// // 链式调用
// log.WithField("user_id", "U123").Info("user logged in")
//
// err = errors.New("database connection failed")
// log.WithError(err).Error("failed to connect to database")
//
// log.WithFields(logger.Fields{
// "order_id": "ORD-123",
// "user_id": "U123",
// "amount": 99.99,
// }).Info("order created")
//
// // 组合使用
// log.WithContext(ctx).
// WithField("user_id", "U123").
// WithError(err).
// Error("operation failed")
//}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ go 1.22.5

require (
github.com/AssemblyAI/assemblyai-go-sdk v1.8.1
github.com/go-audio/audio v1.0.0
github.com/go-audio/wav v1.1.0
github.com/google/uuid v1.6.0
github.com/gordonklaus/portaudio v0.0.0-20230709114228-aafa478834f5
github.com/gorilla/websocket v1.5.3
github.com/joho/godotenv v1.5.1
github.com/minio/minio-go/v7 v7.0.78
github.com/opentracing/opentracing-go v1.2.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
Expand All @@ -20,6 +23,7 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-audio/riff v1.0.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect
Expand Down Expand Up @@ -48,6 +52,7 @@ require (
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
Loading

0 comments on commit da48f1d

Please sign in to comment.