Skip to content

Commit

Permalink
📊 ssgodatabyip: new package
Browse files Browse the repository at this point in the history
  • Loading branch information
database64128 committed Jan 7, 2025
1 parent 065cf55 commit d02eb4f
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
1 change: 1 addition & 0 deletions ssgodatabyip/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/ssgodatabyip
84 changes: 84 additions & 0 deletions ssgodatabyip/ssgodatabyip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Package ssgodatabyip implements a simple command-line tool that reads shadowsocks-go
// log entries from stdin, and prints peer data usage by IP address to stdout.
package main

import (
"bufio"
"bytes"
"cmp"
"encoding/json"
"fmt"
"io"
"net/netip"
"os"
"slices"
"strconv"
)

func main() {
bytesByIP := make(map[netip.Addr]uint64)
r := bufio.NewReader(os.Stdin)

for {
line, err := r.ReadSlice('\n')
if err != nil {
if err == io.EOF {
break
}
fmt.Fprintf(os.Stderr, "Failed to read line: %v\n", err)
os.Exit(1)
}

start := bytes.IndexByte(line, '{')
if start < 0 {
continue
}
data := line[start:]

var event Event
if err := json.Unmarshal(data, &event); err != nil {
fmt.Fprintf(os.Stderr, "Failed to unmarshal event %q: %v\n", data, err)
continue
}

if event.ClientAddress.IsValid() {
bytesByIP[event.ClientAddress.Addr()] += event.NL2R + event.NR2L + event.PayloadBytesSent
}

if event.LastWriteDestAddress.IsValid() {
bytesByIP[event.LastWriteDestAddress.Addr()] += event.PayloadBytesSent
}
}

usage := make([]DataUsage, 0, len(bytesByIP))
for ip, bytes := range bytesByIP {
usage = append(usage, DataUsage{IP: ip, Bytes: bytes})
}
slices.SortFunc(usage, func(a, b DataUsage) int {
return -cmp.Compare(a.Bytes, b.Bytes)
})

const maxOutputLength = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0\t18446744073709551615\n")
output := make([]byte, 0, maxOutputLength)
for _, usage := range usage {
output = usage.IP.AppendTo(output)
output = append(output, '\t')
output = strconv.AppendUint(output, usage.Bytes, 10)
output = append(output, '\n')
}
_, _ = os.Stdout.Write(output)
}

type Event struct {
ClientAddress netip.AddrPort `json:"clientAddress"`
NL2R uint64 `json:"nl2r"`
NR2L uint64 `json:"nr2l"`

LastWriteDestAddress netip.AddrPort `json:"lastWriteDestAddress"`
PayloadBytesSent uint64 `json:"payloadBytesSent"`
}

type DataUsage struct {
IP netip.Addr `json:"ip"`
Bytes uint64 `json:"bytes"`
}

0 comments on commit d02eb4f

Please sign in to comment.