refactor(api): unify monitoring documents for AX
This commit is contained in:
parent
619b3c500d
commit
c0efdfb0ca
4 changed files with 209 additions and 241 deletions
192
api/router.go
192
api/router.go
|
|
@ -12,7 +12,6 @@ package api
|
|||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"dappco.re/go/proxy"
|
||||
)
|
||||
|
|
@ -22,195 +21,30 @@ type Router interface {
|
|||
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
|
||||
}
|
||||
|
||||
// SummaryResponse is the /1/summary JSON body.
|
||||
//
|
||||
// {"version":"1.0.0","mode":"nicehash","hashrate":{"total":[...]}, ...}
|
||||
type SummaryResponse struct {
|
||||
Version string `json:"version"`
|
||||
Mode string `json:"mode"`
|
||||
Hashrate HashrateResponse `json:"hashrate"`
|
||||
Miners MinersCountResponse `json:"miners"`
|
||||
Workers uint64 `json:"workers"`
|
||||
Upstreams UpstreamResponse `json:"upstreams"`
|
||||
Results ResultsResponse `json:"results"`
|
||||
CustomDiffStats map[uint64]proxy.CustomDiffBucketStats `json:"custom_diff_stats,omitempty"`
|
||||
}
|
||||
|
||||
// HashrateResponse carries the per-window hashrate array.
|
||||
//
|
||||
// HashrateResponse{Total: [6]float64{12345.67, 11900.00, 12100.00, 11800.00, 12000.00, 12200.00}}
|
||||
type HashrateResponse struct {
|
||||
Total [6]float64 `json:"total"`
|
||||
}
|
||||
|
||||
// MinersCountResponse carries current and peak miner counts.
|
||||
//
|
||||
// MinersCountResponse{Now: 142, Max: 200}
|
||||
type MinersCountResponse struct {
|
||||
Now uint64 `json:"now"`
|
||||
Max uint64 `json:"max"`
|
||||
}
|
||||
|
||||
// UpstreamResponse carries pool connection state counts.
|
||||
//
|
||||
// UpstreamResponse{Active: 1, Sleep: 0, Error: 0, Total: 1, Ratio: 142.0}
|
||||
type UpstreamResponse struct {
|
||||
Active uint64 `json:"active"`
|
||||
Sleep uint64 `json:"sleep"`
|
||||
Error uint64 `json:"error"`
|
||||
Total uint64 `json:"total"`
|
||||
Ratio float64 `json:"ratio"`
|
||||
}
|
||||
|
||||
// ResultsResponse carries share acceptance statistics.
|
||||
//
|
||||
// ResultsResponse{Accepted: 4821, Rejected: 3, Invalid: 0, Expired: 12}
|
||||
type ResultsResponse struct {
|
||||
Accepted uint64 `json:"accepted"`
|
||||
Rejected uint64 `json:"rejected"`
|
||||
Invalid uint64 `json:"invalid"`
|
||||
Expired uint64 `json:"expired"`
|
||||
AvgTime uint32 `json:"avg_time"`
|
||||
Latency uint32 `json:"latency"`
|
||||
HashesTotal uint64 `json:"hashes_total"`
|
||||
Best [10]uint64 `json:"best"`
|
||||
}
|
||||
|
||||
// WorkersResponse is the /1/workers JSON body.
|
||||
//
|
||||
// {"mode":"rig-id","workers":[["rig-alpha","10.0.0.1",1,10,0,0,100000,1712232000,1.0,1.0,1.0,1.0,1.0]]}
|
||||
type WorkersResponse struct {
|
||||
Mode string `json:"mode"`
|
||||
Workers []proxy.WorkerRow `json:"workers"`
|
||||
}
|
||||
|
||||
// MinersResponse is the /1/miners JSON body.
|
||||
//
|
||||
// {"format":["id","ip","tx","rx","state","diff","user","password","rig_id","agent"],"miners":[[1,"10.0.0.1:49152",4096,512,2,100000,"WALLET","********","rig-alpha","XMRig/6.21.0"]]}
|
||||
type MinersResponse struct {
|
||||
Format []string `json:"format"`
|
||||
Miners []proxy.MinerRow `json:"miners"`
|
||||
}
|
||||
|
||||
// RegisterRoutes wires the monitoring endpoints onto the supplied router.
|
||||
//
|
||||
// proxyapi.RegisterRoutes(mux, p)
|
||||
// // GET /1/summary, /1/workers, and /1/miners are now live.
|
||||
func RegisterRoutes(r Router, p *proxy.Proxy) {
|
||||
if r == nil || p == nil {
|
||||
func RegisterRoutes(router Router, p *proxy.Proxy) {
|
||||
if router == nil || p == nil {
|
||||
return
|
||||
}
|
||||
r.HandleFunc("/1/summary", func(w http.ResponseWriter, req *http.Request) {
|
||||
writeJSON(w, summaryResponse(p))
|
||||
})
|
||||
r.HandleFunc("/1/workers", func(w http.ResponseWriter, req *http.Request) {
|
||||
writeJSON(w, workersResponse(p))
|
||||
})
|
||||
r.HandleFunc("/1/miners", func(w http.ResponseWriter, req *http.Request) {
|
||||
writeJSON(w, minersResponse(p))
|
||||
})
|
||||
registerGETRoute(router, "/1/summary", func() any { return p.SummaryDocument() })
|
||||
registerGETRoute(router, "/1/workers", func() any { return p.WorkersDocument() })
|
||||
registerGETRoute(router, "/1/miners", func() any { return p.MinersDocument() })
|
||||
}
|
||||
|
||||
func summaryResponse(p *proxy.Proxy) SummaryResponse {
|
||||
summary := p.Summary()
|
||||
now, max := p.MinerCount()
|
||||
upstreams := p.Upstreams()
|
||||
return SummaryResponse{
|
||||
Version: "1.0.0",
|
||||
Mode: p.Mode(),
|
||||
Hashrate: HashrateResponse{
|
||||
Total: summary.Hashrate,
|
||||
},
|
||||
CustomDiffStats: summary.CustomDiffStats,
|
||||
Miners: MinersCountResponse{
|
||||
Now: now,
|
||||
Max: max,
|
||||
},
|
||||
Workers: uint64(len(p.WorkerRecords())),
|
||||
Upstreams: UpstreamResponse{
|
||||
Active: upstreams.Active,
|
||||
Sleep: upstreams.Sleep,
|
||||
Error: upstreams.Error,
|
||||
Total: upstreams.Total,
|
||||
Ratio: upstreamRatio(now, upstreams.Total),
|
||||
},
|
||||
Results: ResultsResponse{
|
||||
Accepted: summary.Accepted,
|
||||
Rejected: summary.Rejected,
|
||||
Invalid: summary.Invalid,
|
||||
Expired: summary.Expired,
|
||||
AvgTime: summary.AvgTime,
|
||||
Latency: summary.AvgLatency,
|
||||
HashesTotal: summary.Hashes,
|
||||
Best: summary.TopDiff,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func workersResponse(p *proxy.Proxy) WorkersResponse {
|
||||
records := p.WorkerRecords()
|
||||
rows := make([]proxy.WorkerRow, 0, len(records))
|
||||
for _, record := range records {
|
||||
rows = append(rows, proxy.WorkerRow{
|
||||
record.Name,
|
||||
record.LastIP,
|
||||
record.Connections,
|
||||
record.Accepted,
|
||||
record.Rejected,
|
||||
record.Invalid,
|
||||
record.Hashes,
|
||||
unixOrZero(record.LastHashAt),
|
||||
record.Hashrate(60),
|
||||
record.Hashrate(600),
|
||||
record.Hashrate(3600),
|
||||
record.Hashrate(43200),
|
||||
record.Hashrate(86400),
|
||||
})
|
||||
}
|
||||
return WorkersResponse{
|
||||
Mode: string(p.WorkersMode()),
|
||||
Workers: rows,
|
||||
}
|
||||
}
|
||||
|
||||
func minersResponse(p *proxy.Proxy) MinersResponse {
|
||||
records := p.MinerSnapshots()
|
||||
rows := make([]proxy.MinerRow, 0, len(records))
|
||||
for _, miner := range records {
|
||||
rows = append(rows, proxy.MinerRow{
|
||||
miner.ID,
|
||||
miner.IP,
|
||||
miner.TX,
|
||||
miner.RX,
|
||||
miner.State,
|
||||
miner.Diff,
|
||||
miner.User,
|
||||
miner.Password,
|
||||
miner.RigID,
|
||||
miner.Agent,
|
||||
})
|
||||
}
|
||||
return MinersResponse{
|
||||
Format: []string{"id", "ip", "tx", "rx", "state", "diff", "user", "password", "rig_id", "agent"},
|
||||
Miners: rows,
|
||||
}
|
||||
func registerGETRoute(router Router, pattern string, document func() any) {
|
||||
router.HandleFunc(pattern, func(w http.ResponseWriter, request *http.Request) {
|
||||
if request.Method != http.MethodGet {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
writeJSON(w, document())
|
||||
})
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, payload any) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(payload)
|
||||
}
|
||||
|
||||
func upstreamRatio(now, total uint64) float64 {
|
||||
if total == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(now) / float64(total)
|
||||
}
|
||||
|
||||
func unixOrZero(value time.Time) int64 {
|
||||
if value.IsZero() {
|
||||
return 0
|
||||
}
|
||||
return value.Unix()
|
||||
}
|
||||
|
|
|
|||
104
api/router_test.go
Normal file
104
api/router_test.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"dappco.re/go/proxy"
|
||||
)
|
||||
|
||||
func TestRegisterRoutes_GETSummary_Good(t *testing.T) {
|
||||
config := &proxy.Config{
|
||||
Mode: "nicehash",
|
||||
Workers: proxy.WorkersByRigID,
|
||||
Bind: []proxy.BindAddr{{Host: "127.0.0.1", Port: 3333}},
|
||||
Pools: []proxy.PoolConfig{{URL: "pool.example:3333", Enabled: true}},
|
||||
}
|
||||
p, result := proxy.New(config)
|
||||
if !result.OK {
|
||||
t.Fatalf("new proxy: %v", result.Error)
|
||||
}
|
||||
|
||||
router := http.NewServeMux()
|
||||
RegisterRoutes(router, p)
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "/1/summary", nil)
|
||||
recorder := httptest.NewRecorder()
|
||||
router.ServeHTTP(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("expected %d, got %d", http.StatusOK, recorder.Code)
|
||||
}
|
||||
|
||||
var document proxy.SummaryDocument
|
||||
if err := json.Unmarshal(recorder.Body.Bytes(), &document); err != nil {
|
||||
t.Fatalf("decode summary document: %v", err)
|
||||
}
|
||||
if document.Mode != "nicehash" {
|
||||
t.Fatalf("expected mode %q, got %q", "nicehash", document.Mode)
|
||||
}
|
||||
if document.Version != "1.0.0" {
|
||||
t.Fatalf("expected version %q, got %q", "1.0.0", document.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterRoutes_POSTSummary_Bad(t *testing.T) {
|
||||
config := &proxy.Config{
|
||||
Mode: "nicehash",
|
||||
Workers: proxy.WorkersByRigID,
|
||||
Bind: []proxy.BindAddr{{Host: "127.0.0.1", Port: 3333}},
|
||||
Pools: []proxy.PoolConfig{{URL: "pool.example:3333", Enabled: true}},
|
||||
}
|
||||
p, result := proxy.New(config)
|
||||
if !result.OK {
|
||||
t.Fatalf("new proxy: %v", result.Error)
|
||||
}
|
||||
|
||||
router := http.NewServeMux()
|
||||
RegisterRoutes(router, p)
|
||||
|
||||
request := httptest.NewRequest(http.MethodPost, "/1/summary", nil)
|
||||
recorder := httptest.NewRecorder()
|
||||
router.ServeHTTP(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusMethodNotAllowed {
|
||||
t.Fatalf("expected %d, got %d", http.StatusMethodNotAllowed, recorder.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterRoutes_GETMiners_Ugly(t *testing.T) {
|
||||
config := &proxy.Config{
|
||||
Mode: "simple",
|
||||
Workers: proxy.WorkersDisabled,
|
||||
Bind: []proxy.BindAddr{{Host: "127.0.0.1", Port: 3333}},
|
||||
Pools: []proxy.PoolConfig{{URL: "pool.example:3333", Enabled: true}},
|
||||
}
|
||||
p, result := proxy.New(config)
|
||||
if !result.OK {
|
||||
t.Fatalf("new proxy: %v", result.Error)
|
||||
}
|
||||
|
||||
router := http.NewServeMux()
|
||||
RegisterRoutes(router, p)
|
||||
|
||||
request := httptest.NewRequest(http.MethodGet, "/1/miners", nil)
|
||||
recorder := httptest.NewRecorder()
|
||||
router.ServeHTTP(recorder, request)
|
||||
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("expected %d, got %d", http.StatusOK, recorder.Code)
|
||||
}
|
||||
|
||||
var document proxy.MinersDocument
|
||||
if err := json.Unmarshal(recorder.Body.Bytes(), &document); err != nil {
|
||||
t.Fatalf("decode miners document: %v", err)
|
||||
}
|
||||
if len(document.Format) != 10 {
|
||||
t.Fatalf("expected 10 miner columns, got %d", len(document.Format))
|
||||
}
|
||||
if len(document.Miners) != 0 {
|
||||
t.Fatalf("expected no miners in a new proxy, got %d", len(document.Miners))
|
||||
}
|
||||
}
|
||||
70
api_rows.go
70
api_rows.go
|
|
@ -9,3 +9,73 @@ type WorkerRow [13]any
|
|||
//
|
||||
// MinerRow{1, "10.0.0.1:49152", 4096, 512, 2, 100000, "WALLET", "********", "rig-alpha", "XMRig/6.21.0"}
|
||||
type MinerRow [10]any
|
||||
|
||||
// SummaryDocument is the RFC-shaped /1/summary response body.
|
||||
//
|
||||
// doc := p.SummaryDocument()
|
||||
type SummaryDocument struct {
|
||||
Version string `json:"version"`
|
||||
Mode string `json:"mode"`
|
||||
Hashrate HashrateDocument `json:"hashrate"`
|
||||
Miners MinersCountDocument `json:"miners"`
|
||||
Workers uint64 `json:"workers"`
|
||||
Upstreams UpstreamDocument `json:"upstreams"`
|
||||
Results ResultsDocument `json:"results"`
|
||||
CustomDiffStats map[uint64]CustomDiffBucketStats `json:"custom_diff_stats,omitempty"`
|
||||
}
|
||||
|
||||
// HashrateDocument carries the per-window hashrate array.
|
||||
//
|
||||
// HashrateDocument{Total: [6]float64{12345.67, 11900.00, 12100.00, 11800.00, 12000.00, 12200.00}}
|
||||
type HashrateDocument struct {
|
||||
Total [6]float64 `json:"total"`
|
||||
}
|
||||
|
||||
// MinersCountDocument carries current and peak miner counts.
|
||||
//
|
||||
// MinersCountDocument{Now: 142, Max: 200}
|
||||
type MinersCountDocument struct {
|
||||
Now uint64 `json:"now"`
|
||||
Max uint64 `json:"max"`
|
||||
}
|
||||
|
||||
// UpstreamDocument carries pool connection state counts.
|
||||
//
|
||||
// UpstreamDocument{Active: 1, Sleep: 0, Error: 0, Total: 1, Ratio: 142.0}
|
||||
type UpstreamDocument struct {
|
||||
Active uint64 `json:"active"`
|
||||
Sleep uint64 `json:"sleep"`
|
||||
Error uint64 `json:"error"`
|
||||
Total uint64 `json:"total"`
|
||||
Ratio float64 `json:"ratio"`
|
||||
}
|
||||
|
||||
// ResultsDocument carries share acceptance statistics.
|
||||
//
|
||||
// ResultsDocument{Accepted: 4821, Rejected: 3, Invalid: 0, Expired: 12}
|
||||
type ResultsDocument struct {
|
||||
Accepted uint64 `json:"accepted"`
|
||||
Rejected uint64 `json:"rejected"`
|
||||
Invalid uint64 `json:"invalid"`
|
||||
Expired uint64 `json:"expired"`
|
||||
AvgTime uint32 `json:"avg_time"`
|
||||
Latency uint32 `json:"latency"`
|
||||
HashesTotal uint64 `json:"hashes_total"`
|
||||
Best [10]uint64 `json:"best"`
|
||||
}
|
||||
|
||||
// WorkersDocument is the RFC-shaped /1/workers response body.
|
||||
//
|
||||
// doc := p.WorkersDocument()
|
||||
type WorkersDocument struct {
|
||||
Mode string `json:"mode"`
|
||||
Workers []WorkerRow `json:"workers"`
|
||||
}
|
||||
|
||||
// MinersDocument is the RFC-shaped /1/miners response body.
|
||||
//
|
||||
// doc := p.MinersDocument()
|
||||
type MinersDocument struct {
|
||||
Format []string `json:"format"`
|
||||
Miners []MinerRow `json:"miners"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ func (p *Proxy) startHTTP() bool {
|
|||
w.WriteHeader(status)
|
||||
return
|
||||
}
|
||||
p.writeJSON(w, p.summaryDocument())
|
||||
p.writeJSON(w, p.SummaryDocument())
|
||||
})
|
||||
mux.HandleFunc("/1/workers", func(w http.ResponseWriter, r *http.Request) {
|
||||
if status, ok := p.allowHTTP(r); !ok {
|
||||
|
|
@ -611,7 +611,7 @@ func (p *Proxy) startHTTP() bool {
|
|||
w.WriteHeader(status)
|
||||
return
|
||||
}
|
||||
p.writeJSON(w, p.workersDocument())
|
||||
p.writeJSON(w, p.WorkersDocument())
|
||||
})
|
||||
mux.HandleFunc("/1/miners", func(w http.ResponseWriter, r *http.Request) {
|
||||
if status, ok := p.allowHTTP(r); !ok {
|
||||
|
|
@ -621,7 +621,7 @@ func (p *Proxy) startHTTP() bool {
|
|||
w.WriteHeader(status)
|
||||
return
|
||||
}
|
||||
p.writeJSON(w, p.minersDocument())
|
||||
p.writeJSON(w, p.MinersDocument())
|
||||
})
|
||||
addr := net.JoinHostPort(p.config.HTTP.Host, strconv.Itoa(int(p.config.HTTP.Port)))
|
||||
listener, err := net.Listen("tcp", addr)
|
||||
|
|
@ -659,73 +659,27 @@ func (p *Proxy) writeJSON(w http.ResponseWriter, payload any) {
|
|||
_ = json.NewEncoder(w).Encode(payload)
|
||||
}
|
||||
|
||||
type summaryDocumentPayload struct {
|
||||
Version string `json:"version"`
|
||||
Mode string `json:"mode"`
|
||||
Hashrate summaryHashratePayload `json:"hashrate"`
|
||||
Miners summaryMinersPayload `json:"miners"`
|
||||
Workers uint64 `json:"workers"`
|
||||
Upstreams summaryUpstreamsPayload `json:"upstreams"`
|
||||
Results summaryResultsPayload `json:"results"`
|
||||
CustomDiffStats map[uint64]CustomDiffBucketStats `json:"custom_diff_stats,omitempty"`
|
||||
}
|
||||
|
||||
type summaryHashratePayload struct {
|
||||
Total [6]float64 `json:"total"`
|
||||
}
|
||||
|
||||
type summaryMinersPayload struct {
|
||||
Now uint64 `json:"now"`
|
||||
Max uint64 `json:"max"`
|
||||
}
|
||||
|
||||
type summaryUpstreamsPayload struct {
|
||||
Active uint64 `json:"active"`
|
||||
Sleep uint64 `json:"sleep"`
|
||||
Error uint64 `json:"error"`
|
||||
Total uint64 `json:"total"`
|
||||
Ratio float64 `json:"ratio"`
|
||||
}
|
||||
|
||||
type summaryResultsPayload struct {
|
||||
Accepted uint64 `json:"accepted"`
|
||||
Rejected uint64 `json:"rejected"`
|
||||
Invalid uint64 `json:"invalid"`
|
||||
Expired uint64 `json:"expired"`
|
||||
AvgTime uint32 `json:"avg_time"`
|
||||
Latency uint32 `json:"latency"`
|
||||
HashesTotal uint64 `json:"hashes_total"`
|
||||
Best [10]uint64 `json:"best"`
|
||||
}
|
||||
|
||||
type workersDocumentPayload struct {
|
||||
Mode string `json:"mode"`
|
||||
Workers []WorkerRow `json:"workers"`
|
||||
}
|
||||
|
||||
type minersDocumentPayload struct {
|
||||
Format []string `json:"format"`
|
||||
Miners []MinerRow `json:"miners"`
|
||||
}
|
||||
|
||||
func (p *Proxy) summaryDocument() summaryDocumentPayload {
|
||||
// SummaryDocument builds the RFC-shaped /1/summary response body.
|
||||
//
|
||||
// doc := p.SummaryDocument()
|
||||
func (p *Proxy) SummaryDocument() SummaryDocument {
|
||||
summary := p.Summary()
|
||||
now, max := p.MinerCount()
|
||||
upstreams := p.Upstreams()
|
||||
return summaryDocumentPayload{
|
||||
return SummaryDocument{
|
||||
Version: "1.0.0",
|
||||
Mode: p.Mode(),
|
||||
Hashrate: summaryHashratePayload{
|
||||
Hashrate: HashrateDocument{
|
||||
Total: summary.Hashrate,
|
||||
},
|
||||
CustomDiffStats: summary.CustomDiffStats,
|
||||
Miners: summaryMinersPayload{
|
||||
Miners: MinersCountDocument{
|
||||
Now: now,
|
||||
Max: max,
|
||||
},
|
||||
Workers: uint64(len(p.WorkerRecords())),
|
||||
Upstreams: summaryUpstreamsPayload{Active: upstreams.Active, Sleep: upstreams.Sleep, Error: upstreams.Error, Total: upstreams.Total, Ratio: upstreamRatio(now, upstreams)},
|
||||
Results: summaryResultsPayload{
|
||||
Upstreams: UpstreamDocument{Active: upstreams.Active, Sleep: upstreams.Sleep, Error: upstreams.Error, Total: upstreams.Total, Ratio: upstreamRatio(now, upstreams)},
|
||||
Results: ResultsDocument{
|
||||
Accepted: summary.Accepted,
|
||||
Rejected: summary.Rejected,
|
||||
Invalid: summary.Invalid,
|
||||
|
|
@ -738,7 +692,10 @@ func (p *Proxy) summaryDocument() summaryDocumentPayload {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) workersDocument() workersDocumentPayload {
|
||||
// WorkersDocument builds the RFC-shaped /1/workers response body.
|
||||
//
|
||||
// doc := p.WorkersDocument()
|
||||
func (p *Proxy) WorkersDocument() WorkersDocument {
|
||||
records := p.WorkerRecords()
|
||||
rows := make([]WorkerRow, 0, len(records))
|
||||
for _, record := range records {
|
||||
|
|
@ -758,13 +715,16 @@ func (p *Proxy) workersDocument() workersDocumentPayload {
|
|||
record.Hashrate(86400),
|
||||
})
|
||||
}
|
||||
return workersDocumentPayload{
|
||||
return WorkersDocument{
|
||||
Mode: string(p.WorkersMode()),
|
||||
Workers: rows,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) minersDocument() minersDocumentPayload {
|
||||
// MinersDocument builds the RFC-shaped /1/miners response body.
|
||||
//
|
||||
// doc := p.MinersDocument()
|
||||
func (p *Proxy) MinersDocument() MinersDocument {
|
||||
records := p.MinerSnapshots()
|
||||
rows := make([]MinerRow, 0, len(records))
|
||||
for _, miner := range records {
|
||||
|
|
@ -781,7 +741,7 @@ func (p *Proxy) minersDocument() minersDocumentPayload {
|
|||
miner.Agent,
|
||||
})
|
||||
}
|
||||
return minersDocumentPayload{
|
||||
return MinersDocument{
|
||||
Format: []string{"id", "ip", "tx", "rx", "state", "diff", "user", "password", "rig_id", "agent"},
|
||||
Miners: rows,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue