metrics.go 2.35 KB
Newer Older
Hooman's avatar
Hooman committed
1
package main
2
3
4

import (
	// "golang.org/x/net/internal/timeseries"
5
6
7
8
	"fmt"
	"log"
	"net"
	"sync"
9
10
11
	"time"
)

12
13
14
15
var (
	once sync.Once
)

16
17
const metricsResolution = 24 * time.Hour

18
19
20
21
type CountryStats struct {
	counts map[string]int
}

22
23
// Implements Observable
type Metrics struct {
24
25
26
27
28
	logger  *log.Logger
	tablev4 *GeoIPv4Table
	tablev6 *GeoIPv6Table

	countryStats            CountryStats
29
	clientRoundtripEstimate time.Duration
30
31
32
	proxyIdleCount          int
	clientDeniedCount       int
	clientProxyMatchCount   int
33
34
}

35
func (s CountryStats) Display() string {
36
	return fmt.Sprint(s.counts)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
}

func (m *Metrics) UpdateCountryStats(addr string) {

	var country string
	var ok bool

	ip := net.ParseIP(addr)
	if ip.To4() != nil {
		//This is an IPv4 address
		if m.tablev4 == nil {
			return
		}
		country, ok = GetCountryByAddr(m.tablev4, ip)
	} else {
		if m.tablev6 == nil {
			return
		}
		country, ok = GetCountryByAddr(m.tablev6, ip)
	}

	if !ok {
		country = "??"
		log.Println("Unknown geoip")
	}

	//update map of countries and counts
64
	m.countryStats.counts[country]++
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

	return
}

func (m *Metrics) LoadGeoipDatabases(geoipDB string, geoip6DB string) error {

	// Load geoip databases
	log.Println("Loading geoip databases")
	tablev4 := new(GeoIPv4Table)
	err := GeoIPLoadFile(tablev4, geoipDB)
	if err != nil {
		m.tablev4 = nil
		return err
	} else {
		m.tablev4 = tablev4
	}

	tablev6 := new(GeoIPv6Table)
	err = GeoIPLoadFile(tablev6, geoip6DB)
	if err != nil {
		m.tablev6 = nil
		return err
	} else {
		m.tablev6 = tablev6
	}

	return nil
}

94
func NewMetrics(metricsLogger *log.Logger) (*Metrics, error) {
95
	m := new(Metrics)
96
97
98
99
100

	m.countryStats = CountryStats{
		counts: make(map[string]int),
	}

101
102
	m.logger = metricsLogger

103
	// Write to log file every hour with updated metrics
104
105
106
107
	go once.Do(m.logMetrics)

	return m, nil
}
108

109
func (m *Metrics) logMetrics() {
110

111
112
113
114
115
116
117
	heartbeat := time.Tick(metricsResolution)
	for range heartbeat {
		m.logger.Println("snowflake-stats-end ")
		m.logger.Println("snowflake-ips ", m.countryStats.Display())
		m.logger.Println("snowflake-idle-count ", m.proxyIdleCount)
		m.logger.Println("client-denied-count ", m.clientDeniedCount)
		m.logger.Println("client-snowflake-match-count ", m.clientProxyMatchCount)
118

119
		//restore all metrics to original values
120
121
122
		m.proxyIdleCount = 0
		m.clientDeniedCount = 0
		m.clientProxyMatchCount = 0
123
124
		m.countryStats.counts = make(map[string]int)
	}
125
}