mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
Drop the Avalanche-heritage /ext prefix; /v1 is the single canonical route surface (one way, no backward compat). The node's baseURL is the source of truth; clients, SDKs, CLI, indexer, maker, genesis, netrunner, and the k8s/compose/gateway/explorer configs are updated to match. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
111 lines
2.6 KiB
Go
111 lines
2.6 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package tests
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// cleanlyCloseBody drains and closes an HTTP response body to prevent
|
|
// HTTP/2 GOAWAY errors caused by closing bodies with unread data.
|
|
func cleanlyCloseBody(body io.ReadCloser) error {
|
|
if body == nil {
|
|
return nil
|
|
}
|
|
_, _ = io.Copy(io.Discard, body)
|
|
return body.Close()
|
|
}
|
|
|
|
// "metric name" -> "metric value"
|
|
type SimpleNodeMetrics map[string]float64
|
|
|
|
// URI -> "metric name" -> "metric value"
|
|
type SimpleNodesMetrics map[string]SimpleNodeMetrics
|
|
|
|
// GetSimpleNodeMetrics retrieves the specified metrics the provided node URI.
|
|
func GetSimpleNodeMetrics(nodeURI string, metricNames ...string) (SimpleNodeMetrics, error) {
|
|
uri := nodeURI + "/v1/metrics"
|
|
return GetMetricsValue(uri, metricNames...)
|
|
}
|
|
|
|
// GetSimpleNodesMetrics retrieves the specified metrics for the provided node URIs.
|
|
func GetSimpleNodesMetrics(nodeURIs []string, metricNames ...string) (SimpleNodesMetrics, error) {
|
|
metrics := make(SimpleNodesMetrics, len(nodeURIs))
|
|
for _, u := range nodeURIs {
|
|
var err error
|
|
metrics[u], err = GetSimpleNodeMetrics(u, metricNames...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to retrieve metrics for %s: %w", u, err)
|
|
}
|
|
}
|
|
return metrics, nil
|
|
}
|
|
|
|
func GetMetricsValue(url string, metrics ...string) (SimpleNodeMetrics, error) {
|
|
lines, err := getHTTPLines(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mm := make(map[string]float64, len(metrics))
|
|
for _, line := range lines {
|
|
if strings.HasPrefix(line, "# ") {
|
|
continue
|
|
}
|
|
found, name := false, ""
|
|
for _, name = range metrics {
|
|
if !strings.HasPrefix(line, name) {
|
|
continue
|
|
}
|
|
found = true
|
|
break
|
|
}
|
|
if !found || name == "" { // no matched metric found
|
|
continue
|
|
}
|
|
ll := strings.Split(line, " ")
|
|
if len(ll) != 2 {
|
|
continue
|
|
}
|
|
fv, err := strconv.ParseFloat(ll[1], 64)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse %q (%w)", ll, err)
|
|
}
|
|
mm[name] = fv
|
|
}
|
|
return mm, nil
|
|
}
|
|
|
|
func getHTTPLines(url string) ([]string, error) {
|
|
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cleanlyCloseBody(resp.Body)
|
|
|
|
rd := bufio.NewReader(resp.Body)
|
|
lines := []string{}
|
|
for {
|
|
line, err := rd.ReadString('\n')
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return nil, err
|
|
}
|
|
lines = append(lines, strings.TrimSpace(line))
|
|
}
|
|
return lines, nil
|
|
}
|