How to map expfmt to samples

go
Wrap Lines
Raw
package main

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/golang/snappy"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/expfmt"
	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/prompb"
)

const (
	pushgatewayURL = "https://prom.scanwizard.ru/api/v1/write"
	username       = "scanaryd"
	password       = "$apr1$RseemMSV$H2LzM3cl71lbptrokMhgF/"
)

func main() {
	// Create a new registry
	registry := prometheus.NewRegistry()

	// Create a gauge metric
	asicTestMetric := prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "asic_test_metric",
		Help: "A test metric for ASIC monitoring",
	})

	// Register the metric with the registry
	registry.MustRegister(asicTestMetric)

	// Set the metric value
	asicTestMetric.Set(150.45)

	// Gather metrics from the registry
	metricFamilies, err := registry.Gather()
	if err != nil {
		log.Fatalf("Failed to gather metrics: %v", err)
	}

	// Convert metric families to samples using expfmt
	decodeOptions := &expfmt.DecodeOptions{
		Timestamp: model.TimeFromUnixNano(time.Now().UnixNano()),
	}

	// Extract samples from metric families
	samples, err := expfmt.ExtractSamples(decodeOptions, metricFamilies...)
	if err != nil {
		log.Fatalf("Failed to extract samples: %v", err)
	}
	fmt.Println(samples)

	// Convert samples to remote write format
	var timeseries []prompb.TimeSeries
	for _, sample := range samples {
		// Create labels
		var labels []prompb.Label
		for name, value := range sample.Metric {
			labels = append(labels, prompb.Label{
				Name:  string(name),
				Value: string(value),
			})
		}

		// Create timeseries
		timeseries = append(timeseries, prompb.TimeSeries{
			Labels: labels,
			Samples: []prompb.Sample{
				{
					Value:     float64(sample.Value),
					Timestamp: int64(sample.Timestamp),
				},
			},
		})
	}

	// Create write request according to spec
	writeRequest := &prompb.WriteRequest{
		Timeseries: timeseries,
	}

	// Marshal to protobuf
	data, err := writeRequest.Marshal()
	if err != nil {
		log.Fatalf("Failed to marshal protobuf: %v", err)
	}
	fmt.Println(data)

	// Compress with snappy (block format as required by spec)
	compressedData := snappy.Encode(nil, data)

	// Create HTTP request
	req, err := http.NewRequest("POST", pushgatewayURL, bytes.NewBuffer(compressedData))
	if err != nil {
		log.Fatalf("Failed to create request: %v", err)
	}

	// Set headers according to Prometheus Remote Write 1.0 spec
	req.Header.Set("Content-Type", "application/x-protobuf")
	req.Header.Set("Content-Encoding", "snappy")
	req.Header.Set("User-Agent", "go-test-script/1.0")
	req.Header.Set("X-Prometheus-Remote-Write-Version", "0.1.0")
	req.SetBasicAuth(username, password)

	client := &http.Client{
		Timeout: 10 * time.Second,
	}

	fmt.Println(req)
	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("Failed to send request: %v", err)
	}
	defer resp.Body.Close()

	fmt.Printf("Status Code: %d\n", resp.StatusCode)
	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
		log.Printf("Unexpected status code: %d", resp.StatusCode)
	} else {
		fmt.Println("Metrics successfully sent to Prometheus!")
	}
}