多租户更改
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/prometheus/common/version"
|
||||
)
|
||||
|
||||
type monitoringService int
|
||||
|
||||
const (
|
||||
promService monitoringService = 1
|
||||
influxService monitoringService = 2
|
||||
)
|
||||
|
||||
const (
|
||||
// Minimum interval between InfluxDB pushes in seconds.
|
||||
minPushInterval = 10
|
||||
)
|
||||
|
||||
type promHTTPLogger struct{}
|
||||
|
||||
func (l promHTTPLogger) Println(v ...interface{}) {
|
||||
log.Println(v...)
|
||||
}
|
||||
|
||||
func parseMetricList(list string) []string {
|
||||
metrics := strings.Split(list, ",")
|
||||
for i, m := range metrics {
|
||||
metrics[i] = strings.TrimSpace(m)
|
||||
}
|
||||
return metrics
|
||||
}
|
||||
|
||||
// Build version number defined by the compiler:
|
||||
//
|
||||
// -ldflags "-X main.buildstamp=value_to_assign_to_buildstamp"
|
||||
//
|
||||
// Reported to clients in response to {hi} message.
|
||||
// For instance, to define the buildstamp as a timestamp of when the server was built add a
|
||||
// flag to compiler command line:
|
||||
//
|
||||
// -ldflags "-X main.buildstamp=`date -u '+%Y%m%dT%H:%M:%SZ'`"
|
||||
//
|
||||
// or to set it to git tag:
|
||||
//
|
||||
// -ldflags "-X main.buildstamp=`git describe --tags`"
|
||||
var buildstamp = "undef"
|
||||
|
||||
func main() {
|
||||
log.Printf("Tinode metrics exporter.")
|
||||
|
||||
var (
|
||||
serveFor = flag.String("serve_for", "influxdb",
|
||||
"Monitoring service to gather metrics for. Available: influxdb, prometheus.")
|
||||
tinodeAddr = flag.String("tinode_addr", "http://localhost:6060/stats/expvar",
|
||||
"Address of the Tinode instance to scrape.")
|
||||
listenAt = flag.String("listen_at", ":6222",
|
||||
"Host name and port to listen for incoming requests on.")
|
||||
metricList = flag.String("metric_list",
|
||||
"Version,LiveTopics,TotalTopics,LiveSessions,ClusterLeader,TotalClusterNodes,LiveClusterNodes,memstats.Alloc",
|
||||
"Comma-separated list of numeric metrics to scrape and export.")
|
||||
histoMetricList = flag.String("histo_metric_list",
|
||||
"RequestLatency,OutgoingMessageSize",
|
||||
"Comma-separated list of histogram metrics to scrape and export.")
|
||||
instance = flag.String("instance", "exporter",
|
||||
"Exporter instance name.")
|
||||
|
||||
// Prometheus-specific arguments.
|
||||
promNamespace = flag.String("prom_namespace", "tinode", "Prometheus namespace for metrics '<namespace>_...'")
|
||||
promMetricsPath = flag.String("prom_metrics_path", "/metrics", "Path under which to expose metrics for Prometheus scrapes.")
|
||||
promTimeout = flag.Int("prom_timeout", 15, "Tinode connection timeout in seconds in response to Prometheus scrapes.")
|
||||
|
||||
// InfluxDB-specific arguments.
|
||||
influxPushAddr = flag.String("influx_push_addr", "http://localhost:9999/write",
|
||||
"Address of InfluxDB target server where the data gets sent.")
|
||||
influxDBVersion = flag.String("influx_db_version", "1.7",
|
||||
"Version of InfluxDB (only 1.7 and 2.0 are supported).")
|
||||
influxOrganization = flag.String("influx_organization", "test",
|
||||
"InfluxDB organization to push metrics as.")
|
||||
influxBucket = flag.String("influx_bucket", "test",
|
||||
"InfluxDB storage bucket to store data in (used only in InfluxDB 2.0).")
|
||||
influxAuthToken = flag.String("influx_auth_token", "",
|
||||
"InfluxDB authentication token.")
|
||||
influxPushInterval = flag.Int("influx_push_interval", 30,
|
||||
"InfluxDB push interval in seconds.")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
var service monitoringService
|
||||
if *serveFor == "prometheus" {
|
||||
service = promService
|
||||
} else if *serveFor == "influxdb" {
|
||||
service = influxService
|
||||
} else {
|
||||
log.Fatal("Invalid monitoring service:" + *serveFor + "; must be either \"prometheus\" or \"influxdb\"")
|
||||
}
|
||||
// Validate flags.
|
||||
switch service {
|
||||
case promService:
|
||||
if *promMetricsPath == "/" {
|
||||
log.Fatal("Serving metrics from / is not supported")
|
||||
}
|
||||
case influxService:
|
||||
if *influxOrganization == "" {
|
||||
log.Fatal("Must specify --influx_organization")
|
||||
}
|
||||
if *influxAuthToken == "" {
|
||||
log.Fatal("Must specify --influx_auth_token")
|
||||
}
|
||||
if *influxBucket == "" {
|
||||
log.Fatal("Must specify --influx_bucket")
|
||||
}
|
||||
if *influxDBVersion != "1.7" && *influxDBVersion != "2.0" {
|
||||
log.Fatal("The --influx_db_version must be either 1.7 or 2.0")
|
||||
}
|
||||
if *influxPushInterval > 0 && *influxPushInterval < minPushInterval {
|
||||
*influxPushInterval = minPushInterval
|
||||
log.Println("The --influx_push_interval is too low, reset to", minPushInterval)
|
||||
}
|
||||
}
|
||||
|
||||
// Index page at web root.
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
var servingPath string
|
||||
switch service {
|
||||
case promService:
|
||||
servingPath = "<p>Prometheus exporter path: <a href='" + *promMetricsPath + "'>Metrics</a></p>"
|
||||
case influxService:
|
||||
servingPath = "<p>InfluxDB push path: <a href='/push'>Push</a></p>"
|
||||
}
|
||||
|
||||
w.Write([]byte(`<html><head><title>Tinode Exporter</title></head><body>
|
||||
<h1>Tinode Exporter</h1>
|
||||
<p>Server type` + *serveFor + `</p>` + servingPath +
|
||||
`<h2>Build</h2>
|
||||
<pre>` + version.Info() + ` ` + version.BuildContext() + `</pre>
|
||||
</body></html>`))
|
||||
})
|
||||
|
||||
metrics := parseMetricList(*metricList)
|
||||
histoMetrics := parseMetricList(*histoMetricList)
|
||||
scraper := Scraper{address: *tinodeAddr, simpleMetrics: metrics, histogramMetrics: histoMetrics}
|
||||
var serverTypeString string
|
||||
// Create exporters.
|
||||
switch service {
|
||||
case promService:
|
||||
serverTypeString = *serveFor
|
||||
promExporter := NewPromExporter(*tinodeAddr, *promNamespace, time.Duration(*promTimeout)*time.Second, &scraper)
|
||||
registry := prometheus.NewRegistry()
|
||||
registry.MustRegister(promExporter)
|
||||
http.Handle(*promMetricsPath,
|
||||
promhttp.InstrumentMetricHandler(
|
||||
registry,
|
||||
promhttp.HandlerFor(
|
||||
registry,
|
||||
promhttp.HandlerOpts{
|
||||
ErrorLog: &promHTTPLogger{},
|
||||
Timeout: time.Duration(*promTimeout) * time.Second,
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
case influxService:
|
||||
serverTypeString = fmt.Sprintf("%s, version %s", *serveFor, *influxDBVersion)
|
||||
influxDBExporter := NewInfluxDBExporter(*influxDBVersion, *influxPushAddr, *influxOrganization, *influxBucket,
|
||||
*influxAuthToken, *instance, &scraper)
|
||||
if *influxPushInterval > 0 {
|
||||
go func() {
|
||||
interval := time.Duration(*influxPushInterval) * time.Second
|
||||
ch := time.Tick(interval)
|
||||
for {
|
||||
if _, ok := <-ch; ok {
|
||||
if err := influxDBExporter.Push(); err != nil {
|
||||
log.Println("InfluxDB push failed:", err)
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
log.Println("InfluxDB push interval is zero. Will not push data automatically.")
|
||||
}
|
||||
// Forces a data push.
|
||||
http.HandleFunc("/push", func(w http.ResponseWriter, r *http.Request) {
|
||||
var msg string
|
||||
if err := influxDBExporter.Push(); err == nil {
|
||||
msg = "HTTP 200 OK"
|
||||
} else {
|
||||
msg = err.Error()
|
||||
}
|
||||
|
||||
w.Write([]byte(`<html><head><title>Tinode Push</title></head><body>
|
||||
<h1>Tinode Push</h1>
|
||||
<pre>` + msg + `</pre>
|
||||
</body></html>`))
|
||||
})
|
||||
}
|
||||
|
||||
log.Println("Reading Tinode expvar from", *tinodeAddr)
|
||||
log.Printf("Exporter running at %s. Server type %s", *listenAt, serverTypeString)
|
||||
log.Fatalln(http.ListenAndServe(*listenAt, nil))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user