mirror of
https://github.com/bakito/adguardhome-sync.git
synced 2024-09-20 14:56:13 +08:00
d6d8d2148d
* implement metrics
246 lines
6.7 KiB
Go
246 lines
6.7 KiB
Go
package metrics
|
|
|
|
import (
|
|
"github.com/bakito/adguardhome-sync/pkg/client/model"
|
|
"github.com/bakito/adguardhome-sync/pkg/log"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"golang.org/x/exp/constraints"
|
|
)
|
|
|
|
var (
|
|
l = log.GetLogger("metrics")
|
|
|
|
// avgProcessingTime - Average processing time for a DNS query
|
|
avgProcessingTime = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "avg_processing_time",
|
|
Namespace: "adguard",
|
|
Help: "This represent the average processing time for a DNS query in s",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// dnsQueries - Number of DNS queries
|
|
dnsQueries = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "num_dns_queries",
|
|
Namespace: "adguard",
|
|
Help: "Number of DNS queries",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// blockedFiltering - Number of DNS queries blocked
|
|
blockedFiltering = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "num_blocked_filtering",
|
|
Namespace: "adguard",
|
|
Help: "This represent the number of domains blocked",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// parentalFiltering - Number of DNS queries replaced by parental control
|
|
parentalFiltering = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "num_replaced_parental",
|
|
Namespace: "adguard",
|
|
Help: "This represent the number of domains blocked (parental)",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// safeBrowsingFiltering - Number of DNS queries replaced by safe browsing
|
|
safeBrowsingFiltering = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "num_replaced_safebrowsing",
|
|
Namespace: "adguard",
|
|
Help: "This represent the number of domains blocked (safe browsing)",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// safeSearchFiltering - Number of DNS queries replaced by safe search
|
|
safeSearchFiltering = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "num_replaced_safesearch",
|
|
Namespace: "adguard",
|
|
Help: "This represent the number of domains blocked (safe search)",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// topQueries - The number of top queries
|
|
topQueries = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "top_queried_domains",
|
|
Namespace: "adguard",
|
|
Help: "This represent the top queried domains",
|
|
},
|
|
[]string{"hostname", "domain"},
|
|
)
|
|
|
|
// topBlocked - The number of top domains blocked
|
|
topBlocked = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "top_blocked_domains",
|
|
Namespace: "adguard",
|
|
Help: "This represent the top bloacked domains",
|
|
},
|
|
[]string{"hostname", "domain"},
|
|
)
|
|
|
|
// topClients - The number of top clients
|
|
topClients = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "top_clients",
|
|
Namespace: "adguard",
|
|
Help: "This represent the top clients",
|
|
},
|
|
[]string{"hostname", "client"},
|
|
)
|
|
|
|
// queryTypes - The type of DNS Queries (A, AAAA...)
|
|
queryTypes = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "query_types",
|
|
Namespace: "adguard",
|
|
Help: "This represent the DNS query types",
|
|
},
|
|
[]string{"hostname", "type"},
|
|
)
|
|
|
|
// running - If Adguard is running
|
|
running = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "running",
|
|
Namespace: "adguard",
|
|
Help: "This represent if Adguard is running",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
|
|
// protectionEnabled - If Adguard protection is enabled
|
|
protectionEnabled = prometheus.NewGaugeVec(
|
|
prometheus.GaugeOpts{
|
|
Name: "protection_enabled",
|
|
Namespace: "adguard",
|
|
Help: "This represent if Adguard Protection is enabled",
|
|
},
|
|
[]string{"hostname"},
|
|
)
|
|
)
|
|
|
|
// Init initializes all Prometheus metrics made available by AdGuard exporter.
|
|
func Init() {
|
|
initMetric("avg_processing_time", avgProcessingTime)
|
|
initMetric("num_dns_queries", dnsQueries)
|
|
initMetric("num_blocked_filtering", blockedFiltering)
|
|
initMetric("num_replaced_parental", parentalFiltering)
|
|
initMetric("num_replaced_safebrowsing", safeBrowsingFiltering)
|
|
initMetric("num_replaced_safesearch", safeSearchFiltering)
|
|
initMetric("top_queried_domains", topQueries)
|
|
initMetric("top_blocked_domains", topBlocked)
|
|
initMetric("top_clients", topClients)
|
|
initMetric("query_types", queryTypes)
|
|
initMetric("running", running)
|
|
initMetric("protection_enabled", protectionEnabled)
|
|
}
|
|
|
|
func initMetric(name string, metric *prometheus.GaugeVec) {
|
|
prometheus.MustRegister(metric)
|
|
l.With("name", name).Info("New Prometheus metric registered")
|
|
}
|
|
|
|
func Update(ims ...InstanceMetrics) {
|
|
for _, im := range ims {
|
|
update(im)
|
|
}
|
|
|
|
l.Debug("updated")
|
|
}
|
|
|
|
func update(im InstanceMetrics) {
|
|
// Status
|
|
var isRunning int = 0
|
|
if im.Status.Running {
|
|
isRunning = 1
|
|
}
|
|
running.WithLabelValues(im.HostName).Set(float64(isRunning))
|
|
|
|
var isProtected int = 0
|
|
if im.Status.ProtectionEnabled {
|
|
isProtected = 1
|
|
}
|
|
protectionEnabled.WithLabelValues(im.HostName).Set(float64(isProtected))
|
|
|
|
// Stats
|
|
avgProcessingTime.WithLabelValues(im.HostName).Set(safeMetric(im.Stats.AvgProcessingTime))
|
|
dnsQueries.WithLabelValues(im.HostName).Set(safeMetric(im.Stats.NumDnsQueries))
|
|
blockedFiltering.WithLabelValues(im.HostName).Set(safeMetric(im.Stats.NumBlockedFiltering))
|
|
parentalFiltering.WithLabelValues(im.HostName).Set(safeMetric(im.Stats.NumReplacedParental))
|
|
safeBrowsingFiltering.WithLabelValues(im.HostName).Set(safeMetric(im.Stats.NumReplacedSafebrowsing))
|
|
safeSearchFiltering.WithLabelValues(im.HostName).Set(safeMetric(im.Stats.NumReplacedSafesearch))
|
|
|
|
if im.Stats.TopQueriedDomains != nil {
|
|
for _, tq := range *im.Stats.TopQueriedDomains {
|
|
for domain, value := range tq.AdditionalProperties {
|
|
topQueries.WithLabelValues(im.HostName, domain).Set(float64(value))
|
|
}
|
|
}
|
|
}
|
|
if im.Stats.TopBlockedDomains != nil {
|
|
for _, tb := range *im.Stats.TopBlockedDomains {
|
|
for domain, value := range tb.AdditionalProperties {
|
|
topBlocked.WithLabelValues(im.HostName, domain).Set(float64(value))
|
|
}
|
|
}
|
|
}
|
|
if im.Stats.TopClients != nil {
|
|
for _, tc := range *im.Stats.TopClients {
|
|
for source, value := range tc.AdditionalProperties {
|
|
topClients.WithLabelValues(im.HostName, source).Set(float64(value))
|
|
}
|
|
}
|
|
}
|
|
|
|
// LogQuery
|
|
m := make(map[string]int)
|
|
if im.QueryLog != nil && im.QueryLog.Data != nil {
|
|
logdata := *im.QueryLog.Data
|
|
for _, ld := range logdata {
|
|
if ld.Answer != nil {
|
|
dnsanswer := *ld.Answer
|
|
if len(dnsanswer) > 0 {
|
|
for _, dnsa := range dnsanswer {
|
|
dnsType := *dnsa.Type
|
|
m[dnsType] += 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for key, value := range m {
|
|
queryTypes.WithLabelValues(im.HostName, key).Set(float64(value))
|
|
}
|
|
}
|
|
|
|
type InstanceMetrics struct {
|
|
HostName string
|
|
Status *model.ServerStatus
|
|
Stats *model.Stats
|
|
QueryLog *model.QueryLog
|
|
}
|
|
|
|
func safeMetric[T Number](v *T) float64 {
|
|
if v == nil {
|
|
return 0
|
|
}
|
|
return float64(*v)
|
|
}
|
|
|
|
type Number interface {
|
|
constraints.Float | constraints.Integer
|
|
}
|