server: adjust code structure

This commit is contained in:
fatedier
2019-01-15 00:11:08 +08:00
parent 0c7d778896
commit 611d063e1f
17 changed files with 1458 additions and 1141 deletions

273
server/stats/internal.go Normal file
View File

@@ -0,0 +1,273 @@
// Copyright 2019 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package stats
import (
"sync"
"time"
"github.com/fatedier/frp/utils/log"
"github.com/fatedier/frp/utils/metric"
)
type internalCollector struct {
enable bool
info *ServerStatistics
mu sync.Mutex
}
func NewInternalCollector(enable bool) Collector {
return &internalCollector{
enable: enable,
info: &ServerStatistics{
TotalTrafficIn: metric.NewDateCounter(ReserveDays),
TotalTrafficOut: metric.NewDateCounter(ReserveDays),
CurConns: metric.NewCounter(),
ClientCounts: metric.NewCounter(),
ProxyTypeCounts: make(map[string]metric.Counter),
ProxyStatistics: make(map[string]*ProxyStatistics),
},
}
}
func (collector *internalCollector) Run() error {
go func() {
for {
time.Sleep(12 * time.Hour)
log.Debug("start to clear useless proxy statistics data...")
collector.ClearUselessInfo()
log.Debug("finish to clear useless proxy statistics data")
}
}()
return nil
}
func (collector *internalCollector) ClearUselessInfo() {
// To check if there are proxies that closed than 7 days and drop them.
collector.mu.Lock()
defer collector.mu.Unlock()
for name, data := range collector.info.ProxyStatistics {
if !data.LastCloseTime.IsZero() && time.Since(data.LastCloseTime) > time.Duration(7*24)*time.Hour {
delete(collector.info.ProxyStatistics, name)
log.Trace("clear proxy [%s]'s statistics data, lastCloseTime: [%s]", name, data.LastCloseTime.String())
}
}
}
func (collector *internalCollector) Mark(statsType StatsType, payload interface{}) {
if !collector.enable {
return
}
switch v := payload.(type) {
case *NewClientPayload:
collector.newClient(v)
case *CloseClientPayload:
collector.closeClient(v)
case *OpenConnectionPayload:
collector.openConnection(v)
case *CloseConnectionPayload:
collector.closeConnection(v)
case *AddTrafficInPayload:
collector.addTrafficIn(v)
case *AddTrafficOutPayload:
collector.addTrafficOut(v)
}
}
func (collector *internalCollector) newClient(payload *NewClientPayload) {
collector.info.ClientCounts.Inc(1)
}
func (collector *internalCollector) closeClient(payload *CloseClientPayload) {
collector.info.ClientCounts.Dec(1)
}
func (collector *internalCollector) newProxy(payload *NewProxyPayload) {
collector.mu.Lock()
defer collector.mu.Unlock()
counter, ok := collector.info.ProxyTypeCounts[payload.ProxyType]
if !ok {
counter = metric.NewCounter()
}
counter.Inc(1)
collector.info.ProxyTypeCounts[payload.ProxyType] = counter
proxyStats, ok := collector.info.ProxyStatistics[payload.Name]
if !(ok && proxyStats.ProxyType == payload.ProxyType) {
proxyStats = &ProxyStatistics{
Name: payload.Name,
ProxyType: payload.ProxyType,
CurConns: metric.NewCounter(),
TrafficIn: metric.NewDateCounter(ReserveDays),
TrafficOut: metric.NewDateCounter(ReserveDays),
}
collector.info.ProxyStatistics[payload.Name] = proxyStats
}
proxyStats.LastStartTime = time.Now()
}
func (collector *internalCollector) closeProxy(payload *CloseProxyPayload) {
collector.mu.Lock()
defer collector.mu.Unlock()
if counter, ok := collector.info.ProxyTypeCounts[payload.ProxyType]; ok {
counter.Dec(1)
}
if proxyStats, ok := collector.info.ProxyStatistics[payload.Name]; ok {
proxyStats.LastCloseTime = time.Now()
}
}
func (collector *internalCollector) openConnection(payload *OpenConnectionPayload) {
collector.info.CurConns.Inc(1)
collector.mu.Lock()
defer collector.mu.Unlock()
proxyStats, ok := collector.info.ProxyStatistics[payload.ProxyName]
if ok {
proxyStats.CurConns.Inc(1)
collector.info.ProxyStatistics[payload.ProxyName] = proxyStats
}
}
func (collector *internalCollector) closeConnection(payload *CloseConnectionPayload) {
collector.info.CurConns.Dec(1)
collector.mu.Lock()
defer collector.mu.Unlock()
proxyStats, ok := collector.info.ProxyStatistics[payload.ProxyName]
if ok {
proxyStats.CurConns.Dec(1)
collector.info.ProxyStatistics[payload.ProxyName] = proxyStats
}
}
func (collector *internalCollector) addTrafficIn(payload *AddTrafficInPayload) {
collector.info.TotalTrafficIn.Inc(payload.TrafficBytes)
collector.mu.Lock()
defer collector.mu.Unlock()
proxyStats, ok := collector.info.ProxyStatistics[payload.ProxyName]
if ok {
proxyStats.TrafficIn.Inc(payload.TrafficBytes)
collector.info.ProxyStatistics[payload.ProxyName] = proxyStats
}
}
func (collector *internalCollector) addTrafficOut(payload *AddTrafficOutPayload) {
collector.info.TotalTrafficOut.Inc(payload.TrafficBytes)
collector.mu.Lock()
defer collector.mu.Unlock()
proxyStats, ok := collector.info.ProxyStatistics[payload.ProxyName]
if ok {
proxyStats.TrafficOut.Inc(payload.TrafficBytes)
collector.info.ProxyStatistics[payload.ProxyName] = proxyStats
}
}
func (collector *internalCollector) GetServer() *ServerStats {
collector.mu.Lock()
defer collector.mu.Unlock()
s := &ServerStats{
TotalTrafficIn: collector.info.TotalTrafficIn.TodayCount(),
TotalTrafficOut: collector.info.TotalTrafficOut.TodayCount(),
CurConns: collector.info.CurConns.Count(),
ClientCounts: collector.info.ClientCounts.Count(),
ProxyTypeCounts: make(map[string]int64),
}
for k, v := range collector.info.ProxyTypeCounts {
s.ProxyTypeCounts[k] = v.Count()
}
return s
}
func (collector *internalCollector) GetProxiesByType(proxyType string) []*ProxyStats {
res := make([]*ProxyStats, 0)
collector.mu.Lock()
defer collector.mu.Unlock()
for name, proxyStats := range collector.info.ProxyStatistics {
if proxyStats.ProxyType != proxyType {
continue
}
ps := &ProxyStats{
Name: name,
Type: proxyStats.ProxyType,
TodayTrafficIn: proxyStats.TrafficIn.TodayCount(),
TodayTrafficOut: proxyStats.TrafficOut.TodayCount(),
CurConns: proxyStats.CurConns.Count(),
}
if !proxyStats.LastStartTime.IsZero() {
ps.LastStartTime = proxyStats.LastStartTime.Format("01-02 15:04:05")
}
if !proxyStats.LastCloseTime.IsZero() {
ps.LastCloseTime = proxyStats.LastCloseTime.Format("01-02 15:04:05")
}
res = append(res, ps)
}
return res
}
func (collector *internalCollector) GetProxiesByTypeAndName(proxyType string, proxyName string) (res *ProxyStats) {
collector.mu.Lock()
defer collector.mu.Unlock()
for name, proxyStats := range collector.info.ProxyStatistics {
if proxyStats.ProxyType != proxyType {
continue
}
if name != proxyName {
continue
}
res = &ProxyStats{
Name: name,
Type: proxyStats.ProxyType,
TodayTrafficIn: proxyStats.TrafficIn.TodayCount(),
TodayTrafficOut: proxyStats.TrafficOut.TodayCount(),
CurConns: proxyStats.CurConns.Count(),
}
if !proxyStats.LastStartTime.IsZero() {
res.LastStartTime = proxyStats.LastStartTime.Format("01-02 15:04:05")
}
if !proxyStats.LastCloseTime.IsZero() {
res.LastCloseTime = proxyStats.LastCloseTime.Format("01-02 15:04:05")
}
break
}
return
}
func (collector *internalCollector) GetProxyTraffic(name string) (res *ProxyTrafficInfo) {
collector.mu.Lock()
defer collector.mu.Unlock()
proxyStats, ok := collector.info.ProxyStatistics[name]
if ok {
res = &ProxyTrafficInfo{
Name: name,
}
res.TrafficIn = proxyStats.TrafficIn.GetLastDaysCount(ReserveDays)
res.TrafficOut = proxyStats.TrafficOut.GetLastDaysCount(ReserveDays)
}
return
}

