agalue / gominion

An implementation of the OpenNMS Minion in Go using gRPC
GNU Affero General Public License v3.0
3 stars 1 forks source link

Implement Prometheus Collector #3

Open agalue opened 3 years ago

agalue commented 3 years ago

Unlike SNMP, there are native libraries to work with Prometheus in Go (as that application was written in that language), so it would be useful to write it here.

Also, expose gominion metrics via Prometheus, as an alternative to what you get with JMX-Minion in Java.

agalue commented 1 year ago

The following can serve as an inspiration:

package main

import (
    "crypto/tls"
    "flag"
    "fmt"
    "net/http"
    "time"

    dto "github.com/prometheus/client_model/go"
    "github.com/prometheus/common/expfmt"
)

func parseMF(url string) (map[string]*dto.MetricFamily, error) {
    client := &http.Client{
        Timeout: 30 * time.Second,
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
    }
    res, err := client.Get(url)
    if err == nil {
        if res.StatusCode == 200 {
            defer res.Body.Close()
            var parser expfmt.TextParser
            mf, err := parser.TextToMetricFamilies(res.Body)
            if err == nil {
                return mf, nil
            }
        }
    }
    return nil, err

}

func main() {
    f := flag.String("s", "http://localhost:8080/metrics", "URL to retrieve Prometheus Metrics")
    flag.Parse()

    mf, err := parseMF(*f)
    if err != nil {
        panic(err)
    }

    for _, v := range mf {
        m := v.Metric[0]
        var value float64
        switch v.GetType() {
        case dto.MetricType_GAUGE:
            value = m.GetGauge().GetValue()
        case dto.MetricType_COUNTER:
            value = m.GetCounter().GetValue()
        case dto.MetricType_GAUGE_HISTOGRAM:
            value = m.GetHistogram().GetSampleCountFloat()
        }
        fmt.Printf("%s (%s) {%v}: %f\n", v.GetName(), v.GetType().String(), m.GetLabel(), value)
    }
}
agalue commented 1 year ago

Unfortunately, the implementation relies on Spring Expression Language (SpEL) for filtering, which doesn't exist in Go. That makes it very hard to implement unless we use something different (like Go Templates) when using gominion (incompatible with OpenNMS/Minion).