Skip to content

Commit

Permalink
Add support for proxy headers
Browse files Browse the repository at this point in the history
Fixes #52
  • Loading branch information
boynux committed Oct 22, 2021
1 parent afadec8 commit bfdd0c6
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 29 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.9.4
1.10.0
35 changes: 22 additions & 13 deletions collector/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type CacheObjectClient struct {
hostname string
port int
basicAuthString string
headers map[string]string
headers []string
}

/*SquidClient provides functionality to fetch squid metrics */
Expand All @@ -40,24 +40,32 @@ func buildBasicAuthString(login string, password string) string {
}
}

type CacheObjectRequest struct {
Hostname string
Port int
Login string
Password string
Headers []string
}

/*NewCacheObjectClient initializes a new cache client */
func NewCacheObjectClient(hostname string, port int, login string, password string) *CacheObjectClient {
func NewCacheObjectClient(cor *CacheObjectRequest) *CacheObjectClient {
return &CacheObjectClient{
hostname,
port,
buildBasicAuthString(login, password),
map[string]string{},
cor.Hostname,
cor.Port,
buildBasicAuthString(cor.Login, cor.Password),
cor.Headers,
}
}

func readFromSquid(hostname string, port int, basicAuthString string, endpoint string) (*bufio.Reader, error) {
func readFromSquid(hostname string, port int, basicAuthString string, endpoint string, headers []string) (*bufio.Reader, error) {
conn, err := connect(hostname, port)

if err != nil {
return nil, err
}

r, err := get(conn, endpoint, basicAuthString)
r, err := get(conn, endpoint, basicAuthString, headers)

if err != nil {
return nil, err
Expand Down Expand Up @@ -91,7 +99,7 @@ func readLines(reader *bufio.Reader, lines chan<- string) {
func (c *CacheObjectClient) GetCounters() (types.Counters, error) {
var counters types.Counters

reader, err := readFromSquid(c.hostname, c.port, c.basicAuthString, "counters")
reader, err := readFromSquid(c.hostname, c.port, c.basicAuthString, "counters", c.headers)
if err != nil {
return nil, fmt.Errorf("error getting counters: %v", err)
}
Expand All @@ -115,7 +123,7 @@ func (c *CacheObjectClient) GetCounters() (types.Counters, error) {
func (c *CacheObjectClient) GetServiceTimes() (types.Counters, error) {
var serviceTimes types.Counters

reader, err := readFromSquid(c.hostname, c.port, c.basicAuthString, "service_times")
reader, err := readFromSquid(c.hostname, c.port, c.basicAuthString, "service_times", c.headers)
if err != nil {
return nil, fmt.Errorf("error getting service times: %v", err)
}
Expand All @@ -141,12 +149,13 @@ func connect(hostname string, port int) (net.Conn, error) {
return net.Dial("tcp", fmt.Sprintf("%s:%d", hostname, port))
}

func get(conn net.Conn, path string, basicAuthString string) (*http.Response, error) {
rBody := []string{
func get(conn net.Conn, path string, basicAuthString string, headers []string) (*http.Response, error) {
rBody := append(headers, []string{
fmt.Sprintf(requestProtocol, path),
"Host: localhost",
"User-Agent: squidclient/3.5.12",
}
}...)

if len(basicAuthString) > 0 {
rBody = append(rBody, "Proxy-Authorization: Basic "+basicAuthString)
}
Expand Down
34 changes: 24 additions & 10 deletions collector/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,35 @@ type Exporter struct {
up *prometheus.GaugeVec
}

type CollectorConfig struct {
Hostname string
Port int
Login string
Password string
Labels config.Labels
Headers []string
}

/*New initializes a new exporter */
func New(hostname string, port int, login string, password string, labels config.Labels) *Exporter {
counters = generateSquidCounters(labels.Keys)
func New(c *CollectorConfig) *Exporter {
counters = generateSquidCounters(c.Labels.Keys)
if ExtractServiceTimes {
serviceTimes = generateSquidServiceTimes(labels.Keys)
serviceTimes = generateSquidServiceTimes(c.Labels.Keys)
}
c := NewCacheObjectClient(hostname, port, login, password)

return &Exporter{
c,

hostname,
port,

labels,
NewCacheObjectClient(&CacheObjectRequest{
c.Hostname,
c.Port,
c.Login,
c.Password,
c.Headers,
}),

c.Hostname,
c.Port,

c.Labels,
prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Name: "up",
Expand Down
8 changes: 7 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
defaultSquidHostname = "localhost"
defaultSquidPort = 3128
defaultExtractServiceTimes = true
defaultUseProxyHeader = false
)

const (
Expand All @@ -27,6 +28,7 @@ const (
squidPasswordKey = "SQUID_PASSWORD"
squidPidfile = "SQUID_PIDFILE"
squidExtractServiceTimes = "SQUID_EXTRACTSERVICETIMES"
squidUseProxyHeader = "SQUID_USE_PRODXY_HEADER"
)

var (
Expand All @@ -41,7 +43,6 @@ type Labels struct {
/*Config configurations for exporter */
type Config struct {
ListenAddress string
ListenPort int
MetricPath string
Labels Labels
ExtractServiceTimes bool
Expand All @@ -51,6 +52,8 @@ type Config struct {
Login string
Password string
Pidfile string

UseProxyHeader bool
}

/*NewConfig creates a new config object from command line args */
Expand All @@ -77,6 +80,9 @@ func NewConfig() *Config {

flag.StringVar(&c.Pidfile, "squid-pidfile", loadEnvStringVar(squidPidfile, ""), "Optional path to the squid PID file for additional metrics")

flag.BoolVar(&c.UseProxyHeader, "squid-use-proxy-header",
loadEnvBoolVar(squidUseProxyHeader, defaultUseProxyHeader), "Use proxy headers when fetching metrics")

VersionFlag = flag.Bool("version", false, "Print the version and exit")

flag.Parse()
Expand Down
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ module github.com/boynux/squid-exporter
go 1.13

require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/pires/go-proxyproto v0.6.1 // indirect
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/common v0.29.0
github.com/prometheus/procfs v0.7.0 // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
github.com/prometheus/common v0.31.1
github.com/prometheus/procfs v0.7.3 // indirect
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect
google.golang.org/protobuf v1.27.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down Expand Up @@ -146,6 +148,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pires/go-proxyproto v0.6.1 h1:EBupykFmo22SDjv4fQVQd2J9NOoLPmyZA/15ldOGkPw=
github.com/pires/go-proxyproto v0.6.1/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand All @@ -165,12 +169,16 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE=
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.31.1 h1:d18hG4PkHnNAKNMOmFuXFaiY8Us0nird/2m60uS1AMs=
github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.0 h1:OQZ41sZU9XkRpzrz8/TD0EldH/Rwbddkdu5wDyUwzfE=
github.com/prometheus/procfs v0.7.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
Expand Down Expand Up @@ -305,6 +313,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
62 changes: 62 additions & 0 deletions helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"log"
"net"
"strconv"
"strings"

"github.com/boynux/squid-exporter/config"

proxyproto "github.com/pires/go-proxyproto"
)

func createProxyHeader(cfg *config.Config) string {
la := strings.Split(cfg.ListenAddress, ":")
if len(la) < 2 {
log.Printf("Cannot parse listen address (%s). Failed to create proxy header\n", cfg.ListenAddress)
return ""
}

spt, err := strconv.Atoi(la[1])
if err != nil {
log.Printf("Failed to create proxy header: %v\n", err.Error())
return ""
}

sip, err := net.LookupIP(la[0])
if err != nil {
log.Printf("Failed to create proxy header: %v\n", err.Error())
return ""
}

dip, err := net.LookupIP(cfg.SquidHostname)
if err != nil {
log.Printf("Failed to create proxy header: %v\n", err.Error())
return ""
}

ph := &proxyproto.Header{
Version: 1,
Command: proxyproto.PROXY,
TransportProtocol: proxyproto.TCPv4,
SourceAddr: &net.TCPAddr{
IP: sip[0],
Port: spt,
},

DestinationAddr: &net.TCPAddr{
IP: dip[0],
Port: cfg.SquidPort,
},
}
phs, err := ph.Format()

if err != nil {
log.Printf("Failed to create proxy header: %v\n", err.Error())
}

// proxyproto adds crlf to the end of the header string, but we will add this later
// we are triming it here.
return strings.TrimSuffix(string(phs), "\r\n")
}
15 changes: 14 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,21 @@ func main() {
}
collector.ExtractServiceTimes = cfg.ExtractServiceTimes

headers := []string{}

if cfg.UseProxyHeader {
headers = append(headers, createProxyHeader(cfg))
}

log.Println("Scraping metrics from", fmt.Sprintf("%s:%d", cfg.SquidHostname, cfg.SquidPort))
e := collector.New(cfg.SquidHostname, cfg.SquidPort, cfg.Login, cfg.Password, cfg.Labels)
e := collector.New(&collector.CollectorConfig{
Hostname: cfg.SquidHostname,
Port: cfg.SquidPort,
Login: cfg.Login,
Password: cfg.Password,
Labels: cfg.Labels,
Headers: headers,
})
prometheus.MustRegister(e)

if cfg.Pidfile != "" {
Expand Down

0 comments on commit bfdd0c6

Please sign in to comment.