Created
September 5, 2019 16:03
-
-
Save krishnakumar4a4/4601cdb7c9cd84664fac6eeb8fe92012 to your computer and use it in GitHub Desktop.
TCP level read and write stats using standard golang HTTP client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"net" | |
"net/http" | |
"time" | |
) | |
// ConnStats stats for tcp flow | |
type ConnStats struct { | |
ReadBytes int64 | |
ReadTime time.Duration | |
WroteBytes int64 | |
WroteTime time.Duration | |
Closed bool | |
} | |
// ConnProfiler profiler for connection | |
type ConnProfiler struct { | |
StatsChan chan ConnStats | |
Conn net.Conn | |
} | |
func (cp ConnProfiler) Read(b []byte) (n int, err error) { | |
fmt.Println("reading") | |
t1 := time.Now() | |
n, err = cp.Conn.Read(b) | |
d := time.Now().Sub(t1) | |
cs := ConnStats{ | |
ReadBytes: int64(n), | |
ReadTime: d, | |
} | |
cp.StatsChan <- cs | |
return | |
} | |
func (cp ConnProfiler) Write(b []byte) (n int, err error) { | |
fmt.Println("writing") | |
t1 := time.Now() | |
n, err = cp.Conn.Write(b) | |
d := time.Now().Sub(t1) | |
cs := ConnStats{ | |
WroteBytes: int64(n), | |
WroteTime: d, | |
} | |
cp.StatsChan <- cs | |
return | |
} | |
// Close closes the connection | |
func (cp ConnProfiler) Close() error { | |
fmt.Println("closing") | |
cs := ConnStats{ | |
Closed: true, | |
} | |
cp.StatsChan <- cs | |
return cp.Conn.Close() | |
} | |
// LocalAddr local address | |
func (cp ConnProfiler) LocalAddr() net.Addr { | |
return cp.Conn.LocalAddr() | |
} | |
// RemoteAddr remote address | |
func (cp ConnProfiler) RemoteAddr() net.Addr { | |
return cp.Conn.RemoteAddr() | |
} | |
// SetDeadline sets dead line | |
func (cp ConnProfiler) SetDeadline(t time.Time) error { | |
return cp.Conn.SetDeadline(t) | |
} | |
// SetReadDeadline sets read dead line | |
func (cp ConnProfiler) SetReadDeadline(t time.Time) error { | |
return cp.Conn.SetReadDeadline(t) | |
} | |
// SetWriteDeadline sets write dead line | |
func (cp ConnProfiler) SetWriteDeadline(t time.Time) error { | |
return cp.Conn.SetWriteDeadline(t) | |
} | |
func main() { | |
go req() | |
// sample server code | |
mux := http.NewServeMux() | |
mux.HandleFunc("/test", func(rw http.ResponseWriter, req *http.Request) { | |
fmt.Println("received request and sleep") | |
time.Sleep(time.Second * 10) | |
fmt.Println("ended sleep") | |
}) | |
s := http.Server{ | |
Addr: ":3301", | |
Handler: mux, | |
} | |
s.ListenAndServe() | |
} | |
func req() { | |
// client code | |
statsChan := make(chan ConnStats, 10) | |
stats := ConnProfiler{ | |
StatsChan: statsChan, | |
} | |
// Client requests | |
go func() { | |
for { | |
c := http.Client{ | |
Transport: &http.Transport{ | |
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { | |
conn, err := net.Dial(network, addr) | |
if err != nil { | |
return nil, err | |
} | |
stats.Conn = conn | |
return stats, nil | |
}, | |
}, | |
} | |
resp, err := c.Get("http://localhost:3301/test") | |
if err != nil { | |
fmt.Println("could not send request, err:", err.Error()) | |
} | |
resp.Body.Close() | |
time.Sleep(time.Second * 2) | |
} | |
}() | |
// Accumulator for connection stats | |
go func() { | |
totStats := ConnStats{} | |
for { | |
statsData := <-statsChan | |
if statsData.Closed { | |
break | |
} | |
totStats.ReadBytes += statsData.ReadBytes | |
totStats.ReadTime += statsData.ReadTime | |
totStats.WroteBytes += statsData.WroteBytes | |
totStats.WroteTime += statsData.WroteTime | |
// fmt.Println("statsData: ", statsData) | |
fmt.Println("totStats: ", totStats) | |
} | |
fmt.Println("totStats: ", totStats) | |
}() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment