├── .gitignore ├── vendor ├── github.com │ ├── matttproud │ │ └── golang_protobuf_extensions │ │ │ ├── NOTICE │ │ │ └── pbutil │ │ │ ├── Makefile │ │ │ ├── doc.go │ │ │ ├── encode.go │ │ │ └── decode.go │ ├── jeffail │ │ └── gabs │ │ │ ├── gabs_logo.png │ │ │ └── LICENSE │ ├── prometheus │ │ ├── procfs │ │ │ ├── Makefile │ │ │ ├── NOTICE │ │ │ ├── README.md │ │ │ ├── AUTHORS.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── fs.go │ │ │ ├── proc_io.go │ │ │ ├── stat.go │ │ │ ├── doc.go │ │ │ ├── mdstat.go │ │ │ └── proc_limits.go │ │ ├── client_model │ │ │ └── NOTICE │ │ ├── common │ │ │ ├── NOTICE │ │ │ ├── model │ │ │ │ ├── model.go │ │ │ │ ├── fnv.go │ │ │ │ ├── metric.go │ │ │ │ ├── fingerprinting.go │ │ │ │ ├── silence.go │ │ │ │ ├── alert.go │ │ │ │ ├── signature.go │ │ │ │ └── labelset.go │ │ │ ├── expfmt │ │ │ │ ├── fuzz.go │ │ │ │ ├── expfmt.go │ │ │ │ └── encode.go │ │ │ ├── internal │ │ │ │ └── bitbucket.org │ │ │ │ │ └── ww │ │ │ │ │ └── goautoneg │ │ │ │ │ ├── README.txt │ │ │ │ │ └── autoneg.go │ │ │ └── log │ │ │ │ └── syslog_formatter.go │ │ └── client_golang │ │ │ ├── prometheus │ │ │ ├── fnv.go │ │ │ ├── README.md │ │ │ ├── push.go │ │ │ ├── collector.go │ │ │ ├── expvar.go │ │ │ └── process_collector.go │ │ │ └── NOTICE │ ├── Sirupsen │ │ └── logrus │ │ │ ├── terminal_bsd.go │ │ │ ├── terminal_solaris.go │ │ │ ├── terminal_linux.go │ │ │ ├── terminal_notwindows.go │ │ │ ├── doc.go │ │ │ ├── terminal_windows.go │ │ │ ├── json_formatter.go │ │ │ ├── LICENSE │ │ │ ├── hooks.go │ │ │ ├── writer.go │ │ │ ├── formatter.go │ │ │ ├── CHANGELOG.md │ │ │ ├── alt_exit.go │ │ │ ├── text_formatter.go │ │ │ └── logrus.go │ ├── donovanhide │ │ └── eventsource │ │ │ ├── README.md │ │ │ ├── normalise.go │ │ │ ├── interface.go │ │ │ ├── repository.go │ │ │ ├── encoder.go │ │ │ ├── decoder.go │ │ │ ├── stream.go │ │ │ └── server.go │ ├── gambol99 │ │ └── go-marathon │ │ │ ├── update_strategy.go │ │ │ ├── last_task_failure.go │ │ │ ├── CONTRIBUTING.md │ │ │ ├── Makefile │ │ │ ├── const.go │ │ │ ├── AUTHORS │ │ │ ├── queue.go │ │ │ ├── port_definition.go │ │ │ ├── config.go │ │ │ ├── health.go │ │ │ ├── info.go │ │ │ ├── utils.go │ │ │ └── CHANGELOG.md │ ├── matt-deboer │ │ └── go-marathon │ │ │ ├── update_strategy.go │ │ │ ├── last_task_failure.go │ │ │ ├── CONTRIBUTING.md │ │ │ ├── Makefile │ │ │ ├── const.go │ │ │ ├── AUTHORS │ │ │ ├── queue.go │ │ │ ├── port_definition.go │ │ │ ├── config.go │ │ │ ├── health.go │ │ │ ├── info.go │ │ │ ├── utils.go │ │ │ └── CHANGELOG.md │ ├── beorn7 │ │ └── perks │ │ │ └── LICENSE │ ├── google │ │ └── go-querystring │ │ │ └── LICENSE │ └── golang │ │ └── protobuf │ │ ├── LICENSE │ │ └── proto │ │ └── Makefile └── vendor.json ├── Dockerfile ├── rename.go ├── Makefile ├── scraper.go ├── LICENSE ├── rename_test.go ├── README.md ├── containers_test.go ├── containers.go ├── main.go └── .travis.yml /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | .history/ -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt T. Proud (matt.proud@gmail.com) 2 | -------------------------------------------------------------------------------- /vendor/github.com/jeffail/gabs/gabs_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/criteo/marathon_exporter/HEAD/vendor/github.com/jeffail/gabs/gabs_logo.png -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/Makefile: -------------------------------------------------------------------------------- 1 | ci: 2 | ! gofmt -l *.go | read nothing 3 | go vet 4 | go test -v ./... 5 | go get github.com/golang/lint/golint 6 | golint *.go 7 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | 3 | cover: 4 | go test -cover -v -coverprofile=cover.dat ./... 5 | go tool cover -func cover.dat 6 | 7 | .PHONY: cover 8 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_model/NOTICE: -------------------------------------------------------------------------------- 1 | Data model artifacts for Prometheus. 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/NOTICE: -------------------------------------------------------------------------------- 1 | Common libraries shared by Prometheus Go components. 2 | Copyright 2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd openbsd netbsd dragonfly 2 | 3 | package logrus 4 | 5 | import "syscall" 6 | 7 | const ioctlReadTermios = syscall.TIOCGETA 8 | 9 | type Termios syscall.Termios 10 | -------------------------------------------------------------------------------- /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/Sirupsen/logrus/terminal_solaris.go: -------------------------------------------------------------------------------- 1 | // +build solaris 2 | 3 | package logrus 4 | 5 | import ( 6 | "os" 7 | 8 | "golang.org/x/sys/unix" 9 | ) 10 | 11 | // IsTerminal returns true if the given file descriptor is a terminal. 12 | func IsTerminal() bool { 13 | _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) 14 | return err == nil 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_linux.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2013 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package logrus 7 | 8 | import "syscall" 9 | 10 | const ioctlReadTermios = syscall.TCGETS 11 | 12 | type Termios syscall.Termios 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.9-alpine3.7 as builder 2 | RUN apk add --update \ 3 | make \ 4 | git \ 5 | && rm -rf /var/cache/apk/* 6 | RUN mkdir -p /go/src/github.com/gettyimages/marathon_exporter 7 | ADD . /go/src/github.com/gettyimages/marathon_exporter 8 | WORKDIR /go/src/github.com/gettyimages/marathon_exporter 9 | RUN make build 10 | 11 | FROM alpine:3.7 12 | 13 | COPY --from=builder /go/src/github.com/gettyimages/marathon_exporter/bin/marathon_exporter /marathon_exporter 14 | ENTRYPOINT ["/marathon_exporter"] 15 | 16 | EXPOSE 9088 17 | -------------------------------------------------------------------------------- /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/donovanhide/eventsource/README.md: -------------------------------------------------------------------------------- 1 | # Eventsource 2 | 3 | Eventsource implements a [Go](http://golang.org/) implementation of client and server to allow streaming data one-way over a HTTP connection using the Server-Sent Events API http://dev.w3.org/html5/eventsource/ 4 | 5 | ## Installation 6 | 7 | go get github.com/donovanhide/eventsource 8 | 9 | ## Documentation 10 | 11 | * [Reference](http://godoc.org/github.com/donovanhide/eventsource) 12 | 13 | ## License 14 | 15 | Eventsource is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). 16 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_notwindows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build linux darwin freebsd openbsd netbsd dragonfly 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | // IsTerminal returns true if stderr's file descriptor is a terminal. 16 | func IsTerminal() bool { 17 | fd := syscall.Stderr 18 | var termios Termios 19 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 20 | return err == 0 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package logrus is a structured logger for Go, completely API compatible with the standard library logger. 3 | 4 | 5 | The simplest way to use Logrus is simply the package-level exported logger: 6 | 7 | package main 8 | 9 | import ( 10 | log "github.com/Sirupsen/logrus" 11 | ) 12 | 13 | func main() { 14 | log.WithFields(log.Fields{ 15 | "animal": "walrus", 16 | "number": 1, 17 | "size": 10, 18 | }).Info("A walrus appears") 19 | } 20 | 21 | Output: 22 | time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 23 | 24 | For a full guide visit https://github.com/Sirupsen/logrus 25 | */ 26 | package logrus 27 | -------------------------------------------------------------------------------- /rename.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "strings" 4 | 5 | func renameRate(originalRate string) (name string) { 6 | switch originalRate { 7 | case "m1_rate": 8 | name = "1m" 9 | case "m5_rate": 10 | name = "5m" 11 | case "m15_rate": 12 | name = "15m" 13 | default: 14 | name = strings.TrimSuffix(originalRate, "_rate") 15 | } 16 | return 17 | } 18 | 19 | func renameMetric(originalName string) (name string) { 20 | name = strings.ToLower(originalName) 21 | name = strings.Replace(name, ".", "_", -1) 22 | name = strings.Replace(name, "-", "_", -1) 23 | name = strings.Replace(name, "$", "_", -1) 24 | name = strings.Replace(name, "(", "_", -1) 25 | name = strings.Replace(name, ")", "_", -1) 26 | name = strings.TrimRight(name, "_") 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /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 | * Matthias Rampke 18 | * Nicky Gerritsen 19 | * Rémi Audebert 20 | * Tobias Schmidt 21 | -------------------------------------------------------------------------------- /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/Sirupsen/logrus/terminal_windows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build windows 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 16 | 17 | var ( 18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 19 | ) 20 | 21 | // IsTerminal returns true if stderr's file descriptor is a terminal. 22 | func IsTerminal() bool { 23 | fd := syscall.Stderr 24 | var st uint32 25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 26 | return r != 0 && e == 0 27 | } 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION := $$(git describe --tags --always) 2 | TARGET := marathon_exporter 3 | TEST ?= ./... 4 | 5 | default: test build 6 | 7 | test: 8 | go test -v -run=$(RUN) $(TEST) 9 | 10 | build: clean 11 | CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build \ 12 | -a -tags netgo \ 13 | -ldflags "-X main.Version=$(VERSION)" \ 14 | -o bin/$(TARGET) . 15 | 16 | release: build 17 | docker build -t gettyimages/$(TARGET):$(VERSION) . 18 | 19 | publish: release 20 | docker push gettyimages/$(TARGET):$(VERSION) 21 | docker tag gettyimages/$(TARGET):$(VERSION) gettyimages/$(TARGET):latest 22 | docker push gettyimages/$(TARGET):latest 23 | 24 | clean: 25 | rm -rf bin/ 26 | 27 | image: 28 | docker build -t $(TARGET) . 29 | 30 | shell: 31 | docker run -it --entrypoint /bin/ash $(TARGET) 32 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/normalise.go: -------------------------------------------------------------------------------- 1 | package eventsource 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // A reader which normalises line endings 8 | // "/r" and "/r/n" are converted to "/n" 9 | type normaliser struct { 10 | r io.Reader 11 | lastChar byte 12 | } 13 | 14 | func newNormaliser(r io.Reader) *normaliser { 15 | return &normaliser{r: r} 16 | } 17 | 18 | func (norm *normaliser) Read(p []byte) (n int, err error) { 19 | n, err = norm.r.Read(p) 20 | for i := 0; i < n; i++ { 21 | switch { 22 | case p[i] == '\n' && norm.lastChar == '\r': 23 | copy(p[i:n], p[i+1:]) 24 | norm.lastChar = p[i] 25 | n-- 26 | i-- 27 | case p[i] == '\r': 28 | norm.lastChar = p[i] 29 | p[i] = '\n' 30 | default: 31 | norm.lastChar = p[i] 32 | } 33 | } 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package pbutil provides record length-delimited Protocol Buffer streaming. 16 | package pbutil 17 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/model.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package model contains common data structures that are shared across 15 | // Prometheus components and libraries. 16 | package model 17 | -------------------------------------------------------------------------------- /scraper.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "io/ioutil" 7 | "net" 8 | "net/http" 9 | "net/url" 10 | "time" 11 | ) 12 | 13 | type Scraper interface { 14 | Scrape(path string) ([]byte, error) 15 | } 16 | 17 | type scraper struct { 18 | uri *url.URL 19 | } 20 | 21 | func (s *scraper) Scrape(path string) ([]byte, error) { 22 | client := &http.Client{ 23 | Timeout: 10 * time.Second, 24 | Transport: &http.Transport{ 25 | Dial: (&net.Dialer{ 26 | Timeout: 10 * time.Second, 27 | }).Dial, 28 | TLSClientConfig: &tls.Config{ 29 | InsecureSkipVerify: true, 30 | }, 31 | }, 32 | } 33 | 34 | response, err := client.Get(fmt.Sprintf("%v/%s", s.uri, path)) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | defer response.Body.Close() 40 | body, err := ioutil.ReadAll(response.Body) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | return body, err 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/update_strategy.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // UpgradeStrategy is upgrade strategy applied to a application 20 | type UpgradeStrategy struct { 21 | MinimumHealthCapacity float64 `json:"minimumHealthCapacity"` 22 | MaximumOverCapacity float64 `json:"maximumOverCapacity"` 23 | } 24 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/update_strategy.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // UpgradeStrategy is upgrade strategy applied to a application 20 | type UpgradeStrategy struct { 21 | MinimumHealthCapacity float64 `json:"minimumHealthCapacity"` 22 | MaximumOverCapacity float64 `json:"maximumOverCapacity"` 23 | } 24 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Prometheus uses GitHub to manage reviews of pull requests. 4 | 5 | * If you have a trivial fix or improvement, go ahead and create a pull 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/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/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 | goautoneg 11 | http://bitbucket.org/ww/goautoneg 12 | Copyright 2011, Open Knowledge Foundation Ltd. 13 | See README.txt for license details. 14 | 15 | perks - a fork of https://github.com/bmizerany/perks 16 | https://github.com/beorn7/perks 17 | Copyright 2013-2015 Blake Mizerany, Björn Rabenstein 18 | See https://github.com/beorn7/perks/blob/master/README.md for license details. 19 | 20 | Go support for Protocol Buffers - Google's data interchange format 21 | http://github.com/golang/protobuf/ 22 | Copyright 2010 The Go Authors 23 | See source code for license details. 24 | 25 | Support for streaming Protocol Buffer messages for the Go language (golang). 26 | https://github.com/matttproud/golang_protobuf_extensions 27 | Copyright 2013 Matt T. Proud 28 | Licensed under the Apache License, Version 2.0 29 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/last_task_failure.go: -------------------------------------------------------------------------------- 1 | /* 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 | 16 | package marathon 17 | 18 | // LastTaskFailure provides details on the last error experienced by an application 19 | type LastTaskFailure struct { 20 | AppID string `json:"appId,omitempty"` 21 | Host string `json:"host,omitempty"` 22 | Message string `json:"message,omitempty"` 23 | State string `json:"state,omitempty"` 24 | TaskID string `json:"taskId,omitempty"` 25 | Timestamp string `json:"timestamp,omitempty"` 26 | Version string `json:"version,omitempty"` 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/last_task_failure.go: -------------------------------------------------------------------------------- 1 | /* 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 | 16 | package marathon 17 | 18 | // LastTaskFailure provides details on the last error experienced by an application 19 | type LastTaskFailure struct { 20 | AppID string `json:"appId,omitempty"` 21 | Host string `json:"host,omitempty"` 22 | Message string `json:"message,omitempty"` 23 | State string `json:"state,omitempty"` 24 | TaskID string `json:"taskId,omitempty"` 25 | Timestamp string `json:"timestamp,omitempty"` 26 | Version string `json:"version,omitempty"` 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Dylan Meissner 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/jeffail/gabs/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Ashley Jeffs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/json_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type JSONFormatter struct { 9 | // TimestampFormat sets the format used for marshaling timestamps. 10 | TimestampFormat string 11 | } 12 | 13 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { 14 | data := make(Fields, len(entry.Data)+3) 15 | for k, v := range entry.Data { 16 | switch v := v.(type) { 17 | case error: 18 | // Otherwise errors are ignored by `encoding/json` 19 | // https://github.com/Sirupsen/logrus/issues/137 20 | data[k] = v.Error() 21 | default: 22 | data[k] = v 23 | } 24 | } 25 | prefixFieldClashes(data) 26 | 27 | timestampFormat := f.TimestampFormat 28 | if timestampFormat == "" { 29 | timestampFormat = DefaultTimestampFormat 30 | } 31 | 32 | data["time"] = entry.Time.Format(timestampFormat) 33 | data["msg"] = entry.Message 34 | data["level"] = entry.Level.String() 35 | 36 | serialized, err := json.Marshal(data) 37 | if err != nil { 38 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 39 | } 40 | return append(serialized, '\n'), nil 41 | } 42 | -------------------------------------------------------------------------------- /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/Sirupsen/logrus/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Simon Eskildsen 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/gambol99/go-marathon/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | ## Pre-Development 4 | - Look for an existing Github issue describing the bug you have found/feature request you would like to see getting implemented. 5 | - If no issue exists and there is reason to believe that your (non-trivial) contribution might be subject to an up-front design discussion, file an issue first and propose your idea. 6 | 7 | ## Development 8 | - Fork the repository. 9 | - Create a feature branch (`git checkout -b my-new-feature master`). 10 | - Commit your changes, preferring one commit per logical unit of work. Often times, this simply means having a single commit. 11 | - If applicable, update the documentation in the [README file](README.md). 12 | - In the vast majority of cases, you should add/amend a (regression) test for your bug fix/feature. 13 | - Push your branch (`git push origin my-new-feature`). 14 | - Create a new pull request. 15 | - Address any comments your reviewer raises, pushing additional commits onto your branch along the way. In particular, refrain from amending/force-pushing until you receive an LGTM (Looks Good To Me) from your reviewer. This will allow for a better review experience. 16 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | ## Pre-Development 4 | - Look for an existing Github issue describing the bug you have found/feature request you would like to see getting implemented. 5 | - If no issue exists and there is reason to believe that your (non-trivial) contribution might be subject to an up-front design discussion, file an issue first and propose your idea. 6 | 7 | ## Development 8 | - Fork the repository. 9 | - Create a feature branch (`git checkout -b my-new-feature master`). 10 | - Commit your changes, preferring one commit per logical unit of work. Often times, this simply means having a single commit. 11 | - If applicable, update the documentation in the [README file](README.md). 12 | - In the vast majority of cases, you should add/amend a (regression) test for your bug fix/feature. 13 | - Push your branch (`git push origin my-new-feature`). 14 | - Create a new pull request. 15 | - Address any comments your reviewer raises, pushing additional commits onto your branch along the way. In particular, refrain from amending/force-pushing until you receive an LGTM (Looks Good To Me) from your reviewer. This will allow for a better review experience. 16 | -------------------------------------------------------------------------------- /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/Sirupsen/logrus/hooks.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // A hook to be fired when logging on the logging levels returned from 4 | // `Levels()` on your implementation of the interface. Note that this is not 5 | // fired in a goroutine or a channel with workers, you should handle such 6 | // functionality yourself if your call is non-blocking and you don't wish for 7 | // the logging calls for levels returned from `Levels()` to block. 8 | type Hook interface { 9 | Levels() []Level 10 | Fire(*Entry) error 11 | } 12 | 13 | // Internal type for storing the hooks on a logger instance. 14 | type LevelHooks map[Level][]Hook 15 | 16 | // Add a hook to an instance of logger. This is called with 17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. 18 | func (hooks LevelHooks) Add(hook Hook) { 19 | for _, level := range hook.Levels() { 20 | hooks[level] = append(hooks[level], hook) 21 | } 22 | } 23 | 24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire 25 | // appropriate hooks for a log entry. 26 | func (hooks LevelHooks) Fire(level Level, entry *Entry) error { 27 | for _, hook := range hooks[level] { 28 | if err := hook.Fire(entry); err != nil { 29 | return err 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/interface.go: -------------------------------------------------------------------------------- 1 | // Package eventsource implements a client and server to allow streaming data one-way over a HTTP connection 2 | // using the Server-Sent Events API http://dev.w3.org/html5/eventsource/ 3 | // 4 | // The client and server respect the Last-Event-ID header. 5 | // If the Repository interface is implemented on the server, events can be replayed in case of a network disconnection. 6 | package eventsource 7 | 8 | // Any event received by the client or sent by the server will implement this interface 9 | type Event interface { 10 | // Id is an identifier that can be used to allow a client to replay 11 | // missed Events by returning the Last-Event-Id header. 12 | // Return empty string if not required. 13 | Id() string 14 | // The name of the event. Return empty string if not required. 15 | Event() string 16 | // The payload of the event. 17 | Data() string 18 | } 19 | 20 | // If history is required, this interface will allow clients to reply previous events through the server. 21 | // Both methods can be called from different goroutines concurrently, so you must make sure they are go-routine safe. 22 | type Repository interface { 23 | // Gets the Events which should follow on from the specified channel and event id. 24 | Replay(channel, id string) chan Event 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/writer.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "runtime" 7 | ) 8 | 9 | func (logger *Logger) Writer() *io.PipeWriter { 10 | return logger.WriterLevel(InfoLevel) 11 | } 12 | 13 | func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { 14 | reader, writer := io.Pipe() 15 | 16 | var printFunc func(args ...interface{}) 17 | switch level { 18 | case DebugLevel: 19 | printFunc = logger.Debug 20 | case InfoLevel: 21 | printFunc = logger.Info 22 | case WarnLevel: 23 | printFunc = logger.Warn 24 | case ErrorLevel: 25 | printFunc = logger.Error 26 | case FatalLevel: 27 | printFunc = logger.Fatal 28 | case PanicLevel: 29 | printFunc = logger.Panic 30 | default: 31 | printFunc = logger.Print 32 | } 33 | 34 | go logger.writerScanner(reader, printFunc) 35 | runtime.SetFinalizer(writer, writerFinalizer) 36 | 37 | return writer 38 | } 39 | 40 | func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { 41 | scanner := bufio.NewScanner(reader) 42 | for scanner.Scan() { 43 | printFunc(scanner.Text()) 44 | } 45 | if err := scanner.Err(); err != nil { 46 | logger.Errorf("Error while reading from Writer: %s", err) 47 | } 48 | reader.Close() 49 | } 50 | 51 | func writerFinalizer(writer *io.PipeWriter) { 52 | writer.Close() 53 | } 54 | -------------------------------------------------------------------------------- /rename_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test_rename_metric(t *testing.T) { 6 | cases := []struct { 7 | name string 8 | expect string 9 | }{ 10 | { 11 | name: "Foo", 12 | expect: "foo", 13 | }, { 14 | name: "foo_bar", 15 | expect: "foo_bar", 16 | }, { 17 | name: "foo.bar", 18 | expect: "foo_bar", 19 | }, { 20 | name: "foo-bar", 21 | expect: "foo_bar", 22 | }, { 23 | name: "foo$bar", 24 | expect: "foo_bar", 25 | }, { 26 | name: "foo(bar)", 27 | expect: "foo_bar", 28 | }, 29 | } 30 | 31 | for _, c := range cases { 32 | name := renameMetric(c.name) 33 | if name != c.expect { 34 | t.Errorf("expected metric named %s, got %s", c.expect, name) 35 | } 36 | } 37 | } 38 | 39 | func Test_rename_rate(t *testing.T) { 40 | cases := []struct { 41 | name string 42 | expect string 43 | }{ 44 | { 45 | name: "mean_rate", 46 | expect: "mean", 47 | }, { 48 | name: "m1_rate", 49 | expect: "1m", 50 | }, { 51 | name: "m5_rate", 52 | expect: "5m", 53 | }, { 54 | name: "m15_rate", 55 | expect: "15m", 56 | }, { 57 | name: "foo", 58 | expect: "foo", 59 | }, 60 | } 61 | 62 | for _, c := range cases { 63 | name := renameRate(c.name) 64 | if name != c.expect { 65 | t.Errorf("expected rate named %s, got %s", c.expect, name) 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fnv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | // Inline and byte-free variant of hash/fnv's fnv64a. 17 | 18 | const ( 19 | offset64 = 14695981039346656037 20 | prime64 = 1099511628211 21 | ) 22 | 23 | // hashNew initializies a new fnv64a hash value. 24 | func hashNew() uint64 { 25 | return offset64 26 | } 27 | 28 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 29 | func hashAdd(h uint64, s string) uint64 { 30 | for i := 0; i < len(s); i++ { 31 | h ^= uint64(s[i]) 32 | h *= prime64 33 | } 34 | return h 35 | } 36 | 37 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 38 | func hashAddByte(h uint64, b byte) uint64 { 39 | h ^= uint64(b) 40 | h *= prime64 41 | return h 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_io.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | ) 8 | 9 | // ProcIO models the content of /proc//io. 10 | type ProcIO struct { 11 | // Chars read. 12 | RChar uint64 13 | // Chars written. 14 | WChar uint64 15 | // Read syscalls. 16 | SyscR uint64 17 | // Write syscalls. 18 | SyscW uint64 19 | // Bytes read. 20 | ReadBytes uint64 21 | // Bytes written. 22 | WriteBytes uint64 23 | // Bytes written, but taking into account truncation. See 24 | // Documentation/filesystems/proc.txt in the kernel sources for 25 | // detailed explanation. 26 | CancelledWriteBytes int64 27 | } 28 | 29 | // NewIO creates a new ProcIO instance from a given Proc instance. 30 | func (p Proc) NewIO() (ProcIO, error) { 31 | pio := ProcIO{} 32 | 33 | f, err := os.Open(p.path("io")) 34 | if err != nil { 35 | return pio, err 36 | } 37 | defer f.Close() 38 | 39 | data, err := ioutil.ReadAll(f) 40 | if err != nil { 41 | return pio, err 42 | } 43 | 44 | ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + 45 | "read_bytes: %d\nwrite_bytes: %d\n" + 46 | "cancelled_write_bytes: %d\n" 47 | 48 | _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, 49 | &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) 50 | if err != nil { 51 | return pio, err 52 | } 53 | 54 | return pio, nil 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/repository.go: -------------------------------------------------------------------------------- 1 | package eventsource 2 | 3 | import ( 4 | "sort" 5 | "sync" 6 | ) 7 | 8 | // Example repository that uses a slice as storage for past events. 9 | type SliceRepository struct { 10 | events map[string][]Event 11 | lock sync.RWMutex 12 | } 13 | 14 | func NewSliceRepository() *SliceRepository { 15 | return &SliceRepository{ 16 | events: make(map[string][]Event), 17 | } 18 | } 19 | 20 | func (repo SliceRepository) indexOfEvent(channel, id string) int { 21 | return sort.Search(len(repo.events[channel]), func(i int) bool { 22 | return repo.events[channel][i].Id() >= id 23 | }) 24 | } 25 | 26 | func (repo SliceRepository) Replay(channel, id string) (out chan Event) { 27 | out = make(chan Event) 28 | go func() { 29 | defer close(out) 30 | repo.lock.RLock() 31 | defer repo.lock.RUnlock() 32 | events := repo.events[channel][repo.indexOfEvent(channel, id):] 33 | for i := range events { 34 | out <- events[i] 35 | } 36 | }() 37 | return 38 | } 39 | 40 | func (repo *SliceRepository) Add(channel string, event Event) { 41 | repo.lock.Lock() 42 | defer repo.lock.Unlock() 43 | i := repo.indexOfEvent(channel, event.Id()) 44 | if i < len(repo.events[channel]) && repo.events[channel][i].Id() == event.Id() { 45 | repo.events[channel][i] = event 46 | } else { 47 | repo.events[channel] = append(repo.events[channel][:i], append([]Event{event}, repo.events[channel][i:]...)...) 48 | } 49 | return 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/stat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // Stat represents kernel/system statistics. 12 | type Stat struct { 13 | // Boot time in seconds since the Epoch. 14 | BootTime int64 15 | } 16 | 17 | // NewStat returns kernel/system statistics read from /proc/stat. 18 | func NewStat() (Stat, error) { 19 | fs, err := NewFS(DefaultMountPoint) 20 | if err != nil { 21 | return Stat{}, err 22 | } 23 | 24 | return fs.NewStat() 25 | } 26 | 27 | // NewStat returns an information about current kernel/system statistics. 28 | func (fs FS) NewStat() (Stat, error) { 29 | f, err := os.Open(fs.Path("stat")) 30 | if err != nil { 31 | return Stat{}, err 32 | } 33 | defer f.Close() 34 | 35 | s := bufio.NewScanner(f) 36 | for s.Scan() { 37 | line := s.Text() 38 | if !strings.HasPrefix(line, "btime") { 39 | continue 40 | } 41 | fields := strings.Fields(line) 42 | if len(fields) != 2 { 43 | return Stat{}, fmt.Errorf("couldn't parse %s line %s", f.Name(), line) 44 | } 45 | i, err := strconv.ParseInt(fields[1], 10, 32) 46 | if err != nil { 47 | return Stat{}, fmt.Errorf("couldn't parse %s: %s", fields[1], err) 48 | } 49 | return Stat{BootTime: i}, nil 50 | } 51 | if err := s.Err(); err != nil { 52 | return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err) 53 | } 54 | 55 | return Stat{}, fmt.Errorf("couldn't parse %s, missing btime", f.Name()) 56 | } 57 | -------------------------------------------------------------------------------- /vendor/github.com/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/client_golang/prometheus/README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | This is the [Prometheus](http://www.prometheus.io) telemetric 3 | instrumentation client [Go](http://golang.org) client library. It 4 | enable authors to define process-space metrics for their servers and 5 | expose them through a web service interface for extraction, 6 | aggregation, and a whole slew of other post processing techniques. 7 | 8 | # Installing 9 | $ go get github.com/prometheus/client_golang/prometheus 10 | 11 | # Example 12 | ```go 13 | package main 14 | 15 | import ( 16 | "net/http" 17 | 18 | "github.com/prometheus/client_golang/prometheus" 19 | ) 20 | 21 | var ( 22 | indexed = prometheus.NewCounter(prometheus.CounterOpts{ 23 | Namespace: "my_company", 24 | Subsystem: "indexer", 25 | Name: "documents_indexed", 26 | Help: "The number of documents indexed.", 27 | }) 28 | size = prometheus.NewGauge(prometheus.GaugeOpts{ 29 | Namespace: "my_company", 30 | Subsystem: "storage", 31 | Name: "documents_total_size_bytes", 32 | Help: "The total size of all documents in the storage.", 33 | }) 34 | ) 35 | 36 | func main() { 37 | http.Handle("/metrics", prometheus.Handler()) 38 | 39 | indexed.Inc() 40 | size.Set(5) 41 | 42 | http.ListenAndServe(":8080", nil) 43 | } 44 | 45 | func init() { 46 | prometheus.MustRegister(indexed) 47 | prometheus.MustRegister(size) 48 | } 49 | ``` 50 | 51 | # Documentation 52 | 53 | [![GoDoc](https://godoc.org/github.com/prometheus/client_golang?status.png)](https://godoc.org/github.com/prometheus/client_golang) 54 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import "time" 4 | 5 | const DefaultTimestampFormat = time.RFC3339 6 | 7 | // The Formatter interface is used to implement a custom Formatter. It takes an 8 | // `Entry`. It exposes all the fields, including the default ones: 9 | // 10 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. 11 | // * `entry.Data["time"]`. The timestamp. 12 | // * `entry.Data["level"]. The level the entry was logged at. 13 | // 14 | // Any additional fields added with `WithField` or `WithFields` are also in 15 | // `entry.Data`. Format is expected to return an array of bytes which are then 16 | // logged to `logger.Out`. 17 | type Formatter interface { 18 | Format(*Entry) ([]byte, error) 19 | } 20 | 21 | // This is to not silently overwrite `time`, `msg` and `level` fields when 22 | // dumping it. If this code wasn't there doing: 23 | // 24 | // logrus.WithField("level", 1).Info("hello") 25 | // 26 | // Would just silently drop the user provided level. Instead with this code 27 | // it'll logged as: 28 | // 29 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} 30 | // 31 | // It's not exported because it's still using Data in an opinionated way. It's to 32 | // avoid code duplication between the two default formatters. 33 | func prefixFieldClashes(data Fields) { 34 | if t, ok := data["time"]; ok { 35 | data["fields.time"] = t 36 | } 37 | 38 | if m, ok := data["msg"]; ok { 39 | data["fields.msg"] = m 40 | } 41 | 42 | if l, ok := data["level"]; ok { 43 | data["fields.level"] = l 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Author: Rohith (gambol99@gmail.com) 3 | # Date: 2015-02-10 15:35:14 +0000 (Tue, 10 Feb 2015) 4 | # 5 | # vim:ts=2:sw=2:et 6 | # 7 | HARDWARE=$(shell uname -m) 8 | VERSION=$(shell awk '/const Version/ { print $$4 }' version.go | sed 's/"//g') 9 | DEPS=$(shell go list -f '{{range .TestImports}}{{.}} {{end}}' ./...) 10 | PACKAGES=$(shell go list ./...) 11 | VETARGS?=-asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -structtags -unsafeptr 12 | 13 | .PHONY: test examples authors changelog 14 | 15 | build: 16 | go build 17 | 18 | authors: 19 | git log --format='%aN <%aE>' | sort -u > AUTHORS 20 | 21 | deps: 22 | @echo "--> Installing build dependencies" 23 | @go get -d -v ./... $(DEPS) 24 | 25 | lint: 26 | @echo "--> Running golint" 27 | @which golint 2>/dev/null ; if [ $$? -eq 1 ]; then \ 28 | go get -u github.com/golang/lint/golint; \ 29 | fi 30 | @golint . 31 | 32 | vet: 33 | @echo "--> Running go tool vet $(VETARGS) ." 34 | @go tool vet 2>/dev/null ; if [ $$? -eq 3 ]; then \ 35 | go get golang.org/x/tools/cmd/vet; \ 36 | fi 37 | @go tool vet $(VETARGS) . 38 | 39 | cover: 40 | @echo "--> Running go test --cover" 41 | @go test --cover 42 | 43 | format: 44 | @echo "--> Running go fmt" 45 | @go fmt $(PACKAGES) 46 | 47 | test: deps 48 | @echo "--> Running go tests" 49 | @go test -v 50 | @$(MAKE) vet 51 | @$(MAKE) cover 52 | 53 | examples: 54 | make -C examples all 55 | 56 | changelog: release 57 | git log $(shell git tag | tail -n1)..HEAD --no-merges --format=%B > changelog 58 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Author: Rohith (gambol99@gmail.com) 3 | # Date: 2015-02-10 15:35:14 +0000 (Tue, 10 Feb 2015) 4 | # 5 | # vim:ts=2:sw=2:et 6 | # 7 | HARDWARE=$(shell uname -m) 8 | VERSION=$(shell awk '/const Version/ { print $$4 }' version.go | sed 's/"//g') 9 | DEPS=$(shell go list -f '{{range .TestImports}}{{.}} {{end}}' ./...) 10 | PACKAGES=$(shell go list ./...) 11 | VETARGS?=-asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -structtags -unsafeptr 12 | 13 | .PHONY: test examples authors changelog 14 | 15 | build: 16 | go build 17 | 18 | authors: 19 | git log --format='%aN <%aE>' | sort -u > AUTHORS 20 | 21 | deps: 22 | @echo "--> Installing build dependencies" 23 | @go get -d -v ./... $(DEPS) 24 | 25 | lint: 26 | @echo "--> Running golint" 27 | @which golint 2>/dev/null ; if [ $$? -eq 1 ]; then \ 28 | go get -u github.com/golang/lint/golint; \ 29 | fi 30 | @golint . 31 | 32 | vet: 33 | @echo "--> Running go tool vet $(VETARGS) ." 34 | @go tool vet 2>/dev/null ; if [ $$? -eq 3 ]; then \ 35 | go get golang.org/x/tools/cmd/vet; \ 36 | fi 37 | @go tool vet $(VETARGS) . 38 | 39 | cover: 40 | @echo "--> Running go test --cover" 41 | @go test --cover 42 | 43 | format: 44 | @echo "--> Running go fmt" 45 | @go fmt $(PACKAGES) 46 | 47 | test: deps 48 | @echo "--> Running go tests" 49 | @go test -v 50 | @$(MAKE) vet 51 | @$(MAKE) cover 52 | 53 | examples: 54 | make -C examples all 55 | 56 | changelog: release 57 | git log $(shell git tag | tail -n1)..HEAD --no-merges --format=%B > changelog 58 | -------------------------------------------------------------------------------- /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 | // fmtJSON2 is hidden as it is deprecated. 34 | fmtJSON2 Format = `application/json; version=0.0.2` 35 | ) 36 | 37 | const ( 38 | hdrContentType = "Content-Type" 39 | hdrAccept = "Accept" 40 | ) 41 | -------------------------------------------------------------------------------- /vendor/github.com/google/go-querystring/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Google. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/encoder.go: -------------------------------------------------------------------------------- 1 | package eventsource 2 | 3 | import ( 4 | "compress/gzip" 5 | "fmt" 6 | "io" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | encFields = []struct { 12 | prefix string 13 | value func(Event) string 14 | }{ 15 | {"id: ", Event.Id}, 16 | {"event: ", Event.Event}, 17 | {"data: ", Event.Data}, 18 | } 19 | ) 20 | 21 | // An Encoder is capable of writing Events to a stream. Optionally 22 | // Events can be gzip compressed in this process. 23 | type Encoder struct { 24 | w io.Writer 25 | compressed bool 26 | } 27 | 28 | // NewEncoder returns an Encoder for a given io.Writer. 29 | // When compressed is set to true, a gzip writer will be 30 | // created. 31 | func NewEncoder(w io.Writer, compressed bool) *Encoder { 32 | if compressed { 33 | return &Encoder{w: gzip.NewWriter(w), compressed: true} 34 | } 35 | return &Encoder{w: w} 36 | } 37 | 38 | // Encode writes an event in the format specified by the 39 | // server-sent events protocol. 40 | func (enc *Encoder) Encode(ev Event) error { 41 | for _, field := range encFields { 42 | prefix, value := field.prefix, field.value(ev) 43 | if len(value) == 0 { 44 | continue 45 | } 46 | value = strings.Replace(value, "\n", "\n"+prefix, -1) 47 | if _, err := io.WriteString(enc.w, prefix+value+"\n"); err != nil { 48 | return fmt.Errorf("eventsource encode: %v", err) 49 | } 50 | } 51 | if _, err := io.WriteString(enc.w, "\n"); err != nil { 52 | return fmt.Errorf("eventsource encode: %v", err) 53 | } 54 | if enc.compressed { 55 | return enc.w.(*gzip.Writer).Flush() 56 | } 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/const.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | const ( 20 | defaultEventsURL = "/event" 21 | 22 | /* --- api related constants --- */ 23 | marathonAPIVersion = "v2" 24 | marathonAPIEventStream = marathonAPIVersion + "/events" 25 | marathonAPISubscription = marathonAPIVersion + "/eventSubscriptions" 26 | marathonAPIApps = marathonAPIVersion + "/apps" 27 | marathonAPITasks = marathonAPIVersion + "/tasks" 28 | marathonAPIDeployments = marathonAPIVersion + "/deployments" 29 | marathonAPIGroups = marathonAPIVersion + "/groups" 30 | marathonAPIQueue = marathonAPIVersion + "/queue" 31 | marathonAPIInfo = marathonAPIVersion + "/info" 32 | marathonAPILeader = marathonAPIVersion + "/leader" 33 | marathonAPIPing = "ping" 34 | ) 35 | 36 | const ( 37 | // EventsTransportCallback activates callback events transport 38 | EventsTransportCallback EventsTransport = 1 << iota 39 | 40 | // EventsTransportSSE activates stream events transport 41 | EventsTransportSSE 42 | ) 43 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/const.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | const ( 20 | defaultEventsURL = "/event" 21 | 22 | /* --- api related constants --- */ 23 | marathonAPIVersion = "v2" 24 | marathonAPIEventStream = marathonAPIVersion + "/events" 25 | marathonAPISubscription = marathonAPIVersion + "/eventSubscriptions" 26 | marathonAPIApps = marathonAPIVersion + "/apps" 27 | marathonAPITasks = marathonAPIVersion + "/tasks" 28 | marathonAPIDeployments = marathonAPIVersion + "/deployments" 29 | marathonAPIGroups = marathonAPIVersion + "/groups" 30 | marathonAPIQueue = marathonAPIVersion + "/queue" 31 | marathonAPIInfo = marathonAPIVersion + "/info" 32 | marathonAPILeader = marathonAPIVersion + "/leader" 33 | marathonAPIPing = "ping" 34 | ) 35 | 36 | const ( 37 | // EventsTransportCallback activates callback events transport 38 | EventsTransportCallback EventsTransport = 1 << iota 39 | 40 | // EventsTransportSSE activates stream events transport 41 | EventsTransportSSE 42 | ) 43 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/AUTHORS: -------------------------------------------------------------------------------- 1 | Anton Liparin 2 | atheatos 3 | Brian Knox 4 | Conor Mongey 5 | Daniel Bornkessel 6 | David Bosschaert 7 | Denis Parchenko 8 | Diego de Oliveira 9 | Dmitry Fedorov 10 | eduser25 11 | Elliot Anderson 12 | François Samin 13 | Harpreet Sawhney 14 | Ian Babrou 15 | Israel Derdik 16 | Ivan Babrou 17 | Jacob Koren 18 | Jie Zhang 19 | Johan Haals 20 | juliendsv 21 | Kan Wu 22 | kevinschoon 23 | Luke Amdor 24 | Maarten Dirkse 25 | Marcelo Salazar 26 | Marvin Hoffmann 27 | Matthias Kadenbach 28 | Mike Solomon 29 | Mikhail Dyakov 30 | Nic Grayson 31 | ohmystack 32 | Raffaele Di Fazio 33 | Robert Jacob 34 | Rohith 35 | Timo Reimann 36 | Tracy Livengood 37 | Xavi Ramirez 38 | Yang Bai 39 | Yifa Zhang 40 | Zhanpeng Chen 41 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/AUTHORS: -------------------------------------------------------------------------------- 1 | Anton Liparin 2 | atheatos 3 | Brian Knox 4 | Conor Mongey 5 | Daniel Bornkessel 6 | David Bosschaert 7 | Denis Parchenko 8 | Diego de Oliveira 9 | Dmitry Fedorov 10 | eduser25 11 | Elliot Anderson 12 | François Samin 13 | Harpreet Sawhney 14 | Ian Babrou 15 | Israel Derdik 16 | Ivan Babrou 17 | Jacob Koren 18 | Jie Zhang 19 | Johan Haals 20 | juliendsv 21 | Kan Wu 22 | kevinschoon 23 | Luke Amdor 24 | Maarten Dirkse 25 | Marcelo Salazar 26 | Marvin Hoffmann 27 | Matthias Kadenbach 28 | Mike Solomon 29 | Mikhail Dyakov 30 | Nic Grayson 31 | ohmystack 32 | Raffaele Di Fazio 33 | Robert Jacob 34 | Rohith 35 | Timo Reimann 36 | Tracy Livengood 37 | Xavi Ramirez 38 | Yang Bai 39 | Yifa Zhang 40 | Zhanpeng Chen 41 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/LICENSE: -------------------------------------------------------------------------------- 1 | Go support for Protocol Buffers - Google's data interchange format 2 | 3 | Copyright 2010 The Go Authors. All rights reserved. 4 | https://github.com/golang/protobuf 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following disclaimer 14 | in the documentation and/or other materials provided with the 15 | distribution. 16 | * Neither the name of Google Inc. nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "io" 20 | 21 | "github.com/golang/protobuf/proto" 22 | ) 23 | 24 | // WriteDelimited encodes and dumps a message to the provided writer prefixed 25 | // with a 32-bit varint indicating the length of the encoded message, producing 26 | // a length-delimited record stream, which can be used to chain together 27 | // encoded messages of the same type together in a file. It returns the total 28 | // number of bytes written and any applicable error. This is roughly 29 | // equivalent to the companion Java API's MessageLite#writeDelimitedTo. 30 | func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { 31 | buffer, err := proto.Marshal(m) 32 | if err != nil { 33 | return 0, err 34 | } 35 | 36 | var buf [binary.MaxVarintLen32]byte 37 | encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) 38 | 39 | sync, err := w.Write(buf[:encodedLength]) 40 | if err != nil { 41 | return sync, err 42 | } 43 | 44 | n, err = w.Write(buffer) 45 | return n + sync, err 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Marathon Prometheus Exporter 2 | 3 | 4 | [![Build Status](https://travis-ci.org/criteo/marathon_exporter.svg?branch=master)](https://travis-ci.org/criteo/marathon_exporter) 5 | [![Docker Pulls](https://img.shields.io/docker/pulls/gettyimages/marathon_exporter.svg)](https://hub.docker.com/r/gettyimages/marathon_exporter/) 6 | 7 | A [Prometheus](http://prometheus.io) metrics exporter for the [Marathon](https://mesosphere.github.io/marathon) Mesos framework. 8 | 9 | This exporter exposes Marathon's Codahale/Dropwizard metrics via its `/metrics` endpoint. To learn more, visit the [Marathon metrics doc](http://mesosphere.github.io/marathon/docs/metrics.html). 10 | 11 | Note: version v1.5.1+ of this exporter is not compatible with marathon 1.4.0 and below. 12 | 13 | ## Getting 14 | 15 | ```sh 16 | $ go get github.com/criteo/marathon_exporter 17 | ``` 18 | 19 | *\-or-* 20 | 21 | ```sh 22 | $ docker pull gettyimages/marathon_exporter 23 | ``` 24 | 25 | *\-or-* locally build image: 26 | 27 | ``` 28 | make image 29 | docker run -it marathon_exporter --help 30 | ``` 31 | 32 | ## Using 33 | 34 | ```sh 35 | Usage of marathon_exporter: 36 | -marathon.uri string 37 | URI of Marathon (default "http://marathon.mesos:8080") 38 | Note: Supply HTTP Basic Auth (i.e. user:password@example.com) 39 | -web.listen-address string 40 | Address to listen on for web interface and telemetry. (default ":9088") 41 | -web.telemetry-path string 42 | Path under which to expose metrics. (default "/metrics") 43 | -log.format value 44 | If set use a syslog logger or JSON logging. Example: logger:syslog?appname=bob&local=7 or logger:stdout?json=true. Defaults to stderr. 45 | -log.level value 46 | Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]. (default info) 47 | ``` 48 | -------------------------------------------------------------------------------- /containers_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | func Test_container_key(t *testing.T) { 6 | cases := []struct { 7 | name string 8 | labels []string 9 | expect string 10 | }{ 11 | { 12 | name: "foo", 13 | labels: []string{}, 14 | expect: "foo{}", 15 | }, { 16 | name: "foo", 17 | labels: []string{"value"}, 18 | expect: "foo{value}", 19 | }, { 20 | name: "foo", 21 | labels: []string{"value", "color"}, 22 | expect: "foo{color,value}", 23 | }, 24 | } 25 | 26 | for _, c := range cases { 27 | key := containerKey(c.name, c.labels) 28 | if key != c.expect { 29 | t.Errorf("expected container key %s, got %s", c.expect, key) 30 | } 31 | } 32 | } 33 | 34 | func Test_container_fetch_counter(t *testing.T) { 35 | container := NewCounterContainer("marathon") 36 | _, new := container.Fetch("foo", "") 37 | 38 | if !new { 39 | t.Fatal("expected a new counter") 40 | } 41 | if len(container.counters) != 1 { 42 | t.Fatalf("expected a counter, got %d counters", len(container.counters)) 43 | } 44 | 45 | _, new = container.Fetch("foo", "") 46 | if new { 47 | t.Fatal("expected an existing counter") 48 | } 49 | if len(container.counters) != 1 { 50 | t.Fatalf("expected same counter as before, go %d counters", len(container.counters)) 51 | } 52 | } 53 | 54 | func Test_container_fetch_gauge(t *testing.T) { 55 | container := NewGaugeContainer("marathon") 56 | _, new := container.Fetch("foo", "") 57 | 58 | if !new { 59 | t.Fatal("expected a new gauge") 60 | } 61 | if len(container.gauges) != 1 { 62 | t.Fatalf("expected a gauge, got %d gauges", len(container.gauges)) 63 | } 64 | 65 | _, new = container.Fetch("foo", "") 66 | if new { 67 | t.Fatal("expected an existing gauge") 68 | } 69 | if len(container.gauges) != 1 { 70 | t.Fatalf("expected same gauge as before, go %d gauges", len(container.gauges)) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.10.0 2 | 3 | * feature: Add a test hook (#180) 4 | * feature: `ParseLevel` is now case-insensitive (#326) 5 | * feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) 6 | * performance: avoid re-allocations on `WithFields` (#335) 7 | 8 | # 0.9.0 9 | 10 | * logrus/text_formatter: don't emit empty msg 11 | * logrus/hooks/airbrake: move out of main repository 12 | * logrus/hooks/sentry: move out of main repository 13 | * logrus/hooks/papertrail: move out of main repository 14 | * logrus/hooks/bugsnag: move out of main repository 15 | * logrus/core: run tests with `-race` 16 | * logrus/core: detect TTY based on `stderr` 17 | * logrus/core: support `WithError` on logger 18 | * logrus/core: Solaris support 19 | 20 | # 0.8.7 21 | 22 | * logrus/core: fix possible race (#216) 23 | * logrus/doc: small typo fixes and doc improvements 24 | 25 | 26 | # 0.8.6 27 | 28 | * hooks/raven: allow passing an initialized client 29 | 30 | # 0.8.5 31 | 32 | * logrus/core: revert #208 33 | 34 | # 0.8.4 35 | 36 | * formatter/text: fix data race (#218) 37 | 38 | # 0.8.3 39 | 40 | * logrus/core: fix entry log level (#208) 41 | * logrus/core: improve performance of text formatter by 40% 42 | * logrus/core: expose `LevelHooks` type 43 | * logrus/core: add support for DragonflyBSD and NetBSD 44 | * formatter/text: print structs more verbosely 45 | 46 | # 0.8.2 47 | 48 | * logrus: fix more Fatal family functions 49 | 50 | # 0.8.1 51 | 52 | * logrus: fix not exiting on `Fatalf` and `Fatalln` 53 | 54 | # 0.8.0 55 | 56 | * logrus: defaults to stderr instead of stdout 57 | * hooks/sentry: add special field for `*http.Request` 58 | * formatter/text: ignore Windows for colors 59 | 60 | # 0.7.3 61 | 62 | * formatter/\*: allow configuration of timestamp layout 63 | 64 | # 0.7.2 65 | 66 | * formatter/text: Add configuration option for time format (#158) 67 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/queue.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // Queue is the definition of marathon queue 24 | type Queue struct { 25 | Items []Item `json:"queue"` 26 | } 27 | 28 | // Item is the definition of element in the queue 29 | type Item struct { 30 | Count int `json:"count"` 31 | Delay Delay `json:"delay"` 32 | Application Application `json:"app"` 33 | } 34 | 35 | // Delay cotains the application postpone infomation 36 | type Delay struct { 37 | Overdue bool `json:"overdue"` 38 | TimeLeftSeconds int `json:"timeLeftSeconds"` 39 | } 40 | 41 | // Queue retrieves content of the marathon launch queue 42 | func (r *marathonClient) Queue() (*Queue, error) { 43 | var queue *Queue 44 | err := r.apiGet(marathonAPIQueue, nil, &queue) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return queue, nil 49 | } 50 | 51 | // DeleteQueueDelay resets task launch delay of the specific application 52 | // appID: the ID of the application 53 | func (r *marathonClient) DeleteQueueDelay(appID string) error { 54 | uri := fmt.Sprintf("%s/%s/delay", marathonAPIQueue, trimRootPath(appID)) 55 | err := r.apiDelete(uri, nil, nil) 56 | if err != nil { 57 | return err 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/queue.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // Queue is the definition of marathon queue 24 | type Queue struct { 25 | Items []Item `json:"queue"` 26 | } 27 | 28 | // Item is the definition of element in the queue 29 | type Item struct { 30 | Count int `json:"count"` 31 | Delay Delay `json:"delay"` 32 | Application Application `json:"app"` 33 | } 34 | 35 | // Delay cotains the application postpone infomation 36 | type Delay struct { 37 | Overdue bool `json:"overdue"` 38 | TimeLeftSeconds int `json:"timeLeftSeconds"` 39 | } 40 | 41 | // Queue retrieves content of the marathon launch queue 42 | func (r *marathonClient) Queue() (*Queue, error) { 43 | var queue *Queue 44 | err := r.apiGet(marathonAPIQueue, nil, &queue) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return queue, nil 49 | } 50 | 51 | // DeleteQueueDelay resets task launch delay of the specific application 52 | // appID: the ID of the application 53 | func (r *marathonClient) DeleteQueueDelay(appID string) error { 54 | uri := fmt.Sprintf("%s/%s/delay", marathonAPIQueue, trimRootPath(appID)) 55 | err := r.apiDelete(uri, nil, nil) 56 | if err != nil { 57 | return err 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/port_definition.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // PortDefinition is a definition of a port that should be considered 20 | // part of a resource. Port definitions are necessary when you are 21 | // using HOST networking and no port mappings are specified. 22 | type PortDefinition struct { 23 | Port *int `json:"port,omitempty"` 24 | Protocol string `json:"protocol,omitempty"` 25 | Name string `json:"name,omitempty"` 26 | Labels *map[string]string `json:"labels,omitempty"` 27 | } 28 | 29 | // SetPort sets the given port for the PortDefinition 30 | func (p PortDefinition) SetPort(port int) PortDefinition { 31 | p.Port = &port 32 | return p 33 | } 34 | 35 | // AddLabel adds a label to the PortDefinition 36 | // name: the name of the label 37 | // value: value for this label 38 | func (p PortDefinition) AddLabel(name, value string) PortDefinition { 39 | if p.Labels == nil { 40 | p.EmptyLabels() 41 | } 42 | (*p.Labels)[name] = value 43 | 44 | return p 45 | } 46 | 47 | // EmptyLabels explicitly empties the labels -- use this if you need to empty 48 | // the labels of a PortDefinition that already has labels set 49 | // (setting labels to nill will keep the current value) 50 | func (p *PortDefinition) EmptyLabels() *PortDefinition { 51 | p.Labels = &map[string]string{} 52 | 53 | return p 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/port_definition.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // PortDefinition is a definition of a port that should be considered 20 | // part of a resource. Port definitions are necessary when you are 21 | // using HOST networking and no port mappings are specified. 22 | type PortDefinition struct { 23 | Port *int `json:"port,omitempty"` 24 | Protocol string `json:"protocol,omitempty"` 25 | Name string `json:"name,omitempty"` 26 | Labels *map[string]string `json:"labels,omitempty"` 27 | } 28 | 29 | // SetPort sets the given port for the PortDefinition 30 | func (p PortDefinition) SetPort(port int) PortDefinition { 31 | p.Port = &port 32 | return p 33 | } 34 | 35 | // AddLabel adds a label to the PortDefinition 36 | // name: the name of the label 37 | // value: value for this label 38 | func (p PortDefinition) AddLabel(name, value string) PortDefinition { 39 | if p.Labels == nil { 40 | p.EmptyLabels() 41 | } 42 | (*p.Labels)[name] = value 43 | 44 | return p 45 | } 46 | 47 | // EmptyLabels explicitly empties the labels -- use this if you need to empty 48 | // the labels of a PortDefinition that already has labels set 49 | // (setting labels to nill will keep the current value) 50 | func (p *PortDefinition) EmptyLabels() *PortDefinition { 51 | p.Labels = &map[string]string{} 52 | 53 | return p 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/proto/Makefile: -------------------------------------------------------------------------------- 1 | # Go support for Protocol Buffers - Google's data interchange format 2 | # 3 | # Copyright 2010 The Go Authors. All rights reserved. 4 | # https://github.com/golang/protobuf 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following disclaimer 14 | # in the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Google Inc. nor the names of its 17 | # contributors may be used to endorse or promote products derived from 18 | # this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | install: 33 | go install 34 | 35 | test: install generate-test-pbs 36 | go test 37 | 38 | 39 | generate-test-pbs: 40 | make install 41 | make -C testdata 42 | protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto 43 | make 44 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/decoder.go: -------------------------------------------------------------------------------- 1 | package eventsource 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | type publication struct { 11 | id, event, data string 12 | retry int64 13 | } 14 | 15 | func (s *publication) Id() string { return s.id } 16 | func (s *publication) Event() string { return s.event } 17 | func (s *publication) Data() string { return s.data } 18 | func (s *publication) Retry() int64 { return s.retry } 19 | 20 | // A Decoder is capable of reading Events from a stream. 21 | type Decoder struct { 22 | *bufio.Reader 23 | } 24 | 25 | // NewDecoder returns a new Decoder instance that reads events 26 | // with the given io.Reader. 27 | func NewDecoder(r io.Reader) *Decoder { 28 | dec := &Decoder{bufio.NewReader(newNormaliser(r))} 29 | return dec 30 | } 31 | 32 | // Decode reads the next Event from a stream (and will block until one 33 | // comes in). 34 | // Graceful disconnects (between events) are indicated by an io.EOF error. 35 | // Any error occuring mid-event is considered non-graceful and will 36 | // show up as some other error (most likely io.ErrUnexpectedEOF). 37 | func (dec *Decoder) Decode() (Event, error) { 38 | 39 | // peek ahead before we start a new event so we can return EOFs 40 | _, err := dec.Peek(1) 41 | if err == io.ErrUnexpectedEOF { 42 | err = io.EOF 43 | } 44 | if err != nil { 45 | return nil, err 46 | } 47 | pub := new(publication) 48 | for { 49 | line, err := dec.ReadString('\n') 50 | if err != nil { 51 | return nil, err 52 | } 53 | if line == "\n" { 54 | break 55 | } 56 | line = strings.TrimSuffix(line, "\n") 57 | if strings.HasPrefix(line, ":") { 58 | continue 59 | } 60 | sections := strings.SplitN(line, ":", 2) 61 | field, value := sections[0], "" 62 | if len(sections) == 2 { 63 | value = strings.TrimPrefix(sections[1], " ") 64 | } 65 | switch field { 66 | case "event": 67 | pub.event = value 68 | case "data": 69 | pub.data += value + "\n" 70 | case "id": 71 | pub.id = value 72 | case "retry": 73 | pub.retry, _ = strconv.ParseInt(value, 10, 64) 74 | } 75 | } 76 | pub.data = strings.TrimSuffix(pub.data, "\n") 77 | return pub, nil 78 | } 79 | -------------------------------------------------------------------------------- /containers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "sort" 7 | "strings" 8 | "sync" 9 | 10 | "github.com/prometheus/client_golang/prometheus" 11 | ) 12 | 13 | const ( 14 | counterHelp = "Marathon counter %s" 15 | gaugeHelp = "Marathon gauge %s" 16 | meterHelp = "Marathon meter %s (%s)" 17 | histogramHelp = "Marathon histogram %s" 18 | timerHelp = "Marathon timer %s (%s)" 19 | ) 20 | 21 | type CounterContainer struct { 22 | counters map[string]*prometheus.CounterVec 23 | namespace string 24 | mutex sync.Mutex 25 | } 26 | 27 | func NewCounterContainer(namespace string) *CounterContainer { 28 | return &CounterContainer{ 29 | counters: make(map[string]*prometheus.CounterVec), 30 | namespace: namespace, 31 | } 32 | } 33 | 34 | func (c *CounterContainer) Fetch(name, help string, labels ...string) (*prometheus.CounterVec, bool) { 35 | key := containerKey(name, labels) 36 | c.mutex.Lock() 37 | defer c.mutex.Unlock() 38 | counter, exists := c.counters[key] 39 | 40 | if !exists { 41 | counter = prometheus.NewCounterVec(prometheus.CounterOpts{ 42 | Namespace: c.namespace, 43 | Name: name, 44 | Help: help, 45 | }, labels) 46 | 47 | c.counters[key] = counter 48 | } 49 | 50 | return counter, !exists 51 | } 52 | 53 | type GaugeContainer struct { 54 | gauges map[string]*prometheus.GaugeVec 55 | namespace string 56 | mutex sync.Mutex 57 | } 58 | 59 | func NewGaugeContainer(namespace string) *GaugeContainer { 60 | return &GaugeContainer{ 61 | gauges: make(map[string]*prometheus.GaugeVec), 62 | namespace: namespace, 63 | } 64 | } 65 | 66 | func (c *GaugeContainer) Fetch(name, help string, labels ...string) (*prometheus.GaugeVec, bool) { 67 | key := containerKey(name, labels) 68 | c.mutex.Lock() 69 | defer c.mutex.Unlock() 70 | gauge, exists := c.gauges[key] 71 | 72 | if !exists { 73 | gauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{ 74 | Namespace: c.namespace, 75 | Name: name, 76 | Help: help, 77 | }, labels) 78 | 79 | c.gauges[key] = gauge 80 | } 81 | return gauge, !exists 82 | } 83 | 84 | func containerKey(metric string, labels []string) string { 85 | s := make([]string, len(labels)) 86 | copy(s, labels) 87 | sort.Strings(s) 88 | return fmt.Sprintf("%s{%v}", metric, strings.Join(s, ",")) 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | import ( 20 | "io" 21 | "io/ioutil" 22 | "net/http" 23 | "time" 24 | ) 25 | 26 | const defaultPollingWaitTime = 500 * time.Millisecond 27 | 28 | // EventsTransport describes which transport should be used to deliver Marathon events 29 | type EventsTransport int 30 | 31 | // Config holds the settings and options for the client 32 | type Config struct { 33 | // URL is the url for marathon 34 | URL string 35 | // EventsTransport is the events transport: EventsTransportCallback or EventsTransportSSE 36 | EventsTransport EventsTransport 37 | // EventsPort is the event handler port 38 | EventsPort int 39 | // the interface we should be listening on for events 40 | EventsInterface string 41 | // HTTPBasicAuthUser is the http basic auth 42 | HTTPBasicAuthUser string 43 | // HTTPBasicPassword is the http basic password 44 | HTTPBasicPassword string 45 | // CallbackURL custom callback url 46 | CallbackURL string 47 | // DCOSToken for DCOS environment, This will override the Authorization header 48 | DCOSToken string 49 | // LogOutput the output for debug log messages 50 | LogOutput io.Writer 51 | // HTTPClient is the http client 52 | HTTPClient *http.Client 53 | // wait time (in milliseconds) between repetitive requests to the API during polling 54 | PollingWaitTime time.Duration 55 | } 56 | 57 | // NewDefaultConfig create a default client config 58 | func NewDefaultConfig() Config { 59 | return Config{ 60 | URL: "http://127.0.0.1:8080", 61 | EventsTransport: EventsTransportCallback, 62 | EventsPort: 10001, 63 | EventsInterface: "eth0", 64 | LogOutput: ioutil.Discard, 65 | PollingWaitTime: defaultPollingWaitTime, 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | import ( 20 | "io" 21 | "io/ioutil" 22 | "net/http" 23 | "time" 24 | ) 25 | 26 | const defaultPollingWaitTime = 500 * time.Millisecond 27 | 28 | // EventsTransport describes which transport should be used to deliver Marathon events 29 | type EventsTransport int 30 | 31 | // Config holds the settings and options for the client 32 | type Config struct { 33 | // URL is the url for marathon 34 | URL string 35 | // EventsTransport is the events transport: EventsTransportCallback or EventsTransportSSE 36 | EventsTransport EventsTransport 37 | // EventsPort is the event handler port 38 | EventsPort int 39 | // the interface we should be listening on for events 40 | EventsInterface string 41 | // HTTPBasicAuthUser is the http basic auth 42 | HTTPBasicAuthUser string 43 | // HTTPBasicPassword is the http basic password 44 | HTTPBasicPassword string 45 | // CallbackURL custom callback url 46 | CallbackURL string 47 | // DCOSToken for DCOS environment, This will override the Authorization header 48 | DCOSToken string 49 | // LogOutput the output for debug log messages 50 | LogOutput io.Writer 51 | // HTTPClient is the http client 52 | HTTPClient *http.Client 53 | // wait time (in milliseconds) between repetitive requests to the API during polling 54 | PollingWaitTime time.Duration 55 | } 56 | 57 | // NewDefaultConfig create a default client config 58 | func NewDefaultConfig() Config { 59 | return Config{ 60 | URL: "http://127.0.0.1:8080", 61 | EventsTransport: EventsTransportCallback, 62 | EventsPort: 10001, 63 | EventsInterface: "eth0", 64 | LogOutput: ioutil.Discard, 65 | PollingWaitTime: defaultPollingWaitTime, 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/alt_exit.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // The following code was sourced and modified from the 4 | // https://bitbucket.org/tebeka/atexit package governed by the following license: 5 | // 6 | // Copyright (c) 2012 Miki Tebeka . 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | // this software and associated documentation files (the "Software"), to deal in 10 | // the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | // the Software, and to permit persons to whom the Software is furnished to do so, 13 | // subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 21 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | import ( 26 | "fmt" 27 | "os" 28 | ) 29 | 30 | var handlers = []func(){} 31 | 32 | func runHandler(handler func()) { 33 | defer func() { 34 | if err := recover(); err != nil { 35 | fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) 36 | } 37 | }() 38 | 39 | handler() 40 | } 41 | 42 | func runHandlers() { 43 | for _, handler := range handlers { 44 | runHandler(handler) 45 | } 46 | } 47 | 48 | // Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) 49 | func Exit(code int) { 50 | runHandlers() 51 | os.Exit(code) 52 | } 53 | 54 | // RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke 55 | // all handlers. The handlers will also be invoked when any Fatal log entry is 56 | // made. 57 | // 58 | // This method is useful when a caller wishes to use logrus to log a fatal 59 | // message but also needs to gracefully shutdown. An example usecase could be 60 | // closing database connections, or sending a alert that the application is 61 | // closing. 62 | func RegisterExitHandler(handler func()) { 63 | handlers = append(handlers, handler) 64 | } 65 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "flag" 6 | "net" 7 | "net/http" 8 | "net/url" 9 | "time" 10 | 11 | "github.com/matt-deboer/go-marathon" 12 | "github.com/prometheus/client_golang/prometheus" 13 | "github.com/prometheus/common/log" 14 | ) 15 | 16 | var ( 17 | listenAddress = flag.String( 18 | "web.listen-address", ":9088", 19 | "Address to listen on for web interface and telemetry.") 20 | 21 | metricsPath = flag.String( 22 | "web.telemetry-path", "/metrics", 23 | "Path under which to expose metrics.") 24 | 25 | marathonUri = flag.String( 26 | "marathon.uri", "http://marathon.mesos:8080", 27 | "URI of Marathon") 28 | ) 29 | 30 | func marathonConnect(uri *url.URL) error { 31 | config := marathon.NewDefaultConfig() 32 | config.URL = uri.String() 33 | 34 | if uri.User != nil { 35 | if passwd, ok := uri.User.Password(); ok { 36 | config.HTTPBasicPassword = passwd 37 | config.HTTPBasicAuthUser = uri.User.Username() 38 | } 39 | } 40 | config.HTTPClient = &http.Client{ 41 | Timeout: 10 * time.Second, 42 | Transport: &http.Transport{ 43 | Dial: (&net.Dialer{ 44 | Timeout: 10 * time.Second, 45 | }).Dial, 46 | TLSClientConfig: &tls.Config{ 47 | InsecureSkipVerify: true, 48 | }, 49 | }, 50 | } 51 | 52 | log.Debugln("Connecting to Marathon") 53 | client, err := marathon.NewClient(config) 54 | if err != nil { 55 | return err 56 | } 57 | 58 | info, err := client.Info() 59 | if err != nil { 60 | return err 61 | } 62 | 63 | log.Debugf("Connected to Marathon! Name=%s, Version=%s\n", info.Name, info.Version) 64 | return nil 65 | } 66 | 67 | func main() { 68 | flag.Parse() 69 | uri, err := url.Parse(*marathonUri) 70 | if err != nil { 71 | log.Fatal(err) 72 | } 73 | 74 | retryTimeout := time.Duration(10 * time.Second) 75 | for { 76 | err := marathonConnect(uri) 77 | if err == nil { 78 | break 79 | } 80 | 81 | log.Debugf("Problem connecting to Marathon: %v", err) 82 | log.Infof("Couldn't connect to Marathon! Trying again in %v", retryTimeout) 83 | time.Sleep(retryTimeout) 84 | } 85 | 86 | exporter := NewExporter(&scraper{uri}, defaultNamespace) 87 | prometheus.MustRegister(exporter) 88 | 89 | http.Handle(*metricsPath, prometheus.Handler()) 90 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 91 | w.Write([]byte(` 92 | Marathon Exporter 93 | 94 |

