<commit_before>// Copyright 2016 Mesosphere, Inc.
//
// 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 prometheus

import (
	"errors"
	"fmt"
	"math"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/dcos/dcos-go/store"
	"github.com/dcos/dcos-metrics/producers"
	prodHelpers "github.com/dcos/dcos-metrics/util/producers"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	illegalChars = regexp.MustCompile("\\W")
	promLog      = log.WithFields(log.Fields{"producer": "prometheus"})
)

// Config is a configuration for the Prom producer's behaviour
type Config struct {
	Port        int `yaml:"port"`
	CacheExpiry time.Duration
}

// promProducer implements both producers.MetricsProducer and
// prometheus.Producer
type promProducer struct {
	config             Config
	store              store.Store
	metricsChan        chan producers.MetricsMessage
	janitorRunInterval time.Duration
}

// New returns a prometheus producer and a channel for passing in metrics
func New(cfg Config) (producers.MetricsProducer, chan producers.MetricsMessage) {
	p := promProducer{
		config:             cfg,
		store:              store.New(),
		metricsChan:        make(chan producers.MetricsMessage),
		janitorRunInterval: 60 * time.Second,
	}
	return &p, p.metricsChan
}

func (p *promProducer) Run() error {
	promLog.Info("Starting Prom producer garbage collection service")
	go p.janitor()

	// The below is borrowed wholesale from the http producer.
	// TODO (philipnrmn): rewrite this section to avoid use of the store
	go func() {
		promLog.Debug("Prom producer listening for incoming messages on metricsChan")
		for {
			// read messages off the channel,
			// and give them a unique name in the store
			message := <-p.metricsChan

			var name string
			switch message.Name {
			case producers.NodeMetricPrefix:
				name = joinMetricName(message.Name, message.Dimensions.MesosID)

			case producers.ContainerMetricPrefix:
				name = joinMetricName(message.Name, message.Dimensions.ContainerID)

			case producers.AppMetricPrefix:
				name = joinMetricName(message.Name, message.Dimensions.ContainerID)
			}

			for _, d := range message.Datapoints {
				p.writeObjectToStore(d, message, name)
			}
		}
	}()

	registry := prometheus.NewRegistry()
	registry.MustRegister(p)

	mux := http.NewServeMux()
	mux.Handle("/metrics", promhttp.HandlerFor(
		registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))

	addr := net.JoinHostPort("localhost", strconv.Itoa(p.config.Port))
	server := &http.Server{
		Addr:    addr,
		Handler: mux,
	}

	promLog.Infof("Serving Prometheus metrics on %s", addr)
	return server.ListenAndServe()
}

// Describe passes all the available stat descriptions to Prometheus; we
// send a single 'dummy' stat description, and then create our actual<commit_msg>Expose the default route, not loopback, for Prometheus<commit_after>// Copyright 2016 Mesosphere, Inc.
//
// 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 prometheus

import (
	"errors"
	"fmt"
	"math"
	"net/http"
	"regexp"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/dcos/dcos-go/store"
	"github.com/dcos/dcos-metrics/producers"
	prodHelpers "github.com/dcos/dcos-metrics/util/producers"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	illegalChars = regexp.MustCompile("\\W")
	promLog      = log.WithFields(log.Fields{"producer": "prometheus"})
)

// Config is a configuration for the Prom producer's behaviour
type Config struct {
	Port        int `yaml:"port"`
	CacheExpiry time.Duration
}

// promProducer implements both producers.MetricsProducer and
// prometheus.Producer
type promProducer struct {
	config             Config
	store              store.Store
	metricsChan        chan producers.MetricsMessage
	janitorRunInterval time.Duration
}

// New returns a prometheus producer and a channel for passing in metrics
func New(cfg Config) (producers.MetricsProducer, chan producers.MetricsMessage) {
	p := promProducer{
		config:             cfg,
		store:              store.New(),
		metricsChan:        make(chan producers.MetricsMessage),
		janitorRunInterval: 60 * time.Second,
	}
	return &p, p.metricsChan
}

func (p *promProducer) Run() error {
	promLog.Info("Starting Prom producer garbage collection service")
	go p.janitor()

	// The below is borrowed wholesale from the http producer.
	// TODO (philipnrmn): rewrite this section to avoid use of the store
	go func() {
		promLog.Debug("Prom producer listening for incoming messages on metricsChan")
		for {
			// read messages off the channel,
			// and give them a unique name in the store
			message := <-p.metricsChan

			var name string
			switch message.Name {
			case producers.NodeMetricPrefix:
				name = joinMetricName(message.Name, message.Dimensions.MesosID)

			case producers.ContainerMetricPrefix:
				name = joinMetricName(message.Name, message.Dimensions.ContainerID)

			case producers.AppMetricPrefix:
				name = joinMetricName(message.Name, message.Dimensions.ContainerID)
			}

			for _, d := range message.Datapoints {
				p.writeObjectToStore(d, message, name)
			}
		}
	}()

	registry := prometheus.NewRegistry()
	registry.MustRegister(p)

	mux := http.NewServeMux()
	mux.Handle("/metrics", promhttp.HandlerFor(
		registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))

	addr := fmt.Sprintf(":%d", p.config.Port)
	server := &http.Server{
		Addr:    addr,
		Handler: mux,
	}

	promLog.Infof("Serving Prometheus metrics on %s", addr)
	return server.ListenAndServe()
}

// Describe passes all the available stat descriptions to Prometheus; we
// send a single 'dummy' stat description, and then create our actual
{'fraction_non_alphanumeric': 0.1019842427779399, 'fraction_numerical': 0.0029180040852057193, 'mean_word_length': 3.7439446366782008, 'pattern_counts': {'":': 3, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5812158', 'n_tokens_mistral': 2213, 'n_tokens_neox': 2024, 'n_words': 628}