mirror of
https://github.com/fatedier/frp.git
synced 2025-07-27 07:35:07 +00:00
api: add server web api for statistics
This commit is contained in:
60
utils/metric/counter.go
Normal file
60
utils/metric/counter.go
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 metric
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type Counter interface {
|
||||
Count() int64
|
||||
Inc(int64)
|
||||
Dec(int64)
|
||||
Snapshot() Counter
|
||||
Clear()
|
||||
}
|
||||
|
||||
func NewCounter() Counter {
|
||||
return &StandardCounter{
|
||||
count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
type StandardCounter struct {
|
||||
count int64
|
||||
}
|
||||
|
||||
func (c *StandardCounter) Count() int64 {
|
||||
return atomic.LoadInt64(&c.count)
|
||||
}
|
||||
|
||||
func (c *StandardCounter) Inc(count int64) {
|
||||
atomic.AddInt64(&c.count, count)
|
||||
}
|
||||
|
||||
func (c *StandardCounter) Dec(count int64) {
|
||||
atomic.AddInt64(&c.count, -count)
|
||||
}
|
||||
|
||||
func (c *StandardCounter) Snapshot() Counter {
|
||||
tmp := &StandardCounter{
|
||||
count: atomic.LoadInt64(&c.count),
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
func (c *StandardCounter) Clear() {
|
||||
atomic.StoreInt64(&c.count, 0)
|
||||
}
|
157
utils/metric/date_counter.go
Normal file
157
utils/metric/date_counter.go
Normal file
@@ -0,0 +1,157 @@
|
||||
// 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 metric
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DateCounter interface {
|
||||
TodayCount() int64
|
||||
GetLastDaysCount(lastdays int64) []int64
|
||||
Inc(int64)
|
||||
Dec(int64)
|
||||
Snapshot() DateCounter
|
||||
Clear()
|
||||
Close()
|
||||
}
|
||||
|
||||
func NewDateCounter(reserveDays int64) DateCounter {
|
||||
if reserveDays <= 0 {
|
||||
reserveDays = 1
|
||||
}
|
||||
return newStandardDateCounter(reserveDays)
|
||||
}
|
||||
|
||||
type StandardDateCounter struct {
|
||||
reserveDays int64
|
||||
counts []int64
|
||||
|
||||
closeCh chan struct{}
|
||||
closed bool
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func newStandardDateCounter(reserveDays int64) *StandardDateCounter {
|
||||
s := &StandardDateCounter{
|
||||
reserveDays: reserveDays,
|
||||
counts: make([]int64, reserveDays),
|
||||
closeCh: make(chan struct{}),
|
||||
}
|
||||
s.startRotateWorker()
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) TodayCount() int64 {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.counts[0]
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) GetLastDaysCount(lastdays int64) []int64 {
|
||||
if lastdays > c.reserveDays {
|
||||
lastdays = c.reserveDays
|
||||
}
|
||||
counts := make([]int64, lastdays)
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
for i := 0; i < int(lastdays); i++ {
|
||||
counts[i] = c.counts[i]
|
||||
}
|
||||
return counts
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) Inc(count int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.counts[0] += count
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) Dec(count int64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.counts[0] -= count
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) Snapshot() DateCounter {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
tmp := &StandardDateCounter{
|
||||
reserveDays: c.reserveDays,
|
||||
counts: make([]int64, c.reserveDays),
|
||||
}
|
||||
for i := 0; i < int(c.reserveDays); i++ {
|
||||
tmp.counts[i] = c.counts[i]
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) Clear() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
for i := 0; i < int(c.reserveDays); i++ {
|
||||
c.counts[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) Close() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if !c.closed {
|
||||
close(c.closeCh)
|
||||
c.closed = true
|
||||
}
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) rotate() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
newCounts := make([]int64, c.reserveDays)
|
||||
|
||||
for i := 1; i < int(c.reserveDays-1); i++ {
|
||||
newCounts[i] = c.counts[i+1]
|
||||
}
|
||||
c.counts = newCounts
|
||||
}
|
||||
|
||||
func (c *StandardDateCounter) startRotateWorker() {
|
||||
now := time.Now()
|
||||
nextDayTimeStr := now.Add(24 * time.Hour).Format("20060102")
|
||||
nextDay, _ := time.Parse("20060102", nextDayTimeStr)
|
||||
d := nextDay.Sub(now)
|
||||
|
||||
firstTimer := time.NewTimer(d)
|
||||
rotateTicker := time.NewTicker(24 * time.Hour)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-firstTimer.C:
|
||||
firstTimer.Stop()
|
||||
rotateTicker.Stop()
|
||||
rotateTicker = time.NewTicker(24 * time.Hour)
|
||||
c.rotate()
|
||||
case <-rotateTicker.C:
|
||||
c.rotate()
|
||||
case <-c.closeCh:
|
||||
break
|
||||
}
|
||||
}
|
||||
firstTimer.Stop()
|
||||
rotateTicker.Stop()
|
||||
}()
|
||||
}
|
Reference in New Issue
Block a user