diff --git a/weed/command/filer.go b/weed/command/filer.go index a6670b063..96df0d7dd 100644 --- a/weed/command/filer.go +++ b/weed/command/filer.go @@ -36,6 +36,7 @@ type FilerOptions struct { disableHttp *bool cipher *bool peers *string + metricsHttpPort *int // default leveldb directory, used in "weed server" mode defaultLevelDbDirectory *string @@ -57,6 +58,7 @@ func init() { f.disableHttp = cmdFiler.Flag.Bool("disableHttp", false, "disable http request, only gRpc operations are allowed") f.cipher = cmdFiler.Flag.Bool("encryptVolumeData", false, "encrypt data on volume servers") f.peers = cmdFiler.Flag.String("peers", "", "all filers sharing the same filer store in comma separated ip:port list") + f.metricsHttpPort = cmdFiler.Flag.Int("metricsPort", 0, "Prometheus metrics listen port") } var cmdFiler = &Command{ @@ -122,6 +124,7 @@ func (fo *FilerOptions) startFiler() { Port: uint32(*fo.port), Cipher: *fo.cipher, Filers: peers, + MetricsHttpPort: *fo.metricsHttpPort, }) if nfs_err != nil { glog.Fatalf("Filer startup error: %v", nfs_err) diff --git a/weed/command/s3.go b/weed/command/s3.go index a9b317138..fb09731fa 100644 --- a/weed/command/s3.go +++ b/weed/command/s3.go @@ -23,12 +23,13 @@ var ( ) type S3Options struct { - filer *string - port *int - config *string - domainName *string - tlsPrivateKey *string - tlsCertificate *string + filer *string + port *int + config *string + domainName *string + tlsPrivateKey *string + tlsCertificate *string + metricsHttpPort *int } func init() { @@ -39,6 +40,7 @@ func init() { s3StandaloneOptions.config = cmdS3.Flag.String("config", "", "path to the config file") s3StandaloneOptions.tlsPrivateKey = cmdS3.Flag.String("key.file", "", "path to the TLS private key file") s3StandaloneOptions.tlsCertificate = cmdS3.Flag.String("cert.file", "", "path to the TLS certificate file") + s3StandaloneOptions.metricsHttpPort = cmdS3.Flag.Int("metricsPort", 0, "Prometheus metrics listen port") } var cmdS3 = &Command{ @@ -153,6 +155,7 @@ func (s3opt *S3Options) startS3Server() bool { } } + go stats_collect.StartMetricsServer(stats_collect.S3Gather, *s3opt.metricsHttpPort) go stats_collect.LoopPushingMetric("s3", stats_collect.SourceName(uint32(*s3opt.port)), stats_collect.S3Gather, metricsAddress, metricsIntervalSec) router := mux.NewRouter().SkipClean(true) diff --git a/weed/command/server.go b/weed/command/server.go index aee62290a..b0c99aacf 100644 --- a/weed/command/server.go +++ b/weed/command/server.go @@ -89,6 +89,7 @@ func init() { filerOptions.dirListingLimit = cmdServer.Flag.Int("filer.dirListLimit", 1000, "limit sub dir listing size") filerOptions.cipher = cmdServer.Flag.Bool("filer.encryptVolumeData", false, "encrypt data on volume servers") filerOptions.peers = cmdServer.Flag.String("filer.peers", "", "all filers sharing the same filer store in comma separated ip:port list") + filerOptions.metricsHttpPort = cmdServer.Flag.Int("filer.metricsPort", 0, "Prometheus metrics listen port") serverOptions.v.port = cmdServer.Flag.Int("volume.port", 8080, "volume server http listen port") serverOptions.v.publicPort = cmdServer.Flag.Int("volume.port.public", 0, "volume server public port") @@ -100,12 +101,14 @@ func init() { serverOptions.v.publicUrl = cmdServer.Flag.String("volume.publicUrl", "", "publicly accessible address") serverOptions.v.preStopSeconds = cmdServer.Flag.Int("volume.preStopSeconds", 10, "number of seconds between stop send heartbeats and stop volume server") serverOptions.v.pprof = cmdServer.Flag.Bool("volume.pprof", false, "enable pprof http handlers. precludes --memprofile and --cpuprofile") + serverOptions.v.metricsHttpPort = cmdServer.Flag.Int("volume.metricsPort", 0, "Prometheus metrics listen port") s3Options.port = cmdServer.Flag.Int("s3.port", 8333, "s3 server http listen port") s3Options.domainName = cmdServer.Flag.String("s3.domainName", "", "suffix of the host name, {bucket}.{domainName}") s3Options.tlsPrivateKey = cmdServer.Flag.String("s3.key.file", "", "path to the TLS private key file") s3Options.tlsCertificate = cmdServer.Flag.String("s3.cert.file", "", "path to the TLS certificate file") s3Options.config = cmdServer.Flag.String("s3.config", "", "path to the config file") + s3Options.metricsHttpPort = cmdServer.Flag.Int("s3.metricsPort", 0, "Prometheus metrics listen port") msgBrokerOptions.port = cmdServer.Flag.Int("msgBroker.port", 17777, "broker gRPC listen port") diff --git a/weed/command/volume.go b/weed/command/volume.go index 92f83f945..82f2658c3 100644 --- a/weed/command/volume.go +++ b/weed/command/volume.go @@ -56,6 +56,7 @@ type VolumeServerOptions struct { minFreeSpacePercents []float32 pprof *bool preStopSeconds *int + metricsHttpPort *int // pulseSeconds *int } @@ -80,6 +81,7 @@ func init() { v.compactionMBPerSecond = cmdVolume.Flag.Int("compactionMBps", 0, "limit background compaction or copying speed in mega bytes per second") v.fileSizeLimitMB = cmdVolume.Flag.Int("fileSizeLimitMB", 1024, "limit file size to avoid out of memory") v.pprof = cmdVolume.Flag.Bool("pprof", false, "enable pprof http handlers. precludes --memprofile and --cpuprofile") + v.metricsHttpPort = cmdVolume.Flag.Int("metricsPort", 0, "Prometheus metrics listen port") } var cmdVolume = &Command{ @@ -207,6 +209,7 @@ func (v VolumeServerOptions) startVolumeServer(volumeFolders, maxVolumeCounts, v *v.fixJpgOrientation, *v.readRedirect, *v.compactionMBPerSecond, *v.fileSizeLimitMB, + *v.metricsHttpPort, ) // starting grpc server grpcS := v.startGrpcService(volumeServer) diff --git a/weed/server/filer_server.go b/weed/server/filer_server.go index 4d6d424dc..de271a483 100644 --- a/weed/server/filer_server.go +++ b/weed/server/filer_server.go @@ -54,6 +54,7 @@ type FilerOption struct { recursiveDelete bool Cipher bool Filers []string + MetricsHttpPort int } type FilerServer struct { @@ -157,6 +158,7 @@ func (fs *FilerServer) maybeStartMetrics() { } } + go stats.StartMetricsServer(stats.FilerGather, fs.option.MetricsHttpPort) go stats.LoopPushingMetric("filer", stats.SourceName(fs.option.Port), stats.FilerGather, fs.metricsAddress, fs.metricsIntervalSec) } diff --git a/weed/server/volume_server.go b/weed/server/volume_server.go index 5e9ec1369..2a9097f01 100644 --- a/weed/server/volume_server.go +++ b/weed/server/volume_server.go @@ -46,6 +46,7 @@ func NewVolumeServer(adminMux, publicMux *http.ServeMux, ip string, readRedirect bool, compactionMBPerSecond int, fileSizeLimitMB int, + metricsHttpPort int, ) *VolumeServer { v := util.GetViper() @@ -97,6 +98,7 @@ func NewVolumeServer(adminMux, publicMux *http.ServeMux, ip string, } go vs.heartbeat() + go stats.StartMetricsServer(stats.VolumeServerGather, metricsHttpPort) go stats.LoopPushingMetric("volumeServer", fmt.Sprintf("%s:%d", ip, port), stats.VolumeServerGather, vs.metricsAddress, vs.metricsIntervalSec) return vs diff --git a/weed/stats/metrics.go b/weed/stats/metrics.go index 29e7c8edf..5326622bd 100644 --- a/weed/stats/metrics.go +++ b/weed/stats/metrics.go @@ -2,11 +2,14 @@ package stats import ( "fmt" + "log" + "net/http" "os" "strings" "time" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/push" "github.com/chrislusf/seaweedfs/weed/glog" @@ -150,6 +153,14 @@ func LoopPushingMetric(name, instance string, gatherer *prometheus.Registry, add } } +func StartMetricsServer(gatherer *prometheus.Registry, port int) { + if port == 0 { + return + } + http.Handle("/metrics", promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{})) + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) +} + func SourceName(port uint32) string { hostname, err := os.Hostname() if err != nil {