mirror of
https://github.com/harshabose/simple_skyline_sonata.git
synced 2025-09-27 01:25:52 +08:00
Re-add tools submodule properly
This commit is contained in:
1
dependencies/tools
vendored
Submodule
1
dependencies/tools
vendored
Submodule
Submodule dependencies/tools added at d5ed322260
50
dependencies/tools/.gitignore
vendored
50
dependencies/tools/.gitignore
vendored
@@ -1,50 +0,0 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool
|
||||
*.out
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# Dependency directories
|
||||
vendor/
|
||||
|
||||
# Build directories
|
||||
build/
|
||||
third_party/
|
||||
|
||||
# Environment files
|
||||
*.env
|
||||
!.env.example
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
# Windows
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Linux
|
||||
*~
|
||||
|
||||
# IDE files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
7
dependencies/tools/go.mod
vendored
7
dependencies/tools/go.mod
vendored
@@ -1,7 +0,0 @@
|
||||
module github.com/harshabose/tools
|
||||
|
||||
go 1.24.1
|
||||
|
||||
require github.com/asticode/go-astiav v0.37.0
|
||||
|
||||
require github.com/asticode/go-astikit v0.42.0 // indirect
|
12
dependencies/tools/go.sum
vendored
12
dependencies/tools/go.sum
vendored
@@ -1,12 +0,0 @@
|
||||
github.com/asticode/go-astiav v0.37.0 h1:Ph4usW4lulotVvne8hqZ1JCOHX1f8ces6yVKdg+PnyQ=
|
||||
github.com/asticode/go-astiav v0.37.0/go.mod h1:GI0pHw6K2/pl/o8upCtT49P/q4KCwhv/8nGLlCsZLdA=
|
||||
github.com/asticode/go-astikit v0.42.0 h1:pnir/2KLUSr0527Tv908iAH6EGYYrYta132vvjXsH5w=
|
||||
github.com/asticode/go-astikit v0.42.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
8
dependencies/tools/pkg/buffer/errors.go
vendored
8
dependencies/tools/pkg/buffer/errors.go
vendored
@@ -1,8 +0,0 @@
|
||||
package buffer
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrorElementUnallocated = errors.New("encountered nil in the buffer. this should not happen. check usage")
|
||||
ErrorChannelBufferClose = errors.New("channel buffer has be closed. cannot perform this operation")
|
||||
)
|
55
dependencies/tools/pkg/buffer/frame_pool.go
vendored
55
dependencies/tools/pkg/buffer/frame_pool.go
vendored
@@ -1,55 +0,0 @@
|
||||
//go:build cgo_enabled
|
||||
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/asticode/go-astiav"
|
||||
)
|
||||
|
||||
type framePool struct {
|
||||
pool sync.Pool
|
||||
}
|
||||
|
||||
func CreateFramePool() Pool[*astiav.Frame] {
|
||||
return &framePool{
|
||||
pool: sync.Pool{
|
||||
New: func() any {
|
||||
return astiav.AllocFrame()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (pool *framePool) Get() *astiav.Frame {
|
||||
frame, ok := pool.pool.Get().(*astiav.Frame)
|
||||
|
||||
if frame == nil || !ok {
|
||||
return astiav.AllocFrame()
|
||||
}
|
||||
return frame
|
||||
}
|
||||
|
||||
func (pool *framePool) Put(frame *astiav.Frame) {
|
||||
if frame == nil {
|
||||
return
|
||||
}
|
||||
|
||||
frame.Unref()
|
||||
pool.pool.Put(frame)
|
||||
}
|
||||
|
||||
func (pool *framePool) Release() {
|
||||
for {
|
||||
frame, ok := pool.pool.Get().(*astiav.Frame)
|
||||
if frame == nil {
|
||||
break
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
frame.Free()
|
||||
}
|
||||
}
|
144
dependencies/tools/pkg/buffer/limit_buffer.go
vendored
144
dependencies/tools/pkg/buffer/limit_buffer.go
vendored
@@ -1,144 +0,0 @@
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ChannelBuffer[T any] struct {
|
||||
pool Pool[T]
|
||||
bufferChannel chan T
|
||||
inputBuffer chan T
|
||||
closed bool
|
||||
mux sync.RWMutex
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func CreateChannelBuffer[T any](ctx context.Context, size int, pool Pool[T]) *ChannelBuffer[T] {
|
||||
buffer := &ChannelBuffer[T]{
|
||||
pool: pool,
|
||||
bufferChannel: make(chan T, size),
|
||||
inputBuffer: make(chan T, size),
|
||||
closed: false,
|
||||
ctx: ctx,
|
||||
}
|
||||
go buffer.loop()
|
||||
return buffer
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) Push(ctx context.Context, element T) error {
|
||||
buffer.mux.RLock()
|
||||
defer buffer.mux.RUnlock()
|
||||
|
||||
if buffer.closed {
|
||||
return errors.New("buffer closed")
|
||||
}
|
||||
select {
|
||||
case buffer.inputBuffer <- element:
|
||||
// WARN: LACKS CHECKS FOR CLOSED CHANNEL
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) Pop(ctx context.Context) (T, error) {
|
||||
buffer.mux.RLock()
|
||||
defer buffer.mux.RUnlock()
|
||||
|
||||
var zero T
|
||||
|
||||
if buffer.closed {
|
||||
return zero, errors.New("buffer closed")
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return zero, ctx.Err()
|
||||
case data, ok := <-buffer.bufferChannel:
|
||||
if !ok {
|
||||
return zero, ErrorChannelBufferClose
|
||||
}
|
||||
// TODO: NIL CHECK IS REQUIRED BUT GENERIC CANNOT DO THIS. SOLVE THIS ASAP
|
||||
// if data == nil {
|
||||
// return zero, ErrorElementUnallocated
|
||||
// }
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) Generate() T {
|
||||
return buffer.pool.Get()
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) PutBack(element T) {
|
||||
if buffer.pool != nil {
|
||||
buffer.pool.Put(element)
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) GetChannel() chan T {
|
||||
return buffer.bufferChannel
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) Size() int {
|
||||
return len(buffer.bufferChannel)
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) loop() {
|
||||
defer buffer.close()
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-buffer.ctx.Done():
|
||||
return
|
||||
case element, ok := <-buffer.inputBuffer:
|
||||
// if !ok || element == nil {
|
||||
// continue loop
|
||||
// }
|
||||
if !ok {
|
||||
continue loop
|
||||
}
|
||||
select {
|
||||
case buffer.bufferChannel <- element: // SUCCESSFULLY BUFFERED
|
||||
continue loop
|
||||
default:
|
||||
select {
|
||||
case oldElement := <-buffer.bufferChannel:
|
||||
buffer.PutBack(oldElement)
|
||||
select {
|
||||
case buffer.bufferChannel <- element:
|
||||
continue loop
|
||||
default:
|
||||
fmt.Println("unexpected buffer state. skipping the element..")
|
||||
buffer.PutBack(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (buffer *ChannelBuffer[T]) close() {
|
||||
buffer.mux.Lock()
|
||||
buffer.closed = true
|
||||
buffer.mux.Unlock()
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case element := <-buffer.bufferChannel:
|
||||
if buffer.pool != nil {
|
||||
buffer.pool.Put(element)
|
||||
}
|
||||
default:
|
||||
close(buffer.bufferChannel)
|
||||
close(buffer.inputBuffer)
|
||||
break loop
|
||||
}
|
||||
}
|
||||
if buffer.pool != nil {
|
||||
buffer.pool.Release()
|
||||
}
|
||||
}
|
24
dependencies/tools/pkg/buffer/package.go
vendored
24
dependencies/tools/pkg/buffer/package.go
vendored
@@ -1,24 +0,0 @@
|
||||
// TODO: CLEAN THIS; THIS IS STUPID
|
||||
|
||||
package buffer
|
||||
|
||||
import "context"
|
||||
|
||||
type Pool[T any] interface {
|
||||
Get() T
|
||||
Put(T)
|
||||
Release()
|
||||
}
|
||||
|
||||
type Buffer[T any] interface {
|
||||
Push(context.Context, T) error
|
||||
Pop(ctx context.Context) (T, error)
|
||||
Size() int
|
||||
}
|
||||
|
||||
type BufferWithGenerator[T any] interface {
|
||||
Buffer[T]
|
||||
Generate() T
|
||||
PutBack(T)
|
||||
GetChannel() chan T
|
||||
}
|
55
dependencies/tools/pkg/buffer/packet_pool.go
vendored
55
dependencies/tools/pkg/buffer/packet_pool.go
vendored
@@ -1,55 +0,0 @@
|
||||
//go:build cgo_enabled
|
||||
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/asticode/go-astiav"
|
||||
)
|
||||
|
||||
type packetPool struct {
|
||||
pool sync.Pool
|
||||
}
|
||||
|
||||
func CreatePacketPool() Pool[*astiav.Packet] {
|
||||
return &packetPool{
|
||||
pool: sync.Pool{
|
||||
New: func() any {
|
||||
return astiav.AllocPacket()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (pool *packetPool) Get() *astiav.Packet {
|
||||
packet, ok := pool.pool.Get().(*astiav.Packet)
|
||||
|
||||
if packet == nil || !ok {
|
||||
return astiav.AllocPacket()
|
||||
}
|
||||
return packet
|
||||
}
|
||||
|
||||
func (pool *packetPool) Put(packet *astiav.Packet) {
|
||||
if packet == nil {
|
||||
return
|
||||
}
|
||||
|
||||
packet.Unref()
|
||||
pool.pool.Put(packet)
|
||||
}
|
||||
|
||||
func (pool *packetPool) Release() {
|
||||
for {
|
||||
packet, ok := pool.pool.Get().(*astiav.Packet)
|
||||
if packet == nil {
|
||||
break
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// fmt.Printf("🗑️ Releasing packet: ptr=%p\n", packet)
|
||||
packet.Free()
|
||||
}
|
||||
}
|
338
dependencies/tools/pkg/metrics/metrics.go
vendored
338
dependencies/tools/pkg/metrics/metrics.go
vendored
@@ -1,338 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ClientState int
|
||||
|
||||
const (
|
||||
ClientStateDisconnected ClientState = iota
|
||||
ClientStateConnecting
|
||||
ClientStateConnected
|
||||
ClientStateError
|
||||
)
|
||||
|
||||
func (cs ClientState) String() string {
|
||||
switch cs {
|
||||
case ClientStateDisconnected:
|
||||
return "Disconnected"
|
||||
case ClientStateConnecting:
|
||||
return "Connecting"
|
||||
case ClientStateConnected:
|
||||
return "Connected"
|
||||
case ClientStateError:
|
||||
return "Error"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
type BufferedErrors struct {
|
||||
maxSize int
|
||||
errors []ErrorEntry
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
type ErrorEntry struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func NewBufferedErrors(maxSize int) *BufferedErrors {
|
||||
return &BufferedErrors{
|
||||
maxSize: maxSize,
|
||||
errors: make([]ErrorEntry, 0, maxSize),
|
||||
}
|
||||
}
|
||||
|
||||
func (be *BufferedErrors) Add(err error) {
|
||||
be.mux.Lock()
|
||||
defer be.mux.Unlock()
|
||||
|
||||
if len(be.errors) >= be.maxSize {
|
||||
be.errors = be.errors[1:]
|
||||
}
|
||||
|
||||
be.errors = append(be.errors, ErrorEntry{
|
||||
Timestamp: time.Now(),
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
func (be *BufferedErrors) MarshalJSON() ([]byte, error) {
|
||||
be.mux.RLock()
|
||||
defer be.mux.RUnlock()
|
||||
|
||||
return json.Marshal(be.errors)
|
||||
}
|
||||
|
||||
type MetricsSnapshot struct {
|
||||
State string `json:"state"`
|
||||
PacketsRead uint64 `json:"packetsRead"`
|
||||
PacketsWritten uint64 `json:"packetsWritten"`
|
||||
BytesRead uint64 `json:"bytesRead"`
|
||||
BytesWritten uint64 `json:"bytesWritten"`
|
||||
BytesReadRate float32 `json:"bytesReadRate"`
|
||||
BytesWrittenRate float32 `json:"bytesWrittenRate"`
|
||||
LastWriteTime *time.Time `json:"lastWriteTime,omitempty"`
|
||||
LastReadTime *time.Time `json:"lastReadTime,omitempty"`
|
||||
RecentErrors *BufferedErrors `json:"recentErrors"`
|
||||
}
|
||||
|
||||
type UnifiedMetrics struct {
|
||||
// Basic state
|
||||
state ClientState
|
||||
packetsRead uint64
|
||||
packetsWritten uint64
|
||||
bytesRead uint64
|
||||
bytesWritten uint64
|
||||
lastWriteTime time.Time
|
||||
lastReadTime time.Time
|
||||
recentErrors *BufferedErrors
|
||||
|
||||
// Rate calculation
|
||||
lastBytesRead uint64
|
||||
lastBytesWritten uint64
|
||||
bytesReadRate float32
|
||||
bytesWrittenRate float32
|
||||
tickerInterval time.Duration
|
||||
|
||||
// Control
|
||||
serviceTitle string
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
wg sync.WaitGroup
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
func NewUnifiedMetrics(ctx context.Context, serviceTitle string, maxErrorBuffer int, tickerInterval time.Duration) *UnifiedMetrics {
|
||||
ctx2, cancel := context.WithCancel(ctx)
|
||||
m := &UnifiedMetrics{
|
||||
state: ClientStateDisconnected,
|
||||
recentErrors: NewBufferedErrors(maxErrorBuffer),
|
||||
serviceTitle: serviceTitle,
|
||||
tickerInterval: tickerInterval,
|
||||
ctx: ctx2,
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
m.wg.Add(1)
|
||||
go m.loop()
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) loop() {
|
||||
defer m.wg.Done()
|
||||
|
||||
ticker := time.NewTicker(m.tickerInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-m.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
m.updateRatesAndPrint()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) updateRatesAndPrint() {
|
||||
m.mux.Lock()
|
||||
|
||||
currentBytesRead := m.bytesRead
|
||||
currentBytesWritten := m.bytesWritten
|
||||
|
||||
intervalSeconds := float32(m.tickerInterval.Seconds())
|
||||
m.bytesReadRate = float32(currentBytesRead-m.lastBytesRead) / intervalSeconds
|
||||
m.bytesWrittenRate = float32(currentBytesWritten-m.lastBytesWritten) / intervalSeconds
|
||||
|
||||
m.lastBytesRead = currentBytesRead
|
||||
m.lastBytesWritten = currentBytesWritten
|
||||
|
||||
m.mux.Unlock()
|
||||
|
||||
snapshot := m.GetSnapshot()
|
||||
|
||||
m.printFormattedMetrics(snapshot)
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) printFormattedMetrics(snapshot MetricsSnapshot) {
|
||||
divider := "================================================"
|
||||
|
||||
fmt.Printf("\n%s\n", divider)
|
||||
fmt.Printf("%*s\n", (len(divider)+len(m.serviceTitle))/2, m.serviceTitle)
|
||||
fmt.Printf("%s\n\n", divider)
|
||||
|
||||
fmt.Printf("%-20s: %s\n", "Connection State", snapshot.State)
|
||||
fmt.Println()
|
||||
|
||||
fmt.Printf("%-20s: %d\n", "Packets Read", snapshot.PacketsRead)
|
||||
fmt.Printf("%-20s: %d\n", "Packets Written", snapshot.PacketsWritten)
|
||||
fmt.Println()
|
||||
|
||||
fmt.Printf("%-20s: %s\n", "Bytes Read", formatBytes(snapshot.BytesRead))
|
||||
fmt.Printf("%-20s: %s\n", "Bytes Written", formatBytes(snapshot.BytesWritten))
|
||||
fmt.Println()
|
||||
|
||||
fmt.Printf("%-20s: %s/s\n", "Read Rate", formatBytes(uint64(snapshot.BytesReadRate)))
|
||||
fmt.Printf("%-20s: %s/s\n", "Write Rate", formatBytes(uint64(snapshot.BytesWrittenRate)))
|
||||
fmt.Println()
|
||||
|
||||
if snapshot.LastReadTime != nil {
|
||||
fmt.Printf("%-20s: %s\n", "Last Read", snapshot.LastReadTime.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
if snapshot.LastWriteTime != nil {
|
||||
fmt.Printf("%-20s: %s\n", "Last Write", snapshot.LastWriteTime.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
if snapshot.LastReadTime != nil || snapshot.LastWriteTime != nil {
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
snapshot.RecentErrors.mux.RLock()
|
||||
errorCount := len(snapshot.RecentErrors.errors)
|
||||
if errorCount > 0 {
|
||||
fmt.Printf("Recent Errors (%d error", errorCount)
|
||||
if errorCount != 1 {
|
||||
fmt.Print("s")
|
||||
}
|
||||
fmt.Println("):")
|
||||
|
||||
for _, errorEntry := range snapshot.RecentErrors.errors {
|
||||
fmt.Printf(" [%s] %s\n",
|
||||
errorEntry.Timestamp.Format("15:04:05"),
|
||||
errorEntry.Message)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
snapshot.RecentErrors.mux.RUnlock()
|
||||
|
||||
fmt.Printf("%s\n", divider)
|
||||
}
|
||||
|
||||
func formatBytes(bytes uint64) string {
|
||||
if bytes < 1024 {
|
||||
return fmt.Sprintf("%d B", bytes)
|
||||
} else if bytes < 1024*1024 {
|
||||
return fmt.Sprintf("%.2f KB", float64(bytes)/1024)
|
||||
} else if bytes < 1024*1024*1024 {
|
||||
return fmt.Sprintf("%.2f MB", float64(bytes)/(1024*1024))
|
||||
} else {
|
||||
return fmt.Sprintf("%.2f GB", float64(bytes)/(1024*1024*1024))
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) Close() error {
|
||||
if m.cancel != nil {
|
||||
m.cancel()
|
||||
m.wg.Wait()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) SetState(state ClientState) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.state = state
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) GetState() ClientState {
|
||||
m.mux.RLock()
|
||||
defer m.mux.RUnlock()
|
||||
return m.state
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) IncrementPacketsWritten() {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.packetsWritten++
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) IncrementPacketsRead() {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.packetsRead++
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) IncrementBytesWritten(bytes uint64) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.bytesWritten += bytes
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) IncrementBytesRead(bytes uint64) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.bytesRead += bytes
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) SetLastWriteTime(t time.Time) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.lastWriteTime = t
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) SetLastReadTime(t time.Time) {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
m.lastReadTime = t
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) GetLastWriteTime() time.Time {
|
||||
m.mux.RLock()
|
||||
defer m.mux.RUnlock()
|
||||
return m.lastWriteTime
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) GetLastReadTime() time.Time {
|
||||
m.mux.RLock()
|
||||
defer m.mux.RUnlock()
|
||||
return m.lastReadTime
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) AddErrors(errs ...error) {
|
||||
if len(errs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
|
||||
for _, err := range errs {
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
m.recentErrors.Add(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *UnifiedMetrics) GetSnapshot() MetricsSnapshot {
|
||||
m.mux.RLock()
|
||||
defer m.mux.RUnlock()
|
||||
|
||||
snapshot := MetricsSnapshot{
|
||||
State: m.state.String(),
|
||||
PacketsRead: m.packetsRead,
|
||||
PacketsWritten: m.packetsWritten,
|
||||
BytesRead: m.bytesRead,
|
||||
BytesWritten: m.bytesWritten,
|
||||
BytesReadRate: m.bytesReadRate,
|
||||
BytesWrittenRate: m.bytesWrittenRate,
|
||||
RecentErrors: m.recentErrors,
|
||||
}
|
||||
|
||||
if !m.lastReadTime.IsZero() {
|
||||
snapshot.LastReadTime = &m.lastReadTime
|
||||
}
|
||||
if !m.lastWriteTime.IsZero() {
|
||||
snapshot.LastWriteTime = &m.lastWriteTime
|
||||
}
|
||||
|
||||
return snapshot
|
||||
}
|
116
dependencies/tools/pkg/multierr/multierr.go
vendored
116
dependencies/tools/pkg/multierr/multierr.go
vendored
@@ -1,116 +0,0 @@
|
||||
// Package multierr provides utilities for combining multiple errors into a single error.
|
||||
package multierr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Combine takes a list of errors and combines them into a single error.
|
||||
// If all errors are nil, it returns nil.
|
||||
// If there's only one non-nil error, it returns that error.
|
||||
// If there are multiple non-nil errors, it combines them into a single error.
|
||||
func Combine(errs ...error) error {
|
||||
var nonNilErrs []error
|
||||
for _, err := range errs {
|
||||
if err != nil {
|
||||
nonNilErrs = append(nonNilErrs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(nonNilErrs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(nonNilErrs) == 1 {
|
||||
return nonNilErrs[0]
|
||||
}
|
||||
|
||||
return &multiError{
|
||||
errors: nonNilErrs,
|
||||
}
|
||||
}
|
||||
|
||||
// Append combines the two errors into a single error.
|
||||
// If both errors are nil, it returns nil.
|
||||
// If one error is nil, it returns the non-nil error.
|
||||
// If both errors are non-nil, it combines them into a single error.
|
||||
func Append(err1, err2 error) error {
|
||||
if err1 == nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
if err2 == nil {
|
||||
return err1
|
||||
}
|
||||
|
||||
// If err1 is already a multiError, append err2 to it
|
||||
if me, ok := err1.(*multiError); ok {
|
||||
return &multiError{
|
||||
errors: append(me.errors, err2),
|
||||
}
|
||||
}
|
||||
|
||||
// If err2 is already a multiError, prepend err1 to it
|
||||
if me, ok := err2.(*multiError); ok {
|
||||
return &multiError{
|
||||
errors: append([]error{err1}, me.errors...),
|
||||
}
|
||||
}
|
||||
|
||||
// Neither error is a multiError, create a new one
|
||||
return &multiError{
|
||||
errors: []error{err1, err2},
|
||||
}
|
||||
}
|
||||
|
||||
// multiError is an implementation of error that contains multiple errors.
|
||||
type multiError struct {
|
||||
errors []error
|
||||
}
|
||||
|
||||
// Error returns a string representation of all the errors.
|
||||
func (m *multiError) Error() string {
|
||||
if len(m.errors) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(m.errors) == 1 {
|
||||
return m.errors[0].Error()
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("%d errors occurred:\n", len(m.errors)))
|
||||
for i, err := range m.errors {
|
||||
sb.WriteString(fmt.Sprintf(" %d: %s\n", i+1, err.Error()))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying errors.
|
||||
// This allows errors.Is and errors.As to work with multiError.
|
||||
func (m *multiError) Unwrap() []error {
|
||||
return m.errors
|
||||
}
|
||||
|
||||
// Is reports whether any error in multiError matches target.
|
||||
func (m *multiError) Is(target error) bool {
|
||||
for _, err := range m.errors {
|
||||
if errors.Is(err, target) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// As finds the first error in multiError that matches target, and if one is found, sets
|
||||
// target to that error value and returns true. Otherwise, it returns false.
|
||||
func (m *multiError) As(target interface{}) bool {
|
||||
for _, err := range m.errors {
|
||||
if errors.As(err, target) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
Reference in New Issue
Block a user