diff --git a/go.mod b/go.mod index 50bfdf9..f9d35fc 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/openimsdk/gomake v0.0.15-alpha.11 github.com/openimsdk/tools v0.0.50-alpha.65 + github.com/prometheus/client_golang v1.19.0 github.com/redis/go-redis/v9 v9.5.1 github.com/sashabaranov/go-openai v1.38.1 github.com/spf13/cobra v1.8.0 @@ -48,6 +49,7 @@ require ( github.com/alibabacloud-go/tea-utils v1.4.5 // indirect github.com/alibabacloud-go/tea-xml v1.1.2 // indirect github.com/aliyun/credentials-go v1.1.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect @@ -97,6 +99,9 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openimsdk/protocol v0.0.69-alpha.4 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect diff --git a/internal/api/admin/start.go b/internal/api/admin/start.go index 0bce1f6..dd1894e 100644 --- a/internal/api/admin/start.go +++ b/internal/api/admin/start.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "os/signal" + "strings" "syscall" "time" @@ -26,6 +27,7 @@ import ( "github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/runtimeenv" + "github.com/prometheus/client_golang/prometheus/promhttp" clientv3 "go.etcd.io/etcd/client/v3" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -81,6 +83,24 @@ func Start(ctx context.Context, index int, config *Config) error { } c.Next() }) + + // 可选的 Prometheus metrics 端点 + // 支持配置文件或环境变量控制(环境变量优先) + prometheusEnable := config.AdminAPI.Prometheus.Enable + if envEnable := os.Getenv("PROMETHEUS_ENABLE"); envEnable != "" { + prometheusEnable = strings.ToLower(envEnable) == "true" || envEnable == "1" + } + if prometheusEnable { + metricsPath := config.AdminAPI.Prometheus.Path + if envPath := os.Getenv("PROMETHEUS_PATH"); envPath != "" { + metricsPath = envPath + } + if metricsPath == "" { + metricsPath = "/metrics" + } + engine.GET(metricsPath, gin.WrapH(promhttp.Handler())) + } + SetAdminRoute(engine, adminApi, mwApi, config, client) if config.Discovery.Enable == kdisc.ETCDCONST { diff --git a/internal/api/bot/start.go b/internal/api/bot/start.go index abb62f4..60edd6d 100644 --- a/internal/api/bot/start.go +++ b/internal/api/bot/start.go @@ -24,8 +24,10 @@ import ( "github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/runtimeenv" + "github.com/prometheus/client_golang/prometheus/promhttp" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "strings" ) type Config struct { @@ -75,6 +77,24 @@ func Start(ctx context.Context, index int, cfg *Config) error { } c.Next() }) + + // 可选的 Prometheus metrics 端点 + // 支持配置文件或环境变量控制(环境变量优先) + prometheusEnable := cfg.ApiConfig.Prometheus.Enable + if envEnable := os.Getenv("PROMETHEUS_ENABLE"); envEnable != "" { + prometheusEnable = strings.ToLower(envEnable) == "true" || envEnable == "1" + } + if prometheusEnable { + metricsPath := cfg.ApiConfig.Prometheus.Path + if envPath := os.Getenv("PROMETHEUS_PATH"); envPath != "" { + metricsPath = envPath + } + if metricsPath == "" { + metricsPath = "/metrics" + } + engine.GET(metricsPath, gin.WrapH(promhttp.Handler())) + } + SetBotRoute(engine, botApi, mwApi) var ( diff --git a/internal/api/chat/start.go b/internal/api/chat/start.go index 1bb6a11..0986d01 100644 --- a/internal/api/chat/start.go +++ b/internal/api/chat/start.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "os/signal" + "strings" "syscall" "time" @@ -25,6 +26,7 @@ import ( "github.com/openimsdk/tools/system/program" "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/runtimeenv" + "github.com/prometheus/client_golang/prometheus/promhttp" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) @@ -74,6 +76,24 @@ func Start(ctx context.Context, index int, cfg *Config) error { gin.SetMode(gin.ReleaseMode) engine := gin.New() engine.Use(gin.Recovery(), mw.CorsHandler(), mw.GinParseOperationID()) + + // 可选的 Prometheus metrics 端点 + // 支持配置文件或环境变量控制(环境变量优先) + prometheusEnable := cfg.ApiConfig.Prometheus.Enable + if envEnable := os.Getenv("PROMETHEUS_ENABLE"); envEnable != "" { + prometheusEnable = strings.ToLower(envEnable) == "true" || envEnable == "1" + } + if prometheusEnable { + metricsPath := cfg.ApiConfig.Prometheus.Path + if envPath := os.Getenv("PROMETHEUS_PATH"); envPath != "" { + metricsPath = envPath + } + if metricsPath == "" { + metricsPath = "/metrics" + } + engine.GET(metricsPath, gin.WrapH(promhttp.Handler())) + } + SetChatRoute(engine, adminApi, mwApi) var ( diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index dd38cdd..3dba7ba 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -43,6 +43,7 @@ type API struct { ListenIP string `mapstructure:"listenIP"` Ports []int `mapstructure:"ports"` } `mapstructure:"api"` + Prometheus Prometheus `mapstructure:"prometheus"` // 可选的 Prometheus 配置 } type APIBot struct { @@ -50,6 +51,7 @@ type APIBot struct { ListenIP string `mapstructure:"listenIP"` Ports []int `mapstructure:"ports"` } `mapstructure:"api"` + Prometheus Prometheus `mapstructure:"prometheus"` // 可选的 Prometheus 配置 } type Mongo struct { @@ -104,6 +106,12 @@ type Discovery struct { RpcService RpcService `mapstructure:"rpcService"` } +// Prometheus 配置(可选,用于暴露 /metrics 端点) +type Prometheus struct { + Enable bool `mapstructure:"enable"` // 是否启用 Prometheus metrics,默认 false + Path string `mapstructure:"path"` // metrics 路径,默认 /metrics +} + type Kubernetes struct { Namespace string `mapstructure:"namespace"` }