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  }