Skip to content

Commit 986c2aa

Browse files
authored
Merge pull request #40 from yuuki/feature/refactor-printer-module
refactor: separate printer functionality into dedicated module
2 parents eb1207b + ea311b6 commit 986c2aa

File tree

7 files changed

+769
-121
lines changed

7 files changed

+769
-121
lines changed

client.go

Lines changed: 2 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ package main
33
import (
44
"context"
55
"crypto/rand"
6-
"encoding/json"
76
"errors"
87
"fmt"
9-
"io"
108
"log/slog"
119
"net"
1210
"sync"
@@ -308,35 +306,7 @@ func (c *Client) connectUDP(ctx context.Context, addrport string) error {
308306
return eg.Wait()
309307
}
310308

311-
func toMicroseconds(n int64) int64 {
312-
return time.Duration(n).Microseconds()
313-
}
314-
315-
func toMicrosecondsf(n float64) int64 {
316-
return time.Duration(n).Microseconds()
317-
}
318-
319-
func printStatHeader(w io.Writer) {
320-
fmt.Fprintf(w, "%-20s %-10s %-15s %-15s %-15s %-15s %-15s %-15s %-10s\n",
321-
"PEER", "CNT", "LAT_MAX(µs)", "LAT_MIN(µs)", "LAT_MEAN(µs)",
322-
"LAT_90p(µs)", "LAT_95p(µs)", "LAT_99p(µs)", "RATE(/s)")
323-
}
324-
325-
func printStatLine(w io.Writer, addr string, stat metrics.Timer) {
326-
fmt.Fprintf(w, "%-20s %-10d %-15d %-15d %-15d %-15d %-15d %-15d %-10.2f\n",
327-
addr,
328-
stat.Count(),
329-
toMicroseconds(stat.Max()),
330-
toMicroseconds(stat.Min()),
331-
toMicrosecondsf(stat.Mean()),
332-
toMicrosecondsf(stat.Percentile(0.9)),
333-
toMicrosecondsf(stat.Percentile(0.95)),
334-
toMicrosecondsf(stat.Percentile(0.99)),
335-
stat.RateMean(),
336-
)
337-
}
338-
339-
func runStatLinePrinter(ctx context.Context, w io.Writer, addr string, intervalStats time.Duration, mergeResultsEachHost bool) {
309+
func runStatLinePrinter(ctx context.Context, printer *Printer, addr string, intervalStats time.Duration, mergeResultsEachHost bool) {
340310
go func() {
341311
ticker := time.NewTicker(intervalStats)
342312
defer ticker.Stop()
@@ -347,78 +317,9 @@ func runStatLinePrinter(ctx context.Context, w io.Writer, addr string, intervalS
347317
return
348318
case <-ticker.C:
349319
ts := getOrRegisterTimer("tick.latency", addr, mergeResultsEachHost)
350-
printStatLine(w, addr, ts)
320+
printer.PrintStatLine(addr, ts)
351321
unregisterTimer("tick.latency", addr, mergeResultsEachHost)
352322
}
353323
}
354324
}()
355325
}
356-
357-
type JSONLinesResult struct {
358-
Peer string `json:"peer"`
359-
Count int64 `json:"count"`
360-
LatencyMax int64 `json:"latency_max_us"`
361-
LatencyMin int64 `json:"latency_min_us"`
362-
LatencyMean int64 `json:"latency_mean_us"`
363-
Latency90p int64 `json:"latency_90p_us"`
364-
Latency95p int64 `json:"latency_95p_us"`
365-
Latency99p int64 `json:"latency_99p_us"`
366-
Rate float64 `json:"rate_per_sec"`
367-
Timestamp string `json:"timestamp"`
368-
}
369-
370-
func printJSONLinesReport(w io.Writer, addrs []string, mergeResultsEachHost bool) {
371-
timestamp := time.Now().UTC().Format(time.RFC3339)
372-
results := []JSONLinesResult{}
373-
374-
if mergeResultsEachHost {
375-
ts := getOrRegisterTimer("total.latency", "", mergeResultsEachHost)
376-
results = append(results, JSONLinesResult{
377-
Peer: fmt.Sprintf("merged(%d hosts)", len(addrs)),
378-
Count: ts.Count(),
379-
LatencyMax: toMicroseconds(ts.Max()),
380-
LatencyMin: toMicroseconds(ts.Min()),
381-
LatencyMean: toMicrosecondsf(ts.Mean()),
382-
Latency90p: toMicrosecondsf(ts.Percentile(0.9)),
383-
Latency95p: toMicrosecondsf(ts.Percentile(0.95)),
384-
Latency99p: toMicrosecondsf(ts.Percentile(0.99)),
385-
Rate: ts.RateMean(),
386-
Timestamp: timestamp,
387-
})
388-
} else {
389-
for _, addr := range addrs {
390-
ts := getOrRegisterTimer("total.latency", addr, mergeResultsEachHost)
391-
results = append(results, JSONLinesResult{
392-
Peer: addr,
393-
Count: ts.Count(),
394-
LatencyMax: toMicroseconds(ts.Max()),
395-
LatencyMin: toMicroseconds(ts.Min()),
396-
LatencyMean: toMicrosecondsf(ts.Mean()),
397-
Latency90p: toMicrosecondsf(ts.Percentile(0.9)),
398-
Latency95p: toMicrosecondsf(ts.Percentile(0.95)),
399-
Latency99p: toMicrosecondsf(ts.Percentile(0.99)),
400-
Rate: ts.RateMean(),
401-
Timestamp: timestamp,
402-
})
403-
}
404-
}
405-
406-
for _, result := range results {
407-
if err := json.NewEncoder(w).Encode(result); err != nil {
408-
slog.Error("Failed to encode JSON result", "error", err)
409-
}
410-
}
411-
}
412-
413-
func printReport(w io.Writer, addrs []string, mergeResultsEachHost bool) {
414-
fmt.Fprintln(w, "--- A result during total execution time ---")
415-
if mergeResultsEachHost {
416-
ts := getOrRegisterTimer("total.latency", "", mergeResultsEachHost)
417-
printStatLine(w, fmt.Sprintf("merged(%d hosts)", len(addrs)), ts)
418-
return
419-
}
420-
for _, addr := range addrs {
421-
ts := getOrRegisterTimer("total.latency", addr, mergeResultsEachHost)
422-
printStatLine(w, addr, ts)
423-
}
424-
}

client_test.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ func testRunClient(out io.Writer, args []string) error {
9797
return fmt.Errorf("setting file limit: %w", err)
9898
}
9999

100+
printer := NewPrinter(os.Stdout)
100101
if !jsonlines {
101-
printStatHeader(os.Stdout)
102+
printer.PrintStatHeader()
102103
}
103104

104105
config := ClientConfig{
@@ -121,7 +122,7 @@ func testRunClient(out io.Writer, args []string) error {
121122
if showOnlyResults || jsonlines {
122123
return client.ConnectToAddresses(ctx, []string{addr})
123124
}
124-
runStatLinePrinter(ctx, os.Stdout, addr, intervalStats, mergeResultsEachHost)
125+
runStatLinePrinter(ctx, printer, addr, intervalStats, mergeResultsEachHost)
125126
return client.ConnectToAddresses(ctx, []string{addr})
126127
})
127128
}
@@ -131,9 +132,9 @@ func testRunClient(out io.Writer, args []string) error {
131132
}
132133

