mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-18 22:49:52 +02:00
refactor: refactor to adapt new custom json marshaler
This commit is contained in:
@@ -3,7 +3,6 @@ package systeminfo
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -20,6 +19,7 @@ import (
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
"github.com/yusing/go-proxy/internal/metrics/period"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
// json tags are left for tests
|
||||
@@ -55,7 +55,7 @@ type (
|
||||
DownloadSpeed float64 `json:"download_speed"`
|
||||
}
|
||||
Sensors []sensors.TemperatureStat
|
||||
Aggregated []map[string]any
|
||||
Aggregated = json.MapSlice[any]
|
||||
)
|
||||
|
||||
type SystemInfo struct {
|
||||
@@ -295,8 +295,8 @@ func (s *SystemInfo) collectSensorsInfo(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// explicitly implement MarshalJSON to avoid reflection
|
||||
func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
b := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
func (s *SystemInfo) MarshalJSONTo(buf []byte) []byte {
|
||||
b := bytes.NewBuffer(buf)
|
||||
|
||||
b.WriteRune('{')
|
||||
|
||||
@@ -315,7 +315,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
// memory
|
||||
b.WriteString(`,"memory":`)
|
||||
if s.Memory != nil {
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`{"total":%d,"available":%d,"used":%d,"used_percent":%s}`,
|
||||
s.Memory.Total,
|
||||
s.Memory.Available,
|
||||
@@ -329,13 +329,13 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
// disk
|
||||
b.WriteString(`,"disks":`)
|
||||
if len(s.Disks) > 0 {
|
||||
b.WriteString("{")
|
||||
b.WriteRune('{')
|
||||
first := true
|
||||
for device, disk := range s.Disks {
|
||||
if !first {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`"%s":{"device":%q,"path":%q,"fstype":%q,"total":%d,"free":%d,"used":%d,"used_percent":%s}`,
|
||||
device,
|
||||
device,
|
||||
@@ -362,7 +362,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
if !first {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`"%s":{"name":%q,"read_bytes":%d,"write_bytes":%d,"read_speed":%s,"write_speed":%s,"iops":%d}`,
|
||||
name,
|
||||
name,
|
||||
@@ -382,7 +382,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
// network
|
||||
b.WriteString(`,"network":`)
|
||||
if s.Network != nil {
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`{"bytes_sent":%d,"bytes_recv":%d,"upload_speed":%s,"download_speed":%s}`,
|
||||
s.Network.BytesSent,
|
||||
s.Network.BytesRecv,
|
||||
@@ -396,13 +396,13 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
// sensors
|
||||
b.WriteString(`,"sensors":`)
|
||||
if len(s.Sensors) > 0 {
|
||||
b.WriteString("{")
|
||||
b.WriteRune('{')
|
||||
first := true
|
||||
for _, sensor := range s.Sensors {
|
||||
if !first {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`%q:{"name":%q,"temperature":%s,"high":%s,"critical":%s}`,
|
||||
sensor.SensorKey,
|
||||
sensor.SensorKey,
|
||||
@@ -418,7 +418,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
b.WriteRune('}')
|
||||
return []byte(b.String()), nil
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (s *Sensors) UnmarshalJSON(data []byte) error {
|
||||
@@ -560,43 +560,3 @@ func aggregate(entries []*SystemInfo, query url.Values) (total int, result Aggre
|
||||
}
|
||||
return len(aggregated), aggregated
|
||||
}
|
||||
|
||||
func (result Aggregated) MarshalJSON() ([]byte, error) {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
|
||||
buf.WriteByte('[')
|
||||
i := 0
|
||||
n := len(result)
|
||||
for _, entry := range result {
|
||||
buf.WriteRune('{')
|
||||
j := 0
|
||||
m := len(entry)
|
||||
for k, v := range entry {
|
||||
buf.WriteByte('"')
|
||||
buf.WriteString(k)
|
||||
buf.WriteByte('"')
|
||||
buf.WriteByte(':')
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
buf.WriteString(strconv.FormatFloat(v, 'f', 2, 64))
|
||||
case uint64:
|
||||
buf.WriteString(strconv.FormatUint(v, 10))
|
||||
case int64:
|
||||
buf.WriteString(strconv.FormatInt(v, 10))
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected type: %T", v))
|
||||
}
|
||||
if j != m-1 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
j++
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
if i != n-1 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
i++
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
package systeminfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/sensors"
|
||||
. "github.com/yusing/go-proxy/internal/utils/testing"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
func TestPoller(t *testing.T) {
|
||||
for _, query := range allQueries {
|
||||
t.Run(query, func(t *testing.T) {
|
||||
Poller.Test(t, url.Values{"aggregate": []string{query}})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExcludeDisks(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -191,8 +199,7 @@ func TestSerialize(t *testing.T) {
|
||||
for _, query := range allQueries {
|
||||
t.Run(query, func(t *testing.T) {
|
||||
_, result := aggregate(entries, url.Values{"aggregate": []string{query}})
|
||||
s, err := result.MarshalJSON()
|
||||
ExpectNoError(t, err)
|
||||
s := result.MarshalJSONTo(nil)
|
||||
var v []map[string]any
|
||||
ExpectNoError(t, json.Unmarshal(s, &v))
|
||||
ExpectEqual(t, len(v), len(result))
|
||||
@@ -206,31 +213,3 @@ func TestSerialize(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkJSONMarshal(b *testing.B) {
|
||||
entries := make([]*SystemInfo, b.N)
|
||||
for i := range b.N {
|
||||
entries[i] = testInfo
|
||||
}
|
||||
queries := map[string]Aggregated{}
|
||||
for _, query := range allQueries {
|
||||
_, result := aggregate(entries, url.Values{"aggregate": []string{query}})
|
||||
queries[query] = result
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
b.Run("optimized", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
for _, query := range allQueries {
|
||||
_, _ = queries[query].MarshalJSON()
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("json", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
for _, query := range allQueries {
|
||||
_, _ = json.Marshal([]map[string]any(queries[query]))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user