Skip to content
This repository has been archived by the owner on Nov 7, 2022. It is now read-only.

Commit

Permalink
exporter/metrics: add Prometheus metrics exporter
Browse files Browse the repository at this point in the history
Added a Prometheus metrics exporter that allows
us to export metrics.
Its configuration is available under YAML field option
```yaml
exporters
    prometheus:
        <key>: <value>
```
where <key> could be any of

* address -- the address on which to run the Prometheus
scrape endpoint /metrics on

* const_labels -- labels that will be applied to each
metric that is exported

* namespace -- optionally if defined records metrics
under a specific namespace, leave it blank to preserve
the names of the proxied metrics (if that's the case)

This change uses the Prometheus metrics exporter
at github.com/orijtech/prometheus-go-metrics-exporter
which will be handed over to the OpenCensus community
whenever a repository is created under the
"census-ecosystem" organization.

Fixes #292
Depends on #294
  • Loading branch information
odeke-em committed Jan 10, 2019
1 parent de73c6b commit 72459ff
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 2 deletions.
41 changes: 39 additions & 2 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import (
"time"

"contrib.go.opencensus.io/exporter/ocagent"

"go.opencensus.io/stats"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"go.opencensus.io/trace"
)

Expand All @@ -31,14 +35,47 @@ func main() {
log.Fatalf("Failed to create ocagent-exporter: %v", err)
}
trace.RegisterExporter(oce)
view.RegisterExporter(oce)

trace.ApplyConfig(trace.Config{
DefaultSampler: trace.AlwaysSample(),
})

// Some stats
view.SetReportingPeriod(4 * time.Second)
keyClient, _ := tag.NewKey("client")
keyMethod, _ := tag.NewKey("method")

mLatencyMs := stats.Float64("latency", "The latency in milliseconds", "ms")
views := []*view.View{
&view.View{
Name: "opdemo/latency",
Description: "The various counts",
Measure: mLatencyMs,
Aggregation: view.Distribution(0, 10, 50, 100, 200, 400, 800, 1000, 1400, 2000, 5000, 10000),
TagKeys: []tag.Key{keyClient, keyMethod},
},
&view.View{
Name: "opdemo/process_counts",
Description: "The various counts",
Measure: mLatencyMs,
Aggregation: view.Count(),
TagKeys: []tag.Key{keyClient, keyMethod},
},
}

if err := view.Register(views...); err != nil {
log.Fatalf("Failed to register views for metrics: %v", err)
}

ctx, _ := tag.New(context.Background(), tag.Insert(keyMethod, "repl"), tag.Insert(keyClient, "cli"))
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
for {
_, span := trace.StartSpan(context.Background(), "foo")
time.Sleep(time.Duration(rng.Int63n(1000)) * time.Millisecond)
startTime := time.Now()
_, span := trace.StartSpan(context.Background(), "Foo")
time.Sleep(time.Duration(rng.Int63n(13000)) * time.Millisecond)
span.End()
latencyMs := float64(time.Since(startTime)) / 1e6
stats.Record(ctx, mLatencyMs.M(latencyMs))
}
}
103 changes: 103 additions & 0 deletions exporter/exporterparser/prometheus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2019, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package exporterparser

import (
"context"
"errors"
"net/http"
"strings"

"github.com/census-instrumentation/opencensus-service/data"
"github.com/census-instrumentation/opencensus-service/exporter"
"github.com/orijtech/prometheus-go-metrics-exporter"
prometheus_golang "github.com/prometheus/client_golang/prometheus"
)

type prometheusConfig struct {
// Namespace if set, exports metrics under the provided value.
Namespace string `yaml:"namespace"`

// ConstLabels are values that are applied for every exported metric.
ConstLabels prometheus_golang.Labels `yaml:"const_labels"`

// The address on which the Prometheus scrape handler will be run on.
Address string `yaml:"address"`
}

var errBlankPrometheusAddress = errors.New("expecting a non-blank address to run the Prometheus metrics handler")

// PrometheusExportersFromYAML parses the yaml bytes and returns exporter.MetricsExporters targeting
// Prometheus according to the configuration settings.
func PrometheusExportersFromYAML(config []byte) (tes []exporter.TraceExporter, mes []exporter.MetricsExporter, doneFns []func() error, err error) {
var cfg struct {
Exporters *struct {
Prometheus *prometheusConfig `yaml:"prometheus"`
} `yaml:"exporters"`
}
if err := yamlUnmarshal(config, &cfg); err != nil {
return nil, nil, nil, err
}
if cfg.Exporters == nil {
return nil, nil, nil, nil
}

pcfg := cfg.Exporters.Prometheus
addr := strings.TrimSpace(pcfg.Address)
if addr == "" {
err = errBlankPrometheusAddress
return
}

opts := prometheus.Options{
Namespace: pcfg.Namespace,
ConstLabels: pcfg.ConstLabels,
}
pe, err := prometheus.New(opts)
if err != nil {
return nil, nil, nil, err
}

// The Prometheus metrics exporter has to run on the provided address
// as a server that'll be scraped by Prometheus.
mux := http.NewServeMux()
mux.Handle("/metrics", pe)

srv := http.Server{
Handler: mux,
Addr: pcfg.Address,
}
go func() {
_ = srv.ListenAndServe()
}()
doneFns = append(doneFns, srv.Close)
pexp := &prometheusExporter{exporter: pe}
mes = append(mes, pexp)

return
}

type prometheusExporter struct {
exporter *prometheus.Exporter
}

var _ exporter.MetricsExporter = (*prometheusExporter)(nil)

func (pe *prometheusExporter) ExportMetricsData(ctx context.Context, md data.MetricsData) error {
for _, metric := range md.Metrics {
_ = pe.exporter.ExportMetric(ctx, md.Node, md.Resource, metric)
}
return nil
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ require (
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/opentracing/opentracing-go v1.0.2 // indirect
github.com/openzipkin/zipkin-go v0.1.3
github.com/orijtech/prometheus-go-metrics-exporter v0.0.1
github.com/philhofer/fwd v1.0.0 // indirect
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a // indirect
github.com/prometheus/client_golang v0.8.0
github.com/soheilhy/cmux v0.1.4
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.3 h1:36hTtUTQR/vPX7YVJo2PYexSbHdAJiAkDrjuXw/YlYQ=
github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/orijtech/prometheus-go-metrics-exporter v0.0.1 h1:Wh7eHO8HEduepMno4euif22RKn0Ev6Huxr8uijVeOX0=
github.com/orijtech/prometheus-go-metrics-exporter v0.0.1/go.mod h1:+Mu9w51Uc2RNKSUTA95d6Pvy8cxFiRX3ANRPlCcnGLA=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
Expand Down
2 changes: 2 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ func eqLocalHost(host string) bool {
// + jaeger
// + kafka
// + opencensus
// + prometheus
func ExportersFromYAMLConfig(config []byte) (traceExporters []exporter.TraceExporter, metricsExporters []exporter.MetricsExporter, doneFns []func() error, err error) {
parseFns := []struct {
name string
Expand All @@ -288,6 +289,7 @@ func ExportersFromYAMLConfig(config []byte) (traceExporters []exporter.TraceExpo
{name: "jaeger", fn: exporterparser.JaegerExportersFromYAML},
{name: "kafka", fn: exporterparser.KafkaExportersFromYAML},
{name: "opencensus", fn: exporterparser.OpenCensusTraceExportersFromYAML},
{name: "prometheus", fn: exporterparser.PrometheusExportersFromYAML},
}

for _, cfg := range parseFns {
Expand Down

0 comments on commit 72459ff

Please sign in to comment.