diff --git a/cmd/frps/root.go b/cmd/frps/root.go index ec175fe3..865c10f7 100644 --- a/cmd/frps/root.go +++ b/cmd/frps/root.go @@ -59,6 +59,8 @@ var ( allowPorts string maxPoolCount int64 maxPortsPerClient int64 + promesAddr string + promesPort int ) func init() { @@ -81,6 +83,8 @@ func init() { rootCmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level") rootCmd.PersistentFlags().Int64VarP(&logMaxDays, "log_max_days", "", 3, "log max days") rootCmd.PersistentFlags().BoolVarP(&disableLogColor, "disable_log_color", "", false, "disable log color in console") + rootCmd.PersistentFlags().StringVarP(&promesAddr, "promes_addr", "", "0.0.0.0", "prometheus exporter address") + rootCmd.PersistentFlags().IntVarP(&promesPort, "promes_port", "", 0, "prometheus exporter port") rootCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token") rootCmd.PersistentFlags().StringVarP(&subDomainHost, "subdomain_host", "", "", "subdomain host") @@ -193,6 +197,11 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) { cfg.LogWay = "file" } cfg.DisableLogColor = disableLogColor + + //prometheus exporter + cfg.PromesAddr = promesAddr + cfg.DashboardPort = promesPort + return } diff --git a/conf/frps_full.ini b/conf/frps_full.ini index ed507cef..702f5191 100644 --- a/conf/frps_full.ini +++ b/conf/frps_full.ini @@ -71,3 +71,10 @@ tcp_mux = true # custom 404 page for HTTP requests # custom_404_page = /path/to/404.html + + +# set promes_addr and promes_port to get prometheus monitor of frps +# promes_addr's default value is same with bind_addr +# prometheus exporter is available only if promes_port is set +promes_addr = 0.0.0.0 +promes_port = 7501 \ No newline at end of file diff --git a/go.mod b/go.mod index a71a97c0..64dcced3 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/klauspost/reedsolomon v1.9.1 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc - github.com/pkg/errors v0.8.0 // indirect + github.com/prometheus/client_golang v1.2.1 github.com/rakyll/statik v0.1.1 github.com/rodaine/table v1.0.0 github.com/spf13/cobra v0.0.3 diff --git a/go.sum b/go.sum index 26c9004f..de9cefba 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,38 @@ +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb h1:wCrNShQidLmvVWn/0PikGmpdP0vtQmnvyRg3ZBEhczw= github.com/fatedier/beego v0.0.0-20171024143340-6c6a4f5bd5eb/go.mod h1:wx3gB6dbIfBRcucp94PI9Bt3I0F2c/MyNEWuhzpWiwk= github.com/fatedier/golib v0.0.0-20181107124048-ff8cd814b049 h1:teH578mf2ii42NHhIp3PhgvjU5bv+NFMq9fSQR8NaG8= github.com/fatedier/golib v0.0.0-20181107124048-ff8cd814b049/go.mod h1:DqIrnl0rp3Zybg9zbJmozTy1n8fYJoX+QoAj9slIkKM= github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible h1:ssXat9YXFvigNge/IkkZvFMn8yeYKFX+uI6wn2mLJ74= github.com/fatedier/kcp-go v2.0.4-0.20190803094908-fe8645b0a904+incompatible/go.mod h1:YpCOaxj7vvMThhIQ9AfTOPW2sfztQR5WDfs7AflSy4s= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049 h1:K9KHZbXKpGydfDN0aZrsoHpLJlZsBrGMFWbgLDGnPZk= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= @@ -14,38 +41,95 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/reedsolomon v1.9.1 h1:kYrT1MlR4JH6PqOpC+okdb9CDTcwEC/BqpzK4WFyXL8= github.com/klauspost/reedsolomon v1.9.1/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc h1:lNOt1SMsgHXTdpuGw+RpnJtzUcCb/oRKZP65pBy9pr8= github.com/pires/go-proxyproto v0.0.0-20190111085350-4d51b51e3bfc/go.mod h1:6/gX3+E/IYGa0wMORlSMla999awQFdbaeQCHjSMKIzY= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rakyll/statik v0.1.1 h1:fCLHsIMajHqD5RKigbFXpvX3dN7c80Pm12+NCrI3kvg= github.com/rakyll/statik v0.1.1/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= +github.com/rodaine/table v1.0.0 h1:UaCJG5Axc/cNXVGXqnCrffm1KxP0OfYLe1HuJLf5sFY= github.com/rodaine/table v1.0.0/go.mod h1:YAUzwPOji0DUJNEvggdxyQcUAl4g3hDRcFlyjnnR51I= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047 h1:K+jtWCOuZgCra7eXZ/VWn2FbJmrA/D058mTXhh2rq+8= github.com/templexxx/cpufeat v0.0.0-20170927014610-3794dfbfb047/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= +github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554 h1:pexgSe+JCFuxG+uoMZLO+ce8KHtdHGhst4cs6rw3gmk= github.com/templexxx/xor v0.0.0-20170926022130-0af8e873c554/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= +github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8 h1:6CNSDqI1wiE+JqyOy5Qt/yo/DoNI2/QmmOZeiCid2Nw= github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= +github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec h1:DGmKwyZwEB8dI7tbLt/I/gQuP559o/0FrAkHKlQM/Ks= github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec/go.mod h1:owBmyHYMLkxyrugmfwE/DLJyW8Ro9mkphwuVErQ0iUw= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/models/config/server_common.go b/models/config/server_common.go index a190a61a..e6953e5e 100644 --- a/models/config/server_common.go +++ b/models/config/server_common.go @@ -134,6 +134,13 @@ type ServerCommonConf struct { // UserConnTimeout specifies the maximum time to wait for a work // connection. By default, this value is 10. UserConnTimeout int64 `json:"user_conn_timeout"` + // PromesAddr specifies the address that the prometheus binds to. By default, + // this value is "0.0.0.0". + PromesAddr string `json:"bind_addr"` + // PromesPort specifies the port that the prometueus exporter listens on. If this + // value is 0, the dashboard will not be started. By default, this value is + // 0. + PromesPort int `json:"bind_port"` } // GetDefaultServerConf returns a server configuration with reasonable @@ -167,6 +174,8 @@ func GetDefaultServerConf() ServerCommonConf { HeartBeatTimeout: 90, UserConnTimeout: 10, Custom404Page: "", + PromesAddr: "0.0.0.0", + PromesPort: 0, } } @@ -372,6 +381,25 @@ func UnmarshalServerConfFromIni(content string) (cfg ServerCommonConf, err error cfg.HeartBeatTimeout = v } } + + //prometheus exporter + if tmpStr, ok = conf.Get("common", "promes_addr"); ok { + cfg.PromesAddr = tmpStr + } else { + cfg.PromesAddr = cfg.BindAddr + } + + if tmpStr, ok = conf.Get("common", "promes_port"); ok { + if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil { + err = fmt.Errorf("Parse conf error: invalid promes_port") + return + } else { + cfg.PromesPort = int(v) + } + } else { + cfg.PromesPort = 0 + } + return } diff --git a/server/monitor/prometheus.go b/server/monitor/prometheus.go new file mode 100644 index 00000000..32b9a52e --- /dev/null +++ b/server/monitor/prometheus.go @@ -0,0 +1,214 @@ +package monitor + +import ( + "net/http" + "strconv" + + "github.com/fatedier/frp/models/config" + "github.com/fatedier/frp/server/stats" + "github.com/fatedier/frp/utils/version" + "github.com/fatedier/frp/utils/xlog" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +type Prometheus struct { + statsCollector stats.Collector + config config.ServerCommonConf +} + +func NewPrometheus(statsCollector stats.Collector, config config.ServerCommonConf) *Prometheus { + return &Prometheus{ + statsCollector: statsCollector, + config: config, + } +} + +var ( + serverBindPort = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "frps_server_bind_port", + Help: "The port of server frps.", + }, []string{"address", "version"}) + serverBindUdpPort = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_bind_udp_port", + Help: "The udp port of server frps.", + }) + serverHeartBeatTimeout = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_heartbeat_timeout", + Help: "The heartbeat timeout of server frps.", + }) + serverKcpBindPort = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_kcp_bind_port", + Help: "The kcp port of server frps.", + }) + serverMaxPoolCount = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_max_poolcount", + Help: "The max poolcount of server frps.", + }) + serverVhostHttpPort = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "frps_server_http_port", + Help: "The http port of server frps.", + }, []string{"subdomain"}) + serverMaxPortsPerClient = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_maxport_perclient", + Help: "The maxport perclient of server frps.", + }) + serverVhostHttpsPort = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "frps_server_https_port", + Help: "The https port of server frps.", + }, []string{"subdomain"}) + serverClientCounts = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_client_counts", + Help: "The client counts of server frps.", + }) + serverCurConns = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_current_connections", + Help: "The current connections of server frps.", + }) + serverTotalTrafficIn = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_total_trafficin", + Help: "The total trafficin of server frps.", + }) + serverTotalTrafficOut = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "frps_server_total_trafficout", + Help: "The total trafficout of server frps.", + }) +) + +type ProxyStats struct { + Proxys []*stats.ProxyStats +} + +func NewProxyStats(Proxys []*stats.ProxyStats) *ProxyStats { + return &ProxyStats{ + Proxys: Proxys, + } +} + +func (s *ProxyStats) Describe(ch chan<- *prometheus.Desc) {} +func (s *ProxyStats) Collect(ch chan<- prometheus.Metric) { + dealWithProxyStats(s.Proxys, ch) +} + +func setValue(cfg config.ServerCommonConf) { + serverBindPort.With(prometheus.Labels{"address": cfg.BindAddr, "version": version.Full()}).Set(float64(cfg.BindPort)) + serverBindUdpPort.Set(float64(cfg.BindUdpPort)) + serverVhostHttpsPort.With(prometheus.Labels{"subdomain": cfg.SubDomainHost}).Set(float64(cfg.VhostHttpsPort)) + serverVhostHttpPort.With(prometheus.Labels{"subdomain": cfg.SubDomainHost}).Set(float64(cfg.VhostHttpPort)) + serverMaxPortsPerClient.Set(float64(cfg.MaxPortsPerClient)) + serverMaxPoolCount.Set(float64(cfg.MaxPoolCount)) + serverKcpBindPort.Set(float64(cfg.KcpBindPort)) + serverHeartBeatTimeout.Set(float64(cfg.HeartBeatTimeout)) + +} + +func (p *Prometheus) dealWithServerStats(ServerStats *stats.ServerStats) { + serverClientCounts.Set(float64(ServerStats.ClientCounts)) + serverCurConns.Set(float64(ServerStats.CurConns)) + serverTotalTrafficIn.Set(float64(ServerStats.TotalTrafficIn)) + serverTotalTrafficOut.Set(float64(ServerStats.TotalTrafficOut)) +} + +func dealWithProxyStats(ProxyStats []*stats.ProxyStats, ch chan<- prometheus.Metric) { + for _, v := range ProxyStats { + // Get the constant labels + var Labels = []string{"type", "laststarttime", "lastclosetime"} + var labelValue = []string{v.Type, v.LastStartTime, v.LastCloseTime} + //set value type + vType := prometheus.GaugeValue + + //get name + name := "frps_" + v.Name + "_today_trafficin" + //get description + description := "The today trafficin of proxy." + + //registry + desc := prometheus.NewDesc(name, description, Labels, nil) + ch <- prometheus.MustNewConstMetric(desc, vType, float64(v.TodayTrafficIn), labelValue...) + + //get name + name = "frps_" + v.Name + "_today_trafficout" + description = "The today trafficout of proxy." + + //registry + desc = prometheus.NewDesc(name, description, Labels, nil) + ch <- prometheus.MustNewConstMetric(desc, vType, float64(v.TodayTrafficOut), labelValue...) + + //get name + name = "frps_" + v.Name + "_currconns" + description = "The today currconns of proxy." + + //registry + desc = prometheus.NewDesc(name, description, Labels, nil) + ch <- prometheus.MustNewConstMetric(desc, vType, float64(v.CurConns), labelValue...) + } + +} + +func (p *Prometheus) handle(xl *xlog.Logger, w http.ResponseWriter, r *http.Request) { + //init config metrics + setValue(p.config) + + //deal with server stat. + ServerStats := p.statsCollector.GetServer() + p.dealWithServerStats(ServerStats) + + var Proxys []*stats.ProxyStats + for k, _ := range ServerStats.ProxyTypeCounts { + ProxyStats := p.statsCollector.GetProxiesByType(k) + Proxys = append(Proxys, ProxyStats...) + } + //NewProxyStats + proxyStats := NewProxyStats(Proxys) + //new registry + registry := prometheus.NewRegistry() + //registry exporter + registry.MustRegister(proxyStats) + registry.MustRegister(serverBindPort) + registry.MustRegister(serverBindUdpPort) + registry.MustRegister(serverVhostHttpPort) + registry.MustRegister(serverVhostHttpsPort) + registry.MustRegister(serverKcpBindPort) + registry.MustRegister(serverMaxPoolCount) + registry.MustRegister(serverMaxPortsPerClient) + registry.MustRegister(serverHeartBeatTimeout) + registry.MustRegister(serverClientCounts) + registry.MustRegister(serverCurConns) + registry.MustRegister(serverTotalTrafficIn) + registry.MustRegister(serverTotalTrafficOut) + //http server + h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{}) + h.ServeHTTP(w, r) +} + +func (p *Prometheus) Start() { + //init log + xl := xlog.New() + xl.Debug("Start To Export Data For Prometheus Metrics") + + //script metrics + http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { + p.handle(xl, w, r) + }) + + //root + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(` + frps Exporter + +

