Skip to content

Commit

Permalink
Adds prometheus exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
murex971 committed Nov 3, 2020
1 parent 3589c84 commit 030ece0
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ require (
github.com/gorilla/websocket v1.4.1
github.com/pelletier/go-toml v1.6.0 // indirect
github.com/sdslabs/kiwi v1.0.0
github.com/prometheus/client_golang v0.9.3
github.com/prometheus/common v0.4.0
github.com/sirupsen/logrus v1.4.2
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cast v1.3.1 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
Expand Down
6 changes: 6 additions & 0 deletions pkg/exporter/prometheus/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2020 SDSLabs
// Use of this source code is governed by an MIT license
// details of which can be found in the LICENSE file.

// Package prometheus implements the prometheus metrics exporter.
package prometheus
157 changes: 157 additions & 0 deletions pkg/exporter/prometheus/exporter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Copyright (c) 2020 SDSLabs
// Use of this source code is governed by an MIT license
// details of which can be found in the LICENSE file.

package prometheus

import (
"context"
"fmt"
"net/http"
"time"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/log"

"github.com/sdslabs/pinger/pkg/appcontext"
"github.com/sdslabs/pinger/pkg/checker"
"github.com/sdslabs/pinger/pkg/exporter"
)

const (
probeLatencyLabel = "probe_latency"
probeStatusLabel = "probe_status"
exporterName = "prometheus"
)

func init() {
exporter.Register(exporterName, func() exporter.Exporter { return new(Exporter) })
}

// Exporter for exporting metrics to prometheus db.
type Exporter struct {
Metrics map[string]*prometheus.Desc
checks []checker.Metric
}

// NewExporter creates an empty but not-nil `*Exporter`.
func NewExporter() *Exporter {
metrics := make(map[string]*prometheus.Desc)

// Probe latency metrics descriptor.
metrics[probeLatencyLabel] = prometheus.NewDesc(
// Name of the metrics defined by the descriptor
probeLatencyLabel,
// Help message for the metrics
"Time in micro seconds which measures the latency of the probe defined by the controller",
// Metrics variable level dimensions
[]string{"check_name"},
// Metrics constant label dimensions.
nil,
)

// Status metrics descriptor.
//
// Value is 0.0 if the probe failed,
// -1.0 if it failed due to timeout and +1.0 if it succeeded.
metrics[probeStatusLabel] = prometheus.NewDesc(
probeStatusLabel,
"Status of the probe, value is 0.0 on probe failure, -1.0 on failure due to timeout and +1.0 on success",
[]string{"check_name"},
nil,
)

return &Exporter{
Metrics: metrics,
checks: nil,
}
}

// Describe implements prometheus.Collector.
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
for _, desc := range e.Metrics {
ch <- desc
}
}

// Collect implements prometheus.Collector.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
log.Info("Starting to collect prometheus metrics.")

// Iterate over each check and send them to prometheus.
for _, check := range e.checks {
latencyMetric := prometheus.MustNewConstMetric(
e.Metrics[probeLatencyLabel],
prometheus.GaugeValue,
float64(check.GetDuration()/1e3),

// variable labels for the metric.
check.GetCheckName(),
)
ch <- prometheus.NewMetricWithTimestamp(check.GetStartTime(), latencyMetric)

var statusVal float64 = 1.0
if check.IsTimeout() {
statusVal = -1.0
} else if !check.IsSuccessful() {
statusVal = 0.0
}
statusMetric := prometheus.MustNewConstMetric(
e.Metrics[probeStatusLabel],
prometheus.GaugeValue,
statusVal,

check.GetCheckName(),
)
ch <- prometheus.NewMetricWithTimestamp(check.GetStartTime(), statusMetric)
}
}

// Provision sets e's configuration.
func (e *Exporter) Provision(ctx *appcontext.Context, provider exporter.Provider) error {
exporter := NewExporter()
prometheus.MustRegister(exporter)

httpServer := http.Server{
Addr: fmt.Sprintf(":%d", provider.GetPort()),
}
defer httpServer.Close() //nolint:errcheck

http.Handle("/metrics", promhttp.Handler())
log.Infoln("Beginning to serve prometheus metrics on port", provider.GetPort())

if err := httpServer.ListenAndServe(); err != nil {
return err
}

return nil
}

// Export exports the metrics to the exporter.
func (e *Exporter) Export(_ context.Context, metrics []checker.Metric) error {
ch1 := make(chan<- *prometheus.Desc)
e.Describe(ch1)

e.checks = metrics
ch2 := make(chan<- prometheus.Metric)
e.Collect(ch2)

return nil
}

// GetMetrics get the metrics of the given checks.
func (e *Exporter) GetMetrics(
ctx context.Context,
time time.Duration,
checkIDs ...string,
) (map[string][]checker.Metric, error) {
if len(checkIDs) == 0 {
return nil, nil
}

return nil, nil
}

// Interface guard.
var _ exporter.Exporter = (*Exporter)(nil)

0 comments on commit 030ece0

Please sign in to comment.