129
server/stats/stats.go Normal file
View File

@@ -0,0 +1,129 @@
// Copyright 2017 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package stats
import (
"time"
"github.com/fatedier/frp/utils/metric"
)
const (
ReserveDays = 7
)
type StatsType int
const (
TypeNewClient StatsType = iota
TypeCloseClient
TypeNewProxy
TypeCloseProxy
TypeOpenConnection
TypeCloseConnection
TypeAddTrafficIn
TypeAddTrafficOut
)
type ServerStats struct {
TotalTrafficIn int64
TotalTrafficOut int64
CurConns int64
ClientCounts int64
ProxyTypeCounts map[string]int64
}
type ProxyStats struct {
Name string
Type string
TodayTrafficIn int64
TodayTrafficOut int64
LastStartTime string
LastCloseTime string
CurConns int64
}
type ProxyTrafficInfo struct {
Name string
TrafficIn []int64
TrafficOut []int64
}
type ProxyStatistics struct {
Name string
ProxyType string
TrafficIn metric.DateCounter
TrafficOut metric.DateCounter
CurConns metric.Counter
LastStartTime time.Time
LastCloseTime time.Time
}
type ServerStatistics struct {
TotalTrafficIn metric.DateCounter
TotalTrafficOut metric.DateCounter
CurConns metric.Counter
// counter for clients
ClientCounts metric.Counter
// counter for proxy types
ProxyTypeCounts map[string]metric.Counter
// statistics for different proxies
// key is proxy name
ProxyStatistics map[string]*ProxyStatistics
}
type Collector interface {
Mark(statsType StatsType, payload interface{})
Run() error
GetServer() *ServerStats
GetProxiesByType(proxyType string) []*ProxyStats
GetProxiesByTypeAndName(proxyType string, proxyName string) *ProxyStats
GetProxyTraffic(name string) *ProxyTrafficInfo
}
type NewClientPayload struct{}
type CloseClientPayload struct{}
type NewProxyPayload struct {
Name string
ProxyType string
}
type CloseProxyPayload struct {
Name string
ProxyType string
}
type OpenConnectionPayload struct {
ProxyName string
}
type CloseConnectionPayload struct {
ProxyName string
}
type AddTrafficInPayload struct {
ProxyName string
TrafficBytes int64
}
type AddTrafficOutPayload struct {
ProxyName string
TrafficBytes int64
}