├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── config.go ├── config.json ├── elog.go ├── frontend.go ├── frontendConnection.go ├── frontendQueries.go ├── go.mod ├── go.sum ├── listen.go ├── main.go ├── prometheus.go ├── queryParser.go ├── queryParser_test.go └── vendor ├── github.com ├── beorn7 │ └── perks │ │ ├── LICENSE │ │ └── quantile │ │ ├── exampledata.txt │ │ └── stream.go ├── golang │ └── protobuf │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── LICENSE │ │ └── proto │ │ ├── Makefile │ │ ├── clone.go │ │ ├── decode.go │ │ ├── encode.go │ │ ├── equal.go │ │ ├── extensions.go │ │ ├── lib.go │ │ ├── message_set.go │ │ ├── pointer_reflect.go │ │ ├── pointer_unsafe.go │ │ ├── properties.go │ │ ├── text.go │ │ └── text_parser.go ├── johto │ └── notifyutils │ │ ├── LICENSE │ │ └── notifydispatcher │ │ └── notifydispatcher.go ├── lib │ └── pq │ │ ├── .gitignore │ │ ├── .travis.sh │ │ ├── .travis.yml │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── array.go │ │ ├── buf.go │ │ ├── conn.go │ │ ├── copy.go │ │ ├── doc.go │ │ ├── encode.go │ │ ├── error.go │ │ ├── notify.go │ │ ├── oid │ │ ├── doc.go │ │ └── types.go │ │ ├── url.go │ │ ├── user_posix.go │ │ └── user_windows.go ├── matttproud │ └── golang_protobuf_extensions │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── pbutil │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── decode.go │ │ ├── doc.go │ │ └── encode.go ├── prometheus │ ├── client_golang │ │ ├── AUTHORS.md │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── prometheus │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── collector.go │ │ │ ├── counter.go │ │ │ ├── desc.go │ │ │ ├── doc.go │ │ │ ├── expvar_collector.go │ │ │ ├── fnv.go │ │ │ ├── gauge.go │ │ │ ├── go_collector.go │ │ │ ├── histogram.go │ │ │ ├── http.go │ │ │ ├── metric.go │ │ │ ├── process_collector.go │ │ │ ├── promhttp │ │ │ └── http.go │ │ │ ├── registry.go │ │ │ ├── summary.go │ │ │ ├── timer.go │ │ │ ├── untyped.go │ │ │ ├── value.go │ │ │ └── vec.go │ ├── client_model │ │ ├── AUTHORS.md │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── go │ │ │ └── metrics.pb.go │ ├── common │ │ ├── AUTHORS.md │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── expfmt │ │ │ ├── decode.go │ │ │ ├── encode.go │ │ │ ├── expfmt.go │ │ │ ├── fuzz.go │ │ │ ├── text_create.go │ │ │ └── text_parse.go │ │ ├── internal │ │ │ └── bitbucket.org │ │ │ │ └── ww │ │ │ │ └── goautoneg │ │ │ │ ├── README.txt │ │ │ │ └── autoneg.go │ │ └── model │ │ │ ├── alert.go │ │ │ ├── fingerprinting.go │ │ │ ├── fnv.go │ │ │ ├── labels.go │ │ │ ├── labelset.go │ │ │ ├── metric.go │ │ │ ├── model.go │ │ │ ├── signature.go │ │ │ ├── silence.go │ │ │ ├── time.go │ │ │ └── value.go │ └── procfs │ │ ├── .travis.yml │ │ ├── AUTHORS.md │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── NOTICE │ │ ├── README.md │ │ ├── doc.go │ │ ├── fs.go │ │ ├── ipvs.go │ │ ├── mdstat.go │ │ ├── mountstats.go │ │ ├── proc.go │ │ ├── proc_io.go │ │ ├── proc_limits.go │ │ ├── proc_stat.go │ │ └── stat.go └── uhoh-itsmaciek │ └── femebe │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── buf │ ├── buffer.go │ ├── pack_buffer.go │ └── reader.go │ ├── core │ ├── framing.go │ └── stream.go │ ├── error │ └── error.go │ ├── proto │ ├── message.go │ └── oids.go │ └── util │ └── util.go └── modules.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | allas 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.5 5 | - 1.6 6 | - 1.7 7 | - 1.8 8 | - 1.9 9 | - tip 10 | 11 | env: 12 | global: 13 | - GO15VENDOREXPERIMENT=1 14 | 15 | script: 16 | - go test -v ./... 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2017 Marko Tiikkaja 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | allas 2 | ===== 3 | 4 | Introduction 5 | ------------ 6 | 7 | _allas_ is a connection pooler for [PostgreSQL](http://www.postgresql.org) 8 | which only supports LISTEN / NOTIFY. The idea is to allow the application to 9 | use e.g. pgbouncer in transaction pooling mode while only receiving 10 | notifications through _allas_. _allas_ only uses a single PostgreSQL 11 | connection and takes care of LISTENing and UNLISTENing appropriately on that 12 | connection to make sure all of its clients get the set of notifications they're 13 | interested in. 14 | 15 | How to build 16 | ------------ 17 | 18 | Clone the repository, and run "go build" in the cloned directory. This should 19 | produce a binary called "allas". 20 | 21 | Configuration 22 | ------------- 23 | 24 | The configuration file uses a JSON format and is organized into sections. The 25 | top level structure is a JSON object, with the following keys ("sections"): 26 | 27 | ###### listen 28 | 29 | `listen` specifies how `allas` listens to new connections. It has three possible options: 30 | 31 | 1. **port** (integer) specifies the port to listen on. 32 | 2. **host** (string) specifies the address to listen on. The asterisk 33 | (`"*"`) can be used to listen on all TCP interfaces, or an absolute path can 34 | be used to listen on a UNIX domain socket. 35 | 3. **keepalive** (boolean) specifies whether TCP keepalives should be enabled or not. 36 | 37 | ###### connect 38 | 39 | `connect` is a [pq](http://godoc.org/github.com/lib/pq) connection string. It 40 | supports many of libpq's options. 41 | 42 | ###### startup\_parameters 43 | 44 | `startup_parameters` is a JSON object specifying the list of "startup 45 | parameters" (such as the server's version number) to send to each client when 46 | they connect. 47 | 48 | ###### prometheus 49 | 50 | `prometheus` is a JSON object with the following keys: 51 | 52 | 1. **listen** (object) specifies how `allas` listens to connections from the 53 | Prometheus scraping process. The keys are the same as used by the main 54 | `listen` section, documented above. The port 9226 has been allocated in the 55 | [Prometheus wiki](https://github.com/prometheus/prometheus/wiki/Default-port-allocations) 56 | for allas's use. 57 | 58 | ###### databases 59 | 60 | `databases` is an array of JSON objects with the following keys: 61 | 62 | 1. **name** (string) specifies the name of the database. 63 | 2. **auth** (object) is described in the section `Database 64 | authentication`, below. 65 | 66 | #### Database authentication 67 | 68 | The `auth` key of a database configuration section is a JSON object with a 69 | combination of the following keys: 70 | 71 | 1. **method** (string) is the authentication method used. There are only two 72 | values values: "trust" and "md5". Both match their respective counterpart in 73 | PostgreSQL HBA configuration. 74 | 2. **user** (string) is the user name the user has to pass to match the 75 | authentication method. 76 | 3. **password** (string) is a clear-text copy of the password the client 77 | should use for authentication. 78 | 79 | Configuration example 80 | --------------------- 81 | 82 | Here's an example configuration file: 83 | 84 | ``` 85 | { 86 | "listen": { 87 | "port": 6433, 88 | "host": "localhost" 89 | }, 90 | "connect": "host=localhost port=5432 sslmode=disable", 91 | "startup_parameters": { 92 | "server_version": "9.1.24", 93 | "client_encoding": "UTF8" 94 | }, 95 | "prometheus": { 96 | "listen": { 97 | "port": 9226, 98 | "host": "*" 99 | } 100 | }, 101 | "databases": [ 102 | { 103 | "name": "allas", 104 | "auth": { 105 | "method": "md5", 106 | "user": "allas", 107 | "password": "s3cret" 108 | } 109 | } 110 | ] 111 | } 112 | ``` 113 | 114 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "listen": { 3 | "port": 6433, 4 | "host": "localhost" 5 | }, 6 | "connect": "host=/var/run/postgresql port=5434 user=allas dbname=db sslmode=disable", 7 | "startup_parameters": { 8 | "server_version": "9.1.24" 9 | }, 10 | "prometheus": { 11 | "listen": { 12 | "port": 9226, 13 | "host": "*" 14 | } 15 | }, 16 | "databases": [ 17 | { 18 | "name": "allas", 19 | "auth": { 20 | "method": "md5", 21 | "user": "allas", 22 | "password": "s3cret" 23 | } 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /elog.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "os" 8 | "time" 9 | ) 10 | 11 | var elog *Logger 12 | 13 | type LogSeverity int 14 | 15 | const ( 16 | DEBUG LogSeverity = iota 17 | LOG 18 | WARNING 19 | ERROR 20 | FATAL 21 | PANIC 22 | ) 23 | 24 | func (s LogSeverity) String() string { 25 | switch s { 26 | case DEBUG: 27 | return "DEBUG" 28 | case LOG: 29 | return "LOG" 30 | case WARNING: 31 | return "WARNING" 32 | case ERROR: 33 | return "ERROR" 34 | case FATAL: 35 | return "FATAL" 36 | case PANIC: 37 | return "PANIC" 38 | default: 39 | panic("unknown severity") 40 | } 41 | } 42 | 43 | type Logger struct { 44 | elog *log.Logger 45 | } 46 | 47 | func (l *Logger) Print(severity LogSeverity, output string) { 48 | l.elog.Print(time.Now().Format("2006-01-02 15:04:05.000 -0700") + " " + severity.String() + ": " + output) 49 | 50 | switch severity { 51 | case FATAL: 52 | os.Exit(1) 53 | case PANIC: 54 | panic("Logger.Panic") 55 | 56 | default: 57 | } 58 | } 59 | func (l *Logger) Printf(severity LogSeverity, format string, v ...interface{}) { 60 | l.Print(severity, fmt.Sprintf(format, v...)) 61 | } 62 | func (l *Logger) Debug(output string) { 63 | l.Print(DEBUG, output) 64 | } 65 | func (l *Logger) Debugf(format string, v ...interface{}) { 66 | l.Printf(DEBUG, format, v...) 67 | } 68 | func (l *Logger) Log(output string) { 69 | l.Print(LOG, output) 70 | } 71 | func (l *Logger) Logf(format string, v ...interface{}) { 72 | l.Printf(LOG, format, v...) 73 | } 74 | func (l *Logger) Warning(output string) { 75 | l.Print(WARNING, output) 76 | } 77 | func (l *Logger) Warningf(format string, v ...interface{}) { 78 | l.Printf(WARNING, format, v...) 79 | } 80 | func (l *Logger) Error(output string) { 81 | l.Print(ERROR, output) 82 | } 83 | func (l *Logger) Errorf(format string, v ...interface{}) { 84 | l.Printf(ERROR, format, v...) 85 | } 86 | func (l *Logger) Fatal(output string) { 87 | l.Print(FATAL, output) 88 | } 89 | func (l *Logger) Fatalf(format string, v ...interface{}) { 90 | l.Printf(FATAL, format, v...) 91 | } 92 | func (l *Logger) Panic(output string) { 93 | l.Print(PANIC, output) 94 | } 95 | func (l *Logger) Panicf(format string, v ...interface{}) { 96 | l.Printf(PANIC, format, v...) 97 | } 98 | 99 | func InitErrorLog(w io.Writer) { 100 | if elog != nil { 101 | panic("double init") 102 | } 103 | elog = &Logger{ 104 | elog: log.New(w, "", 0), 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /frontend.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | fbcore "github.com/uhoh-itsmaciek/femebe/core" 5 | 6 | "bytes" 7 | "crypto/md5" 8 | "encoding/hex" 9 | "fmt" 10 | ) 11 | 12 | type Frontend interface { 13 | // Write msg to the frontend's message stream. The message might not be 14 | // sent before FlushStream is called. 15 | WriteMessage(msg *fbcore.Message) error 16 | FlushStream() error 17 | 18 | // Starts delivering notifications on the specified channel, or returns an 19 | // error if the listen request could not be satisfied. If the frontend is 20 | // already listening on the channel, error will be nil. 21 | Listen(channel string) error 22 | 23 | Unlisten(channel string) error 24 | 25 | UnlistenAll() error 26 | } 27 | 28 | type AuthConfig struct { 29 | method string 30 | user string 31 | password string 32 | } 33 | 34 | type virtualDatabase struct { 35 | name string 36 | auth AuthConfig 37 | } 38 | 39 | type VirtualDatabaseConfiguration []virtualDatabase 40 | 41 | func (c VirtualDatabaseConfiguration) find(dbname string) *virtualDatabase { 42 | for _, db := range c { 43 | if db.name == dbname { 44 | return &db 45 | } 46 | } 47 | return nil 48 | } 49 | 50 | // Finds a database and returns the authentication method 51 | func (c VirtualDatabaseConfiguration) FindDatabase(name string) (authMethod string, ok bool) { 52 | db := c.find(name) 53 | if db == nil { 54 | return "", false 55 | } 56 | return db.auth.method, true 57 | } 58 | 59 | func (c VirtualDatabaseConfiguration) MD5Auth(dbname string, username string, salt []byte, password []byte) (success bool, err error) { 60 | if !bytes.HasPrefix(password, []byte{'m', 'd', '5'}) { 61 | return false, nil 62 | } 63 | password = password[3:] 64 | 65 | db := c.find(dbname) 66 | if db == nil { 67 | return false, fmt.Errorf("internal error: database %q disappeared", dbname) 68 | } 69 | 70 | if db.auth.user != username { 71 | return false, nil 72 | } 73 | 74 | md5 := func(input []byte) []byte { 75 | s := md5.Sum(input) 76 | return []byte(hex.EncodeToString(s[:])) 77 | } 78 | expected := md5(append(md5([]byte(db.auth.password+username)), salt...)) 79 | expected = append(expected, 0) 80 | return bytes.Compare(expected, password) == 0, nil 81 | } 82 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module allas 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/johto/notifyutils v0.0.0-20150615093830-a8b71d70b60f 7 | github.com/lib/pq v0.0.0-20161129221428-4a82388ebc51 8 | github.com/prometheus/client_golang v0.8.1-0.20161124155732-575f371f7862 9 | github.com/uhoh-itsmaciek/femebe v0.0.0-20150705092910-78f00f2ef7b4 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a // indirect 14 | github.com/golang/protobuf v0.0.0-20161117033126-8ee79997227b // indirect 15 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 16 | github.com/prometheus/client_model v0.0.0-20150212101744-fa8ad6fec335 // indirect 17 | github.com/prometheus/common v0.0.0-20161201123508-195bde7883f7 // indirect 18 | github.com/prometheus/procfs v0.0.0-20161206222141-fcdb11ccb438 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a h1:BtpsbiV638WQZwhA98cEZw2BsbnQJrbd0BI7tsy0W1c= 2 | github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 3 | github.com/golang/protobuf v0.0.0-20161117033126-8ee79997227b h1:fE/yi9pibxGEc0gSJuEShcsBXE2d5FW3OudsjE9tKzQ= 4 | github.com/golang/protobuf v0.0.0-20161117033126-8ee79997227b/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 5 | github.com/johto/notifyutils v0.0.0-20150615093830-a8b71d70b60f h1:7LZQX2gksjuD9dGVs+jw6ScKLqERDmpFqtQJygHsRF0= 6 | github.com/johto/notifyutils v0.0.0-20150615093830-a8b71d70b60f/go.mod h1:KaujEZhoyyjG7nLRC4jKTGiFk/7146VkDs8HY0o5y+I= 7 | github.com/lib/pq v0.0.0-20161129221428-4a82388ebc51 h1:YqVhKD8mDLVJcXsZaI9AI6UBQeGppTcYCg4bEvCzSv4= 8 | github.com/lib/pq v0.0.0-20161129221428-4a82388ebc51/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 9 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 10 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 11 | github.com/prometheus/client_golang v0.8.1-0.20161124155732-575f371f7862 h1:VOgRS97yMNL1EmGAjwJVmwMpZ/ErKQUwLDKPmM3hVnE= 12 | github.com/prometheus/client_golang v0.8.1-0.20161124155732-575f371f7862/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 13 | github.com/prometheus/client_model v0.0.0-20150212101744-fa8ad6fec335 h1:0E/5GnGmzoDCtmzTycjGDWW33H0UBmAhR0h+FC8hWLs= 14 | github.com/prometheus/client_model v0.0.0-20150212101744-fa8ad6fec335/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 15 | github.com/prometheus/common v0.0.0-20161201123508-195bde7883f7 h1:skjefbrmNeFoEDgFSE3ZXL9t3vWVLm63zPDvVVPreeM= 16 | github.com/prometheus/common v0.0.0-20161201123508-195bde7883f7/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 17 | github.com/prometheus/procfs v0.0.0-20161206222141-fcdb11ccb438 h1:k/s75rGR08iSxh0TE4TCnlrkDzvo8i0MhfyF+g5fy8M= 18 | github.com/prometheus/procfs v0.0.0-20161206222141-fcdb11ccb438/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 19 | github.com/uhoh-itsmaciek/femebe v0.0.0-20150705092910-78f00f2ef7b4 h1:ZXHfDGAbPxDUHnrdCjG0pcdS0MZ4ia7yIgJ/3eRGHsQ= 20 | github.com/uhoh-itsmaciek/femebe v0.0.0-20150705092910-78f00f2ef7b4/go.mod h1:QrMsr+lgO2K1sLsRYsl/zoQ8595mKqTEm+5V0LmIvRQ= 21 | -------------------------------------------------------------------------------- /listen.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "os" 7 | "strconv" 8 | ) 9 | 10 | type ListenConfig struct { 11 | Port int 12 | Host string 13 | 14 | KeepAlive bool 15 | } 16 | 17 | func (lc ListenConfig) Listen() (net.Listener, error) { 18 | var listener net.Listener 19 | var err error 20 | if lc.Host[0] == '/' { 21 | var fi os.FileInfo 22 | 23 | // See if the socket file exists already. Since we can't guarantee the 24 | // socket to be closed in every case (such as in the event of an 25 | // unexpected panic or a crash), we need to be prepared to deal with 26 | // the case where the socket we want to bind to already exists. 27 | // However, try not to be too careless, and only remove the file if it 28 | // pre-exists as a UNIX socket; we wouldn't want to remove regular 29 | // files or directories, for example. 30 | fi, err = os.Stat(lc.Host) 31 | if err == nil { 32 | if fi.Mode() & os.ModeSocket > 0 { 33 | _ = os.Remove(lc.Host) 34 | } else { 35 | return nil, fmt.Errorf("file %q already exists and is not a UNIX socket", lc.Host) 36 | } 37 | } 38 | 39 | listener, err = net.Listen("unix", lc.Host) 40 | if err != nil { 41 | return nil, err 42 | } 43 | } else { 44 | var socket string 45 | if lc.Host == "*" { 46 | lc.Host = "" 47 | } 48 | socket = net.JoinHostPort(lc.Host, strconv.Itoa(lc.Port)) 49 | listener, err = net.Listen("tcp", socket) 50 | if err != nil { 51 | return nil, err 52 | } 53 | } 54 | return listener, nil 55 | } 56 | 57 | func (lc ListenConfig) MaybeEnableKeepAlive(c net.Conn) { 58 | // Try and keepalives if they were asked for 59 | if lc.KeepAlive { 60 | tcpConn, ok := c.(*net.TCPConn) 61 | if ok { 62 | _ = tcpConn.SetKeepAlive(true) 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/johto/notifyutils/notifydispatcher" 5 | "github.com/lib/pq" 6 | 7 | "fmt" 8 | "github.com/prometheus/client_golang/prometheus" 9 | "os" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // Implements a wrapper for pq.Listener for use between the PostgreSQL server 15 | // and NotifyDispatcher. Here we collect some statistics and pass the 16 | // notifications on to the dispatcher. 17 | type pqListenerWrapper struct { 18 | l *pq.Listener 19 | ch chan *pq.Notification 20 | 21 | inputChannelSaturationRatio *prometheus.Desc 22 | dispatcherChannelSaturationRatio *prometheus.Desc 23 | } 24 | 25 | func newPqListenerWrapper(l *pq.Listener) (*pqListenerWrapper, error) { 26 | w := &pqListenerWrapper{ 27 | l: l, 28 | ch: make(chan *pq.Notification, 4), 29 | } 30 | 31 | w.inputChannelSaturationRatio = prometheus.NewDesc( 32 | "allas_input_channel_saturation_ratio", 33 | "main notification input Go channel saturation", 34 | nil, 35 | nil, 36 | ) 37 | w.dispatcherChannelSaturationRatio = prometheus.NewDesc( 38 | "allas_dispatcher_channel_saturation_ratio", 39 | "dispatcher notification Go channel saturation", 40 | nil, 41 | nil, 42 | ) 43 | 44 | err := Config.Prometheus.RegisterMetricsCollector(w) 45 | if err != nil { 46 | return nil, err 47 | } 48 | go w.workerGoroutine() 49 | return w, nil 50 | } 51 | 52 | func (w *pqListenerWrapper) Describe(ch chan<- *prometheus.Desc) { 53 | ch <- w.inputChannelSaturationRatio 54 | ch <- w.dispatcherChannelSaturationRatio 55 | } 56 | 57 | func (w *pqListenerWrapper) Collect(ch chan<- prometheus.Metric) { 58 | inputChSaturation := float64(len(w.l.Notify)) / float64(cap(w.l.Notify)) 59 | ch <- prometheus.MustNewConstMetric(w.inputChannelSaturationRatio, prometheus.GaugeValue, inputChSaturation) 60 | dispatcherChSaturation := float64(len(w.ch)) / float64(cap(w.ch)) 61 | ch <- prometheus.MustNewConstMetric(w.dispatcherChannelSaturationRatio, prometheus.GaugeValue, dispatcherChSaturation) 62 | 63 | } 64 | 65 | func (w *pqListenerWrapper) workerGoroutine() { 66 | input := w.l.NotificationChannel() 67 | for { 68 | m := <-input 69 | MetricNotificationsReceived.Inc() 70 | w.ch <- m 71 | } 72 | } 73 | 74 | func (w *pqListenerWrapper) Listen(channel string) error { 75 | return w.l.Listen(channel) 76 | } 77 | 78 | func (w *pqListenerWrapper) Unlisten(channel string) error { 79 | return w.l.Unlisten(channel) 80 | } 81 | 82 | func (w *pqListenerWrapper) NotificationChannel() <-chan *pq.Notification { 83 | return w.ch 84 | } 85 | 86 | // runs in its own goroutine 87 | func listenerPinger(listener *pq.Listener) { 88 | for { 89 | time.Sleep(60 * time.Second) 90 | _ = listener.Ping() 91 | } 92 | } 93 | 94 | func printUsage() { 95 | fmt.Fprintf(os.Stderr, `Usage: 96 | %s [--help] configfile 97 | 98 | Options: 99 | --help display this help and exit 100 | `, os.Args[0]) 101 | } 102 | 103 | func main() { 104 | InitErrorLog(os.Stderr) 105 | 106 | if len(os.Args) != 2 { 107 | printUsage() 108 | os.Exit(1) 109 | } else if os.Args[1] == "--help" { 110 | printUsage() 111 | os.Exit(1) 112 | } 113 | 114 | err := readConfigFile(os.Args[1]) 115 | if err != nil { 116 | elog.Fatalf("error while reading configuration file: %s", err) 117 | } 118 | if len(Config.Databases) == 0 { 119 | elog.Fatalf("at least one database must be configured") 120 | } 121 | 122 | l, err := Config.Listen.Listen() 123 | if err != nil { 124 | elog.Fatalf("could not open listen socket: %s", err) 125 | } 126 | 127 | err = Config.Prometheus.Setup() 128 | if err != nil { 129 | elog.Fatalf("Prometheus exporter setup failed: %s", err) 130 | } 131 | 132 | var m sync.Mutex 133 | var connStatusNotifier chan struct{} 134 | 135 | listenerStateChange := func(ev pq.ListenerEventType, err error) { 136 | switch ev { 137 | case pq.ListenerEventConnectionAttemptFailed: 138 | elog.Warningf("Listener: could not connect to the database: %s", err.Error()) 139 | 140 | case pq.ListenerEventDisconnected: 141 | elog.Warningf("Listener: lost connection to the database: %s", err.Error()) 142 | m.Lock() 143 | close(connStatusNotifier) 144 | connStatusNotifier = nil 145 | m.Unlock() 146 | 147 | case pq.ListenerEventReconnected, 148 | pq.ListenerEventConnected: 149 | elog.Logf("Listener: connected to the database") 150 | m.Lock() 151 | connStatusNotifier = make(chan struct{}) 152 | m.Unlock() 153 | } 154 | } 155 | 156 | // make sure pq.Listener doesn't pick up any env variables 157 | os.Clearenv() 158 | 159 | clientConnectionString := fmt.Sprintf("fallback_application_name=allas %s", Config.ClientConnInfo) 160 | listener := pq.NewListener( 161 | clientConnectionString, 162 | 250*time.Millisecond, 3*time.Second, 163 | listenerStateChange, 164 | ) 165 | listenerWrapper, err := newPqListenerWrapper(listener) 166 | if err != nil { 167 | elog.Fatalf("%s", err) 168 | } 169 | nd := notifydispatcher.NewNotifyDispatcher(listenerWrapper) 170 | nd.SetBroadcastOnConnectionLoss(false) 171 | nd.SetSlowReaderEliminationStrategy(notifydispatcher.NeglectSlowReaders) 172 | 173 | // We don't strictly speaking need to be pinging the server; this is a 174 | // workaround for PostgreSQL BUG #14830. 175 | go listenerPinger(listener) 176 | 177 | for { 178 | c, err := l.Accept() 179 | if err != nil { 180 | panic(err) 181 | } 182 | 183 | Config.Listen.MaybeEnableKeepAlive(c) 184 | 185 | var myConnStatusNotifier chan struct{} 186 | 187 | m.Lock() 188 | if connStatusNotifier == nil { 189 | m.Unlock() 190 | go RejectFrontendConnection(c) 191 | continue 192 | } else { 193 | myConnStatusNotifier = connStatusNotifier 194 | } 195 | m.Unlock() 196 | 197 | newConn := NewFrontendConnection(c, nd, myConnStatusNotifier) 198 | go newConn.mainLoop(Config.StartupParameters, Config.Databases) 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /prometheus.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/prometheus/client_golang/prometheus" 6 | "github.com/prometheus/client_golang/prometheus/promhttp" 7 | "net/http" 8 | "runtime" 9 | "time" 10 | ) 11 | 12 | type gcStatsCollector struct { 13 | pauseTotalDesc *prometheus.Desc 14 | numGCDesc *prometheus.Desc 15 | } 16 | 17 | func newGCStatsCollector() *gcStatsCollector { 18 | return &gcStatsCollector{ 19 | pauseTotalDesc: prometheus.NewDesc( 20 | "allas_gc_pause_seconds_total", 21 | "how much total time has been spent in garbage collector pauses", 22 | nil, 23 | nil, 24 | ), 25 | numGCDesc: prometheus.NewDesc( 26 | "allas_gc_pauses_total", 27 | "how many times the garbage collector has run", 28 | nil, 29 | nil, 30 | ), 31 | } 32 | } 33 | 34 | func (c *gcStatsCollector) Describe(ch chan<- *prometheus.Desc) { 35 | ch <- c.pauseTotalDesc 36 | ch <- c.numGCDesc 37 | } 38 | 39 | func (c *gcStatsCollector) Collect(ch chan<- prometheus.Metric) { 40 | var m runtime.MemStats 41 | runtime.ReadMemStats(&m) 42 | 43 | ch <- prometheus.MustNewConstMetric(c.pauseTotalDesc, prometheus.CounterValue, float64(m.PauseTotalNs) / 1000000000.0) 44 | ch <- prometheus.MustNewConstMetric(c.numGCDesc, prometheus.CounterValue, float64(m.NumGC)) 45 | } 46 | 47 | type PrometheusConfig struct { 48 | Enabled bool 49 | Listen ListenConfig 50 | 51 | registry *prometheus.Registry 52 | startupTimeDesc *prometheus.Desc 53 | startupTimeMetric prometheus.Metric 54 | gcStatsCollector *gcStatsCollector 55 | } 56 | 57 | func (c *PrometheusConfig) RegisterMetricsCollector(coll prometheus.Collector) error { 58 | if c.registry == nil { 59 | panic("registry not initialized") 60 | } 61 | return c.registry.Register(coll) 62 | } 63 | 64 | type elogWrapper struct { 65 | } 66 | 67 | func (w elogWrapper) Println(v ...interface{}) { 68 | elog.Warningf("Prometheus handler error: %s", fmt.Sprintln(v...)) 69 | } 70 | 71 | var MetricClientConnections prometheus.Gauge 72 | var MetricNotificationsReceived prometheus.Counter 73 | var MetricNotificationsDispatched prometheus.Counter 74 | var MetricListensExecuted prometheus.Counter 75 | var MetricUnlistensExecuted prometheus.Counter 76 | var MetricSlowClientsTerminated prometheus.Counter 77 | 78 | func (cfg *PrometheusConfig) InitializeMetrics(r *prometheus.Registry) error { 79 | var err error 80 | 81 | cfg.startupTimeDesc = prometheus.NewDesc( 82 | "allas_start_time", 83 | "when this instance of allas was started", 84 | nil, 85 | nil, 86 | ) 87 | cfg.startupTimeMetric = prometheus.MustNewConstMetric(cfg.startupTimeDesc, prometheus.GaugeValue, float64(time.Now().Unix())) 88 | err = r.Register(cfg) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | MetricClientConnections = prometheus.NewGauge(prometheus.GaugeOpts{ 94 | Namespace: "allas", 95 | Name: "client_connections", 96 | Help: "the number of clients currently connected to allas", 97 | }) 98 | err = r.Register(MetricClientConnections) 99 | if err != nil { 100 | return err 101 | } 102 | 103 | MetricNotificationsReceived = prometheus.NewCounter(prometheus.CounterOpts{ 104 | Namespace: "allas", 105 | Name: "notifications_received_total", 106 | Help: "how many notifications have been received from the PostgreSQL server so far", 107 | }) 108 | err = r.Register(MetricNotificationsReceived) 109 | if err != nil { 110 | return err 111 | } 112 | 113 | MetricNotificationsDispatched = prometheus.NewCounter(prometheus.CounterOpts{ 114 | Namespace: "allas", 115 | Name: "notifications_dispatched_total", 116 | Help: "how many notifications have been dispatched so far", 117 | }) 118 | err = r.Register(MetricNotificationsDispatched) 119 | if err != nil { 120 | return err 121 | } 122 | 123 | MetricListensExecuted = prometheus.NewCounter(prometheus.CounterOpts{ 124 | Namespace: "allas", 125 | Name: "listens_executed_total", 126 | Help: "how many LISTEN queries have been executed so far", 127 | }) 128 | err = r.Register(MetricListensExecuted) 129 | if err != nil { 130 | return err 131 | } 132 | 133 | MetricUnlistensExecuted = prometheus.NewCounter(prometheus.CounterOpts{ 134 | Namespace: "allas", 135 | Name: "unlistens_executed_total", 136 | Help: "how many UNLISTEN queries have been executed so far", 137 | }) 138 | err = r.Register(MetricUnlistensExecuted) 139 | if err != nil { 140 | return err 141 | } 142 | 143 | MetricSlowClientsTerminated = prometheus.NewCounter(prometheus.CounterOpts{ 144 | Namespace: "allas", 145 | Name: "slow_clients_terminated_total", 146 | Help: "how many clients have been terminated because they could not keep up", 147 | }) 148 | err = r.Register(MetricSlowClientsTerminated) 149 | if err != nil { 150 | return err 151 | } 152 | 153 | cfg.gcStatsCollector = newGCStatsCollector() 154 | err = r.Register(cfg.gcStatsCollector) 155 | if err != nil { 156 | return err 157 | } 158 | 159 | return nil 160 | } 161 | 162 | func (cfg *PrometheusConfig) Describe(ch chan<- *prometheus.Desc) { 163 | ch <- cfg.startupTimeDesc 164 | } 165 | 166 | func (cfg *PrometheusConfig) Collect(ch chan<- prometheus.Metric) { 167 | ch <- cfg.startupTimeMetric 168 | } 169 | 170 | func (cfg *PrometheusConfig) Setup() error { 171 | elogWrapper := elogWrapper{} 172 | registry := prometheus.NewPedanticRegistry() 173 | err := cfg.InitializeMetrics(registry) 174 | if err != nil { 175 | return err 176 | } 177 | cfg.registry = registry 178 | 179 | metricsHandler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{ 180 | ErrorLog: elogWrapper, 181 | }) 182 | muxer := http.NewServeMux() 183 | muxer.Handle("/metrics", metricsHandler) 184 | s := &http.Server{ 185 | Handler: muxer, 186 | } 187 | l, err := cfg.Listen.Listen() 188 | if err != nil { 189 | return err 190 | } 191 | go func() { 192 | elog.Fatalf("Prometheus HTTP endpoint failed: %s", s.Serve(l)) 193 | }() 194 | return nil 195 | } 196 | -------------------------------------------------------------------------------- /queryParser_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestQueryParser(t *testing.T) { 8 | var tests = []struct { 9 | input string 10 | outcome string 11 | err string 12 | }{ 13 | {"", "EmptyQuery", ""}, 14 | {"--", "EmptyQuery", ""}, 15 | {"/**/", "EmptyQuery", ""}, 16 | {"/*/**/*/", "EmptyQuery", ""}, 17 | {"/*/**/", "error", errQueryParserUnexpectedEOF.Error()}, 18 | {"\xFF\x00", "error", errQueryParserInputNotUtf8.Error()}, 19 | {"-", "error", errQueryParserUnexpectedEOF.Error()}, 20 | {"select", "error", errQueryParserUnexpectedEOF.Error()}, 21 | {"select 1", "TrivialSelect", ""}, 22 | {"select 1;", "TrivialSelect", ""}, 23 | {"select 1 ", "TrivialSelect", ""}, 24 | {"select 1 --", "TrivialSelect", ""}, 25 | {"select 1 /*/**/*/", "TrivialSelect", ""}, 26 | {"select 1; ", "TrivialSelect", ""}, 27 | {"select 1; f", "error", "garbage after semicolon"}, 28 | {"select 2", "error", "parse error"}, 29 | {`listen "foo"`, "ListenRequest", ""}, 30 | {`listen *`, "error", `parse error: unexpected token "asterisk"`}, 31 | {`unlisten *`, "UnlistenRequest", ""}, 32 | {"notify", "error", `parse error at or near "notify"`}, 33 | } 34 | 35 | for n, ts := range tests { 36 | q, err := ParseQuery(ts.input) 37 | switch ts.outcome { 38 | case "error": 39 | if err == nil { 40 | t.Errorf("test %d failed: err is nil; expected %s", n, ts.err) 41 | } else if err.Error() != ts.err { 42 | t.Errorf("test %d failed: err %q != %q", n, err.Error(), ts.err) 43 | } 44 | case "EmptyQuery": 45 | if err != nil { 46 | t.Errorf("test %d failed: unexpected error %q", n, err) 47 | } else { 48 | _, ok := q.(emptyQuery) 49 | if !ok { 50 | t.Errorf("test %d failed: unexpected msg %+#v; was expecting EmptyQuery", n, q) 51 | } 52 | } 53 | case "ListenRequest": 54 | if err != nil { 55 | t.Errorf("test %d failed: unexpected error %q", n, err) 56 | } else { 57 | _, ok := q.(listenRequest) 58 | if !ok { 59 | t.Errorf("test %d failed: unexpected msg %+#v; was expecting ListenRequest", n, q) 60 | } 61 | } 62 | case "UnlistenRequest": 63 | if err != nil { 64 | t.Errorf("test %d failed: unexpected error %q", n, err) 65 | } else { 66 | _, ok := q.(unlistenRequest) 67 | if !ok { 68 | t.Errorf("test %d failed: unexpected msg %+#v; was expecting UnlistenRequest", n, q) 69 | } 70 | } 71 | case "TrivialSelect": 72 | if err != nil { 73 | t.Errorf("test %d failed: unexpected error %q", n, err) 74 | } else { 75 | _, ok := q.(trivialSelect) 76 | if !ok { 77 | t.Errorf("test %d failed: unexpected msg %+#v; was expecting TrivialSelect", n, q) 78 | } 79 | } 80 | 81 | default: 82 | t.Fatalf("unexpected outcome %q", ts.outcome) 83 | } 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /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/golang/protobuf/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /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/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/github.com/johto/notifyutils/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Marko Tiikkaja 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.gitignore: -------------------------------------------------------------------------------- 1 | .db 2 | *.test 3 | *~ 4 | *.swp 5 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | client_configure() { 6 | sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key 7 | } 8 | 9 | pgdg_repository() { 10 | local sourcelist='sources.list.d/postgresql.list' 11 | 12 | curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo apt-key add - 13 | echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist" 14 | sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update 15 | } 16 | 17 | postgresql_configure() { 18 | sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null <<-config 19 | local all all trust 20 | hostnossl all pqgossltest 127.0.0.1/32 reject 21 | hostnossl all pqgosslcert 127.0.0.1/32 reject 22 | hostssl all pqgossltest 127.0.0.1/32 trust 23 | hostssl all pqgosslcert 127.0.0.1/32 cert 24 | host all all 127.0.0.1/32 trust 25 | hostnossl all pqgossltest ::1/128 reject 26 | hostnossl all pqgosslcert ::1/128 reject 27 | hostssl all pqgossltest ::1/128 trust 28 | hostssl all pqgosslcert ::1/128 cert 29 | host all all ::1/128 trust 30 | config 31 | 32 | xargs sudo install -o postgres -g postgres -m 600 -t /var/lib/postgresql/$PGVERSION/main/ <<-certificates 33 | certs/root.crt 34 | certs/server.crt 35 | certs/server.key 36 | certificates 37 | 38 | sort -VCu <<-versions || 39 | $PGVERSION 40 | 9.2 41 | versions 42 | sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null <<-config 43 | ssl_ca_file = 'root.crt' 44 | ssl_cert_file = 'server.crt' 45 | ssl_key_file = 'server.key' 46 | config 47 | 48 | echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null 49 | 50 | sudo service postgresql restart 51 | } 52 | 53 | postgresql_install() { 54 | xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages 55 | postgresql-$PGVERSION 56 | postgresql-server-dev-$PGVERSION 57 | postgresql-contrib-$PGVERSION 58 | packages 59 | } 60 | 61 | postgresql_uninstall() { 62 | sudo service postgresql stop 63 | xargs sudo apt-get -y --purge remove <<-packages 64 | libpq-dev 65 | libpq5 66 | postgresql 67 | postgresql-client-common 68 | postgresql-common 69 | packages 70 | sudo rm -rf /var/lib/postgresql 71 | } 72 | 73 | $1 74 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.5 5 | - 1.6 6 | - 1.7 7 | - tip 8 | 9 | sudo: true 10 | 11 | env: 12 | global: 13 | - PGUSER=postgres 14 | - PQGOSSLTESTS=1 15 | - PQSSLCERTTEST_PATH=$PWD/certs 16 | - PGHOST=127.0.0.1 17 | matrix: 18 | - PGVERSION=9.6 19 | - PGVERSION=9.5 20 | - PGVERSION=9.4 21 | - PGVERSION=9.3 22 | - PGVERSION=9.2 23 | - PGVERSION=9.1 24 | - PGVERSION=9.0 25 | 26 | before_install: 27 | - ./.travis.sh postgresql_uninstall 28 | - ./.travis.sh pgdg_repository 29 | - ./.travis.sh postgresql_install 30 | - ./.travis.sh postgresql_configure 31 | - ./.travis.sh client_configure 32 | - go get golang.org/x/tools/cmd/goimports 33 | 34 | before_script: 35 | - createdb pqgotest 36 | - createuser -DRS pqgossltest 37 | - createuser -DRS pqgosslcert 38 | 39 | script: 40 | - > 41 | goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' 42 | - go vet ./... 43 | - PQTEST_BINARY_PARAMETERS=no go test -v ./... 44 | - PQTEST_BINARY_PARAMETERS=yes go test -v ./... 45 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to pq 2 | 3 | `pq` has a backlog of pull requests, but contributions are still very 4 | much welcome. You can help with patch review, submitting bug reports, 5 | or adding new functionality. There is no formal style guide, but 6 | please conform to the style of existing code and general Go formatting 7 | conventions when submitting patches. 8 | 9 | ### Patch review 10 | 11 | Help review existing open pull requests by commenting on the code or 12 | proposed functionality. 13 | 14 | ### Bug reports 15 | 16 | We appreciate any bug reports, but especially ones with self-contained 17 | (doesn't depend on code outside of pq), minimal (can't be simplified 18 | further) test cases. It's especially helpful if you can submit a pull 19 | request with just the failing test case (you'll probably want to 20 | pattern it after the tests in 21 | [conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). 22 | 23 | ### New functionality 24 | 25 | There are a number of pending patches for new functionality, so 26 | additional feature patches will take a while to merge. Still, patches 27 | are generally reviewed based on usefulness and complexity in addition 28 | to time-in-queue, so if you have a knockout idea, take a shot. Feel 29 | free to open an issue discussion your proposed patch beforehand. 30 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2013, 'pq' Contributors 2 | Portions Copyright (C) 2011 Blake Mizerany 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/README.md: -------------------------------------------------------------------------------- 1 | # pq - A pure Go postgres driver for Go's database/sql package 2 | 3 | [![Build Status](https://travis-ci.org/lib/pq.png?branch=master)](https://travis-ci.org/lib/pq) 4 | 5 | ## Install 6 | 7 | go get github.com/lib/pq 8 | 9 | ## Docs 10 | 11 | For detailed documentation and basic usage examples, please see the package 12 | documentation at . 13 | 14 | ## Tests 15 | 16 | `go test` is used for testing. A running PostgreSQL server is 17 | required, with the ability to log in. The default database to connect 18 | to test with is "pqgotest," but it can be overridden using environment 19 | variables. 20 | 21 | Example: 22 | 23 | PGHOST=/run/postgresql go test github.com/lib/pq 24 | 25 | Optionally, a benchmark suite can be run as part of the tests: 26 | 27 | PGHOST=/run/postgresql go test -bench . 28 | 29 | ## Features 30 | 31 | * SSL 32 | * Handles bad connections for `database/sql` 33 | * Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) 34 | * Scan binary blobs correctly (i.e. `bytea`) 35 | * Package for `hstore` support 36 | * COPY FROM support 37 | * pq.ParseURL for converting urls to connection strings for sql.Open. 38 | * Many libpq compatible environment variables 39 | * Unix socket support 40 | * Notifications: `LISTEN`/`NOTIFY` 41 | * pgpass support 42 | 43 | ## Future / Things you can help with 44 | 45 | * Better COPY FROM / COPY TO (see discussion in #181) 46 | 47 | ## Thank you (alphabetical) 48 | 49 | Some of these contributors are from the original library `bmizerany/pq.go` whose 50 | code still exists in here. 51 | 52 | * Andy Balholm (andybalholm) 53 | * Ben Berkert (benburkert) 54 | * Benjamin Heatwole (bheatwole) 55 | * Bill Mill (llimllib) 56 | * Bjørn Madsen (aeons) 57 | * Blake Gentry (bgentry) 58 | * Brad Fitzpatrick (bradfitz) 59 | * Charlie Melbye (cmelbye) 60 | * Chris Bandy (cbandy) 61 | * Chris Gilling (cgilling) 62 | * Chris Walsh (cwds) 63 | * Dan Sosedoff (sosedoff) 64 | * Daniel Farina (fdr) 65 | * Eric Chlebek (echlebek) 66 | * Eric Garrido (minusnine) 67 | * Eric Urban (hydrogen18) 68 | * Everyone at The Go Team 69 | * Evan Shaw (edsrzf) 70 | * Ewan Chou (coocood) 71 | * Fazal Majid (fazalmajid) 72 | * Federico Romero (federomero) 73 | * Fumin (fumin) 74 | * Gary Burd (garyburd) 75 | * Heroku (heroku) 76 | * James Pozdena (jpoz) 77 | * Jason McVetta (jmcvetta) 78 | * Jeremy Jay (pbnjay) 79 | * Joakim Sernbrant (serbaut) 80 | * John Gallagher (jgallagher) 81 | * Jonathan Rudenberg (titanous) 82 | * Joël Stemmer (jstemmer) 83 | * Kamil Kisiel (kisielk) 84 | * Kelly Dunn (kellydunn) 85 | * Keith Rarick (kr) 86 | * Kir Shatrov (kirs) 87 | * Lann Martin (lann) 88 | * Maciek Sakrejda (uhoh-itsmaciek) 89 | * Marc Brinkmann (mbr) 90 | * Marko Tiikkaja (johto) 91 | * Matt Newberry (MattNewberry) 92 | * Matt Robenolt (mattrobenolt) 93 | * Martin Olsen (martinolsen) 94 | * Mike Lewis (mikelikespie) 95 | * Nicolas Patry (Narsil) 96 | * Oliver Tonnhofer (olt) 97 | * Patrick Hayes (phayes) 98 | * Paul Hammond (paulhammond) 99 | * Ryan Smith (ryandotsmith) 100 | * Samuel Stauffer (samuel) 101 | * Timothée Peignier (cyberdelia) 102 | * Travis Cline (tmc) 103 | * TruongSinh Tran-Nguyen (truongsinh) 104 | * Yaismel Miranda (ympons) 105 | * notedit (notedit) 106 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/buf.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | 7 | "github.com/lib/pq/oid" 8 | ) 9 | 10 | type readBuf []byte 11 | 12 | func (b *readBuf) int32() (n int) { 13 | n = int(int32(binary.BigEndian.Uint32(*b))) 14 | *b = (*b)[4:] 15 | return 16 | } 17 | 18 | func (b *readBuf) oid() (n oid.Oid) { 19 | n = oid.Oid(binary.BigEndian.Uint32(*b)) 20 | *b = (*b)[4:] 21 | return 22 | } 23 | 24 | // N.B: this is actually an unsigned 16-bit integer, unlike int32 25 | func (b *readBuf) int16() (n int) { 26 | n = int(binary.BigEndian.Uint16(*b)) 27 | *b = (*b)[2:] 28 | return 29 | } 30 | 31 | func (b *readBuf) string() string { 32 | i := bytes.IndexByte(*b, 0) 33 | if i < 0 { 34 | errorf("invalid message format; expected string terminator") 35 | } 36 | s := (*b)[:i] 37 | *b = (*b)[i+1:] 38 | return string(s) 39 | } 40 | 41 | func (b *readBuf) next(n int) (v []byte) { 42 | v = (*b)[:n] 43 | *b = (*b)[n:] 44 | return 45 | } 46 | 47 | func (b *readBuf) byte() byte { 48 | return b.next(1)[0] 49 | } 50 | 51 | type writeBuf struct { 52 | buf []byte 53 | pos int 54 | } 55 | 56 | func (b *writeBuf) int32(n int) { 57 | x := make([]byte, 4) 58 | binary.BigEndian.PutUint32(x, uint32(n)) 59 | b.buf = append(b.buf, x...) 60 | } 61 | 62 | func (b *writeBuf) int16(n int) { 63 | x := make([]byte, 2) 64 | binary.BigEndian.PutUint16(x, uint16(n)) 65 | b.buf = append(b.buf, x...) 66 | } 67 | 68 | func (b *writeBuf) string(s string) { 69 | b.buf = append(b.buf, (s + "\000")...) 70 | } 71 | 72 | func (b *writeBuf) byte(c byte) { 73 | b.buf = append(b.buf, c) 74 | } 75 | 76 | func (b *writeBuf) bytes(v []byte) { 77 | b.buf = append(b.buf, v...) 78 | } 79 | 80 | func (b *writeBuf) wrap() []byte { 81 | p := b.buf[b.pos:] 82 | binary.BigEndian.PutUint32(p, uint32(len(p))) 83 | return b.buf 84 | } 85 | 86 | func (b *writeBuf) next(c byte) { 87 | p := b.buf[b.pos:] 88 | binary.BigEndian.PutUint32(p, uint32(len(p))) 89 | b.pos = len(b.buf) + 1 90 | b.buf = append(b.buf, c, 0, 0, 0, 0) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/doc.go: -------------------------------------------------------------------------------- 1 | // Package oid contains OID constants 2 | // as defined by the Postgres server. 3 | package oid 4 | 5 | // Oid is a Postgres Object ID. 6 | type Oid uint32 7 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/types.go: -------------------------------------------------------------------------------- 1 | // generated by 'go run gen.go'; do not edit 2 | 3 | package oid 4 | 5 | const ( 6 | T_bool Oid = 16 7 | T_bytea Oid = 17 8 | T_char Oid = 18 9 | T_name Oid = 19 10 | T_int8 Oid = 20 11 | T_int2 Oid = 21 12 | T_int2vector Oid = 22 13 | T_int4 Oid = 23 14 | T_regproc Oid = 24 15 | T_text Oid = 25 16 | T_oid Oid = 26 17 | T_tid Oid = 27 18 | T_xid Oid = 28 19 | T_cid Oid = 29 20 | T_oidvector Oid = 30 21 | T_pg_type Oid = 71 22 | T_pg_attribute Oid = 75 23 | T_pg_proc Oid = 81 24 | T_pg_class Oid = 83 25 | T_json Oid = 114 26 | T_xml Oid = 142 27 | T__xml Oid = 143 28 | T_pg_node_tree Oid = 194 29 | T__json Oid = 199 30 | T_smgr Oid = 210 31 | T_point Oid = 600 32 | T_lseg Oid = 601 33 | T_path Oid = 602 34 | T_box Oid = 603 35 | T_polygon Oid = 604 36 | T_line Oid = 628 37 | T__line Oid = 629 38 | T_cidr Oid = 650 39 | T__cidr Oid = 651 40 | T_float4 Oid = 700 41 | T_float8 Oid = 701 42 | T_abstime Oid = 702 43 | T_reltime Oid = 703 44 | T_tinterval Oid = 704 45 | T_unknown Oid = 705 46 | T_circle Oid = 718 47 | T__circle Oid = 719 48 | T_money Oid = 790 49 | T__money Oid = 791 50 | T_macaddr Oid = 829 51 | T_inet Oid = 869 52 | T__bool Oid = 1000 53 | T__bytea Oid = 1001 54 | T__char Oid = 1002 55 | T__name Oid = 1003 56 | T__int2 Oid = 1005 57 | T__int2vector Oid = 1006 58 | T__int4 Oid = 1007 59 | T__regproc Oid = 1008 60 | T__text Oid = 1009 61 | T__tid Oid = 1010 62 | T__xid Oid = 1011 63 | T__cid Oid = 1012 64 | T__oidvector Oid = 1013 65 | T__bpchar Oid = 1014 66 | T__varchar Oid = 1015 67 | T__int8 Oid = 1016 68 | T__point Oid = 1017 69 | T__lseg Oid = 1018 70 | T__path Oid = 1019 71 | T__box Oid = 1020 72 | T__float4 Oid = 1021 73 | T__float8 Oid = 1022 74 | T__abstime Oid = 1023 75 | T__reltime Oid = 1024 76 | T__tinterval Oid = 1025 77 | T__polygon Oid = 1027 78 | T__oid Oid = 1028 79 | T_aclitem Oid = 1033 80 | T__aclitem Oid = 1034 81 | T__macaddr Oid = 1040 82 | T__inet Oid = 1041 83 | T_bpchar Oid = 1042 84 | T_varchar Oid = 1043 85 | T_date Oid = 1082 86 | T_time Oid = 1083 87 | T_timestamp Oid = 1114 88 | T__timestamp Oid = 1115 89 | T__date Oid = 1182 90 | T__time Oid = 1183 91 | T_timestamptz Oid = 1184 92 | T__timestamptz Oid = 1185 93 | T_interval Oid = 1186 94 | T__interval Oid = 1187 95 | T__numeric Oid = 1231 96 | T_pg_database Oid = 1248 97 | T__cstring Oid = 1263 98 | T_timetz Oid = 1266 99 | T__timetz Oid = 1270 100 | T_bit Oid = 1560 101 | T__bit Oid = 1561 102 | T_varbit Oid = 1562 103 | T__varbit Oid = 1563 104 | T_numeric Oid = 1700 105 | T_refcursor Oid = 1790 106 | T__refcursor Oid = 2201 107 | T_regprocedure Oid = 2202 108 | T_regoper Oid = 2203 109 | T_regoperator Oid = 2204 110 | T_regclass Oid = 2205 111 | T_regtype Oid = 2206 112 | T__regprocedure Oid = 2207 113 | T__regoper Oid = 2208 114 | T__regoperator Oid = 2209 115 | T__regclass Oid = 2210 116 | T__regtype Oid = 2211 117 | T_record Oid = 2249 118 | T_cstring Oid = 2275 119 | T_any Oid = 2276 120 | T_anyarray Oid = 2277 121 | T_void Oid = 2278 122 | T_trigger Oid = 2279 123 | T_language_handler Oid = 2280 124 | T_internal Oid = 2281 125 | T_opaque Oid = 2282 126 | T_anyelement Oid = 2283 127 | T__record Oid = 2287 128 | T_anynonarray Oid = 2776 129 | T_pg_authid Oid = 2842 130 | T_pg_auth_members Oid = 2843 131 | T__txid_snapshot Oid = 2949 132 | T_uuid Oid = 2950 133 | T__uuid Oid = 2951 134 | T_txid_snapshot Oid = 2970 135 | T_fdw_handler Oid = 3115 136 | T_anyenum Oid = 3500 137 | T_tsvector Oid = 3614 138 | T_tsquery Oid = 3615 139 | T_gtsvector Oid = 3642 140 | T__tsvector Oid = 3643 141 | T__gtsvector Oid = 3644 142 | T__tsquery Oid = 3645 143 | T_regconfig Oid = 3734 144 | T__regconfig Oid = 3735 145 | T_regdictionary Oid = 3769 146 | T__regdictionary Oid = 3770 147 | T_anyrange Oid = 3831 148 | T_event_trigger Oid = 3838 149 | T_int4range Oid = 3904 150 | T__int4range Oid = 3905 151 | T_numrange Oid = 3906 152 | T__numrange Oid = 3907 153 | T_tsrange Oid = 3908 154 | T__tsrange Oid = 3909 155 | T_tstzrange Oid = 3910 156 | T__tstzrange Oid = 3911 157 | T_daterange Oid = 3912 158 | T__daterange Oid = 3913 159 | T_int8range Oid = 3926 160 | T__int8range Oid = 3927 161 | ) 162 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/url.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | nurl "net/url" 7 | "sort" 8 | "strings" 9 | ) 10 | 11 | // ParseURL no longer needs to be used by clients of this library since supplying a URL as a 12 | // connection string to sql.Open() is now supported: 13 | // 14 | // sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") 15 | // 16 | // It remains exported here for backwards-compatibility. 17 | // 18 | // ParseURL converts a url to a connection string for driver.Open. 19 | // Example: 20 | // 21 | // "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" 22 | // 23 | // converts to: 24 | // 25 | // "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" 26 | // 27 | // A minimal example: 28 | // 29 | // "postgres://" 30 | // 31 | // This will be blank, causing driver.Open to use all of the defaults 32 | func ParseURL(url string) (string, error) { 33 | u, err := nurl.Parse(url) 34 | if err != nil { 35 | return "", err 36 | } 37 | 38 | if u.Scheme != "postgres" && u.Scheme != "postgresql" { 39 | return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) 40 | } 41 | 42 | var kvs []string 43 | escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) 44 | accrue := func(k, v string) { 45 | if v != "" { 46 | kvs = append(kvs, k+"="+escaper.Replace(v)) 47 | } 48 | } 49 | 50 | if u.User != nil { 51 | v := u.User.Username() 52 | accrue("user", v) 53 | 54 | v, _ = u.User.Password() 55 | accrue("password", v) 56 | } 57 | 58 | if host, port, err := net.SplitHostPort(u.Host); err != nil { 59 | accrue("host", u.Host) 60 | } else { 61 | accrue("host", host) 62 | accrue("port", port) 63 | } 64 | 65 | if u.Path != "" { 66 | accrue("dbname", u.Path[1:]) 67 | } 68 | 69 | q := u.Query() 70 | for k := range q { 71 | accrue(k, q.Get(k)) 72 | } 73 | 74 | sort.Strings(kvs) // Makes testing easier (not a performance concern) 75 | return strings.Join(kvs, " "), nil 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_posix.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | 3 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun 4 | 5 | package pq 6 | 7 | import ( 8 | "os" 9 | "os/user" 10 | ) 11 | 12 | func userCurrent() (string, error) { 13 | u, err := user.Current() 14 | if err == nil { 15 | return u.Username, nil 16 | } 17 | 18 | name := os.Getenv("USER") 19 | if name != "" { 20 | return name, nil 21 | } 22 | 23 | return "", ErrCouldNotDetectUsername 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_windows.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | package pq 3 | 4 | import ( 5 | "path/filepath" 6 | "syscall" 7 | ) 8 | 9 | // Perform Windows user name lookup identically to libpq. 10 | // 11 | // The PostgreSQL code makes use of the legacy Win32 function 12 | // GetUserName, and that function has not been imported into stock Go. 13 | // GetUserNameEx is available though, the difference being that a 14 | // wider range of names are available. To get the output to be the 15 | // same as GetUserName, only the base (or last) component of the 16 | // result is returned. 17 | func userCurrent() (string, error) { 18 | pw_name := make([]uint16, 128) 19 | pwname_size := uint32(len(pw_name)) - 1 20 | err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) 21 | if err != nil { 22 | return "", ErrCouldNotDetectUsername 23 | } 24 | s := syscall.UTF16ToString(pw_name) 25 | u := filepath.Base(s) 26 | return u, nil 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt T. Proud (matt.proud@gmail.com) 2 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore: -------------------------------------------------------------------------------- 1 | cover.dat 2 | -------------------------------------------------------------------------------- /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/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/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/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/prometheus/client_golang/AUTHORS.md: -------------------------------------------------------------------------------- 1 | The Prometheus project was started by Matt T. Proud (emeritus) and 2 | Julius Volz in 2012. 3 | 4 | Maintainers of this repository: 5 | 6 | * Björn Rabenstein 7 | 8 | More than [30 individuals][1] have contributed to this repository. Please refer 9 | to the Git commit log for a complete list. 10 | 11 | [1]: https://github.com/prometheus/client_golang/graphs/contributors 12 | -------------------------------------------------------------------------------- /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/client_golang/prometheus/.gitignore: -------------------------------------------------------------------------------- 1 | command-line-arguments.test 2 | -------------------------------------------------------------------------------- /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_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/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 | -------------------------------------------------------------------------------- /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/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/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/metric.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 | "strings" 18 | 19 | dto "github.com/prometheus/client_model/go" 20 | ) 21 | 22 | const separatorByte byte = 255 23 | 24 | // A Metric models a single sample value with its meta data being exported to 25 | // Prometheus. Implementations of Metric in this package are Gauge, Counter, 26 | // Histogram, Summary, and Untyped. 27 | type Metric interface { 28 | // Desc returns the descriptor for the Metric. This method idempotently 29 | // returns the same descriptor throughout the lifetime of the 30 | // Metric. The returned descriptor is immutable by contract. A Metric 31 | // unable to describe itself must return an invalid descriptor (created 32 | // with NewInvalidDesc). 33 | Desc() *Desc 34 | // Write encodes the Metric into a "Metric" Protocol Buffer data 35 | // transmission object. 36 | // 37 | // Metric implementations must observe concurrency safety as reads of 38 | // this metric may occur at any time, and any blocking occurs at the 39 | // expense of total performance of rendering all registered 40 | // metrics. Ideally, Metric implementations should support concurrent 41 | // readers. 42 | // 43 | // While populating dto.Metric, it is the responsibility of the 44 | // implementation to ensure validity of the Metric protobuf (like valid 45 | // UTF-8 strings or syntactically valid metric and label names). It is 46 | // recommended to sort labels lexicographically. (Implementers may find 47 | // LabelPairSorter useful for that.) Callers of Write should still make 48 | // sure of sorting if they depend on it. 49 | Write(*dto.Metric) error 50 | // TODO(beorn7): The original rationale of passing in a pre-allocated 51 | // dto.Metric protobuf to save allocations has disappeared. The 52 | // signature of this method should be changed to "Write() (*dto.Metric, 53 | // error)". 54 | } 55 | 56 | // Opts bundles the options for creating most Metric types. Each metric 57 | // implementation XXX has its own XXXOpts type, but in most cases, it is just be 58 | // an alias of this type (which might change when the requirement arises.) 59 | // 60 | // It is mandatory to set Name and Help to a non-empty string. All other fields 61 | // are optional and can safely be left at their zero value. 62 | type Opts struct { 63 | // Namespace, Subsystem, and Name are components of the fully-qualified 64 | // name of the Metric (created by joining these components with 65 | // "_"). Only Name is mandatory, the others merely help structuring the 66 | // name. Note that the fully-qualified name of the metric must be a 67 | // valid Prometheus metric name. 68 | Namespace string 69 | Subsystem string 70 | Name string 71 | 72 | // Help provides information about this metric. Mandatory! 73 | // 74 | // Metrics with the same fully-qualified name must have the same Help 75 | // string. 76 | Help string 77 | 78 | // ConstLabels are used to attach fixed labels to this metric. Metrics 79 | // with the same fully-qualified name must have the same label names in 80 | // their ConstLabels. 81 | // 82 | // Note that in most cases, labels have a value that varies during the 83 | // lifetime of a process. Those labels are usually managed with a metric 84 | // vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels 85 | // serve only special purposes. One is for the special case where the 86 | // value of a label does not change during the lifetime of a process, 87 | // e.g. if the revision of the running binary is put into a 88 | // label. Another, more advanced purpose is if more than one Collector 89 | // needs to collect Metrics with the same fully-qualified name. In that 90 | // case, those Metrics must differ in the values of their 91 | // ConstLabels. See the Collector examples. 92 | // 93 | // If the value of a label never changes (not even between binaries), 94 | // that label most likely should not be a label at all (but part of the 95 | // metric name). 96 | ConstLabels Labels 97 | } 98 | 99 | // BuildFQName joins the given three name components by "_". Empty name 100 | // components are ignored. If the name parameter itself is empty, an empty 101 | // string is returned, no matter what. Metric implementations included in this 102 | // library use this function internally to generate the fully-qualified metric 103 | // name from the name component in their Opts. Users of the library will only 104 | // need this function if they implement their own Metric or instantiate a Desc 105 | // (with NewDesc) directly. 106 | func BuildFQName(namespace, subsystem, name string) string { 107 | if name == "" { 108 | return "" 109 | } 110 | switch { 111 | case namespace != "" && subsystem != "": 112 | return strings.Join([]string{namespace, subsystem, name}, "_") 113 | case namespace != "": 114 | return strings.Join([]string{namespace, name}, "_") 115 | case subsystem != "": 116 | return strings.Join([]string{subsystem, name}, "_") 117 | } 118 | return name 119 | } 120 | 121 | // LabelPairSorter implements sort.Interface. It is used to sort a slice of 122 | // dto.LabelPair pointers. This is useful for implementing the Write method of 123 | // custom metrics. 124 | type LabelPairSorter []*dto.LabelPair 125 | 126 | func (s LabelPairSorter) Len() int { 127 | return len(s) 128 | } 129 | 130 | func (s LabelPairSorter) Swap(i, j int) { 131 | s[i], s[j] = s[j], s[i] 132 | } 133 | 134 | func (s LabelPairSorter) Less(i, j int) bool { 135 | return s[i].GetName() < s[j].GetName() 136 | } 137 | 138 | type hashSorter []uint64 139 | 140 | func (s hashSorter) Len() int { 141 | return len(s) 142 | } 143 | 144 | func (s hashSorter) Swap(i, j int) { 145 | s[i], s[j] = s[j], s[i] 146 | } 147 | 148 | func (s hashSorter) Less(i, j int) bool { 149 | return s[i] < s[j] 150 | } 151 | 152 | type invalidMetric struct { 153 | desc *Desc 154 | err error 155 | } 156 | 157 | // NewInvalidMetric returns a metric whose Write method always returns the 158 | // provided error. It is useful if a Collector finds itself unable to collect 159 | // a metric and wishes to report an error to the registry. 160 | func NewInvalidMetric(desc *Desc, err error) Metric { 161 | return &invalidMetric{desc, err} 162 | } 163 | 164 | func (m *invalidMetric) Desc() *Desc { return m.desc } 165 | 166 | func (m *invalidMetric) Write(*dto.Metric) error { return m.err } 167 | -------------------------------------------------------------------------------- /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/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/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/client_model/AUTHORS.md: -------------------------------------------------------------------------------- 1 | The Prometheus project was started by Matt T. Proud (emeritus) and 2 | Julius Volz in 2012. 3 | 4 | Maintainers of this repository: 5 | 6 | * Björn Rabenstein 7 | 8 | The following individuals have contributed code to this repository 9 | (listed in alphabetical order): 10 | 11 | * Björn Rabenstein 12 | * Matt T. Proud 13 | * Tobias Schmidt 14 | -------------------------------------------------------------------------------- /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/AUTHORS.md: -------------------------------------------------------------------------------- 1 | Maintainers of this repository: 2 | 3 | * Fabian Reinartz 4 | 5 | The following individuals have contributed code to this repository 6 | (listed in alphabetical order): 7 | 8 | * Björn Rabenstein 9 | * Fabian Reinartz 10 | * Julius Volz 11 | * Miguel Molina 12 | -------------------------------------------------------------------------------- /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/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/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 | // A package for reading and writing Prometheus metrics. 15 | package expfmt 16 | 17 | type Format string 18 | 19 | const ( 20 | TextVersion = "0.0.4" 21 | 22 | ProtoType = `application/vnd.google.protobuf` 23 | ProtoProtocol = `io.prometheus.client.MetricFamily` 24 | ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" 25 | 26 | // The Content-Type values for the different wire protocols. 27 | FmtUnknown Format = `` 28 | FmtText Format = `text/plain; version=` + TextVersion 29 | FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` 30 | FmtProtoText Format = ProtoFmt + ` encoding=text` 31 | FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` 32 | ) 33 | 34 | const ( 35 | hdrContentType = "Content-Type" 36 | hdrAccept = "Accept" 37 | ) 38 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/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/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/common/model/labels.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 | "regexp" 20 | "strings" 21 | "unicode/utf8" 22 | ) 23 | 24 | const ( 25 | // AlertNameLabel is the name of the label containing the an alert's name. 26 | AlertNameLabel = "alertname" 27 | 28 | // ExportedLabelPrefix is the prefix to prepend to the label names present in 29 | // exported metrics if a label of the same name is added by the server. 30 | ExportedLabelPrefix = "exported_" 31 | 32 | // MetricNameLabel is the label name indicating the metric name of a 33 | // timeseries. 34 | MetricNameLabel = "__name__" 35 | 36 | // SchemeLabel is the name of the label that holds the scheme on which to 37 | // scrape a target. 38 | SchemeLabel = "__scheme__" 39 | 40 | // AddressLabel is the name of the label that holds the address of 41 | // a scrape target. 42 | AddressLabel = "__address__" 43 | 44 | // MetricsPathLabel is the name of the label that holds the path on which to 45 | // scrape a target. 46 | MetricsPathLabel = "__metrics_path__" 47 | 48 | // ReservedLabelPrefix is a prefix which is not legal in user-supplied 49 | // label names. 50 | ReservedLabelPrefix = "__" 51 | 52 | // MetaLabelPrefix is a prefix for labels that provide meta information. 53 | // Labels with this prefix are used for intermediate label processing and 54 | // will not be attached to time series. 55 | MetaLabelPrefix = "__meta_" 56 | 57 | // TmpLabelPrefix is a prefix for temporary labels as part of relabelling. 58 | // Labels with this prefix are used for intermediate label processing and 59 | // will not be attached to time series. This is reserved for use in 60 | // Prometheus configuration files by users. 61 | TmpLabelPrefix = "__tmp_" 62 | 63 | // ParamLabelPrefix is a prefix for labels that provide URL parameters 64 | // used to scrape a target. 65 | ParamLabelPrefix = "__param_" 66 | 67 | // JobLabel is the label name indicating the job from which a timeseries 68 | // was scraped. 69 | JobLabel = "job" 70 | 71 | // InstanceLabel is the label name used for the instance label. 72 | InstanceLabel = "instance" 73 | 74 | // BucketLabel is used for the label that defines the upper bound of a 75 | // bucket of a histogram ("le" -> "less or equal"). 76 | BucketLabel = "le" 77 | 78 | // QuantileLabel is used for the label that defines the quantile in a 79 | // summary. 80 | QuantileLabel = "quantile" 81 | ) 82 | 83 | // LabelNameRE is a regular expression matching valid label names. Note that the 84 | // IsValid method of LabelName performs the same check but faster than a match 85 | // with this regular expression. 86 | var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") 87 | 88 | // A LabelName is a key for a LabelSet or Metric. It has a value associated 89 | // therewith. 90 | type LabelName string 91 | 92 | // IsValid is true iff the label name matches the pattern of LabelNameRE. This 93 | // method, however, does not use LabelNameRE for the check but a much faster 94 | // hardcoded implementation. 95 | func (ln LabelName) IsValid() bool { 96 | if len(ln) == 0 { 97 | return false 98 | } 99 | for i, b := range ln { 100 | if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { 101 | return false 102 | } 103 | } 104 | return true 105 | } 106 | 107 | // UnmarshalYAML implements the yaml.Unmarshaler interface. 108 | func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error { 109 | var s string 110 | if err := unmarshal(&s); err != nil { 111 | return err 112 | } 113 | if !LabelName(s).IsValid() { 114 | return fmt.Errorf("%q is not a valid label name", s) 115 | } 116 | *ln = LabelName(s) 117 | return nil 118 | } 119 | 120 | // UnmarshalJSON implements the json.Unmarshaler interface. 121 | func (ln *LabelName) UnmarshalJSON(b []byte) error { 122 | var s string 123 | if err := json.Unmarshal(b, &s); err != nil { 124 | return err 125 | } 126 | if !LabelName(s).IsValid() { 127 | return fmt.Errorf("%q is not a valid label name", s) 128 | } 129 | *ln = LabelName(s) 130 | return nil 131 | } 132 | 133 | // LabelNames is a sortable LabelName slice. In implements sort.Interface. 134 | type LabelNames []LabelName 135 | 136 | func (l LabelNames) Len() int { 137 | return len(l) 138 | } 139 | 140 | func (l LabelNames) Less(i, j int) bool { 141 | return l[i] < l[j] 142 | } 143 | 144 | func (l LabelNames) Swap(i, j int) { 145 | l[i], l[j] = l[j], l[i] 146 | } 147 | 148 | func (l LabelNames) String() string { 149 | labelStrings := make([]string, 0, len(l)) 150 | for _, label := range l { 151 | labelStrings = append(labelStrings, string(label)) 152 | } 153 | return strings.Join(labelStrings, ", ") 154 | } 155 | 156 | // A LabelValue is an associated value for a LabelName. 157 | type LabelValue string 158 | 159 | // IsValid returns true iff the string is a valid UTF8. 160 | func (lv LabelValue) IsValid() bool { 161 | return utf8.ValidString(string(lv)) 162 | } 163 | 164 | // LabelValues is a sortable LabelValue slice. It implements sort.Interface. 165 | type LabelValues []LabelValue 166 | 167 | func (l LabelValues) Len() int { 168 | return len(l) 169 | } 170 | 171 | func (l LabelValues) Less(i, j int) bool { 172 | return string(l[i]) < string(l[j]) 173 | } 174 | 175 | func (l LabelValues) Swap(i, j int) { 176 | l[i], l[j] = l[j], l[i] 177 | } 178 | 179 | // LabelPair pairs a name with a value. 180 | type LabelPair struct { 181 | Name LabelName 182 | Value LabelValue 183 | } 184 | 185 | // LabelPairs is a sortable slice of LabelPair pointers. It implements 186 | // sort.Interface. 187 | type LabelPairs []*LabelPair 188 | 189 | func (l LabelPairs) Len() int { 190 | return len(l) 191 | } 192 | 193 | func (l LabelPairs) Less(i, j int) bool { 194 | switch { 195 | case l[i].Name > l[j].Name: 196 | return false 197 | case l[i].Name < l[j].Name: 198 | return true 199 | case l[i].Value > l[j].Value: 200 | return false 201 | case l[i].Value < l[j].Value: 202 | return true 203 | default: 204 | return false 205 | } 206 | } 207 | 208 | func (l LabelPairs) Swap(i, j int) { 209 | l[i], l[j] = l[j], l[i] 210 | } 211 | -------------------------------------------------------------------------------- /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/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 := Metric{} 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/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 | -------------------------------------------------------------------------------- /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/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/procfs/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go: 4 | - 1.6.4 5 | - 1.7.4 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/AUTHORS.md: -------------------------------------------------------------------------------- 1 | The Prometheus project was started by Matt T. Proud (emeritus) and 2 | Julius Volz in 2012. 3 | 4 | Maintainers of this repository: 5 | 6 | * Tobias Schmidt 7 | 8 | The following individuals have contributed code to this repository 9 | (listed in alphabetical order): 10 | 11 | * Armen Baghumian 12 | * Bjoern Rabenstein 13 | * David Cournapeau 14 | * Ji-Hoon, Seol 15 | * Jonas Große Sundrup 16 | * Julius Volz 17 | * Matt Layher 18 | * Matthias Rampke 19 | * Nicky Gerritsen 20 | * Rémi Audebert 21 | * Tobias Schmidt 22 | -------------------------------------------------------------------------------- /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 6 | request, addressing (with `@...`) one or more of the maintainers 7 | (see [AUTHORS.md](AUTHORS.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/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/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/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 | -------------------------------------------------------------------------------- /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/prometheus/procfs/fs.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path" 7 | ) 8 | 9 | // FS represents the pseudo-filesystem proc, which provides an interface to 10 | // kernel data structures. 11 | type FS string 12 | 13 | // DefaultMountPoint is the common mount point of the proc filesystem. 14 | const DefaultMountPoint = "/proc" 15 | 16 | // NewFS returns a new FS mounted under the given mountPoint. It will error 17 | // if the mount point can't be read. 18 | func NewFS(mountPoint string) (FS, error) { 19 | info, err := os.Stat(mountPoint) 20 | if err != nil { 21 | return "", fmt.Errorf("could not read %s: %s", mountPoint, err) 22 | } 23 | if !info.IsDir() { 24 | return "", fmt.Errorf("mount point %s is not a directory", mountPoint) 25 | } 26 | 27 | return FS(mountPoint), nil 28 | } 29 | 30 | // Path returns the path of the given subsystem relative to the procfs root. 31 | func (fs FS) Path(p ...string) string { 32 | return path.Join(append([]string{string(fs)}, p...)...) 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/ipvs.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "encoding/hex" 6 | "errors" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "net" 11 | "os" 12 | "strconv" 13 | "strings" 14 | ) 15 | 16 | // IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`. 17 | type IPVSStats struct { 18 | // Total count of connections. 19 | Connections uint64 20 | // Total incoming packages processed. 21 | IncomingPackets uint64 22 | // Total outgoing packages processed. 23 | OutgoingPackets uint64 24 | // Total incoming traffic. 25 | IncomingBytes uint64 26 | // Total outgoing traffic. 27 | OutgoingBytes uint64 28 | } 29 | 30 | // IPVSBackendStatus holds current metrics of one virtual / real address pair. 31 | type IPVSBackendStatus struct { 32 | // The local (virtual) IP address. 33 | LocalAddress net.IP 34 | // The local (virtual) port. 35 | LocalPort uint16 36 | // The transport protocol (TCP, UDP). 37 | Proto string 38 | // The remote (real) IP address. 39 | RemoteAddress net.IP 40 | // The remote (real) port. 41 | RemotePort uint16 42 | // The current number of active connections for this virtual/real address pair. 43 | ActiveConn uint64 44 | // The current number of inactive connections for this virtual/real address pair. 45 | InactConn uint64 46 | // The current weight of this virtual/real address pair. 47 | Weight uint64 48 | } 49 | 50 | // NewIPVSStats reads the IPVS statistics. 51 | func NewIPVSStats() (IPVSStats, error) { 52 | fs, err := NewFS(DefaultMountPoint) 53 | if err != nil { 54 | return IPVSStats{}, err 55 | } 56 | 57 | return fs.NewIPVSStats() 58 | } 59 | 60 | // NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem. 61 | func (fs FS) NewIPVSStats() (IPVSStats, error) { 62 | file, err := os.Open(fs.Path("net/ip_vs_stats")) 63 | if err != nil { 64 | return IPVSStats{}, err 65 | } 66 | defer file.Close() 67 | 68 | return parseIPVSStats(file) 69 | } 70 | 71 | // parseIPVSStats performs the actual parsing of `ip_vs_stats`. 72 | func parseIPVSStats(file io.Reader) (IPVSStats, error) { 73 | var ( 74 | statContent []byte 75 | statLines []string 76 | statFields []string 77 | stats IPVSStats 78 | ) 79 | 80 | statContent, err := ioutil.ReadAll(file) 81 | if err != nil { 82 | return IPVSStats{}, err 83 | } 84 | 85 | statLines = strings.SplitN(string(statContent), "\n", 4) 86 | if len(statLines) != 4 { 87 | return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short") 88 | } 89 | 90 | statFields = strings.Fields(statLines[2]) 91 | if len(statFields) != 5 { 92 | return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields") 93 | } 94 | 95 | stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64) 96 | if err != nil { 97 | return IPVSStats{}, err 98 | } 99 | stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64) 100 | if err != nil { 101 | return IPVSStats{}, err 102 | } 103 | stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64) 104 | if err != nil { 105 | return IPVSStats{}, err 106 | } 107 | stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64) 108 | if err != nil { 109 | return IPVSStats{}, err 110 | } 111 | stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64) 112 | if err != nil { 113 | return IPVSStats{}, err 114 | } 115 | 116 | return stats, nil 117 | } 118 | 119 | // NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs. 120 | func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) { 121 | fs, err := NewFS(DefaultMountPoint) 122 | if err != nil { 123 | return []IPVSBackendStatus{}, err 124 | } 125 | 126 | return fs.NewIPVSBackendStatus() 127 | } 128 | 129 | // NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem. 130 | func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) { 131 | file, err := os.Open(fs.Path("net/ip_vs")) 132 | if err != nil { 133 | return nil, err 134 | } 135 | defer file.Close() 136 | 137 | return parseIPVSBackendStatus(file) 138 | } 139 | 140 | func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) { 141 | var ( 142 | status []IPVSBackendStatus 143 | scanner = bufio.NewScanner(file) 144 | proto string 145 | localAddress net.IP 146 | localPort uint16 147 | err error 148 | ) 149 | 150 | for scanner.Scan() { 151 | fields := strings.Fields(string(scanner.Text())) 152 | if len(fields) == 0 { 153 | continue 154 | } 155 | switch { 156 | case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port": 157 | continue 158 | case fields[0] == "TCP" || fields[0] == "UDP": 159 | if len(fields) < 2 { 160 | continue 161 | } 162 | proto = fields[0] 163 | localAddress, localPort, err = parseIPPort(fields[1]) 164 | if err != nil { 165 | return nil, err 166 | } 167 | case fields[0] == "->": 168 | if len(fields) < 6 { 169 | continue 170 | } 171 | remoteAddress, remotePort, err := parseIPPort(fields[1]) 172 | if err != nil { 173 | return nil, err 174 | } 175 | weight, err := strconv.ParseUint(fields[3], 10, 64) 176 | if err != nil { 177 | return nil, err 178 | } 179 | activeConn, err := strconv.ParseUint(fields[4], 10, 64) 180 | if err != nil { 181 | return nil, err 182 | } 183 | inactConn, err := strconv.ParseUint(fields[5], 10, 64) 184 | if err != nil { 185 | return nil, err 186 | } 187 | status = append(status, IPVSBackendStatus{ 188 | LocalAddress: localAddress, 189 | LocalPort: localPort, 190 | RemoteAddress: remoteAddress, 191 | RemotePort: remotePort, 192 | Proto: proto, 193 | Weight: weight, 194 | ActiveConn: activeConn, 195 | InactConn: inactConn, 196 | }) 197 | } 198 | } 199 | return status, nil 200 | } 201 | 202 | func parseIPPort(s string) (net.IP, uint16, error) { 203 | tmp := strings.SplitN(s, ":", 2) 204 | 205 | if len(tmp) != 2 { 206 | return nil, 0, fmt.Errorf("invalid IP:Port: %s", s) 207 | } 208 | 209 | if len(tmp[0]) != 8 && len(tmp[0]) != 32 { 210 | return nil, 0, fmt.Errorf("invalid IP: %s", tmp[0]) 211 | } 212 | 213 | ip, err := hex.DecodeString(tmp[0]) 214 | if err != nil { 215 | return nil, 0, err 216 | } 217 | 218 | port, err := strconv.ParseUint(tmp[1], 16, 16) 219 | if err != nil { 220 | return nil, 0, err 221 | } 222 | 223 | return ip, uint16(port), nil 224 | } 225 | -------------------------------------------------------------------------------- /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/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/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/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/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/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/uhoh-itsmaciek/femebe/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Blake Mizerany 2 | Daniel Farina 3 | Eric Fode 4 | Maciek Sakrejda 5 | Marko Tiikkaja 6 | Timothée Peignier 7 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, The Femebe 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 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/buf/buffer.go: -------------------------------------------------------------------------------- 1 | package buf 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "io" 7 | ) 8 | 9 | // WriteInt16 writes the bytes of the int16 val to the io.Writer w 10 | // in big-endian byte order. It returns the number of bytes written 11 | // and any error encountered in writing. Like io.Writer, it will 12 | // return a non-nil error if not all bytes are written. 13 | func WriteInt16(w io.Writer, val int16) (n int, err error) { 14 | var be [2]byte 15 | valBytes := be[0:2] 16 | binary.BigEndian.PutUint16(valBytes, uint16(val)) 17 | return w.Write(valBytes) 18 | } 19 | 20 | // WriteInt32 writes the bytes of the int32 val to the io.Writer w 21 | // in big-endian byte order. It returns the number of bytes written 22 | // and any error encountered in writing. Like io.Writer, it will 23 | // return a non-nil error if not all bytes are written. 24 | func WriteInt32(w io.Writer, val int32) (n int, err error) { 25 | return WriteUint32(w, uint32(val)) 26 | } 27 | 28 | // WriteUint32 writes the bytes of the uint32 val to the io.Writer w 29 | // in big-endian byte order. It returns the number of bytes written 30 | // and any error encountered in writing. Like io.Writer, it will 31 | // return a non-nil error if not all bytes are written. 32 | func WriteUint32(w io.Writer, val uint32) (n int, err error) { 33 | var be [4]byte 34 | valBytes := be[0:4] 35 | binary.BigEndian.PutUint32(valBytes, val) 36 | 37 | return w.Write(valBytes) 38 | } 39 | 40 | // WriteCString writes the bytes of the string val to the io.Writer w 41 | // in UTF-8 encoding, followed by a null termination byte (i.e., the 42 | // standard C representation of a string). Like io.Writer, it will 43 | // return a non-nil error if not all bytes are written. 44 | func WriteCString(w io.Writer, val string) (n int, err error) { 45 | n, err = w.Write([]byte(val)) 46 | if err != nil { 47 | return n, err 48 | } 49 | _, err = w.Write([]byte{'\000'}) 50 | return n + 1, err 51 | } 52 | 53 | // ReadInt16 reads a 16-bit signed integer from the io.Reader r in 54 | // big-endian byte order. Note that if an error is encountered when 55 | // reading, it will be returned along with the value 0. An EOF error 56 | // is returned when no bytes could be read; an UnexpectedEOF if some 57 | // bytes were read first. 58 | func ReadInt16(r io.Reader) (int16, error) { 59 | var be [2]byte 60 | valBytes := be[0:2] 61 | if _, err := io.ReadFull(r, valBytes); err != nil { 62 | return 0, err 63 | } 64 | 65 | return int16(binary.BigEndian.Uint16(valBytes)), nil 66 | } 67 | 68 | // ReadUint16 reads a 16-bit unsigned integer from the io.Reader r in 69 | // big-endian byte order. Note that if an error is encountered when 70 | // reading, it will be returned along with the value 0. An EOF error 71 | // is returned when no bytes could be read; an UnexpectedEOF if some 72 | // bytes were read first. 73 | func ReadUint16(r io.Reader) (uint16, error) { 74 | var be [2]byte 75 | valBytes := be[0:2] 76 | if _, err := io.ReadFull(r, valBytes); err != nil { 77 | return 0, err 78 | } 79 | 80 | return uint16(binary.BigEndian.Uint16(valBytes)), nil 81 | } 82 | 83 | // ReadInt32 reads a 32-bit signed integer from the io.Reader r in 84 | // big-endian byte order. Note that if an error is encountered when 85 | // reading, it will be returned along with the value 0. An EOF error 86 | // is returned when no bytes could be read; an UnexpectedEOF if some 87 | // bytes were read first. 88 | func ReadInt32(r io.Reader) (int32, error) { 89 | var be [4]byte 90 | valBytes := be[0:4] 91 | if _, err := io.ReadFull(r, valBytes); err != nil { 92 | return 0, err 93 | } 94 | 95 | return int32(binary.BigEndian.Uint32(valBytes)), nil 96 | } 97 | 98 | // ReadUint32 reads a 32-bit unsigned integer from the io.Reader r in 99 | // big-endian byte order. Note that if an error is encountered when 100 | // reading, it will be returned along with the value 0. An EOF error 101 | // is returned when no bytes could be read; an UnexpectedEOF if some 102 | // bytes were read first. 103 | func ReadUint32(r io.Reader) (ret uint32, err error) { 104 | var be [4]byte 105 | valBytes := be[0:4] 106 | if _, err = io.ReadFull(r, valBytes); err != nil { 107 | return 0, err 108 | } 109 | 110 | return binary.BigEndian.Uint32(valBytes), nil 111 | } 112 | 113 | // ReadUint32FromBuffer reads a 32-bit unsigned integer from the 114 | // bytes.Buffer r in big-endian byte order. 115 | func ReadUint32FromBuffer(r *bytes.Buffer) uint32 { 116 | return binary.BigEndian.Uint32(r.Next(4)) 117 | } 118 | 119 | // ReadCString reads a null-terminated string in UTF-8 encoding from 120 | // the io.Reader r. If an error is encountered in decoding, it returns 121 | // an empty string and the error. 122 | func ReadCString(r io.Reader) (s string, err error) { 123 | var be [1]byte 124 | charBuf := be[0:1] 125 | 126 | var accum bytes.Buffer 127 | 128 | for { 129 | n, err := r.Read(charBuf) 130 | 131 | if err != nil { 132 | return "", err 133 | } 134 | 135 | // Handle the case of no error, yet no bytes were 136 | // retrieved. 137 | if n < 1 { 138 | continue 139 | } 140 | 141 | switch charBuf[0] { 142 | case '\000': 143 | return string(accum.Bytes()), nil 144 | default: 145 | accum.Write(charBuf) 146 | } 147 | } 148 | } 149 | 150 | // ReadByte reads a single byte from the io.Reader r. If an error is 151 | // encountered in reading, it returns 0 and the error. 152 | func ReadByte(r io.Reader) (ret byte, err error) { 153 | var be [1]byte 154 | valBytes := be[0:1] 155 | 156 | if _, err = io.ReadFull(r, valBytes); err != nil { 157 | return 0, err 158 | } 159 | 160 | return valBytes[0], nil 161 | } 162 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/buf/pack_buffer.go: -------------------------------------------------------------------------------- 1 | package buf 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | ) 7 | 8 | // Idea: Change this so that the writer can only write infrount of the read pointer once 9 | // but can write anywhere behind the Read pointer since the protocol does not need to have 10 | // seek access... 11 | // Result: not so much... To many edge cases 12 | 13 | // Idea: compacting buffer 14 | 15 | // A Reader implements the io.Reader, io.ReaderAt, io.Seeker, and 16 | // io.ByteScanner interfaces by reading from a byte slice. Unlike a 17 | // Buffer, a Reader is read-only and supports seeking. 18 | 19 | //should probably be int64s 20 | //Should add left counter 21 | type PackBuffer struct { 22 | r int 23 | w int 24 | s []byte 25 | } 26 | 27 | func NewPackBuffer(size int) *PackBuffer { 28 | b := &PackBuffer{0, 0, make([]byte, size, size)} 29 | return b 30 | } 31 | 32 | // re-initializes a reader 33 | func (b *PackBuffer) InitPackBuffer(bin []byte) { 34 | b.r = 0 35 | b.w = 0 36 | b.s = bin 37 | } 38 | 39 | // Like bytes.Buffer.Next 40 | func (b *PackBuffer) Next(n int) []byte { 41 | oldR := b.r 42 | b.r += n 43 | return b.s[oldR:b.r] 44 | } 45 | 46 | // Returns the complete slice underlying the Reader 47 | func (b *PackBuffer) Bytes() []byte { 48 | return b.s 49 | } 50 | 51 | // Len returns the number of bytes of the unread portion of the 52 | // slice. 53 | // Note readLeft now does what this function did... 54 | func (b *PackBuffer) Width() int { 55 | return len(b.s) 56 | } 57 | 58 | //The amount left to be read 59 | func (b *PackBuffer) ReadLen() int { 60 | if b.w >= len(b.s) { 61 | return 0 62 | } 63 | return (b.w - b.r) 64 | } 65 | 66 | //the amount of room left to write before there is no room or buffer needs to be compacted 67 | func (b *PackBuffer) WriteLen() int { 68 | if b.w >= len(b.s) { 69 | return 0 70 | } 71 | return len(b.s) - b.w 72 | } 73 | 74 | func (b *PackBuffer) Read(outB []byte) (n int, err error) { 75 | if len(outB) == 0 { 76 | return 0, nil 77 | } 78 | if b.r >= len(b.s) { 79 | return 0, io.EOF 80 | } 81 | if b.r == b.w { 82 | return 0, io.EOF 83 | } 84 | n = copy(outB, b.s[b.r:b.w]) 85 | b.r += n 86 | return n, nil 87 | } 88 | 89 | //This should not be supported because the data may have been compacted... 90 | func (b *PackBuffer) ReadAt(outB []byte, off int64) (n int, err error) { 91 | if off < 0 { 92 | return 0, errors.New("bytes: invalid offset") 93 | } 94 | if off >= int64(len(b.s)) { 95 | return 0, io.EOF 96 | } 97 | n = copy(outB, b.s[int(off):]) 98 | if n < len(outB) { 99 | err = io.EOF 100 | } 101 | return 102 | } 103 | 104 | func (b *PackBuffer) ReadByte() (outB byte, err error) { 105 | if b.r >= len(b.s) { 106 | return 0, io.EOF 107 | } 108 | outB = b.s[b.r] 109 | b.r++ 110 | return 111 | } 112 | 113 | func (b *PackBuffer) UnreadByte() error { 114 | if b.r <= 0 { 115 | return errors.New("bytes.Reader: at beginning of slice") 116 | } 117 | b.r-- 118 | return nil 119 | } 120 | 121 | // Seek implements the io.Seeker interface. 122 | // This again feels like you don't know if your buffer has been compacted... 123 | func (b *PackBuffer) Seek(offset int64, whence int) (int64, error) { 124 | var abs int64 125 | switch whence { 126 | case 0: 127 | abs = offset 128 | case 1: 129 | abs = int64(b.r) + offset 130 | case 2: 131 | abs = int64(len(b.s)) + offset 132 | default: 133 | return 0, errors.New("bytes: invalid whence") 134 | } 135 | if abs < 0 { 136 | return 0, errors.New("bytes: negative position") 137 | } 138 | if abs >= 1<<31 { 139 | return 0, errors.New("bytes: position out of range") 140 | } 141 | b.r = int(abs) 142 | return abs, nil 143 | } 144 | 145 | //Compacts and sets read and write cursors to where it belongs 146 | func (b *PackBuffer) Compact(squash bool) (err error) { 147 | if squash { 148 | b.r = 0 149 | b.w = 0 150 | } else { 151 | if b.r == b.w { 152 | b.r = 0 153 | b.w = 0 154 | } else { 155 | var temp []byte 156 | count := copy(temp, b.s[b.r:b.w]) 157 | if count == 0 { 158 | return 159 | } 160 | copy(b.s, temp) 161 | b.w = b.r - b.w 162 | b.r = 0 163 | } 164 | } 165 | return 166 | } 167 | 168 | //Writes without compacting if possible, if needed it does, if there is no room 169 | //then it returns an error 170 | func (b *PackBuffer) Write(p []byte) (n int, err error) { 171 | 172 | space := b.WriteLen() 173 | if space < len(p) { 174 | n = copy(b.s[b.w:], p) 175 | b.w = b.w + n 176 | } else { 177 | b.Compact(false) 178 | space = b.WriteLen() 179 | if space > len(p) { 180 | n = copy(b.s[b.w:], p[:]) 181 | } else { 182 | n = copy(b.s[b.w:], p[:space]) 183 | } 184 | } 185 | if n == 0 { 186 | return 0, errors.New("No room left in buffer") 187 | } 188 | return n, nil 189 | } 190 | 191 | func (b *PackBuffer) Close() error { 192 | b.s = nil 193 | return nil 194 | } 195 | 196 | func (b *PackBuffer) ReadPos() int { 197 | return b.r 198 | } 199 | 200 | func (b *PackBuffer) WritePos() int { 201 | return b.w 202 | } 203 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/buf/reader.go: -------------------------------------------------------------------------------- 1 | // The same as the standard Reader, except allowing for no-allocation 2 | // re-initialization, access to the underlying byte slice, and removal 3 | // of all rune manipulation. These alterations bear the copyright 4 | // listed in the accompanying LICENSE file. 5 | // 6 | // Otherwise, the original copyright (referring to the original Go 7 | // LICENSE file) is: 8 | // 9 | // Copyright 2012 The Go Authors. All rights reserved. 10 | // Use of this source code is governed by a BSD-style 11 | // license that can be found in the LICENSE file. 12 | 13 | package buf 14 | 15 | import ( 16 | "errors" 17 | "io" 18 | ) 19 | 20 | // re-initializes a reader 21 | func (r *Reader) InitReader(b []byte) { 22 | r.s = b 23 | r.i = 0 24 | } 25 | 26 | // Like bytes.Buffer.Next 27 | func (r *Reader) Next(n int) []byte { 28 | oldI := r.i 29 | r.i += n 30 | return r.s[oldI:r.i] 31 | } 32 | 33 | // Returns the complete slice underlying the Reader 34 | func (r *Reader) Bytes() []byte { 35 | return r.s 36 | } 37 | 38 | // A Reader implements the io.Reader, io.ReaderAt, io.Seeker, and 39 | // io.ByteScanner interfaces by reading from a byte slice. Unlike a 40 | // Buffer, a Reader is read-only and supports seeking. 41 | type Reader struct { 42 | s []byte 43 | i int // current reading index 44 | } 45 | 46 | // Len returns the number of bytes of the unread portion of the 47 | // slice. 48 | func (r *Reader) Len() int { 49 | if r.i >= len(r.s) { 50 | return 0 51 | } 52 | return len(r.s) - r.i 53 | } 54 | 55 | func (r *Reader) Read(b []byte) (n int, err error) { 56 | if len(b) == 0 { 57 | return 0, nil 58 | } 59 | if r.i >= len(r.s) { 60 | return 0, io.EOF 61 | } 62 | n = copy(b, r.s[r.i:]) 63 | r.i += n 64 | return 65 | } 66 | 67 | func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { 68 | if off < 0 { 69 | return 0, errors.New("bytes: invalid offset") 70 | } 71 | if off >= int64(len(r.s)) { 72 | return 0, io.EOF 73 | } 74 | n = copy(b, r.s[int(off):]) 75 | if n < len(b) { 76 | err = io.EOF 77 | } 78 | return 79 | } 80 | 81 | func (r *Reader) ReadByte() (b byte, err error) { 82 | if r.i >= len(r.s) { 83 | return 0, io.EOF 84 | } 85 | b = r.s[r.i] 86 | r.i++ 87 | return 88 | } 89 | 90 | func (r *Reader) UnreadByte() error { 91 | if r.i <= 0 { 92 | return errors.New("bytes.Reader: at beginning of slice") 93 | } 94 | r.i-- 95 | return nil 96 | } 97 | 98 | // Seek implements the io.Seeker interface. 99 | func (r *Reader) Seek(offset int64, whence int) (int64, error) { 100 | var abs int64 101 | switch whence { 102 | case 0: 103 | abs = offset 104 | case 1: 105 | abs = int64(r.i) + offset 106 | case 2: 107 | abs = int64(len(r.s)) + offset 108 | default: 109 | return 0, errors.New("bytes: invalid whence") 110 | } 111 | if abs < 0 { 112 | return 0, errors.New("bytes: negative position") 113 | } 114 | if abs >= 1<<31 { 115 | return 0, errors.New("bytes: position out of range") 116 | } 117 | r.i = int(abs) 118 | return abs, nil 119 | } 120 | 121 | // NewReader returns a new Reader reading from b. 122 | func NewReader(b []byte) *Reader { return &Reader{b, 0} } 123 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/core/framing.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "github.com/uhoh-itsmaciek/femebe/buf" 7 | "io" 8 | "io/ioutil" 9 | ) 10 | 11 | var ErrTooLarge = errors.New("Message buffering size limit exceeded") 12 | 13 | const MsgTypeFirst = '\000' 14 | 15 | type Message struct { 16 | // Constant-width header 17 | msgType byte 18 | sz uint32 19 | 20 | buffered buf.Reader 21 | union io.Reader 22 | 23 | // The rest of the message yet to be read. 24 | future io.Reader 25 | } 26 | 27 | func (m *Message) MsgType() byte { 28 | return m.msgType 29 | } 30 | 31 | func (m *Message) Payload() io.Reader { 32 | return m.union 33 | } 34 | 35 | func (m *Message) Size() uint32 { 36 | return m.sz 37 | } 38 | 39 | func (m *Message) IsBuffered() bool { 40 | return m.future == nil 41 | } 42 | 43 | func (m *Message) Discard() error { 44 | if m.IsBuffered() { 45 | return nil 46 | } 47 | _, err := io.Copy(ioutil.Discard, m.future) 48 | m.future = nil 49 | return err 50 | } 51 | 52 | func (m *Message) Force() ([]byte, error) { 53 | if m.IsBuffered() { 54 | return m.buffered.Bytes(), nil 55 | } 56 | 57 | payloadSz := m.Size() - 4 58 | curBuf := m.buffered.Bytes() 59 | var payload []byte 60 | 61 | // Try to reuse the buffer if possible 62 | if uint32(cap(curBuf)) >= payloadSz { 63 | payload = curBuf[:payloadSz] 64 | } else { 65 | payload = make([]byte, payloadSz) 66 | } 67 | _, err := io.ReadFull(m.union, payload) 68 | 69 | m.buffered.InitReader(payload) 70 | m.future = nil 71 | 72 | return m.buffered.Bytes(), err 73 | } 74 | 75 | func (m *Message) WriteTo(w io.Writer) (_ int64, err error) { 76 | var bufBack [4]byte 77 | var totalN int64 78 | 79 | if mt := m.MsgType(); mt != MsgTypeFirst { 80 | n, err := w.Write([]byte{mt}) 81 | totalN += int64(n) 82 | if err != nil { 83 | return totalN, err 84 | } 85 | } 86 | 87 | // Write message size integer to the stream 88 | 89 | buf := bufBack[:] 90 | binary.BigEndian.PutUint32(buf, m.Size()) 91 | nMsgSz, err := w.Write(buf) 92 | totalN += int64(nMsgSz) 93 | if err != nil { 94 | return totalN, err 95 | } 96 | 97 | // Write the actual payload 98 | var nPayload int64 99 | 100 | if m.future == nil { 101 | // Fast path for fully buffered messages 102 | var nPayloadSm int 103 | nPayloadSm, err = w.Write(m.buffered.Bytes()) 104 | nPayload = int64(nPayloadSm) 105 | } else { 106 | // Slow generic path 107 | nPayload, err = io.Copy(w, m.Payload()) 108 | } 109 | 110 | totalN += nPayload 111 | return totalN, err 112 | } 113 | 114 | func (m *Message) baseInitMessage(msgType byte, size uint32) { 115 | m.msgType = msgType 116 | m.sz = size 117 | } 118 | 119 | func (m *Message) InitFromBytes(msgType byte, payload []byte) { 120 | m.baseInitMessage(msgType, uint32(len(payload))+4) 121 | m.future = nil 122 | m.buffered.InitReader(payload) 123 | m.union = &m.buffered 124 | } 125 | 126 | func (m *Message) InitPromise(msgType byte, size uint32, 127 | buffered []byte, r io.Reader) { 128 | m.baseInitMessage(msgType, size) 129 | m.buffered.InitReader(buffered) 130 | 131 | remaining := int64(size - 4 - uint32(len(buffered))) 132 | m.future = io.LimitReader(r, remaining) 133 | 134 | m.union = io.MultiReader(&m.buffered, m.future) 135 | } 136 | 137 | func (m *Message) InitFromMessage(src *Message) { 138 | payloadBytes, err := src.Force() 139 | if err != nil { 140 | panic(err) 141 | } 142 | dstBytes := make([]byte, len(payloadBytes), len(payloadBytes)) 143 | copy(dstBytes, payloadBytes) 144 | m.InitFromBytes(src.MsgType(), dstBytes) 145 | } 146 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/error/error.go: -------------------------------------------------------------------------------- 1 | package error 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type ErrTooBig struct { 8 | error 9 | } 10 | 11 | type ErrWrongSize struct { 12 | error 13 | } 14 | 15 | type ErrStartupVersion struct { 16 | error 17 | } 18 | 19 | type ErrStartupFmt struct { 20 | error 21 | } 22 | 23 | type ErrBadTypeCode struct { 24 | error 25 | } 26 | 27 | func TooBig(format string, args ...interface{}) ErrTooBig { 28 | return ErrTooBig{fmt.Errorf(format, args...)} 29 | } 30 | 31 | func WrongSize(format string, args ...interface{}) ErrWrongSize { 32 | return ErrWrongSize{fmt.Errorf(format, args...)} 33 | } 34 | 35 | func StartupVersion(format string, args ...interface{}) ErrStartupVersion { 36 | return ErrStartupVersion{fmt.Errorf(format, args...)} 37 | } 38 | 39 | func StartupFmt(format string, args ...interface{}) ErrStartupFmt { 40 | return ErrStartupFmt{fmt.Errorf(format, args...)} 41 | } 42 | 43 | func BadTypeCode(code byte) ErrBadTypeCode { 44 | return ErrBadTypeCode{fmt.Errorf("Invalid message type %v", code)} 45 | } 46 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/proto/oids.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | // TypSize returns the size in bytes of the Postgres type specified by 4 | // typOid, where undertood by femebe. For variable-length types or if 5 | // the type is not known, -1 is returned. 6 | func TypSize(typOid Oid) int16 { 7 | // TODO: right now, we hardcode the length of the various types 8 | // here; ideally, we should have a mapping for the fixed-length 9 | // types (although it seems that all the dynamic-length types, 10 | // even those with explicit length restrictions, is just -1, so 11 | // perhaps we can provide a mapping for that as well). 12 | switch typOid { 13 | case OidBool: 14 | return 1 15 | case OidInt2: 16 | return 2 17 | case OidInt4, OidFloat4: 18 | return 4 19 | case OidInt8, OidFloat8: 20 | return 8 21 | case OidText: 22 | return -1 23 | default: 24 | // unknown, assume variable length 25 | return -1 26 | } 27 | } 28 | 29 | type Oid uint32 30 | 31 | // The oids of the Postgres built-in types 32 | const ( 33 | // generated via 34 | // psql -qAt -F $'\t' -p 5434 postgres -c 35 | // "select 'OID_' || upper(typname) || '=' || oid from pg_type" 36 | // and pared down 37 | OidBool Oid = 16 38 | OidBytea = 17 39 | OidChar = 18 40 | OidName = 19 41 | OidInt8 = 20 42 | OidInt2 = 21 43 | OidInt2vector = 22 44 | OidInt4 = 23 45 | OidRegproc = 24 46 | OidText = 25 47 | OidOid = 26 48 | OidTid = 27 49 | OidXid = 28 50 | OidCid = 29 51 | OidOidvector = 30 52 | OidPgType = 71 53 | OidPgAttribute = 75 54 | OidPgProc = 81 55 | OidPgClass = 83 56 | OidJson = 114 57 | OidXml = 142 58 | OidSmgr = 210 59 | OidPoint = 600 60 | OidLseg = 601 61 | OidPath = 602 62 | OidBox = 603 63 | OidPolygon = 604 64 | OidLine = 628 65 | OidFloat4 = 700 66 | OidFloat8 = 701 67 | OidAbstime = 702 68 | OidReltime = 703 69 | OidTinterval = 704 70 | OidUnknown = 705 71 | OidCircle = 718 72 | OidMoney = 790 73 | OidMacaddr = 829 74 | OidInet = 869 75 | OidCidr = 650 76 | OidAclitem = 1033 77 | OidBpchar = 1042 78 | OidVarchar = 1043 79 | OidDate = 1082 80 | OidTime = 1083 81 | OidTimestamp = 1114 82 | OidTimestamptz = 1184 83 | OidInterval = 1186 84 | OidTimetz = 1266 85 | OidBit = 1560 86 | OidVarbit = 1562 87 | OidNumeric = 1700 88 | OidRefcursor = 1790 89 | OidRegprocedure = 2202 90 | OidRegoper = 2203 91 | OidRegoperator = 2204 92 | OidRegclass = 2205 93 | OidRegtype = 2206 94 | OidUuid = 2950 95 | OidTsvector = 3614 96 | OidGtsvector = 3642 97 | OidTsquery = 3615 98 | OidRegconfig = 3734 99 | OidRegdictionary = 3769 100 | OidTxidSnapshot = 2970 101 | OidInt4range = 3904 102 | OidNumrange = 3906 103 | OidTsrange = 3908 104 | OidTstzrange = 3910 105 | OidDaterange = 3912 106 | OidInt8range = 3926 107 | OidRecord = 2249 108 | OidCstring = 2275 109 | OidAny = 2276 110 | OidAnyarray = 2277 111 | OidVoid = 2278 112 | OidTrigger = 2279 113 | OidLanguageHandler = 2280 114 | OidInternal = 2281 115 | OidOpaque = 2282 116 | OidAnyelement = 2283 117 | OidAnynonarray = 2776 118 | OidAnyenum = 3500 119 | OidFdwHandler = 3115 120 | OidAnyrange = 3831 121 | ) 122 | -------------------------------------------------------------------------------- /vendor/github.com/uhoh-itsmaciek/femebe/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "bufio" 5 | "crypto/tls" 6 | "errors" 7 | "io" 8 | "net" 9 | "strings" 10 | ) 11 | 12 | // Call fn repeatedly until an error is returned; then send the error 13 | // on the given channel and return 14 | func ErrToChannel(fn func() error, ch chan<- error) { 15 | var err error 16 | for err = fn(); err == nil; err = fn() { 17 | } 18 | ch <- err 19 | } 20 | 21 | // Automatically chooses between unix sockets and tcp sockets for 22 | // listening 23 | func AutoListen(location string) (net.Listener, error) { 24 | if strings.Contains(location, "/") { 25 | return net.Listen("unix", location) 26 | } 27 | return net.Listen("tcp", location) 28 | } 29 | 30 | // Automatically chooses between unix sockets and tcp sockets for 31 | // dialing. 32 | func AutoDial(location string) (net.Conn, error) { 33 | if strings.Contains(location, "/") { 34 | return net.Dial("unix", location) 35 | } 36 | return net.Dial("tcp", location) 37 | } 38 | 39 | // Flush buffers, returning any error encountered 40 | type Flusher interface { 41 | Flush() error 42 | } 43 | 44 | type bufWriteConn struct { 45 | io.ReadCloser 46 | Flusher 47 | io.Writer 48 | } 49 | 50 | func NewBufferedReadWriteCloser(rwc io.ReadWriteCloser) io.ReadWriteCloser { 51 | bw := bufio.NewWriter(rwc) 52 | return &bufWriteConn{rwc, bw, bw} 53 | } 54 | 55 | type SSLMode string 56 | 57 | const ( 58 | SSLDisable SSLMode = "disable" 59 | SSLAllow = "allow" 60 | SSLPrefer = "prefer" 61 | SSLRequire = "require" 62 | ) 63 | 64 | type SSLConfig struct { 65 | Mode SSLMode 66 | Config tls.Config 67 | } 68 | 69 | func NegotiateTLS(c net.Conn, config *SSLConfig) (net.Conn, error) { 70 | sslmode := config.Mode 71 | if sslmode != SSLDisable { 72 | // send an SSLRequest message 73 | // length: int32(8) 74 | // code: int32(80877103) 75 | c.Write([]byte{0x00, 0x00, 0x00, 0x08, 76 | 0x04, 0xd2, 0x16, 0x2f}) 77 | 78 | sslResponse := make([]byte, 1) 79 | bytesRead, err := io.ReadFull(c, sslResponse) 80 | if bytesRead != 1 || err != nil { 81 | return nil, errors.New("Could not read response to SSL Request") 82 | } 83 | 84 | if sslResponse[0] == 'S' { 85 | return tls.Client(c, &config.Config), nil 86 | } else if sslResponse[0] == 'N' && sslmode != SSLAllow && 87 | sslmode != SSLPrefer { 88 | // reject; we require ssl 89 | return nil, errors.New("SSL required but declined by server.") 90 | } else { 91 | return c, nil 92 | } 93 | } 94 | 95 | return c, nil 96 | } 97 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a 2 | ## explicit 3 | github.com/beorn7/perks/quantile 4 | # github.com/golang/protobuf v0.0.0-20161117033126-8ee79997227b 5 | ## explicit 6 | github.com/golang/protobuf/proto 7 | # github.com/johto/notifyutils v0.0.0-20150615093830-a8b71d70b60f 8 | ## explicit 9 | github.com/johto/notifyutils/notifydispatcher 10 | # github.com/lib/pq v0.0.0-20161129221428-4a82388ebc51 11 | ## explicit 12 | github.com/lib/pq 13 | github.com/lib/pq/oid 14 | # github.com/matttproud/golang_protobuf_extensions v1.0.1 15 | ## explicit 16 | github.com/matttproud/golang_protobuf_extensions/pbutil 17 | # github.com/prometheus/client_golang v0.8.1-0.20161124155732-575f371f7862 18 | ## explicit 19 | github.com/prometheus/client_golang/prometheus 20 | github.com/prometheus/client_golang/prometheus/promhttp 21 | # github.com/prometheus/client_model v0.0.0-20150212101744-fa8ad6fec335 22 | ## explicit 23 | github.com/prometheus/client_model/go 24 | # github.com/prometheus/common v0.0.0-20161201123508-195bde7883f7 25 | ## explicit 26 | github.com/prometheus/common/expfmt 27 | github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg 28 | github.com/prometheus/common/model 29 | # github.com/prometheus/procfs v0.0.0-20161206222141-fcdb11ccb438 30 | ## explicit 31 | github.com/prometheus/procfs 32 | # github.com/uhoh-itsmaciek/femebe v0.0.0-20150705092910-78f00f2ef7b4 33 | ## explicit 34 | github.com/uhoh-itsmaciek/femebe/buf 35 | github.com/uhoh-itsmaciek/femebe/core 36 | github.com/uhoh-itsmaciek/femebe/error 37 | github.com/uhoh-itsmaciek/femebe/proto 38 | github.com/uhoh-itsmaciek/femebe/util 39 | --------------------------------------------------------------------------------