-
Notifications
You must be signed in to change notification settings - Fork 8
/
stats.go
120 lines (108 loc) · 3.24 KB
/
stats.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2018 Virta Laboratories, Inc. All rights reserved.
/*
Track stats of packets decoded.
*/
package main
import (
"encoding/json"
"sort"
"sync"
)
// Stats stores statistics about observed Assets and packets.
type Stats struct {
sync.Mutex
TotalPacketCount uint64 `json:"packet_count"` // Grand total number of packets
PacketLayers map[string]uint64 `json:"packet_layers"` // Count of each packet layer type
IPv4Addresses map[string]uint64 `json:"ipv4_addresses"` // Unique sender IPv4 addresses
IPv6Addresses map[string]uint64 `json:"ipv6_addresses"` // Unique sender IPv6 addresses
Ports map[string]uint64 `json:"ports"` // Unique sender TCP ports
MACs map[string]uint64 `json:"mac_addresses"` // Unique sender MAC addresses
Identifiers map[string]uint64 `json:"identifiers"` // Unique device identification strings
Provenances map[string]uint64 `json:"provenances"` // Count of identifier provenance
Errors map[string]uint64 `json:"errors"` // Count of errors
UploadResults map[string]uint64 `json:"uploads"` // Count upload outcodes
}
// NewStats returns a new, empty container for statistics.
func NewStats() *Stats {
s := new(Stats)
s.PacketLayers = make(map[string]uint64)
s.IPv4Addresses = make(map[string]uint64)
s.IPv6Addresses = make(map[string]uint64)
s.Ports = make(map[string]uint64)
s.MACs = make(map[string]uint64)
s.Identifiers = make(map[string]uint64)
s.Provenances = make(map[string]uint64)
s.Errors = make(map[string]uint64)
s.UploadResults = make(map[string]uint64)
return s
}
// AddLayer tracks the number of each type of packet layer
func (s *Stats) AddLayer(layerName string) {
s.Lock()
defer s.Unlock()
s.PacketLayers[layerName]++
}
// AddPacket updates the packet count.
func (s *Stats) AddPacket() {
s.Lock()
defer s.Unlock()
s.TotalPacketCount++
}
// AddError tracks the number of each type of error
func (s *Stats) AddError(err error) {
s.Lock()
defer s.Unlock()
s.Errors[err.Error()]++
}
// AddAsset reports that a valid packet with identifying information has been
// seen.
func (s *Stats) AddAsset(asset *Asset) {
logger.Println("AddAsset()")
s.Lock()
defer s.Unlock()
if asset.IPv4Address != "" {
s.IPv4Addresses[asset.IPv4Address]++
}
if asset.IPv6Address != "" {
s.IPv6Addresses[asset.IPv6Address]++
}
if asset.ListensOnPort != "" {
s.Ports[asset.ListensOnPort]++
}
if asset.ConnectsToPort != "" {
s.Ports[asset.ConnectsToPort]++
}
if asset.MACAddress != "" {
s.MACs[asset.MACAddress]++
}
if asset.Identifier != "" {
s.Identifiers[asset.Identifier]++
}
if asset.Provenance != "" {
s.Provenances[asset.Provenance]++
}
}
// AddUpload reports that an API upload succeeded.
func (s *Stats) AddUpload() {
s.Lock()
defer s.Unlock()
s.UploadResults["OK"]++
}
// AddUploadError reports that an API upload succeeded.
func (s *Stats) AddUploadError(err error) {
s.Lock()
defer s.Unlock()
s.UploadResults[err.Error()]++
}
func sortedMapKeys(m map[string]uint64) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
func (s *Stats) String() string {
statJSON, _ := json.MarshalIndent(s, "", " ")
return string(statJSON)
}