├── .gitignore ├── vendor ├── github.com │ ├── prometheus │ │ ├── procfs │ │ │ ├── MAINTAINERS.md │ │ │ ├── Makefile │ │ │ ├── NOTICE │ │ │ ├── README.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── fs.go │ │ │ ├── proc_io.go │ │ │ ├── stat.go │ │ │ ├── doc.go │ │ │ ├── buddyinfo.go │ │ │ ├── mdstat.go │ │ │ ├── proc_limits.go │ │ │ ├── xfs │ │ │ │ └── xfs.go │ │ │ ├── proc_stat.go │ │ │ └── proc.go │ │ ├── client_golang │ │ │ ├── prometheus │ │ │ │ ├── README.md │ │ │ │ ├── fnv.go │ │ │ │ ├── timer.go │ │ │ │ ├── collector.go │ │ │ │ ├── process_collector.go │ │ │ │ ├── expvar_collector.go │ │ │ │ ├── gauge.go │ │ │ │ ├── untyped.go │ │ │ │ └── counter.go │ │ │ └── NOTICE │ │ ├── client_model │ │ │ └── NOTICE │ │ └── common │ │ │ ├── NOTICE │ │ │ ├── model │ │ │ ├── model.go │ │ │ ├── fnv.go │ │ │ ├── fingerprinting.go │ │ │ ├── silence.go │ │ │ ├── metric.go │ │ │ ├── alert.go │ │ │ ├── labelset.go │ │ │ └── signature.go │ │ │ ├── expfmt │ │ │ ├── fuzz.go │ │ │ ├── expfmt.go │ │ │ └── encode.go │ │ │ └── internal │ │ │ └── bitbucket.org │ │ │ └── ww │ │ │ └── goautoneg │ │ │ ├── README.txt │ │ │ └── autoneg.go │ ├── matttproud │ │ └── golang_protobuf_extensions │ │ │ ├── NOTICE │ │ │ └── pbutil │ │ │ ├── Makefile │ │ │ ├── doc.go │ │ │ ├── encode.go │ │ │ └── decode.go │ ├── gorilla │ │ ├── mux │ │ │ ├── context_native.go │ │ │ ├── context_gorilla.go │ │ │ └── LICENSE │ │ └── context │ │ │ ├── README.md │ │ │ ├── LICENSE │ │ │ ├── doc.go │ │ │ └── context.go │ ├── urfave │ │ └── negroni │ │ │ ├── doc.go │ │ │ ├── LICENSE │ │ │ ├── CHANGELOG.md │ │ │ ├── recovery.go │ │ │ ├── logger.go │ │ │ ├── static.go │ │ │ ├── response_writer.go │ │ │ └── negroni.go │ ├── beorn7 │ │ └── perks │ │ │ └── LICENSE │ └── golang │ │ └── protobuf │ │ ├── LICENSE │ │ └── proto │ │ └── Makefile ├── gopkg.in │ ├── redis.v3 │ │ ├── doc.go │ │ ├── safe.go │ │ ├── unsafe.go │ │ ├── internal │ │ │ ├── log.go │ │ │ ├── pool │ │ │ │ ├── pool_single.go │ │ │ │ ├── conn.go │ │ │ │ └── pool_sticky.go │ │ │ ├── consistenthash │ │ │ │ └── consistenthash.go │ │ │ └── hashtag │ │ │ │ └── hashtag.go │ │ ├── Makefile │ │ ├── script.go │ │ ├── LICENSE │ │ ├── error.go │ │ ├── pipeline.go │ │ ├── cluster_pipeline.go │ │ ├── options.go │ │ ├── redis.go │ │ ├── README.md │ │ └── multi.go │ └── bsm │ │ └── ratelimit.v1 │ │ ├── Makefile │ │ ├── README.md │ │ └── ratelimit.go └── vendor.json ├── prometheus.yml ├── Makefile ├── weather ├── weather.go └── client.go ├── main.go ├── handlers.go └── redis └── client.go /.gitignore: -------------------------------------------------------------------------------- 1 | data/ -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | * Tobias Schmidt 2 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package redis implements a Redis client. 3 | */ 4 | package redis 5 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt T. Proud (matt.proud@gmail.com) 2 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/safe.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package redis 4 | 5 | func bytesToString(b []byte) string { 6 | return string(b) 7 | } 8 | -------------------------------------------------------------------------------- /prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 10s 3 | 4 | scrape_configs: 5 | - job_name: myapp 6 | static_configs: 7 | - targets: 8 | - localhost:8080 9 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/Makefile: -------------------------------------------------------------------------------- 1 | ci: 2 | ! gofmt -l *.go | read nothing 3 | go vet 4 | go test -v ./... 5 | go get github.com/golang/lint/golint 6 | golint *.go 7 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | 3 | cover: 4 | go test -cover -v -coverprofile=cover.dat ./... 5 | go tool cover -func cover.dat 6 | 7 | .PHONY: cover 8 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/README.md: -------------------------------------------------------------------------------- 1 | See [![go-doc](https://godoc.org/github.com/prometheus/client_golang/prometheus?status.svg)](https://godoc.org/github.com/prometheus/client_golang/prometheus). 2 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_model/NOTICE: -------------------------------------------------------------------------------- 1 | Data model artifacts for Prometheus. 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/NOTICE: -------------------------------------------------------------------------------- 1 | Common libraries shared by Prometheus Go components. 2 | Copyright 2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/NOTICE: -------------------------------------------------------------------------------- 1 | procfs provides functions to retrieve system, kernel and process 2 | metrics from the pseudo-filesystem proc. 3 | 4 | Copyright 2014-2015 The Prometheus Authors 5 | 6 | This product includes software developed at 7 | SoundCloud Ltd. (http://soundcloud.com/). 8 | -------------------------------------------------------------------------------- /vendor/gopkg.in/bsm/ratelimit.v1/Makefile: -------------------------------------------------------------------------------- 1 | default: test 2 | 3 | testdeps: 4 | @go get github.com/onsi/ginkgo 5 | @go get github.com/onsi/gomega 6 | 7 | test: testdeps 8 | @go test ./... 9 | 10 | testrace: testdeps 11 | @go test ./... -race 12 | 13 | testall: test testrace 14 | 15 | bench: 16 | @go test ./... -run=NONE -bench=. 17 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/unsafe.go: -------------------------------------------------------------------------------- 1 | // +build !appengine 2 | 3 | package redis 4 | 5 | import ( 6 | "reflect" 7 | "unsafe" 8 | ) 9 | 10 | func bytesToString(b []byte) string { 11 | bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 12 | strHeader := reflect.StringHeader{bytesHeader.Data, bytesHeader.Len} 13 | return *(*string)(unsafe.Pointer(&strHeader)) 14 | } 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | prom: 2 | prometheus -config.file=prometheus.yml 3 | 4 | run: 5 | go run main.go handlers.go 6 | 7 | stress: 8 | wrk -c 100 -t 20 http://localhost:8080/city/london/temp 9 | 10 | grafana: 11 | grafana-server --config=/usr/local/etc/grafana/grafana.ini --homepath /usr/local/share/grafana cfg:default.paths.logs=/usr/local/var/log/grafana cfg:default.paths.data=/usr/local/var/lib/grafana cfg:default.paths.plugins=/usr/local/var/lib/grafana/plugins -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/internal/log.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | ) 8 | 9 | var Debug bool 10 | 11 | var Logger = log.New(ioutil.Discard, "redis: ", log.LstdFlags) 12 | 13 | func Debugf(s string, args ...interface{}) { 14 | if !Debug { 15 | return 16 | } 17 | Logger.Output(2, fmt.Sprintf(s, args...)) 18 | } 19 | 20 | func Logf(s string, args ...interface{}) { 21 | Logger.Output(2, fmt.Sprintf(s, args...)) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/Makefile: -------------------------------------------------------------------------------- 1 | all: testdeps 2 | go test ./... 3 | go test ./... -short -race 4 | 5 | testdeps: testdata/redis/src/redis-server 6 | 7 | bench: testdeps 8 | go test ./... -test.run=NONE -test.bench=. -test.benchmem 9 | 10 | .PHONY: all test testdeps bench 11 | 12 | testdata/redis: 13 | mkdir -p $@ 14 | wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@ 15 | 16 | testdata/redis/src/redis-server: testdata/redis 17 | cd $< && make all 18 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_native.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "context" 7 | "net/http" 8 | ) 9 | 10 | func contextGet(r *http.Request, key interface{}) interface{} { 11 | return r.Context().Value(key) 12 | } 13 | 14 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 15 | if val == nil { 16 | return r 17 | } 18 | 19 | return r.WithContext(context.WithValue(r.Context(), key, val)) 20 | } 21 | 22 | func contextClear(r *http.Request) { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/context_gorilla.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package mux 4 | 5 | import ( 6 | "net/http" 7 | 8 | "github.com/gorilla/context" 9 | ) 10 | 11 | func contextGet(r *http.Request, key interface{}) interface{} { 12 | return context.Get(r, key) 13 | } 14 | 15 | func contextSet(r *http.Request, key, val interface{}) *http.Request { 16 | if val == nil { 17 | return r 18 | } 19 | 20 | context.Set(r, key, val) 21 | return r 22 | } 23 | 24 | func contextClear(r *http.Request) { 25 | context.Clear(r) 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/README.md: -------------------------------------------------------------------------------- 1 | context 2 | ======= 3 | [![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) 4 | 5 | gorilla/context is a general purpose registry for global request variables. 6 | 7 | > Note: gorilla/context, having been born well before `context.Context` existed, does not play well 8 | > with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`. 9 | 10 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context 11 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/README.md: -------------------------------------------------------------------------------- 1 | # procfs 2 | 3 | This procfs package provides functions to retrieve system, kernel and process 4 | metrics from the pseudo-filesystem proc. 5 | 6 | *WARNING*: This package is a work in progress. Its API may still break in 7 | backwards-incompatible ways without warnings. Use it at your own risk. 8 | 9 | [![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs) 10 | [![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs) 11 | [![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs) 12 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/fnv.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | // Inline and byte-free variant of hash/fnv's fnv64a. 4 | 5 | const ( 6 | offset64 = 14695981039346656037 7 | prime64 = 1099511628211 8 | ) 9 | 10 | // hashNew initializies a new fnv64a hash value. 11 | func hashNew() uint64 { 12 | return offset64 13 | } 14 | 15 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 16 | func hashAdd(h uint64, s string) uint64 { 17 | for i := 0; i < len(s); i++ { 18 | h ^= uint64(s[i]) 19 | h *= prime64 20 | } 21 | return h 22 | } 23 | 24 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 25 | func hashAddByte(h uint64, b byte) uint64 { 26 | h ^= uint64(b) 27 | h *= prime64 28 | return h 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package pbutil provides record length-delimited Protocol Buffer streaming. 16 | package pbutil 17 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/model.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package model contains common data structures that are shared across 15 | // Prometheus components and libraries. 16 | package model 17 | -------------------------------------------------------------------------------- /weather/weather.go: -------------------------------------------------------------------------------- 1 | package weather 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | type cityResult struct { 9 | Main mainResult 10 | } 11 | 12 | type mainResult struct { 13 | Temp float64 14 | } 15 | 16 | type CityTemp struct { 17 | Temp float64 18 | Unit string 19 | } 20 | 21 | func GetCityTemp(name string) (*CityTemp, error) { 22 | client, err := getClient() 23 | if err != nil { 24 | return nil, err 25 | } 26 | resp, err := client.do(http.MethodGet, "data/2.5/weather", map[string]string{"q": name, "units": "metric"}) 27 | if err != nil { 28 | return nil, err 29 | } 30 | defer resp.Body.Close() 31 | var result cityResult 32 | err = json.NewDecoder(resp.Body).Decode(&result) 33 | if err != nil { 34 | return nil, err 35 | } 36 | return &CityTemp{Temp: result.Main.Temp, Unit: "C"}, nil 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/doc.go: -------------------------------------------------------------------------------- 1 | // Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers. 2 | // 3 | // If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. 4 | // 5 | // For a full guide visit http://github.com/urfave/negroni 6 | // 7 | // package main 8 | // 9 | // import ( 10 | // "github.com/urfave/negroni" 11 | // "net/http" 12 | // "fmt" 13 | // ) 14 | // 15 | // func main() { 16 | // mux := http.NewServeMux() 17 | // mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 18 | // fmt.Fprintf(w, "Welcome to the home page!") 19 | // }) 20 | // 21 | // n := negroni.Classic() 22 | // n.UseHandler(mux) 23 | // n.Run(":3000") 24 | // } 25 | package negroni 26 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/NOTICE: -------------------------------------------------------------------------------- 1 | Prometheus instrumentation library for Go applications 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | 7 | 8 | The following components are included in this product: 9 | 10 | perks - a fork of https://github.com/bmizerany/perks 11 | https://github.com/beorn7/perks 12 | Copyright 2013-2015 Blake Mizerany, Björn Rabenstein 13 | See https://github.com/beorn7/perks/blob/master/README.md for license details. 14 | 15 | Go support for Protocol Buffers - Google's data interchange format 16 | http://github.com/golang/protobuf/ 17 | Copyright 2010 The Go Authors 18 | See source code for license details. 19 | 20 | Support for streaming Protocol Buffer messages for the Go language (golang). 21 | https://github.com/matttproud/golang_protobuf_extensions 22 | Copyright 2013 Matt T. Proud 23 | Licensed under the Apache License, Version 2.0 24 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Prometheus uses GitHub to manage reviews of pull requests. 4 | 5 | * If you have a trivial fix or improvement, go ahead and create a pull request, 6 | addressing (with `@...`) the maintainer of this repository (see 7 | [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request. 8 | 9 | * If you plan to do something more involved, first discuss your ideas 10 | on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers). 11 | This will avoid unnecessary work and surely give you and us a good deal 12 | of inspiration. 13 | 14 | * Relevant coding style guidelines are the [Go Code Review 15 | Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) 16 | and the _Formatting and style_ section of Peter Bourgon's [Go: Best 17 | Practices for Production 18 | Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style). 19 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/internal/pool/pool_single.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | type SingleConnPool struct { 4 | cn *Conn 5 | } 6 | 7 | var _ Pooler = (*SingleConnPool)(nil) 8 | 9 | func NewSingleConnPool(cn *Conn) *SingleConnPool { 10 | return &SingleConnPool{ 11 | cn: cn, 12 | } 13 | } 14 | 15 | func (p *SingleConnPool) First() *Conn { 16 | return p.cn 17 | } 18 | 19 | func (p *SingleConnPool) Get() (*Conn, error) { 20 | return p.cn, nil 21 | } 22 | 23 | func (p *SingleConnPool) Put(cn *Conn) error { 24 | if p.cn != cn { 25 | panic("p.cn != cn") 26 | } 27 | return nil 28 | } 29 | 30 | func (p *SingleConnPool) Remove(cn *Conn, _ error) error { 31 | if p.cn != cn { 32 | panic("p.cn != cn") 33 | } 34 | return nil 35 | } 36 | 37 | func (p *SingleConnPool) Len() int { 38 | return 1 39 | } 40 | 41 | func (p *SingleConnPool) FreeLen() int { 42 | return 0 43 | } 44 | 45 | func (p *SingleConnPool) Stats() *PoolStats { 46 | return nil 47 | } 48 | 49 | func (p *SingleConnPool) Close() error { 50 | return nil 51 | } 52 | 53 | func (p *SingleConnPool) Closed() bool { 54 | return false 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/beorn7/perks/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Blake Mizerany 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jeremy Saenz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Build only when actually fuzzing 15 | // +build gofuzz 16 | 17 | package expfmt 18 | 19 | import "bytes" 20 | 21 | // Fuzz text metric parser with with github.com/dvyukov/go-fuzz: 22 | // 23 | // go-fuzz-build github.com/prometheus/common/expfmt 24 | // go-fuzz -bin expfmt-fuzz.zip -workdir fuzz 25 | // 26 | // Further input samples should go in the folder fuzz/corpus. 27 | func Fuzz(in []byte) int { 28 | parser := TextParser{} 29 | _, err := parser.TextToMetricFamilies(bytes.NewReader(in)) 30 | 31 | if err != nil { 32 | return 0 33 | } 34 | 35 | return 1 36 | } 37 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/gorilla/mux" 10 | "github.com/prometheus/client_golang/prometheus" 11 | "github.com/prometheus/client_golang/prometheus/promhttp" 12 | "github.com/urfave/negroni" 13 | ) 14 | 15 | var ( 16 | openConnections = prometheus.NewGauge(prometheus.GaugeOpts{ 17 | Name: "myapp_open_connections", 18 | Help: "The current number of open connections.", 19 | }) 20 | ) 21 | 22 | func init() { 23 | prometheus.MustRegister(openConnections) 24 | } 25 | 26 | func main() { 27 | s := &http.Server{ 28 | Addr: ":8080", 29 | Handler: router(), 30 | ReadTimeout: 10 * time.Second, 31 | WriteTimeout: 30 * time.Second, 32 | ConnState: func(c net.Conn, s http.ConnState) { 33 | switch s { 34 | case http.StateNew: 35 | openConnections.Inc() 36 | case http.StateHijacked | http.StateClosed: 37 | openConnections.Dec() 38 | } 39 | }, 40 | } 41 | log.Println("HTTP server listening at :8080...") 42 | log.Fatal(s.ListenAndServe()) 43 | } 44 | 45 | func router() http.Handler { 46 | r := mux.NewRouter().StrictSlash(true) 47 | r.Handle("/metrics", promhttp.Handler()) 48 | r.HandleFunc("/city/{name}/temp", instrumentHandler("/city/{name}/temp", cityTemp)) 49 | n := negroni.Classic() 50 | n.UseHandler(r) 51 | return n 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/fs.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path" 7 | 8 | "github.com/prometheus/procfs/xfs" 9 | ) 10 | 11 | // FS represents the pseudo-filesystem proc, which provides an interface to 12 | // kernel data structures. 13 | type FS string 14 | 15 | // DefaultMountPoint is the common mount point of the proc filesystem. 16 | const DefaultMountPoint = "/proc" 17 | 18 | // NewFS returns a new FS mounted under the given mountPoint. It will error 19 | // if the mount point can't be read. 20 | func NewFS(mountPoint string) (FS, error) { 21 | info, err := os.Stat(mountPoint) 22 | if err != nil { 23 | return "", fmt.Errorf("could not read %s: %s", mountPoint, err) 24 | } 25 | if !info.IsDir() { 26 | return "", fmt.Errorf("mount point %s is not a directory", mountPoint) 27 | } 28 | 29 | return FS(mountPoint), nil 30 | } 31 | 32 | // Path returns the path of the given subsystem relative to the procfs root. 33 | func (fs FS) Path(p ...string) string { 34 | return path.Join(append([]string{string(fs)}, p...)...) 35 | } 36 | 37 | // XFSStats retrieves XFS filesystem runtime statistics. 38 | func (fs FS) XFSStats() (*xfs.Stats, error) { 39 | f, err := os.Open(fs.Path("fs/xfs/stat")) 40 | if err != nil { 41 | return nil, err 42 | } 43 | defer f.Close() 44 | 45 | return xfs.ParseStats(f) 46 | } 47 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/script.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/hex" 6 | "io" 7 | "strings" 8 | ) 9 | 10 | type scripter interface { 11 | Eval(script string, keys []string, args []string) *Cmd 12 | EvalSha(sha1 string, keys []string, args []string) *Cmd 13 | ScriptExists(scripts ...string) *BoolSliceCmd 14 | ScriptLoad(script string) *StringCmd 15 | } 16 | 17 | type Script struct { 18 | src, hash string 19 | } 20 | 21 | func NewScript(src string) *Script { 22 | h := sha1.New() 23 | io.WriteString(h, src) 24 | return &Script{ 25 | src: src, 26 | hash: hex.EncodeToString(h.Sum(nil)), 27 | } 28 | } 29 | 30 | func (s *Script) Load(c scripter) *StringCmd { 31 | return c.ScriptLoad(s.src) 32 | } 33 | 34 | func (s *Script) Exists(c scripter) *BoolSliceCmd { 35 | return c.ScriptExists(s.src) 36 | } 37 | 38 | func (s *Script) Eval(c scripter, keys []string, args []string) *Cmd { 39 | return c.Eval(s.src, keys, args) 40 | } 41 | 42 | func (s *Script) EvalSha(c scripter, keys []string, args []string) *Cmd { 43 | return c.EvalSha(s.hash, keys, args) 44 | } 45 | 46 | func (s *Script) Run(c scripter, keys []string, args []string) *Cmd { 47 | r := s.EvalSha(c, keys, args) 48 | if err := r.Err(); err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") { 49 | return s.Eval(c, keys, args) 50 | } 51 | return r 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fnv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | // Inline and byte-free variant of hash/fnv's fnv64a. 17 | 18 | const ( 19 | offset64 = 14695981039346656037 20 | prime64 = 1099511628211 21 | ) 22 | 23 | // hashNew initializies a new fnv64a hash value. 24 | func hashNew() uint64 { 25 | return offset64 26 | } 27 | 28 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 29 | func hashAdd(h uint64, s string) uint64 { 30 | for i := 0; i < len(s); i++ { 31 | h ^= uint64(s[i]) 32 | h *= prime64 33 | } 34 | return h 35 | } 36 | 37 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 38 | func hashAddByte(h uint64, b byte) uint64 { 39 | h ^= uint64(b) 40 | h *= prime64 41 | return h 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_io.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | ) 8 | 9 | // ProcIO models the content of /proc//io. 10 | type ProcIO struct { 11 | // Chars read. 12 | RChar uint64 13 | // Chars written. 14 | WChar uint64 15 | // Read syscalls. 16 | SyscR uint64 17 | // Write syscalls. 18 | SyscW uint64 19 | // Bytes read. 20 | ReadBytes uint64 21 | // Bytes written. 22 | WriteBytes uint64 23 | // Bytes written, but taking into account truncation. See 24 | // Documentation/filesystems/proc.txt in the kernel sources for 25 | // detailed explanation. 26 | CancelledWriteBytes int64 27 | } 28 | 29 | // NewIO creates a new ProcIO instance from a given Proc instance. 30 | func (p Proc) NewIO() (ProcIO, error) { 31 | pio := ProcIO{} 32 | 33 | f, err := os.Open(p.path("io")) 34 | if err != nil { 35 | return pio, err 36 | } 37 | defer f.Close() 38 | 39 | data, err := ioutil.ReadAll(f) 40 | if err != nil { 41 | return pio, err 42 | } 43 | 44 | ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + 45 | "read_bytes: %d\nwrite_bytes: %d\n" + 46 | "cancelled_write_bytes: %d\n" 47 | 48 | _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, 49 | &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) 50 | if err != nil { 51 | return pio, err 52 | } 53 | 54 | return pio, nil 55 | } 56 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 The github.com/go-redis/redis Contributors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /handlers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/andrestc/demo-go-instrument/redis" 9 | "github.com/andrestc/demo-go-instrument/weather" 10 | "github.com/gorilla/mux" 11 | "github.com/prometheus/client_golang/prometheus" 12 | ) 13 | 14 | var ( 15 | handlerDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ 16 | Name: "myapp_handlers_duration_seconds", 17 | Help: "Handlers request duration in seconds", 18 | }, []string{"path"}) 19 | ) 20 | 21 | func init() { 22 | prometheus.MustRegister(handlerDuration) 23 | } 24 | 25 | func instrumentHandler(pattern string, next http.HandlerFunc) http.HandlerFunc { 26 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 27 | now := time.Now() 28 | next(w, r) 29 | handlerDuration.WithLabelValues(pattern).Observe(time.Since(now).Seconds()) 30 | }) 31 | } 32 | 33 | func cityTemp(w http.ResponseWriter, r *http.Request) { 34 | vars := mux.Vars(r) 35 | name := vars["name"] 36 | if name == "" { 37 | http.Error(w, "Must provide a city name.", http.StatusBadRequest) 38 | return 39 | } 40 | redis.Increment(name) 41 | temp, err := weather.GetCityTemp(name) 42 | if err != nil { 43 | http.Error(w, err.Error(), http.StatusInternalServerError) 44 | return 45 | } 46 | err = json.NewEncoder(w).Encode(temp) 47 | if err != nil { 48 | http.Error(w, err.Error(), http.StatusInternalServerError) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/stat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // Stat represents kernel/system statistics. 12 | type Stat struct { 13 | // Boot time in seconds since the Epoch. 14 | BootTime int64 15 | } 16 | 17 | // NewStat returns kernel/system statistics read from /proc/stat. 18 | func NewStat() (Stat, error) { 19 | fs, err := NewFS(DefaultMountPoint) 20 | if err != nil { 21 | return Stat{}, err 22 | } 23 | 24 | return fs.NewStat() 25 | } 26 | 27 | // NewStat returns an information about current kernel/system statistics. 28 | func (fs FS) NewStat() (Stat, error) { 29 | f, err := os.Open(fs.Path("stat")) 30 | if err != nil { 31 | return Stat{}, err 32 | } 33 | defer f.Close() 34 | 35 | s := bufio.NewScanner(f) 36 | for s.Scan() { 37 | line := s.Text() 38 | if !strings.HasPrefix(line, "btime") { 39 | continue 40 | } 41 | fields := strings.Fields(line) 42 | if len(fields) != 2 { 43 | return Stat{}, fmt.Errorf("couldn't parse %s line %s", f.Name(), line) 44 | } 45 | i, err := strconv.ParseInt(fields[1], 10, 32) 46 | if err != nil { 47 | return Stat{}, fmt.Errorf("couldn't parse %s: %s", fields[1], err) 48 | } 49 | return Stat{BootTime: i}, nil 50 | } 51 | if err := s.Err(); err != nil { 52 | return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err) 53 | } 54 | 55 | return Stat{}, fmt.Errorf("couldn't parse %s, missing btime", f.Name()) 56 | } 57 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | **ATTN**: This project uses [semantic versioning](http://semver.org/). 4 | 5 | ## [Unreleased] 6 | ### Added 7 | - `Recovery.ErrorHandlerFunc` for custom error handling during recovery 8 | - `With()` helper for building a new `Negroni` struct chaining handlers from 9 | existing `Negroni` structs 10 | 11 | ### Fixed 12 | - `Written()` correct returns `false` if no response header has been written 13 | 14 | ### Changed 15 | - Set default status to `0` in the case that no handler writes status -- was 16 | previously `200` (in 0.2.0, before that it was `0` so this reestablishes that 17 | behavior) 18 | - Catch `panic`s thrown by callbacks provided to the `Recovery` handler 19 | 20 | ## [0.2.0] - 2016-05-10 21 | ### Added 22 | - Support for variadic handlers in `New()` 23 | - Added `Negroni.Handlers()` to fetch all of the handlers for a given chain 24 | - Allowed size in `Recovery` handler was bumped to 8k 25 | - `Negroni.UseFunc` to push another handler onto the chain 26 | 27 | ### Changed 28 | - Set the status before calling `beforeFuncs` so the information is available to them 29 | - Set default status to `200` in the case that no handler writes status -- was previously `0` 30 | - Panic if `nil` handler is given to `negroni.Use` 31 | 32 | ## 0.1.0 - 2013-07-22 33 | ### Added 34 | - Initial implementation. 35 | 36 | [Unreleased]: https://github.com/urfave/negroni/compare/v0.2.0...HEAD 37 | [0.2.0]: https://github.com/urfave/negroni/compare/v0.1.0...v0.2.0 38 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Prometheus Team 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package procfs provides functions to retrieve system, kernel and process 15 | // metrics from the pseudo-filesystem proc. 16 | // 17 | // Example: 18 | // 19 | // package main 20 | // 21 | // import ( 22 | // "fmt" 23 | // "log" 24 | // 25 | // "github.com/prometheus/procfs" 26 | // ) 27 | // 28 | // func main() { 29 | // p, err := procfs.Self() 30 | // if err != nil { 31 | // log.Fatalf("could not get process: %s", err) 32 | // } 33 | // 34 | // stat, err := p.NewStat() 35 | // if err != nil { 36 | // log.Fatalf("could not get process stat: %s", err) 37 | // } 38 | // 39 | // fmt.Printf("command: %s\n", stat.Comm) 40 | // fmt.Printf("cpu time: %fs\n", stat.CPUTime()) 41 | // fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) 42 | // fmt.Printf("rss: %dB\n", stat.ResidentMemory()) 43 | // } 44 | // 45 | package procfs 46 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/expfmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package expfmt contains tools for reading and writing Prometheus metrics. 15 | package expfmt 16 | 17 | // Format specifies the HTTP content type of the different wire protocols. 18 | type Format string 19 | 20 | // Constants to assemble the Content-Type values for the different wire protocols. 21 | const ( 22 | TextVersion = "0.0.4" 23 | ProtoType = `application/vnd.google.protobuf` 24 | ProtoProtocol = `io.prometheus.client.MetricFamily` 25 | ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" 26 | 27 | // The Content-Type values for the different wire protocols. 28 | FmtUnknown Format = `` 29 | FmtText Format = `text/plain; version=` + TextVersion 30 | FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` 31 | FmtProtoText Format = ProtoFmt + ` encoding=text` 32 | FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` 33 | ) 34 | 35 | const ( 36 | hdrContentType = "Content-Type" 37 | hdrAccept = "Accept" 38 | ) 39 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/LICENSE: -------------------------------------------------------------------------------- 1 | Go support for Protocol Buffers - Google's data interchange format 2 | 3 | Copyright 2010 The Go Authors. All rights reserved. 4 | https://github.com/golang/protobuf 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following disclaimer 14 | in the documentation and/or other materials provided with the 15 | distribution. 16 | * Neither the name of Google Inc. nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "io" 20 | 21 | "github.com/golang/protobuf/proto" 22 | ) 23 | 24 | // WriteDelimited encodes and dumps a message to the provided writer prefixed 25 | // with a 32-bit varint indicating the length of the encoded message, producing 26 | // a length-delimited record stream, which can be used to chain together 27 | // encoded messages of the same type together in a file. It returns the total 28 | // number of bytes written and any applicable error. This is roughly 29 | // equivalent to the companion Java API's MessageLite#writeDelimitedTo. 30 | func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { 31 | buffer, err := proto.Marshal(m) 32 | if err != nil { 33 | return 0, err 34 | } 35 | 36 | var buf [binary.MaxVarintLen32]byte 37 | encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) 38 | 39 | sync, err := w.Write(buf[:encodedLength]) 40 | if err != nil { 41 | return sync, err 42 | } 43 | 44 | n, err = w.Write(buffer) 45 | return n + sync, err 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/recovery.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "os" 8 | "runtime" 9 | "runtime/debug" 10 | ) 11 | 12 | // Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. 13 | type Recovery struct { 14 | Logger ALogger 15 | PrintStack bool 16 | ErrorHandlerFunc func(interface{}) 17 | StackAll bool 18 | StackSize int 19 | } 20 | 21 | // NewRecovery returns a new instance of Recovery 22 | func NewRecovery() *Recovery { 23 | return &Recovery{ 24 | Logger: log.New(os.Stdout, "[negroni] ", 0), 25 | PrintStack: true, 26 | StackAll: false, 27 | StackSize: 1024 * 8, 28 | } 29 | } 30 | 31 | func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 32 | defer func() { 33 | if err := recover(); err != nil { 34 | if rw.Header().Get("Content-Type") == "" { 35 | rw.Header().Set("Content-Type", "text/plain; charset=utf-8") 36 | } 37 | 38 | rw.WriteHeader(http.StatusInternalServerError) 39 | 40 | stack := make([]byte, rec.StackSize) 41 | stack = stack[:runtime.Stack(stack, rec.StackAll)] 42 | 43 | f := "PANIC: %s\n%s" 44 | rec.Logger.Printf(f, err, stack) 45 | 46 | if rec.PrintStack { 47 | fmt.Fprintf(rw, f, err, stack) 48 | } 49 | 50 | if rec.ErrorHandlerFunc != nil { 51 | func() { 52 | defer func() { 53 | if err := recover(); err != nil { 54 | rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack()) 55 | rec.Logger.Printf("%s\n", debug.Stack()) 56 | } 57 | }() 58 | rec.ErrorHandlerFunc(err) 59 | }() 60 | } 61 | } 62 | }() 63 | 64 | next(rw, r) 65 | } 66 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/error.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net" 7 | "strings" 8 | ) 9 | 10 | // Redis nil reply, .e.g. when key does not exist. 11 | var Nil = errorf("redis: nil") 12 | 13 | // Redis transaction failed. 14 | var TxFailedErr = errorf("redis: transaction failed") 15 | 16 | type redisError struct { 17 | s string 18 | } 19 | 20 | func errorf(s string, args ...interface{}) redisError { 21 | return redisError{s: fmt.Sprintf(s, args...)} 22 | } 23 | 24 | func (err redisError) Error() string { 25 | return err.s 26 | } 27 | 28 | func isInternalError(err error) bool { 29 | _, ok := err.(redisError) 30 | return ok 31 | } 32 | 33 | func isNetworkError(err error) bool { 34 | if err == io.EOF { 35 | return true 36 | } 37 | _, ok := err.(net.Error) 38 | return ok 39 | } 40 | 41 | func isBadConn(err error, allowTimeout bool) bool { 42 | if err == nil { 43 | return false 44 | } 45 | if isInternalError(err) { 46 | return false 47 | } 48 | if allowTimeout { 49 | if netErr, ok := err.(net.Error); ok && netErr.Timeout() { 50 | return false 51 | } 52 | } 53 | return true 54 | } 55 | 56 | func isMovedError(err error) (moved bool, ask bool, addr string) { 57 | if _, ok := err.(redisError); !ok { 58 | return 59 | } 60 | 61 | s := err.Error() 62 | if strings.HasPrefix(s, "MOVED ") { 63 | moved = true 64 | } else if strings.HasPrefix(s, "ASK ") { 65 | ask = true 66 | } else { 67 | return 68 | } 69 | 70 | ind := strings.LastIndexByte(s, ' ') 71 | if ind == -1 { 72 | return false, false, "" 73 | } 74 | addr = s[ind+1:] 75 | return 76 | } 77 | 78 | // shouldRetry reports whether failed command should be retried. 79 | func shouldRetry(err error) bool { 80 | return isNetworkError(err) 81 | } 82 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/internal/pool/conn.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "net" 7 | "time" 8 | ) 9 | 10 | const defaultBufSize = 4096 11 | 12 | var noDeadline = time.Time{} 13 | 14 | type Conn struct { 15 | NetConn net.Conn 16 | Rd *bufio.Reader 17 | Buf []byte 18 | 19 | Inited bool 20 | UsedAt time.Time 21 | 22 | ReadTimeout time.Duration 23 | WriteTimeout time.Duration 24 | } 25 | 26 | func NewConn(netConn net.Conn) *Conn { 27 | cn := &Conn{ 28 | NetConn: netConn, 29 | Buf: make([]byte, defaultBufSize), 30 | 31 | UsedAt: time.Now(), 32 | } 33 | cn.Rd = bufio.NewReader(cn) 34 | return cn 35 | } 36 | 37 | func (cn *Conn) IsStale(timeout time.Duration) bool { 38 | return timeout > 0 && time.Since(cn.UsedAt) > timeout 39 | } 40 | 41 | func (cn *Conn) Read(b []byte) (int, error) { 42 | cn.UsedAt = time.Now() 43 | if cn.ReadTimeout != 0 { 44 | cn.NetConn.SetReadDeadline(cn.UsedAt.Add(cn.ReadTimeout)) 45 | } else { 46 | cn.NetConn.SetReadDeadline(noDeadline) 47 | } 48 | return cn.NetConn.Read(b) 49 | } 50 | 51 | func (cn *Conn) Write(b []byte) (int, error) { 52 | cn.UsedAt = time.Now() 53 | if cn.WriteTimeout != 0 { 54 | cn.NetConn.SetWriteDeadline(cn.UsedAt.Add(cn.WriteTimeout)) 55 | } else { 56 | cn.NetConn.SetWriteDeadline(noDeadline) 57 | } 58 | return cn.NetConn.Write(b) 59 | } 60 | 61 | func (cn *Conn) RemoteAddr() net.Addr { 62 | return cn.NetConn.RemoteAddr() 63 | } 64 | 65 | func (cn *Conn) ReadN(n int) ([]byte, error) { 66 | if d := n - cap(cn.Buf); d > 0 { 67 | cn.Buf = cn.Buf[:cap(cn.Buf)] 68 | cn.Buf = append(cn.Buf, make([]byte, d)...) 69 | } else { 70 | cn.Buf = cn.Buf[:n] 71 | } 72 | _, err := io.ReadFull(cn.Rd, cn.Buf) 73 | return cn.Buf, err 74 | } 75 | 76 | func (cn *Conn) Close() error { 77 | return cn.NetConn.Close() 78 | } 79 | -------------------------------------------------------------------------------- /vendor/gopkg.in/bsm/ratelimit.v1/README.md: -------------------------------------------------------------------------------- 1 | # RateLimit [![Build Status](https://travis-ci.org/bsm/ratelimit.png?branch=master)](https://travis-ci.org/bsm/ratelimit) 2 | 3 | Simple, thread-safe Go rate-limiter. 4 | Inspired by Antti Huima's algorithm on http://stackoverflow.com/a/668327 5 | 6 | ### Example 7 | 8 | ```go 9 | package main 10 | 11 | import ( 12 | "github.com/bsm/ratelimit" 13 | "log" 14 | ) 15 | 16 | func main() { 17 | // Create a new rate-limiter, allowing up-to 10 calls 18 | // per second 19 | rl := ratelimit.New(10, time.Second) 20 | 21 | for i:=0; i<20; i++ { 22 | if rl.Limit() { 23 | fmt.Println("DOH! Over limit!") 24 | } else { 25 | fmt.Println("OK") 26 | } 27 | } 28 | } 29 | ``` 30 | 31 | ### Licence 32 | 33 | ``` 34 | Copyright (c) 2015 Black Square Media 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining 37 | a copy of this software and associated documentation files (the 38 | "Software"), to deal in the Software without restriction, including 39 | without limitation the rights to use, copy, modify, merge, publish, 40 | distribute, sublicense, and/or sell copies of the Software, and to 41 | permit persons to whom the Software is furnished to do so, subject to 42 | the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be 45 | included in all copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 51 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 52 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 53 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 54 | ``` 55 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/proto/Makefile: -------------------------------------------------------------------------------- 1 | # Go support for Protocol Buffers - Google's data interchange format 2 | # 3 | # Copyright 2010 The Go Authors. All rights reserved. 4 | # https://github.com/golang/protobuf 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following disclaimer 14 | # in the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Google Inc. nor the names of its 17 | # contributors may be used to endorse or promote products derived from 18 | # this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | install: 33 | go install 34 | 35 | test: install generate-test-pbs 36 | go test 37 | 38 | 39 | generate-test-pbs: 40 | make install 41 | make -C testdata 42 | protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto 43 | make 44 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/internal/consistenthash/consistenthash.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2013 Google Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package consistenthash provides an implementation of a ring hash. 18 | package consistenthash 19 | 20 | import ( 21 | "hash/crc32" 22 | "sort" 23 | "strconv" 24 | ) 25 | 26 | type Hash func(data []byte) uint32 27 | 28 | type Map struct { 29 | hash Hash 30 | replicas int 31 | keys []int // Sorted 32 | hashMap map[int]string 33 | } 34 | 35 | func New(replicas int, fn Hash) *Map { 36 | m := &Map{ 37 | replicas: replicas, 38 | hash: fn, 39 | hashMap: make(map[int]string), 40 | } 41 | if m.hash == nil { 42 | m.hash = crc32.ChecksumIEEE 43 | } 44 | return m 45 | } 46 | 47 | // Returns true if there are no items available. 48 | func (m *Map) IsEmpty() bool { 49 | return len(m.keys) == 0 50 | } 51 | 52 | // Adds some keys to the hash. 53 | func (m *Map) Add(keys ...string) { 54 | for _, key := range keys { 55 | for i := 0; i < m.replicas; i++ { 56 | hash := int(m.hash([]byte(strconv.Itoa(i) + key))) 57 | m.keys = append(m.keys, hash) 58 | m.hashMap[hash] = key 59 | } 60 | } 61 | sort.Ints(m.keys) 62 | } 63 | 64 | // Gets the closest item in the hash to the provided key. 65 | func (m *Map) Get(key string) string { 66 | if m.IsEmpty() { 67 | return "" 68 | } 69 | 70 | hash := int(m.hash([]byte(key))) 71 | 72 | // Binary search for appropriate replica. 73 | idx := sort.Search(len(m.keys), func(i int) bool { return m.keys[i] >= hash }) 74 | 75 | // Means we have cycled back to the first replica. 76 | if idx == len(m.keys) { 77 | idx = 0 78 | } 79 | 80 | return m.hashMap[m.keys[idx]] 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/logger.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "bytes" 5 | 6 | "log" 7 | "net/http" 8 | "os" 9 | "text/template" 10 | "time" 11 | ) 12 | 13 | // LoggerEntry is the structure 14 | // passed to the template. 15 | type LoggerEntry struct { 16 | StartTime string 17 | Status int 18 | Duration time.Duration 19 | Hostname string 20 | Method string 21 | Path string 22 | } 23 | 24 | // LoggerDefaultFormat is the format 25 | // logged used by the default Logger instance. 26 | var LoggerDefaultFormat = "{{.StartTime}} | {{.Status}} | \t {{.Duration}} | {{.Hostname}} | {{.Method}} {{.Path}} \n" 27 | 28 | // LoggerDefaultDateFormat is the 29 | // format used for date by the 30 | // default Logger instance. 31 | var LoggerDefaultDateFormat = time.RFC3339 32 | 33 | // ALogger interface 34 | type ALogger interface { 35 | Println(v ...interface{}) 36 | Printf(format string, v ...interface{}) 37 | } 38 | 39 | // Logger is a middleware handler that logs the request as it goes in and the response as it goes out. 40 | type Logger struct { 41 | // ALogger implements just enough log.Logger interface to be compatible with other implementations 42 | ALogger 43 | dateFormat string 44 | template *template.Template 45 | } 46 | 47 | // NewLogger returns a new Logger instance 48 | func NewLogger() *Logger { 49 | logger := &Logger{ALogger: log.New(os.Stdout, "[negroni] ", 0), dateFormat: LoggerDefaultDateFormat} 50 | logger.SetFormat(LoggerDefaultFormat) 51 | return logger 52 | } 53 | 54 | func (l *Logger) SetFormat(format string) { 55 | l.template = template.Must(template.New("negroni_parser").Parse(format)) 56 | } 57 | 58 | func (l *Logger) SetDateFormat(format string) { 59 | l.dateFormat = format 60 | } 61 | 62 | func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 63 | start := time.Now() 64 | 65 | next(rw, r) 66 | 67 | res := rw.(ResponseWriter) 68 | log := LoggerEntry{ 69 | StartTime: start.Format(l.dateFormat), 70 | Status: res.Status(), 71 | Duration: time.Since(start), 72 | Hostname: r.Host, 73 | Method: r.Method, 74 | Path: r.URL.Path, 75 | } 76 | 77 | buff := &bytes.Buffer{} 78 | l.template.Execute(buff, log) 79 | l.Printf(buff.String()) 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/static.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "net/http" 5 | "path" 6 | "strings" 7 | ) 8 | 9 | // Static is a middleware handler that serves static files in the given 10 | // directory/filesystem. If the file does not exist on the filesystem, it 11 | // passes along to the next middleware in the chain. If you desire "fileserver" 12 | // type behavior where it returns a 404 for unfound files, you should consider 13 | // using http.FileServer from the Go stdlib. 14 | type Static struct { 15 | // Dir is the directory to serve static files from 16 | Dir http.FileSystem 17 | // Prefix is the optional prefix used to serve the static directory content 18 | Prefix string 19 | // IndexFile defines which file to serve as index if it exists. 20 | IndexFile string 21 | } 22 | 23 | // NewStatic returns a new instance of Static 24 | func NewStatic(directory http.FileSystem) *Static { 25 | return &Static{ 26 | Dir: directory, 27 | Prefix: "", 28 | IndexFile: "index.html", 29 | } 30 | } 31 | 32 | func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 33 | if r.Method != "GET" && r.Method != "HEAD" { 34 | next(rw, r) 35 | return 36 | } 37 | file := r.URL.Path 38 | // if we have a prefix, filter requests by stripping the prefix 39 | if s.Prefix != "" { 40 | if !strings.HasPrefix(file, s.Prefix) { 41 | next(rw, r) 42 | return 43 | } 44 | file = file[len(s.Prefix):] 45 | if file != "" && file[0] != '/' { 46 | next(rw, r) 47 | return 48 | } 49 | } 50 | f, err := s.Dir.Open(file) 51 | if err != nil { 52 | // discard the error? 53 | next(rw, r) 54 | return 55 | } 56 | defer f.Close() 57 | 58 | fi, err := f.Stat() 59 | if err != nil { 60 | next(rw, r) 61 | return 62 | } 63 | 64 | // try to serve index file 65 | if fi.IsDir() { 66 | // redirect if missing trailing slash 67 | if !strings.HasSuffix(r.URL.Path, "/") { 68 | http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound) 69 | return 70 | } 71 | 72 | file = path.Join(file, s.IndexFile) 73 | f, err = s.Dir.Open(file) 74 | if err != nil { 75 | next(rw, r) 76 | return 77 | } 78 | defer f.Close() 79 | 80 | fi, err = f.Stat() 81 | if err != nil || fi.IsDir() { 82 | next(rw, r) 83 | return 84 | } 85 | } 86 | 87 | http.ServeContent(rw, r, file, fi.ModTime(), f) 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt: -------------------------------------------------------------------------------- 1 | PACKAGE 2 | 3 | package goautoneg 4 | import "bitbucket.org/ww/goautoneg" 5 | 6 | HTTP Content-Type Autonegotiation. 7 | 8 | The functions in this package implement the behaviour specified in 9 | http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 10 | 11 | Copyright (c) 2011, Open Knowledge Foundation Ltd. 12 | All rights reserved. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are 16 | met: 17 | 18 | Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 21 | Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in 23 | the documentation and/or other materials provided with the 24 | distribution. 25 | 26 | Neither the name of the Open Knowledge Foundation Ltd. nor the 27 | names of its contributors may be used to endorse or promote 28 | products derived from this software without specific prior written 29 | permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 37 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 38 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 39 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 41 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | 43 | 44 | FUNCTIONS 45 | 46 | func Negotiate(header string, alternatives []string) (content_type string) 47 | Negotiate the most appropriate content_type given the accept header 48 | and a list of alternatives. 49 | 50 | func ParseAccept(header string) (accept []Accept) 51 | Parse an Accept Header string returning a sorted list 52 | of clauses 53 | 54 | 55 | TYPES 56 | 57 | type Accept struct { 58 | Type, SubType string 59 | Q float32 60 | Params map[string]string 61 | } 62 | Structure to represent a clause in an HTTP Accept Header 63 | 64 | 65 | SUBDIRECTORIES 66 | 67 | .hg 68 | -------------------------------------------------------------------------------- /weather/client.go: -------------------------------------------------------------------------------- 1 | package weather 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | "time" 9 | 10 | "strconv" 11 | 12 | "github.com/prometheus/client_golang/prometheus" 13 | ) 14 | 15 | const ( 16 | apiURL = "http://api.openweathermap.org" 17 | ) 18 | 19 | var ( 20 | client *weatherClient 21 | ) 22 | 23 | var ( 24 | requestsDuration = prometheus.NewHistogram(prometheus.HistogramOpts{ 25 | Name: "myapp_weather_request_duration_seconds", 26 | Help: "The duration of the requests to the weather service.", 27 | }) 28 | 29 | requestsCurrent = prometheus.NewGauge(prometheus.GaugeOpts{ 30 | Name: "myapp_weather_requests_current", 31 | Help: "The current number of requests to the weather service.", 32 | }) 33 | 34 | requestsStatus = prometheus.NewCounterVec(prometheus.CounterOpts{ 35 | Name: "myapp_weather_requests_total", 36 | Help: "The total number of requests to the weather service by status.", 37 | }, []string{"status"}) 38 | 39 | clientErrors = prometheus.NewCounter(prometheus.CounterOpts{ 40 | Name: "myapp_weather_errors", 41 | Help: "The total number of weather client errors", 42 | }) 43 | ) 44 | 45 | func init() { 46 | prometheus.MustRegister(requestsDuration) 47 | prometheus.MustRegister(requestsCurrent) 48 | prometheus.MustRegister(requestsStatus) 49 | prometheus.MustRegister(clientErrors) 50 | } 51 | 52 | type weatherClient struct { 53 | httpClient *http.Client 54 | apiKey string 55 | } 56 | 57 | func (w *weatherClient) do(method string, path string, params map[string]string) (resp *http.Response, err error) { 58 | now := time.Now() 59 | requestsCurrent.Inc() 60 | defer func() { 61 | requestsDuration.Observe(time.Since(now).Seconds()) 62 | requestsCurrent.Dec() 63 | if resp != nil { 64 | requestsStatus.WithLabelValues(strconv.Itoa(resp.StatusCode)).Inc() 65 | } 66 | if err != nil { 67 | clientErrors.Inc() 68 | } 69 | }() 70 | url := fmt.Sprintf("%s/%s?appid=%s", apiURL, path, w.apiKey) 71 | for k, v := range params { 72 | url += fmt.Sprintf("&%s=%s", k, v) 73 | } 74 | fmt.Printf("DEBUG: %s\n", url) 75 | request, err := http.NewRequest(method, url, nil) 76 | if err != nil { 77 | return nil, err 78 | } 79 | return w.httpClient.Do(request) 80 | } 81 | 82 | func getClient() (*weatherClient, error) { 83 | apiKey := os.Getenv("WEATHER_API_KEY") 84 | if apiKey == "" { 85 | return nil, errors.New("must set WEATHER_API_KEY env") 86 | } 87 | if client == nil { 88 | client = &weatherClient{ 89 | httpClient: &http.Client{Timeout: time.Second * 15}, 90 | apiKey: apiKey, 91 | } 92 | } 93 | return client, nil 94 | } 95 | -------------------------------------------------------------------------------- /vendor/gopkg.in/bsm/ratelimit.v1/ratelimit.go: -------------------------------------------------------------------------------- 1 | /* 2 | Simple, thread-safe Go rate-limiter. 3 | Inspired by Antti Huima's algorithm on http://stackoverflow.com/a/668327 4 | 5 | Example: 6 | 7 | // Create a new rate-limiter, allowing up-to 10 calls 8 | // per second 9 | rl := ratelimit.New(10, time.Second) 10 | 11 | for i:=0; i<20; i++ { 12 | if rl.Limit() { 13 | fmt.Println("DOH! Over limit!") 14 | } else { 15 | fmt.Println("OK") 16 | } 17 | } 18 | */ 19 | package ratelimit 20 | 21 | import ( 22 | "sync/atomic" 23 | "time" 24 | ) 25 | 26 | // RateLimiter instances are thread-safe. 27 | type RateLimiter struct { 28 | rate, allowance, max, unit, lastCheck uint64 29 | } 30 | 31 | // New creates a new rate limiter instance 32 | func New(rate int, per time.Duration) *RateLimiter { 33 | nano := uint64(per) 34 | if nano < 1 { 35 | nano = uint64(time.Second) 36 | } 37 | if rate < 1 { 38 | rate = 1 39 | } 40 | 41 | return &RateLimiter{ 42 | rate: uint64(rate), // store the rate 43 | allowance: uint64(rate) * nano, // set our allowance to max in the beginning 44 | max: uint64(rate) * nano, // remember our maximum allowance 45 | unit: nano, // remember our unit size 46 | 47 | lastCheck: unixNano(), 48 | } 49 | } 50 | 51 | // UpdateRate allows to update the allowed rate 52 | func (rl *RateLimiter) UpdateRate(rate int) { 53 | atomic.StoreUint64(&rl.rate, uint64(rate)) 54 | atomic.StoreUint64(&rl.max, uint64(rate)*rl.unit) 55 | } 56 | 57 | // Limit returns true if rate was exceeded 58 | func (rl *RateLimiter) Limit() bool { 59 | // Calculate the number of ns that have passed since our last call 60 | now := unixNano() 61 | passed := now - atomic.SwapUint64(&rl.lastCheck, now) 62 | 63 | // Add them to our allowance 64 | rate := atomic.LoadUint64(&rl.rate) 65 | current := atomic.AddUint64(&rl.allowance, passed*rate) 66 | 67 | // Ensure our allowance is not over maximum 68 | if max := atomic.LoadUint64(&rl.max); current > max { 69 | atomic.AddUint64(&rl.allowance, max-current) 70 | current = max 71 | } 72 | 73 | // If our allowance is less than one unit, rate-limit! 74 | if current < rl.unit { 75 | return true 76 | } 77 | 78 | // Not limited, subtract a unit 79 | atomic.AddUint64(&rl.allowance, -rl.unit) 80 | return false 81 | } 82 | 83 | // Undo reverts the last Limit() call, returning consumed allowance 84 | func (rl *RateLimiter) Undo() { 85 | current := atomic.AddUint64(&rl.allowance, rl.unit) 86 | 87 | // Ensure our allowance is not over maximum 88 | if max := atomic.LoadUint64(&rl.max); current > max { 89 | atomic.AddUint64(&rl.allowance, max-current) 90 | } 91 | } 92 | 93 | // now as unix nanoseconds 94 | func unixNano() uint64 { 95 | return uint64(time.Now().UnixNano()) 96 | } 97 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/timer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import "time" 17 | 18 | // Observer is the interface that wraps the Observe method, which is used by 19 | // Histogram and Summary to add observations. 20 | type Observer interface { 21 | Observe(float64) 22 | } 23 | 24 | // The ObserverFunc type is an adapter to allow the use of ordinary 25 | // functions as Observers. If f is a function with the appropriate 26 | // signature, ObserverFunc(f) is an Observer that calls f. 27 | // 28 | // This adapter is usually used in connection with the Timer type, and there are 29 | // two general use cases: 30 | // 31 | // The most common one is to use a Gauge as the Observer for a Timer. 32 | // See the "Gauge" Timer example. 33 | // 34 | // The more advanced use case is to create a function that dynamically decides 35 | // which Observer to use for observing the duration. See the "Complex" Timer 36 | // example. 37 | type ObserverFunc func(float64) 38 | 39 | // Observe calls f(value). It implements Observer. 40 | func (f ObserverFunc) Observe(value float64) { 41 | f(value) 42 | } 43 | 44 | // Timer is a helper type to time functions. Use NewTimer to create new 45 | // instances. 46 | type Timer struct { 47 | begin time.Time 48 | observer Observer 49 | } 50 | 51 | // NewTimer creates a new Timer. The provided Observer is used to observe a 52 | // duration in seconds. Timer is usually used to time a function call in the 53 | // following way: 54 | // func TimeMe() { 55 | // timer := NewTimer(myHistogram) 56 | // defer timer.ObserveDuration() 57 | // // Do actual work. 58 | // } 59 | func NewTimer(o Observer) *Timer { 60 | return &Timer{ 61 | begin: time.Now(), 62 | observer: o, 63 | } 64 | } 65 | 66 | // ObserveDuration records the duration passed since the Timer was created with 67 | // NewTimer. It calls the Observe method of the Observer provided during 68 | // construction with the duration in seconds as an argument. ObserveDuration is 69 | // usually called with a defer statement. 70 | func (t *Timer) ObserveDuration() { 71 | if t.observer != nil { 72 | t.observer.Observe(time.Since(t.begin).Seconds()) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/internal/pool/pool_sticky.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "errors" 5 | "sync" 6 | ) 7 | 8 | type StickyConnPool struct { 9 | pool *ConnPool 10 | reusable bool 11 | 12 | cn *Conn 13 | closed bool 14 | mx sync.Mutex 15 | } 16 | 17 | var _ Pooler = (*StickyConnPool)(nil) 18 | 19 | func NewStickyConnPool(pool *ConnPool, reusable bool) *StickyConnPool { 20 | return &StickyConnPool{ 21 | pool: pool, 22 | reusable: reusable, 23 | } 24 | } 25 | 26 | func (p *StickyConnPool) First() *Conn { 27 | p.mx.Lock() 28 | cn := p.cn 29 | p.mx.Unlock() 30 | return cn 31 | } 32 | 33 | func (p *StickyConnPool) Get() (*Conn, error) { 34 | defer p.mx.Unlock() 35 | p.mx.Lock() 36 | 37 | if p.closed { 38 | return nil, ErrClosed 39 | } 40 | if p.cn != nil { 41 | return p.cn, nil 42 | } 43 | 44 | cn, err := p.pool.Get() 45 | if err != nil { 46 | return nil, err 47 | } 48 | p.cn = cn 49 | return cn, nil 50 | } 51 | 52 | func (p *StickyConnPool) put() (err error) { 53 | err = p.pool.Put(p.cn) 54 | p.cn = nil 55 | return err 56 | } 57 | 58 | func (p *StickyConnPool) Put(cn *Conn) error { 59 | defer p.mx.Unlock() 60 | p.mx.Lock() 61 | if p.closed { 62 | return ErrClosed 63 | } 64 | if p.cn != cn { 65 | panic("p.cn != cn") 66 | } 67 | return nil 68 | } 69 | 70 | func (p *StickyConnPool) remove(reason error) error { 71 | err := p.pool.Remove(p.cn, reason) 72 | p.cn = nil 73 | return err 74 | } 75 | 76 | func (p *StickyConnPool) Remove(cn *Conn, reason error) error { 77 | defer p.mx.Unlock() 78 | p.mx.Lock() 79 | if p.closed { 80 | return nil 81 | } 82 | if p.cn == nil { 83 | panic("p.cn == nil") 84 | } 85 | if cn != nil && p.cn != cn { 86 | panic("p.cn != cn") 87 | } 88 | return p.remove(reason) 89 | } 90 | 91 | func (p *StickyConnPool) Len() int { 92 | defer p.mx.Unlock() 93 | p.mx.Lock() 94 | if p.cn == nil { 95 | return 0 96 | } 97 | return 1 98 | } 99 | 100 | func (p *StickyConnPool) FreeLen() int { 101 | defer p.mx.Unlock() 102 | p.mx.Lock() 103 | if p.cn == nil { 104 | return 1 105 | } 106 | return 0 107 | } 108 | 109 | func (p *StickyConnPool) Stats() *PoolStats { return nil } 110 | 111 | func (p *StickyConnPool) Close() error { 112 | defer p.mx.Unlock() 113 | p.mx.Lock() 114 | if p.closed { 115 | return ErrClosed 116 | } 117 | p.closed = true 118 | var err error 119 | if p.cn != nil { 120 | if p.reusable { 121 | err = p.put() 122 | } else { 123 | reason := errors.New("redis: sticky not reusable connection") 124 | err = p.remove(reason) 125 | } 126 | } 127 | return err 128 | } 129 | 130 | func (p *StickyConnPool) Closed() bool { 131 | p.mx.Lock() 132 | closed := p.closed 133 | p.mx.Unlock() 134 | return closed 135 | } 136 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/buddyinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "os" 21 | "strconv" 22 | "strings" 23 | ) 24 | 25 | // A BuddyInfo is the details parsed from /proc/buddyinfo. 26 | // The data is comprised of an array of free fragments of each size. 27 | // The sizes are 2^n*PAGE_SIZE, where n is the array index. 28 | type BuddyInfo struct { 29 | Node string 30 | Zone string 31 | Sizes []float64 32 | } 33 | 34 | // NewBuddyInfo reads the buddyinfo statistics. 35 | func NewBuddyInfo() ([]BuddyInfo, error) { 36 | fs, err := NewFS(DefaultMountPoint) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return fs.NewBuddyInfo() 42 | } 43 | 44 | // NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem. 45 | func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) { 46 | file, err := os.Open(fs.Path("buddyinfo")) 47 | if err != nil { 48 | return nil, err 49 | } 50 | defer file.Close() 51 | 52 | return parseBuddyInfo(file) 53 | } 54 | 55 | func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { 56 | var ( 57 | buddyInfo = []BuddyInfo{} 58 | scanner = bufio.NewScanner(r) 59 | bucketCount = -1 60 | ) 61 | 62 | for scanner.Scan() { 63 | var err error 64 | line := scanner.Text() 65 | parts := strings.Fields(string(line)) 66 | 67 | if len(parts) < 4 { 68 | return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo") 69 | } 70 | 71 | node := strings.TrimRight(parts[1], ",") 72 | zone := strings.TrimRight(parts[3], ",") 73 | arraySize := len(parts[4:]) 74 | 75 | if bucketCount == -1 { 76 | bucketCount = arraySize 77 | } else { 78 | if bucketCount != arraySize { 79 | return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize) 80 | } 81 | } 82 | 83 | sizes := make([]float64, arraySize) 84 | for i := 0; i < arraySize; i++ { 85 | sizes[i], err = strconv.ParseFloat(parts[i+4], 64) 86 | if err != nil { 87 | return nil, fmt.Errorf("invalid value in buddyinfo: %s", err) 88 | } 89 | } 90 | 91 | buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes}) 92 | } 93 | 94 | return buddyInfo, scanner.Err() 95 | } 96 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package expfmt 15 | 16 | import ( 17 | "fmt" 18 | "io" 19 | "net/http" 20 | 21 | "github.com/golang/protobuf/proto" 22 | "github.com/matttproud/golang_protobuf_extensions/pbutil" 23 | "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" 24 | 25 | dto "github.com/prometheus/client_model/go" 26 | ) 27 | 28 | // Encoder types encode metric families into an underlying wire protocol. 29 | type Encoder interface { 30 | Encode(*dto.MetricFamily) error 31 | } 32 | 33 | type encoder func(*dto.MetricFamily) error 34 | 35 | func (e encoder) Encode(v *dto.MetricFamily) error { 36 | return e(v) 37 | } 38 | 39 | // Negotiate returns the Content-Type based on the given Accept header. 40 | // If no appropriate accepted type is found, FmtText is returned. 41 | func Negotiate(h http.Header) Format { 42 | for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { 43 | // Check for protocol buffer 44 | if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { 45 | switch ac.Params["encoding"] { 46 | case "delimited": 47 | return FmtProtoDelim 48 | case "text": 49 | return FmtProtoText 50 | case "compact-text": 51 | return FmtProtoCompact 52 | } 53 | } 54 | // Check for text format. 55 | ver := ac.Params["version"] 56 | if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { 57 | return FmtText 58 | } 59 | } 60 | return FmtText 61 | } 62 | 63 | // NewEncoder returns a new encoder based on content type negotiation. 64 | func NewEncoder(w io.Writer, format Format) Encoder { 65 | switch format { 66 | case FmtProtoDelim: 67 | return encoder(func(v *dto.MetricFamily) error { 68 | _, err := pbutil.WriteDelimited(w, v) 69 | return err 70 | }) 71 | case FmtProtoCompact: 72 | return encoder(func(v *dto.MetricFamily) error { 73 | _, err := fmt.Fprintln(w, v.String()) 74 | return err 75 | }) 76 | case FmtProtoText: 77 | return encoder(func(v *dto.MetricFamily) error { 78 | _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) 79 | return err 80 | }) 81 | case FmtText: 82 | return encoder(func(v *dto.MetricFamily) error { 83 | _, err := MetricFamilyToText(w, v) 84 | return err 85 | }) 86 | } 87 | panic("expfmt.NewEncoder: unknown format") 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fingerprinting.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "strconv" 19 | ) 20 | 21 | // Fingerprint provides a hash-capable representation of a Metric. 22 | // For our purposes, FNV-1A 64-bit is used. 23 | type Fingerprint uint64 24 | 25 | // FingerprintFromString transforms a string representation into a Fingerprint. 26 | func FingerprintFromString(s string) (Fingerprint, error) { 27 | num, err := strconv.ParseUint(s, 16, 64) 28 | return Fingerprint(num), err 29 | } 30 | 31 | // ParseFingerprint parses the input string into a fingerprint. 32 | func ParseFingerprint(s string) (Fingerprint, error) { 33 | num, err := strconv.ParseUint(s, 16, 64) 34 | if err != nil { 35 | return 0, err 36 | } 37 | return Fingerprint(num), nil 38 | } 39 | 40 | func (f Fingerprint) String() string { 41 | return fmt.Sprintf("%016x", uint64(f)) 42 | } 43 | 44 | // Fingerprints represents a collection of Fingerprint subject to a given 45 | // natural sorting scheme. It implements sort.Interface. 46 | type Fingerprints []Fingerprint 47 | 48 | // Len implements sort.Interface. 49 | func (f Fingerprints) Len() int { 50 | return len(f) 51 | } 52 | 53 | // Less implements sort.Interface. 54 | func (f Fingerprints) Less(i, j int) bool { 55 | return f[i] < f[j] 56 | } 57 | 58 | // Swap implements sort.Interface. 59 | func (f Fingerprints) Swap(i, j int) { 60 | f[i], f[j] = f[j], f[i] 61 | } 62 | 63 | // FingerprintSet is a set of Fingerprints. 64 | type FingerprintSet map[Fingerprint]struct{} 65 | 66 | // Equal returns true if both sets contain the same elements (and not more). 67 | func (s FingerprintSet) Equal(o FingerprintSet) bool { 68 | if len(s) != len(o) { 69 | return false 70 | } 71 | 72 | for k := range s { 73 | if _, ok := o[k]; !ok { 74 | return false 75 | } 76 | } 77 | 78 | return true 79 | } 80 | 81 | // Intersection returns the elements contained in both sets. 82 | func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet { 83 | myLength, otherLength := len(s), len(o) 84 | if myLength == 0 || otherLength == 0 { 85 | return FingerprintSet{} 86 | } 87 | 88 | subSet := s 89 | superSet := o 90 | 91 | if otherLength < myLength { 92 | subSet = o 93 | superSet = s 94 | } 95 | 96 | out := FingerprintSet{} 97 | 98 | for k := range subSet { 99 | if _, ok := superSet[k]; ok { 100 | out[k] = struct{}{} 101 | } 102 | } 103 | 104 | return out 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "errors" 20 | "io" 21 | 22 | "github.com/golang/protobuf/proto" 23 | ) 24 | 25 | var errInvalidVarint = errors.New("invalid varint32 encountered") 26 | 27 | // ReadDelimited decodes a message from the provided length-delimited stream, 28 | // where the length is encoded as 32-bit varint prefix to the message body. 29 | // It returns the total number of bytes read and any applicable error. This is 30 | // roughly equivalent to the companion Java API's 31 | // MessageLite#parseDelimitedFrom. As per the reader contract, this function 32 | // calls r.Read repeatedly as required until exactly one message including its 33 | // prefix is read and decoded (or an error has occurred). The function never 34 | // reads more bytes from the stream than required. The function never returns 35 | // an error if a message has been read and decoded correctly, even if the end 36 | // of the stream has been reached in doing so. In that case, any subsequent 37 | // calls return (0, io.EOF). 38 | func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { 39 | // Per AbstractParser#parsePartialDelimitedFrom with 40 | // CodedInputStream#readRawVarint32. 41 | var headerBuf [binary.MaxVarintLen32]byte 42 | var bytesRead, varIntBytes int 43 | var messageLength uint64 44 | for varIntBytes == 0 { // i.e. no varint has been decoded yet. 45 | if bytesRead >= len(headerBuf) { 46 | return bytesRead, errInvalidVarint 47 | } 48 | // We have to read byte by byte here to avoid reading more bytes 49 | // than required. Each read byte is appended to what we have 50 | // read before. 51 | newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) 52 | if newBytesRead == 0 { 53 | if err != nil { 54 | return bytesRead, err 55 | } 56 | // A Reader should not return (0, nil), but if it does, 57 | // it should be treated as no-op (according to the 58 | // Reader contract). So let's go on... 59 | continue 60 | } 61 | bytesRead += newBytesRead 62 | // Now present everything read so far to the varint decoder and 63 | // see if a varint can be decoded already. 64 | messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead]) 65 | } 66 | 67 | messageBuf := make([]byte, messageLength) 68 | newBytesRead, err := io.ReadFull(r, messageBuf) 69 | bytesRead += newBytesRead 70 | if err != nil { 71 | return bytesRead, err 72 | } 73 | 74 | return bytesRead, proto.Unmarshal(messageBuf, m) 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package context stores values shared during a request lifetime. 7 | 8 | Note: gorilla/context, having been born well before `context.Context` existed, 9 | does not play well > with the shallow copying of the request that 10 | [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) 11 | (added to net/http Go 1.7 onwards) performs. You should either use *just* 12 | gorilla/context, or moving forward, the new `http.Request.Context()`. 13 | 14 | For example, a router can set variables extracted from the URL and later 15 | application handlers can access those values, or it can be used to store 16 | sessions values to be saved at the end of a request. There are several 17 | others common uses. 18 | 19 | The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: 20 | 21 | http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 22 | 23 | Here's the basic usage: first define the keys that you will need. The key 24 | type is interface{} so a key can be of any type that supports equality. 25 | Here we define a key using a custom int type to avoid name collisions: 26 | 27 | package foo 28 | 29 | import ( 30 | "github.com/gorilla/context" 31 | ) 32 | 33 | type key int 34 | 35 | const MyKey key = 0 36 | 37 | Then set a variable. Variables are bound to an http.Request object, so you 38 | need a request instance to set a value: 39 | 40 | context.Set(r, MyKey, "bar") 41 | 42 | The application can later access the variable using the same key you provided: 43 | 44 | func MyHandler(w http.ResponseWriter, r *http.Request) { 45 | // val is "bar". 46 | val := context.Get(r, foo.MyKey) 47 | 48 | // returns ("bar", true) 49 | val, ok := context.GetOk(r, foo.MyKey) 50 | // ... 51 | } 52 | 53 | And that's all about the basic usage. We discuss some other ideas below. 54 | 55 | Any type can be stored in the context. To enforce a given type, make the key 56 | private and wrap Get() and Set() to accept and return values of a specific 57 | type: 58 | 59 | type key int 60 | 61 | const mykey key = 0 62 | 63 | // GetMyKey returns a value for this package from the request values. 64 | func GetMyKey(r *http.Request) SomeType { 65 | if rv := context.Get(r, mykey); rv != nil { 66 | return rv.(SomeType) 67 | } 68 | return nil 69 | } 70 | 71 | // SetMyKey sets a value for this package in the request values. 72 | func SetMyKey(r *http.Request, val SomeType) { 73 | context.Set(r, mykey, val) 74 | } 75 | 76 | Variables must be cleared at the end of a request, to remove all values 77 | that were stored. This can be done in an http.Handler, after a request was 78 | served. Just call Clear() passing the request: 79 | 80 | context.Clear(r) 81 | 82 | ...or use ClearHandler(), which conveniently wraps an http.Handler to clear 83 | variables at the end of a request lifetime. 84 | 85 | The Routers from the packages gorilla/mux and gorilla/pat call Clear() 86 | so if you are using either of them you don't need to clear the context manually. 87 | */ 88 | package context 89 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/internal/hashtag/hashtag.go: -------------------------------------------------------------------------------- 1 | package hashtag 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | ) 7 | 8 | const SlotNumber = 16384 9 | 10 | // CRC16 implementation according to CCITT standards. 11 | // Copyright 2001-2010 Georges Menie (www.menie.org) 12 | // Copyright 2013 The Go Authors. All rights reserved. 13 | // http://redis.io/topics/cluster-spec#appendix-a-crc16-reference-implementation-in-ansi-c 14 | var crc16tab = [256]uint16{ 15 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 16 | 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 17 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 18 | 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 19 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 20 | 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 21 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 22 | 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 23 | 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 24 | 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 25 | 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 26 | 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 27 | 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 28 | 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 29 | 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 30 | 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 31 | 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 32 | 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 33 | 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 34 | 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 35 | 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 36 | 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 37 | 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 38 | 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 39 | 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 40 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 41 | 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 42 | 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 43 | 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 44 | 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 45 | 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 46 | 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, 47 | } 48 | 49 | func Key(key string) string { 50 | if s := strings.IndexByte(key, '{'); s > -1 { 51 | if e := strings.IndexByte(key[s+1:], '}'); e > 0 { 52 | return key[s+1 : s+e+1] 53 | } 54 | } 55 | return key 56 | } 57 | 58 | // hashSlot returns a consistent slot number between 0 and 16383 59 | // for any given string key. 60 | func Slot(key string) int { 61 | key = Key(key) 62 | if key == "" { 63 | return rand.Intn(SlotNumber) 64 | } 65 | return int(crc16sum(key)) % SlotNumber 66 | } 67 | 68 | func crc16sum(key string) (crc uint16) { 69 | for i := 0; i < len(key); i++ { 70 | crc = (crc << 8) ^ crc16tab[(byte(crc>>8)^key[i])&0x00ff] 71 | } 72 | return 73 | } 74 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/pipeline.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "sync" 5 | "sync/atomic" 6 | 7 | "gopkg.in/redis.v3/internal/pool" 8 | ) 9 | 10 | // Pipeline implements pipelining as described in 11 | // http://redis.io/topics/pipelining. It's safe for concurrent use 12 | // by multiple goroutines. 13 | type Pipeline struct { 14 | commandable 15 | 16 | client baseClient 17 | 18 | mu sync.Mutex // protects cmds 19 | cmds []Cmder 20 | 21 | closed int32 22 | } 23 | 24 | func (c *Client) Pipeline() *Pipeline { 25 | pipe := &Pipeline{ 26 | client: c.baseClient, 27 | cmds: make([]Cmder, 0, 10), 28 | } 29 | pipe.commandable.process = pipe.process 30 | return pipe 31 | } 32 | 33 | func (c *Client) Pipelined(fn func(*Pipeline) error) ([]Cmder, error) { 34 | pipe := c.Pipeline() 35 | if err := fn(pipe); err != nil { 36 | return nil, err 37 | } 38 | cmds, err := pipe.Exec() 39 | _ = pipe.Close() 40 | return cmds, err 41 | } 42 | 43 | func (pipe *Pipeline) process(cmd Cmder) { 44 | pipe.mu.Lock() 45 | pipe.cmds = append(pipe.cmds, cmd) 46 | pipe.mu.Unlock() 47 | } 48 | 49 | // Close closes the pipeline, releasing any open resources. 50 | func (pipe *Pipeline) Close() error { 51 | atomic.StoreInt32(&pipe.closed, 1) 52 | pipe.Discard() 53 | return nil 54 | } 55 | 56 | func (pipe *Pipeline) isClosed() bool { 57 | return atomic.LoadInt32(&pipe.closed) == 1 58 | } 59 | 60 | // Discard resets the pipeline and discards queued commands. 61 | func (pipe *Pipeline) Discard() error { 62 | defer pipe.mu.Unlock() 63 | pipe.mu.Lock() 64 | if pipe.isClosed() { 65 | return pool.ErrClosed 66 | } 67 | pipe.cmds = pipe.cmds[:0] 68 | return nil 69 | } 70 | 71 | // Exec executes all previously queued commands using one 72 | // client-server roundtrip. 73 | // 74 | // Exec always returns list of commands and error of the first failed 75 | // command if any. 76 | func (pipe *Pipeline) Exec() (cmds []Cmder, retErr error) { 77 | if pipe.isClosed() { 78 | return nil, pool.ErrClosed 79 | } 80 | 81 | defer pipe.mu.Unlock() 82 | pipe.mu.Lock() 83 | 84 | if len(pipe.cmds) == 0 { 85 | return pipe.cmds, nil 86 | } 87 | 88 | cmds = pipe.cmds 89 | pipe.cmds = make([]Cmder, 0, 10) 90 | 91 | failedCmds := cmds 92 | for i := 0; i <= pipe.client.opt.MaxRetries; i++ { 93 | cn, err := pipe.client.conn() 94 | if err != nil { 95 | setCmdsErr(failedCmds, err) 96 | return cmds, err 97 | } 98 | 99 | if i > 0 { 100 | resetCmds(failedCmds) 101 | } 102 | failedCmds, err = execCmds(cn, failedCmds) 103 | pipe.client.putConn(cn, err, false) 104 | if err != nil && retErr == nil { 105 | retErr = err 106 | } 107 | if len(failedCmds) == 0 { 108 | break 109 | } 110 | } 111 | 112 | return cmds, retErr 113 | } 114 | 115 | func execCmds(cn *pool.Conn, cmds []Cmder) ([]Cmder, error) { 116 | if err := writeCmd(cn, cmds...); err != nil { 117 | setCmdsErr(cmds, err) 118 | return cmds, err 119 | } 120 | 121 | var firstCmdErr error 122 | var failedCmds []Cmder 123 | for _, cmd := range cmds { 124 | err := cmd.readReply(cn) 125 | if err == nil { 126 | continue 127 | } 128 | if firstCmdErr == nil { 129 | firstCmdErr = err 130 | } 131 | if shouldRetry(err) { 132 | failedCmds = append(failedCmds, cmd) 133 | } 134 | } 135 | 136 | return failedCmds, firstCmdErr 137 | } 138 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/silence.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | "regexp" 20 | "time" 21 | ) 22 | 23 | // Matcher describes a matches the value of a given label. 24 | type Matcher struct { 25 | Name LabelName `json:"name"` 26 | Value string `json:"value"` 27 | IsRegex bool `json:"isRegex"` 28 | } 29 | 30 | func (m *Matcher) UnmarshalJSON(b []byte) error { 31 | type plain Matcher 32 | if err := json.Unmarshal(b, (*plain)(m)); err != nil { 33 | return err 34 | } 35 | 36 | if len(m.Name) == 0 { 37 | return fmt.Errorf("label name in matcher must not be empty") 38 | } 39 | if m.IsRegex { 40 | if _, err := regexp.Compile(m.Value); err != nil { 41 | return err 42 | } 43 | } 44 | return nil 45 | } 46 | 47 | // Validate returns true iff all fields of the matcher have valid values. 48 | func (m *Matcher) Validate() error { 49 | if !m.Name.IsValid() { 50 | return fmt.Errorf("invalid name %q", m.Name) 51 | } 52 | if m.IsRegex { 53 | if _, err := regexp.Compile(m.Value); err != nil { 54 | return fmt.Errorf("invalid regular expression %q", m.Value) 55 | } 56 | } else if !LabelValue(m.Value).IsValid() || len(m.Value) == 0 { 57 | return fmt.Errorf("invalid value %q", m.Value) 58 | } 59 | return nil 60 | } 61 | 62 | // Silence defines the representation of a silence definiton 63 | // in the Prometheus eco-system. 64 | type Silence struct { 65 | ID uint64 `json:"id,omitempty"` 66 | 67 | Matchers []*Matcher `json:"matchers"` 68 | 69 | StartsAt time.Time `json:"startsAt"` 70 | EndsAt time.Time `json:"endsAt"` 71 | 72 | CreatedAt time.Time `json:"createdAt,omitempty"` 73 | CreatedBy string `json:"createdBy"` 74 | Comment string `json:"comment,omitempty"` 75 | } 76 | 77 | // Validate returns true iff all fields of the silence have valid values. 78 | func (s *Silence) Validate() error { 79 | if len(s.Matchers) == 0 { 80 | return fmt.Errorf("at least one matcher required") 81 | } 82 | for _, m := range s.Matchers { 83 | if err := m.Validate(); err != nil { 84 | return fmt.Errorf("invalid matcher: %s", err) 85 | } 86 | } 87 | if s.StartsAt.IsZero() { 88 | return fmt.Errorf("start time missing") 89 | } 90 | if s.EndsAt.IsZero() { 91 | return fmt.Errorf("end time missing") 92 | } 93 | if s.EndsAt.Before(s.StartsAt) { 94 | return fmt.Errorf("start time must be before end time") 95 | } 96 | if s.CreatedBy == "" { 97 | return fmt.Errorf("creator information missing") 98 | } 99 | if s.Comment == "" { 100 | return fmt.Errorf("comment missing") 101 | } 102 | if s.CreatedAt.IsZero() { 103 | return fmt.Errorf("creation timestamp missing") 104 | } 105 | return nil 106 | } 107 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/metric.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "regexp" 19 | "sort" 20 | "strings" 21 | ) 22 | 23 | var ( 24 | separator = []byte{0} 25 | // MetricNameRE is a regular expression matching valid metric 26 | // names. Note that the IsValidMetricName function performs the same 27 | // check but faster than a match with this regular expression. 28 | MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`) 29 | ) 30 | 31 | // A Metric is similar to a LabelSet, but the key difference is that a Metric is 32 | // a singleton and refers to one and only one stream of samples. 33 | type Metric LabelSet 34 | 35 | // Equal compares the metrics. 36 | func (m Metric) Equal(o Metric) bool { 37 | return LabelSet(m).Equal(LabelSet(o)) 38 | } 39 | 40 | // Before compares the metrics' underlying label sets. 41 | func (m Metric) Before(o Metric) bool { 42 | return LabelSet(m).Before(LabelSet(o)) 43 | } 44 | 45 | // Clone returns a copy of the Metric. 46 | func (m Metric) Clone() Metric { 47 | clone := make(Metric, len(m)) 48 | for k, v := range m { 49 | clone[k] = v 50 | } 51 | return clone 52 | } 53 | 54 | func (m Metric) String() string { 55 | metricName, hasName := m[MetricNameLabel] 56 | numLabels := len(m) - 1 57 | if !hasName { 58 | numLabels = len(m) 59 | } 60 | labelStrings := make([]string, 0, numLabels) 61 | for label, value := range m { 62 | if label != MetricNameLabel { 63 | labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value)) 64 | } 65 | } 66 | 67 | switch numLabels { 68 | case 0: 69 | if hasName { 70 | return string(metricName) 71 | } 72 | return "{}" 73 | default: 74 | sort.Strings(labelStrings) 75 | return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", ")) 76 | } 77 | } 78 | 79 | // Fingerprint returns a Metric's Fingerprint. 80 | func (m Metric) Fingerprint() Fingerprint { 81 | return LabelSet(m).Fingerprint() 82 | } 83 | 84 | // FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing 85 | // algorithm, which is, however, more susceptible to hash collisions. 86 | func (m Metric) FastFingerprint() Fingerprint { 87 | return LabelSet(m).FastFingerprint() 88 | } 89 | 90 | // IsValidMetricName returns true iff name matches the pattern of MetricNameRE. 91 | // This function, however, does not use MetricNameRE for the check but a much 92 | // faster hardcoded implementation. 93 | func IsValidMetricName(n LabelValue) bool { 94 | if len(n) == 0 { 95 | return false 96 | } 97 | for i, b := range n { 98 | if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) { 99 | return false 100 | } 101 | } 102 | return true 103 | } 104 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/response_writer.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | ) 9 | 10 | // ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about 11 | // the response. It is recommended that middleware handlers use this construct to wrap a responsewriter 12 | // if the functionality calls for it. 13 | type ResponseWriter interface { 14 | http.ResponseWriter 15 | http.Flusher 16 | // Status returns the status code of the response or 200 if the response has 17 | // not been written (as this is the default response code in net/http) 18 | Status() int 19 | // Written returns whether or not the ResponseWriter has been written. 20 | Written() bool 21 | // Size returns the size of the response body. 22 | Size() int 23 | // Before allows for a function to be called before the ResponseWriter has been written to. This is 24 | // useful for setting headers or any other operations that must happen before a response has been written. 25 | Before(func(ResponseWriter)) 26 | } 27 | 28 | type beforeFunc func(ResponseWriter) 29 | 30 | // NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter 31 | func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { 32 | nrw := &responseWriter{ 33 | ResponseWriter: rw, 34 | } 35 | 36 | if _, ok := rw.(http.CloseNotifier); ok { 37 | return &responseWriterCloseNotifer{nrw} 38 | } 39 | 40 | return nrw 41 | } 42 | 43 | type responseWriter struct { 44 | http.ResponseWriter 45 | status int 46 | size int 47 | beforeFuncs []beforeFunc 48 | } 49 | 50 | func (rw *responseWriter) WriteHeader(s int) { 51 | rw.status = s 52 | rw.callBefore() 53 | rw.ResponseWriter.WriteHeader(s) 54 | } 55 | 56 | func (rw *responseWriter) Write(b []byte) (int, error) { 57 | if !rw.Written() { 58 | // The status will be StatusOK if WriteHeader has not been called yet 59 | rw.WriteHeader(http.StatusOK) 60 | } 61 | size, err := rw.ResponseWriter.Write(b) 62 | rw.size += size 63 | return size, err 64 | } 65 | 66 | func (rw *responseWriter) Status() int { 67 | return rw.status 68 | } 69 | 70 | func (rw *responseWriter) Size() int { 71 | return rw.size 72 | } 73 | 74 | func (rw *responseWriter) Written() bool { 75 | return rw.status != 0 76 | } 77 | 78 | func (rw *responseWriter) Before(before func(ResponseWriter)) { 79 | rw.beforeFuncs = append(rw.beforeFuncs, before) 80 | } 81 | 82 | func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { 83 | hijacker, ok := rw.ResponseWriter.(http.Hijacker) 84 | if !ok { 85 | return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") 86 | } 87 | return hijacker.Hijack() 88 | } 89 | 90 | func (rw *responseWriter) callBefore() { 91 | for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { 92 | rw.beforeFuncs[i](rw) 93 | } 94 | } 95 | 96 | func (rw *responseWriter) Flush() { 97 | flusher, ok := rw.ResponseWriter.(http.Flusher) 98 | if ok { 99 | if !rw.Written() { 100 | // The status will be StatusOK if WriteHeader has not been called yet 101 | rw.WriteHeader(http.StatusOK) 102 | } 103 | flusher.Flush() 104 | } 105 | } 106 | 107 | type responseWriterCloseNotifer struct { 108 | *responseWriter 109 | } 110 | 111 | func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool { 112 | return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() 113 | } 114 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/cluster_pipeline.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "gopkg.in/redis.v3/internal/hashtag" 5 | "gopkg.in/redis.v3/internal/pool" 6 | ) 7 | 8 | // ClusterPipeline is not thread-safe. 9 | type ClusterPipeline struct { 10 | commandable 11 | 12 | cluster *ClusterClient 13 | 14 | cmds []Cmder 15 | closed bool 16 | } 17 | 18 | // Pipeline creates a new pipeline which is able to execute commands 19 | // against multiple shards. It's NOT safe for concurrent use by 20 | // multiple goroutines. 21 | func (c *ClusterClient) Pipeline() *ClusterPipeline { 22 | pipe := &ClusterPipeline{ 23 | cluster: c, 24 | cmds: make([]Cmder, 0, 10), 25 | } 26 | pipe.commandable.process = pipe.process 27 | return pipe 28 | } 29 | 30 | func (c *ClusterClient) Pipelined(fn func(*ClusterPipeline) error) ([]Cmder, error) { 31 | pipe := c.Pipeline() 32 | if err := fn(pipe); err != nil { 33 | return nil, err 34 | } 35 | cmds, err := pipe.Exec() 36 | _ = pipe.Close() 37 | return cmds, err 38 | } 39 | 40 | func (pipe *ClusterPipeline) process(cmd Cmder) { 41 | pipe.cmds = append(pipe.cmds, cmd) 42 | } 43 | 44 | // Discard resets the pipeline and discards queued commands. 45 | func (pipe *ClusterPipeline) Discard() error { 46 | if pipe.closed { 47 | return pool.ErrClosed 48 | } 49 | pipe.cmds = pipe.cmds[:0] 50 | return nil 51 | } 52 | 53 | func (pipe *ClusterPipeline) Exec() (cmds []Cmder, retErr error) { 54 | if pipe.closed { 55 | return nil, pool.ErrClosed 56 | } 57 | if len(pipe.cmds) == 0 { 58 | return []Cmder{}, nil 59 | } 60 | 61 | cmds = pipe.cmds 62 | pipe.cmds = make([]Cmder, 0, 10) 63 | 64 | cmdsMap := make(map[string][]Cmder) 65 | for _, cmd := range cmds { 66 | slot := hashtag.Slot(cmd.clusterKey()) 67 | addr := pipe.cluster.slotMasterAddr(slot) 68 | cmdsMap[addr] = append(cmdsMap[addr], cmd) 69 | } 70 | 71 | for attempt := 0; attempt <= pipe.cluster.opt.getMaxRedirects(); attempt++ { 72 | failedCmds := make(map[string][]Cmder) 73 | 74 | for addr, cmds := range cmdsMap { 75 | client, err := pipe.cluster.getClient(addr) 76 | if err != nil { 77 | setCmdsErr(cmds, err) 78 | retErr = err 79 | continue 80 | } 81 | 82 | cn, err := client.conn() 83 | if err != nil { 84 | setCmdsErr(cmds, err) 85 | retErr = err 86 | continue 87 | } 88 | 89 | failedCmds, err = pipe.execClusterCmds(cn, cmds, failedCmds) 90 | if err != nil { 91 | retErr = err 92 | } 93 | client.putConn(cn, err, false) 94 | } 95 | 96 | cmdsMap = failedCmds 97 | } 98 | 99 | return cmds, retErr 100 | } 101 | 102 | // Close closes the pipeline, releasing any open resources. 103 | func (pipe *ClusterPipeline) Close() error { 104 | pipe.Discard() 105 | pipe.closed = true 106 | return nil 107 | } 108 | 109 | func (pipe *ClusterPipeline) execClusterCmds( 110 | cn *pool.Conn, cmds []Cmder, failedCmds map[string][]Cmder, 111 | ) (map[string][]Cmder, error) { 112 | if err := writeCmd(cn, cmds...); err != nil { 113 | setCmdsErr(cmds, err) 114 | return failedCmds, err 115 | } 116 | 117 | var firstCmdErr error 118 | for i, cmd := range cmds { 119 | err := cmd.readReply(cn) 120 | if err == nil { 121 | continue 122 | } 123 | if isNetworkError(err) { 124 | cmd.reset() 125 | failedCmds[""] = append(failedCmds[""], cmds[i:]...) 126 | break 127 | } else if moved, ask, addr := isMovedError(err); moved { 128 | pipe.cluster.lazyReloadSlots() 129 | cmd.reset() 130 | failedCmds[addr] = append(failedCmds[addr], cmd) 131 | } else if ask { 132 | cmd.reset() 133 | failedCmds[addr] = append(failedCmds[addr], NewCmd("ASKING"), cmd) 134 | } else if firstCmdErr == nil { 135 | firstCmdErr = err 136 | } 137 | } 138 | 139 | return failedCmds, firstCmdErr 140 | } 141 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/collector.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Collector is the interface implemented by anything that can be used by 17 | // Prometheus to collect metrics. A Collector has to be registered for 18 | // collection. See Registerer.Register. 19 | // 20 | // The stock metrics provided by this package (Gauge, Counter, Summary, 21 | // Histogram, Untyped) are also Collectors (which only ever collect one metric, 22 | // namely itself). An implementer of Collector may, however, collect multiple 23 | // metrics in a coordinated fashion and/or create metrics on the fly. Examples 24 | // for collectors already implemented in this library are the metric vectors 25 | // (i.e. collection of multiple instances of the same Metric but with different 26 | // label values) like GaugeVec or SummaryVec, and the ExpvarCollector. 27 | type Collector interface { 28 | // Describe sends the super-set of all possible descriptors of metrics 29 | // collected by this Collector to the provided channel and returns once 30 | // the last descriptor has been sent. The sent descriptors fulfill the 31 | // consistency and uniqueness requirements described in the Desc 32 | // documentation. (It is valid if one and the same Collector sends 33 | // duplicate descriptors. Those duplicates are simply ignored. However, 34 | // two different Collectors must not send duplicate descriptors.) This 35 | // method idempotently sends the same descriptors throughout the 36 | // lifetime of the Collector. If a Collector encounters an error while 37 | // executing this method, it must send an invalid descriptor (created 38 | // with NewInvalidDesc) to signal the error to the registry. 39 | Describe(chan<- *Desc) 40 | // Collect is called by the Prometheus registry when collecting 41 | // metrics. The implementation sends each collected metric via the 42 | // provided channel and returns once the last metric has been sent. The 43 | // descriptor of each sent metric is one of those returned by 44 | // Describe. Returned metrics that share the same descriptor must differ 45 | // in their variable label values. This method may be called 46 | // concurrently and must therefore be implemented in a concurrency safe 47 | // way. Blocking occurs at the expense of total performance of rendering 48 | // all registered metrics. Ideally, Collector implementations support 49 | // concurrent readers. 50 | Collect(chan<- Metric) 51 | } 52 | 53 | // selfCollector implements Collector for a single Metric so that the Metric 54 | // collects itself. Add it as an anonymous field to a struct that implements 55 | // Metric, and call init with the Metric itself as an argument. 56 | type selfCollector struct { 57 | self Metric 58 | } 59 | 60 | // init provides the selfCollector with a reference to the metric it is supposed 61 | // to collect. It is usually called within the factory function to create a 62 | // metric. See example. 63 | func (c *selfCollector) init(self Metric) { 64 | c.self = self 65 | } 66 | 67 | // Describe implements Collector. 68 | func (c *selfCollector) Describe(ch chan<- *Desc) { 69 | ch <- c.self.Desc() 70 | } 71 | 72 | // Collect implements Collector. 73 | func (c *selfCollector) Collect(ch chan<- Metric) { 74 | ch <- c.self 75 | } 76 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/options.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "net" 5 | "time" 6 | 7 | "gopkg.in/redis.v3/internal/pool" 8 | ) 9 | 10 | type Options struct { 11 | // The network type, either tcp or unix. 12 | // Default is tcp. 13 | Network string 14 | // host:port address. 15 | Addr string 16 | 17 | // Dialer creates new network connection and has priority over 18 | // Network and Addr options. 19 | Dialer func() (net.Conn, error) 20 | 21 | // An optional password. Must match the password specified in the 22 | // requirepass server configuration option. 23 | Password string 24 | // A database to be selected after connecting to server. 25 | DB int64 26 | 27 | // The maximum number of retries before giving up. 28 | // Default is to not retry failed commands. 29 | MaxRetries int 30 | 31 | // Sets the deadline for establishing new connections. If reached, 32 | // dial will fail with a timeout. 33 | // Default is 5 seconds. 34 | DialTimeout time.Duration 35 | // Sets the deadline for socket reads. If reached, commands will 36 | // fail with a timeout instead of blocking. 37 | ReadTimeout time.Duration 38 | // Sets the deadline for socket writes. If reached, commands will 39 | // fail with a timeout instead of blocking. 40 | WriteTimeout time.Duration 41 | 42 | // The maximum number of socket connections. 43 | // Default is 10 connections. 44 | PoolSize int 45 | // Specifies amount of time client waits for connection if all 46 | // connections are busy before returning an error. 47 | // Default is 1 second. 48 | PoolTimeout time.Duration 49 | // Specifies amount of time after which client closes idle 50 | // connections. Should be less than server's timeout. 51 | // Default is to not close idle connections. 52 | IdleTimeout time.Duration 53 | // The frequency of idle checks. 54 | // Default is 1 minute. 55 | IdleCheckFrequency time.Duration 56 | } 57 | 58 | func (opt *Options) getNetwork() string { 59 | if opt.Network == "" { 60 | return "tcp" 61 | } 62 | return opt.Network 63 | } 64 | 65 | func (opt *Options) getDialer() func() (net.Conn, error) { 66 | if opt.Dialer != nil { 67 | return opt.Dialer 68 | } 69 | return func() (net.Conn, error) { 70 | return net.DialTimeout(opt.getNetwork(), opt.Addr, opt.getDialTimeout()) 71 | } 72 | } 73 | 74 | func (opt *Options) getPoolSize() int { 75 | if opt.PoolSize == 0 { 76 | return 10 77 | } 78 | return opt.PoolSize 79 | } 80 | 81 | func (opt *Options) getDialTimeout() time.Duration { 82 | if opt.DialTimeout == 0 { 83 | return 5 * time.Second 84 | } 85 | return opt.DialTimeout 86 | } 87 | 88 | func (opt *Options) getPoolTimeout() time.Duration { 89 | if opt.PoolTimeout == 0 { 90 | return 1 * time.Second 91 | } 92 | return opt.PoolTimeout 93 | } 94 | 95 | func (opt *Options) getIdleTimeout() time.Duration { 96 | return opt.IdleTimeout 97 | } 98 | 99 | func (opt *Options) getIdleCheckFrequency() time.Duration { 100 | if opt.IdleCheckFrequency == 0 { 101 | return time.Minute 102 | } 103 | return opt.IdleCheckFrequency 104 | } 105 | 106 | func newConnPool(opt *Options) *pool.ConnPool { 107 | return pool.NewConnPool( 108 | opt.getDialer(), 109 | opt.getPoolSize(), 110 | opt.getPoolTimeout(), 111 | opt.getIdleTimeout(), 112 | opt.getIdleCheckFrequency(), 113 | ) 114 | } 115 | 116 | // PoolStats contains pool state information and accumulated stats. 117 | type PoolStats struct { 118 | Requests uint32 // number of times a connection was requested by the pool 119 | Hits uint32 // number of times free connection was found in the pool 120 | Waits uint32 // number of times the pool had to wait for a connection 121 | Timeouts uint32 // number of times a wait timeout occurred 122 | 123 | TotalConns uint32 // the number of total connections in the pool 124 | FreeConns uint32 // the number of free connections in the pool 125 | } 126 | -------------------------------------------------------------------------------- /redis/client.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | 8 | "github.com/prometheus/client_golang/prometheus" 9 | "gopkg.in/redis.v3" 10 | ) 11 | 12 | var ( 13 | keys chan string 14 | ) 15 | 16 | func init() { 17 | client := redis.NewClient(&redis.Options{ 18 | Addr: "localhost:6379", 19 | }) 20 | status := client.Ping() 21 | if status.Err() != nil { 22 | log.Fatalf("failed to initialize redis client: %s", status.Err()) 23 | } 24 | keys = make(chan string) 25 | go startWorker(client) 26 | prometheus.MustRegister(&redisCollector{client: client}) 27 | prometheus.MustRegister(prometheus.NewGaugeFunc(prometheus.GaugeOpts{ 28 | Name: "myapp_redis_queue_current_length", 29 | Help: "The current number of itens on redis queue.", 30 | }, func() float64 { 31 | return float64(len(keys)) 32 | })) 33 | prometheus.MustRegister(queueWaitDuration) 34 | prometheus.MustRegister(redisOps) 35 | } 36 | 37 | var ( 38 | redisOps = prometheus.NewCounterVec(prometheus.CounterOpts{ 39 | Name: "myapp_redis_worker_operations", 40 | Help: "The total operations performed by redis worker.", 41 | }, []string{"operation", "result"}) 42 | ) 43 | 44 | func startWorker(client *redis.Client) { 45 | fmt.Printf("Starting background worker...\n") 46 | for { 47 | opLabel := "ping" 48 | var err error 49 | select { 50 | case key := <-keys: 51 | result := client.Incr(key) 52 | opLabel = "incr" 53 | err = result.Err() 54 | case <-time.After(time.Second * 10): 55 | result := client.Ping() 56 | err = result.Err() 57 | } 58 | resultLabel := "ok" 59 | if err != nil { 60 | resultLabel = "error" 61 | } 62 | redisOps.WithLabelValues(opLabel, resultLabel).Inc() 63 | } 64 | } 65 | 66 | var ( 67 | queueWaitDuration = prometheus.NewHistogram(prometheus.HistogramOpts{ 68 | Name: "myapp_redis_queue_wait_duration_seconds", 69 | Help: "The wait duration when trying to write to the redis queue", 70 | }) 71 | ) 72 | 73 | func Increment(key string) { 74 | select { 75 | case keys <- key: 76 | default: 77 | now := time.Now() 78 | keys <- key 79 | queueWaitDuration.Observe(time.Since(now).Seconds()) 80 | } 81 | } 82 | 83 | var ( 84 | requestsDesc = prometheus.NewDesc("myapp_redis_connections_requests_total", "The total number of connections requests to redis pool.", []string{}, nil) 85 | hitsDesc = prometheus.NewDesc("myapp_redis_connections_hits_total", "The total number of times a free connection was found in redis pool.", []string{}, nil) 86 | waitsDesc = prometheus.NewDesc("myapp_redis_connections_waits_total", "The total number of times the redis pool had to wait for a connection.", []string{}, nil) 87 | timeoutsDesc = prometheus.NewDesc("myapp_redis_connections_timeouts_total", "The total number of wait timeouts in redis pool.", []string{}, nil) 88 | connsDesc = prometheus.NewDesc("myapp_redis_connections_current", "The current number of connections in redis pool.", []string{}, nil) 89 | freeConnsDesc = prometheus.NewDesc("myapp_redis_connections_free_current", "The current number of free connections in redis pool.", []string{}, nil) 90 | ) 91 | 92 | type redisCollector struct { 93 | client *redis.Client 94 | } 95 | 96 | func (c *redisCollector) Describe(ch chan<- *prometheus.Desc) { 97 | ch <- requestsDesc 98 | ch <- hitsDesc 99 | ch <- waitsDesc 100 | ch <- timeoutsDesc 101 | ch <- connsDesc 102 | ch <- freeConnsDesc 103 | } 104 | 105 | func (c *redisCollector) Collect(ch chan<- prometheus.Metric) { 106 | stats := c.client.PoolStats() 107 | ch <- prometheus.MustNewConstMetric(requestsDesc, prometheus.CounterValue, float64(stats.Requests)) 108 | ch <- prometheus.MustNewConstMetric(hitsDesc, prometheus.CounterValue, float64(stats.Hits)) 109 | ch <- prometheus.MustNewConstMetric(waitsDesc, prometheus.CounterValue, float64(stats.Waits)) 110 | ch <- prometheus.MustNewConstMetric(timeoutsDesc, prometheus.CounterValue, float64(stats.Timeouts)) 111 | ch <- prometheus.MustNewConstMetric(connsDesc, prometheus.GaugeValue, float64(stats.TotalConns)) 112 | ch <- prometheus.MustNewConstMetric(freeConnsDesc, prometheus.GaugeValue, float64(stats.FreeConns)) 113 | } 114 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/context.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package context 6 | 7 | import ( 8 | "net/http" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | var ( 14 | mutex sync.RWMutex 15 | data = make(map[*http.Request]map[interface{}]interface{}) 16 | datat = make(map[*http.Request]int64) 17 | ) 18 | 19 | // Set stores a value for a given key in a given request. 20 | func Set(r *http.Request, key, val interface{}) { 21 | mutex.Lock() 22 | if data[r] == nil { 23 | data[r] = make(map[interface{}]interface{}) 24 | datat[r] = time.Now().Unix() 25 | } 26 | data[r][key] = val 27 | mutex.Unlock() 28 | } 29 | 30 | // Get returns a value stored for a given key in a given request. 31 | func Get(r *http.Request, key interface{}) interface{} { 32 | mutex.RLock() 33 | if ctx := data[r]; ctx != nil { 34 | value := ctx[key] 35 | mutex.RUnlock() 36 | return value 37 | } 38 | mutex.RUnlock() 39 | return nil 40 | } 41 | 42 | // GetOk returns stored value and presence state like multi-value return of map access. 43 | func GetOk(r *http.Request, key interface{}) (interface{}, bool) { 44 | mutex.RLock() 45 | if _, ok := data[r]; ok { 46 | value, ok := data[r][key] 47 | mutex.RUnlock() 48 | return value, ok 49 | } 50 | mutex.RUnlock() 51 | return nil, false 52 | } 53 | 54 | // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. 55 | func GetAll(r *http.Request) map[interface{}]interface{} { 56 | mutex.RLock() 57 | if context, ok := data[r]; ok { 58 | result := make(map[interface{}]interface{}, len(context)) 59 | for k, v := range context { 60 | result[k] = v 61 | } 62 | mutex.RUnlock() 63 | return result 64 | } 65 | mutex.RUnlock() 66 | return nil 67 | } 68 | 69 | // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if 70 | // the request was registered. 71 | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { 72 | mutex.RLock() 73 | context, ok := data[r] 74 | result := make(map[interface{}]interface{}, len(context)) 75 | for k, v := range context { 76 | result[k] = v 77 | } 78 | mutex.RUnlock() 79 | return result, ok 80 | } 81 | 82 | // Delete removes a value stored for a given key in a given request. 83 | func Delete(r *http.Request, key interface{}) { 84 | mutex.Lock() 85 | if data[r] != nil { 86 | delete(data[r], key) 87 | } 88 | mutex.Unlock() 89 | } 90 | 91 | // Clear removes all values stored for a given request. 92 | // 93 | // This is usually called by a handler wrapper to clean up request 94 | // variables at the end of a request lifetime. See ClearHandler(). 95 | func Clear(r *http.Request) { 96 | mutex.Lock() 97 | clear(r) 98 | mutex.Unlock() 99 | } 100 | 101 | // clear is Clear without the lock. 102 | func clear(r *http.Request) { 103 | delete(data, r) 104 | delete(datat, r) 105 | } 106 | 107 | // Purge removes request data stored for longer than maxAge, in seconds. 108 | // It returns the amount of requests removed. 109 | // 110 | // If maxAge <= 0, all request data is removed. 111 | // 112 | // This is only used for sanity check: in case context cleaning was not 113 | // properly set some request data can be kept forever, consuming an increasing 114 | // amount of memory. In case this is detected, Purge() must be called 115 | // periodically until the problem is fixed. 116 | func Purge(maxAge int) int { 117 | mutex.Lock() 118 | count := 0 119 | if maxAge <= 0 { 120 | count = len(data) 121 | data = make(map[*http.Request]map[interface{}]interface{}) 122 | datat = make(map[*http.Request]int64) 123 | } else { 124 | min := time.Now().Unix() - int64(maxAge) 125 | for r := range data { 126 | if datat[r] < min { 127 | clear(r) 128 | count++ 129 | } 130 | } 131 | } 132 | mutex.Unlock() 133 | return count 134 | } 135 | 136 | // ClearHandler wraps an http.Handler and clears request values at the end 137 | // of a request lifetime. 138 | func ClearHandler(h http.Handler) http.Handler { 139 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 140 | defer Clear(r) 141 | h.ServeHTTP(w, r) 142 | }) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/mdstat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "regexp" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | var ( 12 | statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) 13 | buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) 14 | ) 15 | 16 | // MDStat holds info parsed from /proc/mdstat. 17 | type MDStat struct { 18 | // Name of the device. 19 | Name string 20 | // activity-state of the device. 21 | ActivityState string 22 | // Number of active disks. 23 | DisksActive int64 24 | // Total number of disks the device consists of. 25 | DisksTotal int64 26 | // Number of blocks the device holds. 27 | BlocksTotal int64 28 | // Number of blocks on the device that are in sync. 29 | BlocksSynced int64 30 | } 31 | 32 | // ParseMDStat parses an mdstat-file and returns a struct with the relevant infos. 33 | func (fs FS) ParseMDStat() (mdstates []MDStat, err error) { 34 | mdStatusFilePath := fs.Path("mdstat") 35 | content, err := ioutil.ReadFile(mdStatusFilePath) 36 | if err != nil { 37 | return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 38 | } 39 | 40 | mdStates := []MDStat{} 41 | lines := strings.Split(string(content), "\n") 42 | for i, l := range lines { 43 | if l == "" { 44 | continue 45 | } 46 | if l[0] == ' ' { 47 | continue 48 | } 49 | if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") { 50 | continue 51 | } 52 | 53 | mainLine := strings.Split(l, " ") 54 | if len(mainLine) < 3 { 55 | return mdStates, fmt.Errorf("error parsing mdline: %s", l) 56 | } 57 | mdName := mainLine[0] 58 | activityState := mainLine[2] 59 | 60 | if len(lines) <= i+3 { 61 | return mdStates, fmt.Errorf( 62 | "error parsing %s: too few lines for md device %s", 63 | mdStatusFilePath, 64 | mdName, 65 | ) 66 | } 67 | 68 | active, total, size, err := evalStatusline(lines[i+1]) 69 | if err != nil { 70 | return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 71 | } 72 | 73 | // j is the line number of the syncing-line. 74 | j := i + 2 75 | if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line 76 | j = i + 3 77 | } 78 | 79 | // If device is syncing at the moment, get the number of currently 80 | // synced bytes, otherwise that number equals the size of the device. 81 | syncedBlocks := size 82 | if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") { 83 | syncedBlocks, err = evalBuildline(lines[j]) 84 | if err != nil { 85 | return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 86 | } 87 | } 88 | 89 | mdStates = append(mdStates, MDStat{ 90 | Name: mdName, 91 | ActivityState: activityState, 92 | DisksActive: active, 93 | DisksTotal: total, 94 | BlocksTotal: size, 95 | BlocksSynced: syncedBlocks, 96 | }) 97 | } 98 | 99 | return mdStates, nil 100 | } 101 | 102 | func evalStatusline(statusline string) (active, total, size int64, err error) { 103 | matches := statuslineRE.FindStringSubmatch(statusline) 104 | if len(matches) != 4 { 105 | return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline) 106 | } 107 | 108 | size, err = strconv.ParseInt(matches[1], 10, 64) 109 | if err != nil { 110 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 111 | } 112 | 113 | total, err = strconv.ParseInt(matches[2], 10, 64) 114 | if err != nil { 115 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 116 | } 117 | 118 | active, err = strconv.ParseInt(matches[3], 10, 64) 119 | if err != nil { 120 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 121 | } 122 | 123 | return active, total, size, nil 124 | } 125 | 126 | func evalBuildline(buildline string) (syncedBlocks int64, err error) { 127 | matches := buildlineRE.FindStringSubmatch(buildline) 128 | if len(matches) != 2 { 129 | return 0, fmt.Errorf("unexpected buildline: %s", buildline) 130 | } 131 | 132 | syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) 133 | if err != nil { 134 | return 0, fmt.Errorf("%s in buildline: %s", err, buildline) 135 | } 136 | 137 | return syncedBlocks, nil 138 | } 139 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/redis.go: -------------------------------------------------------------------------------- 1 | package redis // import "gopkg.in/redis.v3" 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "gopkg.in/redis.v3/internal" 8 | "gopkg.in/redis.v3/internal/pool" 9 | ) 10 | 11 | var Logger *log.Logger 12 | 13 | func SetLogger(logger *log.Logger) { 14 | internal.Logger = logger 15 | } 16 | 17 | type baseClient struct { 18 | connPool pool.Pooler 19 | opt *Options 20 | 21 | onClose func() error // hook called when client is closed 22 | } 23 | 24 | func (c *baseClient) String() string { 25 | return fmt.Sprintf("Redis<%s db:%d>", c.opt.Addr, c.opt.DB) 26 | } 27 | 28 | func (c *baseClient) conn() (*pool.Conn, error) { 29 | cn, err := c.connPool.Get() 30 | if err != nil { 31 | return nil, err 32 | } 33 | if !cn.Inited { 34 | if err := c.initConn(cn); err != nil { 35 | _ = c.connPool.Remove(cn, err) 36 | return nil, err 37 | } 38 | } 39 | return cn, err 40 | } 41 | 42 | func (c *baseClient) putConn(cn *pool.Conn, err error, allowTimeout bool) bool { 43 | if isBadConn(err, allowTimeout) { 44 | _ = c.connPool.Remove(cn, err) 45 | return false 46 | } 47 | 48 | _ = c.connPool.Put(cn) 49 | return true 50 | } 51 | 52 | func (c *baseClient) initConn(cn *pool.Conn) error { 53 | cn.Inited = true 54 | 55 | if c.opt.Password == "" && c.opt.DB == 0 { 56 | return nil 57 | } 58 | 59 | // Temp client for Auth and Select. 60 | client := newClient(c.opt, pool.NewSingleConnPool(cn)) 61 | 62 | if c.opt.Password != "" { 63 | if err := client.Auth(c.opt.Password).Err(); err != nil { 64 | return err 65 | } 66 | } 67 | 68 | if c.opt.DB > 0 { 69 | if err := client.Select(c.opt.DB).Err(); err != nil { 70 | return err 71 | } 72 | } 73 | 74 | return nil 75 | } 76 | 77 | func (c *baseClient) process(cmd Cmder) { 78 | for i := 0; i <= c.opt.MaxRetries; i++ { 79 | if i > 0 { 80 | cmd.reset() 81 | } 82 | 83 | cn, err := c.conn() 84 | if err != nil { 85 | cmd.setErr(err) 86 | return 87 | } 88 | 89 | readTimeout := cmd.readTimeout() 90 | if readTimeout != nil { 91 | cn.ReadTimeout = *readTimeout 92 | } else { 93 | cn.ReadTimeout = c.opt.ReadTimeout 94 | } 95 | cn.WriteTimeout = c.opt.WriteTimeout 96 | 97 | if err := writeCmd(cn, cmd); err != nil { 98 | c.putConn(cn, err, false) 99 | cmd.setErr(err) 100 | if err != nil && shouldRetry(err) { 101 | continue 102 | } 103 | return 104 | } 105 | 106 | err = cmd.readReply(cn) 107 | c.putConn(cn, err, readTimeout != nil) 108 | if err != nil && shouldRetry(err) { 109 | continue 110 | } 111 | 112 | return 113 | } 114 | } 115 | 116 | func (c *baseClient) closed() bool { 117 | return c.connPool.Closed() 118 | } 119 | 120 | // Close closes the client, releasing any open resources. 121 | // 122 | // It is rare to Close a Client, as the Client is meant to be 123 | // long-lived and shared between many goroutines. 124 | func (c *baseClient) Close() error { 125 | var retErr error 126 | if c.onClose != nil { 127 | if err := c.onClose(); err != nil && retErr == nil { 128 | retErr = err 129 | } 130 | } 131 | if err := c.connPool.Close(); err != nil && retErr == nil { 132 | retErr = err 133 | } 134 | return retErr 135 | } 136 | 137 | //------------------------------------------------------------------------------ 138 | 139 | // Client is a Redis client representing a pool of zero or more 140 | // underlying connections. It's safe for concurrent use by multiple 141 | // goroutines. 142 | type Client struct { 143 | baseClient 144 | commandable 145 | } 146 | 147 | func newClient(opt *Options, pool pool.Pooler) *Client { 148 | base := baseClient{opt: opt, connPool: pool} 149 | return &Client{ 150 | baseClient: base, 151 | commandable: commandable{ 152 | process: base.process, 153 | }, 154 | } 155 | } 156 | 157 | // NewClient returns a client to the Redis Server specified by Options. 158 | func NewClient(opt *Options) *Client { 159 | return newClient(opt, newConnPool(opt)) 160 | } 161 | 162 | // PoolStats returns connection pool stats. 163 | func (c *Client) PoolStats() *PoolStats { 164 | s := c.connPool.Stats() 165 | return &PoolStats{ 166 | Requests: s.Requests, 167 | Hits: s.Hits, 168 | Waits: s.Waits, 169 | Timeouts: s.Timeouts, 170 | 171 | TotalConns: s.TotalConns, 172 | FreeConns: s.FreeConns, 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/alert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "time" 19 | ) 20 | 21 | type AlertStatus string 22 | 23 | const ( 24 | AlertFiring AlertStatus = "firing" 25 | AlertResolved AlertStatus = "resolved" 26 | ) 27 | 28 | // Alert is a generic representation of an alert in the Prometheus eco-system. 29 | type Alert struct { 30 | // Label value pairs for purpose of aggregation, matching, and disposition 31 | // dispatching. This must minimally include an "alertname" label. 32 | Labels LabelSet `json:"labels"` 33 | 34 | // Extra key/value information which does not define alert identity. 35 | Annotations LabelSet `json:"annotations"` 36 | 37 | // The known time range for this alert. Both ends are optional. 38 | StartsAt time.Time `json:"startsAt,omitempty"` 39 | EndsAt time.Time `json:"endsAt,omitempty"` 40 | GeneratorURL string `json:"generatorURL"` 41 | } 42 | 43 | // Name returns the name of the alert. It is equivalent to the "alertname" label. 44 | func (a *Alert) Name() string { 45 | return string(a.Labels[AlertNameLabel]) 46 | } 47 | 48 | // Fingerprint returns a unique hash for the alert. It is equivalent to 49 | // the fingerprint of the alert's label set. 50 | func (a *Alert) Fingerprint() Fingerprint { 51 | return a.Labels.Fingerprint() 52 | } 53 | 54 | func (a *Alert) String() string { 55 | s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7]) 56 | if a.Resolved() { 57 | return s + "[resolved]" 58 | } 59 | return s + "[active]" 60 | } 61 | 62 | // Resolved returns true iff the activity interval ended in the past. 63 | func (a *Alert) Resolved() bool { 64 | return a.ResolvedAt(time.Now()) 65 | } 66 | 67 | // ResolvedAt returns true off the activity interval ended before 68 | // the given timestamp. 69 | func (a *Alert) ResolvedAt(ts time.Time) bool { 70 | if a.EndsAt.IsZero() { 71 | return false 72 | } 73 | return !a.EndsAt.After(ts) 74 | } 75 | 76 | // Status returns the status of the alert. 77 | func (a *Alert) Status() AlertStatus { 78 | if a.Resolved() { 79 | return AlertResolved 80 | } 81 | return AlertFiring 82 | } 83 | 84 | // Validate checks whether the alert data is inconsistent. 85 | func (a *Alert) Validate() error { 86 | if a.StartsAt.IsZero() { 87 | return fmt.Errorf("start time missing") 88 | } 89 | if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { 90 | return fmt.Errorf("start time must be before end time") 91 | } 92 | if err := a.Labels.Validate(); err != nil { 93 | return fmt.Errorf("invalid label set: %s", err) 94 | } 95 | if len(a.Labels) == 0 { 96 | return fmt.Errorf("at least one label pair required") 97 | } 98 | if err := a.Annotations.Validate(); err != nil { 99 | return fmt.Errorf("invalid annotations: %s", err) 100 | } 101 | return nil 102 | } 103 | 104 | // Alert is a list of alerts that can be sorted in chronological order. 105 | type Alerts []*Alert 106 | 107 | func (as Alerts) Len() int { return len(as) } 108 | func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] } 109 | 110 | func (as Alerts) Less(i, j int) bool { 111 | if as[i].StartsAt.Before(as[j].StartsAt) { 112 | return true 113 | } 114 | if as[i].EndsAt.Before(as[j].EndsAt) { 115 | return true 116 | } 117 | return as[i].Fingerprint() < as[j].Fingerprint() 118 | } 119 | 120 | // HasFiring returns true iff one of the alerts is not resolved. 121 | func (as Alerts) HasFiring() bool { 122 | for _, a := range as { 123 | if !a.Resolved() { 124 | return true 125 | } 126 | } 127 | return false 128 | } 129 | 130 | // Status returns StatusFiring iff at least one of the alerts is firing. 131 | func (as Alerts) Status() AlertStatus { 132 | if as.HasFiring() { 133 | return AlertFiring 134 | } 135 | return AlertResolved 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_limits.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "strconv" 9 | ) 10 | 11 | // ProcLimits represents the soft limits for each of the process's resource 12 | // limits. For more information see getrlimit(2): 13 | // http://man7.org/linux/man-pages/man2/getrlimit.2.html. 14 | type ProcLimits struct { 15 | // CPU time limit in seconds. 16 | CPUTime int 17 | // Maximum size of files that the process may create. 18 | FileSize int 19 | // Maximum size of the process's data segment (initialized data, 20 | // uninitialized data, and heap). 21 | DataSize int 22 | // Maximum size of the process stack in bytes. 23 | StackSize int 24 | // Maximum size of a core file. 25 | CoreFileSize int 26 | // Limit of the process's resident set in pages. 27 | ResidentSet int 28 | // Maximum number of processes that can be created for the real user ID of 29 | // the calling process. 30 | Processes int 31 | // Value one greater than the maximum file descriptor number that can be 32 | // opened by this process. 33 | OpenFiles int 34 | // Maximum number of bytes of memory that may be locked into RAM. 35 | LockedMemory int 36 | // Maximum size of the process's virtual memory address space in bytes. 37 | AddressSpace int 38 | // Limit on the combined number of flock(2) locks and fcntl(2) leases that 39 | // this process may establish. 40 | FileLocks int 41 | // Limit of signals that may be queued for the real user ID of the calling 42 | // process. 43 | PendingSignals int 44 | // Limit on the number of bytes that can be allocated for POSIX message 45 | // queues for the real user ID of the calling process. 46 | MsqqueueSize int 47 | // Limit of the nice priority set using setpriority(2) or nice(2). 48 | NicePriority int 49 | // Limit of the real-time priority set using sched_setscheduler(2) or 50 | // sched_setparam(2). 51 | RealtimePriority int 52 | // Limit (in microseconds) on the amount of CPU time that a process 53 | // scheduled under a real-time scheduling policy may consume without making 54 | // a blocking system call. 55 | RealtimeTimeout int 56 | } 57 | 58 | const ( 59 | limitsFields = 3 60 | limitsUnlimited = "unlimited" 61 | ) 62 | 63 | var ( 64 | limitsDelimiter = regexp.MustCompile(" +") 65 | ) 66 | 67 | // NewLimits returns the current soft limits of the process. 68 | func (p Proc) NewLimits() (ProcLimits, error) { 69 | f, err := os.Open(p.path("limits")) 70 | if err != nil { 71 | return ProcLimits{}, err 72 | } 73 | defer f.Close() 74 | 75 | var ( 76 | l = ProcLimits{} 77 | s = bufio.NewScanner(f) 78 | ) 79 | for s.Scan() { 80 | fields := limitsDelimiter.Split(s.Text(), limitsFields) 81 | if len(fields) != limitsFields { 82 | return ProcLimits{}, fmt.Errorf( 83 | "couldn't parse %s line %s", f.Name(), s.Text()) 84 | } 85 | 86 | switch fields[0] { 87 | case "Max cpu time": 88 | l.CPUTime, err = parseInt(fields[1]) 89 | case "Max file size": 90 | l.FileSize, err = parseInt(fields[1]) 91 | case "Max data size": 92 | l.DataSize, err = parseInt(fields[1]) 93 | case "Max stack size": 94 | l.StackSize, err = parseInt(fields[1]) 95 | case "Max core file size": 96 | l.CoreFileSize, err = parseInt(fields[1]) 97 | case "Max resident set": 98 | l.ResidentSet, err = parseInt(fields[1]) 99 | case "Max processes": 100 | l.Processes, err = parseInt(fields[1]) 101 | case "Max open files": 102 | l.OpenFiles, err = parseInt(fields[1]) 103 | case "Max locked memory": 104 | l.LockedMemory, err = parseInt(fields[1]) 105 | case "Max address space": 106 | l.AddressSpace, err = parseInt(fields[1]) 107 | case "Max file locks": 108 | l.FileLocks, err = parseInt(fields[1]) 109 | case "Max pending signals": 110 | l.PendingSignals, err = parseInt(fields[1]) 111 | case "Max msgqueue size": 112 | l.MsqqueueSize, err = parseInt(fields[1]) 113 | case "Max nice priority": 114 | l.NicePriority, err = parseInt(fields[1]) 115 | case "Max realtime priority": 116 | l.RealtimePriority, err = parseInt(fields[1]) 117 | case "Max realtime timeout": 118 | l.RealtimeTimeout, err = parseInt(fields[1]) 119 | } 120 | if err != nil { 121 | return ProcLimits{}, err 122 | } 123 | } 124 | 125 | return l, s.Err() 126 | } 127 | 128 | func parseInt(s string) (int, error) { 129 | if s == limitsUnlimited { 130 | return -1, nil 131 | } 132 | i, err := strconv.ParseInt(s, 10, 32) 133 | if err != nil { 134 | return 0, fmt.Errorf("couldn't parse value %s: %s", s, err) 135 | } 136 | return int(i), nil 137 | } 138 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/process_collector.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import "github.com/prometheus/procfs" 17 | 18 | type processCollector struct { 19 | pid int 20 | collectFn func(chan<- Metric) 21 | pidFn func() (int, error) 22 | cpuTotal *Desc 23 | openFDs, maxFDs *Desc 24 | vsize, rss *Desc 25 | startTime *Desc 26 | } 27 | 28 | // NewProcessCollector returns a collector which exports the current state of 29 | // process metrics including cpu, memory and file descriptor usage as well as 30 | // the process start time for the given process id under the given namespace. 31 | func NewProcessCollector(pid int, namespace string) Collector { 32 | return NewProcessCollectorPIDFn( 33 | func() (int, error) { return pid, nil }, 34 | namespace, 35 | ) 36 | } 37 | 38 | // NewProcessCollectorPIDFn returns a collector which exports the current state 39 | // of process metrics including cpu, memory and file descriptor usage as well 40 | // as the process start time under the given namespace. The given pidFn is 41 | // called on each collect and is used to determine the process to export 42 | // metrics for. 43 | func NewProcessCollectorPIDFn( 44 | pidFn func() (int, error), 45 | namespace string, 46 | ) Collector { 47 | ns := "" 48 | if len(namespace) > 0 { 49 | ns = namespace + "_" 50 | } 51 | 52 | c := processCollector{ 53 | pidFn: pidFn, 54 | collectFn: func(chan<- Metric) {}, 55 | 56 | cpuTotal: NewDesc( 57 | ns+"process_cpu_seconds_total", 58 | "Total user and system CPU time spent in seconds.", 59 | nil, nil, 60 | ), 61 | openFDs: NewDesc( 62 | ns+"process_open_fds", 63 | "Number of open file descriptors.", 64 | nil, nil, 65 | ), 66 | maxFDs: NewDesc( 67 | ns+"process_max_fds", 68 | "Maximum number of open file descriptors.", 69 | nil, nil, 70 | ), 71 | vsize: NewDesc( 72 | ns+"process_virtual_memory_bytes", 73 | "Virtual memory size in bytes.", 74 | nil, nil, 75 | ), 76 | rss: NewDesc( 77 | ns+"process_resident_memory_bytes", 78 | "Resident memory size in bytes.", 79 | nil, nil, 80 | ), 81 | startTime: NewDesc( 82 | ns+"process_start_time_seconds", 83 | "Start time of the process since unix epoch in seconds.", 84 | nil, nil, 85 | ), 86 | } 87 | 88 | // Set up process metric collection if supported by the runtime. 89 | if _, err := procfs.NewStat(); err == nil { 90 | c.collectFn = c.processCollect 91 | } 92 | 93 | return &c 94 | } 95 | 96 | // Describe returns all descriptions of the collector. 97 | func (c *processCollector) Describe(ch chan<- *Desc) { 98 | ch <- c.cpuTotal 99 | ch <- c.openFDs 100 | ch <- c.maxFDs 101 | ch <- c.vsize 102 | ch <- c.rss 103 | ch <- c.startTime 104 | } 105 | 106 | // Collect returns the current state of all metrics of the collector. 107 | func (c *processCollector) Collect(ch chan<- Metric) { 108 | c.collectFn(ch) 109 | } 110 | 111 | // TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the 112 | // client allows users to configure the error behavior. 113 | func (c *processCollector) processCollect(ch chan<- Metric) { 114 | pid, err := c.pidFn() 115 | if err != nil { 116 | return 117 | } 118 | 119 | p, err := procfs.NewProc(pid) 120 | if err != nil { 121 | return 122 | } 123 | 124 | if stat, err := p.NewStat(); err == nil { 125 | ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime()) 126 | ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory())) 127 | ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory())) 128 | if startTime, err := stat.StartTime(); err == nil { 129 | ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime) 130 | } 131 | } 132 | 133 | if fds, err := p.FileDescriptorsLen(); err == nil { 134 | ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds)) 135 | } 136 | 137 | if limits, err := p.NewLimits(); err == nil { 138 | ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles)) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import ( 17 | "encoding/json" 18 | "expvar" 19 | ) 20 | 21 | type expvarCollector struct { 22 | exports map[string]*Desc 23 | } 24 | 25 | // NewExpvarCollector returns a newly allocated expvar Collector that still has 26 | // to be registered with a Prometheus registry. 27 | // 28 | // An expvar Collector collects metrics from the expvar interface. It provides a 29 | // quick way to expose numeric values that are already exported via expvar as 30 | // Prometheus metrics. Note that the data models of expvar and Prometheus are 31 | // fundamentally different, and that the expvar Collector is inherently slower 32 | // than native Prometheus metrics. Thus, the expvar Collector is probably great 33 | // for experiments and prototying, but you should seriously consider a more 34 | // direct implementation of Prometheus metrics for monitoring production 35 | // systems. 36 | // 37 | // The exports map has the following meaning: 38 | // 39 | // The keys in the map correspond to expvar keys, i.e. for every expvar key you 40 | // want to export as Prometheus metric, you need an entry in the exports 41 | // map. The descriptor mapped to each key describes how to export the expvar 42 | // value. It defines the name and the help string of the Prometheus metric 43 | // proxying the expvar value. The type will always be Untyped. 44 | // 45 | // For descriptors without variable labels, the expvar value must be a number or 46 | // a bool. The number is then directly exported as the Prometheus sample 47 | // value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values 48 | // that are not numbers or bools are silently ignored. 49 | // 50 | // If the descriptor has one variable label, the expvar value must be an expvar 51 | // map. The keys in the expvar map become the various values of the one 52 | // Prometheus label. The values in the expvar map must be numbers or bools again 53 | // as above. 54 | // 55 | // For descriptors with more than one variable label, the expvar must be a 56 | // nested expvar map, i.e. where the values of the topmost map are maps again 57 | // etc. until a depth is reached that corresponds to the number of labels. The 58 | // leaves of that structure must be numbers or bools as above to serve as the 59 | // sample values. 60 | // 61 | // Anything that does not fit into the scheme above is silently ignored. 62 | func NewExpvarCollector(exports map[string]*Desc) Collector { 63 | return &expvarCollector{ 64 | exports: exports, 65 | } 66 | } 67 | 68 | // Describe implements Collector. 69 | func (e *expvarCollector) Describe(ch chan<- *Desc) { 70 | for _, desc := range e.exports { 71 | ch <- desc 72 | } 73 | } 74 | 75 | // Collect implements Collector. 76 | func (e *expvarCollector) Collect(ch chan<- Metric) { 77 | for name, desc := range e.exports { 78 | var m Metric 79 | expVar := expvar.Get(name) 80 | if expVar == nil { 81 | continue 82 | } 83 | var v interface{} 84 | labels := make([]string, len(desc.variableLabels)) 85 | if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil { 86 | ch <- NewInvalidMetric(desc, err) 87 | continue 88 | } 89 | var processValue func(v interface{}, i int) 90 | processValue = func(v interface{}, i int) { 91 | if i >= len(labels) { 92 | copiedLabels := append(make([]string, 0, len(labels)), labels...) 93 | switch v := v.(type) { 94 | case float64: 95 | m = MustNewConstMetric(desc, UntypedValue, v, copiedLabels...) 96 | case bool: 97 | if v { 98 | m = MustNewConstMetric(desc, UntypedValue, 1, copiedLabels...) 99 | } else { 100 | m = MustNewConstMetric(desc, UntypedValue, 0, copiedLabels...) 101 | } 102 | default: 103 | return 104 | } 105 | ch <- m 106 | return 107 | } 108 | vm, ok := v.(map[string]interface{}) 109 | if !ok { 110 | return 111 | } 112 | for lv, val := range vm { 113 | labels[i] = lv 114 | processValue(val, i+1) 115 | } 116 | } 117 | processValue(v, 0) 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "spyv5/YFBjYyZLZa1U2LBfDR8PM=", 7 | "path": "github.com/beorn7/perks/quantile", 8 | "revision": "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9", 9 | "revisionTime": "2016-08-04T10:47:26Z" 10 | }, 11 | { 12 | "checksumSHA1": "kBeNcaKk56FguvPSUCEaH6AxpRc=", 13 | "path": "github.com/golang/protobuf/proto", 14 | "revision": "2bba0603135d7d7f5cb73b2125beeda19c09f4ef", 15 | "revisionTime": "2017-03-31T03:19:02Z" 16 | }, 17 | { 18 | "checksumSHA1": "g/V4qrXjUGG9B+e3hB+4NAYJ5Gs=", 19 | "path": "github.com/gorilla/context", 20 | "revision": "08b5f424b9271eedf6f9f0ce86cb9396ed337a42", 21 | "revisionTime": "2016-08-17T18:46:32Z" 22 | }, 23 | { 24 | "checksumSHA1": "zmCk+lgIeiOf0Ng9aFP9aFy8ksE=", 25 | "path": "github.com/gorilla/mux", 26 | "revision": "599cba5e7b6137d46ddf58fb1765f5d928e69604", 27 | "revisionTime": "2017-02-28T22:43:54Z" 28 | }, 29 | { 30 | "checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=", 31 | "path": "github.com/matttproud/golang_protobuf_extensions/pbutil", 32 | "revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c", 33 | "revisionTime": "2016-04-24T11:30:07Z" 34 | }, 35 | { 36 | "checksumSHA1": "d2irkxoHgazkTuLIvJGiYwagl8o=", 37 | "path": "github.com/prometheus/client_golang/prometheus", 38 | "revision": "08fd2e12372a66e68e30523c7642e0cbc3e4fbde", 39 | "revisionTime": "2017-04-01T10:34:46Z" 40 | }, 41 | { 42 | "checksumSHA1": "lG3//eDlwqA4IOuAPrNtLh9G0TA=", 43 | "path": "github.com/prometheus/client_golang/prometheus/promhttp", 44 | "revision": "08fd2e12372a66e68e30523c7642e0cbc3e4fbde", 45 | "revisionTime": "2017-04-01T10:34:46Z" 46 | }, 47 | { 48 | "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=", 49 | "path": "github.com/prometheus/client_model/go", 50 | "revision": "6f3806018612930941127f2a7c6c453ba2c527d2", 51 | "revisionTime": "2017-02-16T18:52:47Z" 52 | }, 53 | { 54 | "checksumSHA1": "Wtpzndm/+bdwwNU5PCTfb4oUhc8=", 55 | "path": "github.com/prometheus/common/expfmt", 56 | "revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8", 57 | "revisionTime": "2017-04-18T15:52:10Z" 58 | }, 59 | { 60 | "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=", 61 | "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", 62 | "revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8", 63 | "revisionTime": "2017-04-18T15:52:10Z" 64 | }, 65 | { 66 | "checksumSHA1": "0LL9u9tfv1KPBjNEiMDP6q7lpog=", 67 | "path": "github.com/prometheus/common/model", 68 | "revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8", 69 | "revisionTime": "2017-04-18T15:52:10Z" 70 | }, 71 | { 72 | "checksumSHA1": "cD4xn1qxbkiuXqUExpdnDroCTrY=", 73 | "path": "github.com/prometheus/procfs", 74 | "revision": "a1dba9ce8baed984a2495b658c82687f8157b98f", 75 | "revisionTime": "2017-02-16T22:32:56Z" 76 | }, 77 | { 78 | "checksumSHA1": "kOWRcAHWFkId0aCIOSOyjzC0Zfc=", 79 | "path": "github.com/prometheus/procfs/xfs", 80 | "revision": "a1dba9ce8baed984a2495b658c82687f8157b98f", 81 | "revisionTime": "2017-02-16T22:32:56Z" 82 | }, 83 | { 84 | "checksumSHA1": "ezZyPBDiKHM5y+YmlIhrWIzgbfw=", 85 | "path": "github.com/urfave/negroni", 86 | "revision": "c0db5feaa33826cd5117930c8f4ee5c0f565eec6", 87 | "revisionTime": "2017-02-26T00:53:33Z" 88 | }, 89 | { 90 | "checksumSHA1": "+4r0PnLwwyhO5/jvU5R/TEJb4kA=", 91 | "path": "gopkg.in/bsm/ratelimit.v1", 92 | "revision": "db14e161995a5177acef654cb0dd785e8ee8bc22", 93 | "revisionTime": "2016-02-20T15:49:07Z" 94 | }, 95 | { 96 | "checksumSHA1": "/EL/UuzIPObHgESjkBMaD4gaXOw=", 97 | "path": "gopkg.in/redis.v3", 98 | "revision": "b5e368500d0a508ef8f16e9c2d4025a8a46bcc29", 99 | "revisionTime": "2016-06-27T09:56:34Z" 100 | }, 101 | { 102 | "checksumSHA1": "b4Z72l8sq4xuWhR+nM5vbLQIv+o=", 103 | "path": "gopkg.in/redis.v3/internal", 104 | "revision": "b5e368500d0a508ef8f16e9c2d4025a8a46bcc29", 105 | "revisionTime": "2016-06-27T09:56:34Z" 106 | }, 107 | { 108 | "checksumSHA1": "tNI/mAuqqQqfYU4vuJghUroIts4=", 109 | "path": "gopkg.in/redis.v3/internal/consistenthash", 110 | "revision": "b5e368500d0a508ef8f16e9c2d4025a8a46bcc29", 111 | "revisionTime": "2016-06-27T09:56:34Z" 112 | }, 113 | { 114 | "checksumSHA1": "JvqkSear94dc+NgofRqBAUmLcN0=", 115 | "path": "gopkg.in/redis.v3/internal/hashtag", 116 | "revision": "b5e368500d0a508ef8f16e9c2d4025a8a46bcc29", 117 | "revisionTime": "2016-06-27T09:56:34Z" 118 | }, 119 | { 120 | "checksumSHA1": "ROpD4/McQLnnxpPenjA0mEZfTL8=", 121 | "path": "gopkg.in/redis.v3/internal/pool", 122 | "revision": "b5e368500d0a508ef8f16e9c2d4025a8a46bcc29", 123 | "revisionTime": "2016-06-27T09:56:34Z" 124 | } 125 | ], 126 | "rootPath": "github.com/andrestc/go-prom-talk" 127 | } 128 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/negroni/negroni.go: -------------------------------------------------------------------------------- 1 | package negroni 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "os" 7 | ) 8 | 9 | // Handler handler is an interface that objects can implement to be registered to serve as middleware 10 | // in the Negroni middleware stack. 11 | // ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc 12 | // passed in. 13 | // 14 | // If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked. 15 | type Handler interface { 16 | ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) 17 | } 18 | 19 | // HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers. 20 | // If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f. 21 | type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) 22 | 23 | func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 24 | h(rw, r, next) 25 | } 26 | 27 | type middleware struct { 28 | handler Handler 29 | next *middleware 30 | } 31 | 32 | func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 33 | m.handler.ServeHTTP(rw, r, m.next.ServeHTTP) 34 | } 35 | 36 | // Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni 37 | // middleware. The next http.HandlerFunc is automatically called after the Handler 38 | // is executed. 39 | func Wrap(handler http.Handler) Handler { 40 | return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { 41 | handler.ServeHTTP(rw, r) 42 | next(rw, r) 43 | }) 44 | } 45 | 46 | // Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler. 47 | // Negroni middleware is evaluated in the order that they are added to the stack using 48 | // the Use and UseHandler methods. 49 | type Negroni struct { 50 | middleware middleware 51 | handlers []Handler 52 | } 53 | 54 | // New returns a new Negroni instance with no middleware preconfigured. 55 | func New(handlers ...Handler) *Negroni { 56 | return &Negroni{ 57 | handlers: handlers, 58 | middleware: build(handlers), 59 | } 60 | } 61 | 62 | // With returns a new Negroni instance that is a combination of the negroni 63 | // receiver's handlers and the provided handlers. 64 | func (n *Negroni) With(handlers ...Handler) *Negroni { 65 | return New( 66 | append(n.handlers, handlers...)..., 67 | ) 68 | } 69 | 70 | // Classic returns a new Negroni instance with the default middleware already 71 | // in the stack. 72 | // 73 | // Recovery - Panic Recovery Middleware 74 | // Logger - Request/Response Logging 75 | // Static - Static File Serving 76 | func Classic() *Negroni { 77 | return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public"))) 78 | } 79 | 80 | func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { 81 | n.middleware.ServeHTTP(NewResponseWriter(rw), r) 82 | } 83 | 84 | // Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. 85 | func (n *Negroni) Use(handler Handler) { 86 | if handler == nil { 87 | panic("handler cannot be nil") 88 | } 89 | 90 | n.handlers = append(n.handlers, handler) 91 | n.middleware = build(n.handlers) 92 | } 93 | 94 | // UseFunc adds a Negroni-style handler function onto the middleware stack. 95 | func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) { 96 | n.Use(HandlerFunc(handlerFunc)) 97 | } 98 | 99 | // UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. 100 | func (n *Negroni) UseHandler(handler http.Handler) { 101 | n.Use(Wrap(handler)) 102 | } 103 | 104 | // UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack. 105 | func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { 106 | n.UseHandler(http.HandlerFunc(handlerFunc)) 107 | } 108 | 109 | // Run is a convenience function that runs the negroni stack as an HTTP 110 | // server. The addr string takes the same format as http.ListenAndServe. 111 | func (n *Negroni) Run(addr string) { 112 | l := log.New(os.Stdout, "[negroni] ", 0) 113 | l.Printf("listening on %s", addr) 114 | l.Fatal(http.ListenAndServe(addr, n)) 115 | } 116 | 117 | // Returns a list of all the handlers in the current Negroni middleware chain. 118 | func (n *Negroni) Handlers() []Handler { 119 | return n.handlers 120 | } 121 | 122 | func build(handlers []Handler) middleware { 123 | var next middleware 124 | 125 | if len(handlers) == 0 { 126 | return voidMiddleware() 127 | } else if len(handlers) > 1 { 128 | next = build(handlers[1:]) 129 | } else { 130 | next = voidMiddleware() 131 | } 132 | 133 | return middleware{handlers[0], &next} 134 | } 135 | 136 | func voidMiddleware() middleware { 137 | return middleware{ 138 | HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}), 139 | &middleware{}, 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/labelset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | "sort" 20 | "strings" 21 | ) 22 | 23 | // A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet 24 | // may be fully-qualified down to the point where it may resolve to a single 25 | // Metric in the data store or not. All operations that occur within the realm 26 | // of a LabelSet can emit a vector of Metric entities to which the LabelSet may 27 | // match. 28 | type LabelSet map[LabelName]LabelValue 29 | 30 | // Validate checks whether all names and values in the label set 31 | // are valid. 32 | func (ls LabelSet) Validate() error { 33 | for ln, lv := range ls { 34 | if !ln.IsValid() { 35 | return fmt.Errorf("invalid name %q", ln) 36 | } 37 | if !lv.IsValid() { 38 | return fmt.Errorf("invalid value %q", lv) 39 | } 40 | } 41 | return nil 42 | } 43 | 44 | // Equal returns true iff both label sets have exactly the same key/value pairs. 45 | func (ls LabelSet) Equal(o LabelSet) bool { 46 | if len(ls) != len(o) { 47 | return false 48 | } 49 | for ln, lv := range ls { 50 | olv, ok := o[ln] 51 | if !ok { 52 | return false 53 | } 54 | if olv != lv { 55 | return false 56 | } 57 | } 58 | return true 59 | } 60 | 61 | // Before compares the metrics, using the following criteria: 62 | // 63 | // If m has fewer labels than o, it is before o. If it has more, it is not. 64 | // 65 | // If the number of labels is the same, the superset of all label names is 66 | // sorted alphanumerically. The first differing label pair found in that order 67 | // determines the outcome: If the label does not exist at all in m, then m is 68 | // before o, and vice versa. Otherwise the label value is compared 69 | // alphanumerically. 70 | // 71 | // If m and o are equal, the method returns false. 72 | func (ls LabelSet) Before(o LabelSet) bool { 73 | if len(ls) < len(o) { 74 | return true 75 | } 76 | if len(ls) > len(o) { 77 | return false 78 | } 79 | 80 | lns := make(LabelNames, 0, len(ls)+len(o)) 81 | for ln := range ls { 82 | lns = append(lns, ln) 83 | } 84 | for ln := range o { 85 | lns = append(lns, ln) 86 | } 87 | // It's probably not worth it to de-dup lns. 88 | sort.Sort(lns) 89 | for _, ln := range lns { 90 | mlv, ok := ls[ln] 91 | if !ok { 92 | return true 93 | } 94 | olv, ok := o[ln] 95 | if !ok { 96 | return false 97 | } 98 | if mlv < olv { 99 | return true 100 | } 101 | if mlv > olv { 102 | return false 103 | } 104 | } 105 | return false 106 | } 107 | 108 | // Clone returns a copy of the label set. 109 | func (ls LabelSet) Clone() LabelSet { 110 | lsn := make(LabelSet, len(ls)) 111 | for ln, lv := range ls { 112 | lsn[ln] = lv 113 | } 114 | return lsn 115 | } 116 | 117 | // Merge is a helper function to non-destructively merge two label sets. 118 | func (l LabelSet) Merge(other LabelSet) LabelSet { 119 | result := make(LabelSet, len(l)) 120 | 121 | for k, v := range l { 122 | result[k] = v 123 | } 124 | 125 | for k, v := range other { 126 | result[k] = v 127 | } 128 | 129 | return result 130 | } 131 | 132 | func (l LabelSet) String() string { 133 | lstrs := make([]string, 0, len(l)) 134 | for l, v := range l { 135 | lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v)) 136 | } 137 | 138 | sort.Strings(lstrs) 139 | return fmt.Sprintf("{%s}", strings.Join(lstrs, ", ")) 140 | } 141 | 142 | // Fingerprint returns the LabelSet's fingerprint. 143 | func (ls LabelSet) Fingerprint() Fingerprint { 144 | return labelSetToFingerprint(ls) 145 | } 146 | 147 | // FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing 148 | // algorithm, which is, however, more susceptible to hash collisions. 149 | func (ls LabelSet) FastFingerprint() Fingerprint { 150 | return labelSetToFastFingerprint(ls) 151 | } 152 | 153 | // UnmarshalJSON implements the json.Unmarshaler interface. 154 | func (l *LabelSet) UnmarshalJSON(b []byte) error { 155 | var m map[LabelName]LabelValue 156 | if err := json.Unmarshal(b, &m); err != nil { 157 | return err 158 | } 159 | // encoding/json only unmarshals maps of the form map[string]T. It treats 160 | // LabelName as a string and does not call its UnmarshalJSON method. 161 | // Thus, we have to replicate the behavior here. 162 | for ln := range m { 163 | if !ln.IsValid() { 164 | return fmt.Errorf("%q is not a valid label name", ln) 165 | } 166 | } 167 | *l = LabelSet(m) 168 | return nil 169 | } 170 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go: -------------------------------------------------------------------------------- 1 | /* 2 | HTTP Content-Type Autonegotiation. 3 | 4 | The functions in this package implement the behaviour specified in 5 | http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 6 | 7 | Copyright (c) 2011, Open Knowledge Foundation Ltd. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are 12 | met: 13 | 14 | Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in 19 | the documentation and/or other materials provided with the 20 | distribution. 21 | 22 | Neither the name of the Open Knowledge Foundation Ltd. nor the 23 | names of its contributors may be used to endorse or promote 24 | products derived from this software without specific prior written 25 | permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | 40 | */ 41 | package goautoneg 42 | 43 | import ( 44 | "sort" 45 | "strconv" 46 | "strings" 47 | ) 48 | 49 | // Structure to represent a clause in an HTTP Accept Header 50 | type Accept struct { 51 | Type, SubType string 52 | Q float64 53 | Params map[string]string 54 | } 55 | 56 | // For internal use, so that we can use the sort interface 57 | type accept_slice []Accept 58 | 59 | func (accept accept_slice) Len() int { 60 | slice := []Accept(accept) 61 | return len(slice) 62 | } 63 | 64 | func (accept accept_slice) Less(i, j int) bool { 65 | slice := []Accept(accept) 66 | ai, aj := slice[i], slice[j] 67 | if ai.Q > aj.Q { 68 | return true 69 | } 70 | if ai.Type != "*" && aj.Type == "*" { 71 | return true 72 | } 73 | if ai.SubType != "*" && aj.SubType == "*" { 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | func (accept accept_slice) Swap(i, j int) { 80 | slice := []Accept(accept) 81 | slice[i], slice[j] = slice[j], slice[i] 82 | } 83 | 84 | // Parse an Accept Header string returning a sorted list 85 | // of clauses 86 | func ParseAccept(header string) (accept []Accept) { 87 | parts := strings.Split(header, ",") 88 | accept = make([]Accept, 0, len(parts)) 89 | for _, part := range parts { 90 | part := strings.Trim(part, " ") 91 | 92 | a := Accept{} 93 | a.Params = make(map[string]string) 94 | a.Q = 1.0 95 | 96 | mrp := strings.Split(part, ";") 97 | 98 | media_range := mrp[0] 99 | sp := strings.Split(media_range, "/") 100 | a.Type = strings.Trim(sp[0], " ") 101 | 102 | switch { 103 | case len(sp) == 1 && a.Type == "*": 104 | a.SubType = "*" 105 | case len(sp) == 2: 106 | a.SubType = strings.Trim(sp[1], " ") 107 | default: 108 | continue 109 | } 110 | 111 | if len(mrp) == 1 { 112 | accept = append(accept, a) 113 | continue 114 | } 115 | 116 | for _, param := range mrp[1:] { 117 | sp := strings.SplitN(param, "=", 2) 118 | if len(sp) != 2 { 119 | continue 120 | } 121 | token := strings.Trim(sp[0], " ") 122 | if token == "q" { 123 | a.Q, _ = strconv.ParseFloat(sp[1], 32) 124 | } else { 125 | a.Params[token] = strings.Trim(sp[1], " ") 126 | } 127 | } 128 | 129 | accept = append(accept, a) 130 | } 131 | 132 | slice := accept_slice(accept) 133 | sort.Sort(slice) 134 | 135 | return 136 | } 137 | 138 | // Negotiate the most appropriate content_type given the accept header 139 | // and a list of alternatives. 140 | func Negotiate(header string, alternatives []string) (content_type string) { 141 | asp := make([][]string, 0, len(alternatives)) 142 | for _, ctype := range alternatives { 143 | asp = append(asp, strings.SplitN(ctype, "/", 2)) 144 | } 145 | for _, clause := range ParseAccept(header) { 146 | for i, ctsp := range asp { 147 | if clause.Type == ctsp[0] && clause.SubType == ctsp[1] { 148 | content_type = alternatives[i] 149 | return 150 | } 151 | if clause.Type == ctsp[0] && clause.SubType == "*" { 152 | content_type = alternatives[i] 153 | return 154 | } 155 | if clause.Type == "*" && clause.SubType == "*" { 156 | content_type = alternatives[i] 157 | return 158 | } 159 | } 160 | } 161 | return 162 | } 163 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/signature.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "sort" 18 | ) 19 | 20 | // SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is 21 | // used to separate label names, label values, and other strings from each other 22 | // when calculating their combined hash value (aka signature aka fingerprint). 23 | const SeparatorByte byte = 255 24 | 25 | var ( 26 | // cache the signature of an empty label set. 27 | emptyLabelSignature = hashNew() 28 | ) 29 | 30 | // LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a 31 | // given label set. (Collisions are possible but unlikely if the number of label 32 | // sets the function is applied to is small.) 33 | func LabelsToSignature(labels map[string]string) uint64 { 34 | if len(labels) == 0 { 35 | return emptyLabelSignature 36 | } 37 | 38 | labelNames := make([]string, 0, len(labels)) 39 | for labelName := range labels { 40 | labelNames = append(labelNames, labelName) 41 | } 42 | sort.Strings(labelNames) 43 | 44 | sum := hashNew() 45 | for _, labelName := range labelNames { 46 | sum = hashAdd(sum, labelName) 47 | sum = hashAddByte(sum, SeparatorByte) 48 | sum = hashAdd(sum, labels[labelName]) 49 | sum = hashAddByte(sum, SeparatorByte) 50 | } 51 | return sum 52 | } 53 | 54 | // labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as 55 | // parameter (rather than a label map) and returns a Fingerprint. 56 | func labelSetToFingerprint(ls LabelSet) Fingerprint { 57 | if len(ls) == 0 { 58 | return Fingerprint(emptyLabelSignature) 59 | } 60 | 61 | labelNames := make(LabelNames, 0, len(ls)) 62 | for labelName := range ls { 63 | labelNames = append(labelNames, labelName) 64 | } 65 | sort.Sort(labelNames) 66 | 67 | sum := hashNew() 68 | for _, labelName := range labelNames { 69 | sum = hashAdd(sum, string(labelName)) 70 | sum = hashAddByte(sum, SeparatorByte) 71 | sum = hashAdd(sum, string(ls[labelName])) 72 | sum = hashAddByte(sum, SeparatorByte) 73 | } 74 | return Fingerprint(sum) 75 | } 76 | 77 | // labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a 78 | // faster and less allocation-heavy hash function, which is more susceptible to 79 | // create hash collisions. Therefore, collision detection should be applied. 80 | func labelSetToFastFingerprint(ls LabelSet) Fingerprint { 81 | if len(ls) == 0 { 82 | return Fingerprint(emptyLabelSignature) 83 | } 84 | 85 | var result uint64 86 | for labelName, labelValue := range ls { 87 | sum := hashNew() 88 | sum = hashAdd(sum, string(labelName)) 89 | sum = hashAddByte(sum, SeparatorByte) 90 | sum = hashAdd(sum, string(labelValue)) 91 | result ^= sum 92 | } 93 | return Fingerprint(result) 94 | } 95 | 96 | // SignatureForLabels works like LabelsToSignature but takes a Metric as 97 | // parameter (rather than a label map) and only includes the labels with the 98 | // specified LabelNames into the signature calculation. The labels passed in 99 | // will be sorted by this function. 100 | func SignatureForLabels(m Metric, labels ...LabelName) uint64 { 101 | if len(labels) == 0 { 102 | return emptyLabelSignature 103 | } 104 | 105 | sort.Sort(LabelNames(labels)) 106 | 107 | sum := hashNew() 108 | for _, label := range labels { 109 | sum = hashAdd(sum, string(label)) 110 | sum = hashAddByte(sum, SeparatorByte) 111 | sum = hashAdd(sum, string(m[label])) 112 | sum = hashAddByte(sum, SeparatorByte) 113 | } 114 | return sum 115 | } 116 | 117 | // SignatureWithoutLabels works like LabelsToSignature but takes a Metric as 118 | // parameter (rather than a label map) and excludes the labels with any of the 119 | // specified LabelNames from the signature calculation. 120 | func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 { 121 | if len(m) == 0 { 122 | return emptyLabelSignature 123 | } 124 | 125 | labelNames := make(LabelNames, 0, len(m)) 126 | for labelName := range m { 127 | if _, exclude := labels[labelName]; !exclude { 128 | labelNames = append(labelNames, labelName) 129 | } 130 | } 131 | if len(labelNames) == 0 { 132 | return emptyLabelSignature 133 | } 134 | sort.Sort(labelNames) 135 | 136 | sum := hashNew() 137 | for _, labelName := range labelNames { 138 | sum = hashAdd(sum, string(labelName)) 139 | sum = hashAddByte(sum, SeparatorByte) 140 | sum = hashAdd(sum, string(m[labelName])) 141 | sum = hashAddByte(sum, SeparatorByte) 142 | } 143 | return sum 144 | } 145 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/README.md: -------------------------------------------------------------------------------- 1 | # Redis client for Golang [![Build Status](https://travis-ci.org/go-redis/redis.png?branch=master)](https://travis-ci.org/go-redis/redis) 2 | 3 | Supports: 4 | 5 | - Redis 3 commands except QUIT, MONITOR, SLOWLOG and SYNC. 6 | - [Pub/Sub](http://godoc.org/gopkg.in/redis.v3#PubSub). 7 | - [Transactions](http://godoc.org/gopkg.in/redis.v3#Multi). 8 | - [Pipelining](http://godoc.org/gopkg.in/redis.v3#Client.Pipeline). 9 | - [Scripting](http://godoc.org/gopkg.in/redis.v3#Script). 10 | - [Timeouts](http://godoc.org/gopkg.in/redis.v3#Options). 11 | - [Redis Sentinel](http://godoc.org/gopkg.in/redis.v3#NewFailoverClient). 12 | - [Redis Cluster](http://godoc.org/gopkg.in/redis.v3#NewClusterClient). 13 | - [Ring](http://godoc.org/gopkg.in/redis.v3#NewRing). 14 | - [Cache friendly](https://github.com/go-redis/cache). 15 | - [Rate limiting](https://github.com/go-redis/rate). 16 | - [Distributed Locks](https://github.com/bsm/redis-lock). 17 | 18 | API docs: http://godoc.org/gopkg.in/redis.v3. 19 | Examples: http://godoc.org/gopkg.in/redis.v3#pkg-examples. 20 | 21 | ## Installation 22 | 23 | Install: 24 | 25 | go get gopkg.in/redis.v3 26 | 27 | ## Quickstart 28 | 29 | ```go 30 | func ExampleNewClient() { 31 | client := redis.NewClient(&redis.Options{ 32 | Addr: "localhost:6379", 33 | Password: "", // no password set 34 | DB: 0, // use default DB 35 | }) 36 | 37 | pong, err := client.Ping().Result() 38 | fmt.Println(pong, err) 39 | // Output: PONG 40 | } 41 | 42 | func ExampleClient() { 43 | err := client.Set("key", "value", 0).Err() 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | val, err := client.Get("key").Result() 49 | if err != nil { 50 | panic(err) 51 | } 52 | fmt.Println("key", val) 53 | 54 | val2, err := client.Get("key2").Result() 55 | if err == redis.Nil { 56 | fmt.Println("key2 does not exists") 57 | } else if err != nil { 58 | panic(err) 59 | } else { 60 | fmt.Println("key2", val2) 61 | } 62 | // Output: key value 63 | // key2 does not exists 64 | } 65 | ``` 66 | 67 | ## Howto 68 | 69 | Please go through [examples](http://godoc.org/gopkg.in/redis.v3#pkg-examples) to get an idea how to use this package. 70 | 71 | ## Look and feel 72 | 73 | Some corner cases: 74 | 75 | SET key value EX 10 NX 76 | set, err := client.SetNX("key", "value", 10*time.Second).Result() 77 | 78 | SORT list LIMIT 0 2 ASC 79 | vals, err := client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result() 80 | 81 | ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2 82 | vals, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeByScore{ 83 | Min: "-inf", 84 | Max: "+inf", 85 | Offset: 0, 86 | Count: 2, 87 | }).Result() 88 | 89 | ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM 90 | vals, err := client.ZInterStore("out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2").Result() 91 | 92 | EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello" 93 | vals, err := client.Eval("return {KEYS[1],ARGV[1]}", []string{"key"}, []string{"hello"}).Result() 94 | 95 | ## Benchmark 96 | 97 | go-redis vs redigo: 98 | 99 | ``` 100 | BenchmarkSetGoRedis10Conns64Bytes-4 200000 7621 ns/op 210 B/op 6 allocs/op 101 | BenchmarkSetGoRedis100Conns64Bytes-4 200000 7554 ns/op 210 B/op 6 allocs/op 102 | BenchmarkSetGoRedis10Conns1KB-4 200000 7697 ns/op 210 B/op 6 allocs/op 103 | BenchmarkSetGoRedis100Conns1KB-4 200000 7688 ns/op 210 B/op 6 allocs/op 104 | BenchmarkSetGoRedis10Conns10KB-4 200000 9214 ns/op 210 B/op 6 allocs/op 105 | BenchmarkSetGoRedis100Conns10KB-4 200000 9181 ns/op 210 B/op 6 allocs/op 106 | BenchmarkSetGoRedis10Conns1MB-4 2000 583242 ns/op 2337 B/op 6 allocs/op 107 | BenchmarkSetGoRedis100Conns1MB-4 2000 583089 ns/op 2338 B/op 6 allocs/op 108 | BenchmarkSetRedigo10Conns64Bytes-4 200000 7576 ns/op 208 B/op 7 allocs/op 109 | BenchmarkSetRedigo100Conns64Bytes-4 200000 7782 ns/op 208 B/op 7 allocs/op 110 | BenchmarkSetRedigo10Conns1KB-4 200000 7958 ns/op 208 B/op 7 allocs/op 111 | BenchmarkSetRedigo100Conns1KB-4 200000 7725 ns/op 208 B/op 7 allocs/op 112 | BenchmarkSetRedigo10Conns10KB-4 100000 18442 ns/op 208 B/op 7 allocs/op 113 | BenchmarkSetRedigo100Conns10KB-4 100000 18818 ns/op 208 B/op 7 allocs/op 114 | BenchmarkSetRedigo10Conns1MB-4 2000 668829 ns/op 226 B/op 7 allocs/op 115 | BenchmarkSetRedigo100Conns1MB-4 2000 679542 ns/op 226 B/op 7 allocs/op 116 | ``` 117 | 118 | Redis Cluster: 119 | 120 | ``` 121 | BenchmarkRedisPing-4 200000 6983 ns/op 116 B/op 4 allocs/op 122 | BenchmarkRedisClusterPing-4 100000 11535 ns/op 117 B/op 4 allocs/op 123 | ``` 124 | 125 | ## Shameless plug 126 | 127 | Check my [PostgreSQL client for Go](https://github.com/go-pg/pg). 128 | -------------------------------------------------------------------------------- /vendor/gopkg.in/redis.v3/multi.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "gopkg.in/redis.v3/internal" 8 | "gopkg.in/redis.v3/internal/pool" 9 | ) 10 | 11 | var errDiscard = errors.New("redis: Discard can be used only inside Exec") 12 | 13 | // Multi implements Redis transactions as described in 14 | // http://redis.io/topics/transactions. It's NOT safe for concurrent use 15 | // by multiple goroutines, because Exec resets list of watched keys. 16 | // If you don't need WATCH it is better to use Pipeline. 17 | // 18 | // TODO(vmihailenco): rename to Tx and rework API 19 | type Multi struct { 20 | commandable 21 | 22 | base *baseClient 23 | 24 | cmds []Cmder 25 | closed bool 26 | } 27 | 28 | // Watch creates new transaction and marks the keys to be watched 29 | // for conditional execution of a transaction. 30 | func (c *Client) Watch(keys ...string) (*Multi, error) { 31 | tx := c.Multi() 32 | if err := tx.Watch(keys...).Err(); err != nil { 33 | tx.Close() 34 | return nil, err 35 | } 36 | return tx, nil 37 | } 38 | 39 | // Deprecated. Use Watch instead. 40 | func (c *Client) Multi() *Multi { 41 | multi := &Multi{ 42 | base: &baseClient{ 43 | opt: c.opt, 44 | connPool: pool.NewStickyConnPool(c.connPool.(*pool.ConnPool), true), 45 | }, 46 | } 47 | multi.commandable.process = multi.process 48 | return multi 49 | } 50 | 51 | func (c *Multi) process(cmd Cmder) { 52 | if c.cmds == nil { 53 | c.base.process(cmd) 54 | } else { 55 | c.cmds = append(c.cmds, cmd) 56 | } 57 | } 58 | 59 | // Close closes the client, releasing any open resources. 60 | func (c *Multi) Close() error { 61 | c.closed = true 62 | if err := c.Unwatch().Err(); err != nil { 63 | internal.Logf("Unwatch failed: %s", err) 64 | } 65 | return c.base.Close() 66 | } 67 | 68 | // Watch marks the keys to be watched for conditional execution 69 | // of a transaction. 70 | func (c *Multi) Watch(keys ...string) *StatusCmd { 71 | args := make([]interface{}, 1+len(keys)) 72 | args[0] = "WATCH" 73 | for i, key := range keys { 74 | args[1+i] = key 75 | } 76 | cmd := NewStatusCmd(args...) 77 | c.Process(cmd) 78 | return cmd 79 | } 80 | 81 | // Unwatch flushes all the previously watched keys for a transaction. 82 | func (c *Multi) Unwatch(keys ...string) *StatusCmd { 83 | args := make([]interface{}, 1+len(keys)) 84 | args[0] = "UNWATCH" 85 | for i, key := range keys { 86 | args[1+i] = key 87 | } 88 | cmd := NewStatusCmd(args...) 89 | c.Process(cmd) 90 | return cmd 91 | } 92 | 93 | // Discard discards queued commands. 94 | func (c *Multi) Discard() error { 95 | if c.cmds == nil { 96 | return errDiscard 97 | } 98 | c.cmds = c.cmds[:1] 99 | return nil 100 | } 101 | 102 | // Exec executes all previously queued commands in a transaction 103 | // and restores the connection state to normal. 104 | // 105 | // When using WATCH, EXEC will execute commands only if the watched keys 106 | // were not modified, allowing for a check-and-set mechanism. 107 | // 108 | // Exec always returns list of commands. If transaction fails 109 | // TxFailedErr is returned. Otherwise Exec returns error of the first 110 | // failed command or nil. 111 | func (c *Multi) Exec(f func() error) ([]Cmder, error) { 112 | if c.closed { 113 | return nil, pool.ErrClosed 114 | } 115 | 116 | c.cmds = []Cmder{NewStatusCmd("MULTI")} 117 | if err := f(); err != nil { 118 | return nil, err 119 | } 120 | c.cmds = append(c.cmds, NewSliceCmd("EXEC")) 121 | 122 | cmds := c.cmds 123 | c.cmds = nil 124 | 125 | if len(cmds) == 2 { 126 | return []Cmder{}, nil 127 | } 128 | 129 | // Strip MULTI and EXEC commands. 130 | retCmds := cmds[1 : len(cmds)-1] 131 | 132 | cn, err := c.base.conn() 133 | if err != nil { 134 | setCmdsErr(retCmds, err) 135 | return retCmds, err 136 | } 137 | 138 | err = c.execCmds(cn, cmds) 139 | c.base.putConn(cn, err, false) 140 | return retCmds, err 141 | } 142 | 143 | func (c *Multi) execCmds(cn *pool.Conn, cmds []Cmder) error { 144 | err := writeCmd(cn, cmds...) 145 | if err != nil { 146 | setCmdsErr(cmds[1:len(cmds)-1], err) 147 | return err 148 | } 149 | 150 | statusCmd := NewStatusCmd() 151 | 152 | // Omit last command (EXEC). 153 | cmdsLen := len(cmds) - 1 154 | 155 | // Parse queued replies. 156 | for i := 0; i < cmdsLen; i++ { 157 | if err := statusCmd.readReply(cn); err != nil { 158 | setCmdsErr(cmds[1:len(cmds)-1], err) 159 | return err 160 | } 161 | } 162 | 163 | // Parse number of replies. 164 | line, err := readLine(cn) 165 | if err != nil { 166 | if err == Nil { 167 | err = TxFailedErr 168 | } 169 | setCmdsErr(cmds[1:len(cmds)-1], err) 170 | return err 171 | } 172 | if line[0] != '*' { 173 | err := fmt.Errorf("redis: expected '*', but got line %q", line) 174 | setCmdsErr(cmds[1:len(cmds)-1], err) 175 | return err 176 | } 177 | 178 | var firstCmdErr error 179 | 180 | // Parse replies. 181 | // Loop starts from 1 to omit MULTI cmd. 182 | for i := 1; i < cmdsLen; i++ { 183 | cmd := cmds[i] 184 | if err := cmd.readReply(cn); err != nil { 185 | if firstCmdErr == nil { 186 | firstCmdErr = err 187 | } 188 | } 189 | } 190 | 191 | return firstCmdErr 192 | } 193 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/xfs/xfs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package xfs provides access to statistics exposed by the XFS filesystem. 15 | package xfs 16 | 17 | // Stats contains XFS filesystem runtime statistics, parsed from 18 | // /proc/fs/xfs/stat. 19 | // 20 | // The names and meanings of each statistic were taken from 21 | // http://xfs.org/index.php/Runtime_Stats and xfs_stats.h in the Linux 22 | // kernel source. Most counters are uint32s (same data types used in 23 | // xfs_stats.h), but some of the "extended precision stats" are uint64s. 24 | type Stats struct { 25 | ExtentAllocation ExtentAllocationStats 26 | AllocationBTree BTreeStats 27 | BlockMapping BlockMappingStats 28 | BlockMapBTree BTreeStats 29 | DirectoryOperation DirectoryOperationStats 30 | Transaction TransactionStats 31 | InodeOperation InodeOperationStats 32 | LogOperation LogOperationStats 33 | ReadWrite ReadWriteStats 34 | AttributeOperation AttributeOperationStats 35 | InodeClustering InodeClusteringStats 36 | Vnode VnodeStats 37 | Buffer BufferStats 38 | ExtendedPrecision ExtendedPrecisionStats 39 | } 40 | 41 | // ExtentAllocationStats contains statistics regarding XFS extent allocations. 42 | type ExtentAllocationStats struct { 43 | ExtentsAllocated uint32 44 | BlocksAllocated uint32 45 | ExtentsFreed uint32 46 | BlocksFreed uint32 47 | } 48 | 49 | // BTreeStats contains statistics regarding an XFS internal B-tree. 50 | type BTreeStats struct { 51 | Lookups uint32 52 | Compares uint32 53 | RecordsInserted uint32 54 | RecordsDeleted uint32 55 | } 56 | 57 | // BlockMappingStats contains statistics regarding XFS block maps. 58 | type BlockMappingStats struct { 59 | Reads uint32 60 | Writes uint32 61 | Unmaps uint32 62 | ExtentListInsertions uint32 63 | ExtentListDeletions uint32 64 | ExtentListLookups uint32 65 | ExtentListCompares uint32 66 | } 67 | 68 | // DirectoryOperationStats contains statistics regarding XFS directory entries. 69 | type DirectoryOperationStats struct { 70 | Lookups uint32 71 | Creates uint32 72 | Removes uint32 73 | Getdents uint32 74 | } 75 | 76 | // TransactionStats contains statistics regarding XFS metadata transactions. 77 | type TransactionStats struct { 78 | Sync uint32 79 | Async uint32 80 | Empty uint32 81 | } 82 | 83 | // InodeOperationStats contains statistics regarding XFS inode operations. 84 | type InodeOperationStats struct { 85 | Attempts uint32 86 | Found uint32 87 | Recycle uint32 88 | Missed uint32 89 | Duplicate uint32 90 | Reclaims uint32 91 | AttributeChange uint32 92 | } 93 | 94 | // LogOperationStats contains statistics regarding the XFS log buffer. 95 | type LogOperationStats struct { 96 | Writes uint32 97 | Blocks uint32 98 | NoInternalBuffers uint32 99 | Force uint32 100 | ForceSleep uint32 101 | } 102 | 103 | // ReadWriteStats contains statistics regarding the number of read and write 104 | // system calls for XFS filesystems. 105 | type ReadWriteStats struct { 106 | Read uint32 107 | Write uint32 108 | } 109 | 110 | // AttributeOperationStats contains statistics regarding manipulation of 111 | // XFS extended file attributes. 112 | type AttributeOperationStats struct { 113 | Get uint32 114 | Set uint32 115 | Remove uint32 116 | List uint32 117 | } 118 | 119 | // InodeClusteringStats contains statistics regarding XFS inode clustering 120 | // operations. 121 | type InodeClusteringStats struct { 122 | Iflush uint32 123 | Flush uint32 124 | FlushInode uint32 125 | } 126 | 127 | // VnodeStats contains statistics regarding XFS vnode operations. 128 | type VnodeStats struct { 129 | Active uint32 130 | Allocate uint32 131 | Get uint32 132 | Hold uint32 133 | Release uint32 134 | Reclaim uint32 135 | Remove uint32 136 | Free uint32 137 | } 138 | 139 | // BufferStats contains statistics regarding XFS read/write I/O buffers. 140 | type BufferStats struct { 141 | Get uint32 142 | Create uint32 143 | GetLocked uint32 144 | GetLockedWaited uint32 145 | BusyLocked uint32 146 | MissLocked uint32 147 | PageRetries uint32 148 | PageFound uint32 149 | GetRead uint32 150 | } 151 | 152 | // ExtendedPrecisionStats contains high precision counters used to track the 153 | // total number of bytes read, written, or flushed, during XFS operations. 154 | type ExtendedPrecisionStats struct { 155 | FlushBytes uint64 156 | WriteBytes uint64 157 | ReadBytes uint64 158 | } 159 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_stat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | // Originally, this USER_HZ value was dynamically retrieved via a sysconf call 11 | // which required cgo. However, that caused a lot of problems regarding 12 | // cross-compilation. Alternatives such as running a binary to determine the 13 | // value, or trying to derive it in some other way were all problematic. After 14 | // much research it was determined that USER_HZ is actually hardcoded to 100 on 15 | // all Go-supported platforms as of the time of this writing. This is why we 16 | // decided to hardcode it here as well. It is not impossible that there could 17 | // be systems with exceptions, but they should be very exotic edge cases, and 18 | // in that case, the worst outcome will be two misreported metrics. 19 | // 20 | // See also the following discussions: 21 | // 22 | // - https://github.com/prometheus/node_exporter/issues/52 23 | // - https://github.com/prometheus/procfs/pull/2 24 | // - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue 25 | const userHZ = 100 26 | 27 | // ProcStat provides status information about the process, 28 | // read from /proc/[pid]/stat. 29 | type ProcStat struct { 30 | // The process ID. 31 | PID int 32 | // The filename of the executable. 33 | Comm string 34 | // The process state. 35 | State string 36 | // The PID of the parent of this process. 37 | PPID int 38 | // The process group ID of the process. 39 | PGRP int 40 | // The session ID of the process. 41 | Session int 42 | // The controlling terminal of the process. 43 | TTY int 44 | // The ID of the foreground process group of the controlling terminal of 45 | // the process. 46 | TPGID int 47 | // The kernel flags word of the process. 48 | Flags uint 49 | // The number of minor faults the process has made which have not required 50 | // loading a memory page from disk. 51 | MinFlt uint 52 | // The number of minor faults that the process's waited-for children have 53 | // made. 54 | CMinFlt uint 55 | // The number of major faults the process has made which have required 56 | // loading a memory page from disk. 57 | MajFlt uint 58 | // The number of major faults that the process's waited-for children have 59 | // made. 60 | CMajFlt uint 61 | // Amount of time that this process has been scheduled in user mode, 62 | // measured in clock ticks. 63 | UTime uint 64 | // Amount of time that this process has been scheduled in kernel mode, 65 | // measured in clock ticks. 66 | STime uint 67 | // Amount of time that this process's waited-for children have been 68 | // scheduled in user mode, measured in clock ticks. 69 | CUTime uint 70 | // Amount of time that this process's waited-for children have been 71 | // scheduled in kernel mode, measured in clock ticks. 72 | CSTime uint 73 | // For processes running a real-time scheduling policy, this is the negated 74 | // scheduling priority, minus one. 75 | Priority int 76 | // The nice value, a value in the range 19 (low priority) to -20 (high 77 | // priority). 78 | Nice int 79 | // Number of threads in this process. 80 | NumThreads int 81 | // The time the process started after system boot, the value is expressed 82 | // in clock ticks. 83 | Starttime uint64 84 | // Virtual memory size in bytes. 85 | VSize int 86 | // Resident set size in pages. 87 | RSS int 88 | 89 | fs FS 90 | } 91 | 92 | // NewStat returns the current status information of the process. 93 | func (p Proc) NewStat() (ProcStat, error) { 94 | f, err := os.Open(p.path("stat")) 95 | if err != nil { 96 | return ProcStat{}, err 97 | } 98 | defer f.Close() 99 | 100 | data, err := ioutil.ReadAll(f) 101 | if err != nil { 102 | return ProcStat{}, err 103 | } 104 | 105 | var ( 106 | ignore int 107 | 108 | s = ProcStat{PID: p.PID, fs: p.fs} 109 | l = bytes.Index(data, []byte("(")) 110 | r = bytes.LastIndex(data, []byte(")")) 111 | ) 112 | 113 | if l < 0 || r < 0 { 114 | return ProcStat{}, fmt.Errorf( 115 | "unexpected format, couldn't extract comm: %s", 116 | data, 117 | ) 118 | } 119 | 120 | s.Comm = string(data[l+1 : r]) 121 | _, err = fmt.Fscan( 122 | bytes.NewBuffer(data[r+2:]), 123 | &s.State, 124 | &s.PPID, 125 | &s.PGRP, 126 | &s.Session, 127 | &s.TTY, 128 | &s.TPGID, 129 | &s.Flags, 130 | &s.MinFlt, 131 | &s.CMinFlt, 132 | &s.MajFlt, 133 | &s.CMajFlt, 134 | &s.UTime, 135 | &s.STime, 136 | &s.CUTime, 137 | &s.CSTime, 138 | &s.Priority, 139 | &s.Nice, 140 | &s.NumThreads, 141 | &ignore, 142 | &s.Starttime, 143 | &s.VSize, 144 | &s.RSS, 145 | ) 146 | if err != nil { 147 | return ProcStat{}, err 148 | } 149 | 150 | return s, nil 151 | } 152 | 153 | // VirtualMemory returns the virtual memory size in bytes. 154 | func (s ProcStat) VirtualMemory() int { 155 | return s.VSize 156 | } 157 | 158 | // ResidentMemory returns the resident memory size in bytes. 159 | func (s ProcStat) ResidentMemory() int { 160 | return s.RSS * os.Getpagesize() 161 | } 162 | 163 | // StartTime returns the unix timestamp of the process in seconds. 164 | func (s ProcStat) StartTime() (float64, error) { 165 | stat, err := s.fs.NewStat() 166 | if err != nil { 167 | return 0, err 168 | } 169 | return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil 170 | } 171 | 172 | // CPUTime returns the total CPU user and system time in seconds. 173 | func (s ProcStat) CPUTime() float64 { 174 | return float64(s.UTime+s.STime) / userHZ 175 | } 176 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/gauge.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Gauge is a Metric that represents a single numerical value that can 17 | // arbitrarily go up and down. 18 | // 19 | // A Gauge is typically used for measured values like temperatures or current 20 | // memory usage, but also "counts" that can go up and down, like the number of 21 | // running goroutines. 22 | // 23 | // To create Gauge instances, use NewGauge. 24 | type Gauge interface { 25 | Metric 26 | Collector 27 | 28 | // Set sets the Gauge to an arbitrary value. 29 | Set(float64) 30 | // Inc increments the Gauge by 1. Use Add to increment it by arbitrary 31 | // values. 32 | Inc() 33 | // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary 34 | // values. 35 | Dec() 36 | // Add adds the given value to the Gauge. (The value can be negative, 37 | // resulting in a decrease of the Gauge.) 38 | Add(float64) 39 | // Sub subtracts the given value from the Gauge. (The value can be 40 | // negative, resulting in an increase of the Gauge.) 41 | Sub(float64) 42 | 43 | // SetToCurrentTime sets the Gauge to the current Unix time in seconds. 44 | SetToCurrentTime() 45 | } 46 | 47 | // GaugeOpts is an alias for Opts. See there for doc comments. 48 | type GaugeOpts Opts 49 | 50 | // NewGauge creates a new Gauge based on the provided GaugeOpts. 51 | func NewGauge(opts GaugeOpts) Gauge { 52 | return newValue(NewDesc( 53 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 54 | opts.Help, 55 | nil, 56 | opts.ConstLabels, 57 | ), GaugeValue, 0) 58 | } 59 | 60 | // GaugeVec is a Collector that bundles a set of Gauges that all share the same 61 | // Desc, but have different values for their variable labels. This is used if 62 | // you want to count the same thing partitioned by various dimensions 63 | // (e.g. number of operations queued, partitioned by user and operation 64 | // type). Create instances with NewGaugeVec. 65 | type GaugeVec struct { 66 | *MetricVec 67 | } 68 | 69 | // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and 70 | // partitioned by the given label names. At least one label name must be 71 | // provided. 72 | func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { 73 | desc := NewDesc( 74 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 75 | opts.Help, 76 | labelNames, 77 | opts.ConstLabels, 78 | ) 79 | return &GaugeVec{ 80 | MetricVec: newMetricVec(desc, func(lvs ...string) Metric { 81 | return newValue(desc, GaugeValue, 0, lvs...) 82 | }), 83 | } 84 | } 85 | 86 | // GetMetricWithLabelValues replaces the method of the same name in 87 | // MetricVec. The difference is that this method returns a Gauge and not a 88 | // Metric so that no type conversion is required. 89 | func (m *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) { 90 | metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) 91 | if metric != nil { 92 | return metric.(Gauge), err 93 | } 94 | return nil, err 95 | } 96 | 97 | // GetMetricWith replaces the method of the same name in MetricVec. The 98 | // difference is that this method returns a Gauge and not a Metric so that no 99 | // type conversion is required. 100 | func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { 101 | metric, err := m.MetricVec.GetMetricWith(labels) 102 | if metric != nil { 103 | return metric.(Gauge), err 104 | } 105 | return nil, err 106 | } 107 | 108 | // WithLabelValues works as GetMetricWithLabelValues, but panics where 109 | // GetMetricWithLabelValues would have returned an error. By not returning an 110 | // error, WithLabelValues allows shortcuts like 111 | // myVec.WithLabelValues("404", "GET").Add(42) 112 | func (m *GaugeVec) WithLabelValues(lvs ...string) Gauge { 113 | return m.MetricVec.WithLabelValues(lvs...).(Gauge) 114 | } 115 | 116 | // With works as GetMetricWith, but panics where GetMetricWithLabels would have 117 | // returned an error. By not returning an error, With allows shortcuts like 118 | // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) 119 | func (m *GaugeVec) With(labels Labels) Gauge { 120 | return m.MetricVec.With(labels).(Gauge) 121 | } 122 | 123 | // GaugeFunc is a Gauge whose value is determined at collect time by calling a 124 | // provided function. 125 | // 126 | // To create GaugeFunc instances, use NewGaugeFunc. 127 | type GaugeFunc interface { 128 | Metric 129 | Collector 130 | } 131 | 132 | // NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The 133 | // value reported is determined by calling the given function from within the 134 | // Write method. Take into account that metric collection may happen 135 | // concurrently. If that results in concurrent calls to Write, like in the case 136 | // where a GaugeFunc is directly registered with Prometheus, the provided 137 | // function must be concurrency-safe. 138 | func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc { 139 | return newValueFunc(NewDesc( 140 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 141 | opts.Help, 142 | nil, 143 | opts.ConstLabels, 144 | ), GaugeValue, function) 145 | } 146 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/untyped.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Untyped is a Metric that represents a single numerical value that can 17 | // arbitrarily go up and down. 18 | // 19 | // An Untyped metric works the same as a Gauge. The only difference is that to 20 | // no type information is implied. 21 | // 22 | // To create Untyped instances, use NewUntyped. 23 | // 24 | // Deprecated: The Untyped type is deprecated because it doesn't make sense in 25 | // direct instrumentation. If you need to mirror an external metric of unknown 26 | // type (usually while writing exporters), Use MustNewConstMetric to create an 27 | // untyped metric instance on the fly. 28 | type Untyped interface { 29 | Metric 30 | Collector 31 | 32 | // Set sets the Untyped metric to an arbitrary value. 33 | Set(float64) 34 | // Inc increments the Untyped metric by 1. 35 | Inc() 36 | // Dec decrements the Untyped metric by 1. 37 | Dec() 38 | // Add adds the given value to the Untyped metric. (The value can be 39 | // negative, resulting in a decrease.) 40 | Add(float64) 41 | // Sub subtracts the given value from the Untyped metric. (The value can 42 | // be negative, resulting in an increase.) 43 | Sub(float64) 44 | } 45 | 46 | // UntypedOpts is an alias for Opts. See there for doc comments. 47 | type UntypedOpts Opts 48 | 49 | // NewUntyped creates a new Untyped metric from the provided UntypedOpts. 50 | func NewUntyped(opts UntypedOpts) Untyped { 51 | return newValue(NewDesc( 52 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 53 | opts.Help, 54 | nil, 55 | opts.ConstLabels, 56 | ), UntypedValue, 0) 57 | } 58 | 59 | // UntypedVec is a Collector that bundles a set of Untyped metrics that all 60 | // share the same Desc, but have different values for their variable 61 | // labels. This is used if you want to count the same thing partitioned by 62 | // various dimensions. Create instances with NewUntypedVec. 63 | type UntypedVec struct { 64 | *MetricVec 65 | } 66 | 67 | // NewUntypedVec creates a new UntypedVec based on the provided UntypedOpts and 68 | // partitioned by the given label names. At least one label name must be 69 | // provided. 70 | func NewUntypedVec(opts UntypedOpts, labelNames []string) *UntypedVec { 71 | desc := NewDesc( 72 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 73 | opts.Help, 74 | labelNames, 75 | opts.ConstLabels, 76 | ) 77 | return &UntypedVec{ 78 | MetricVec: newMetricVec(desc, func(lvs ...string) Metric { 79 | return newValue(desc, UntypedValue, 0, lvs...) 80 | }), 81 | } 82 | } 83 | 84 | // GetMetricWithLabelValues replaces the method of the same name in 85 | // MetricVec. The difference is that this method returns an Untyped and not a 86 | // Metric so that no type conversion is required. 87 | func (m *UntypedVec) GetMetricWithLabelValues(lvs ...string) (Untyped, error) { 88 | metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) 89 | if metric != nil { 90 | return metric.(Untyped), err 91 | } 92 | return nil, err 93 | } 94 | 95 | // GetMetricWith replaces the method of the same name in MetricVec. The 96 | // difference is that this method returns an Untyped and not a Metric so that no 97 | // type conversion is required. 98 | func (m *UntypedVec) GetMetricWith(labels Labels) (Untyped, error) { 99 | metric, err := m.MetricVec.GetMetricWith(labels) 100 | if metric != nil { 101 | return metric.(Untyped), err 102 | } 103 | return nil, err 104 | } 105 | 106 | // WithLabelValues works as GetMetricWithLabelValues, but panics where 107 | // GetMetricWithLabelValues would have returned an error. By not returning an 108 | // error, WithLabelValues allows shortcuts like 109 | // myVec.WithLabelValues("404", "GET").Add(42) 110 | func (m *UntypedVec) WithLabelValues(lvs ...string) Untyped { 111 | return m.MetricVec.WithLabelValues(lvs...).(Untyped) 112 | } 113 | 114 | // With works as GetMetricWith, but panics where GetMetricWithLabels would have 115 | // returned an error. By not returning an error, With allows shortcuts like 116 | // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) 117 | func (m *UntypedVec) With(labels Labels) Untyped { 118 | return m.MetricVec.With(labels).(Untyped) 119 | } 120 | 121 | // UntypedFunc is an Untyped whose value is determined at collect time by 122 | // calling a provided function. 123 | // 124 | // To create UntypedFunc instances, use NewUntypedFunc. 125 | type UntypedFunc interface { 126 | Metric 127 | Collector 128 | } 129 | 130 | // NewUntypedFunc creates a new UntypedFunc based on the provided 131 | // UntypedOpts. The value reported is determined by calling the given function 132 | // from within the Write method. Take into account that metric collection may 133 | // happen concurrently. If that results in concurrent calls to Write, like in 134 | // the case where an UntypedFunc is directly registered with Prometheus, the 135 | // provided function must be concurrency-safe. 136 | func NewUntypedFunc(opts UntypedOpts, function func() float64) UntypedFunc { 137 | return newValueFunc(NewDesc( 138 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 139 | opts.Help, 140 | nil, 141 | opts.ConstLabels, 142 | ), UntypedValue, function) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // Proc provides information about a running process. 12 | type Proc struct { 13 | // The process ID. 14 | PID int 15 | 16 | fs FS 17 | } 18 | 19 | // Procs represents a list of Proc structs. 20 | type Procs []Proc 21 | 22 | func (p Procs) Len() int { return len(p) } 23 | func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 24 | func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } 25 | 26 | // Self returns a process for the current process read via /proc/self. 27 | func Self() (Proc, error) { 28 | fs, err := NewFS(DefaultMountPoint) 29 | if err != nil { 30 | return Proc{}, err 31 | } 32 | return fs.Self() 33 | } 34 | 35 | // NewProc returns a process for the given pid under /proc. 36 | func NewProc(pid int) (Proc, error) { 37 | fs, err := NewFS(DefaultMountPoint) 38 | if err != nil { 39 | return Proc{}, err 40 | } 41 | return fs.NewProc(pid) 42 | } 43 | 44 | // AllProcs returns a list of all currently available processes under /proc. 45 | func AllProcs() (Procs, error) { 46 | fs, err := NewFS(DefaultMountPoint) 47 | if err != nil { 48 | return Procs{}, err 49 | } 50 | return fs.AllProcs() 51 | } 52 | 53 | // Self returns a process for the current process. 54 | func (fs FS) Self() (Proc, error) { 55 | p, err := os.Readlink(fs.Path("self")) 56 | if err != nil { 57 | return Proc{}, err 58 | } 59 | pid, err := strconv.Atoi(strings.Replace(p, string(fs), "", -1)) 60 | if err != nil { 61 | return Proc{}, err 62 | } 63 | return fs.NewProc(pid) 64 | } 65 | 66 | // NewProc returns a process for the given pid. 67 | func (fs FS) NewProc(pid int) (Proc, error) { 68 | if _, err := os.Stat(fs.Path(strconv.Itoa(pid))); err != nil { 69 | return Proc{}, err 70 | } 71 | return Proc{PID: pid, fs: fs}, nil 72 | } 73 | 74 | // AllProcs returns a list of all currently available processes. 75 | func (fs FS) AllProcs() (Procs, error) { 76 | d, err := os.Open(fs.Path()) 77 | if err != nil { 78 | return Procs{}, err 79 | } 80 | defer d.Close() 81 | 82 | names, err := d.Readdirnames(-1) 83 | if err != nil { 84 | return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err) 85 | } 86 | 87 | p := Procs{} 88 | for _, n := range names { 89 | pid, err := strconv.ParseInt(n, 10, 64) 90 | if err != nil { 91 | continue 92 | } 93 | p = append(p, Proc{PID: int(pid), fs: fs}) 94 | } 95 | 96 | return p, nil 97 | } 98 | 99 | // CmdLine returns the command line of a process. 100 | func (p Proc) CmdLine() ([]string, error) { 101 | f, err := os.Open(p.path("cmdline")) 102 | if err != nil { 103 | return nil, err 104 | } 105 | defer f.Close() 106 | 107 | data, err := ioutil.ReadAll(f) 108 | if err != nil { 109 | return nil, err 110 | } 111 | 112 | if len(data) < 1 { 113 | return []string{}, nil 114 | } 115 | 116 | return strings.Split(string(data[:len(data)-1]), string(byte(0))), nil 117 | } 118 | 119 | // Comm returns the command name of a process. 120 | func (p Proc) Comm() (string, error) { 121 | f, err := os.Open(p.path("comm")) 122 | if err != nil { 123 | return "", err 124 | } 125 | defer f.Close() 126 | 127 | data, err := ioutil.ReadAll(f) 128 | if err != nil { 129 | return "", err 130 | } 131 | 132 | return strings.TrimSpace(string(data)), nil 133 | } 134 | 135 | // Executable returns the absolute path of the executable command of a process. 136 | func (p Proc) Executable() (string, error) { 137 | exe, err := os.Readlink(p.path("exe")) 138 | if os.IsNotExist(err) { 139 | return "", nil 140 | } 141 | 142 | return exe, err 143 | } 144 | 145 | // FileDescriptors returns the currently open file descriptors of a process. 146 | func (p Proc) FileDescriptors() ([]uintptr, error) { 147 | names, err := p.fileDescriptors() 148 | if err != nil { 149 | return nil, err 150 | } 151 | 152 | fds := make([]uintptr, len(names)) 153 | for i, n := range names { 154 | fd, err := strconv.ParseInt(n, 10, 32) 155 | if err != nil { 156 | return nil, fmt.Errorf("could not parse fd %s: %s", n, err) 157 | } 158 | fds[i] = uintptr(fd) 159 | } 160 | 161 | return fds, nil 162 | } 163 | 164 | // FileDescriptorTargets returns the targets of all file descriptors of a process. 165 | // If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string. 166 | func (p Proc) FileDescriptorTargets() ([]string, error) { 167 | names, err := p.fileDescriptors() 168 | if err != nil { 169 | return nil, err 170 | } 171 | 172 | targets := make([]string, len(names)) 173 | 174 | for i, name := range names { 175 | target, err := os.Readlink(p.path("fd", name)) 176 | if err == nil { 177 | targets[i] = target 178 | } 179 | } 180 | 181 | return targets, nil 182 | } 183 | 184 | // FileDescriptorsLen returns the number of currently open file descriptors of 185 | // a process. 186 | func (p Proc) FileDescriptorsLen() (int, error) { 187 | fds, err := p.fileDescriptors() 188 | if err != nil { 189 | return 0, err 190 | } 191 | 192 | return len(fds), nil 193 | } 194 | 195 | // MountStats retrieves statistics and configuration for mount points in a 196 | // process's namespace. 197 | func (p Proc) MountStats() ([]*Mount, error) { 198 | f, err := os.Open(p.path("mountstats")) 199 | if err != nil { 200 | return nil, err 201 | } 202 | defer f.Close() 203 | 204 | return parseMountStats(f) 205 | } 206 | 207 | func (p Proc) fileDescriptors() ([]string, error) { 208 | d, err := os.Open(p.path("fd")) 209 | if err != nil { 210 | return nil, err 211 | } 212 | defer d.Close() 213 | 214 | names, err := d.Readdirnames(-1) 215 | if err != nil { 216 | return nil, fmt.Errorf("could not read %s: %s", d.Name(), err) 217 | } 218 | 219 | return names, nil 220 | } 221 | 222 | func (p Proc) path(pa ...string) string { 223 | return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) 224 | } 225 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/counter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import ( 17 | "errors" 18 | ) 19 | 20 | // Counter is a Metric that represents a single numerical value that only ever 21 | // goes up. That implies that it cannot be used to count items whose number can 22 | // also go down, e.g. the number of currently running goroutines. Those 23 | // "counters" are represented by Gauges. 24 | // 25 | // A Counter is typically used to count requests served, tasks completed, errors 26 | // occurred, etc. 27 | // 28 | // To create Counter instances, use NewCounter. 29 | type Counter interface { 30 | Metric 31 | Collector 32 | 33 | // Inc increments the counter by 1. Use Add to increment it by arbitrary 34 | // non-negative values. 35 | Inc() 36 | // Add adds the given value to the counter. It panics if the value is < 37 | // 0. 38 | Add(float64) 39 | } 40 | 41 | // CounterOpts is an alias for Opts. See there for doc comments. 42 | type CounterOpts Opts 43 | 44 | // NewCounter creates a new Counter based on the provided CounterOpts. 45 | func NewCounter(opts CounterOpts) Counter { 46 | desc := NewDesc( 47 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 48 | opts.Help, 49 | nil, 50 | opts.ConstLabels, 51 | ) 52 | result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}} 53 | result.init(result) // Init self-collection. 54 | return result 55 | } 56 | 57 | type counter struct { 58 | value 59 | } 60 | 61 | func (c *counter) Add(v float64) { 62 | if v < 0 { 63 | panic(errors.New("counter cannot decrease in value")) 64 | } 65 | c.value.Add(v) 66 | } 67 | 68 | // CounterVec is a Collector that bundles a set of Counters that all share the 69 | // same Desc, but have different values for their variable labels. This is used 70 | // if you want to count the same thing partitioned by various dimensions 71 | // (e.g. number of HTTP requests, partitioned by response code and 72 | // method). Create instances with NewCounterVec. 73 | // 74 | // CounterVec embeds MetricVec. See there for a full list of methods with 75 | // detailed documentation. 76 | type CounterVec struct { 77 | *MetricVec 78 | } 79 | 80 | // NewCounterVec creates a new CounterVec based on the provided CounterOpts and 81 | // partitioned by the given label names. At least one label name must be 82 | // provided. 83 | func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { 84 | desc := NewDesc( 85 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 86 | opts.Help, 87 | labelNames, 88 | opts.ConstLabels, 89 | ) 90 | return &CounterVec{ 91 | MetricVec: newMetricVec(desc, func(lvs ...string) Metric { 92 | result := &counter{value: value{ 93 | desc: desc, 94 | valType: CounterValue, 95 | labelPairs: makeLabelPairs(desc, lvs), 96 | }} 97 | result.init(result) // Init self-collection. 98 | return result 99 | }), 100 | } 101 | } 102 | 103 | // GetMetricWithLabelValues replaces the method of the same name in 104 | // MetricVec. The difference is that this method returns a Counter and not a 105 | // Metric so that no type conversion is required. 106 | func (m *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) { 107 | metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) 108 | if metric != nil { 109 | return metric.(Counter), err 110 | } 111 | return nil, err 112 | } 113 | 114 | // GetMetricWith replaces the method of the same name in MetricVec. The 115 | // difference is that this method returns a Counter and not a Metric so that no 116 | // type conversion is required. 117 | func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) { 118 | metric, err := m.MetricVec.GetMetricWith(labels) 119 | if metric != nil { 120 | return metric.(Counter), err 121 | } 122 | return nil, err 123 | } 124 | 125 | // WithLabelValues works as GetMetricWithLabelValues, but panics where 126 | // GetMetricWithLabelValues would have returned an error. By not returning an 127 | // error, WithLabelValues allows shortcuts like 128 | // myVec.WithLabelValues("404", "GET").Add(42) 129 | func (m *CounterVec) WithLabelValues(lvs ...string) Counter { 130 | return m.MetricVec.WithLabelValues(lvs...).(Counter) 131 | } 132 | 133 | // With works as GetMetricWith, but panics where GetMetricWithLabels would have 134 | // returned an error. By not returning an error, With allows shortcuts like 135 | // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) 136 | func (m *CounterVec) With(labels Labels) Counter { 137 | return m.MetricVec.With(labels).(Counter) 138 | } 139 | 140 | // CounterFunc is a Counter whose value is determined at collect time by calling a 141 | // provided function. 142 | // 143 | // To create CounterFunc instances, use NewCounterFunc. 144 | type CounterFunc interface { 145 | Metric 146 | Collector 147 | } 148 | 149 | // NewCounterFunc creates a new CounterFunc based on the provided 150 | // CounterOpts. The value reported is determined by calling the given function 151 | // from within the Write method. Take into account that metric collection may 152 | // happen concurrently. If that results in concurrent calls to Write, like in 153 | // the case where a CounterFunc is directly registered with Prometheus, the 154 | // provided function must be concurrency-safe. The function should also honor 155 | // the contract for a Counter (values only go up, not down), but compliance will 156 | // not be checked. 157 | func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc { 158 | return newValueFunc(NewDesc( 159 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 160 | opts.Help, 161 | nil, 162 | opts.ConstLabels, 163 | ), CounterValue, function) 164 | } 165 | --------------------------------------------------------------------------------