-
Notifications
You must be signed in to change notification settings - Fork 1
/
traffic_monitors.go
94 lines (80 loc) · 2.33 KB
/
traffic_monitors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
64
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
94
package main
import (
"fmt"
"strings"
"time"
)
type TrafficMonitor interface {
Monitor(Event)
Stop()
}
type TrafficStatistics struct {
Destination string
AveragePayload float64
TotalPayload int64
Count int64
}
func (t *TrafficStatistics) String() string {
statisticsFormat := "Destination: %s\nAverage Payload: %f\nTotal Payload: %d\nCount: %d\n"
return fmt.Sprintf(statisticsFormat, t.Destination, t.AveragePayload, t.TotalPayload, t.Count)
}
type SummaryStatsTrafficMonitor struct {
duration time.Duration
notification Notification
ticker *time.Ticker
events chan Event
statistics map[string]TrafficStatistics
}
func NewSummaryStatsTrafficMonitor(duration time.Duration, notification Notification) *SummaryStatsTrafficMonitor {
monitor := &SummaryStatsTrafficMonitor{
duration: duration,
notification: notification,
events: make(chan Event),
statistics: map[string]TrafficStatistics{},
}
go monitor.consumeEvents()
go monitor.publishStatistics()
return monitor
}
func (s *SummaryStatsTrafficMonitor) Monitor(event Event) {
s.events <- event
}
func (s *SummaryStatsTrafficMonitor) Stop() {
s.ticker.Stop()
close(s.events)
}
func (s *SummaryStatsTrafficMonitor) summary() string {
statistics := make([]string, len(s.statistics))
i := 0
for _, statistic := range s.statistics {
statistics[i] = statistic.String()
i++
}
return strings.Join(statistics, "\n")
}
func (s *SummaryStatsTrafficMonitor) publishStatistics() {
s.ticker = time.NewTicker(s.duration)
for _ = range s.ticker.C {
s.notification.Send(s.summary())
s.statistics = map[string]TrafficStatistics{}
}
}
func (s *SummaryStatsTrafficMonitor) consumeEvents() {
for event := range s.events {
if statistic, ok := s.statistics[event.Destination]; ok {
s.statistics[event.Destination] = TrafficStatistics{
Destination: event.Destination,
AveragePayload: (float64(statistic.Count)*statistic.AveragePayload + float64(len(event.Payload))) / float64((statistic.Count + 1)),
TotalPayload: statistic.TotalPayload + int64(len(event.Payload)),
Count: statistic.Count + 1,
}
} else {
s.statistics[event.Destination] = TrafficStatistics{
Destination: event.Destination,
AveragePayload: float64(len(event.Payload)),
TotalPayload: int64(len(event.Payload)),
Count: 1,
}
}
}
}