-
Notifications
You must be signed in to change notification settings - Fork 0
/
log_conn.go
128 lines (111 loc) · 5.9 KB
/
log_conn.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
package redis_nats_proxy
import (
"fmt"
"log/slog"
"net"
"slices"
"time"
)
// DebugLogger is an interface that defines a method for logging debug messages.
// The Debug method takes a message string and optional variadic arguments and logs the debug message.
// Example usage:
// debug := defaultDebugLogger
// debug.Debug("This is a debug message")
// debug.Debug("This is a debug message with arguments, "arg1", 42, "arg2", "foo")
type DebugLogger interface {
Debug(msg string, args ...any)
}
// DebugLoggerFunc represents a function type that can be used as a debug logger.
// The DebugLoggerFunc type takes a message string and optional variadic arguments and logs the debug message.
type DebugLoggerFunc func(msg string, args ...any)
// Debug prints the debug message using the specified DebugLoggerFunc.
// The message and any additional arguments are passed to the DebugLoggerFunc as arguments.
func (d DebugLoggerFunc) Debug(msg string, args ...any) {
d(msg, args...)
}
// `_` is a variable of type `net.Conn` that is assigned the address of a `DebugLogNetConn` object.
// `DebugLogNetConn` is a type that implements the `net.Conn` interface, providing methods for reading, writing, closing, and managing deadlines on network connections.
// The `Read` method reads data from the underlying connection, while logging debug information before and after the read operation.
// The `Write` method writes data to the underlying connection, while logging debug information before and after the write operation.
// The `Close` method closes the connection and logs debug information.
// The `LocalAddr` method returns the local network address of the connection.
// The `RemoteAddr` method returns the remote network address of the connection.
// The `SetDeadline` method sets the deadline for future network operations and logs debug information.
// The `SetReadDeadline` method sets the deadline for future read operations and logs debug information.
// The `SetWriteDeadline` method sets the deadline for future write operations and logs debug information.
var _ net.Conn = &DebugLogNetConn{}
// DebugLogNetConn is a type that wraps a net.Conn and logs debugging information for read, write, and close operations.
// Read reads data from the connection and logs the bytes read and the length of the buffer.
type DebugLogNetConn struct {
conn net.Conn
log DebugLogger
}
// NewDebugLogNetConn returns a new DebugLogNetConn instance.
// It wraps the provided net.Conn and adds debug logging to Read,
// Write, Close, LocalAddr, RemoteAddr, SetDeadline,
// SetReadDeadline, and SetWriteDeadline methods.
func NewDebugLogNetConn(conn net.Conn) *DebugLogNetConn {
return &DebugLogNetConn{conn: conn, log: slog.Default()}
}
// NewDebugCustomLogNetConn returns a new DebugLogNetConn instance with the provided debug logger.
func NewDebugCustomLogNetConn(conn net.Conn, log DebugLogger) *DebugLogNetConn {
return &DebugLogNetConn{conn: conn, log: log}
}
// Read reads data from the underlying net.Conn into the provided byte slice.
func (lc *DebugLogNetConn) Read(b []byte) (n int, err error) {
read, err := lc.conn.Read(b)
if err != nil {
return 0, fmt.Errorf("read: %w", err)
}
bb := slices.Compact(slices.Clone(b))
defer lc.log.Debug("read", slog.String("bytes", string(bb)), slog.Int("len", len(b)))
return read, nil
}
// Write writes the provided byte slice to the underlying net.Conn.
// Before writing, the byte slice is compacted and cloned.
// After writing, debug logging is performed, including the number of bytes written and the length of the original byte slice.
func (lc *DebugLogNetConn) Write(b []byte) (n int, err error) {
bb := slices.Compact(slices.Clone(b))
defer lc.log.Debug("write", slog.String("bytes", string(bb)), slog.Int("len", len(b)))
return lc.conn.Write(b)
}
// Close closes the underlying net.Conn and logs a debug message.
func (lc *DebugLogNetConn) Close() error {
defer lc.log.Debug("close connection", slog.String("remote", lc.conn.RemoteAddr().String()))
return lc.conn.Close()
}
// LocalAddr returns the local network address.
func (lc *DebugLogNetConn) LocalAddr() net.Addr {
return lc.conn.LocalAddr()
}
// RemoteAddr returns the remote network address of the underlying net.Conn connection.
func (lc *DebugLogNetConn) RemoteAddr() net.Addr {
return lc.conn.RemoteAddr()
}
// SetDeadline sets the deadline for all I/O operations on the underlying net.Conn.
// The deadline is an absolute time after which I/O operations will fail with a timeout error.
// If `t` is in the past, I/O operations will fail immediately with a timeout error.
//
// The logs the deadline information including the deadline time and the time remaining until the deadline.
//
// This method returns an error if the net.Conn implementation returns an error when setting the deadline.
func (lc *DebugLogNetConn) SetDeadline(t time.Time) error {
defer lc.log.Debug("deadline", slog.Time("time", t), slog.Duration("diff", time.Until(t)))
return lc.conn.SetDeadline(t)
}
// SetReadDeadline sets the read deadline for the underlying net.Conn.
// After the specified time, if no data is read, the Read operation will return with an error.
// The time difference between the specified time and the current time is logged.
// It returns an error if there was an error while setting the read deadline.
func (lc *DebugLogNetConn) SetReadDeadline(t time.Time) error {
defer lc.log.Debug("read deadline", slog.Time("time", t), slog.Duration("diff", time.Until(t)))
return lc.conn.SetReadDeadline(t)
}
// SetWriteDeadline sets the write deadline for the current DebugLogNetConn.
// The provided time `t` specifies the deadline.
// After the deadline, any write operation will fail with a timeout error.
// The difference between the current time and the deadline time is logged using slog.Debug.
func (lc *DebugLogNetConn) SetWriteDeadline(t time.Time) error {
defer lc.log.Debug("write deadline", slog.Time("time", t), slog.Duration("diff", time.Until(t)))
return lc.conn.SetWriteDeadline(t)
}