133134
if jsonlines {
134-
printJSONLinesReport(os.Stdout, args, mergeResultsEachHost)
135+
printer.PrintJSONLinesReport(args, mergeResultsEachHost)
135136
} else {
136-
printReport(os.Stdout, args, mergeResultsEachHost)
137+
printer.PrintReport(args, mergeResultsEachHost)
137138
}
138139
return nil
139140
}
@@ -337,7 +338,8 @@ func TestUnregisterTimer(t *testing.T) {
337338

338339
func TestPrintStatHeader(t *testing.T) {
339340
var buf bytes.Buffer
340-
printStatHeader(&buf)
341+
printer := NewPrinter(&buf)
342+
printer.PrintStatHeader()
341343

342344
output := buf.String()
343345
expectedHeaders := []string{"PEER", "CNT", "LAT_MAX(µs)", "LAT_MIN(µs)",
@@ -356,7 +358,8 @@ func TestPrintStatLine(t *testing.T) {
356358
timer.Update(2 * time.Millisecond)
357359

358360
var buf bytes.Buffer
359-
printStatLine(&buf, "test.addr", timer)
361+
printer := NewPrinter(&buf)
362+
printer.PrintStatLine("test.addr", timer)
360363

361364
output := buf.String()
362365
if !strings.Contains(output, "test.addr") {
@@ -405,7 +408,8 @@ func TestPrintReport(t *testing.T) {
405408
tt.setupTimers(tt.addrs)
406409

407410
var buf bytes.Buffer
408-
printReport(&buf, tt.addrs, tt.mergeResultsEachHost)
411+
printer := NewPrinter(&buf)
412+
printer.PrintReport(tt.addrs, tt.mergeResultsEachHost)
409413

410414
output := buf.String()
411415
if !strings.Contains(output, "--- A result during total execution time ---") {
@@ -656,8 +660,9 @@ func TestRunStatLinePrinter(t *testing.T) {
656660
safeWriter := &threadSafeWriter{
657661
writer: &buf,
658662
}
663+
printer := NewPrinter(safeWriter)
659664

660-
runStatLinePrinter(ctx, safeWriter, addr, 50*time.Millisecond, false)
665+
runStatLinePrinter(ctx, printer, addr, 50*time.Millisecond, false)
661666

662667
// Wait for at least one interval
663668
time.Sleep(60 * time.Millisecond)

e2e_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ func testRunClientE2E(out io.Writer, args []string) error {
5454
return fmt.Errorf("setting file limit: %w", err)
5555
}
5656

57+
printer := NewPrinter(os.Stdout)
5758
if !jsonlines {
58-
printStatHeader(os.Stdout)
59+
printer.PrintStatHeader()
5960
}
6061

6162
config := ClientConfig{
@@ -78,7 +79,7 @@ func testRunClientE2E(out io.Writer, args []string) error {
7879
if showOnlyResults || jsonlines {
7980
return client.ConnectToAddresses(ctx, []string{addr})
8081
}
81-
runStatLinePrinter(ctx, os.Stdout, addr, intervalStats, mergeResultsEachHost)
82+
runStatLinePrinter(ctx, printer, addr, intervalStats, mergeResultsEachHost)
8283
return client.ConnectToAddresses(ctx, []string{addr})
8384
})
8485
}
@@ -88,9 +89,9 @@ func testRunClientE2E(out io.Writer, args []string) error {
8889
}
8990

9091
if jsonlines {
91-
printJSONLinesReport(os.Stdout, args, mergeResultsEachHost)
92+
printer.PrintJSONLinesReport(args, mergeResultsEachHost)
9293
} else {
93-
printReport(os.Stdout, args, mergeResultsEachHost)
94+
printer.PrintReport(args, mergeResultsEachHost)
9495
}
9596
return nil
9697
}

jsonlines_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ func TestPrintJSONLinesReport_SingleHost(t *testing.T) {
2525
timer.Update(300 * time.Microsecond)
2626

2727
var buf bytes.Buffer
28-
printJSONLinesReport(&buf, []string{addr}, false)
28+
printer := NewPrinter(&buf)
29+
printer.PrintJSONLinesReport([]string{addr}, false)
2930

3031
output := strings.TrimSpace(buf.String())
3132
if output == "" {
@@ -81,7 +82,8 @@ func TestPrintJSONLinesReport_MultipleHosts(t *testing.T) {
8182
}
8283

8384
var buf bytes.Buffer
84-
printJSONLinesReport(&buf, addrs, false)
85+
printer := NewPrinter(&buf)
86+
printer.PrintJSONLinesReport(addrs, false)
8587

8688
lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
8789
if len(lines) != 2 {
@@ -125,7 +127,8 @@ func TestPrintJSONLinesReport_MergedHosts(t *testing.T) {
125127
timer.Update(400 * time.Microsecond)
126128

127129
var buf bytes.Buffer
128-
printJSONLinesReport(&buf, addrs, true)
130+
printer := NewPrinter(&buf)
131+
printer.PrintJSONLinesReport(addrs, true)
129132

130133
output := strings.TrimSpace(buf.String())
131134
lines := strings.Split(output, "\n")
@@ -184,7 +187,8 @@ func TestJSONLinesResultFields(t *testing.T) {
184187
}
185188

186189
var buf bytes.Buffer
187-
printJSONLinesReport(&buf, []string{addr}, false)
190+
printer := NewPrinter(&buf)
191+
printer.PrintJSONLinesReport([]string{addr}, false)
188192

189193
var result JSONLinesResult
190194
if err := json.Unmarshal(buf.Bytes(), &result); err != nil {

main.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,9 @@ func runClient() error {
248248
}
249249
}
250250

251+
printer := NewPrinter(os.Stdout)
251252
if !jsonlines {
252-
printStatHeader(os.Stdout)
253+
printer.PrintStatHeader()
253254
}
254255

255256
config := ClientConfig{
@@ -272,7 +273,7 @@ func runClient() error {
272273
if showOnlyResults || jsonlines {
273274
return client.ConnectToAddresses(ctx, []string{addr})
274275
}
275-
runStatLinePrinter(ctx, os.Stdout, addr, intervalStats, mergeResultsEachHost)
276+
runStatLinePrinter(ctx, printer, addr, intervalStats, mergeResultsEachHost)
276277
return client.ConnectToAddresses(ctx, []string{addr})
277278
})
278279
}
@@ -282,9 +283,9 @@ func runClient() error {
282283
}
283284

284285
if jsonlines {
285-
printJSONLinesReport(os.Stdout, addrs, mergeResultsEachHost)
286+
printer.PrintJSONLinesReport(addrs, mergeResultsEachHost)
286287
} else {
287-
printReport(os.Stdout, addrs, mergeResultsEachHost)
288+
printer.PrintReport(addrs, mergeResultsEachHost)
288289
}
289290
return nil
290291
}

0 commit comments

Comments
 (0)