多租户更改
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// PromExporter collects metrics in Prometheus format from a Tinode server.
|
||||
type PromExporter struct {
|
||||
address string
|
||||
timeout time.Duration
|
||||
namespace string
|
||||
|
||||
scraper *Scraper
|
||||
|
||||
up *prometheus.Desc
|
||||
version *prometheus.Desc
|
||||
topicsLive *prometheus.Desc
|
||||
topicsTotal *prometheus.Desc
|
||||
sessionsLive *prometheus.Desc
|
||||
sessionsTotal *prometheus.Desc
|
||||
|
||||
numGoroutines *prometheus.Desc
|
||||
|
||||
incomingMessagesWebsockTotal *prometheus.Desc
|
||||
outgoingMessagesWebsockTotal *prometheus.Desc
|
||||
|
||||
incomingMessagesLongpollTotal *prometheus.Desc
|
||||
outgoingMessagesLongpollTotal *prometheus.Desc
|
||||
|
||||
incomingMessagesGrpcTotal *prometheus.Desc
|
||||
outgoingMessagesGrpcTotal *prometheus.Desc
|
||||
|
||||
fileDownloadsTotal *prometheus.Desc
|
||||
fileUploadsTotal *prometheus.Desc
|
||||
|
||||
ctrlCodesTotal2xx *prometheus.Desc
|
||||
ctrlCodesTotal3xx *prometheus.Desc
|
||||
ctrlCodesTotal4xx *prometheus.Desc
|
||||
ctrlCodesTotal5xx *prometheus.Desc
|
||||
|
||||
clusterLeader *prometheus.Desc
|
||||
clusterSize *prometheus.Desc
|
||||
clusterNodesLive *prometheus.Desc
|
||||
malloced *prometheus.Desc
|
||||
requestLatencyMsCount *prometheus.Desc
|
||||
outgoingMessageBytesCount *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewPromExporter returns an initialized Prometheus exporter.
|
||||
func NewPromExporter(server, namespace string, timeout time.Duration, scraper *Scraper) *PromExporter {
|
||||
return &PromExporter{
|
||||
address: server,
|
||||
timeout: timeout,
|
||||
namespace: namespace,
|
||||
scraper: scraper,
|
||||
up: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "up"),
|
||||
"If tinode instance is reachable.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
version: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "version"),
|
||||
"The version of this tinode instance.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
topicsLive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "topics_live_count"),
|
||||
"Number of currently active topics.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
topicsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "topics_total"),
|
||||
"Total number of topics used during instance lifetime.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
sessionsLive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "sessions_live_count"),
|
||||
"Number of currently active sessions.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
sessionsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "sessions_total"),
|
||||
"Total number of sessions since instance start.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
numGoroutines: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "num_goroutines"),
|
||||
"Number of currently spawned goroutines.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
incomingMessagesWebsockTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "incoming_messages_websock_total"),
|
||||
"Total number of incoming messages via websocket.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
outgoingMessagesWebsockTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "outgoing_messages_websock_total"),
|
||||
"Total number of outgoiing messages via websocket.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
incomingMessagesLongpollTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "incoming_messages_longpoll_total"),
|
||||
"Total number of incoming messages via longpoll.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
outgoingMessagesLongpollTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "outgoing_messages_longpoll_total"),
|
||||
"Total number of outgoiing messages via longpoll.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
incomingMessagesGrpcTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "incoming_messages_grpc_total"),
|
||||
"Total number of incoming messages via grpc.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
outgoingMessagesGrpcTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "outgoing_messages_grpc_total"),
|
||||
"Total number of outgoiing messages via grpc.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
fileDownloadsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "file_downloads_total"),
|
||||
"Total number of large file downloads.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
fileUploadsTotal: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "file_uploads_total"),
|
||||
"Total number of large file uploads.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ctrlCodesTotal2xx: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "ctrl_codes_total_2xx"),
|
||||
"Total number of 2xx ctrl response codes.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ctrlCodesTotal3xx: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "ctrl_codes_total_3xx"),
|
||||
"Total number of 3xx ctrl response codes.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ctrlCodesTotal4xx: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "ctrl_codes_total_4xx"),
|
||||
"Total number of 4xx ctrl response codes.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
ctrlCodesTotal5xx: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "ctrl_codes_total_5xx"),
|
||||
"Total number of 5xx ctrl response codes.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
clusterLeader: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "cluster_leader"),
|
||||
"If this cluster node is the cluster leader.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
clusterSize: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "cluster_size"),
|
||||
"Configured number of cluster nodes.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
clusterNodesLive: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "cluster_nodes_live"),
|
||||
"Number of cluster nodes believed to be live by the current node.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
malloced: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "malloced_bytes"),
|
||||
"Number of bytes of memory allocated and in use.",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
requestLatencyMsCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "request_latency_ms_count"),
|
||||
"Request latency histogram (in ms).",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
outgoingMessageBytesCount: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(namespace, "", "outgoing_message_bytes"),
|
||||
"Response size histogram (in bytes).",
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Describe describes all the metrics exported by the memcached exporter. It
|
||||
// implements prometheus.Collector.
|
||||
func (e *PromExporter) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- e.up
|
||||
ch <- e.version
|
||||
ch <- e.topicsLive
|
||||
ch <- e.topicsTotal
|
||||
ch <- e.sessionsLive
|
||||
ch <- e.sessionsTotal
|
||||
ch <- e.numGoroutines
|
||||
|
||||
ch <- e.incomingMessagesWebsockTotal
|
||||
ch <- e.outgoingMessagesWebsockTotal
|
||||
|
||||
ch <- e.incomingMessagesLongpollTotal
|
||||
ch <- e.outgoingMessagesLongpollTotal
|
||||
|
||||
ch <- e.incomingMessagesGrpcTotal
|
||||
ch <- e.outgoingMessagesGrpcTotal
|
||||
|
||||
ch <- e.fileDownloadsTotal
|
||||
ch <- e.fileUploadsTotal
|
||||
|
||||
ch <- e.ctrlCodesTotal2xx
|
||||
ch <- e.ctrlCodesTotal3xx
|
||||
ch <- e.ctrlCodesTotal4xx
|
||||
ch <- e.ctrlCodesTotal5xx
|
||||
|
||||
ch <- e.clusterLeader
|
||||
ch <- e.clusterSize
|
||||
ch <- e.clusterNodesLive
|
||||
ch <- e.malloced
|
||||
|
||||
ch <- e.requestLatencyMsCount
|
||||
ch <- e.outgoingMessageBytesCount
|
||||
}
|
||||
|
||||
// Collect fetches statistics from the configured Tinode instance, and
|
||||
// delivers them as Prometheus metrics. It implements prometheus.Collector.
|
||||
func (e *PromExporter) Collect(ch chan<- prometheus.Metric) {
|
||||
up := float64(1)
|
||||
if stats, err := e.scraper.Scrape(); err != nil {
|
||||
log.Println("Failed to fetch or parse response", err)
|
||||
up = 0
|
||||
} else {
|
||||
if err := e.parseStats(ch, stats); err != nil {
|
||||
up = 0
|
||||
}
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, up)
|
||||
}
|
||||
|
||||
func (e *PromExporter) parseStats(ch chan<- prometheus.Metric, stats map[string]interface{}) error {
|
||||
err := firstError(
|
||||
e.parseAndUpdate(ch, e.version, prometheus.GaugeValue, stats, "Version"),
|
||||
e.parseAndUpdate(ch, e.topicsLive, prometheus.GaugeValue, stats, "LiveTopics"),
|
||||
e.parseAndUpdate(ch, e.topicsTotal, prometheus.CounterValue, stats, "TotalTopics"),
|
||||
e.parseAndUpdate(ch, e.sessionsLive, prometheus.GaugeValue, stats, "LiveSessions"),
|
||||
e.parseAndUpdate(ch, e.sessionsTotal, prometheus.CounterValue, stats, "TotalSessions"),
|
||||
e.parseAndUpdate(ch, e.numGoroutines, prometheus.GaugeValue, stats, "NumGoroutines"),
|
||||
|
||||
e.parseAndUpdate(ch, e.incomingMessagesWebsockTotal, prometheus.CounterValue, stats, "IncomingMessagesWebsockTotal"),
|
||||
e.parseAndUpdate(ch, e.outgoingMessagesWebsockTotal, prometheus.CounterValue, stats, "OutgoingMessagesWebsockTotal"),
|
||||
|
||||
e.parseAndUpdate(ch, e.incomingMessagesLongpollTotal, prometheus.CounterValue, stats, "IncomingMessagesLongpollTotal"),
|
||||
e.parseAndUpdate(ch, e.outgoingMessagesLongpollTotal, prometheus.CounterValue, stats, "OutgoingMessagesLongpollTotal"),
|
||||
|
||||
e.parseAndUpdate(ch, e.incomingMessagesGrpcTotal, prometheus.CounterValue, stats, "IncomingMessagesGrpcTotal"),
|
||||
e.parseAndUpdate(ch, e.outgoingMessagesGrpcTotal, prometheus.CounterValue, stats, "OutgoingMessagesGrpcTotal"),
|
||||
|
||||
e.parseAndUpdate(ch, e.fileDownloadsTotal, prometheus.CounterValue, stats, "FileDownloadsTotal"),
|
||||
e.parseAndUpdate(ch, e.fileUploadsTotal, prometheus.CounterValue, stats, "FileUploadsTotal"),
|
||||
|
||||
e.parseAndUpdate(ch, e.ctrlCodesTotal2xx, prometheus.CounterValue, stats, "CtrlCodesTotal2xx"),
|
||||
e.parseAndUpdate(ch, e.ctrlCodesTotal3xx, prometheus.CounterValue, stats, "CtrlCodesTotal3xx"),
|
||||
e.parseAndUpdate(ch, e.ctrlCodesTotal4xx, prometheus.CounterValue, stats, "CtrlCodesTotal4xx"),
|
||||
e.parseAndUpdate(ch, e.ctrlCodesTotal5xx, prometheus.CounterValue, stats, "CtrlCodesTotal5xx"),
|
||||
|
||||
e.parseAndUpdate(ch, e.clusterLeader, prometheus.GaugeValue, stats, "ClusterLeader"),
|
||||
e.parseAndUpdate(ch, e.clusterSize, prometheus.GaugeValue, stats, "TotalClusterNodes"),
|
||||
e.parseAndUpdate(ch, e.clusterNodesLive, prometheus.GaugeValue, stats, "LiveClusterNodes"),
|
||||
e.parseAndUpdate(ch, e.malloced, prometheus.GaugeValue, stats, "memstats.Alloc"),
|
||||
|
||||
e.parseAndUpdateHisto(ch, e.requestLatencyMsCount, stats, "RequestLatency"),
|
||||
e.parseAndUpdateHisto(ch, e.outgoingMessageBytesCount, stats, "OutgoingMessageSize"),
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *PromExporter) parseAndUpdate(ch chan<- prometheus.Metric, desc *prometheus.Desc, valueType prometheus.ValueType,
|
||||
stats map[string]interface{}, key string) error {
|
||||
v, err := parseNumeric(stats, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ch <- prometheus.MustNewConstMetric(desc, valueType, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *PromExporter) parseAndUpdateHisto(ch chan<- prometheus.Metric, desc *prometheus.Desc,
|
||||
stats map[string]interface{}, key string) error {
|
||||
h, err := parseHisto(stats, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ch <- prometheus.MustNewConstHistogram(desc, h.count, h.sum, h.buckets)
|
||||
return nil
|
||||
}
|
||||
|
||||
func firstError(errs ...error) error {
|
||||
for _, v := range errs {
|
||||
if v != nil {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user