frps Exporter

+

Metrics

+ + `)) + }) + + listenAddress := p.config.PromesAddr + ":" + strconv.Itoa(p.config.PromesPort) + xl.Info("prometheus exporter listen on %s:%d", p.config.PromesAddr, p.config.PromesPort) + + //listen + if err := http.ListenAndServe(listenAddress, nil); err != nil { + xl.Error("Error starting HTTP server: %s", err) + } + +} diff --git a/server/service.go b/server/service.go index a4d2e9df..4b6c82b7 100644 --- a/server/service.go +++ b/server/service.go @@ -23,6 +23,7 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "github.com/fatedier/frp/server/monitor" "io/ioutil" "math/big" "net" @@ -88,6 +89,9 @@ type Service struct { tlsConfig *tls.Config cfg config.ServerCommonConf + + //monitor in prometheus + promes *monitor.Prometheus } func NewService(cfg config.ServerCommonConf) (svr *Service, err error) { @@ -241,7 +245,18 @@ func NewService(cfg config.ServerCommonConf) (svr *Service, err error) { statsEnable = true } + //start monitor server in prometheus + if cfg.PromesPort > 0 { + statsEnable = true + } svr.statsCollector = stats.NewInternalCollector(statsEnable) + + //start monitor server in prometheus + if cfg.PromesPort > 0 { + svr.promes = monitor.NewPrometheus(svr.statsCollector, cfg) + go svr.promes.Start() + } + return }