github.com/MetalBlockchain/metalgo@v1.11.9/api/metrics/client.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package metrics 5 6 import ( 7 "bytes" 8 "context" 9 "fmt" 10 "net/http" 11 "net/url" 12 13 "github.com/prometheus/common/expfmt" 14 15 dto "github.com/prometheus/client_model/go" 16 ) 17 18 // Client for requesting metrics from a remote AvalancheGo instance 19 type Client struct { 20 uri string 21 } 22 23 // NewClient returns a new Metrics API Client 24 func NewClient(uri string) *Client { 25 return &Client{ 26 uri: uri + "/ext/metrics", 27 } 28 } 29 30 // GetMetrics returns the metrics from the connected node. The metrics are 31 // returned as a map of metric family name to the metric family. 32 func (c *Client) GetMetrics(ctx context.Context) (map[string]*dto.MetricFamily, error) { 33 uri, err := url.Parse(c.uri) 34 if err != nil { 35 return nil, err 36 } 37 38 request, err := http.NewRequestWithContext( 39 ctx, 40 http.MethodGet, 41 uri.String(), 42 bytes.NewReader(nil), 43 ) 44 if err != nil { 45 return nil, fmt.Errorf("failed to create request: %w", err) 46 } 47 48 resp, err := http.DefaultClient.Do(request) 49 if err != nil { 50 return nil, fmt.Errorf("failed to issue request: %w", err) 51 } 52 53 // Return an error for any non successful status code 54 if resp.StatusCode < 200 || resp.StatusCode > 299 { 55 // Drop any error during close to report the original error 56 _ = resp.Body.Close() 57 return nil, fmt.Errorf("received status code: %d", resp.StatusCode) 58 } 59 60 var parser expfmt.TextParser 61 metrics, err := parser.TextToMetricFamilies(resp.Body) 62 if err != nil { 63 // Drop any error during close to report the original error 64 _ = resp.Body.Close() 65 return nil, err 66 } 67 return metrics, resp.Body.Close() 68 }