func (f *Framework) ParseMetrics(metrics func(io.Writer) error) (map[string]*dto.MetricFamily, error) {
	buf := &bytes.Buffer{}
	err := metrics(buf)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get metrics")
	}
	parser := &expfmt.TextParser{}
	return parser.TextToMetricFamilies(buf)
}
ParseMetrics uses a prometheus TextParser to parse metrics, given a function
that fetches and writes metrics.
package framework
import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"path"
	"strings"
	"github.com/pkg/errors"
	dto "github.com/prometheus/client_model/go"
	"github.com/prometheus/common/expfmt"
)
const (
	epHealthz = "/healthz"
	epMetrics = "/metrics"
)
type Framework struct {
	KsmClient *KSMClient
}
func New(ksmHTTPMetricsURL, ksmTelemetryURL string) (*Framework, error) {
	ksmClient, err := NewKSMClient(ksmHTTPMetricsURL, ksmTelemetryURL)
	if err != nil {
		return nil, err
	}
	return &Framework{
		KsmClient: ksmClient,
	}, nil
}
type KSMClient struct {
	httpMetricsEndpoint *url.URL
	telemetryEndpoint   *url.URL
	client              *http.Client
}
func NewKSMClient(ksmHTTPMetricsAddress, ksmTelemetryAddress string) (*KSMClient, error) {
	ksmHTTPMetricsURL, err := validateURL(ksmHTTPMetricsAddress)
	if err != nil {
		return nil, err
	}
	ksmTelemetryURL, err := validateURL(ksmTelemetryAddress)
	if err != nil {
		return nil, err
	}
	return &KSMClient{
		httpMetricsEndpoint: ksmHTTPMetricsURL,
		telemetryEndpoint:   ksmTelemetryURL,
		client:              &http.Client{},
	}, nil
}
func validateURL(address string) (*url.URL, error) {
	u, err := url.Parse(address)
	if err != nil {
		return nil, err
	}
	u.Path = strings.TrimRight(u.Path, "/")
	return u, nil
}
func (k *KSMClient) IsHealthz() (bool, error) {
	p := path.Join(k.httpMetricsEndpoint.Path, epHealthz)
	u := *k.httpMetricsEndpoint
	u.Path = p
	req, err := http.NewRequest(http.MethodGet, u.String(), nil)
	if err != nil {
		return false, err
	}
	resp, err := k.client.Do(req)
	if err != nil {
		return false, err
	}
	defer func() {
		io.Copy(io.Discard, resp.Body)
		resp.Body.Close()
	}()
	if resp.StatusCode != http.StatusOK {
		return false, fmt.Errorf("server returned HTTP status %s", resp.Status)
	}
	return true, nil
}
func (k *KSMClient) writeMetrics(endpoint *url.URL, w io.Writer) error {
	if endpoint == nil {
		return errors.New("Endpoint is nil")
	}
	u := *endpoint
	u.Path = path.Join(endpoint.Path, epMetrics)
	req, err := http.NewRequest(http.MethodGet, u.String(), nil)
	if err != nil {
		return err
	}
	resp, err := k.client.Do(req)
	if err != nil {
		return err
	}
	defer func() {
		io.Copy(io.Discard, resp.Body)
		resp.Body.Close()
	}()
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("server returned HTTP status %s", resp.Status)
	}
	io.Copy(w, resp.Body)
	return nil
}
func (k *KSMClient) Metrics(w io.Writer) error {
	return k.writeMetrics(k.httpMetricsEndpoint, w)
}
func (k *KSMClient) TelemetryMetrics(w io.Writer) error {
	return k.writeMetrics(k.telemetryEndpoint, w)
}