-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathoutput.go
128 lines (107 loc) · 4.13 KB
/
output.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
121
122
123
124
125
126
127
128
// @license
// Copyright (C) 2024 Dinko Korunic
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package main
import (
"fmt"
"sort"
"time"
"github.com/goccy/go-json"
)
const (
Bps float64 = 1.0
Kbps = 1000 * Bps
Mbps = 1000 * Kbps
Gbps = 1000 * Mbps
Tbps = 1000 * Gbps
)
type statJSON struct {
statKey
statEntry
}
// outputPlain generates output based on the statistics collected.
//
// startTime - the start time of the statistics collection.
// statMap - a map containing statistical data.
// totalPackets - total number of packets.
// totalBytes - total number of bytes.
func outputPlain(startTime time.Time, statMap StatMap, totalPackets, totalBytes uint64) {
dur := time.Since(startTime).Seconds()
keySlice := calcBitrate(statMap, dur)
for _, k := range keySlice {
fmt.Printf("bitrate: %v, packets: %d, bytes: %d, proto: %v, src: %v:%v, dst: %v:%v\n",
formatBitrate(statMap[k].Bitrate), statMap[k].Packets, statMap[k].Size, k.Proto.String(), k.SrcIP, k.SrcPort, k.DstIP, k.DstPort)
}
fmt.Printf("\nRead total packets: %d, total bytes: %d in %0.2f seconds\n", totalPackets, totalBytes, dur)
}
// outputJSON generates a JSON output based on the provided statistics map and time duration.
// startTime: the start time used to calculate the duration.
// statMap: the map containing statistics entries.
// totalPackets: the total number of packets.
// totalBytes: the total number of bytes.
func outputJSON(startTime time.Time, statMap StatMap, _, _ uint64) {
dur := time.Since(startTime).Seconds()
keySlice := calcBitrate(statMap, dur)
statJSONs := make([]statJSON, 0, len(keySlice))
for _, k := range keySlice {
statJSONs = append(statJSONs, statJSON{
statEntry: statMap[k],
statKey: k,
})
}
out, _ := json.Marshal(statJSONs)
fmt.Printf("%v\n", string(out))
}
// calcBitrate calculates the bitrate for each statEntry in the given statMap based on the duration provided, and returns a slice of statKeys sorted by bitrate in descending order.
//
// Parameters:
// - statMap: a map containing statKey as keys and statEntry as values
// - dur: a float64 representing the duration for bitrate calculation
// Returns:
// - []statKey: a slice of statKeys sorted by bitrate in descending order
func calcBitrate(statMap StatMap, dur float64) []statKey {
keySlice := make([]statKey, 0, len(statMap))
// calculate bitrates and prepare keys for sort
for k, v := range statMap {
v.Bitrate = 8 * float64(v.Size) / dur
keySlice = append(keySlice, k)
statMap[k] = v
}
// sort by bitrate descending
sort.Slice(keySlice, func(i, j int) bool {
return statMap[keySlice[i]].Bitrate > statMap[keySlice[j]].Bitrate
})
return keySlice
}
// MarshalJSON marshals the statKey struct into a JSON byte slice.
//
// It returns a byte slice containing the JSON representation of the struct
// and an error if any occurred during the marshaling process.
func (s *statJSON) MarshalJSON() ([]byte, error) {
type Alias statJSON
// create a temporary struct to override Proto field serialization
return json.Marshal(&struct {
*Alias
Proto string `json:"proto"`
}{
Alias: (*Alias)(s),
Proto: s.Proto.String(),
})
}