Marathon Exporter

95 |

Metrics

96 | 97 | `)) 98 | }) 99 | 100 | log.Info("Starting Server: ", *listenAddress) 101 | log.Fatal(http.ListenAndServe(*listenAddress, nil)) 102 | } 103 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package expfmt 15 | 16 | import ( 17 | "fmt" 18 | "io" 19 | "net/http" 20 | 21 | "github.com/golang/protobuf/proto" 22 | "github.com/matttproud/golang_protobuf_extensions/pbutil" 23 | "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" 24 | 25 | dto "github.com/prometheus/client_model/go" 26 | ) 27 | 28 | // Encoder types encode metric families into an underlying wire protocol. 29 | type Encoder interface { 30 | Encode(*dto.MetricFamily) error 31 | } 32 | 33 | type encoder func(*dto.MetricFamily) error 34 | 35 | func (e encoder) Encode(v *dto.MetricFamily) error { 36 | return e(v) 37 | } 38 | 39 | // Negotiate returns the Content-Type based on the given Accept header. 40 | // If no appropriate accepted type is found, FmtText is returned. 41 | func Negotiate(h http.Header) Format { 42 | for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { 43 | // Check for protocol buffer 44 | if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { 45 | switch ac.Params["encoding"] { 46 | case "delimited": 47 | return FmtProtoDelim 48 | case "text": 49 | return FmtProtoText 50 | case "compact-text": 51 | return FmtProtoCompact 52 | } 53 | } 54 | // Check for text format. 55 | ver := ac.Params["version"] 56 | if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { 57 | return FmtText 58 | } 59 | } 60 | return FmtText 61 | } 62 | 63 | // NewEncoder returns a new encoder based on content type negotiation. 64 | func NewEncoder(w io.Writer, format Format) Encoder { 65 | switch format { 66 | case FmtProtoDelim: 67 | return encoder(func(v *dto.MetricFamily) error { 68 | _, err := pbutil.WriteDelimited(w, v) 69 | return err 70 | }) 71 | case FmtProtoCompact: 72 | return encoder(func(v *dto.MetricFamily) error { 73 | _, err := fmt.Fprintln(w, v.String()) 74 | return err 75 | }) 76 | case FmtProtoText: 77 | return encoder(func(v *dto.MetricFamily) error { 78 | _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) 79 | return err 80 | }) 81 | case FmtText: 82 | return encoder(func(v *dto.MetricFamily) error { 83 | _, err := MetricFamilyToText(w, v) 84 | return err 85 | }) 86 | } 87 | panic("expfmt.NewEncoder: unknown format") 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/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 = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_:]*$`) 26 | ) 27 | 28 | // A Metric is similar to a LabelSet, but the key difference is that a Metric is 29 | // a singleton and refers to one and only one stream of samples. 30 | type Metric LabelSet 31 | 32 | // Equal compares the metrics. 33 | func (m Metric) Equal(o Metric) bool { 34 | return LabelSet(m).Equal(LabelSet(o)) 35 | } 36 | 37 | // Before compares the metrics' underlying label sets. 38 | func (m Metric) Before(o Metric) bool { 39 | return LabelSet(m).Before(LabelSet(o)) 40 | } 41 | 42 | // Clone returns a copy of the Metric. 43 | func (m Metric) Clone() Metric { 44 | clone := Metric{} 45 | for k, v := range m { 46 | clone[k] = v 47 | } 48 | return clone 49 | } 50 | 51 | func (m Metric) String() string { 52 | metricName, hasName := m[MetricNameLabel] 53 | numLabels := len(m) - 1 54 | if !hasName { 55 | numLabels = len(m) 56 | } 57 | labelStrings := make([]string, 0, numLabels) 58 | for label, value := range m { 59 | if label != MetricNameLabel { 60 | labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value)) 61 | } 62 | } 63 | 64 | switch numLabels { 65 | case 0: 66 | if hasName { 67 | return string(metricName) 68 | } 69 | return "{}" 70 | default: 71 | sort.Strings(labelStrings) 72 | return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", ")) 73 | } 74 | } 75 | 76 | // Fingerprint returns a Metric's Fingerprint. 77 | func (m Metric) Fingerprint() Fingerprint { 78 | return LabelSet(m).Fingerprint() 79 | } 80 | 81 | // FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing 82 | // algorithm, which is, however, more susceptible to hash collisions. 83 | func (m Metric) FastFingerprint() Fingerprint { 84 | return LabelSet(m).FastFingerprint() 85 | } 86 | 87 | // IsValidMetricName returns true iff name matches the pattern of MetricNameRE. 88 | func IsValidMetricName(n LabelValue) bool { 89 | if len(n) == 0 { 90 | return false 91 | } 92 | for i, b := range n { 93 | if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) { 94 | return false 95 | } 96 | } 97 | return true 98 | } 99 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/push.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 | // Copyright (c) 2013, The Prometheus Authors 15 | // All rights reserved. 16 | // 17 | // Use of this source code is governed by a BSD-style license that can be found 18 | // in the LICENSE file. 19 | 20 | package prometheus 21 | 22 | // Push triggers a metric collection by the default registry and pushes all 23 | // collected metrics to the Pushgateway specified by url. See the Pushgateway 24 | // documentation for detailed implications of the job and instance 25 | // parameter. instance can be left empty. You can use just host:port or ip:port 26 | // as url, in which case 'http://' is added automatically. You can also include 27 | // the schema in the URL. However, do not include the '/metrics/jobs/...' part. 28 | // 29 | // Note that all previously pushed metrics with the same job and instance will 30 | // be replaced with the metrics pushed by this call. (It uses HTTP method 'PUT' 31 | // to push to the Pushgateway.) 32 | func Push(job, instance, url string) error { 33 | return defRegistry.Push(job, instance, url, "PUT") 34 | } 35 | 36 | // PushAdd works like Push, but only previously pushed metrics with the same 37 | // name (and the same job and instance) will be replaced. (It uses HTTP method 38 | // 'POST' to push to the Pushgateway.) 39 | func PushAdd(job, instance, url string) error { 40 | return defRegistry.Push(job, instance, url, "POST") 41 | } 42 | 43 | // PushCollectors works like Push, but it does not collect from the default 44 | // registry. Instead, it collects from the provided collectors. It is a 45 | // convenient way to push only a few metrics. 46 | func PushCollectors(job, instance, url string, collectors ...Collector) error { 47 | return pushCollectors(job, instance, url, "PUT", collectors...) 48 | } 49 | 50 | // PushAddCollectors works like PushAdd, but it does not collect from the 51 | // default registry. Instead, it collects from the provided collectors. It is a 52 | // convenient way to push only a few metrics. 53 | func PushAddCollectors(job, instance, url string, collectors ...Collector) error { 54 | return pushCollectors(job, instance, url, "POST", collectors...) 55 | } 56 | 57 | func pushCollectors(job, instance, url, method string, collectors ...Collector) error { 58 | r := newRegistry() 59 | for _, collector := range collectors { 60 | if _, err := r.Register(collector); err != nil { 61 | return err 62 | } 63 | } 64 | return r.Push(job, instance, url, method) 65 | } 66 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fingerprinting.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "strconv" 19 | ) 20 | 21 | // Fingerprint provides a hash-capable representation of a Metric. 22 | // For our purposes, FNV-1A 64-bit is used. 23 | type Fingerprint uint64 24 | 25 | // FingerprintFromString transforms a string representation into a Fingerprint. 26 | func FingerprintFromString(s string) (Fingerprint, error) { 27 | num, err := strconv.ParseUint(s, 16, 64) 28 | return Fingerprint(num), err 29 | } 30 | 31 | // ParseFingerprint parses the input string into a fingerprint. 32 | func ParseFingerprint(s string) (Fingerprint, error) { 33 | num, err := strconv.ParseUint(s, 16, 64) 34 | if err != nil { 35 | return 0, err 36 | } 37 | return Fingerprint(num), nil 38 | } 39 | 40 | func (f Fingerprint) String() string { 41 | return fmt.Sprintf("%016x", uint64(f)) 42 | } 43 | 44 | // Fingerprints represents a collection of Fingerprint subject to a given 45 | // natural sorting scheme. It implements sort.Interface. 46 | type Fingerprints []Fingerprint 47 | 48 | // Len implements sort.Interface. 49 | func (f Fingerprints) Len() int { 50 | return len(f) 51 | } 52 | 53 | // Less implements sort.Interface. 54 | func (f Fingerprints) Less(i, j int) bool { 55 | return f[i] < f[j] 56 | } 57 | 58 | // Swap implements sort.Interface. 59 | func (f Fingerprints) Swap(i, j int) { 60 | f[i], f[j] = f[j], f[i] 61 | } 62 | 63 | // FingerprintSet is a set of Fingerprints. 64 | type FingerprintSet map[Fingerprint]struct{} 65 | 66 | // Equal returns true if both sets contain the same elements (and not more). 67 | func (s FingerprintSet) Equal(o FingerprintSet) bool { 68 | if len(s) != len(o) { 69 | return false 70 | } 71 | 72 | for k := range s { 73 | if _, ok := o[k]; !ok { 74 | return false 75 | } 76 | } 77 | 78 | return true 79 | } 80 | 81 | // Intersection returns the elements contained in both sets. 82 | func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet { 83 | myLength, otherLength := len(s), len(o) 84 | if myLength == 0 || otherLength == 0 { 85 | return FingerprintSet{} 86 | } 87 | 88 | subSet := s 89 | superSet := o 90 | 91 | if otherLength < myLength { 92 | subSet = o 93 | superSet = s 94 | } 95 | 96 | out := FingerprintSet{} 97 | 98 | for k := range subSet { 99 | if _, ok := superSet[k]; ok { 100 | out[k] = struct{}{} 101 | } 102 | } 103 | 104 | return out 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "errors" 20 | "io" 21 | 22 | "github.com/golang/protobuf/proto" 23 | ) 24 | 25 | var errInvalidVarint = errors.New("invalid varint32 encountered") 26 | 27 | // ReadDelimited decodes a message from the provided length-delimited stream, 28 | // where the length is encoded as 32-bit varint prefix to the message body. 29 | // It returns the total number of bytes read and any applicable error. This is 30 | // roughly equivalent to the companion Java API's 31 | // MessageLite#parseDelimitedFrom. As per the reader contract, this function 32 | // calls r.Read repeatedly as required until exactly one message including its 33 | // prefix is read and decoded (or an error has occurred). The function never 34 | // reads more bytes from the stream than required. The function never returns 35 | // an error if a message has been read and decoded correctly, even if the end 36 | // of the stream has been reached in doing so. In that case, any subsequent 37 | // calls return (0, io.EOF). 38 | func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { 39 | // Per AbstractParser#parsePartialDelimitedFrom with 40 | // CodedInputStream#readRawVarint32. 41 | var headerBuf [binary.MaxVarintLen32]byte 42 | var bytesRead, varIntBytes int 43 | var messageLength uint64 44 | for varIntBytes == 0 { // i.e. no varint has been decoded yet. 45 | if bytesRead >= len(headerBuf) { 46 | return bytesRead, errInvalidVarint 47 | } 48 | // We have to read byte by byte here to avoid reading more bytes 49 | // than required. Each read byte is appended to what we have 50 | // read before. 51 | newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) 52 | if newBytesRead == 0 { 53 | if err != nil { 54 | return bytesRead, err 55 | } 56 | // A Reader should not return (0, nil), but if it does, 57 | // it should be treated as no-op (according to the 58 | // Reader contract). So let's go on... 59 | continue 60 | } 61 | bytesRead += newBytesRead 62 | // Now present everything read so far to the varint decoder and 63 | // see if a varint can be decoded already. 64 | messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead]) 65 | } 66 | 67 | messageBuf := make([]byte, messageLength) 68 | newBytesRead, err := io.ReadFull(r, messageBuf) 69 | bytesRead += newBytesRead 70 | if err != nil { 71 | return bytesRead, err 72 | } 73 | 74 | return bytesRead, proto.Unmarshal(messageBuf, m) 75 | } 76 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | services: 3 | - docker 4 | language: go 5 | go: 6 | - 1.7 7 | script: 8 | - make release 9 | deploy: 10 | provider: releases 11 | skip_cleanup: true 12 | api_key: 13 | secure: oJ5oD3x3lSvcQvt0CO7XpFIN2I1OimP6pyT7cJxsffqLvxdz1u6tF12Uq737c1FRvtbmZpkYwrkg+90eGA4Qym4nVLynyt1zCR6aP5O0yJ8fMaJRYyNFsGfSX2YSSlIQmrnj+L8XNpjvkuOg7yqc3s/RYT5Vngt2QyiZPqFjK2+FweQh6IdEB11UTtYjhz+hWPu3NoMiNGJ91K7p4i0HWkySFsI5nmOZZNYjeBbPu3gpnerZ1K7ybtchDh05uFjen7O3ww5ZK+4/LD1rOK+SX1kO5OCnkyh/ZFRO3q07krhK64Z8yVOWsi71fOw+8/hSA0eAu9WZ3/AA14zMUNuNVHoGBR4hEEDboBKtvG0fjtaODdGSw5AW3aHWcLxq/11MmbjZFt/yN1M4A3fP3pIPcjoz2GdSh3hhWe7GIumEc1kHlCD2w2I310x489O2vdnwbvRSWM7/vKVOqRPehyaNtB4rlg8mJb35d2taVjcJk+3UjZ9LWKt8v3jsYNZS2Z1tu+E/tOIA4JY5V0b3l5K512MbHJ+CPewM4+XJYevo8gYM6m8RSLqFke6vqvClb/ajF+FdV9pwKGwU6PH8lZrMMIvwgb+fCWAwFQqgONYgm+mt6uyj7ai7nWNiyoLru25CRmv1SFrQkktT93AWJpuDaMm20SHUMtkZaUnM3nRuN14= 14 | file: bin/marathon_exporter 15 | on: 16 | repo: criteo/marathon_exporter 17 | tags: true 18 | after_deploy: 19 | - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS 20 | - export REPO=gettimages/marathon_exporter 21 | - docker build -f Dockerfile -t $REPO:$TRAVIS_TAG . 22 | - docker push $REPO:$TRAVIS_TAG 23 | - docker tag $REPO:$TRAVIS_TAG $REPO:latest 24 | - docker push $REPO:latest 25 | 26 | env: 27 | global: 28 | - secure: LsEsjlRNGVYaXIzbQfxLg+j6ItgaE5sQV8AKTPcK1zbcXdAuznRi+EfVknyZCCVz6NIRGsyT5BullKZHHKltIdcgEquSIAXM3tov+r3a6mjjYDHocP/EKSRzdTPlUCs4v/en8G11polWEeQ12Fg0dYH7KEx0/JycszTVrCt8sYmiSPFtZpEllJDmDHZbavXNyP5hFjlH6h8szhxPLd2xyGDJivcRXWgGx0qewIGwsJ13jrMRq8fI453N99PRP9iO4tyztE/XO6AYqu3CvUBGJp3MyizQXL7ljUTcfcPJNWm8KcOxOrypB6tDFha6lfQomIhKNUGe0ytwpFwPVWblXlQIa/IlxPvAqolslYQAnC68ir+3FpZBvKaZPOKACumUF3RzrMM0EtZCvooDitjs1KnzQeZWS4FQqTz4FzsjvPGncBoqK+MC2A0L2NuuYHeWmTcsvLdEqC8McnS/2kdGEDed+0ZFzIN9oEQvOx1IoO83AeltnumMYW8JSacGAiCYRs5rYoqjxaExPd2jYEh1mpoh2zseKnNyJCgcTU+7/wykQaahcFR1CDimToZ/lfDt6ih2kyndj189ZYPLt+gokbU8JJ8NERse3xH2DMeBplO8zkGT1oO9uPg2OQk2M0xw9RFRB3fFdYqwSlDCOxl7jjMDgKGodjT/WX78aqXmLCw= 29 | - secure: A5y+5o+gzatjN2ugpQDoTw0jz26pwmpOsN1TDH12iGBywFhvo7bS+1S2+xE8KFBjG8oIo7D3mKMWWR4PiK0U39I3EFJ7MEp5YhLysFZ9lurBffi15bfIHzDV+iregaQv+kItfr2s2rvO6CakpB+QeGWpe/T9+Fu/8oPBaMmZDyju4XRcEkCwsqzgX7ELc7HjxxkP+X95BpdOlk17PNkGUS8Y5cvALHb4LzR0MmS0vK5XmgdY8JBOIaNMjaH+T0HC0pqP3JmnFCgxNWOO4lHW54e9IpTaBUG/dAan/FS1Sh4bGBjC1wyLBlJhR78oPxgQlhhEeCXm0DN34u6qUpXDia7LqBRG+bfzU3UdKg4sql1Cw/qswAw0W+CB7rvCDci/+vNlBQE1kukpOiFJBTEwDLLPZKrhyAJu5BETS8sZS/Gp7Y0u+SZtqFwZs6WQqqmW2EggBsYUm7UxUG009oqXeYD92mLjsuj9M1nv8mHr2qvAz0Mp9B38IXs/fZC6OYPQoYLUZWXJ+eIPZdfY7OMVL11AGGOZBZs4nB+lCb3ZIl6vljuUpUc33k9/3aAQjFNyzAd34lqZhsJyzEbyXfZllfgnbN08JGFBmQOPobMNT4ACLbHgRqrk0H7MrDPfWLsjKkDcAOJFGsapCSl4Sm/m3FJ1VMZ4Zr97dMEab3prXRU= 30 | - secure: L5XtZfAiEVWhQw+gvV9fyhWfZ7w0SgjbEgof9vAONurQMeTQXoSI4Tjr0NdEdjMyt0KbcRa66TFZLBRu34OG+z75YtwfMRYooUi64/bfBUOt+pJfUECwha+/IND/vHxMoE68ex9zpb6Q4CJthVRLANyH9DYfzPQw94zsCntRpT7y1y5MeWOdujltgFGefK/igjnfvshHCBBEstk10wuPWwYT5rTjAvSeV7dYFoLYUwd56jOGRGDxR1E8L4xJMMC8glv7dPwkDtEfQ0ss69Nnu/Wv9UNTRGvr8541QGqP8e8NYSg5j/nzcdQRIgwlphX7LuGqzz+4PwtDGvboPnCnRWbCYZiLg3TxtmqTqRYluNNt3tj8YcKzz3CohFrtjSVvk1HLu4eaJsEe84VeET4lk5zZE4wLigTtdWI1DYJGIR/EwgABJZYgV+8QgJPzytP2RnUEUjNNZlnunJ78Uy6q/lS8RHCR4ccNBjK+J52wbIns74Md2xd3K6eUD4/AcaVyROS1pk0znoG1xlVa2WGL/uFcOzeINl623oHzCgsC2dnNa6qEv8gsB+QALYEfQ2eb4425FQ0SWPxzbZu78mYMTcR/U98pqyWn6tZGaoMC24WwbyyJ5ooYtpU02vVO6tI1PPr/29NywESoPlPNdfM1MbMKbyUGgo/kwgYMYfjJtZs= 31 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/health.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // HealthCheck is the definition for an application health check 20 | type HealthCheck struct { 21 | Command *Command `json:"command,omitempty"` 22 | PortIndex *int `json:"portIndex,omitempty"` 23 | Port *int `json:"port,omitempty"` 24 | Path *string `json:"path,omitempty"` 25 | MaxConsecutiveFailures *int `json:"maxConsecutiveFailures,omitempty"` 26 | Protocol string `json:"protocol,omitempty"` 27 | GracePeriodSeconds int `json:"gracePeriodSeconds,omitempty"` 28 | IntervalSeconds int `json:"intervalSeconds,omitempty"` 29 | TimeoutSeconds int `json:"timeoutSeconds,omitempty"` 30 | } 31 | 32 | // SetCommand sets the given command on the health check. 33 | func (h HealthCheck) SetCommand(c Command) HealthCheck { 34 | h.Command = &c 35 | return h 36 | } 37 | 38 | // SetPortIndex sets the given port index on the health check. 39 | func (h HealthCheck) SetPortIndex(i int) HealthCheck { 40 | h.PortIndex = &i 41 | return h 42 | } 43 | 44 | // SetPort sets the given port on the health check. 45 | func (h HealthCheck) SetPort(i int) HealthCheck { 46 | h.Port = &i 47 | return h 48 | } 49 | 50 | // SetPath sets the given path on the health check. 51 | func (h HealthCheck) SetPath(p string) HealthCheck { 52 | h.Path = &p 53 | return h 54 | } 55 | 56 | // SetMaxConsecutiveFailures sets the maximum consecutive failures on the health check. 57 | func (h HealthCheck) SetMaxConsecutiveFailures(i int) HealthCheck { 58 | h.MaxConsecutiveFailures = &i 59 | return h 60 | } 61 | 62 | // NewDefaultHealthCheck creates a default application health check 63 | func NewDefaultHealthCheck() *HealthCheck { 64 | portIndex := 0 65 | path := "" 66 | maxConsecutiveFailures := 3 67 | 68 | return &HealthCheck{ 69 | Protocol: "HTTP", 70 | Path: &path, 71 | PortIndex: &portIndex, 72 | MaxConsecutiveFailures: &maxConsecutiveFailures, 73 | GracePeriodSeconds: 30, 74 | IntervalSeconds: 10, 75 | TimeoutSeconds: 5, 76 | } 77 | } 78 | 79 | // HealthCheckResult is the health check result 80 | type HealthCheckResult struct { 81 | Alive bool `json:"alive"` 82 | ConsecutiveFailures int `json:"consecutiveFailures"` 83 | FirstSuccess string `json:"firstSuccess"` 84 | LastFailure string `json:"lastFailure"` 85 | LastFailureCause string `json:"lastFailureCause"` 86 | LastSuccess string `json:"lastSuccess"` 87 | TaskID string `json:"taskId"` 88 | } 89 | 90 | // Command is the command health check type 91 | type Command struct { 92 | Value string `json:"value"` 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/health.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // HealthCheck is the definition for an application health check 20 | type HealthCheck struct { 21 | Command *Command `json:"command,omitempty"` 22 | PortIndex *int `json:"portIndex,omitempty"` 23 | Port *int `json:"port,omitempty"` 24 | Path *string `json:"path,omitempty"` 25 | MaxConsecutiveFailures *int `json:"maxConsecutiveFailures,omitempty"` 26 | Protocol string `json:"protocol,omitempty"` 27 | GracePeriodSeconds int `json:"gracePeriodSeconds,omitempty"` 28 | IntervalSeconds int `json:"intervalSeconds,omitempty"` 29 | TimeoutSeconds int `json:"timeoutSeconds,omitempty"` 30 | } 31 | 32 | // SetCommand sets the given command on the health check. 33 | func (h HealthCheck) SetCommand(c Command) HealthCheck { 34 | h.Command = &c 35 | return h 36 | } 37 | 38 | // SetPortIndex sets the given port index on the health check. 39 | func (h HealthCheck) SetPortIndex(i int) HealthCheck { 40 | h.PortIndex = &i 41 | return h 42 | } 43 | 44 | // SetPort sets the given port on the health check. 45 | func (h HealthCheck) SetPort(i int) HealthCheck { 46 | h.Port = &i 47 | return h 48 | } 49 | 50 | // SetPath sets the given path on the health check. 51 | func (h HealthCheck) SetPath(p string) HealthCheck { 52 | h.Path = &p 53 | return h 54 | } 55 | 56 | // SetMaxConsecutiveFailures sets the maximum consecutive failures on the health check. 57 | func (h HealthCheck) SetMaxConsecutiveFailures(i int) HealthCheck { 58 | h.MaxConsecutiveFailures = &i 59 | return h 60 | } 61 | 62 | // NewDefaultHealthCheck creates a default application health check 63 | func NewDefaultHealthCheck() *HealthCheck { 64 | portIndex := 0 65 | path := "" 66 | maxConsecutiveFailures := 3 67 | 68 | return &HealthCheck{ 69 | Protocol: "HTTP", 70 | Path: &path, 71 | PortIndex: &portIndex, 72 | MaxConsecutiveFailures: &maxConsecutiveFailures, 73 | GracePeriodSeconds: 30, 74 | IntervalSeconds: 10, 75 | TimeoutSeconds: 5, 76 | } 77 | } 78 | 79 | // HealthCheckResult is the health check result 80 | type HealthCheckResult struct { 81 | Alive bool `json:"alive"` 82 | ConsecutiveFailures int `json:"consecutiveFailures"` 83 | FirstSuccess string `json:"firstSuccess"` 84 | LastFailure string `json:"lastFailure"` 85 | LastFailureCause string `json:"lastFailureCause"` 86 | LastSuccess string `json:"lastSuccess"` 87 | TaskID string `json:"taskId"` 88 | } 89 | 90 | // Command is the command health check type 91 | type Command struct { 92 | Value string `json:"value"` 93 | } 94 | -------------------------------------------------------------------------------- /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/gambol99/go-marathon/info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // Info is the detailed stats returned from marathon info 20 | type Info struct { 21 | EventSubscriber struct { 22 | HTTPEndpoints []string `json:"http_endpoints"` 23 | Type string `json:"type"` 24 | } `json:"event_subscriber"` 25 | FrameworkID string `json:"frameworkId"` 26 | HTTPConfig struct { 27 | AssetsPath interface{} `json:"assets_path"` 28 | HTTPPort float64 `json:"http_port"` 29 | HTTPSPort float64 `json:"https_port"` 30 | } `json:"http_config"` 31 | Leader string `json:"leader"` 32 | MarathonConfig struct { 33 | Checkpoint bool `json:"checkpoint"` 34 | Executor string `json:"executor"` 35 | FailoverTimeout float64 `json:"failover_timeout"` 36 | Ha bool `json:"ha"` 37 | Hostname string `json:"hostname"` 38 | LocalPortMax float64 `json:"local_port_max"` 39 | LocalPortMin float64 `json:"local_port_min"` 40 | Master string `json:"master"` 41 | MesosRole string `json:"mesos_role"` 42 | MesosUser string `json:"mesos_user"` 43 | ReconciliationInitialDelay float64 `json:"reconciliation_initial_delay"` 44 | ReconciliationInterval float64 `json:"reconciliation_interval"` 45 | TaskLaunchTimeout float64 `json:"task_launch_timeout"` 46 | } `json:"marathon_config"` 47 | Name string `json:"name"` 48 | Version string `json:"version"` 49 | ZookeeperConfig struct { 50 | Zk string `json:"zk"` 51 | ZkFutureTimeout struct { 52 | Duration float64 `json:"duration"` 53 | } `json:"zk_future_timeout"` 54 | ZkHosts string `json:"zk_hosts"` 55 | ZkPath string `json:"zk_path"` 56 | ZkState string `json:"zk_state"` 57 | ZkTimeout float64 `json:"zk_timeout"` 58 | } `json:"zookeeper_config"` 59 | } 60 | 61 | // Info retrieves the info stats from marathon 62 | func (r *marathonClient) Info() (*Info, error) { 63 | info := new(Info) 64 | if err := r.apiGet(marathonAPIInfo, nil, info); err != nil { 65 | return nil, err 66 | } 67 | 68 | return info, nil 69 | } 70 | 71 | // Leader retrieves the current marathon leader node 72 | func (r *marathonClient) Leader() (string, error) { 73 | var leader struct { 74 | Leader string `json:"leader"` 75 | } 76 | if err := r.apiGet(marathonAPILeader, nil, &leader); err != nil { 77 | return "", err 78 | } 79 | 80 | return leader.Leader, nil 81 | } 82 | 83 | // AbdicateLeader abdicates the marathon leadership 84 | func (r *marathonClient) AbdicateLeader() (string, error) { 85 | var message struct { 86 | Message string `json:"message"` 87 | } 88 | 89 | if err := r.apiDelete(marathonAPILeader, nil, &message); err != nil { 90 | return "", err 91 | } 92 | 93 | return message.Message, nil 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | // Info is the detailed stats returned from marathon info 20 | type Info struct { 21 | EventSubscriber struct { 22 | HTTPEndpoints []string `json:"http_endpoints"` 23 | Type string `json:"type"` 24 | } `json:"event_subscriber"` 25 | FrameworkID string `json:"frameworkId"` 26 | HTTPConfig struct { 27 | AssetsPath interface{} `json:"assets_path"` 28 | HTTPPort float64 `json:"http_port"` 29 | HTTPSPort float64 `json:"https_port"` 30 | } `json:"http_config"` 31 | Leader string `json:"leader"` 32 | MarathonConfig struct { 33 | Checkpoint bool `json:"checkpoint"` 34 | Executor string `json:"executor"` 35 | FailoverTimeout float64 `json:"failover_timeout"` 36 | Ha bool `json:"ha"` 37 | Hostname string `json:"hostname"` 38 | LocalPortMax float64 `json:"local_port_max"` 39 | LocalPortMin float64 `json:"local_port_min"` 40 | Master string `json:"master"` 41 | MesosRole string `json:"mesos_role"` 42 | MesosUser string `json:"mesos_user"` 43 | ReconciliationInitialDelay float64 `json:"reconciliation_initial_delay"` 44 | ReconciliationInterval float64 `json:"reconciliation_interval"` 45 | TaskLaunchTimeout float64 `json:"task_launch_timeout"` 46 | } `json:"marathon_config"` 47 | Name string `json:"name"` 48 | Version string `json:"version"` 49 | ZookeeperConfig struct { 50 | Zk string `json:"zk"` 51 | ZkFutureTimeout struct { 52 | Duration float64 `json:"duration"` 53 | } `json:"zk_future_timeout"` 54 | ZkHosts string `json:"zk_hosts"` 55 | ZkPath string `json:"zk_path"` 56 | ZkState string `json:"zk_state"` 57 | ZkTimeout float64 `json:"zk_timeout"` 58 | } `json:"zookeeper_config"` 59 | } 60 | 61 | // Info retrieves the info stats from marathon 62 | func (r *marathonClient) Info() (*Info, error) { 63 | info := new(Info) 64 | if err := r.apiGet(marathonAPIInfo, nil, info); err != nil { 65 | return nil, err 66 | } 67 | 68 | return info, nil 69 | } 70 | 71 | // Leader retrieves the current marathon leader node 72 | func (r *marathonClient) Leader() (string, error) { 73 | var leader struct { 74 | Leader string `json:"leader"` 75 | } 76 | if err := r.apiGet(marathonAPILeader, nil, &leader); err != nil { 77 | return "", err 78 | } 79 | 80 | return leader.Leader, nil 81 | } 82 | 83 | // AbdicateLeader abdicates the marathon leadership 84 | func (r *marathonClient) AbdicateLeader() (string, error) { 85 | var message struct { 86 | Message string `json:"message"` 87 | } 88 | 89 | if err := r.apiDelete(marathonAPILeader, nil, &message); err != nil { 90 | return "", err 91 | } 92 | 93 | return message.Message, nil 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/log/syslog_formatter.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 | // +build !windows,!nacl,!plan9 15 | 16 | package log 17 | 18 | import ( 19 | "fmt" 20 | "log/syslog" 21 | "os" 22 | 23 | "github.com/Sirupsen/logrus" 24 | ) 25 | 26 | func init() { 27 | setSyslogFormatter = func(appname, local string) error { 28 | if appname == "" { 29 | return fmt.Errorf("missing appname parameter") 30 | } 31 | if local == "" { 32 | return fmt.Errorf("missing local parameter") 33 | } 34 | 35 | fmter, err := newSyslogger(appname, local, origLogger.Formatter) 36 | if err != nil { 37 | fmt.Fprintf(os.Stderr, "error creating syslog formatter: %v\n", err) 38 | origLogger.Errorf("can't connect logger to syslog: %v", err) 39 | return err 40 | } 41 | origLogger.Formatter = fmter 42 | return nil 43 | } 44 | } 45 | 46 | var ceeTag = []byte("@cee:") 47 | 48 | type syslogger struct { 49 | wrap logrus.Formatter 50 | out *syslog.Writer 51 | } 52 | 53 | func newSyslogger(appname string, facility string, fmter logrus.Formatter) (*syslogger, error) { 54 | priority, err := getFacility(facility) 55 | if err != nil { 56 | return nil, err 57 | } 58 | out, err := syslog.New(priority, appname) 59 | return &syslogger{ 60 | out: out, 61 | wrap: fmter, 62 | }, err 63 | } 64 | 65 | func getFacility(facility string) (syslog.Priority, error) { 66 | switch facility { 67 | case "0": 68 | return syslog.LOG_LOCAL0, nil 69 | case "1": 70 | return syslog.LOG_LOCAL1, nil 71 | case "2": 72 | return syslog.LOG_LOCAL2, nil 73 | case "3": 74 | return syslog.LOG_LOCAL3, nil 75 | case "4": 76 | return syslog.LOG_LOCAL4, nil 77 | case "5": 78 | return syslog.LOG_LOCAL5, nil 79 | case "6": 80 | return syslog.LOG_LOCAL6, nil 81 | case "7": 82 | return syslog.LOG_LOCAL7, nil 83 | } 84 | return syslog.LOG_LOCAL0, fmt.Errorf("invalid local(%s) for syslog", facility) 85 | } 86 | 87 | func (s *syslogger) Format(e *logrus.Entry) ([]byte, error) { 88 | data, err := s.wrap.Format(e) 89 | if err != nil { 90 | fmt.Fprintf(os.Stderr, "syslogger: can't format entry: %v\n", err) 91 | return data, err 92 | } 93 | // only append tag to data sent to syslog (line), not to what 94 | // is returned 95 | line := string(append(ceeTag, data...)) 96 | 97 | switch e.Level { 98 | case logrus.PanicLevel: 99 | err = s.out.Crit(line) 100 | case logrus.FatalLevel: 101 | err = s.out.Crit(line) 102 | case logrus.ErrorLevel: 103 | err = s.out.Err(line) 104 | case logrus.WarnLevel: 105 | err = s.out.Warning(line) 106 | case logrus.InfoLevel: 107 | err = s.out.Info(line) 108 | case logrus.DebugLevel: 109 | err = s.out.Debug(line) 110 | default: 111 | err = s.out.Notice(line) 112 | } 113 | 114 | if err != nil { 115 | fmt.Fprintf(os.Stderr, "syslogger: can't send log to syslog: %v\n", err) 116 | } 117 | 118 | return data, err 119 | } 120 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "net" 23 | "net/url" 24 | "reflect" 25 | "strings" 26 | "sync/atomic" 27 | "time" 28 | 29 | "github.com/google/go-querystring/query" 30 | ) 31 | 32 | type atomicSwitch int64 33 | 34 | func (r *atomicSwitch) IsSwitched() bool { 35 | return atomic.LoadInt64((*int64)(r)) != 0 36 | } 37 | 38 | func (r *atomicSwitch) SwitchOn() { 39 | atomic.StoreInt64((*int64)(r), 1) 40 | } 41 | 42 | func (r *atomicSwitch) SwitchedOff() { 43 | atomic.StoreInt64((*int64)(r), 0) 44 | } 45 | 46 | func validateID(id string) string { 47 | if !strings.HasPrefix(id, "/") { 48 | return fmt.Sprintf("/%s", id) 49 | } 50 | return id 51 | } 52 | 53 | func trimRootPath(id string) string { 54 | if strings.HasPrefix(id, "/") { 55 | return strings.TrimPrefix(id, "/") 56 | } 57 | return id 58 | } 59 | 60 | func deadline(timeout time.Duration, work func(chan bool) error) error { 61 | result := make(chan error) 62 | timer := time.After(timeout) 63 | stopChannel := make(chan bool, 1) 64 | 65 | // allow the method to attempt 66 | go func() { 67 | result <- work(stopChannel) 68 | }() 69 | for { 70 | select { 71 | case err := <-result: 72 | return err 73 | case <-timer: 74 | stopChannel <- true 75 | return ErrTimeoutError 76 | } 77 | } 78 | } 79 | 80 | func getInterfaceAddress(name string) (string, error) { 81 | interfaces, err := net.Interfaces() 82 | if err != nil { 83 | return "", err 84 | } 85 | for _, iface := range interfaces { 86 | // step: get only the interface we're interested in 87 | if iface.Name == name { 88 | addrs, err := iface.Addrs() 89 | if err != nil { 90 | return "", err 91 | } 92 | // step: return the first address 93 | if len(addrs) > 0 { 94 | return parseIPAddr(addrs[0]), nil 95 | } 96 | } 97 | } 98 | 99 | return "", errors.New("Unable to determine or find the interface") 100 | } 101 | 102 | func contains(elements []string, value string) bool { 103 | for _, element := range elements { 104 | if element == value { 105 | return true 106 | } 107 | } 108 | return false 109 | } 110 | 111 | func parseIPAddr(addr net.Addr) string { 112 | return strings.SplitN(addr.String(), "/", 2)[0] 113 | } 114 | 115 | // addOptions adds the parameters in opt as URL query parameters to s. 116 | // opt must be a struct whose fields may contain "url" tags. 117 | func addOptions(s string, opt interface{}) (string, error) { 118 | v := reflect.ValueOf(opt) 119 | if v.Kind() == reflect.Ptr && v.IsNil() { 120 | return s, nil 121 | } 122 | 123 | u, err := url.Parse(s) 124 | if err != nil { 125 | return s, err 126 | } 127 | 128 | qs, err := query.Values(opt) 129 | if err != nil { 130 | return s, err 131 | } 132 | 133 | u.RawQuery = qs.Encode() 134 | return u.String(), nil 135 | } 136 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 Rohith All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package marathon 18 | 19 | import ( 20 | "errors" 21 | "fmt" 22 | "net" 23 | "net/url" 24 | "reflect" 25 | "strings" 26 | "sync/atomic" 27 | "time" 28 | 29 | "github.com/google/go-querystring/query" 30 | ) 31 | 32 | type atomicSwitch int64 33 | 34 | func (r *atomicSwitch) IsSwitched() bool { 35 | return atomic.LoadInt64((*int64)(r)) != 0 36 | } 37 | 38 | func (r *atomicSwitch) SwitchOn() { 39 | atomic.StoreInt64((*int64)(r), 1) 40 | } 41 | 42 | func (r *atomicSwitch) SwitchedOff() { 43 | atomic.StoreInt64((*int64)(r), 0) 44 | } 45 | 46 | func validateID(id string) string { 47 | if !strings.HasPrefix(id, "/") { 48 | return fmt.Sprintf("/%s", id) 49 | } 50 | return id 51 | } 52 | 53 | func trimRootPath(id string) string { 54 | if strings.HasPrefix(id, "/") { 55 | return strings.TrimPrefix(id, "/") 56 | } 57 | return id 58 | } 59 | 60 | func deadline(timeout time.Duration, work func(chan bool) error) error { 61 | result := make(chan error) 62 | timer := time.After(timeout) 63 | stopChannel := make(chan bool, 1) 64 | 65 | // allow the method to attempt 66 | go func() { 67 | result <- work(stopChannel) 68 | }() 69 | for { 70 | select { 71 | case err := <-result: 72 | return err 73 | case <-timer: 74 | stopChannel <- true 75 | return ErrTimeoutError 76 | } 77 | } 78 | } 79 | 80 | func getInterfaceAddress(name string) (string, error) { 81 | interfaces, err := net.Interfaces() 82 | if err != nil { 83 | return "", err 84 | } 85 | for _, iface := range interfaces { 86 | // step: get only the interface we're interested in 87 | if iface.Name == name { 88 | addrs, err := iface.Addrs() 89 | if err != nil { 90 | return "", err 91 | } 92 | // step: return the first address 93 | if len(addrs) > 0 { 94 | return parseIPAddr(addrs[0]), nil 95 | } 96 | } 97 | } 98 | 99 | return "", errors.New("Unable to determine or find the interface") 100 | } 101 | 102 | func contains(elements []string, value string) bool { 103 | for _, element := range elements { 104 | if element == value { 105 | return true 106 | } 107 | } 108 | return false 109 | } 110 | 111 | func parseIPAddr(addr net.Addr) string { 112 | return strings.SplitN(addr.String(), "/", 2)[0] 113 | } 114 | 115 | // addOptions adds the parameters in opt as URL query parameters to s. 116 | // opt must be a struct whose fields may contain "url" tags. 117 | func addOptions(s string, opt interface{}) (string, error) { 118 | v := reflect.ValueOf(opt) 119 | if v.Kind() == reflect.Ptr && v.IsNil() { 120 | return s, nil 121 | } 122 | 123 | u, err := url.Parse(s) 124 | if err != nil { 125 | return s, err 126 | } 127 | 128 | qs, err := query.Values(opt) 129 | if err != nil { 130 | return s, err 131 | } 132 | 133 | u.RawQuery = qs.Encode() 134 | return u.String(), nil 135 | } 136 | -------------------------------------------------------------------------------- /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 Register, MustRegister, RegisterOrGet, and MustRegisterOrGet. 19 | // 20 | // The stock metrics provided by this package (like Gauge, Counter, Summary) are 21 | // also Collectors (which only ever collect one metric, namely itself). An 22 | // implementer of Collector may, however, collect multiple metrics in a 23 | // coordinated fashion and/or create metrics on the fly. Examples for collectors 24 | // already implemented in this library are the metric vectors (i.e. collection 25 | // of multiple instances of the same Metric but with different label values) 26 | // 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 Prometheus when collecting metrics. The 41 | // implementation sends each collected metric via the provided channel 42 | // and returns once the last metric has been sent. The descriptor of 43 | // each sent metric is one of those returned by Describe. Returned 44 | // metrics that share the same descriptor must differ in their variable 45 | // label values. This method may be called concurrently and must 46 | // therefore be implemented in a concurrency safe way. Blocking occurs 47 | // at the expense of total performance of rendering all registered 48 | // metrics. Ideally, Collector implementations support concurrent 49 | // readers. 50 | Collect(chan<- Metric) 51 | } 52 | 53 | // SelfCollector implements Collector for a single Metric so that that the 54 | // Metric collects itself. Add it as an anonymous field to a struct that 55 | // implements 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/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "yXrS4e4yxaRBu/MX+39X3cS4kbg=", 7 | "path": "github.com/Sirupsen/logrus", 8 | "revision": "a283a10442df8dc09befd873fab202bf8a253d6a", 9 | "revisionTime": "2016-07-16T02:56:31Z" 10 | }, 11 | { 12 | "checksumSHA1": "4QnLdmB1kG3N+KlDd1N+G9TWAGQ=", 13 | "path": "github.com/beorn7/perks/quantile", 14 | "revision": "3ac7bf7a47d159a033b107610db8a1b6575507a4", 15 | "revisionTime": "2016-02-29T21:34:45Z" 16 | }, 17 | { 18 | "checksumSHA1": "O/eUfUoi7lWgZiipUP939AAdKk4=", 19 | "origin": "github.com/gambol99/go-marathon/vendor/github.com/donovanhide/eventsource", 20 | "path": "github.com/donovanhide/eventsource", 21 | "revision": "e6dc89572b363835b1222dce4810c83d7757514e", 22 | "revisionTime": "2016-11-07T14:32:42Z" 23 | }, 24 | { 25 | "checksumSHA1": "MLTVo33+2kBWuF5aAVMzOg8Ku8M=", 26 | "path": "github.com/gambol99/go-marathon", 27 | "revision": "e6dc89572b363835b1222dce4810c83d7757514e", 28 | "revisionTime": "2016-11-07T14:32:42Z" 29 | }, 30 | { 31 | "checksumSHA1": "5MVpi9U1WCrzZ1VMMn61Fc+trE0=", 32 | "path": "github.com/golang/protobuf/proto", 33 | "revision": "c3cefd437628a0b7d31b34fe44b3a7a540e98527", 34 | "revisionTime": "2016-07-27T17:26:17Z" 35 | }, 36 | { 37 | "checksumSHA1": "yyAzHoiVLu+xywYI2BDyRq6sOqE=", 38 | "origin": "github.com/gambol99/go-marathon/vendor/github.com/google/go-querystring/query", 39 | "path": "github.com/google/go-querystring/query", 40 | "revision": "e6dc89572b363835b1222dce4810c83d7757514e", 41 | "revisionTime": "2016-11-07T14:32:42Z" 42 | }, 43 | { 44 | "checksumSHA1": "17v7y+3r/KG8PPYIolf+zSAifbs=", 45 | "path": "github.com/jeffail/gabs", 46 | "revision": "855034b6b7a3b7144977efcaefe72d2c64b0d039", 47 | "revisionTime": "2016-08-09T16:55:30Z" 48 | }, 49 | { 50 | "checksumSHA1": "AEmfVw8uamcLRIEe1v74vDIIPaE=", 51 | "path": "github.com/matt-deboer/go-marathon", 52 | "revision": "2e43425f10404af7a7db643b9f8c10edf2b0bf8f", 53 | "revisionTime": "2016-11-16T00:53:54Z" 54 | }, 55 | { 56 | "checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=", 57 | "path": "github.com/matttproud/golang_protobuf_extensions/pbutil", 58 | "revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c", 59 | "revisionTime": "2016-04-24T11:30:07Z" 60 | }, 61 | { 62 | "checksumSHA1": "E9hLErovYB3phLHwM/OoyL0d+hs=", 63 | "path": "github.com/prometheus/client_golang/prometheus", 64 | "revision": "28be15864ef9ba05d74fa6fd13b928fd250e8f01", 65 | "revisionTime": "2016-07-11T22:22:38Z" 66 | }, 67 | { 68 | "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=", 69 | "path": "github.com/prometheus/client_model/go", 70 | "revision": "fa8ad6fec33561be4280a8f0514318c79d7f6cb6", 71 | "revisionTime": "2015-02-12T10:17:44Z" 72 | }, 73 | { 74 | "checksumSHA1": "OFZ6f2tsxQ+pk+wl7474eIxBs80=", 75 | "path": "github.com/prometheus/common/expfmt", 76 | "revision": "ebdfc6da46522d58825777cf1f90490a5b1ef1d8", 77 | "revisionTime": "2016-08-01T17:19:55Z" 78 | }, 79 | { 80 | "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=", 81 | "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", 82 | "revision": "ebdfc6da46522d58825777cf1f90490a5b1ef1d8", 83 | "revisionTime": "2016-08-01T17:19:55Z" 84 | }, 85 | { 86 | "checksumSHA1": "fKMoxZehNhXbklRQy7lpFAVH0XY=", 87 | "path": "github.com/prometheus/common/log", 88 | "revision": "ebdfc6da46522d58825777cf1f90490a5b1ef1d8", 89 | "revisionTime": "2016-08-01T17:19:55Z" 90 | }, 91 | { 92 | "checksumSHA1": "Jx0GXl5hGnO25s3ryyvtdWHdCpw=", 93 | "path": "github.com/prometheus/common/model", 94 | "revision": "ebdfc6da46522d58825777cf1f90490a5b1ef1d8", 95 | "revisionTime": "2016-08-01T17:19:55Z" 96 | }, 97 | { 98 | "checksumSHA1": "W218eJZPXJG783fUr/z6IaAZyes=", 99 | "path": "github.com/prometheus/procfs", 100 | "revision": "abf152e5f3e97f2fafac028d2cc06c1feb87ffa5", 101 | "revisionTime": "2016-04-11T19:08:41Z" 102 | } 103 | ], 104 | "rootPath": "github.com/gettyimages/marathon_exporter" 105 | } 106 | -------------------------------------------------------------------------------- /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/Sirupsen/logrus/text_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "runtime" 7 | "sort" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | const ( 13 | nocolor = 0 14 | red = 31 15 | green = 32 16 | yellow = 33 17 | blue = 34 18 | gray = 37 19 | ) 20 | 21 | var ( 22 | baseTimestamp time.Time 23 | isTerminal bool 24 | ) 25 | 26 | func init() { 27 | baseTimestamp = time.Now() 28 | isTerminal = IsTerminal() 29 | } 30 | 31 | func miniTS() int { 32 | return int(time.Since(baseTimestamp) / time.Second) 33 | } 34 | 35 | type TextFormatter struct { 36 | // Set to true to bypass checking for a TTY before outputting colors. 37 | ForceColors bool 38 | 39 | // Force disabling colors. 40 | DisableColors bool 41 | 42 | // Disable timestamp logging. useful when output is redirected to logging 43 | // system that already adds timestamps. 44 | DisableTimestamp bool 45 | 46 | // Enable logging the full timestamp when a TTY is attached instead of just 47 | // the time passed since beginning of execution. 48 | FullTimestamp bool 49 | 50 | // TimestampFormat to use for display when a full timestamp is printed 51 | TimestampFormat string 52 | 53 | // The fields are sorted by default for a consistent output. For applications 54 | // that log extremely frequently and don't use the JSON formatter this may not 55 | // be desired. 56 | DisableSorting bool 57 | } 58 | 59 | func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { 60 | var keys []string = make([]string, 0, len(entry.Data)) 61 | for k := range entry.Data { 62 | keys = append(keys, k) 63 | } 64 | 65 | if !f.DisableSorting { 66 | sort.Strings(keys) 67 | } 68 | 69 | b := &bytes.Buffer{} 70 | 71 | prefixFieldClashes(entry.Data) 72 | 73 | isColorTerminal := isTerminal && (runtime.GOOS != "windows") 74 | isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors 75 | 76 | timestampFormat := f.TimestampFormat 77 | if timestampFormat == "" { 78 | timestampFormat = DefaultTimestampFormat 79 | } 80 | if isColored { 81 | f.printColored(b, entry, keys, timestampFormat) 82 | } else { 83 | if !f.DisableTimestamp { 84 | f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) 85 | } 86 | f.appendKeyValue(b, "level", entry.Level.String()) 87 | if entry.Message != "" { 88 | f.appendKeyValue(b, "msg", entry.Message) 89 | } 90 | for _, key := range keys { 91 | f.appendKeyValue(b, key, entry.Data[key]) 92 | } 93 | } 94 | 95 | b.WriteByte('\n') 96 | return b.Bytes(), nil 97 | } 98 | 99 | func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { 100 | var levelColor int 101 | switch entry.Level { 102 | case DebugLevel: 103 | levelColor = gray 104 | case WarnLevel: 105 | levelColor = yellow 106 | case ErrorLevel, FatalLevel, PanicLevel: 107 | levelColor = red 108 | default: 109 | levelColor = blue 110 | } 111 | 112 | levelText := strings.ToUpper(entry.Level.String())[0:4] 113 | 114 | if !f.FullTimestamp { 115 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message) 116 | } else { 117 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) 118 | } 119 | for _, k := range keys { 120 | v := entry.Data[k] 121 | fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v) 122 | } 123 | } 124 | 125 | func needsQuoting(text string) bool { 126 | for _, ch := range text { 127 | if !((ch >= 'a' && ch <= 'z') || 128 | (ch >= 'A' && ch <= 'Z') || 129 | (ch >= '0' && ch <= '9') || 130 | ch == '-' || ch == '.') { 131 | return true 132 | } 133 | } 134 | return false 135 | } 136 | 137 | func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { 138 | 139 | b.WriteString(key) 140 | b.WriteByte('=') 141 | 142 | switch value := value.(type) { 143 | case string: 144 | if !needsQuoting(value) { 145 | b.WriteString(value) 146 | } else { 147 | fmt.Fprintf(b, "%q", value) 148 | } 149 | case error: 150 | errmsg := value.Error() 151 | if !needsQuoting(errmsg) { 152 | b.WriteString(errmsg) 153 | } else { 154 | fmt.Fprintf(b, "%q", value) 155 | } 156 | default: 157 | fmt.Fprint(b, value) 158 | } 159 | 160 | b.WriteByte(' ') 161 | } 162 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/logrus.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strings" 7 | ) 8 | 9 | // Fields type, used to pass to `WithFields`. 10 | type Fields map[string]interface{} 11 | 12 | // Level type 13 | type Level uint8 14 | 15 | // Convert the Level to a string. E.g. PanicLevel becomes "panic". 16 | func (level Level) String() string { 17 | switch level { 18 | case DebugLevel: 19 | return "debug" 20 | case InfoLevel: 21 | return "info" 22 | case WarnLevel: 23 | return "warning" 24 | case ErrorLevel: 25 | return "error" 26 | case FatalLevel: 27 | return "fatal" 28 | case PanicLevel: 29 | return "panic" 30 | } 31 | 32 | return "unknown" 33 | } 34 | 35 | // ParseLevel takes a string level and returns the Logrus log level constant. 36 | func ParseLevel(lvl string) (Level, error) { 37 | switch strings.ToLower(lvl) { 38 | case "panic": 39 | return PanicLevel, nil 40 | case "fatal": 41 | return FatalLevel, nil 42 | case "error": 43 | return ErrorLevel, nil 44 | case "warn", "warning": 45 | return WarnLevel, nil 46 | case "info": 47 | return InfoLevel, nil 48 | case "debug": 49 | return DebugLevel, nil 50 | } 51 | 52 | var l Level 53 | return l, fmt.Errorf("not a valid logrus Level: %q", lvl) 54 | } 55 | 56 | // A constant exposing all logging levels 57 | var AllLevels = []Level{ 58 | PanicLevel, 59 | FatalLevel, 60 | ErrorLevel, 61 | WarnLevel, 62 | InfoLevel, 63 | DebugLevel, 64 | } 65 | 66 | // These are the different logging levels. You can set the logging level to log 67 | // on your instance of logger, obtained with `logrus.New()`. 68 | const ( 69 | // PanicLevel level, highest level of severity. Logs and then calls panic with the 70 | // message passed to Debug, Info, ... 71 | PanicLevel Level = iota 72 | // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the 73 | // logging level is set to Panic. 74 | FatalLevel 75 | // ErrorLevel level. Logs. Used for errors that should definitely be noted. 76 | // Commonly used for hooks to send errors to an error tracking service. 77 | ErrorLevel 78 | // WarnLevel level. Non-critical entries that deserve eyes. 79 | WarnLevel 80 | // InfoLevel level. General operational entries about what's going on inside the 81 | // application. 82 | InfoLevel 83 | // DebugLevel level. Usually only enabled when debugging. Very verbose logging. 84 | DebugLevel 85 | ) 86 | 87 | // Won't compile if StdLogger can't be realized by a log.Logger 88 | var ( 89 | _ StdLogger = &log.Logger{} 90 | _ StdLogger = &Entry{} 91 | _ StdLogger = &Logger{} 92 | ) 93 | 94 | // StdLogger is what your logrus-enabled library should take, that way 95 | // it'll accept a stdlib logger and a logrus logger. There's no standard 96 | // interface, this is the closest we get, unfortunately. 97 | type StdLogger interface { 98 | Print(...interface{}) 99 | Printf(string, ...interface{}) 100 | Println(...interface{}) 101 | 102 | Fatal(...interface{}) 103 | Fatalf(string, ...interface{}) 104 | Fatalln(...interface{}) 105 | 106 | Panic(...interface{}) 107 | Panicf(string, ...interface{}) 108 | Panicln(...interface{}) 109 | } 110 | 111 | // The FieldLogger interface generalizes the Entry and Logger types 112 | type FieldLogger interface { 113 | WithField(key string, value interface{}) *Entry 114 | WithFields(fields Fields) *Entry 115 | WithError(err error) *Entry 116 | 117 | Debugf(format string, args ...interface{}) 118 | Infof(format string, args ...interface{}) 119 | Printf(format string, args ...interface{}) 120 | Warnf(format string, args ...interface{}) 121 | Warningf(format string, args ...interface{}) 122 | Errorf(format string, args ...interface{}) 123 | Fatalf(format string, args ...interface{}) 124 | Panicf(format string, args ...interface{}) 125 | 126 | Debug(args ...interface{}) 127 | Info(args ...interface{}) 128 | Print(args ...interface{}) 129 | Warn(args ...interface{}) 130 | Warning(args ...interface{}) 131 | Error(args ...interface{}) 132 | Fatal(args ...interface{}) 133 | Panic(args ...interface{}) 134 | 135 | Debugln(args ...interface{}) 136 | Infoln(args ...interface{}) 137 | Println(args ...interface{}) 138 | Warnln(args ...interface{}) 139 | Warningln(args ...interface{}) 140 | Errorln(args ...interface{}) 141 | Fatalln(args ...interface{}) 142 | Panicln(args ...interface{}) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/alert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "time" 19 | ) 20 | 21 | type AlertStatus string 22 | 23 | const ( 24 | AlertFiring AlertStatus = "firing" 25 | AlertResolved AlertStatus = "resolved" 26 | ) 27 | 28 | // Alert is a generic representation of an alert in the Prometheus eco-system. 29 | type Alert struct { 30 | // Label value pairs for purpose of aggregation, matching, and disposition 31 | // dispatching. This must minimally include an "alertname" label. 32 | Labels LabelSet `json:"labels"` 33 | 34 | // Extra key/value information which does not define alert identity. 35 | Annotations LabelSet `json:"annotations"` 36 | 37 | // The known time range for this alert. Both ends are optional. 38 | StartsAt time.Time `json:"startsAt,omitempty"` 39 | EndsAt time.Time `json:"endsAt,omitempty"` 40 | GeneratorURL string `json:"generatorURL"` 41 | } 42 | 43 | // Name returns the name of the alert. It is equivalent to the "alertname" label. 44 | func (a *Alert) Name() string { 45 | return string(a.Labels[AlertNameLabel]) 46 | } 47 | 48 | // Fingerprint returns a unique hash for the alert. It is equivalent to 49 | // the fingerprint of the alert's label set. 50 | func (a *Alert) Fingerprint() Fingerprint { 51 | return a.Labels.Fingerprint() 52 | } 53 | 54 | func (a *Alert) String() string { 55 | s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7]) 56 | if a.Resolved() { 57 | return s + "[resolved]" 58 | } 59 | return s + "[active]" 60 | } 61 | 62 | // Resolved returns true iff the activity interval ended in the past. 63 | func (a *Alert) Resolved() bool { 64 | return a.ResolvedAt(time.Now()) 65 | } 66 | 67 | // ResolvedAt returns true off the activity interval ended before 68 | // the given timestamp. 69 | func (a *Alert) ResolvedAt(ts time.Time) bool { 70 | if a.EndsAt.IsZero() { 71 | return false 72 | } 73 | return !a.EndsAt.After(ts) 74 | } 75 | 76 | // Status returns the status of the alert. 77 | func (a *Alert) Status() AlertStatus { 78 | if a.Resolved() { 79 | return AlertResolved 80 | } 81 | return AlertFiring 82 | } 83 | 84 | // Validate checks whether the alert data is inconsistent. 85 | func (a *Alert) Validate() error { 86 | if a.StartsAt.IsZero() { 87 | return fmt.Errorf("start time missing") 88 | } 89 | if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { 90 | return fmt.Errorf("start time must be before end time") 91 | } 92 | if err := a.Labels.Validate(); err != nil { 93 | return fmt.Errorf("invalid label set: %s", err) 94 | } 95 | if len(a.Labels) == 0 { 96 | return fmt.Errorf("at least one label pair required") 97 | } 98 | if err := a.Annotations.Validate(); err != nil { 99 | return fmt.Errorf("invalid annotations: %s", err) 100 | } 101 | return nil 102 | } 103 | 104 | // Alert is a list of alerts that can be sorted in chronological order. 105 | type Alerts []*Alert 106 | 107 | func (as Alerts) Len() int { return len(as) } 108 | func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] } 109 | 110 | func (as Alerts) Less(i, j int) bool { 111 | if as[i].StartsAt.Before(as[j].StartsAt) { 112 | return true 113 | } 114 | if as[i].EndsAt.Before(as[j].EndsAt) { 115 | return true 116 | } 117 | return as[i].Fingerprint() < as[j].Fingerprint() 118 | } 119 | 120 | // HasFiring returns true iff one of the alerts is not resolved. 121 | func (as Alerts) HasFiring() bool { 122 | for _, a := range as { 123 | if !a.Resolved() { 124 | return true 125 | } 126 | } 127 | return false 128 | } 129 | 130 | // Status returns StatusFiring iff at least one of the alerts is firing. 131 | func (as Alerts) Status() AlertStatus { 132 | if as.HasFiring() { 133 | return AlertFiring 134 | } 135 | return AlertResolved 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_limits.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "strconv" 9 | ) 10 | 11 | // ProcLimits represents the soft limits for each of the process's resource 12 | // limits. For more information see getrlimit(2): 13 | // http://man7.org/linux/man-pages/man2/getrlimit.2.html. 14 | type ProcLimits struct { 15 | // CPU time limit in seconds. 16 | CPUTime int 17 | // Maximum size of files that the process may create. 18 | FileSize int 19 | // Maximum size of the process's data segment (initialized data, 20 | // uninitialized data, and heap). 21 | DataSize int 22 | // Maximum size of the process stack in bytes. 23 | StackSize int 24 | // Maximum size of a core file. 25 | CoreFileSize int 26 | // Limit of the process's resident set in pages. 27 | ResidentSet int 28 | // Maximum number of processes that can be created for the real user ID of 29 | // the calling process. 30 | Processes int 31 | // Value one greater than the maximum file descriptor number that can be 32 | // opened by this process. 33 | OpenFiles int 34 | // Maximum number of bytes of memory that may be locked into RAM. 35 | LockedMemory int 36 | // Maximum size of the process's virtual memory address space in bytes. 37 | AddressSpace int 38 | // Limit on the combined number of flock(2) locks and fcntl(2) leases that 39 | // this process may establish. 40 | FileLocks int 41 | // Limit of signals that may be queued for the real user ID of the calling 42 | // process. 43 | PendingSignals int 44 | // Limit on the number of bytes that can be allocated for POSIX message 45 | // queues for the real user ID of the calling process. 46 | MsqqueueSize int 47 | // Limit of the nice priority set using setpriority(2) or nice(2). 48 | NicePriority int 49 | // Limit of the real-time priority set using sched_setscheduler(2) or 50 | // sched_setparam(2). 51 | RealtimePriority int 52 | // Limit (in microseconds) on the amount of CPU time that a process 53 | // scheduled under a real-time scheduling policy may consume without making 54 | // a blocking system call. 55 | RealtimeTimeout int 56 | } 57 | 58 | const ( 59 | limitsFields = 3 60 | limitsUnlimited = "unlimited" 61 | ) 62 | 63 | var ( 64 | limitsDelimiter = regexp.MustCompile(" +") 65 | ) 66 | 67 | // NewLimits returns the current soft limits of the process. 68 | func (p Proc) NewLimits() (ProcLimits, error) { 69 | f, err := os.Open(p.path("limits")) 70 | if err != nil { 71 | return ProcLimits{}, err 72 | } 73 | defer f.Close() 74 | 75 | var ( 76 | l = ProcLimits{} 77 | s = bufio.NewScanner(f) 78 | ) 79 | for s.Scan() { 80 | fields := limitsDelimiter.Split(s.Text(), limitsFields) 81 | if len(fields) != limitsFields { 82 | return ProcLimits{}, fmt.Errorf( 83 | "couldn't parse %s line %s", f.Name(), s.Text()) 84 | } 85 | 86 | switch fields[0] { 87 | case "Max cpu time": 88 | l.CPUTime, err = parseInt(fields[1]) 89 | case "Max file size": 90 | l.FileSize, err = parseInt(fields[1]) 91 | case "Max data size": 92 | l.DataSize, err = parseInt(fields[1]) 93 | case "Max stack size": 94 | l.StackSize, err = parseInt(fields[1]) 95 | case "Max core file size": 96 | l.CoreFileSize, err = parseInt(fields[1]) 97 | case "Max resident set": 98 | l.ResidentSet, err = parseInt(fields[1]) 99 | case "Max processes": 100 | l.Processes, err = parseInt(fields[1]) 101 | case "Max open files": 102 | l.OpenFiles, err = parseInt(fields[1]) 103 | case "Max locked memory": 104 | l.LockedMemory, err = parseInt(fields[1]) 105 | case "Max address space": 106 | l.AddressSpace, err = parseInt(fields[1]) 107 | case "Max file locks": 108 | l.FileLocks, err = parseInt(fields[1]) 109 | case "Max pending signals": 110 | l.PendingSignals, err = parseInt(fields[1]) 111 | case "Max msgqueue size": 112 | l.MsqqueueSize, err = parseInt(fields[1]) 113 | case "Max nice priority": 114 | l.NicePriority, err = parseInt(fields[1]) 115 | case "Max realtime priority": 116 | l.RealtimePriority, err = parseInt(fields[1]) 117 | case "Max realtime timeout": 118 | l.RealtimeTimeout, err = parseInt(fields[1]) 119 | } 120 | if err != nil { 121 | return ProcLimits{}, err 122 | } 123 | } 124 | 125 | return l, s.Err() 126 | } 127 | 128 | func parseInt(s string) (int, error) { 129 | if s == limitsUnlimited { 130 | return -1, nil 131 | } 132 | i, err := strconv.ParseInt(s, 10, 32) 133 | if err != nil { 134 | return 0, fmt.Errorf("couldn't parse value %s: %s", s, err) 135 | } 136 | return int(i), nil 137 | } 138 | -------------------------------------------------------------------------------- /vendor/github.com/gambol99/go-marathon/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [Unreleased] 8 | 9 | ## [0.5.0] - 2016-11-07 10 | ### Fixed 11 | - [#231][PR231] Fixed Marathon cluster code 12 | - [#229][PR229] Add LastFailureCause field to HealthCheckResult. 13 | 14 | ## [0.4.0] - 2016-10-28 15 | ### Added 16 | - [#223][PR223] Add support for IP-per-task. 17 | - [#220][PR220] Add external volume definition to container. 18 | - [#211][PR211] Close event channel on event listener removal. 19 | 20 | ### Fixed 21 | - [#218][PR218] Remove TimeWaitPolling from marathonClient. 22 | - [#214][PR214] Remove extra pointer layers when passing to r.api*. 23 | 24 | ## [0.3.0] - 2016-09-28 25 | - [#201][PR201]: Subscribe method is now exposed on the client to allow subscription of callback URL's 26 | 27 | ### Fixed 28 | - [#205][PR205]: Fix memory leak by signalling goroutine termination on event listener removal. 29 | 30 | ### Changed 31 | - [#205][PR205]: Change AddEventsListener to return event channel instead of taking one. 32 | 33 | ## [0.2.0] - 2016-09-23 34 | ### Added 35 | - [#196][PR196]: Port definitions. 36 | - [#191][PR191]: name and labels to portMappings. 37 | 38 | ### Changed 39 | - [#191][PR191] ExposePort() now takes a portMapping instance. 40 | 41 | ### Fixed 42 | - [#202][PR202]: Timeout error in WaitOnApplication. 43 | 44 | ## [0.1.1] - 2016-09-07 45 | ### Fixed 46 | - Drop question mark-only query parameter in Applications(url.Values) manually 47 | due to changed behavior in Go 1.7's net/url.Parse. 48 | 49 | ## [0.1.0] - 2016-08-01 50 | ### Added 51 | - Field `message` to the EventStatusUpdate struct. 52 | - Method `Host()` to set host mode explicitly. 53 | - Field `port` to HealthCheck. 54 | - Support for launch queues. 55 | - Convenience method `AddFetchURIs()`. 56 | - Support for forced operations across all methods. 57 | - Filtering method variants (`*By`-suffixed). 58 | - Support for Marathon DCOS token. 59 | - Basic auth and HTTP client settings. 60 | - Marshalling of `Deployment.DeploymentStep` for Marathon v1.X. 61 | - Field `ipAddresses` to tasks and events. 62 | - Field `slaveId` to tasks. 63 | - Convenience methods to populate/clear pointerized values. 64 | - Method `ApplicationByVersion()` to retrieve version-specific apps. 65 | - Support for fetch URIs. 66 | - Parse API error responses on all error types for programmatic evaluation. 67 | 68 | ### Changed 69 | - Consider app as unhealthy in ApplicationOK if health check is missing. (Ensures result stability during all phases of deployment.) 70 | - Various identifiers violating golint rules. 71 | - Do not set "bridged" mode on Docker containers by default. 72 | 73 | ### Fixed 74 | - Flawed unmarshalling of `CurrentStep` in events. 75 | - Missing omitempty tag modifiers on `Application.Uris`. 76 | - Missing leading slash in path used by `Ping()`. 77 | - Flawed `KillTask()` in case of hierarchical app ID path. 78 | - Missing omitempty tag modifier on `PortMapping.Protocol`. 79 | - Nil dereference on empty debug log. 80 | - Various occasions where omitted and empty fields could not be distinguished. 81 | 82 | ## 0.0.1 - 2016-01-27 83 | ### Added 84 | - Initial SemVer release. 85 | 86 | [Unreleased]: https://github.com/gambol99/go-marathon/compare/v0.5.0...HEAD 87 | [0.5.0]: https://github.com/gambol99/go-marathon/compare/v0.4.0...v0.5.0 88 | [0.4.0]: https://github.com/gambol99/go-marathon/compare/v0.3.0...v0.4.0 89 | [0.3.0]: https://github.com/gambol99/go-marathon/compare/v0.2.0...v0.3.0 90 | [0.2.0]: https://github.com/gambol99/go-marathon/compare/v0.1.1...v0.2.0 91 | [0.1.1]: https://github.com/gambol99/go-marathon/compare/v0.1.0...v0.1.1 92 | [0.1.0]: https://github.com/gambol99/go-marathon/compare/v0.0.1...v0.1.0 93 | 94 | [PR231]: https://github.com/gambol99/go-marathon/pull/231 95 | [PR229]: https://github.com/gambol99/go-marathon/pull/229 96 | [PR223]: https://github.com/gambol99/go-marathon/pull/223 97 | [PR220]: https://github.com/gambol99/go-marathon/pull/220 98 | [PR218]: https://github.com/gambol99/go-marathon/pull/218 99 | [PR214]: https://github.com/gambol99/go-marathon/pull/214 100 | [PR211]: https://github.com/gambol99/go-marathon/pull/211 101 | [PR205]: https://github.com/gambol99/go-marathon/pull/205 102 | [PR202]: https://github.com/gambol99/go-marathon/pull/202 103 | [PR201]: https://github.com/gambol99/go-marathon/pull/201 104 | [PR196]: https://github.com/gambol99/go-marathon/pull/196 105 | [PR191]: https://github.com/gambol99/go-marathon/pull/191 106 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/expvar.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 | // ExpvarCollector collects metrics from the expvar interface. It provides a 22 | // quick way to expose numeric values that are already exported via expvar as 23 | // Prometheus metrics. Note that the data models of expvar and Prometheus are 24 | // fundamentally different, and that the ExpvarCollector is inherently 25 | // slow. Thus, the ExpvarCollector is probably great for experiments and 26 | // prototying, but you should seriously consider a more direct implementation of 27 | // Prometheus metrics for monitoring production systems. 28 | // 29 | // Use NewExpvarCollector to create new instances. 30 | type ExpvarCollector struct { 31 | exports map[string]*Desc 32 | } 33 | 34 | // NewExpvarCollector returns a newly allocated ExpvarCollector that still has 35 | // to be registered with the Prometheus registry. 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) *ExpvarCollector { 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/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 Counter 23 | openFDs, maxFDs Gauge 24 | vsize, rss Gauge 25 | startTime Gauge 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) *processCollector { 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 | ) *processCollector { 47 | c := processCollector{ 48 | pidFn: pidFn, 49 | collectFn: func(chan<- Metric) {}, 50 | 51 | cpuTotal: NewCounter(CounterOpts{ 52 | Namespace: namespace, 53 | Name: "process_cpu_seconds_total", 54 | Help: "Total user and system CPU time spent in seconds.", 55 | }), 56 | openFDs: NewGauge(GaugeOpts{ 57 | Namespace: namespace, 58 | Name: "process_open_fds", 59 | Help: "Number of open file descriptors.", 60 | }), 61 | maxFDs: NewGauge(GaugeOpts{ 62 | Namespace: namespace, 63 | Name: "process_max_fds", 64 | Help: "Maximum number of open file descriptors.", 65 | }), 66 | vsize: NewGauge(GaugeOpts{ 67 | Namespace: namespace, 68 | Name: "process_virtual_memory_bytes", 69 | Help: "Virtual memory size in bytes.", 70 | }), 71 | rss: NewGauge(GaugeOpts{ 72 | Namespace: namespace, 73 | Name: "process_resident_memory_bytes", 74 | Help: "Resident memory size in bytes.", 75 | }), 76 | startTime: NewGauge(GaugeOpts{ 77 | Namespace: namespace, 78 | Name: "process_start_time_seconds", 79 | Help: "Start time of the process since unix epoch in seconds.", 80 | }), 81 | } 82 | 83 | // Set up process metric collection if supported by the runtime. 84 | if _, err := procfs.NewStat(); err == nil { 85 | c.collectFn = c.processCollect 86 | } 87 | 88 | return &c 89 | } 90 | 91 | // Describe returns all descriptions of the collector. 92 | func (c *processCollector) Describe(ch chan<- *Desc) { 93 | ch <- c.cpuTotal.Desc() 94 | ch <- c.openFDs.Desc() 95 | ch <- c.maxFDs.Desc() 96 | ch <- c.vsize.Desc() 97 | ch <- c.rss.Desc() 98 | ch <- c.startTime.Desc() 99 | } 100 | 101 | // Collect returns the current state of all metrics of the collector. 102 | func (c *processCollector) Collect(ch chan<- Metric) { 103 | c.collectFn(ch) 104 | } 105 | 106 | // TODO(ts): Bring back error reporting by reverting 7faf9e7 as soon as the 107 | // client allows users to configure the error behavior. 108 | func (c *processCollector) processCollect(ch chan<- Metric) { 109 | pid, err := c.pidFn() 110 | if err != nil { 111 | return 112 | } 113 | 114 | p, err := procfs.NewProc(pid) 115 | if err != nil { 116 | return 117 | } 118 | 119 | if stat, err := p.NewStat(); err == nil { 120 | c.cpuTotal.Set(stat.CPUTime()) 121 | ch <- c.cpuTotal 122 | c.vsize.Set(float64(stat.VirtualMemory())) 123 | ch <- c.vsize 124 | c.rss.Set(float64(stat.ResidentMemory())) 125 | ch <- c.rss 126 | 127 | if startTime, err := stat.StartTime(); err == nil { 128 | c.startTime.Set(startTime) 129 | ch <- c.startTime 130 | } 131 | } 132 | 133 | if fds, err := p.FileDescriptorsLen(); err == nil { 134 | c.openFDs.Set(float64(fds)) 135 | ch <- c.openFDs 136 | } 137 | 138 | if limits, err := p.NewLimits(); err == nil { 139 | c.maxFDs.Set(float64(limits.OpenFiles)) 140 | ch <- c.maxFDs 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/stream.go: -------------------------------------------------------------------------------- 1 | package eventsource 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | "time" 11 | ) 12 | 13 | // Stream handles a connection for receiving Server Sent Events. 14 | // It will try and reconnect if the connection is lost, respecting both 15 | // received retry delays and event id's. 16 | type Stream struct { 17 | c *http.Client 18 | req *http.Request 19 | lastEventId string 20 | retry time.Duration 21 | // Events emits the events received by the stream 22 | Events chan Event 23 | // Errors emits any errors encountered while reading events from the stream. 24 | // It's mainly for informative purposes - the client isn't required to take any 25 | // action when an error is encountered. The stream will always attempt to continue, 26 | // even if that involves reconnecting to the server. 27 | Errors chan error 28 | // Logger is a logger that, when set, will be used for logging debug messages 29 | Logger *log.Logger 30 | } 31 | 32 | type SubscriptionError struct { 33 | Code int 34 | Message string 35 | } 36 | 37 | func (e SubscriptionError) Error() string { 38 | return fmt.Sprintf("%d: %s", e.Code, e.Message) 39 | } 40 | 41 | // Subscribe to the Events emitted from the specified url. 42 | // If lastEventId is non-empty it will be sent to the server in case it can replay missed events. 43 | func Subscribe(url, lastEventId string) (*Stream, error) { 44 | req, err := http.NewRequest("GET", url, nil) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return SubscribeWithRequest(lastEventId, req) 49 | } 50 | 51 | // SubscribeWithRequest will take an http.Request to setup the stream, allowing custom headers 52 | // to be specified, authentication to be configured, etc. 53 | func SubscribeWithRequest(lastEventId string, request *http.Request) (*Stream, error) { 54 | return SubscribeWith(lastEventId, http.DefaultClient, request) 55 | } 56 | 57 | // SubscribeWith takes a http client and request providing customization over both headers and 58 | // control over the http client settings (timeouts, tls, etc) 59 | func SubscribeWith(lastEventId string, client *http.Client, request *http.Request) (*Stream, error) { 60 | stream := &Stream{ 61 | c: client, 62 | req: request, 63 | lastEventId: lastEventId, 64 | retry: (time.Millisecond * 3000), 65 | Events: make(chan Event), 66 | Errors: make(chan error), 67 | } 68 | stream.c.CheckRedirect = checkRedirect 69 | 70 | r, err := stream.connect() 71 | if err != nil { 72 | return nil, err 73 | } 74 | go stream.stream(r) 75 | return stream, nil 76 | } 77 | 78 | // Go's http package doesn't copy headers across when it encounters 79 | // redirects so we need to do that manually. 80 | func checkRedirect(req *http.Request, via []*http.Request) error { 81 | if len(via) >= 10 { 82 | return errors.New("stopped after 10 redirects") 83 | } 84 | for k, vv := range via[0].Header { 85 | for _, v := range vv { 86 | req.Header.Add(k, v) 87 | } 88 | } 89 | return nil 90 | } 91 | 92 | func (stream *Stream) connect() (r io.ReadCloser, err error) { 93 | var resp *http.Response 94 | stream.req.Header.Set("Cache-Control", "no-cache") 95 | stream.req.Header.Set("Accept", "text/event-stream") 96 | if len(stream.lastEventId) > 0 { 97 | stream.req.Header.Set("Last-Event-ID", stream.lastEventId) 98 | } 99 | if resp, err = stream.c.Do(stream.req); err != nil { 100 | return 101 | } 102 | if resp.StatusCode != 200 { 103 | message, _ := ioutil.ReadAll(resp.Body) 104 | err = SubscriptionError{ 105 | Code: resp.StatusCode, 106 | Message: string(message), 107 | } 108 | } 109 | r = resp.Body 110 | return 111 | } 112 | 113 | func (stream *Stream) stream(r io.ReadCloser) { 114 | defer r.Close() 115 | dec := NewDecoder(r) 116 | for { 117 | ev, err := dec.Decode() 118 | 119 | if err != nil { 120 | stream.Errors <- err 121 | // respond to all errors by reconnecting and trying again 122 | break 123 | } 124 | pub := ev.(*publication) 125 | if pub.Retry() > 0 { 126 | stream.retry = time.Duration(pub.Retry()) * time.Millisecond 127 | } 128 | if len(pub.Id()) > 0 { 129 | stream.lastEventId = pub.Id() 130 | } 131 | stream.Events <- ev 132 | } 133 | backoff := stream.retry 134 | for { 135 | time.Sleep(backoff) 136 | if stream.Logger != nil { 137 | stream.Logger.Printf("Reconnecting in %0.4f secs\n", backoff.Seconds()) 138 | } 139 | 140 | // NOTE: because of the defer we're opening the new connection 141 | // before closing the old one. Shouldn't be a problem in practice, 142 | // but something to be aware of. 143 | next, err := stream.connect() 144 | if err == nil { 145 | go stream.stream(next) 146 | break 147 | } 148 | stream.Errors <- err 149 | backoff *= 2 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /vendor/github.com/donovanhide/eventsource/server.go: -------------------------------------------------------------------------------- 1 | package eventsource 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "strings" 7 | ) 8 | 9 | type subscription struct { 10 | channel string 11 | lastEventId string 12 | out chan Event 13 | } 14 | 15 | type outbound struct { 16 | channels []string 17 | event Event 18 | } 19 | type registration struct { 20 | channel string 21 | repository Repository 22 | } 23 | 24 | type Server struct { 25 | AllowCORS bool // Enable all handlers to be accessible from any origin 26 | ReplayAll bool // Replay repository even if there's no Last-Event-Id specified 27 | BufferSize int // How many messages do we let the client get behind before disconnecting 28 | Gzip bool // Enable compression if client can accept it 29 | Logger *log.Logger // Logger is a logger that, when set, will be used for logging debug messages 30 | registrations chan *registration 31 | pub chan *outbound 32 | subs chan *subscription 33 | unregister chan *subscription 34 | quit chan bool 35 | } 36 | 37 | // Create a new Server ready for handler creation and publishing events 38 | func NewServer() *Server { 39 | srv := &Server{ 40 | registrations: make(chan *registration), 41 | pub: make(chan *outbound), 42 | subs: make(chan *subscription), 43 | unregister: make(chan *subscription, 2), 44 | quit: make(chan bool), 45 | BufferSize: 128, 46 | } 47 | go srv.run() 48 | return srv 49 | } 50 | 51 | // Stop handling publishing 52 | func (srv *Server) Close() { 53 | srv.quit <- true 54 | } 55 | 56 | // Create a new handler for serving a specified channel 57 | func (srv *Server) Handler(channel string) http.HandlerFunc { 58 | return func(w http.ResponseWriter, req *http.Request) { 59 | h := w.Header() 60 | h.Set("Content-Type", "text/event-stream; charset=utf-8") 61 | h.Set("Cache-Control", "no-cache, no-store, must-revalidate") 62 | h.Set("Connection", "keep-alive") 63 | if srv.AllowCORS { 64 | h.Set("Access-Control-Allow-Origin", "*") 65 | } 66 | useGzip := srv.Gzip && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") 67 | if useGzip { 68 | h.Set("Content-Encoding", "gzip") 69 | } 70 | w.WriteHeader(http.StatusOK) 71 | 72 | sub := &subscription{ 73 | channel: channel, 74 | lastEventId: req.Header.Get("Last-Event-ID"), 75 | out: make(chan Event, srv.BufferSize), 76 | } 77 | srv.subs <- sub 78 | flusher := w.(http.Flusher) 79 | notifier := w.(http.CloseNotifier) 80 | flusher.Flush() 81 | enc := NewEncoder(w, useGzip) 82 | for { 83 | select { 84 | case <-notifier.CloseNotify(): 85 | srv.unregister <- sub 86 | return 87 | case ev, ok := <-sub.out: 88 | if !ok { 89 | return 90 | } 91 | if err := enc.Encode(ev); err != nil { 92 | srv.unregister <- sub 93 | if srv.Logger != nil { 94 | srv.Logger.Println(err) 95 | } 96 | return 97 | } 98 | flusher.Flush() 99 | } 100 | } 101 | } 102 | } 103 | 104 | // Register the repository to be used for the specified channel 105 | func (srv *Server) Register(channel string, repo Repository) { 106 | srv.registrations <- ®istration{ 107 | channel: channel, 108 | repository: repo, 109 | } 110 | } 111 | 112 | // Publish an event with the specified id to one or more channels 113 | func (srv *Server) Publish(channels []string, ev Event) { 114 | srv.pub <- &outbound{ 115 | channels: channels, 116 | event: ev, 117 | } 118 | } 119 | 120 | func replay(repo Repository, sub *subscription) { 121 | for ev := range repo.Replay(sub.channel, sub.lastEventId) { 122 | sub.out <- ev 123 | } 124 | } 125 | 126 | func (srv *Server) run() { 127 | subs := make(map[string]map[*subscription]struct{}) 128 | repos := make(map[string]Repository) 129 | for { 130 | select { 131 | case reg := <-srv.registrations: 132 | repos[reg.channel] = reg.repository 133 | case sub := <-srv.unregister: 134 | delete(subs[sub.channel], sub) 135 | case pub := <-srv.pub: 136 | for _, c := range pub.channels { 137 | for s := range subs[c] { 138 | select { 139 | case s.out <- pub.event: 140 | default: 141 | srv.unregister <- s 142 | close(s.out) 143 | } 144 | 145 | } 146 | } 147 | case sub := <-srv.subs: 148 | if _, ok := subs[sub.channel]; !ok { 149 | subs[sub.channel] = make(map[*subscription]struct{}) 150 | } 151 | subs[sub.channel][sub] = struct{}{} 152 | if srv.ReplayAll || len(sub.lastEventId) > 0 { 153 | repo, ok := repos[sub.channel] 154 | if ok { 155 | go replay(repo, sub) 156 | } 157 | } 158 | case <-srv.quit: 159 | for _, sub := range subs { 160 | for s := range sub { 161 | close(s.out) 162 | } 163 | } 164 | return 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /vendor/github.com/matt-deboer/go-marathon/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [Unreleased] 8 | ### Changed 9 | - [#242][PR242] Pointerize IPAddressPerTask.Discovery. 10 | 11 | ## [0.5.1] - 2016-11-09 12 | ### Fixed 13 | - [#239][PR239] Fix scheme-less endpoint with port. 14 | 15 | ## [0.5.0] - 2016-11-07 16 | ### Fixed 17 | - [#231][PR231] Fixed Marathon cluster code 18 | - [#229][PR229] Add LastFailureCause field to HealthCheckResult. 19 | 20 | ## [0.4.0] - 2016-10-28 21 | ### Added 22 | - [#223][PR223] Add support for IP-per-task. 23 | - [#220][PR220] Add external volume definition to container. 24 | - [#211][PR211] Close event channel on event listener removal. 25 | 26 | ### Fixed 27 | - [#218][PR218] Remove TimeWaitPolling from marathonClient. 28 | - [#214][PR214] Remove extra pointer layers when passing to r.api*. 29 | 30 | ## [0.3.0] - 2016-09-28 31 | - [#201][PR201]: Subscribe method is now exposed on the client to allow subscription of callback URL's 32 | 33 | ### Fixed 34 | - [#205][PR205]: Fix memory leak by signalling goroutine termination on event listener removal. 35 | 36 | ### Changed 37 | - [#205][PR205]: Change AddEventsListener to return event channel instead of taking one. 38 | 39 | ## [0.2.0] - 2016-09-23 40 | ### Added 41 | - [#196][PR196]: Port definitions. 42 | - [#191][PR191]: name and labels to portMappings. 43 | 44 | ### Changed 45 | - [#191][PR191] ExposePort() now takes a portMapping instance. 46 | 47 | ### Fixed 48 | - [#202][PR202]: Timeout error in WaitOnApplication. 49 | 50 | ## [0.1.1] - 2016-09-07 51 | ### Fixed 52 | - Drop question mark-only query parameter in Applications(url.Values) manually 53 | due to changed behavior in Go 1.7's net/url.Parse. 54 | 55 | ## [0.1.0] - 2016-08-01 56 | ### Added 57 | - Field `message` to the EventStatusUpdate struct. 58 | - Method `Host()` to set host mode explicitly. 59 | - Field `port` to HealthCheck. 60 | - Support for launch queues. 61 | - Convenience method `AddFetchURIs()`. 62 | - Support for forced operations across all methods. 63 | - Filtering method variants (`*By`-suffixed). 64 | - Support for Marathon DCOS token. 65 | - Basic auth and HTTP client settings. 66 | - Marshalling of `Deployment.DeploymentStep` for Marathon v1.X. 67 | - Field `ipAddresses` to tasks and events. 68 | - Field `slaveId` to tasks. 69 | - Convenience methods to populate/clear pointerized values. 70 | - Method `ApplicationByVersion()` to retrieve version-specific apps. 71 | - Support for fetch URIs. 72 | - Parse API error responses on all error types for programmatic evaluation. 73 | 74 | ### Changed 75 | - Consider app as unhealthy in ApplicationOK if health check is missing. (Ensures result stability during all phases of deployment.) 76 | - Various identifiers violating golint rules. 77 | - Do not set "bridged" mode on Docker containers by default. 78 | 79 | ### Fixed 80 | - Flawed unmarshalling of `CurrentStep` in events. 81 | - Missing omitempty tag modifiers on `Application.Uris`. 82 | - Missing leading slash in path used by `Ping()`. 83 | - Flawed `KillTask()` in case of hierarchical app ID path. 84 | - Missing omitempty tag modifier on `PortMapping.Protocol`. 85 | - Nil dereference on empty debug log. 86 | - Various occasions where omitted and empty fields could not be distinguished. 87 | 88 | ## 0.0.1 - 2016-01-27 89 | ### Added 90 | - Initial SemVer release. 91 | 92 | [Unreleased]: https://github.com/gambol99/go-marathon/compare/v0.5.1...HEAD 93 | [0.5.1]: https://github.com/gambol99/go-marathon/compare/v0.5.0...v0.5.1 94 | [0.5.0]: https://github.com/gambol99/go-marathon/compare/v0.4.0...v0.5.0 95 | [0.4.0]: https://github.com/gambol99/go-marathon/compare/v0.3.0...v0.4.0 96 | [0.3.0]: https://github.com/gambol99/go-marathon/compare/v0.2.0...v0.3.0 97 | [0.2.0]: https://github.com/gambol99/go-marathon/compare/v0.1.1...v0.2.0 98 | [0.1.1]: https://github.com/gambol99/go-marathon/compare/v0.1.0...v0.1.1 99 | [0.1.0]: https://github.com/gambol99/go-marathon/compare/v0.0.1...v0.1.0 100 | 101 | [PR242]: https://github.com/gambol99/go-marathon/pull/242 102 | [PR239]: https://github.com/gambol99/go-marathon/pull/239 103 | [PR231]: https://github.com/gambol99/go-marathon/pull/231 104 | [PR229]: https://github.com/gambol99/go-marathon/pull/229 105 | [PR223]: https://github.com/gambol99/go-marathon/pull/223 106 | [PR220]: https://github.com/gambol99/go-marathon/pull/220 107 | [PR218]: https://github.com/gambol99/go-marathon/pull/218 108 | [PR214]: https://github.com/gambol99/go-marathon/pull/214 109 | [PR211]: https://github.com/gambol99/go-marathon/pull/211 110 | [PR205]: https://github.com/gambol99/go-marathon/pull/205 111 | [PR202]: https://github.com/gambol99/go-marathon/pull/202 112 | [PR201]: https://github.com/gambol99/go-marathon/pull/201 113 | [PR196]: https://github.com/gambol99/go-marathon/pull/196 114 | [PR191]: https://github.com/gambol99/go-marathon/pull/191 115 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go: -------------------------------------------------------------------------------- 1 | /* 2 | HTTP Content-Type Autonegotiation. 3 | 4 | The functions in this package implement the behaviour specified in 5 | http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 6 | 7 | Copyright (c) 2011, Open Knowledge Foundation Ltd. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are 12 | met: 13 | 14 | Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in 19 | the documentation and/or other materials provided with the 20 | distribution. 21 | 22 | Neither the name of the Open Knowledge Foundation Ltd. nor the 23 | names of its contributors may be used to endorse or promote 24 | products derived from this software without specific prior written 25 | permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | 40 | */ 41 | package goautoneg 42 | 43 | import ( 44 | "sort" 45 | "strconv" 46 | "strings" 47 | ) 48 | 49 | // Structure to represent a clause in an HTTP Accept Header 50 | type Accept struct { 51 | Type, SubType string 52 | Q float64 53 | Params map[string]string 54 | } 55 | 56 | // For internal use, so that we can use the sort interface 57 | type accept_slice []Accept 58 | 59 | func (accept accept_slice) Len() int { 60 | slice := []Accept(accept) 61 | return len(slice) 62 | } 63 | 64 | func (accept accept_slice) Less(i, j int) bool { 65 | slice := []Accept(accept) 66 | ai, aj := slice[i], slice[j] 67 | if ai.Q > aj.Q { 68 | return true 69 | } 70 | if ai.Type != "*" && aj.Type == "*" { 71 | return true 72 | } 73 | if ai.SubType != "*" && aj.SubType == "*" { 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | func (accept accept_slice) Swap(i, j int) { 80 | slice := []Accept(accept) 81 | slice[i], slice[j] = slice[j], slice[i] 82 | } 83 | 84 | // Parse an Accept Header string returning a sorted list 85 | // of clauses 86 | func ParseAccept(header string) (accept []Accept) { 87 | parts := strings.Split(header, ",") 88 | accept = make([]Accept, 0, len(parts)) 89 | for _, part := range parts { 90 | part := strings.Trim(part, " ") 91 | 92 | a := Accept{} 93 | a.Params = make(map[string]string) 94 | a.Q = 1.0 95 | 96 | mrp := strings.Split(part, ";") 97 | 98 | media_range := mrp[0] 99 | sp := strings.Split(media_range, "/") 100 | a.Type = strings.Trim(sp[0], " ") 101 | 102 | switch { 103 | case len(sp) == 1 && a.Type == "*": 104 | a.SubType = "*" 105 | case len(sp) == 2: 106 | a.SubType = strings.Trim(sp[1], " ") 107 | default: 108 | continue 109 | } 110 | 111 | if len(mrp) == 1 { 112 | accept = append(accept, a) 113 | continue 114 | } 115 | 116 | for _, param := range mrp[1:] { 117 | sp := strings.SplitN(param, "=", 2) 118 | if len(sp) != 2 { 119 | continue 120 | } 121 | token := strings.Trim(sp[0], " ") 122 | if token == "q" { 123 | a.Q, _ = strconv.ParseFloat(sp[1], 32) 124 | } else { 125 | a.Params[token] = strings.Trim(sp[1], " ") 126 | } 127 | } 128 | 129 | accept = append(accept, a) 130 | } 131 | 132 | slice := accept_slice(accept) 133 | sort.Sort(slice) 134 | 135 | return 136 | } 137 | 138 | // Negotiate the most appropriate content_type given the accept header 139 | // and a list of alternatives. 140 | func Negotiate(header string, alternatives []string) (content_type string) { 141 | asp := make([][]string, 0, len(alternatives)) 142 | for _, ctype := range alternatives { 143 | asp = append(asp, strings.SplitN(ctype, "/", 2)) 144 | } 145 | for _, clause := range ParseAccept(header) { 146 | for i, ctsp := range asp { 147 | if clause.Type == ctsp[0] && clause.SubType == ctsp[1] { 148 | content_type = alternatives[i] 149 | return 150 | } 151 | if clause.Type == ctsp[0] && clause.SubType == "*" { 152 | content_type = alternatives[i] 153 | return 154 | } 155 | if clause.Type == "*" && clause.SubType == "*" { 156 | content_type = alternatives[i] 157 | return 158 | } 159 | } 160 | } 161 | return 162 | } 163 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/signature.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "sort" 18 | ) 19 | 20 | // SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is 21 | // used to separate label names, label values, and other strings from each other 22 | // when calculating their combined hash value (aka signature aka fingerprint). 23 | const SeparatorByte byte = 255 24 | 25 | var ( 26 | // cache the signature of an empty label set. 27 | emptyLabelSignature = hashNew() 28 | ) 29 | 30 | // LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a 31 | // given label set. (Collisions are possible but unlikely if the number of label 32 | // sets the function is applied to is small.) 33 | func LabelsToSignature(labels map[string]string) uint64 { 34 | if len(labels) == 0 { 35 | return emptyLabelSignature 36 | } 37 | 38 | labelNames := make([]string, 0, len(labels)) 39 | for labelName := range labels { 40 | labelNames = append(labelNames, labelName) 41 | } 42 | sort.Strings(labelNames) 43 | 44 | sum := hashNew() 45 | for _, labelName := range labelNames { 46 | sum = hashAdd(sum, labelName) 47 | sum = hashAddByte(sum, SeparatorByte) 48 | sum = hashAdd(sum, labels[labelName]) 49 | sum = hashAddByte(sum, SeparatorByte) 50 | } 51 | return sum 52 | } 53 | 54 | // labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as 55 | // parameter (rather than a label map) and returns a Fingerprint. 56 | func labelSetToFingerprint(ls LabelSet) Fingerprint { 57 | if len(ls) == 0 { 58 | return Fingerprint(emptyLabelSignature) 59 | } 60 | 61 | labelNames := make(LabelNames, 0, len(ls)) 62 | for labelName := range ls { 63 | labelNames = append(labelNames, labelName) 64 | } 65 | sort.Sort(labelNames) 66 | 67 | sum := hashNew() 68 | for _, labelName := range labelNames { 69 | sum = hashAdd(sum, string(labelName)) 70 | sum = hashAddByte(sum, SeparatorByte) 71 | sum = hashAdd(sum, string(ls[labelName])) 72 | sum = hashAddByte(sum, SeparatorByte) 73 | } 74 | return Fingerprint(sum) 75 | } 76 | 77 | // labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a 78 | // faster and less allocation-heavy hash function, which is more susceptible to 79 | // create hash collisions. Therefore, collision detection should be applied. 80 | func labelSetToFastFingerprint(ls LabelSet) Fingerprint { 81 | if len(ls) == 0 { 82 | return Fingerprint(emptyLabelSignature) 83 | } 84 | 85 | var result uint64 86 | for labelName, labelValue := range ls { 87 | sum := hashNew() 88 | sum = hashAdd(sum, string(labelName)) 89 | sum = hashAddByte(sum, SeparatorByte) 90 | sum = hashAdd(sum, string(labelValue)) 91 | result ^= sum 92 | } 93 | return Fingerprint(result) 94 | } 95 | 96 | // SignatureForLabels works like LabelsToSignature but takes a Metric as 97 | // parameter (rather than a label map) and only includes the labels with the 98 | // specified LabelNames into the signature calculation. The labels passed in 99 | // will be sorted by this function. 100 | func SignatureForLabels(m Metric, labels ...LabelName) uint64 { 101 | if len(labels) == 0 { 102 | return emptyLabelSignature 103 | } 104 | 105 | sort.Sort(LabelNames(labels)) 106 | 107 | sum := hashNew() 108 | for _, label := range labels { 109 | sum = hashAdd(sum, string(label)) 110 | sum = hashAddByte(sum, SeparatorByte) 111 | sum = hashAdd(sum, string(m[label])) 112 | sum = hashAddByte(sum, SeparatorByte) 113 | } 114 | return sum 115 | } 116 | 117 | // SignatureWithoutLabels works like LabelsToSignature but takes a Metric as 118 | // parameter (rather than a label map) and excludes the labels with any of the 119 | // specified LabelNames from the signature calculation. 120 | func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 { 121 | if len(m) == 0 { 122 | return emptyLabelSignature 123 | } 124 | 125 | labelNames := make(LabelNames, 0, len(m)) 126 | for labelName := range m { 127 | if _, exclude := labels[labelName]; !exclude { 128 | labelNames = append(labelNames, labelName) 129 | } 130 | } 131 | if len(labelNames) == 0 { 132 | return emptyLabelSignature 133 | } 134 | sort.Sort(labelNames) 135 | 136 | sum := hashNew() 137 | for _, labelName := range labelNames { 138 | sum = hashAdd(sum, string(labelName)) 139 | sum = hashAddByte(sum, SeparatorByte) 140 | sum = hashAdd(sum, string(m[labelName])) 141 | sum = hashAddByte(sum, SeparatorByte) 142 | } 143 | return sum 144 | } 145 | -------------------------------------------------------------------------------- /vendor/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 !LabelNameRE.MatchString(string(ln)) { 164 | return fmt.Errorf("%q is not a valid label name", ln) 165 | } 166 | } 167 | *l = LabelSet(m) 168 | return nil 169 | } 170 | --------------------------------------------------------------------------------