-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprintlog.go
144 lines (119 loc) · 3.44 KB
/
printlog.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"bufio"
"encoding/json"
"flag"
"fmt"
"io"
"log"
"os"
"strings"
"time"
)
type LogEntry struct {
Timestamp string `json:"timestamp"`
Direction string `json:"direction"`
Type string `json:"type"`
RawJSON interface{} `json:"raw_json"`
}
type OutputWriter struct {
writer io.Writer
}
func NewOutputWriter(outputFile string) (*OutputWriter, error) {
var w io.Writer = os.Stdout
if outputFile != "" {
file, err := os.Create(outputFile)
if err != nil {
return nil, fmt.Errorf("error creating output file: %w", err)
}
w = file
}
return &OutputWriter{writer: w}, nil
}
func (w *OutputWriter) Write(format string, a ...interface{}) {
fmt.Fprintf(w.writer, format, a...)
}
func (w *OutputWriter) WriteString(s string) {
fmt.Fprint(w.writer, s)
}
func formatJSON(data interface{}) string {
b, err := json.MarshalIndent(data, "", " ")
if err != nil {
return fmt.Sprintf("%v", data)
}
return string(b)
}
func formatTimestamp(timestamp string) string {
t, err := time.Parse(time.RFC3339Nano, timestamp)
if err != nil {
return timestamp
}
return t.Format("2006-01-02 15:04:05.000")
}
func printLogEntry(writer *OutputWriter, entry LogEntry) {
// Create direction indicator
directionArrow := "→"
if entry.Direction == "received" {
directionArrow = "←"
}
// Format timestamp
timestamp := formatTimestamp(entry.Timestamp)
// Print header
writer.Write("\n%s %s [%s] %s\n",
timestamp,
directionArrow,
strings.ToUpper(entry.Direction),
strings.ToUpper(entry.Type))
// Print separator
writer.WriteString(strings.Repeat("-", 80) + "\n")
// Print formatted JSON data
writer.WriteString(formatJSON(entry.RawJSON) + "\n")
}
func processLogFile(inputFile string, writer *OutputWriter) error {
file, err := os.Open(inputFile)
if err != nil {
return fmt.Errorf("error opening input file: %w", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
// Increase scanner buffer size for large JSON lines
const maxCapacity = 1024 * 1024 // 1MB
buf := make([]byte, maxCapacity)
scanner.Buffer(buf, maxCapacity)
for scanner.Scan() {
var entry LogEntry
if err := json.Unmarshal(scanner.Bytes(), &entry); err != nil {
log.Printf("Error parsing log entry: %v", err)
continue
}
printLogEntry(writer, entry)
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("error reading file: %w", err)
}
return nil
}
func main() {
// Parse command line flags
inputFile := flag.String("f", "", "Input log file to process")
outputFile := flag.String("o", "", "Output file (optional, defaults to terminal)")
flag.Parse()
if *inputFile == "" {
log.Fatal("Please provide an input log file using the -f flag")
}
// Create output writer
writer, err := NewOutputWriter(*outputFile)
if err != nil {
log.Fatal(err)
}
// If we're writing to a file, make sure it's closed properly
if *outputFile != "" {
if closer, ok := writer.writer.(io.Closer); ok {
defer closer.Close()
}
}
// Process the log file
if err := processLogFile(*inputFile, writer); err != nil {
log.Fatal(err)
}
}