pax_global_header00006660000000000000000000000064136056214570014523gustar00rootroot0000000000000052 comment=1cbf5e536d6275e21df39de8d31c4f0ec90b0b99 prometheus-squid-exporter-1.8.2+ds/000077500000000000000000000000001360562145700173215ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/.github/000077500000000000000000000000001360562145700206615ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/.github/ISSUE_TEMPLATE/000077500000000000000000000000001360562145700230445ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000007031360562145700255360ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: **Expected behavior** A clear and concise description of what you expected to happen. **OS (please complete the following information):** - OS: [e.g. Ubuntu] - Version [e.g. v0.4] **Additional context** Add any other context about the problem here. prometheus-squid-exporter-1.8.2+ds/.gitignore000066400000000000000000000000251360562145700213060ustar00rootroot00000000000000bin/* squid-exporter prometheus-squid-exporter-1.8.2+ds/.travis.yml000066400000000000000000000014671360562145700214420ustar00rootroot00000000000000language: go deploy: provider: releases api_key: secure: "iumDvYQyMvTdD2AHxFDIVpixE7GK5VhCDo4wqkH9s3lmLIXTw2LPgUq4tx73aV7PGKskvWpILq87bh6t1AlFYnk/0VF12zMQWujsvh/iSdyCVvraobhYjiwQyHkFSoTBZ0xpwVImqRhF/AcAP/zwCTAGZMZMSm8xZucqkPaj02o8xgCKgPyDwv/IPo2Iiy6LmLbYeWBFScMtEyPqxjoKL5lL3b6e1W0esbJvPhzWQvTn2IBB8Ntm5hBBcqzG+/K3dNLpRTefX1xJlo2c5ZFT+KPFqIvNviNne7OhlX+NGZ33jUXVDPF4Lk6jLr49QnlTbqz8CKp3QzlpzOs+eF+2BBl5Gc1vJ0thmZ/TEujYD0rGzwDQ6nCVC6/VBbPiYhmQigk+AYFfxgutzHIfnuuySEoi5KOLNINtppwUTYjuxUv+YkQTUswCTa2MBoL0ZfAkdyrbBkGRL78sPRDRLK6KFXqz0Bk+pQdS0PebNclqaPnEML1jQYdRBgBQ0uFGcfOLkmIDr/L7icSif4uDrwaE1GnhHeloUOlaTSc63BSw1GdC+iYiGi8/TNg0Nw5co+M6Ii/Wuea9ngayAhVgNC64hV1giQEPPTfuS3EAxBf4ytybuqH3p+VtqD3ES97OqGGup4PHHQVPEdc6bzsD2aThLCeqpS/O9By9PiQcku+L+oo=" file: bin/squid-exporter skip_cleanup: true on: tags: true prometheus-squid-exporter-1.8.2+ds/CODE_OF_CONDUCT.md000066400000000000000000000062151360562145700221240ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at boynux@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ prometheus-squid-exporter-1.8.2+ds/Dockerfile000066400000000000000000000007461360562145700213220ustar00rootroot00000000000000FROM golang:alpine as builder WORKDIR /go/src/github.com/boynux/squid-exporter COPY . . # Compile the binary statically, so it can be run without libraries. RUN CGO_ENABLED=0 GOOS=linux go install -a -ldflags '-extldflags "-s -w -static"' . FROM scratch COPY --from=builder /go/bin/squid-exporter /usr/local/bin/squid-exporter # Allow /etc/hosts to be used for DNS COPY --from=builder /etc/nsswitch.conf /etc/nsswitch.conf EXPOSE 9301 ENTRYPOINT ["/usr/local/bin/squid-exporter"] prometheus-squid-exporter-1.8.2+ds/LICENSE000066400000000000000000000020561360562145700203310ustar00rootroot00000000000000MIT License Copyright (c) 2017 Mohammad Arab Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. prometheus-squid-exporter-1.8.2+ds/Makefile000066400000000000000000000014071360562145700207630ustar00rootroot00000000000000.PHONY: all clean all: test build EXE = ./bin/squid-exporter SRC = $(shell find ./ -type f -name '*.go') VERSION ?= $(shell cat VERSION) REVISION = $(shell git rev-parse HEAD) BRANCH = $(shell git rev-parse --abbrev-ref HEAD) LDFLAGS = -extldflags "-s -w -static" \ -X github.com/boynux/squid-exporter/vendor/github.com/prometheus/common/version.Version=$(VERSION) \ -X github.com/boynux/squid-exporter/vendor/github.com/prometheus/common/version.Revision=$(REVISION) \ -X github.com/boynux/squid-exporter/vendor/github.com/prometheus/common/version.Branch=$(BRANCH) $(EXE): $(SRC) CGO_ENABLED=0 GOOS=linux go build -a -ldflags '$(LDFLAGS)' -o $(EXE) . test: go test -v ./... build: $(EXE) docker: docker build -t squid-exporter . clean: rm -f $(EXE) prometheus-squid-exporter-1.8.2+ds/README.md000066400000000000000000000066401360562145700206060ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/boynux/squid-exporter.svg?branch=master)](https://travis-ci.org/boynux/squid-exporter) [![Go Report Card](https://goreportcard.com/badge/github.com/boynux/squid-exporter)](https://goreportcard.com/report/github.com/boynux/squid-exporter) [![Maintainability](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/boynux/squid-exporter) Squid Prometheus exporter -------------------------- Exports squid metrics in Prometheus format **NOTE**: From release 1.0 metric names and some parameters has changed. Make sure you check the docs and update your deployments accordingly! New ----- * Using environment variables to configure the exporter * Adding custom labels to metrics Usage: ------ Simple usage: squid-exporter -squid-hostname "localhost" -squid-port 3128 [Configure Prometheus](https://github.com/boynux/squid-exporter/blob/master/prometheus/prometheus.yml) to scrape metrics from `localhost:9301/metrics` - job_name: squid # squid-exporter is installed, grab stats about the local # squid instance. target_groups: - targets: ['localhost:9301'] To get all the parameteres, command line arguments always override default and environment variables configs: squid-exporter -help The following environment variables can be used to override default parameters: ``` SQUID_EXPORTER_LISTEN SQUID_EXPORTER_METRICS_PATH SQUID_HOSTNAME SQUID_PORT SQUID_LOGIN SQUID_PASSWORD ``` Usage with docker: ------ Basic setup assuming Squid is running on the same machine: docker run --net=host -d boynux/squid-exporter Setup with Squid running on a different host docker run -p 9301:9301 -d boynux/squid-exporter -squid-hostname "192.168.0.2" -squid-port 3128 -listen ":9301" With environment variables docker run -p 9301:9301 -d -e SQUID_PORT="3128" -e SQUID_HOSTNAME="192.168.0.2" -e SQUID_EXPORTER_LISTEN=":9301" boynux/squid-exporter Build: -------- This project is written in Go, so all the usual methods for building (or cross compiling) a Go application would work. If you are not very familiar with Go you can download the binary from [releases](https://github.com/boynux/squid-exporter/releases). Or build it for your OS: `go install https://github.com/boynux/squid-exporter` then you can find the binary in: `$GOPATH/bin/squid-exporter` Features: --------- - [ ] Expose Squid counters - [x] Client HTTP - [x] Server HTTP - [x] Server ALL - [x] Server FTP - [x] Server Other - [ ] ICP - [ ] CD - [x] Swap - [ ] Page Faults - [ ] Others - [ ] Histograms - [ ] Other metrics - [x] Squid Authentication (Basic Auth) FAQ: -------- - Q: Metrics are not reported by exporter - A: That usually means the exporter cannot reach squid server or the config manager permissions are not set corretly. To debug and mitigate: - First make sure the exporter service can reach to squid server IP Address (you can use telnet to test that) - Make sure you allow exporter to query the squid server in config you will need something like this (`172.20.0.0/16` is the network for exporter, you can also use a single IP if needed): ``` #http_access allow manager localhost acl prometheus src 172.20.0.0/16 http_access allow manager prometheus ``` Contribution: ------------- Pull request and issues are very welcome. Copyright: ---------- [MIT License](https://opensource.org/licenses/MIT) prometheus-squid-exporter-1.8.2+ds/VERSION000066400000000000000000000000041360562145700203630ustar00rootroot000000000000001.8 prometheus-squid-exporter-1.8.2+ds/_config.yml000066400000000000000000000000331360562145700214440ustar00rootroot00000000000000theme: jekyll-theme-minimalprometheus-squid-exporter-1.8.2+ds/collector/000077500000000000000000000000001360562145700213075ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/collector/client.go000066400000000000000000000057651360562145700231310ustar00rootroot00000000000000package collector import ( "bufio" "encoding/base64" "errors" "fmt" "github.com/boynux/squid-exporter/types" "io" "log" "net" "net/http" "strconv" "strings" ) /*CacheObjectClient holds information about squid manager */ type CacheObjectClient struct { hostname string port int basicAuthString string headers map[string]string } /*SquidClient provides functionality to fetch squid metrics */ type SquidClient interface { GetCounters() (types.Counters, error) } const ( requestProtocol = "GET cache_object://localhost/%s HTTP/1.0" ) func buildBasicAuthString(login string, password string) string { if len(login) == 0 { return "" } else { return base64.StdEncoding.EncodeToString([]byte(login + ":" + password)) } } /*NewCacheObjectClient initializes a new cache client */ func NewCacheObjectClient(hostname string, port int, login string, password string) *CacheObjectClient { return &CacheObjectClient{ hostname, port, buildBasicAuthString(login, password), map[string]string{}, } } /*GetCounters fetches counters from squid cache manager */ func (c *CacheObjectClient) GetCounters() (types.Counters, error) { conn, err := connect(c.hostname, c.port) if err != nil { return types.Counters{}, err } r, err := get(conn, "counters", c.basicAuthString) if err != nil { return nil, err } if r.StatusCode != 200 { return nil, fmt.Errorf("Non success code %d while fetching metrics", r.StatusCode) } var counters types.Counters // TODO: Move to another func reader := bufio.NewReader(r.Body) for { line, err := reader.ReadString('\n') if err == io.EOF { break } if err != nil { return nil, err } c, err := decodeCounterStrings(line) if err != nil { log.Println(err) } else { counters = append(counters, c) } } return counters, err } 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{ fmt.Sprintf(requestProtocol, path), "Host: localhost", "User-Agent: squidclient/3.5.12", } if len(basicAuthString) > 0 { rBody = append(rBody, "Proxy-Authorization: Basic "+basicAuthString) } rBody = append(rBody, "Accept: */*", "\r\n") request := strings.Join(rBody, "\r\n") fmt.Fprintf(conn, request) return http.ReadResponse(bufio.NewReader(conn), nil) } func decodeCounterStrings(line string) (types.Counter, error) { if equal := strings.Index(line, "="); equal >= 0 { if key := strings.TrimSpace(line[:equal]); len(key) > 0 { value := "" if len(line) > equal { value = strings.TrimSpace(line[equal+1:]) } // Remove additional formating string from `sample_time` if slices := strings.Split(value, " "); len(slices) > 0 { value = slices[0] } if i, err := strconv.ParseFloat(value, 64); err == nil { return types.Counter{key, i}, nil } } } return types.Counter{}, errors.New("could not parse line: " + line) } prometheus-squid-exporter-1.8.2+ds/collector/counters.go000066400000000000000000000055241360562145700235060ustar00rootroot00000000000000package collector import ( "fmt" "strings" "github.com/prometheus/client_golang/prometheus" ) type squidCounter struct { Section string Counter string Suffix string Description string } var squidCounters = []squidCounter{ {"client_http", "requests", "total", "The total number of client requests"}, {"client_http", "hits", "total", "The total number of client cache hits"}, {"client_http", "errors", "total", "The total number of client http errors"}, {"client_http", "kbytes_in", "kbytes_total", "The total number of client kbytes received"}, {"client_http", "kbytes_out", "kbytes_total", "The total number of client kbytes transferred"}, {"client_http", "hit_kbytes_out", "bytes_total", "The total number of client kbytes cache hit"}, {"server.http", "requests", "total", "The total number of server http requests"}, {"server.http", "errors", "total", "The total number of server http errors"}, {"server.http", "kbytes_in", "kbytes_total", "The total number of server http kbytes received"}, {"server.http", "kbytes_out", "kbytes_total", "The total number of server http kbytes transferred"}, {"server.all", "requests", "total", "The total number of server all requests"}, {"server.all", "errors", "total", "The total number of server all errors"}, {"server.all", "kbytes_in", "kbytes_total", "The total number of server kbytes received"}, {"server.all", "kbytes_out", "kbytes_total", "The total number of server kbytes transferred"}, {"server.ftp", "requests", "total", "The total number of server ftp requests"}, {"server.ftp", "errors", "total", "The total number of server ftp errors"}, {"server.ftp", "kbytes_in", "kbytes_total", "The total number of server ftp kbytes received"}, {"server.ftp", "kbytes_out", "kbytes_total", "The total number of server ftp kbytes transferred"}, {"server.other", "requests", "total", "The total number of server other requests"}, {"server.other", "errors", "total", "The total number of server other errors"}, {"server.other", "kbytes_in", "kbytes_total", "The total number of server other kbytes received"}, {"server.other", "kbytes_out", "kbytes_total", "The total number of server other kbytes transferred"}, {"swap", "ins", "total", "The number of objects read from disk"}, {"swap", "outs", "total", "The number of objects saved to disk"}, {"swap", "files_cleaned", "total", "The number of orphaned cache files removed by the periodic cleanup procedure"}, } func generateSquidCounters(labels []string) descMap { counters := descMap{} for i := range squidCounters { counter := squidCounters[i] counters[fmt.Sprintf("%s.%s", counter.Section, counter.Counter)] = prometheus.NewDesc( prometheus.BuildFQName(namespace, strings.Replace(counter.Section, ".", "_", -1), fmt.Sprintf("%s_%s", counter.Counter, counter.Suffix)), counter.Description, labels, nil, ) } return counters } prometheus-squid-exporter-1.8.2+ds/collector/metrics.go000066400000000000000000000033221360562145700233040ustar00rootroot00000000000000package collector import ( "log" "time" "github.com/boynux/squid-exporter/config" "github.com/prometheus/client_golang/prometheus" ) type descMap map[string]*prometheus.Desc const ( namespace = "squid" timeout = 10 * time.Second ) var ( counters descMap ) /*Exporter entry point to squid exporter */ type Exporter struct { client SquidClient hostname string port int labels config.Labels up *prometheus.GaugeVec } /*New initializes a new exporter */ func New(hostname string, port int, login string, password string, labels config.Labels) *Exporter { counters = generateSquidCounters(labels.Keys) c := NewCacheObjectClient(hostname, port, login, password) return &Exporter{ c, hostname, port, labels, prometheus.NewGaugeVec(prometheus.GaugeOpts{ Namespace: namespace, Name: "up", Help: "Was the last query of squid successful?", }, []string{"host"}), } } // Describe describes all the metrics ever exported by the ECS exporter. It // implements prometheus.Collector. func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { e.up.Describe(ch) for _, v := range counters { ch <- v } } /*Collect fetches metrics from squid manager and pushes them to promethus */ func (e *Exporter) Collect(c chan<- prometheus.Metric) { insts, err := e.client.GetCounters() if err == nil { e.up.With(prometheus.Labels{"host": e.hostname}).Set(1) for i := range insts { if d, ok := counters[insts[i].Key]; ok { c <- prometheus.MustNewConstMetric(d, prometheus.CounterValue, insts[i].Value, e.labels.Values...) } } } else { e.up.With(prometheus.Labels{"host": e.hostname}).Set(0) log.Println("Could not fetch metrics from squid instance: ", err) } e.up.Collect(c) } prometheus-squid-exporter-1.8.2+ds/config/000077500000000000000000000000001360562145700205665ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/config/config.go000066400000000000000000000056751360562145700223770ustar00rootroot00000000000000package config import ( "fmt" "flag" "log" "os" "strconv" "strings" ) const ( defaultListenAddress = "127.0.0.1:9301" defaultListenPort = 9301 defaultMetricsPath = "/metrics" defaultSquidHostname = "localhost" defaultSquidPort = 3128 ) const ( squidExporterListenKey = "SQUID_EXPORTER_LISTEN" squidExporterMetricsPathKey = "SQUID_EXPORTER_METRICS_PATH" squidHostnameKey = "SQUID_HOSTNAME" squidPortKey = "SQUID_PORT" squidLoginKey = "SQUID_LOGIN" squidPasswordKey = "SQUID_PASSWORD" ) var ( VersionFlag *bool ) type Labels struct { Keys []string Values []string } /*Config configurations for exporter */ type Config struct { ListenAddress string ListenPort int MetricPath string Labels Labels SquidHostname string SquidPort int Login string Password string } /*NewConfig creates a new config object from command line args */ func NewConfig() *Config { c := &Config{} flag.StringVar(&c.ListenAddress, "listen", loadEnvStringVar(squidExporterListenKey, defaultListenAddress), "Address and Port to bind exporter, in host:port format") flag.StringVar(&c.MetricPath, "metrics-path", loadEnvStringVar(squidExporterMetricsPathKey, defaultMetricsPath), "Metrics path to expose prometheus metrics") flag.Var(&c.Labels, "label", "Custom metrics to attach to metrics, use -label multiple times for each additional label") flag.StringVar(&c.SquidHostname, "squid-hostname", loadEnvStringVar(squidHostnameKey, defaultSquidHostname), "Squid hostname") flag.IntVar(&c.SquidPort, "squid-port", loadEnvIntVar(squidPortKey, defaultSquidPort), "Squid port to read metrics") flag.StringVar(&c.Login, "squid-login", loadEnvStringVar(squidLoginKey, ""), "Login to squid service") flag.StringVar(&c.Password, "squid-password", loadEnvStringVar(squidPasswordKey, ""), "Password to squid service") VersionFlag = flag.Bool("version", false, "Print the version and exit") flag.Parse() return c } func loadEnvStringVar(key, def string) string { val := os.Getenv(key) if val == "" { return def } return val } func loadEnvIntVar(key string, def int) int { valStr := os.Getenv(key) if valStr != "" { val, err := strconv.ParseInt(valStr, 0, 32) if err == nil { return int(val) } log.Printf("Error parsing %s='%s'. Integer value expected", key, valStr) } return def } func (l *Labels) String() string { var lbls []string for i := range l.Keys { lbls = append(lbls, l.Keys[i] + "=" + l.Values[i]) } return strings.Join(lbls, ", ") } func (l *Labels) Set(value string) error { args := strings.Split(value, "=") if len(args) != 2 || len(args[1]) < 1 { return fmt.Errorf("Label must be in 'key=value' format") } for _, key := range l.Keys { if key == args[0] { return fmt.Errorf("Labels must be distinct, found duplicated key %s", args[0]) } } l.Keys = append(l.Keys, args[0]) l.Values = append(l.Values, args[1]) return nil } prometheus-squid-exporter-1.8.2+ds/dashboards/000077500000000000000000000000001360562145700214335ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/dashboards/squid-sample-dashboard.json000066400000000000000000000330031360562145700266560ustar00rootroot00000000000000{ "__inputs": [], "__requires": [ { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "5.2.4" }, { "type": "panel", "id": "graph", "name": "Graph", "version": "5.0.0" }, { "type": "panel", "id": "singlestat", "name": "Singlestat", "version": "5.0.0" }, { "type": "panel", "id": "text", "name": "Text", "version": "5.0.0" } ], "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "gnetId": null, "graphTooltip": 0, "id": null, "iteration": 1536353270000, "links": [], "panels": [ { "content": "

Squid Sample Dashboard

", "gridPos": { "h": 3, "w": 6, "x": 0, "y": 0 }, "id": 10, "links": [], "mode": "html", "title": "", "type": "text" }, { "cacheTimeout": null, "colorBackground": true, "colorValue": false, "colors": [ "#d44a3a", "rgba(237, 129, 40, 0.89)", "#299c46" ], "datasource": "$datasource", "format": "none", "gauge": { "maxValue": 100, "minValue": 0, "show": false, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 3, "w": 6, "x": 6, "y": 0 }, "id": 14, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "200%", "prefix": "", "prefixFontSize": "200%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": true }, "tableColumn": "", "targets": [ { "expr": "up{job='squid'}", "format": "time_series", "intervalFactor": 1, "legendFormat": "", "refId": "A" } ], "thresholds": "0,1", "title": "Services Up", "type": "singlestat", "valueFontSize": "200%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "current" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, "colors": [ "#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a" ], "datasource": "$datasource", "format": "percentunit", "gauge": { "maxValue": 100, "minValue": 0, "show": false, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 3, "w": 4, "x": 12, "y": 0 }, "id": 8, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "50%", "prefix": "", "prefixFontSize": "50%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": false }, "tableColumn": "", "targets": [ { "expr": "squid_client_http_hit_kbytes_out_bytes_total / squid_client_http_kbytes_out_kbytes_total", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "thresholds": "", "title": "Bytes Hit Rate", "type": "singlestat", "valueFontSize": "80%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "avg" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, "colors": [ "#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a" ], "datasource": "$datasource", "format": "percentunit", "gauge": { "maxValue": 100, "minValue": 0, "show": false, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 3, "w": 4, "x": 16, "y": 0 }, "id": 6, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "50%", "prefix": "", "prefixFontSize": "50%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": false }, "tableColumn": "", "targets": [ { "expr": "squid_client_http_hits_total / squid_client_http_requests_total", "format": "time_series", "intervalFactor": 1, "legendFormat": "Hit rate", "refId": "A" } ], "thresholds": "", "title": "Catch Hit Rate", "type": "singlestat", "valueFontSize": "80%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "avg" }, { "cacheTimeout": null, "colorBackground": false, "colorValue": false, "colors": [ "#299c46", "rgba(237, 129, 40, 0.89)", "#d44a3a" ], "datasource": "$datasource", "format": "percentunit", "gauge": { "maxValue": 100, "minValue": 0, "show": false, "thresholdLabels": false, "thresholdMarkers": true }, "gridPos": { "h": 3, "w": 4, "x": 20, "y": 0 }, "id": 12, "interval": null, "links": [], "mappingType": 1, "mappingTypes": [ { "name": "value to text", "value": 1 }, { "name": "range to text", "value": 2 } ], "maxDataPoints": 100, "nullPointMode": "connected", "nullText": null, "postfix": "", "postfixFontSize": "50%", "prefix": "", "prefixFontSize": "50%", "rangeMaps": [ { "from": "null", "text": "N/A", "to": "null" } ], "sparkline": { "fillColor": "rgba(31, 118, 189, 0.18)", "full": false, "lineColor": "rgb(31, 120, 193)", "show": false }, "tableColumn": "", "targets": [ { "expr": "squid_client_http_errors_total / squid_client_http_requests_total", "format": "time_series", "intervalFactor": 1, "refId": "A" } ], "thresholds": "", "title": "Error Rate", "type": "singlestat", "valueFontSize": "80%", "valueMaps": [ { "op": "=", "text": "N/A", "value": "null" } ], "valueName": "avg" }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "$datasource", "fill": 1, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 3 }, "id": 2, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "rate(squid_client_http_requests_total[5m])", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "Total Requests", "refId": "B" }, { "expr": "rate(squid_client_http_hits_total[5m])", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "Total HTTP hits", "refId": "A" }, { "expr": "rate(squid_client_http_errors_total[5m])", "format": "time_series", "intervalFactor": 1, "legendFormat": "Total Errors", "refId": "C" } ], "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Client Requests", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "reqps", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "$datasource", "fill": 1, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 3 }, "id": 4, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "rate(squid_client_http_kbytes_in_kbytes_total[5m]) * -1", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "HTTP Traffic in", "refId": "A" }, { "expr": "rate(squid_client_http_kbytes_out_kbytes_total[5m])", "format": "time_series", "intervalFactor": 1, "legendFormat": "HTTP Traffic Out", "refId": "B" }, { "expr": "rate(squid_client_http_hit_kbytes_out_bytes_total[5m])", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "HTTP Traffic Out Hits", "refId": "C" } ], "thresholds": [], "timeFrom": null, "timeShift": null, "title": "Client Traffic", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "KBs", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } } ], "schemaVersion": 16, "style": "dark", "tags": [], "templating": { "list": [ { "current": { "text": "default", "value": "default" }, "hide": 0, "label": null, "name": "datasource", "options": [], "query": "prometheus", "refresh": 1, "regex": "", "type": "datasource" } ] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": { "refresh_intervals": [ "5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ], "time_options": [ "5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d" ] }, "timezone": "", "title": "Squid Sample Dashboard", "uid": "yRc_Bj2ik", "version": 3 }prometheus-squid-exporter-1.8.2+ds/go.mod000066400000000000000000000004211360562145700204240ustar00rootroot00000000000000module github.com/boynux/squid-exporter go 1.12 require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/prometheus/client_golang v1.1.0 github.com/prometheus/common v0.6.0 ) prometheus-squid-exporter-1.8.2+ds/go.sum000066400000000000000000000151031360562145700204540ustar00rootroot00000000000000github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/boynux/squid-exporter v0.0.0-20171021195124-6dcf7c016995/go.mod h1:VSICGV4XC8I2AsWmKFRAxYOYNc/GxKAVkARON6FaD68= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 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/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 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.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= prometheus-squid-exporter-1.8.2+ds/main.go000066400000000000000000000024101360562145700205710ustar00rootroot00000000000000package main import ( "fmt" "log" "net/http" "os" "github.com/boynux/squid-exporter/collector" "github.com/boynux/squid-exporter/config" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/version" ) const indexContent = ` Squid Exporter

Squid Exporter

Metrics

` func init() { prometheus.MustRegister(version.NewCollector("squid_exporter")) } func main() { cfg := config.NewConfig() if *config.VersionFlag { log.Println(version.Print("squid_exporter")) os.Exit(0) } 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) prometheus.MustRegister(e) // Serve metrics http.Handle(cfg.MetricPath, promhttp.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(indexContent)) }) log.Println("Listening on", fmt.Sprintf("%s", cfg.ListenAddress)) log.Fatal(http.ListenAndServe(fmt.Sprintf("%s", cfg.ListenAddress), nil)) } prometheus-squid-exporter-1.8.2+ds/prometheus/000077500000000000000000000000001360562145700215145ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/prometheus/prometheus.yml000066400000000000000000000016301360562145700244320ustar00rootroot00000000000000# my global config global: scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. # scrape_timeout is set to the global default (10s). # Alertmanager configuration alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093 # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. rule_files: # - "first_rules.yml" # - "second_rules.yml" # A scrape configuration containing exactly one endpoint to scrape: # Here it's Prometheus itself. scrape_configs: # The job name is added as a label `job=` to any timeseries scraped from this config. - job_name: 'squid' # metrics_path defaults to '/metrics' # scheme defaults to 'http' static_configs: - targets: ['localhost:9301'] prometheus-squid-exporter-1.8.2+ds/types/000077500000000000000000000000001360562145700204655ustar00rootroot00000000000000prometheus-squid-exporter-1.8.2+ds/types/types.go000066400000000000000000000002621360562145700221600ustar00rootroot00000000000000package types /*Counter maps a squid conters */ type Counter struct { Key string Value float64 } /*Counters is a list of multiple squid counters */ type Counters []Counter