server.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2016 fatedier, fatedier@gmail.com
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package metric
  15. import (
  16. "sort"
  17. "sync"
  18. "time"
  19. "github.com/fatedier/frp/src/models/consts"
  20. )
  21. var (
  22. DailyDataKeepDays int = 7
  23. ServerMetricInfoMap map[string]*ServerMetric
  24. smMutex sync.RWMutex
  25. )
  26. type ServerMetric struct {
  27. Name string `json:"name"`
  28. Type string `json:"type"`
  29. BindAddr string `json:"bind_addr"`
  30. ListenPort int64 `json:"listen_port"`
  31. CustomDomains []string `json:"custom_domains"`
  32. Locations []string `json:"locations"`
  33. Status string `json:"status"`
  34. UseEncryption bool `json:"use_encryption"`
  35. UseGzip bool `json:"use_gzip"`
  36. PrivilegeMode bool `json:"privilege_mode"`
  37. // statistics
  38. CurrentConns int64 `json:"current_conns"`
  39. Daily []*DailyServerStats `json:"daily"`
  40. mutex sync.RWMutex
  41. }
  42. type DailyServerStats struct {
  43. Time string `json:"time"`
  44. FlowIn int64 `json:"flow_in"`
  45. FlowOut int64 `json:"flow_out"`
  46. TotalAcceptConns int64 `json:"total_accept_conns"`
  47. }
  48. // for sort
  49. type ServerMetricList []*ServerMetric
  50. func (l ServerMetricList) Len() int { return len(l) }
  51. func (l ServerMetricList) Less(i, j int) bool { return l[i].Name < l[j].Name }
  52. func (l ServerMetricList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
  53. func init() {
  54. ServerMetricInfoMap = make(map[string]*ServerMetric)
  55. }
  56. func (s *ServerMetric) clone() *ServerMetric {
  57. copy := *s
  58. copy.CustomDomains = make([]string, len(s.CustomDomains))
  59. var i int
  60. for i = range copy.CustomDomains {
  61. copy.CustomDomains[i] = s.CustomDomains[i]
  62. }
  63. copy.Daily = make([]*DailyServerStats, len(s.Daily))
  64. for i = range copy.Daily {
  65. tmpDaily := *s.Daily[i]
  66. copy.Daily[i] = &tmpDaily
  67. }
  68. return &copy
  69. }
  70. func GetAllProxyMetrics() []*ServerMetric {
  71. result := make(ServerMetricList, 0)
  72. smMutex.RLock()
  73. for _, metric := range ServerMetricInfoMap {
  74. metric.mutex.RLock()
  75. tmpMetric := metric.clone()
  76. metric.mutex.RUnlock()
  77. result = append(result, tmpMetric)
  78. }
  79. smMutex.RUnlock()
  80. // sort for result by proxy name
  81. sort.Sort(result)
  82. return result
  83. }
  84. // if proxyName isn't exist, return nil
  85. func GetProxyMetrics(proxyName string) *ServerMetric {
  86. smMutex.RLock()
  87. defer smMutex.RUnlock()
  88. metric, ok := ServerMetricInfoMap[proxyName]
  89. if ok {
  90. metric.mutex.RLock()
  91. tmpMetric := metric.clone()
  92. metric.mutex.RUnlock()
  93. return tmpMetric
  94. } else {
  95. return nil
  96. }
  97. }
  98. func SetProxyInfo(proxyName string, proxyType, bindAddr string,
  99. useEncryption, useGzip, privilegeMode bool, customDomains []string,
  100. locations []string, listenPort int64) {
  101. smMutex.Lock()
  102. info, ok := ServerMetricInfoMap[proxyName]
  103. if !ok {
  104. info = &ServerMetric{}
  105. info.Daily = make([]*DailyServerStats, 0)
  106. }
  107. info.Name = proxyName
  108. info.Type = proxyType
  109. info.UseEncryption = useEncryption
  110. info.UseGzip = useGzip
  111. info.PrivilegeMode = privilegeMode
  112. info.BindAddr = bindAddr
  113. info.ListenPort = listenPort
  114. info.CustomDomains = customDomains
  115. info.Locations = locations
  116. ServerMetricInfoMap[proxyName] = info
  117. smMutex.Unlock()
  118. }
  119. func SetStatus(proxyName string, status int64) {
  120. smMutex.RLock()
  121. metric, ok := ServerMetricInfoMap[proxyName]
  122. smMutex.RUnlock()
  123. if ok {
  124. metric.mutex.Lock()
  125. metric.Status = consts.StatusStr[status]
  126. metric.mutex.Unlock()
  127. }
  128. }
  129. type DealFuncType func(*DailyServerStats)
  130. func DealDailyData(dailyData []*DailyServerStats, fn DealFuncType) (newDailyData []*DailyServerStats) {
  131. now := time.Now().Format("20060102")
  132. dailyLen := len(dailyData)
  133. if dailyLen == 0 {
  134. daily := &DailyServerStats{}
  135. daily.Time = now
  136. fn(daily)
  137. dailyData = append(dailyData, daily)
  138. } else {
  139. daily := dailyData[dailyLen-1]
  140. if daily.Time == now {
  141. fn(daily)
  142. } else {
  143. newDaily := &DailyServerStats{}
  144. newDaily.Time = now
  145. fn(newDaily)
  146. if dailyLen == DailyDataKeepDays {
  147. for i := 0; i < dailyLen-1; i++ {
  148. dailyData[i] = dailyData[i+1]
  149. }
  150. dailyData[dailyLen-1] = newDaily
  151. } else {
  152. dailyData = append(dailyData, newDaily)
  153. }
  154. }
  155. }
  156. return dailyData
  157. }
  158. func OpenConnection(proxyName string) {
  159. smMutex.RLock()
  160. metric, ok := ServerMetricInfoMap[proxyName]
  161. smMutex.RUnlock()
  162. if ok {
  163. metric.mutex.Lock()
  164. metric.CurrentConns++
  165. metric.Daily = DealDailyData(metric.Daily, func(stats *DailyServerStats) {
  166. stats.TotalAcceptConns++
  167. })
  168. metric.mutex.Unlock()
  169. }
  170. }
  171. func CloseConnection(proxyName string) {
  172. smMutex.RLock()
  173. metric, ok := ServerMetricInfoMap[proxyName]
  174. smMutex.RUnlock()
  175. if ok {
  176. metric.mutex.Lock()
  177. metric.CurrentConns--
  178. metric.mutex.Unlock()
  179. }
  180. }
  181. func AddFlowIn(proxyName string, value int64) {
  182. smMutex.RLock()
  183. metric, ok := ServerMetricInfoMap[proxyName]
  184. smMutex.RUnlock()
  185. if ok {
  186. metric.mutex.Lock()
  187. metric.Daily = DealDailyData(metric.Daily, func(stats *DailyServerStats) {
  188. stats.FlowIn += value
  189. })
  190. metric.mutex.Unlock()
  191. }
  192. }
  193. func AddFlowOut(proxyName string, value int64) {
  194. smMutex.RLock()
  195. metric, ok := ServerMetricInfoMap[proxyName]
  196. smMutex.RUnlock()
  197. if ok {
  198. metric.mutex.Lock()
  199. metric.Daily = DealDailyData(metric.Daily, func(stats *DailyServerStats) {
  200. stats.FlowOut += value
  201. })
  202. metric.mutex.Unlock()
  203. }
  204. }