mirror of
https://github.com/ebrianne/adguard-exporter.git
synced 2024-12-22 17:37:33 +01:00
Added https support, added more metrics, cleaned up dns_queries types
This commit is contained in:
parent
7a328b11be
commit
1d6549a9e2
@ -17,22 +17,22 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
AdguardProtocol string `config:"adguard_protocol"`
|
AdguardProtocol string `config:"adguard_protocol"`
|
||||||
AdguardHostname string `config:"adguard_hostname"`
|
AdguardHostname string `config:"adguard_hostname"`
|
||||||
AdguardPort uint16 `config:"adguard_port"`
|
|
||||||
AdguardUsername string `config:"adguard_username"`
|
AdguardUsername string `config:"adguard_username"`
|
||||||
AdguardPassword string `config:"adguard_password"`
|
AdguardPassword string `config:"adguard_password"`
|
||||||
Port string `config:"port"`
|
ServerPort string `config:"server_port"`
|
||||||
Interval time.Duration `config:"interval"`
|
Interval time.Duration `config:"interval"`
|
||||||
|
LogLimit string `config:"log_limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultConfig() *Config {
|
func getDefaultConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
AdguardProtocol: "http",
|
AdguardProtocol: "http",
|
||||||
AdguardHostname: "127.0.0.1",
|
AdguardHostname: "127.0.0.1",
|
||||||
AdguardPort: 80,
|
|
||||||
AdguardUsername: "",
|
AdguardUsername: "",
|
||||||
AdguardPassword: "",
|
AdguardPassword: "",
|
||||||
Port: "9617",
|
ServerPort: "9617",
|
||||||
Interval: 10 * time.Second,
|
Interval: 10 * time.Second,
|
||||||
|
LogLimit: "1000",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.14
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/heetch/confita v0.9.2
|
github.com/heetch/confita v0.9.2
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2
|
||||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
|
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
|
||||||
)
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -105,6 +105,7 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
|
|||||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
@ -187,6 +188,7 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
|
||||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -1,47 +1,66 @@
|
|||||||
package adguard
|
package adguard
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ebrianne/adguard-exporter/internal/metrics"
|
"github.com/ebrianne/adguard-exporter/internal/metrics"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
port uint16
|
||||||
|
statusURLPattern = "%s://%s:%d/control/status"
|
||||||
statsURLPattern = "%s://%s:%d/control/stats"
|
statsURLPattern = "%s://%s:%d/control/stats"
|
||||||
logstatsURLPattern = "%s://%s:%d/control/querylog"
|
logstatsURLPattern = "%s://%s:%d/control/querylog?limit=%s&response_status=\"all\""
|
||||||
m map[string]int
|
m map[string]int
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client struct is a AdGuard client to request an instance of a AdGuard ad blocker.
|
// Client struct is a AdGuard client to request an instance of a AdGuard ad blocker.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
httpClient http.Client
|
httpClient http.Client
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
protocol string
|
logLimit string
|
||||||
hostname string
|
protocol string
|
||||||
port uint16
|
hostname string
|
||||||
b64password string
|
port uint16
|
||||||
|
username string
|
||||||
|
password string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient method initializes a new AdGuard client.
|
// NewClient method initializes a new AdGuard client.
|
||||||
func NewClient(protocol, hostname string, port uint16, b64password string, interval time.Duration) *Client {
|
func NewClient(protocol, hostname string, username, password string, interval time.Duration, logLimit string) *Client {
|
||||||
if protocol != "http" {
|
if protocol != "http" && protocol != "https" {
|
||||||
log.Printf("protocol %s is invalid. Must be http.", protocol)
|
log.Printf("protocol %s is invalid. Must be http or https.", protocol)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port = 80
|
||||||
|
if protocol == "https" {
|
||||||
|
port = 443
|
||||||
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
hostname: hostname,
|
hostname: hostname,
|
||||||
port: port,
|
port: port,
|
||||||
b64password: b64password,
|
username: username,
|
||||||
interval: interval,
|
password: password,
|
||||||
httpClient: http.Client{},
|
interval: interval,
|
||||||
|
logLimit: logLimit,
|
||||||
|
httpClient: http.Client{
|
||||||
|
Transport: &http.Transport{TLSClientConfig: GetTlsConfig()},
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,20 +69,30 @@ func NewClient(protocol, hostname string, port uint16, b64password string, inter
|
|||||||
func (c *Client) Scrape() {
|
func (c *Client) Scrape() {
|
||||||
for range time.Tick(c.interval) {
|
for range time.Tick(c.interval) {
|
||||||
|
|
||||||
//Get the general stats
|
allstats := c.getStatistics()
|
||||||
stats := c.getStatistics()
|
//Set the metrics
|
||||||
c.setMetrics(stats)
|
c.setMetrics(allstats.status, allstats.stats, allstats.logStats)
|
||||||
|
|
||||||
//Get the log stats
|
log.Printf("New tick of statistics: %s", allstats.stats.ToString())
|
||||||
logdata := c.getLogStatistics()
|
|
||||||
c.setLogMetrics(logdata)
|
|
||||||
|
|
||||||
log.Printf("New tick of statistics: %s", stats.ToString())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to set the general stats
|
// Function to set the prometheus metrics
|
||||||
func (c *Client) setMetrics(stats *Stats) {
|
func (c *Client) setMetrics(status *Status, stats *Stats, logstats *LogStats) {
|
||||||
|
//Status
|
||||||
|
var isRunning int = 0
|
||||||
|
if status.Running == true {
|
||||||
|
isRunning = 1
|
||||||
|
}
|
||||||
|
metrics.Running.WithLabelValues(c.hostname).Set(float64(isRunning))
|
||||||
|
|
||||||
|
var isProtected int = 0
|
||||||
|
if status.ProtectionEnabled == true {
|
||||||
|
isProtected = 1
|
||||||
|
}
|
||||||
|
metrics.ProtectionEnabled.WithLabelValues(c.hostname).Set(float64(isProtected))
|
||||||
|
|
||||||
|
//Stats
|
||||||
metrics.AvgProcessingTime.WithLabelValues(c.hostname).Set(float64(stats.AvgProcessingTime))
|
metrics.AvgProcessingTime.WithLabelValues(c.hostname).Set(float64(stats.AvgProcessingTime))
|
||||||
metrics.DnsQueries.WithLabelValues(c.hostname).Set(float64(stats.DnsQueries))
|
metrics.DnsQueries.WithLabelValues(c.hostname).Set(float64(stats.DnsQueries))
|
||||||
metrics.BlockedFiltering.WithLabelValues(c.hostname).Set(float64(stats.BlockedFiltering))
|
metrics.BlockedFiltering.WithLabelValues(c.hostname).Set(float64(stats.BlockedFiltering))
|
||||||
@ -88,51 +117,28 @@ func (c *Client) setMetrics(stats *Stats) {
|
|||||||
metrics.TopClients.WithLabelValues(c.hostname, source).Set(float64(value))
|
metrics.TopClients.WithLabelValues(c.hostname, source).Set(float64(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Function to get the general stats
|
//LogQuery
|
||||||
func (c *Client) getStatistics() *Stats {
|
|
||||||
log.Printf("Getting general statistics")
|
|
||||||
|
|
||||||
var stats Stats
|
|
||||||
statsURL := fmt.Sprintf(statsURLPattern, c.protocol, c.hostname, c.port)
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", statsURL, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("An error has occurred when creating HTTP statistics request ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.isUsingPassword() {
|
|
||||||
c.authenticateRequest(req)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.httpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("An error has occurred during login to Adguard: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to read Adguard statistics HTTP response", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(body, &stats)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to unmarshal Adguard statistics to statistics struct model", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &stats
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to get the log metrics
|
|
||||||
func (c *Client) setLogMetrics(logdata *LogData) {
|
|
||||||
m = make(map[string]int)
|
m = make(map[string]int)
|
||||||
for i := range logdata.Data {
|
logdata := logstats.Data
|
||||||
logstats := logdata.Data[i]
|
for i := range logdata {
|
||||||
if logstats.DNS != nil {
|
dnsanswer := logdata[i].Answer
|
||||||
for j := range logstats.DNS {
|
if dnsanswer != nil && len(dnsanswer) > 0 {
|
||||||
dnsType := logstats.DNS[j].Type
|
for j := range dnsanswer {
|
||||||
m[dnsType] += 1
|
var dnsType string
|
||||||
|
//Check the type of dnsanswer[j].Value, if string leave it be, otherwise get back the object to get the correct DNS type
|
||||||
|
switch v := dnsanswer[j].Value.(type) {
|
||||||
|
case string:
|
||||||
|
dnsType = dnsanswer[j].Type
|
||||||
|
m[dnsType] += 1
|
||||||
|
case map[string]interface{}:
|
||||||
|
var dns65 Type65
|
||||||
|
mapstructure.Decode(v, &dns65)
|
||||||
|
dnsType = "TYPE" + strconv.Itoa(dns65.Hdr.Rrtype)
|
||||||
|
m[dnsType] += 1
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,49 +147,87 @@ func (c *Client) setLogMetrics(logdata *LogData) {
|
|||||||
metrics.QueryTypes.WithLabelValues(c.hostname, key).Set(float64(value))
|
metrics.QueryTypes.WithLabelValues(c.hostname, key).Set(float64(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clear the map
|
||||||
for k := range m {
|
for k := range m {
|
||||||
delete(m, k)
|
delete(m, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to get the log stats
|
// Function to get the general stats
|
||||||
func (c *Client) getLogStatistics() *LogData {
|
func (c *Client) getStatistics() *AllStats {
|
||||||
log.Printf("Getting log statistics")
|
|
||||||
|
|
||||||
var logdata LogData
|
var status Status
|
||||||
logstatsURL := fmt.Sprintf(logstatsURLPattern, c.protocol, c.hostname, c.port)
|
statusURL := fmt.Sprintf(statusURLPattern, c.protocol, c.hostname, c.port)
|
||||||
|
body := c.MakeRequest(statusURL)
|
||||||
req, err := http.NewRequest("GET", logstatsURL, nil)
|
err := json.Unmarshal(body, &status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("An error has occurred when creating HTTP statistics request ", err)
|
log.Println("Unable to unmarshal Adguard log statistics to log statistics struct model", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stats Stats
|
||||||
|
statsURL := fmt.Sprintf(statsURLPattern, c.protocol, c.hostname, c.port)
|
||||||
|
body = c.MakeRequest(statsURL)
|
||||||
|
err = json.Unmarshal(body, &stats)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Unable to unmarshal Adguard statistics to statistics struct model", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var logstats LogStats
|
||||||
|
logstatsURL := fmt.Sprintf(logstatsURLPattern, c.protocol, c.hostname, c.port, c.logLimit)
|
||||||
|
body = c.MakeRequest(logstatsURL)
|
||||||
|
err = json.Unmarshal(body, &logstats)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Unable to unmarshal Adguard log statistics to log statistics struct model", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var allstats AllStats
|
||||||
|
allstats.status = &status
|
||||||
|
allstats.stats = &stats
|
||||||
|
allstats.logStats = &logstats
|
||||||
|
|
||||||
|
return &allstats
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) MakeRequest(url string) []byte {
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("An error has occurred when creating HTTP statistics request", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Host = "adguard.home-lab.io"
|
||||||
|
req.Header.Add("User-Agent", "Mozilla/5.0")
|
||||||
|
|
||||||
if c.isUsingPassword() {
|
if c.isUsingPassword() {
|
||||||
c.authenticateRequest(req)
|
c.authenticateRequest(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := c.httpClient.Do(req)
|
resp, err := c.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("An error has occurred during login to Adguard: %v", err)
|
log.Fatal("An error has occurred during login to Adguard", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
log.Fatal("An error occured in the request, Status Code ", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Unable to read Adguard statistics HTTP response", err)
|
log.Fatal("Unable to read Adguard statistics HTTP response", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(body, &logdata)
|
return body
|
||||||
if err != nil {
|
|
||||||
log.Println("Unable to unmarshal Adguard log statistics to log statistics struct model", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &logdata
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) isUsingPassword() bool {
|
func (c *Client) isUsingPassword() bool {
|
||||||
return len(c.b64password) > 0
|
return len(c.password) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) authenticateRequest(req *http.Request) {
|
func (c *Client) authenticateRequest(req *http.Request) {
|
||||||
req.Header.Add("Authorization", "Basic "+c.b64password)
|
req.SetBasicAuth(c.username, c.password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTlsConfig() *tls.Config {
|
||||||
|
return &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,25 @@ package adguard
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// SllStats struct containing all Adguard statistics structs
|
||||||
|
type AllStats struct {
|
||||||
|
status *Status
|
||||||
|
stats *Stats
|
||||||
|
logStats *LogStats
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status struct is the Adguard statistics JSON API corresponding model.
|
||||||
|
type Status struct {
|
||||||
|
Dhcp bool `json:"dhcp_available"`
|
||||||
|
DNSAddresses []string `json:"dns_addresses"`
|
||||||
|
DNSPort int `json:"dns_port"`
|
||||||
|
HttpPort int `json:"http_port"`
|
||||||
|
Language string `json:"language"`
|
||||||
|
ProtectionEnabled bool `json:"protection_enabled"`
|
||||||
|
Running bool `json:"running"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
// Stats struct is the Adguard statistics JSON API corresponding model.
|
// Stats struct is the Adguard statistics JSON API corresponding model.
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
AvgProcessingTime float64 `json:"avg_processing_time"`
|
AvgProcessingTime float64 `json:"avg_processing_time"`
|
||||||
@ -15,38 +34,51 @@ type Stats struct {
|
|||||||
TopClients []map[string]int `json:"top_clients"`
|
TopClients []map[string]int `json:"top_clients"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSAnswer struct from LogStats
|
type DNSHeader struct {
|
||||||
type DNSAnswer struct {
|
Name string `json:"Name"`
|
||||||
Ttl float64 `json:"ttl"`
|
Rrtype int `json:"Rrtype"`
|
||||||
Type string `json:"type"`
|
Class int `json:"Class"`
|
||||||
Value string `json:"value"`
|
TTL int `json:"Ttl"`
|
||||||
|
Rdlength int `json:"Rdlength"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSQuery struct from LogStats
|
type Type65 struct {
|
||||||
|
Hdr DNSHeader `json:"Hdr"`
|
||||||
|
RData string `json:"Rdata"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNSAnswer struct from LogData
|
||||||
|
type DNSAnswer struct {
|
||||||
|
TTL float64 `json:"ttl"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Value interface{} `json:"value"` // DNSAnswer struct can change sometimes... value:string or value: { "Hdr": { "Name":string, "Rrtype":int, "Class":int, "Ttl":int, "Rdlength":int }, "RData":string }
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNSQuery struct from LogData
|
||||||
type DNSQuery struct {
|
type DNSQuery struct {
|
||||||
Class string `json:"class"`
|
Class string `json:"class"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogStats struct, sub struct of LogData to collect the dns stats from the log
|
// LogData struct, sub struct of LogStats to collect the dns stats from the log
|
||||||
type LogStats struct {
|
type LogData struct {
|
||||||
DNS []DNSAnswer `json:"answer"`
|
Answer []DNSAnswer `json:"answer"`
|
||||||
DNSSec bool `json:"answer_dnssec"`
|
DNSSec bool `json:"answer_dnssec"`
|
||||||
Client string `json:"client"`
|
Client string `json:"client"`
|
||||||
ClientProto string `json:"client_proto"`
|
ClientProto string `json:"client_proto"`
|
||||||
Elapsed string `json:"elapsedMs"`
|
Elapsed string `json:"elapsedMs"`
|
||||||
Question DNSQuery `json:"question"`
|
Question DNSQuery `json:"question"`
|
||||||
Reason string `json:"reason"`
|
Reason string `json:"reason"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Time string `json:"time"`
|
Time string `json:"time"`
|
||||||
Upstream string `json:"upstream"`
|
Upstream string `json:"upstream"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogData struct for the Adguard log statistics JSON API corresponding model.
|
// LogStats struct for the Adguard log statistics JSON API corresponding model.
|
||||||
type LogData struct {
|
type LogStats struct {
|
||||||
Data []LogStats `json:"data"`
|
Data []LogData `json:"data"`
|
||||||
Oldest string `json:"oldest"`
|
Oldest string `json:"oldest"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToString method returns a string of the current statistics struct.
|
// ToString method returns a string of the current statistics struct.
|
||||||
|
@ -106,6 +106,26 @@ var (
|
|||||||
},
|
},
|
||||||
[]string{"hostname", "type"},
|
[]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"},
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProtectionEnable - 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.
|
// Init initializes all Prometheus metrics made available by AdGuard exporter.
|
||||||
@ -120,6 +140,8 @@ func Init() {
|
|||||||
initMetric("top_blocked_domains", TopBlocked)
|
initMetric("top_blocked_domains", TopBlocked)
|
||||||
initMetric("top_clients", TopClients)
|
initMetric("top_clients", TopClients)
|
||||||
initMetric("query_types", QueryTypes)
|
initMetric("query_types", QueryTypes)
|
||||||
|
initMetric("running", Running)
|
||||||
|
initMetric("protection_enabled", ProtectionEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initMetric(name string, metric *prometheus.GaugeVec) {
|
func initMetric(name string, metric *prometheus.GaugeVec) {
|
||||||
|
19
main.go
19
main.go
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -27,24 +26,14 @@ func main() {
|
|||||||
|
|
||||||
metrics.Init()
|
metrics.Init()
|
||||||
|
|
||||||
initAdguardClient(conf.AdguardProtocol, conf.AdguardHostname, conf.AdguardPort, conf.AdguardUsername, conf.AdguardPassword, conf.Interval)
|
initAdguardClient(conf.AdguardProtocol, conf.AdguardHostname, conf.AdguardUsername, conf.AdguardPassword, conf.Interval, conf.LogLimit)
|
||||||
initHttpServer(conf.Port)
|
initHttpServer(conf.ServerPort)
|
||||||
|
|
||||||
handleExitSignal()
|
handleExitSignal()
|
||||||
}
|
}
|
||||||
|
|
||||||
func basicAuth(username, password string) string {
|
func initAdguardClient(protocol, hostname string, username, password string, interval time.Duration, logLimit string) {
|
||||||
auth := username + ":" + password
|
client := adguard.NewClient(protocol, hostname, username, password, interval, logLimit)
|
||||||
return base64.StdEncoding.EncodeToString([]byte(auth))
|
|
||||||
}
|
|
||||||
|
|
||||||
func initAdguardClient(protocol, hostname string, port uint16, username, password string, interval time.Duration) {
|
|
||||||
b64password := ""
|
|
||||||
if len(username) > 0 && len(password) > 0 {
|
|
||||||
b64password = basicAuth(username, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
client := adguard.NewClient(protocol, hostname, port, b64password, interval)
|
|
||||||
go client.Scrape()
|
go client.Scrape()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user