├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── main.go ├── probe.go └── vendor ├── github.com ├── Sirupsen │ └── logrus │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── entry.go │ │ ├── exported.go │ │ ├── formatter.go │ │ ├── hooks.go │ │ ├── json_formatter.go │ │ ├── logger.go │ │ ├── logrus.go │ │ ├── terminal_bsd.go │ │ ├── terminal_linux.go │ │ ├── terminal_notwindows.go │ │ ├── terminal_solaris.go │ │ ├── terminal_windows.go │ │ ├── text_formatter.go │ │ └── writer.go ├── beorn7 │ └── perks │ │ ├── LICENSE │ │ └── quantile │ │ ├── exampledata.txt │ │ └── stream.go ├── golang │ └── protobuf │ │ ├── LICENSE │ │ └── proto │ │ ├── Makefile │ │ ├── clone.go │ │ ├── decode.go │ │ ├── encode.go │ │ ├── equal.go │ │ ├── extensions.go │ │ ├── lib.go │ │ ├── message_set.go │ │ ├── pointer_reflect.go │ │ ├── pointer_unsafe.go │ │ ├── properties.go │ │ ├── text.go │ │ └── text_parser.go ├── matttproud │ └── golang_protobuf_extensions │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── pbutil │ │ ├── Makefile │ │ ├── decode.go │ │ ├── doc.go │ │ └── encode.go ├── prometheus │ ├── client_golang │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── prometheus │ │ │ ├── README.md │ │ │ ├── collector.go │ │ │ ├── counter.go │ │ │ ├── desc.go │ │ │ ├── doc.go │ │ │ ├── expvar.go │ │ │ ├── fnv.go │ │ │ ├── gauge.go │ │ │ ├── go_collector.go │ │ │ ├── histogram.go │ │ │ ├── http.go │ │ │ ├── metric.go │ │ │ ├── process_collector.go │ │ │ ├── push.go │ │ │ ├── registry.go │ │ │ ├── summary.go │ │ │ ├── untyped.go │ │ │ ├── value.go │ │ │ └── vec.go │ ├── client_model │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── go │ │ │ └── metrics.pb.go │ ├── common │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── expfmt │ │ │ ├── decode.go │ │ │ ├── encode.go │ │ │ ├── expfmt.go │ │ │ ├── fuzz.go │ │ │ ├── text_create.go │ │ │ └── text_parse.go │ │ ├── internal │ │ │ └── bitbucket.org │ │ │ │ └── ww │ │ │ │ └── goautoneg │ │ │ │ ├── README.txt │ │ │ │ └── autoneg.go │ │ ├── log │ │ │ ├── log.go │ │ │ └── syslog_formatter.go │ │ ├── model │ │ │ ├── alert.go │ │ │ ├── fingerprinting.go │ │ │ ├── fnv.go │ │ │ ├── labels.go │ │ │ ├── labelset.go │ │ │ ├── metric.go │ │ │ ├── model.go │ │ │ ├── signature.go │ │ │ ├── silence.go │ │ │ ├── time.go │ │ │ └── value.go │ │ └── version │ │ │ └── info.go │ └── procfs │ │ ├── AUTHORS.md │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── NOTICE │ │ ├── README.md │ │ ├── doc.go │ │ ├── fs.go │ │ ├── ipvs.go │ │ ├── mdstat.go │ │ ├── proc.go │ │ ├── proc_io.go │ │ ├── proc_limits.go │ │ ├── proc_stat.go │ │ └── stat.go └── sclevine │ └── agouti │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── THANKS.md │ ├── agouti.go │ ├── api │ ├── api.go │ ├── element.go │ ├── internal │ │ ├── bus │ │ │ ├── client.go │ │ │ └── connect.go │ │ └── service │ │ │ ├── build.go │ │ │ └── service.go │ ├── offset.go │ ├── session.go │ ├── speed.go │ ├── types.go │ ├── webdriver.go │ └── window.go │ ├── capabilities.go │ ├── internal │ ├── element │ │ └── repository.go │ └── target │ │ ├── selector.go │ │ └── selectors.go │ ├── multiselection.go │ ├── options.go │ ├── page.go │ ├── selectable.go │ ├── selection.go │ ├── selection_actions.go │ ├── selection_frames.go │ ├── selection_properties.go │ ├── types.go │ └── webdriver.go └── vendor.json /.gitignore: -------------------------------------------------------------------------------- 1 | webdriver_exporter 2 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | WebDriver Exporter: Probes a web page using the WebDriver protocol and exposes metrics to Prometheus 2 | Copyright 2016 The Prometheus Authors 3 | 4 | Uses portions of code from https://github.com/prometheus/blackbox_exporter: 5 | The Blackbox exporter for blackbox probing metrics 6 | Copyright 2012-2016 The Prometheus Authors 7 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package main 15 | 16 | import ( 17 | "flag" 18 | "fmt" 19 | "net/http" 20 | "os" 21 | "time" 22 | 23 | "github.com/prometheus/client_golang/prometheus" 24 | "github.com/prometheus/common/log" 25 | "github.com/prometheus/common/version" 26 | "github.com/sclevine/agouti" 27 | ) 28 | 29 | const versionString = "0.0.2" 30 | 31 | var ( 32 | driver = agouti.ChromeDriver() 33 | listenAddress = flag.String("web.listen-address", "localhost:9156", "The address to listen on for HTTP requests.") 34 | showVersion = flag.Bool("version", false, "Print version information.") 35 | ) 36 | 37 | func init() { 38 | version.Version = versionString 39 | prometheus.MustRegister(version.NewCollector("webdriver_exporter")) 40 | } 41 | 42 | func main() { 43 | flag.Parse() 44 | 45 | if *showVersion { 46 | fmt.Fprintln(os.Stdout, version.Print("webdriver_exporter")) 47 | os.Exit(0) 48 | } 49 | 50 | log.Infoln("Starting webdriver_exporter", version.Info()) 51 | log.Infoln("Build context", version.BuildContext()) 52 | 53 | http.Handle("/metrics", prometheus.Handler()) 54 | http.HandleFunc("/probe", 55 | func(w http.ResponseWriter, r *http.Request) { 56 | probeHandler(w, r) 57 | }) 58 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 59 | w.Write([]byte(` 60 | WebDriver Exporter 61 | 62 |

WebDriver Exporter

63 |

Probe prometheus.io

64 |

Metrics

65 | 66 | `)) 67 | }) 68 | 69 | log.Infoln("Starting webdriver") 70 | err := driver.Start() 71 | if err != nil { 72 | log.Fatalf("failed to start webdriver: %s", err) 73 | } 74 | defer driver.Stop() 75 | 76 | log.Infoln("Listening on", *listenAddress) 77 | if err := http.ListenAndServe(*listenAddress, nil); err != nil { 78 | log.Fatalf("Error starting HTTP server: %s", err) 79 | } 80 | } 81 | 82 | func probeHandler(w http.ResponseWriter, r *http.Request) { 83 | params := r.URL.Query() 84 | target := params.Get("target") 85 | if target == "" { 86 | http.Error(w, "Target parameter is missing", 400) 87 | return 88 | } 89 | 90 | start := time.Now() 91 | success := probe(target, w) 92 | fmt.Fprintf(w, "probe_duration_seconds %f\n", float64(time.Since(start))/1e9) 93 | 94 | if success { 95 | fmt.Fprintf(w, "probe_success %d\n", 1) 96 | } else { 97 | fmt.Fprintf(w, "probe_success %d\n", 0) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /probe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package main 15 | 16 | import ( 17 | "fmt" 18 | "net/http" 19 | 20 | "github.com/prometheus/common/log" 21 | "github.com/sclevine/agouti" 22 | ) 23 | 24 | const msInSecond = 1000 25 | 26 | // from https://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface 27 | type navigationTimings struct { 28 | ConnectEnd float64 29 | ConnectStart float64 30 | DomComplete float64 31 | DomContentLoadedEventEnd float64 32 | DomContentLoadedEventStart float64 33 | DomInteractive float64 34 | DomLoading float64 35 | DomainLookupEnd float64 36 | DomainLookupStart float64 37 | FetchStart float64 38 | LoadEventEnd float64 39 | LoadEventStart float64 40 | NavigationStart float64 41 | RedirectEnd float64 42 | RedirectStart float64 43 | RequestStart float64 44 | ResponseEnd float64 45 | ResponseStart float64 46 | SecureConnectionStart float64 47 | UnloadEventEnd float64 48 | UnloadEventStart float64 49 | } 50 | 51 | func probe(target string, w http.ResponseWriter) bool { 52 | // new page to ensure a clean session (no caching) 53 | options := []agouti.Option{ 54 | agouti.Desired(agouti.NewCapabilities().Browser("chrome").With("javascriptEnabled")), 55 | agouti.Timeout(5), 56 | } 57 | page, err := driver.NewPage(options...) 58 | if err != nil { 59 | log.Error(err) 60 | return false 61 | } 62 | defer page.Destroy() 63 | 64 | err = page.Navigate(target) 65 | if err != nil { 66 | log.Error(err) 67 | return false 68 | } 69 | url, err := page.URL() 70 | if err != nil { 71 | log.Error(err) 72 | return false 73 | } 74 | if url != target { 75 | log.Errorf("got unexpected URL, ensure target accounts for any redirects; got %q, expected %q", url, target) 76 | return false 77 | } 78 | 79 | var timings *navigationTimings 80 | err = page.RunScript("return window.performance.timing;", nil, &timings) 81 | if err != nil { 82 | log.Error(err) 83 | return false 84 | } 85 | 86 | fmt.Fprintf(w, "navigation_timing_connect_end_seconds %f\n", timings.ConnectEnd/msInSecond) 87 | fmt.Fprintf(w, "navigation_timing_connect_start_seconds %f\n", timings.ConnectStart/msInSecond) 88 | fmt.Fprintf(w, "navigation_timing_dom_complete_seconds %f\n", timings.DomComplete/msInSecond) 89 | fmt.Fprintf(w, "navigation_timing_dom_content_loaded_event_end_seconds %f\n", timings.DomContentLoadedEventEnd/msInSecond) 90 | fmt.Fprintf(w, "navigation_timing_dom_content_loaded_event_start_seconds %f\n", timings.DomContentLoadedEventStart/msInSecond) 91 | fmt.Fprintf(w, "navigation_timing_dom_interactive_seconds %f\n", timings.DomInteractive/msInSecond) 92 | fmt.Fprintf(w, "navigation_timing_dom_loading_seconds %f\n", timings.DomLoading/msInSecond) 93 | fmt.Fprintf(w, "navigation_timing_domain_lookup_end_seconds %f\n", timings.DomainLookupEnd/msInSecond) 94 | fmt.Fprintf(w, "navigation_timing_domain_lookup_start_seconds %f\n", timings.DomainLookupStart/msInSecond) 95 | fmt.Fprintf(w, "navigation_timing_fetch_start_seconds %f\n", timings.FetchStart/msInSecond) 96 | fmt.Fprintf(w, "navigation_timing_load_event_end_seconds %f\n", timings.LoadEventEnd/msInSecond) 97 | fmt.Fprintf(w, "navigation_timing_load_event_start_seconds %f\n", timings.LoadEventStart/msInSecond) 98 | fmt.Fprintf(w, "navigation_timing_redirect_end_seconds %f\n", timings.RedirectEnd/msInSecond) 99 | fmt.Fprintf(w, "navigation_timing_redirect_start_seconds %f\n", timings.RedirectStart/msInSecond) 100 | fmt.Fprintf(w, "navigation_timing_request_start_seconds %f\n", timings.RequestStart/msInSecond) 101 | fmt.Fprintf(w, "navigation_timing_response_end_seconds %f\n", timings.ResponseEnd/msInSecond) 102 | fmt.Fprintf(w, "navigation_timing_response_start_seconds %f\n", timings.ResponseStart/msInSecond) 103 | fmt.Fprintf(w, "navigation_timing_secure_connection_start_seconds %f\n", timings.SecureConnectionStart/msInSecond) 104 | fmt.Fprintf(w, "navigation_timing_start_seconds %f\n", timings.NavigationStart/msInSecond) 105 | fmt.Fprintf(w, "navigation_timing_unload_event_end_seconds %f\n", timings.UnloadEventEnd/msInSecond) 106 | fmt.Fprintf(w, "navigation_timing_unload_event_start_seconds %f\n", timings.UnloadEventStart/msInSecond) 107 | 108 | logs, err := page.ReadAllLogs("browser") 109 | if err != nil { 110 | log.Error(err) 111 | return false 112 | } 113 | var warningCount, severeCount int 114 | for _, log := range logs { 115 | if log.Level == "WARNING" { 116 | warningCount++ 117 | } 118 | if log.Level == "SEVERE" { 119 | severeCount++ 120 | } 121 | } 122 | fmt.Fprintf(w, "browser_log_warning_count %d\n", warningCount) 123 | fmt.Fprintf(w, "browser_log_severe_count %d\n", severeCount) 124 | 125 | return true 126 | } 127 | -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/exported.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | var ( 8 | // std is the name of the standard logger in stdlib `log` 9 | std = New() 10 | ) 11 | 12 | func StandardLogger() *Logger { 13 | return std 14 | } 15 | 16 | // SetOutput sets the standard logger output. 17 | func SetOutput(out io.Writer) { 18 | std.mu.Lock() 19 | defer std.mu.Unlock() 20 | std.Out = out 21 | } 22 | 23 | // SetFormatter sets the standard logger formatter. 24 | func SetFormatter(formatter Formatter) { 25 | std.mu.Lock() 26 | defer std.mu.Unlock() 27 | std.Formatter = formatter 28 | } 29 | 30 | // SetLevel sets the standard logger level. 31 | func SetLevel(level Level) { 32 | std.mu.Lock() 33 | defer std.mu.Unlock() 34 | std.Level = level 35 | } 36 | 37 | // GetLevel returns the standard logger level. 38 | func GetLevel() Level { 39 | std.mu.Lock() 40 | defer std.mu.Unlock() 41 | return std.Level 42 | } 43 | 44 | // AddHook adds a hook to the standard logger hooks. 45 | func AddHook(hook Hook) { 46 | std.mu.Lock() 47 | defer std.mu.Unlock() 48 | std.Hooks.Add(hook) 49 | } 50 | 51 | // WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. 52 | func WithError(err error) *Entry { 53 | return std.WithField(ErrorKey, err) 54 | } 55 | 56 | // WithField creates an entry from the standard logger and adds a field to 57 | // it. If you want multiple fields, use `WithFields`. 58 | // 59 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal 60 | // or Panic on the Entry it returns. 61 | func WithField(key string, value interface{}) *Entry { 62 | return std.WithField(key, value) 63 | } 64 | 65 | // WithFields creates an entry from the standard logger and adds multiple 66 | // fields to it. This is simply a helper for `WithField`, invoking it 67 | // once for each field. 68 | // 69 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal 70 | // or Panic on the Entry it returns. 71 | func WithFields(fields Fields) *Entry { 72 | return std.WithFields(fields) 73 | } 74 | 75 | // Debug logs a message at level Debug on the standard logger. 76 | func Debug(args ...interface{}) { 77 | std.Debug(args...) 78 | } 79 | 80 | // Print logs a message at level Info on the standard logger. 81 | func Print(args ...interface{}) { 82 | std.Print(args...) 83 | } 84 | 85 | // Info logs a message at level Info on the standard logger. 86 | func Info(args ...interface{}) { 87 | std.Info(args...) 88 | } 89 | 90 | // Warn logs a message at level Warn on the standard logger. 91 | func Warn(args ...interface{}) { 92 | std.Warn(args...) 93 | } 94 | 95 | // Warning logs a message at level Warn on the standard logger. 96 | func Warning(args ...interface{}) { 97 | std.Warning(args...) 98 | } 99 | 100 | // Error logs a message at level Error on the standard logger. 101 | func Error(args ...interface{}) { 102 | std.Error(args...) 103 | } 104 | 105 | // Panic logs a message at level Panic on the standard logger. 106 | func Panic(args ...interface{}) { 107 | std.Panic(args...) 108 | } 109 | 110 | // Fatal logs a message at level Fatal on the standard logger. 111 | func Fatal(args ...interface{}) { 112 | std.Fatal(args...) 113 | } 114 | 115 | // Debugf logs a message at level Debug on the standard logger. 116 | func Debugf(format string, args ...interface{}) { 117 | std.Debugf(format, args...) 118 | } 119 | 120 | // Printf logs a message at level Info on the standard logger. 121 | func Printf(format string, args ...interface{}) { 122 | std.Printf(format, args...) 123 | } 124 | 125 | // Infof logs a message at level Info on the standard logger. 126 | func Infof(format string, args ...interface{}) { 127 | std.Infof(format, args...) 128 | } 129 | 130 | // Warnf logs a message at level Warn on the standard logger. 131 | func Warnf(format string, args ...interface{}) { 132 | std.Warnf(format, args...) 133 | } 134 | 135 | // Warningf logs a message at level Warn on the standard logger. 136 | func Warningf(format string, args ...interface{}) { 137 | std.Warningf(format, args...) 138 | } 139 | 140 | // Errorf logs a message at level Error on the standard logger. 141 | func Errorf(format string, args ...interface{}) { 142 | std.Errorf(format, args...) 143 | } 144 | 145 | // Panicf logs a message at level Panic on the standard logger. 146 | func Panicf(format string, args ...interface{}) { 147 | std.Panicf(format, args...) 148 | } 149 | 150 | // Fatalf logs a message at level Fatal on the standard logger. 151 | func Fatalf(format string, args ...interface{}) { 152 | std.Fatalf(format, args...) 153 | } 154 | 155 | // Debugln logs a message at level Debug on the standard logger. 156 | func Debugln(args ...interface{}) { 157 | std.Debugln(args...) 158 | } 159 | 160 | // Println logs a message at level Info on the standard logger. 161 | func Println(args ...interface{}) { 162 | std.Println(args...) 163 | } 164 | 165 | // Infoln logs a message at level Info on the standard logger. 166 | func Infoln(args ...interface{}) { 167 | std.Infoln(args...) 168 | } 169 | 170 | // Warnln logs a message at level Warn on the standard logger. 171 | func Warnln(args ...interface{}) { 172 | std.Warnln(args...) 173 | } 174 | 175 | // Warningln logs a message at level Warn on the standard logger. 176 | func Warningln(args ...interface{}) { 177 | std.Warningln(args...) 178 | } 179 | 180 | // Errorln logs a message at level Error on the standard logger. 181 | func Errorln(args ...interface{}) { 182 | std.Errorln(args...) 183 | } 184 | 185 | // Panicln logs a message at level Panic on the standard logger. 186 | func Panicln(args ...interface{}) { 187 | std.Panicln(args...) 188 | } 189 | 190 | // Fatalln logs a message at level Fatal on the standard logger. 191 | func Fatalln(args ...interface{}) { 192 | std.Fatalln(args...) 193 | } 194 | -------------------------------------------------------------------------------- /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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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/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_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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /vendor/github.com/beorn7/perks/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Blake Mizerany 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/LICENSE: -------------------------------------------------------------------------------- 1 | Go support for Protocol Buffers - Google's data interchange format 2 | 3 | Copyright 2010 The Go Authors. All rights reserved. 4 | https://github.com/golang/protobuf 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following disclaimer 14 | in the documentation and/or other materials provided with the 15 | distribution. 16 | * Neither the name of Google Inc. nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/proto/Makefile: -------------------------------------------------------------------------------- 1 | # Go support for Protocol Buffers - Google's data interchange format 2 | # 3 | # Copyright 2010 The Go Authors. All rights reserved. 4 | # https://github.com/golang/protobuf 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following disclaimer 14 | # in the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Google Inc. nor the names of its 17 | # contributors may be used to endorse or promote products derived from 18 | # this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | install: 33 | go install 34 | 35 | test: install generate-test-pbs 36 | go test 37 | 38 | 39 | generate-test-pbs: 40 | make install 41 | make -C testdata 42 | protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto 43 | make 44 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt T. Proud (matt.proud@gmail.com) 2 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | 3 | cover: 4 | go test -cover -v -coverprofile=cover.dat ./... 5 | go tool cover -func cover.dat 6 | 7 | .PHONY: cover 8 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "errors" 20 | "io" 21 | 22 | "github.com/golang/protobuf/proto" 23 | ) 24 | 25 | var errInvalidVarint = errors.New("invalid varint32 encountered") 26 | 27 | // ReadDelimited decodes a message from the provided length-delimited stream, 28 | // where the length is encoded as 32-bit varint prefix to the message body. 29 | // It returns the total number of bytes read and any applicable error. This is 30 | // roughly equivalent to the companion Java API's 31 | // MessageLite#parseDelimitedFrom. As per the reader contract, this function 32 | // calls r.Read repeatedly as required until exactly one message including its 33 | // prefix is read and decoded (or an error has occurred). The function never 34 | // reads more bytes from the stream than required. The function never returns 35 | // an error if a message has been read and decoded correctly, even if the end 36 | // of the stream has been reached in doing so. In that case, any subsequent 37 | // calls return (0, io.EOF). 38 | func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { 39 | // Per AbstractParser#parsePartialDelimitedFrom with 40 | // CodedInputStream#readRawVarint32. 41 | var headerBuf [binary.MaxVarintLen32]byte 42 | var bytesRead, varIntBytes int 43 | var messageLength uint64 44 | for varIntBytes == 0 { // i.e. no varint has been decoded yet. 45 | if bytesRead >= len(headerBuf) { 46 | return bytesRead, errInvalidVarint 47 | } 48 | // We have to read byte by byte here to avoid reading more bytes 49 | // than required. Each read byte is appended to what we have 50 | // read before. 51 | newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) 52 | if newBytesRead == 0 { 53 | if err != nil { 54 | return bytesRead, err 55 | } 56 | // A Reader should not return (0, nil), but if it does, 57 | // it should be treated as no-op (according to the 58 | // Reader contract). So let's go on... 59 | continue 60 | } 61 | bytesRead += newBytesRead 62 | // Now present everything read so far to the varint decoder and 63 | // see if a varint can be decoded already. 64 | messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead]) 65 | } 66 | 67 | messageBuf := make([]byte, messageLength) 68 | newBytesRead, err := io.ReadFull(r, messageBuf) 69 | bytesRead += newBytesRead 70 | if err != nil { 71 | return bytesRead, err 72 | } 73 | 74 | return bytesRead, proto.Unmarshal(messageBuf, m) 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package pbutil provides record length-delimited Protocol Buffer streaming. 16 | package pbutil 17 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "io" 20 | 21 | "github.com/golang/protobuf/proto" 22 | ) 23 | 24 | // WriteDelimited encodes and dumps a message to the provided writer prefixed 25 | // with a 32-bit varint indicating the length of the encoded message, producing 26 | // a length-delimited record stream, which can be used to chain together 27 | // encoded messages of the same type together in a file. It returns the total 28 | // number of bytes written and any applicable error. This is roughly 29 | // equivalent to the companion Java API's MessageLite#writeDelimitedTo. 30 | func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { 31 | buffer, err := proto.Marshal(m) 32 | if err != nil { 33 | return 0, err 34 | } 35 | 36 | var buf [binary.MaxVarintLen32]byte 37 | encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) 38 | 39 | sync, err := w.Write(buf[:encodedLength]) 40 | if err != nil { 41 | return sync, err 42 | } 43 | 44 | n, err = w.Write(buffer) 45 | return n + sync, err 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/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/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/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/github.com/prometheus/client_golang/prometheus/doc.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 provides embeddable metric primitives for servers and 15 | // standardized exposition of telemetry through a web services interface. 16 | // 17 | // All exported functions and methods are safe to be used concurrently unless 18 | // specified otherwise. 19 | // 20 | // To expose metrics registered with the Prometheus registry, an HTTP server 21 | // needs to know about the Prometheus handler. The usual endpoint is "/metrics". 22 | // 23 | // http.Handle("/metrics", prometheus.Handler()) 24 | // 25 | // As a starting point a very basic usage example: 26 | // 27 | // package main 28 | // 29 | // import ( 30 | // "net/http" 31 | // 32 | // "github.com/prometheus/client_golang/prometheus" 33 | // ) 34 | // 35 | // var ( 36 | // cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{ 37 | // Name: "cpu_temperature_celsius", 38 | // Help: "Current temperature of the CPU.", 39 | // }) 40 | // hdFailures = prometheus.NewCounter(prometheus.CounterOpts{ 41 | // Name: "hd_errors_total", 42 | // Help: "Number of hard-disk errors.", 43 | // }) 44 | // ) 45 | // 46 | // func init() { 47 | // prometheus.MustRegister(cpuTemp) 48 | // prometheus.MustRegister(hdFailures) 49 | // } 50 | // 51 | // func main() { 52 | // cpuTemp.Set(65.3) 53 | // hdFailures.Inc() 54 | // 55 | // http.Handle("/metrics", prometheus.Handler()) 56 | // http.ListenAndServe(":8080", nil) 57 | // } 58 | // 59 | // 60 | // This is a complete program that exports two metrics, a Gauge and a Counter. 61 | // It also exports some stats about the HTTP usage of the /metrics 62 | // endpoint. (See the Handler function for more detail.) 63 | // 64 | // Two more advanced metric types are the Summary and Histogram. A more 65 | // thorough description of metric types can be found in the prometheus docs: 66 | // https://prometheus.io/docs/concepts/metric_types/ 67 | // 68 | // In addition to the fundamental metric types Gauge, Counter, Summary, and 69 | // Histogram, a very important part of the Prometheus data model is the 70 | // partitioning of samples along dimensions called labels, which results in 71 | // metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec, 72 | // and HistogramVec. 73 | // 74 | // Those are all the parts needed for basic usage. Detailed documentation and 75 | // examples are provided below. 76 | // 77 | // Everything else this package offers is essentially for "power users" only. A 78 | // few pointers to "power user features": 79 | // 80 | // All the various ...Opts structs have a ConstLabels field for labels that 81 | // never change their value (which is only useful under special circumstances, 82 | // see documentation of the Opts type). 83 | // 84 | // The Untyped metric behaves like a Gauge, but signals the Prometheus server 85 | // not to assume anything about its type. 86 | // 87 | // Functions to fine-tune how the metric registry works: EnableCollectChecks, 88 | // PanicOnCollectError, Register, Unregister, SetMetricFamilyInjectionHook. 89 | // 90 | // For custom metric collection, there are two entry points: Custom Metric 91 | // implementations and custom Collector implementations. A Metric is the 92 | // fundamental unit in the Prometheus data model: a sample at a point in time 93 | // together with its meta-data (like its fully-qualified name and any number of 94 | // pairs of label name and label value) that knows how to marshal itself into a 95 | // data transfer object (aka DTO, implemented as a protocol buffer). A Collector 96 | // gets registered with the Prometheus registry and manages the collection of 97 | // one or more Metrics. Many parts of this package are building blocks for 98 | // Metrics and Collectors. Desc is the metric descriptor, actually used by all 99 | // metrics under the hood, and by Collectors to describe the Metrics to be 100 | // collected, but only to be dealt with by users if they implement their own 101 | // Metrics or Collectors. To create a Desc, the BuildFQName function will come 102 | // in handy. Other useful components for Metric and Collector implementation 103 | // include: LabelPairSorter to sort the DTO version of label pairs, 104 | // NewConstMetric and MustNewConstMetric to create "throw away" Metrics at 105 | // collection time, MetricVec to bundle custom Metrics into a metric vector 106 | // Collector, SelfCollector to make a custom Metric collect itself. 107 | // 108 | // A good example for a custom Collector is the ExpVarCollector included in this 109 | // package, which exports variables exported via the "expvar" package as 110 | // Prometheus metrics. 111 | package prometheus 112 | -------------------------------------------------------------------------------- /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/fnv.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | // Inline and byte-free variant of hash/fnv's fnv64a. 4 | 5 | const ( 6 | offset64 = 14695981039346656037 7 | prime64 = 1099511628211 8 | ) 9 | 10 | // hashNew initializies a new fnv64a hash value. 11 | func hashNew() uint64 { 12 | return offset64 13 | } 14 | 15 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 16 | func hashAdd(h uint64, s string) uint64 { 17 | for i := 0; i < len(s); i++ { 18 | h ^= uint64(s[i]) 19 | h *= prime64 20 | } 21 | return h 22 | } 23 | 24 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 25 | func hashAddByte(h uint64, b byte) uint64 { 26 | h ^= uint64(b) 27 | h *= prime64 28 | return h 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/gauge.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Gauge is a Metric that represents a single numerical value that can 17 | // arbitrarily go up and down. 18 | // 19 | // A Gauge is typically used for measured values like temperatures or current 20 | // memory usage, but also "counts" that can go up and down, like the number of 21 | // running goroutines. 22 | // 23 | // To create Gauge instances, use NewGauge. 24 | type Gauge interface { 25 | Metric 26 | Collector 27 | 28 | // Set sets the Gauge to an arbitrary value. 29 | Set(float64) 30 | // Inc increments the Gauge by 1. 31 | Inc() 32 | // Dec decrements the Gauge by 1. 33 | Dec() 34 | // Add adds the given value to the Gauge. (The value can be 35 | // negative, resulting in a decrease of the Gauge.) 36 | Add(float64) 37 | // Sub subtracts the given value from the Gauge. (The value can be 38 | // negative, resulting in an increase of the Gauge.) 39 | Sub(float64) 40 | } 41 | 42 | // GaugeOpts is an alias for Opts. See there for doc comments. 43 | type GaugeOpts Opts 44 | 45 | // NewGauge creates a new Gauge based on the provided GaugeOpts. 46 | func NewGauge(opts GaugeOpts) Gauge { 47 | return newValue(NewDesc( 48 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 49 | opts.Help, 50 | nil, 51 | opts.ConstLabels, 52 | ), GaugeValue, 0) 53 | } 54 | 55 | // GaugeVec is a Collector that bundles a set of Gauges that all share the same 56 | // Desc, but have different values for their variable labels. This is used if 57 | // you want to count the same thing partitioned by various dimensions 58 | // (e.g. number of operations queued, partitioned by user and operation 59 | // type). Create instances with NewGaugeVec. 60 | type GaugeVec struct { 61 | MetricVec 62 | } 63 | 64 | // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and 65 | // partitioned by the given label names. At least one label name must be 66 | // provided. 67 | func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { 68 | desc := NewDesc( 69 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 70 | opts.Help, 71 | labelNames, 72 | opts.ConstLabels, 73 | ) 74 | return &GaugeVec{ 75 | MetricVec: MetricVec{ 76 | children: map[uint64]Metric{}, 77 | desc: desc, 78 | newMetric: func(lvs ...string) Metric { 79 | return newValue(desc, GaugeValue, 0, lvs...) 80 | }, 81 | }, 82 | } 83 | } 84 | 85 | // GetMetricWithLabelValues replaces the method of the same name in 86 | // MetricVec. The difference is that this method returns a Gauge and not a 87 | // Metric so that no type conversion is required. 88 | func (m *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) { 89 | metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) 90 | if metric != nil { 91 | return metric.(Gauge), err 92 | } 93 | return nil, err 94 | } 95 | 96 | // GetMetricWith replaces the method of the same name in MetricVec. The 97 | // difference is that this method returns a Gauge and not a Metric so that no 98 | // type conversion is required. 99 | func (m *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { 100 | metric, err := m.MetricVec.GetMetricWith(labels) 101 | if metric != nil { 102 | return metric.(Gauge), err 103 | } 104 | return nil, err 105 | } 106 | 107 | // WithLabelValues works as GetMetricWithLabelValues, but panics where 108 | // GetMetricWithLabelValues would have returned an error. By not returning an 109 | // error, WithLabelValues allows shortcuts like 110 | // myVec.WithLabelValues("404", "GET").Add(42) 111 | func (m *GaugeVec) WithLabelValues(lvs ...string) Gauge { 112 | return m.MetricVec.WithLabelValues(lvs...).(Gauge) 113 | } 114 | 115 | // With works as GetMetricWith, but panics where GetMetricWithLabels would have 116 | // returned an error. By not returning an error, With allows shortcuts like 117 | // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) 118 | func (m *GaugeVec) With(labels Labels) Gauge { 119 | return m.MetricVec.With(labels).(Gauge) 120 | } 121 | 122 | // GaugeFunc is a Gauge whose value is determined at collect time by calling a 123 | // provided function. 124 | // 125 | // To create GaugeFunc instances, use NewGaugeFunc. 126 | type GaugeFunc interface { 127 | Metric 128 | Collector 129 | } 130 | 131 | // NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The 132 | // value reported is determined by calling the given function from within the 133 | // Write method. Take into account that metric collection may happen 134 | // concurrently. If that results in concurrent calls to Write, like in the case 135 | // where a GaugeFunc is directly registered with Prometheus, the provided 136 | // function must be concurrency-safe. 137 | func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc { 138 | return newValueFunc(NewDesc( 139 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 140 | opts.Help, 141 | nil, 142 | opts.ConstLabels, 143 | ), GaugeValue, function) 144 | } 145 | -------------------------------------------------------------------------------- /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/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/client_golang/prometheus/untyped.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Untyped is a Metric that represents a single numerical value that can 17 | // arbitrarily go up and down. 18 | // 19 | // An Untyped metric works the same as a Gauge. The only difference is that to 20 | // no type information is implied. 21 | // 22 | // To create Untyped instances, use NewUntyped. 23 | type Untyped interface { 24 | Metric 25 | Collector 26 | 27 | // Set sets the Untyped metric to an arbitrary value. 28 | Set(float64) 29 | // Inc increments the Untyped metric by 1. 30 | Inc() 31 | // Dec decrements the Untyped metric by 1. 32 | Dec() 33 | // Add adds the given value to the Untyped metric. (The value can be 34 | // negative, resulting in a decrease.) 35 | Add(float64) 36 | // Sub subtracts the given value from the Untyped metric. (The value can 37 | // be negative, resulting in an increase.) 38 | Sub(float64) 39 | } 40 | 41 | // UntypedOpts is an alias for Opts. See there for doc comments. 42 | type UntypedOpts Opts 43 | 44 | // NewUntyped creates a new Untyped metric from the provided UntypedOpts. 45 | func NewUntyped(opts UntypedOpts) Untyped { 46 | return newValue(NewDesc( 47 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 48 | opts.Help, 49 | nil, 50 | opts.ConstLabels, 51 | ), UntypedValue, 0) 52 | } 53 | 54 | // UntypedVec is a Collector that bundles a set of Untyped metrics that all 55 | // share the same Desc, but have different values for their variable 56 | // labels. This is used if you want to count the same thing partitioned by 57 | // various dimensions. Create instances with NewUntypedVec. 58 | type UntypedVec struct { 59 | MetricVec 60 | } 61 | 62 | // NewUntypedVec creates a new UntypedVec based on the provided UntypedOpts and 63 | // partitioned by the given label names. At least one label name must be 64 | // provided. 65 | func NewUntypedVec(opts UntypedOpts, labelNames []string) *UntypedVec { 66 | desc := NewDesc( 67 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 68 | opts.Help, 69 | labelNames, 70 | opts.ConstLabels, 71 | ) 72 | return &UntypedVec{ 73 | MetricVec: MetricVec{ 74 | children: map[uint64]Metric{}, 75 | desc: desc, 76 | newMetric: func(lvs ...string) Metric { 77 | return newValue(desc, UntypedValue, 0, lvs...) 78 | }, 79 | }, 80 | } 81 | } 82 | 83 | // GetMetricWithLabelValues replaces the method of the same name in 84 | // MetricVec. The difference is that this method returns an Untyped and not a 85 | // Metric so that no type conversion is required. 86 | func (m *UntypedVec) GetMetricWithLabelValues(lvs ...string) (Untyped, error) { 87 | metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...) 88 | if metric != nil { 89 | return metric.(Untyped), err 90 | } 91 | return nil, err 92 | } 93 | 94 | // GetMetricWith replaces the method of the same name in MetricVec. The 95 | // difference is that this method returns an Untyped and not a Metric so that no 96 | // type conversion is required. 97 | func (m *UntypedVec) GetMetricWith(labels Labels) (Untyped, error) { 98 | metric, err := m.MetricVec.GetMetricWith(labels) 99 | if metric != nil { 100 | return metric.(Untyped), err 101 | } 102 | return nil, err 103 | } 104 | 105 | // WithLabelValues works as GetMetricWithLabelValues, but panics where 106 | // GetMetricWithLabelValues would have returned an error. By not returning an 107 | // error, WithLabelValues allows shortcuts like 108 | // myVec.WithLabelValues("404", "GET").Add(42) 109 | func (m *UntypedVec) WithLabelValues(lvs ...string) Untyped { 110 | return m.MetricVec.WithLabelValues(lvs...).(Untyped) 111 | } 112 | 113 | // With works as GetMetricWith, but panics where GetMetricWithLabels would have 114 | // returned an error. By not returning an error, With allows shortcuts like 115 | // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) 116 | func (m *UntypedVec) With(labels Labels) Untyped { 117 | return m.MetricVec.With(labels).(Untyped) 118 | } 119 | 120 | // UntypedFunc is an Untyped whose value is determined at collect time by 121 | // calling a provided function. 122 | // 123 | // To create UntypedFunc instances, use NewUntypedFunc. 124 | type UntypedFunc interface { 125 | Metric 126 | Collector 127 | } 128 | 129 | // NewUntypedFunc creates a new UntypedFunc based on the provided 130 | // UntypedOpts. The value reported is determined by calling the given function 131 | // from within the Write method. Take into account that metric collection may 132 | // happen concurrently. If that results in concurrent calls to Write, like in 133 | // the case where an UntypedFunc is directly registered with Prometheus, the 134 | // provided function must be concurrency-safe. 135 | func NewUntypedFunc(opts UntypedOpts, function func() float64) UntypedFunc { 136 | return newValueFunc(NewDesc( 137 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 138 | opts.Help, 139 | nil, 140 | opts.ConstLabels, 141 | ), UntypedValue, function) 142 | } 143 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_model/NOTICE: -------------------------------------------------------------------------------- 1 | Data model artifacts for Prometheus. 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/NOTICE: -------------------------------------------------------------------------------- 1 | Common libraries shared by Prometheus Go components. 2 | Copyright 2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package expfmt 15 | 16 | import ( 17 | "fmt" 18 | "io" 19 | "net/http" 20 | 21 | "github.com/golang/protobuf/proto" 22 | "github.com/matttproud/golang_protobuf_extensions/pbutil" 23 | "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" 24 | 25 | dto "github.com/prometheus/client_model/go" 26 | ) 27 | 28 | // Encoder types encode metric families into an underlying wire protocol. 29 | type Encoder interface { 30 | Encode(*dto.MetricFamily) error 31 | } 32 | 33 | type encoder func(*dto.MetricFamily) error 34 | 35 | func (e encoder) Encode(v *dto.MetricFamily) error { 36 | return e(v) 37 | } 38 | 39 | // Negotiate returns the Content-Type based on the given Accept header. 40 | // If no appropriate accepted type is found, FmtText is returned. 41 | func Negotiate(h http.Header) Format { 42 | for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { 43 | // Check for protocol buffer 44 | if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { 45 | switch ac.Params["encoding"] { 46 | case "delimited": 47 | return FmtProtoDelim 48 | case "text": 49 | return FmtProtoText 50 | case "compact-text": 51 | return FmtProtoCompact 52 | } 53 | } 54 | // Check for text format. 55 | ver := ac.Params["version"] 56 | if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { 57 | return FmtText 58 | } 59 | } 60 | return FmtText 61 | } 62 | 63 | // NewEncoder returns a new encoder based on content type negotiation. 64 | func NewEncoder(w io.Writer, format Format) Encoder { 65 | switch format { 66 | case FmtProtoDelim: 67 | return encoder(func(v *dto.MetricFamily) error { 68 | _, err := pbutil.WriteDelimited(w, v) 69 | return err 70 | }) 71 | case FmtProtoCompact: 72 | return encoder(func(v *dto.MetricFamily) error { 73 | _, err := fmt.Fprintln(w, v.String()) 74 | return err 75 | }) 76 | case FmtProtoText: 77 | return encoder(func(v *dto.MetricFamily) error { 78 | _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) 79 | return err 80 | }) 81 | case FmtText: 82 | return encoder(func(v *dto.MetricFamily) error { 83 | _, err := MetricFamilyToText(w, v) 84 | return err 85 | }) 86 | } 87 | panic("expfmt.NewEncoder: unknown format") 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/expfmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // A package for reading and writing Prometheus metrics. 15 | package expfmt 16 | 17 | type Format string 18 | 19 | const ( 20 | TextVersion = "0.0.4" 21 | 22 | ProtoType = `application/vnd.google.protobuf` 23 | ProtoProtocol = `io.prometheus.client.MetricFamily` 24 | ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" 25 | 26 | // The Content-Type values for the different wire protocols. 27 | FmtUnknown Format = `` 28 | FmtText Format = `text/plain; version=` + TextVersion 29 | FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` 30 | FmtProtoText Format = ProtoFmt + ` encoding=text` 31 | FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` 32 | 33 | // 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/prometheus/common/expfmt/fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Build only when actually fuzzing 15 | // +build gofuzz 16 | 17 | package expfmt 18 | 19 | import "bytes" 20 | 21 | // Fuzz text metric parser with with github.com/dvyukov/go-fuzz: 22 | // 23 | // go-fuzz-build github.com/prometheus/common/expfmt 24 | // go-fuzz -bin expfmt-fuzz.zip -workdir fuzz 25 | // 26 | // Further input samples should go in the folder fuzz/corpus. 27 | func Fuzz(in []byte) int { 28 | parser := TextParser{} 29 | _, err := parser.TextToMetricFamilies(bytes.NewReader(in)) 30 | 31 | if err != nil { 32 | return 0 33 | } 34 | 35 | return 1 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt: -------------------------------------------------------------------------------- 1 | PACKAGE 2 | 3 | package goautoneg 4 | import "bitbucket.org/ww/goautoneg" 5 | 6 | HTTP Content-Type Autonegotiation. 7 | 8 | The functions in this package implement the behaviour specified in 9 | http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 10 | 11 | Copyright (c) 2011, Open Knowledge Foundation Ltd. 12 | All rights reserved. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are 16 | met: 17 | 18 | Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 21 | Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in 23 | the documentation and/or other materials provided with the 24 | distribution. 25 | 26 | Neither the name of the Open Knowledge Foundation Ltd. nor the 27 | names of its contributors may be used to endorse or promote 28 | products derived from this software without specific prior written 29 | permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 37 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 38 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 39 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 41 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | 43 | 44 | FUNCTIONS 45 | 46 | func Negotiate(header string, alternatives []string) (content_type string) 47 | Negotiate the most appropriate content_type given the accept header 48 | and a list of alternatives. 49 | 50 | func ParseAccept(header string) (accept []Accept) 51 | Parse an Accept Header string returning a sorted list 52 | of clauses 53 | 54 | 55 | TYPES 56 | 57 | type Accept struct { 58 | Type, SubType string 59 | Q float32 60 | Params map[string]string 61 | } 62 | Structure to represent a clause in an HTTP Accept Header 63 | 64 | 65 | SUBDIRECTORIES 66 | 67 | .hg 68 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go: -------------------------------------------------------------------------------- 1 | /* 2 | HTTP Content-Type Autonegotiation. 3 | 4 | The functions in this package implement the behaviour specified in 5 | http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 6 | 7 | Copyright (c) 2011, Open Knowledge Foundation Ltd. 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are 12 | met: 13 | 14 | Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in 19 | the documentation and/or other materials provided with the 20 | distribution. 21 | 22 | Neither the name of the Open Knowledge Foundation Ltd. nor the 23 | names of its contributors may be used to endorse or promote 24 | products derived from this software without specific prior written 25 | permission. 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | 39 | 40 | */ 41 | package goautoneg 42 | 43 | import ( 44 | "sort" 45 | "strconv" 46 | "strings" 47 | ) 48 | 49 | // Structure to represent a clause in an HTTP Accept Header 50 | type Accept struct { 51 | Type, SubType string 52 | Q float64 53 | Params map[string]string 54 | } 55 | 56 | // For internal use, so that we can use the sort interface 57 | type accept_slice []Accept 58 | 59 | func (accept accept_slice) Len() int { 60 | slice := []Accept(accept) 61 | return len(slice) 62 | } 63 | 64 | func (accept accept_slice) Less(i, j int) bool { 65 | slice := []Accept(accept) 66 | ai, aj := slice[i], slice[j] 67 | if ai.Q > aj.Q { 68 | return true 69 | } 70 | if ai.Type != "*" && aj.Type == "*" { 71 | return true 72 | } 73 | if ai.SubType != "*" && aj.SubType == "*" { 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | func (accept accept_slice) Swap(i, j int) { 80 | slice := []Accept(accept) 81 | slice[i], slice[j] = slice[j], slice[i] 82 | } 83 | 84 | // Parse an Accept Header string returning a sorted list 85 | // of clauses 86 | func ParseAccept(header string) (accept []Accept) { 87 | parts := strings.Split(header, ",") 88 | accept = make([]Accept, 0, len(parts)) 89 | for _, part := range parts { 90 | part := strings.Trim(part, " ") 91 | 92 | a := Accept{} 93 | a.Params = make(map[string]string) 94 | a.Q = 1.0 95 | 96 | mrp := strings.Split(part, ";") 97 | 98 | media_range := mrp[0] 99 | sp := strings.Split(media_range, "/") 100 | a.Type = strings.Trim(sp[0], " ") 101 | 102 | switch { 103 | case len(sp) == 1 && a.Type == "*": 104 | a.SubType = "*" 105 | case len(sp) == 2: 106 | a.SubType = strings.Trim(sp[1], " ") 107 | default: 108 | continue 109 | } 110 | 111 | if len(mrp) == 1 { 112 | accept = append(accept, a) 113 | continue 114 | } 115 | 116 | for _, param := range mrp[1:] { 117 | sp := strings.SplitN(param, "=", 2) 118 | if len(sp) != 2 { 119 | continue 120 | } 121 | token := strings.Trim(sp[0], " ") 122 | if token == "q" { 123 | a.Q, _ = strconv.ParseFloat(sp[1], 32) 124 | } else { 125 | a.Params[token] = strings.Trim(sp[1], " ") 126 | } 127 | } 128 | 129 | accept = append(accept, a) 130 | } 131 | 132 | slice := accept_slice(accept) 133 | sort.Sort(slice) 134 | 135 | return 136 | } 137 | 138 | // Negotiate the most appropriate content_type given the accept header 139 | // and a list of alternatives. 140 | func Negotiate(header string, alternatives []string) (content_type string) { 141 | asp := make([][]string, 0, len(alternatives)) 142 | for _, ctype := range alternatives { 143 | asp = append(asp, strings.SplitN(ctype, "/", 2)) 144 | } 145 | for _, clause := range ParseAccept(header) { 146 | for i, ctsp := range asp { 147 | if clause.Type == ctsp[0] && clause.SubType == ctsp[1] { 148 | content_type = alternatives[i] 149 | return 150 | } 151 | if clause.Type == ctsp[0] && clause.SubType == "*" { 152 | content_type = alternatives[i] 153 | return 154 | } 155 | if clause.Type == "*" && clause.SubType == "*" { 156 | content_type = alternatives[i] 157 | return 158 | } 159 | } 160 | } 161 | return 162 | } 163 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/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/prometheus/common/model/alert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "time" 19 | ) 20 | 21 | type AlertStatus string 22 | 23 | const ( 24 | AlertFiring AlertStatus = "firing" 25 | AlertResolved AlertStatus = "resolved" 26 | ) 27 | 28 | // Alert is a generic representation of an alert in the Prometheus eco-system. 29 | type Alert struct { 30 | // Label value pairs for purpose of aggregation, matching, and disposition 31 | // dispatching. This must minimally include an "alertname" label. 32 | Labels LabelSet `json:"labels"` 33 | 34 | // Extra key/value information which does not define alert identity. 35 | Annotations LabelSet `json:"annotations"` 36 | 37 | // The known time range for this alert. Both ends are optional. 38 | StartsAt time.Time `json:"startsAt,omitempty"` 39 | EndsAt time.Time `json:"endsAt,omitempty"` 40 | GeneratorURL string `json:"generatorURL"` 41 | } 42 | 43 | // Name returns the name of the alert. It is equivalent to the "alertname" label. 44 | func (a *Alert) Name() string { 45 | return string(a.Labels[AlertNameLabel]) 46 | } 47 | 48 | // Fingerprint returns a unique hash for the alert. It is equivalent to 49 | // the fingerprint of the alert's label set. 50 | func (a *Alert) Fingerprint() Fingerprint { 51 | return a.Labels.Fingerprint() 52 | } 53 | 54 | func (a *Alert) String() string { 55 | s := fmt.Sprintf("%s[%s]", a.Name(), a.Fingerprint().String()[:7]) 56 | if a.Resolved() { 57 | return s + "[resolved]" 58 | } 59 | return s + "[active]" 60 | } 61 | 62 | // Resolved returns true iff the activity interval ended in the past. 63 | func (a *Alert) Resolved() bool { 64 | return a.ResolvedAt(time.Now()) 65 | } 66 | 67 | // ResolvedAt returns true off the activity interval ended before 68 | // the given timestamp. 69 | func (a *Alert) ResolvedAt(ts time.Time) bool { 70 | if a.EndsAt.IsZero() { 71 | return false 72 | } 73 | return !a.EndsAt.After(ts) 74 | } 75 | 76 | // Status returns the status of the alert. 77 | func (a *Alert) Status() AlertStatus { 78 | if a.Resolved() { 79 | return AlertResolved 80 | } 81 | return AlertFiring 82 | } 83 | 84 | // Validate checks whether the alert data is inconsistent. 85 | func (a *Alert) Validate() error { 86 | if a.StartsAt.IsZero() { 87 | return fmt.Errorf("start time missing") 88 | } 89 | if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { 90 | return fmt.Errorf("start time must be before end time") 91 | } 92 | if err := a.Labels.Validate(); err != nil { 93 | return fmt.Errorf("invalid label set: %s", err) 94 | } 95 | if len(a.Labels) == 0 { 96 | return fmt.Errorf("at least one label pair required") 97 | } 98 | if err := a.Annotations.Validate(); err != nil { 99 | return fmt.Errorf("invalid annotations: %s", err) 100 | } 101 | return nil 102 | } 103 | 104 | // Alert is a list of alerts that can be sorted in chronological order. 105 | type Alerts []*Alert 106 | 107 | func (as Alerts) Len() int { return len(as) } 108 | func (as Alerts) Swap(i, j int) { as[i], as[j] = as[j], as[i] } 109 | 110 | func (as Alerts) Less(i, j int) bool { 111 | if as[i].StartsAt.Before(as[j].StartsAt) { 112 | return true 113 | } 114 | if as[i].EndsAt.Before(as[j].EndsAt) { 115 | return true 116 | } 117 | return as[i].Fingerprint() < as[j].Fingerprint() 118 | } 119 | 120 | // HasFiring returns true iff one of the alerts is not resolved. 121 | func (as Alerts) HasFiring() bool { 122 | for _, a := range as { 123 | if !a.Resolved() { 124 | return true 125 | } 126 | } 127 | return false 128 | } 129 | 130 | // Status returns StatusFiring iff at least one of the alerts is firing. 131 | func (as Alerts) Status() AlertStatus { 132 | if as.HasFiring() { 133 | return AlertFiring 134 | } 135 | return AlertResolved 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fingerprinting.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "strconv" 19 | ) 20 | 21 | // Fingerprint provides a hash-capable representation of a Metric. 22 | // For our purposes, FNV-1A 64-bit is used. 23 | type Fingerprint uint64 24 | 25 | // FingerprintFromString transforms a string representation into a Fingerprint. 26 | func FingerprintFromString(s string) (Fingerprint, error) { 27 | num, err := strconv.ParseUint(s, 16, 64) 28 | return Fingerprint(num), err 29 | } 30 | 31 | // ParseFingerprint parses the input string into a fingerprint. 32 | func ParseFingerprint(s string) (Fingerprint, error) { 33 | num, err := strconv.ParseUint(s, 16, 64) 34 | if err != nil { 35 | return 0, err 36 | } 37 | return Fingerprint(num), nil 38 | } 39 | 40 | func (f Fingerprint) String() string { 41 | return fmt.Sprintf("%016x", uint64(f)) 42 | } 43 | 44 | // Fingerprints represents a collection of Fingerprint subject to a given 45 | // natural sorting scheme. It implements sort.Interface. 46 | type Fingerprints []Fingerprint 47 | 48 | // Len implements sort.Interface. 49 | func (f Fingerprints) Len() int { 50 | return len(f) 51 | } 52 | 53 | // Less implements sort.Interface. 54 | func (f Fingerprints) Less(i, j int) bool { 55 | return f[i] < f[j] 56 | } 57 | 58 | // Swap implements sort.Interface. 59 | func (f Fingerprints) Swap(i, j int) { 60 | f[i], f[j] = f[j], f[i] 61 | } 62 | 63 | // FingerprintSet is a set of Fingerprints. 64 | type FingerprintSet map[Fingerprint]struct{} 65 | 66 | // Equal returns true if both sets contain the same elements (and not more). 67 | func (s FingerprintSet) Equal(o FingerprintSet) bool { 68 | if len(s) != len(o) { 69 | return false 70 | } 71 | 72 | for k := range s { 73 | if _, ok := o[k]; !ok { 74 | return false 75 | } 76 | } 77 | 78 | return true 79 | } 80 | 81 | // Intersection returns the elements contained in both sets. 82 | func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet { 83 | myLength, otherLength := len(s), len(o) 84 | if myLength == 0 || otherLength == 0 { 85 | return FingerprintSet{} 86 | } 87 | 88 | subSet := s 89 | superSet := o 90 | 91 | if otherLength < myLength { 92 | subSet = o 93 | superSet = s 94 | } 95 | 96 | out := FingerprintSet{} 97 | 98 | for k := range subSet { 99 | if _, ok := superSet[k]; ok { 100 | out[k] = struct{}{} 101 | } 102 | } 103 | 104 | return out 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fnv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | // Inline and byte-free variant of hash/fnv's fnv64a. 17 | 18 | const ( 19 | offset64 = 14695981039346656037 20 | prime64 = 1099511628211 21 | ) 22 | 23 | // hashNew initializies a new fnv64a hash value. 24 | func hashNew() uint64 { 25 | return offset64 26 | } 27 | 28 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 29 | func hashAdd(h uint64, s string) uint64 { 30 | for i := 0; i < len(s); i++ { 31 | h ^= uint64(s[i]) 32 | h *= prime64 33 | } 34 | return h 35 | } 36 | 37 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 38 | func hashAddByte(h uint64, b byte) uint64 { 39 | h ^= uint64(b) 40 | h *= prime64 41 | return h 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/labels.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | "regexp" 20 | "strings" 21 | "unicode/utf8" 22 | ) 23 | 24 | const ( 25 | // AlertNameLabel is the name of the label containing the an alert's name. 26 | AlertNameLabel = "alertname" 27 | 28 | // ExportedLabelPrefix is the prefix to prepend to the label names present in 29 | // exported metrics if a label of the same name is added by the server. 30 | ExportedLabelPrefix = "exported_" 31 | 32 | // MetricNameLabel is the label name indicating the metric name of a 33 | // timeseries. 34 | MetricNameLabel = "__name__" 35 | 36 | // SchemeLabel is the name of the label that holds the scheme on which to 37 | // scrape a target. 38 | SchemeLabel = "__scheme__" 39 | 40 | // AddressLabel is the name of the label that holds the address of 41 | // a scrape target. 42 | AddressLabel = "__address__" 43 | 44 | // MetricsPathLabel is the name of the label that holds the path on which to 45 | // scrape a target. 46 | MetricsPathLabel = "__metrics_path__" 47 | 48 | // ReservedLabelPrefix is a prefix which is not legal in user-supplied 49 | // label names. 50 | ReservedLabelPrefix = "__" 51 | 52 | // MetaLabelPrefix is a prefix for labels that provide meta information. 53 | // Labels with this prefix are used for intermediate label processing and 54 | // will not be attached to time series. 55 | MetaLabelPrefix = "__meta_" 56 | 57 | // TmpLabelPrefix is a prefix for temporary labels as part of relabelling. 58 | // Labels with this prefix are used for intermediate label processing and 59 | // will not be attached to time series. This is reserved for use in 60 | // Prometheus configuration files by users. 61 | TmpLabelPrefix = "__tmp_" 62 | 63 | // ParamLabelPrefix is a prefix for labels that provide URL parameters 64 | // used to scrape a target. 65 | ParamLabelPrefix = "__param_" 66 | 67 | // JobLabel is the label name indicating the job from which a timeseries 68 | // was scraped. 69 | JobLabel = "job" 70 | 71 | // InstanceLabel is the label name used for the instance label. 72 | InstanceLabel = "instance" 73 | 74 | // BucketLabel is used for the label that defines the upper bound of a 75 | // bucket of a histogram ("le" -> "less or equal"). 76 | BucketLabel = "le" 77 | 78 | // QuantileLabel is used for the label that defines the quantile in a 79 | // summary. 80 | QuantileLabel = "quantile" 81 | ) 82 | 83 | // LabelNameRE is a regular expression matching valid label names. 84 | var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") 85 | 86 | // A LabelName is a key for a LabelSet or Metric. It has a value associated 87 | // therewith. 88 | type LabelName string 89 | 90 | // IsValid is true iff the label name matches the pattern of LabelNameRE. 91 | func (ln LabelName) IsValid() bool { 92 | if len(ln) == 0 { 93 | return false 94 | } 95 | for i, b := range ln { 96 | if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { 97 | return false 98 | } 99 | } 100 | return true 101 | } 102 | 103 | // UnmarshalYAML implements the yaml.Unmarshaler interface. 104 | func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error { 105 | var s string 106 | if err := unmarshal(&s); err != nil { 107 | return err 108 | } 109 | if !LabelNameRE.MatchString(s) { 110 | return fmt.Errorf("%q is not a valid label name", s) 111 | } 112 | *ln = LabelName(s) 113 | return nil 114 | } 115 | 116 | // UnmarshalJSON implements the json.Unmarshaler interface. 117 | func (ln *LabelName) UnmarshalJSON(b []byte) error { 118 | var s string 119 | if err := json.Unmarshal(b, &s); err != nil { 120 | return err 121 | } 122 | if !LabelNameRE.MatchString(s) { 123 | return fmt.Errorf("%q is not a valid label name", s) 124 | } 125 | *ln = LabelName(s) 126 | return nil 127 | } 128 | 129 | // LabelNames is a sortable LabelName slice. In implements sort.Interface. 130 | type LabelNames []LabelName 131 | 132 | func (l LabelNames) Len() int { 133 | return len(l) 134 | } 135 | 136 | func (l LabelNames) Less(i, j int) bool { 137 | return l[i] < l[j] 138 | } 139 | 140 | func (l LabelNames) Swap(i, j int) { 141 | l[i], l[j] = l[j], l[i] 142 | } 143 | 144 | func (l LabelNames) String() string { 145 | labelStrings := make([]string, 0, len(l)) 146 | for _, label := range l { 147 | labelStrings = append(labelStrings, string(label)) 148 | } 149 | return strings.Join(labelStrings, ", ") 150 | } 151 | 152 | // A LabelValue is an associated value for a LabelName. 153 | type LabelValue string 154 | 155 | // IsValid returns true iff the string is a valid UTF8. 156 | func (lv LabelValue) IsValid() bool { 157 | return utf8.ValidString(string(lv)) 158 | } 159 | 160 | // LabelValues is a sortable LabelValue slice. It implements sort.Interface. 161 | type LabelValues []LabelValue 162 | 163 | func (l LabelValues) Len() int { 164 | return len(l) 165 | } 166 | 167 | func (l LabelValues) Less(i, j int) bool { 168 | return string(l[i]) < string(l[j]) 169 | } 170 | 171 | func (l LabelValues) Swap(i, j int) { 172 | l[i], l[j] = l[j], l[i] 173 | } 174 | 175 | // LabelPair pairs a name with a value. 176 | type LabelPair struct { 177 | Name LabelName 178 | Value LabelValue 179 | } 180 | 181 | // LabelPairs is a sortable slice of LabelPair pointers. It implements 182 | // sort.Interface. 183 | type LabelPairs []*LabelPair 184 | 185 | func (l LabelPairs) Len() int { 186 | return len(l) 187 | } 188 | 189 | func (l LabelPairs) Less(i, j int) bool { 190 | switch { 191 | case l[i].Name > l[j].Name: 192 | return false 193 | case l[i].Name < l[j].Name: 194 | return true 195 | case l[i].Value > l[j].Value: 196 | return false 197 | case l[i].Value < l[j].Value: 198 | return true 199 | default: 200 | return false 201 | } 202 | } 203 | 204 | func (l LabelPairs) Swap(i, j int) { 205 | l[i], l[j] = l[j], l[i] 206 | } 207 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/common/model/model.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package model contains common data structures that are shared across 15 | // Prometheus components and libraries. 16 | package model 17 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/signature.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "sort" 18 | ) 19 | 20 | // SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is 21 | // used to separate label names, label values, and other strings from each other 22 | // when calculating their combined hash value (aka signature aka fingerprint). 23 | const SeparatorByte byte = 255 24 | 25 | var ( 26 | // cache the signature of an empty label set. 27 | emptyLabelSignature = hashNew() 28 | ) 29 | 30 | // LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a 31 | // given label set. (Collisions are possible but unlikely if the number of label 32 | // sets the function is applied to is small.) 33 | func LabelsToSignature(labels map[string]string) uint64 { 34 | if len(labels) == 0 { 35 | return emptyLabelSignature 36 | } 37 | 38 | labelNames := make([]string, 0, len(labels)) 39 | for labelName := range labels { 40 | labelNames = append(labelNames, labelName) 41 | } 42 | sort.Strings(labelNames) 43 | 44 | sum := hashNew() 45 | for _, labelName := range labelNames { 46 | sum = hashAdd(sum, labelName) 47 | sum = hashAddByte(sum, SeparatorByte) 48 | sum = hashAdd(sum, labels[labelName]) 49 | sum = hashAddByte(sum, SeparatorByte) 50 | } 51 | return sum 52 | } 53 | 54 | // labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as 55 | // parameter (rather than a label map) and returns a Fingerprint. 56 | func labelSetToFingerprint(ls LabelSet) Fingerprint { 57 | if len(ls) == 0 { 58 | return Fingerprint(emptyLabelSignature) 59 | } 60 | 61 | labelNames := make(LabelNames, 0, len(ls)) 62 | for labelName := range ls { 63 | labelNames = append(labelNames, labelName) 64 | } 65 | sort.Sort(labelNames) 66 | 67 | sum := hashNew() 68 | for _, labelName := range labelNames { 69 | sum = hashAdd(sum, string(labelName)) 70 | sum = hashAddByte(sum, SeparatorByte) 71 | sum = hashAdd(sum, string(ls[labelName])) 72 | sum = hashAddByte(sum, SeparatorByte) 73 | } 74 | return Fingerprint(sum) 75 | } 76 | 77 | // labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a 78 | // faster and less allocation-heavy hash function, which is more susceptible to 79 | // create hash collisions. Therefore, collision detection should be applied. 80 | func labelSetToFastFingerprint(ls LabelSet) Fingerprint { 81 | if len(ls) == 0 { 82 | return Fingerprint(emptyLabelSignature) 83 | } 84 | 85 | var result uint64 86 | for labelName, labelValue := range ls { 87 | sum := hashNew() 88 | sum = hashAdd(sum, string(labelName)) 89 | sum = hashAddByte(sum, SeparatorByte) 90 | sum = hashAdd(sum, string(labelValue)) 91 | result ^= sum 92 | } 93 | return Fingerprint(result) 94 | } 95 | 96 | // SignatureForLabels works like LabelsToSignature but takes a Metric as 97 | // parameter (rather than a label map) and only includes the labels with the 98 | // specified LabelNames into the signature calculation. The labels passed in 99 | // will be sorted by this function. 100 | func SignatureForLabels(m Metric, labels ...LabelName) uint64 { 101 | if len(labels) == 0 { 102 | return emptyLabelSignature 103 | } 104 | 105 | sort.Sort(LabelNames(labels)) 106 | 107 | sum := hashNew() 108 | for _, label := range labels { 109 | sum = hashAdd(sum, string(label)) 110 | sum = hashAddByte(sum, SeparatorByte) 111 | sum = hashAdd(sum, string(m[label])) 112 | sum = hashAddByte(sum, SeparatorByte) 113 | } 114 | return sum 115 | } 116 | 117 | // SignatureWithoutLabels works like LabelsToSignature but takes a Metric as 118 | // parameter (rather than a label map) and excludes the labels with any of the 119 | // specified LabelNames from the signature calculation. 120 | func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 { 121 | if len(m) == 0 { 122 | return emptyLabelSignature 123 | } 124 | 125 | labelNames := make(LabelNames, 0, len(m)) 126 | for labelName := range m { 127 | if _, exclude := labels[labelName]; !exclude { 128 | labelNames = append(labelNames, labelName) 129 | } 130 | } 131 | if len(labelNames) == 0 { 132 | return emptyLabelSignature 133 | } 134 | sort.Sort(labelNames) 135 | 136 | sum := hashNew() 137 | for _, labelName := range labelNames { 138 | sum = hashAdd(sum, string(labelName)) 139 | sum = hashAddByte(sum, SeparatorByte) 140 | sum = hashAdd(sum, string(m[labelName])) 141 | sum = hashAddByte(sum, SeparatorByte) 142 | } 143 | return sum 144 | } 145 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/silence.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | "regexp" 20 | "time" 21 | ) 22 | 23 | // Matcher describes a matches the value of a given label. 24 | type Matcher struct { 25 | Name LabelName `json:"name"` 26 | Value string `json:"value"` 27 | IsRegex bool `json:"isRegex"` 28 | } 29 | 30 | func (m *Matcher) UnmarshalJSON(b []byte) error { 31 | type plain Matcher 32 | if err := json.Unmarshal(b, (*plain)(m)); err != nil { 33 | return err 34 | } 35 | 36 | if len(m.Name) == 0 { 37 | return fmt.Errorf("label name in matcher must not be empty") 38 | } 39 | if m.IsRegex { 40 | if _, err := regexp.Compile(m.Value); err != nil { 41 | return err 42 | } 43 | } 44 | return nil 45 | } 46 | 47 | // Validate returns true iff all fields of the matcher have valid values. 48 | func (m *Matcher) Validate() error { 49 | if !m.Name.IsValid() { 50 | return fmt.Errorf("invalid name %q", m.Name) 51 | } 52 | if m.IsRegex { 53 | if _, err := regexp.Compile(m.Value); err != nil { 54 | return fmt.Errorf("invalid regular expression %q", m.Value) 55 | } 56 | } else if !LabelValue(m.Value).IsValid() || len(m.Value) == 0 { 57 | return fmt.Errorf("invalid value %q", m.Value) 58 | } 59 | return nil 60 | } 61 | 62 | // Silence defines the representation of a silence definiton 63 | // in the Prometheus eco-system. 64 | type Silence struct { 65 | ID uint64 `json:"id,omitempty"` 66 | 67 | Matchers []*Matcher `json:"matchers"` 68 | 69 | StartsAt time.Time `json:"startsAt"` 70 | EndsAt time.Time `json:"endsAt"` 71 | 72 | CreatedAt time.Time `json:"createdAt,omitempty"` 73 | CreatedBy string `json:"createdBy"` 74 | Comment string `json:"comment,omitempty"` 75 | } 76 | 77 | // Validate returns true iff all fields of the silence have valid values. 78 | func (s *Silence) Validate() error { 79 | if len(s.Matchers) == 0 { 80 | return fmt.Errorf("at least one matcher required") 81 | } 82 | for _, m := range s.Matchers { 83 | if err := m.Validate(); err != nil { 84 | return fmt.Errorf("invalid matcher: %s", err) 85 | } 86 | } 87 | if s.StartsAt.IsZero() { 88 | return fmt.Errorf("start time missing") 89 | } 90 | if s.EndsAt.IsZero() { 91 | return fmt.Errorf("end time missing") 92 | } 93 | if s.EndsAt.Before(s.StartsAt) { 94 | return fmt.Errorf("start time must be before end time") 95 | } 96 | if s.CreatedBy == "" { 97 | return fmt.Errorf("creator information missing") 98 | } 99 | if s.Comment == "" { 100 | return fmt.Errorf("comment missing") 101 | } 102 | if s.CreatedAt.IsZero() { 103 | return fmt.Errorf("creation timestamp missing") 104 | } 105 | return nil 106 | } 107 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/version/info.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package version 15 | 16 | import ( 17 | "bytes" 18 | "fmt" 19 | "runtime" 20 | "strings" 21 | "text/template" 22 | 23 | "github.com/prometheus/client_golang/prometheus" 24 | ) 25 | 26 | // Build information. Populated at build-time. 27 | var ( 28 | Version string 29 | Revision string 30 | Branch string 31 | BuildUser string 32 | BuildDate string 33 | GoVersion = runtime.Version() 34 | ) 35 | 36 | // NewCollector returns a collector which exports metrics about current version information. 37 | func NewCollector(program string) *prometheus.GaugeVec { 38 | buildInfo := prometheus.NewGaugeVec( 39 | prometheus.GaugeOpts{ 40 | Namespace: program, 41 | Name: "build_info", 42 | Help: fmt.Sprintf( 43 | "A metric with a constant '1' value labeled by version, revision, branch, and goversion from which %s was built.", 44 | program, 45 | ), 46 | }, 47 | []string{"version", "revision", "branch", "goversion"}, 48 | ) 49 | buildInfo.WithLabelValues(Version, Revision, Branch, GoVersion).Set(1) 50 | return buildInfo 51 | } 52 | 53 | // versionInfoTmpl contains the template used by Info. 54 | var versionInfoTmpl = ` 55 | {{.program}}, version {{.version}} (branch: {{.branch}}, revision: {{.revision}}) 56 | build user: {{.buildUser}} 57 | build date: {{.buildDate}} 58 | go version: {{.goVersion}} 59 | ` 60 | 61 | // Print returns version information. 62 | func Print(program string) string { 63 | m := map[string]string{ 64 | "program": program, 65 | "version": Version, 66 | "revision": Revision, 67 | "branch": Branch, 68 | "buildUser": BuildUser, 69 | "buildDate": BuildDate, 70 | "goVersion": GoVersion, 71 | } 72 | t := template.Must(template.New("version").Parse(versionInfoTmpl)) 73 | 74 | var buf bytes.Buffer 75 | if err := t.ExecuteTemplate(&buf, "version", m); err != nil { 76 | panic(err) 77 | } 78 | return strings.TrimSpace(buf.String()) 79 | } 80 | 81 | // Info returns version, branch and revision information. 82 | func Info() string { 83 | return fmt.Sprintf("(version=%s, branch=%s, revision=%s)", Version, Branch, Revision) 84 | } 85 | 86 | // BuildContext returns goVersion, buildUser and buildDate information. 87 | func BuildContext() string { 88 | return fmt.Sprintf("(go=%s, user=%s, date=%s)", GoVersion, BuildUser, BuildDate) 89 | } 90 | -------------------------------------------------------------------------------- /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/procfs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Prometheus uses GitHub to manage reviews of pull requests. 4 | 5 | * If you have a trivial fix or improvement, go ahead and create a pull 6 | request, addressing (with `@...`) one or more of the maintainers 7 | (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request. 8 | 9 | * If you plan to do something more involved, first discuss your ideas 10 | on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers). 11 | This will avoid unnecessary work and surely give you and us a good deal 12 | of inspiration. 13 | 14 | * Relevant coding style guidelines are the [Go Code Review 15 | Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) 16 | and the _Formatting and style_ section of Peter Bourgon's [Go: Best 17 | Practices for Production 18 | Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style). 19 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/Makefile: -------------------------------------------------------------------------------- 1 | ci: 2 | ! gofmt -l *.go | read nothing 3 | go vet 4 | go test -v ./... 5 | go get github.com/golang/lint/golint 6 | golint *.go 7 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/NOTICE: -------------------------------------------------------------------------------- 1 | procfs provides functions to retrieve system, kernel and process 2 | metrics from the pseudo-filesystem proc. 3 | 4 | Copyright 2014-2015 The Prometheus Authors 5 | 6 | This product includes software developed at 7 | SoundCloud Ltd. (http://soundcloud.com/). 8 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/README.md: -------------------------------------------------------------------------------- 1 | # procfs 2 | 3 | This procfs package provides functions to retrieve system, kernel and process 4 | metrics from the pseudo-filesystem proc. 5 | 6 | *WARNING*: This package is a work in progress. Its API may still break in 7 | backwards-incompatible ways without warnings. Use it at your own risk. 8 | 9 | [![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs) 10 | [![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs) 11 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Prometheus Team 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package procfs provides functions to retrieve system, kernel and process 15 | // metrics from the pseudo-filesystem proc. 16 | // 17 | // Example: 18 | // 19 | // package main 20 | // 21 | // import ( 22 | // "fmt" 23 | // "log" 24 | // 25 | // "github.com/prometheus/procfs" 26 | // ) 27 | // 28 | // func main() { 29 | // p, err := procfs.Self() 30 | // if err != nil { 31 | // log.Fatalf("could not get process: %s", err) 32 | // } 33 | // 34 | // stat, err := p.NewStat() 35 | // if err != nil { 36 | // log.Fatalf("could not get process stat: %s", err) 37 | // } 38 | // 39 | // fmt.Printf("command: %s\n", stat.Comm) 40 | // fmt.Printf("cpu time: %fs\n", stat.CPUTime()) 41 | // fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) 42 | // fmt.Printf("rss: %dB\n", stat.ResidentMemory()) 43 | // } 44 | // 45 | package procfs 46 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/fs.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path" 7 | ) 8 | 9 | // FS represents the pseudo-filesystem proc, which provides an interface to 10 | // kernel data structures. 11 | type FS string 12 | 13 | // DefaultMountPoint is the common mount point of the proc filesystem. 14 | const DefaultMountPoint = "/proc" 15 | 16 | // NewFS returns a new FS mounted under the given mountPoint. It will error 17 | // if the mount point can't be read. 18 | func NewFS(mountPoint string) (FS, error) { 19 | info, err := os.Stat(mountPoint) 20 | if err != nil { 21 | return "", fmt.Errorf("could not read %s: %s", mountPoint, err) 22 | } 23 | if !info.IsDir() { 24 | return "", fmt.Errorf("mount point %s is not a directory", mountPoint) 25 | } 26 | 27 | return FS(mountPoint), nil 28 | } 29 | 30 | // Path returns the path of the given subsystem relative to the procfs root. 31 | func (fs FS) Path(p ...string) string { 32 | return path.Join(append([]string{string(fs)}, p...)...) 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/mdstat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "regexp" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | var ( 12 | statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) 13 | buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) 14 | ) 15 | 16 | // MDStat holds info parsed from /proc/mdstat. 17 | type MDStat struct { 18 | // Name of the device. 19 | Name string 20 | // activity-state of the device. 21 | ActivityState string 22 | // Number of active disks. 23 | DisksActive int64 24 | // Total number of disks the device consists of. 25 | DisksTotal int64 26 | // Number of blocks the device holds. 27 | BlocksTotal int64 28 | // Number of blocks on the device that are in sync. 29 | BlocksSynced int64 30 | } 31 | 32 | // ParseMDStat parses an mdstat-file and returns a struct with the relevant infos. 33 | func (fs FS) ParseMDStat() (mdstates []MDStat, err error) { 34 | mdStatusFilePath := fs.Path("mdstat") 35 | content, err := ioutil.ReadFile(mdStatusFilePath) 36 | if err != nil { 37 | return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 38 | } 39 | 40 | mdStates := []MDStat{} 41 | lines := strings.Split(string(content), "\n") 42 | for i, l := range lines { 43 | if l == "" { 44 | continue 45 | } 46 | if l[0] == ' ' { 47 | continue 48 | } 49 | if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") { 50 | continue 51 | } 52 | 53 | mainLine := strings.Split(l, " ") 54 | if len(mainLine) < 3 { 55 | return mdStates, fmt.Errorf("error parsing mdline: %s", l) 56 | } 57 | mdName := mainLine[0] 58 | activityState := mainLine[2] 59 | 60 | if len(lines) <= i+3 { 61 | return mdStates, fmt.Errorf( 62 | "error parsing %s: too few lines for md device %s", 63 | mdStatusFilePath, 64 | mdName, 65 | ) 66 | } 67 | 68 | active, total, size, err := evalStatusline(lines[i+1]) 69 | if err != nil { 70 | return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 71 | } 72 | 73 | // j is the line number of the syncing-line. 74 | j := i + 2 75 | if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line 76 | j = i + 3 77 | } 78 | 79 | // If device is syncing at the moment, get the number of currently 80 | // synced bytes, otherwise that number equals the size of the device. 81 | syncedBlocks := size 82 | if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") { 83 | syncedBlocks, err = evalBuildline(lines[j]) 84 | if err != nil { 85 | return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 86 | } 87 | } 88 | 89 | mdStates = append(mdStates, MDStat{ 90 | Name: mdName, 91 | ActivityState: activityState, 92 | DisksActive: active, 93 | DisksTotal: total, 94 | BlocksTotal: size, 95 | BlocksSynced: syncedBlocks, 96 | }) 97 | } 98 | 99 | return mdStates, nil 100 | } 101 | 102 | func evalStatusline(statusline string) (active, total, size int64, err error) { 103 | matches := statuslineRE.FindStringSubmatch(statusline) 104 | if len(matches) != 4 { 105 | return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline) 106 | } 107 | 108 | size, err = strconv.ParseInt(matches[1], 10, 64) 109 | if err != nil { 110 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 111 | } 112 | 113 | total, err = strconv.ParseInt(matches[2], 10, 64) 114 | if err != nil { 115 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 116 | } 117 | 118 | active, err = strconv.ParseInt(matches[3], 10, 64) 119 | if err != nil { 120 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 121 | } 122 | 123 | return active, total, size, nil 124 | } 125 | 126 | func evalBuildline(buildline string) (syncedBlocks int64, err error) { 127 | matches := buildlineRE.FindStringSubmatch(buildline) 128 | if len(matches) != 2 { 129 | return 0, fmt.Errorf("unexpected buildline: %s", buildline) 130 | } 131 | 132 | syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) 133 | if err != nil { 134 | return 0, fmt.Errorf("%s in buildline: %s", err, buildline) 135 | } 136 | 137 | return syncedBlocks, nil 138 | } 139 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // Proc provides information about a running process. 12 | type Proc struct { 13 | // The process ID. 14 | PID int 15 | 16 | fs FS 17 | } 18 | 19 | // Procs represents a list of Proc structs. 20 | type Procs []Proc 21 | 22 | func (p Procs) Len() int { return len(p) } 23 | func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 24 | func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } 25 | 26 | // Self returns a process for the current process read via /proc/self. 27 | func Self() (Proc, error) { 28 | fs, err := NewFS(DefaultMountPoint) 29 | if err != nil { 30 | return Proc{}, err 31 | } 32 | return fs.Self() 33 | } 34 | 35 | // NewProc returns a process for the given pid under /proc. 36 | func NewProc(pid int) (Proc, error) { 37 | fs, err := NewFS(DefaultMountPoint) 38 | if err != nil { 39 | return Proc{}, err 40 | } 41 | return fs.NewProc(pid) 42 | } 43 | 44 | // AllProcs returns a list of all currently available processes under /proc. 45 | func AllProcs() (Procs, error) { 46 | fs, err := NewFS(DefaultMountPoint) 47 | if err != nil { 48 | return Procs{}, err 49 | } 50 | return fs.AllProcs() 51 | } 52 | 53 | // Self returns a process for the current process. 54 | func (fs FS) Self() (Proc, error) { 55 | p, err := os.Readlink(fs.Path("self")) 56 | if err != nil { 57 | return Proc{}, err 58 | } 59 | pid, err := strconv.Atoi(strings.Replace(p, string(fs), "", -1)) 60 | if err != nil { 61 | return Proc{}, err 62 | } 63 | return fs.NewProc(pid) 64 | } 65 | 66 | // NewProc returns a process for the given pid. 67 | func (fs FS) NewProc(pid int) (Proc, error) { 68 | if _, err := os.Stat(fs.Path(strconv.Itoa(pid))); err != nil { 69 | return Proc{}, err 70 | } 71 | return Proc{PID: pid, fs: fs}, nil 72 | } 73 | 74 | // AllProcs returns a list of all currently available processes. 75 | func (fs FS) AllProcs() (Procs, error) { 76 | d, err := os.Open(fs.Path()) 77 | if err != nil { 78 | return Procs{}, err 79 | } 80 | defer d.Close() 81 | 82 | names, err := d.Readdirnames(-1) 83 | if err != nil { 84 | return Procs{}, fmt.Errorf("could not read %s: %s", d.Name(), err) 85 | } 86 | 87 | p := Procs{} 88 | for _, n := range names { 89 | pid, err := strconv.ParseInt(n, 10, 64) 90 | if err != nil { 91 | continue 92 | } 93 | p = append(p, Proc{PID: int(pid), fs: fs}) 94 | } 95 | 96 | return p, nil 97 | } 98 | 99 | // CmdLine returns the command line of a process. 100 | func (p Proc) CmdLine() ([]string, error) { 101 | f, err := os.Open(p.path("cmdline")) 102 | if err != nil { 103 | return nil, err 104 | } 105 | defer f.Close() 106 | 107 | data, err := ioutil.ReadAll(f) 108 | if err != nil { 109 | return nil, err 110 | } 111 | 112 | if len(data) < 1 { 113 | return []string{}, nil 114 | } 115 | 116 | return strings.Split(string(data[:len(data)-1]), string(byte(0))), nil 117 | } 118 | 119 | // Comm returns the command name of a process. 120 | func (p Proc) Comm() (string, error) { 121 | f, err := os.Open(p.path("comm")) 122 | if err != nil { 123 | return "", err 124 | } 125 | defer f.Close() 126 | 127 | data, err := ioutil.ReadAll(f) 128 | if err != nil { 129 | return "", err 130 | } 131 | 132 | return strings.TrimSpace(string(data)), nil 133 | } 134 | 135 | // Executable returns the absolute path of the executable command of a process. 136 | func (p Proc) Executable() (string, error) { 137 | exe, err := os.Readlink(p.path("exe")) 138 | if os.IsNotExist(err) { 139 | return "", nil 140 | } 141 | 142 | return exe, err 143 | } 144 | 145 | // FileDescriptors returns the currently open file descriptors of a process. 146 | func (p Proc) FileDescriptors() ([]uintptr, error) { 147 | names, err := p.fileDescriptors() 148 | if err != nil { 149 | return nil, err 150 | } 151 | 152 | fds := make([]uintptr, len(names)) 153 | for i, n := range names { 154 | fd, err := strconv.ParseInt(n, 10, 32) 155 | if err != nil { 156 | return nil, fmt.Errorf("could not parse fd %s: %s", n, err) 157 | } 158 | fds[i] = uintptr(fd) 159 | } 160 | 161 | return fds, nil 162 | } 163 | 164 | // FileDescriptorTargets returns the targets of all file descriptors of a process. 165 | // If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string. 166 | func (p Proc) FileDescriptorTargets() ([]string, error) { 167 | names, err := p.fileDescriptors() 168 | if err != nil { 169 | return nil, err 170 | } 171 | 172 | targets := make([]string, len(names)) 173 | 174 | for i, name := range names { 175 | target, err := os.Readlink(p.path("fd", name)) 176 | if err == nil { 177 | targets[i] = target 178 | } 179 | } 180 | 181 | return targets, nil 182 | } 183 | 184 | // FileDescriptorsLen returns the number of currently open file descriptors of 185 | // a process. 186 | func (p Proc) FileDescriptorsLen() (int, error) { 187 | fds, err := p.fileDescriptors() 188 | if err != nil { 189 | return 0, err 190 | } 191 | 192 | return len(fds), nil 193 | } 194 | 195 | func (p Proc) fileDescriptors() ([]string, error) { 196 | d, err := os.Open(p.path("fd")) 197 | if err != nil { 198 | return nil, err 199 | } 200 | defer d.Close() 201 | 202 | names, err := d.Readdirnames(-1) 203 | if err != nil { 204 | return nil, fmt.Errorf("could not read %s: %s", d.Name(), err) 205 | } 206 | 207 | return names, nil 208 | } 209 | 210 | func (p Proc) path(pa ...string) string { 211 | return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) 212 | } 213 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_io.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | ) 8 | 9 | // ProcIO models the content of /proc//io. 10 | type ProcIO struct { 11 | // Chars read. 12 | RChar uint64 13 | // Chars written. 14 | WChar uint64 15 | // Read syscalls. 16 | SyscR uint64 17 | // Write syscalls. 18 | SyscW uint64 19 | // Bytes read. 20 | ReadBytes uint64 21 | // Bytes written. 22 | WriteBytes uint64 23 | // Bytes written, but taking into account truncation. See 24 | // Documentation/filesystems/proc.txt in the kernel sources for 25 | // detailed explanation. 26 | CancelledWriteBytes int64 27 | } 28 | 29 | // NewIO creates a new ProcIO instance from a given Proc instance. 30 | func (p Proc) NewIO() (ProcIO, error) { 31 | pio := ProcIO{} 32 | 33 | f, err := os.Open(p.path("io")) 34 | if err != nil { 35 | return pio, err 36 | } 37 | defer f.Close() 38 | 39 | data, err := ioutil.ReadAll(f) 40 | if err != nil { 41 | return pio, err 42 | } 43 | 44 | ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + 45 | "read_bytes: %d\nwrite_bytes: %d\n" + 46 | "cancelled_write_bytes: %d\n" 47 | 48 | _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, 49 | &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) 50 | if err != nil { 51 | return pio, err 52 | } 53 | 54 | return pio, nil 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_limits.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "strconv" 9 | ) 10 | 11 | // ProcLimits represents the soft limits for each of the process's resource 12 | // limits. For more information see getrlimit(2): 13 | // http://man7.org/linux/man-pages/man2/getrlimit.2.html. 14 | type ProcLimits struct { 15 | // CPU time limit in seconds. 16 | CPUTime int 17 | // Maximum size of files that the process may create. 18 | FileSize int 19 | // Maximum size of the process's data segment (initialized data, 20 | // uninitialized data, and heap). 21 | DataSize int 22 | // Maximum size of the process stack in bytes. 23 | StackSize int 24 | // Maximum size of a core file. 25 | CoreFileSize int 26 | // Limit of the process's resident set in pages. 27 | ResidentSet int 28 | // Maximum number of processes that can be created for the real user ID of 29 | // the calling process. 30 | Processes int 31 | // Value one greater than the maximum file descriptor number that can be 32 | // opened by this process. 33 | OpenFiles int 34 | // Maximum number of bytes of memory that may be locked into RAM. 35 | LockedMemory int 36 | // Maximum size of the process's virtual memory address space in bytes. 37 | AddressSpace int 38 | // Limit on the combined number of flock(2) locks and fcntl(2) leases that 39 | // this process may establish. 40 | FileLocks int 41 | // Limit of signals that may be queued for the real user ID of the calling 42 | // process. 43 | PendingSignals int 44 | // Limit on the number of bytes that can be allocated for POSIX message 45 | // queues for the real user ID of the calling process. 46 | MsqqueueSize int 47 | // Limit of the nice priority set using setpriority(2) or nice(2). 48 | NicePriority int 49 | // Limit of the real-time priority set using sched_setscheduler(2) or 50 | // sched_setparam(2). 51 | RealtimePriority int 52 | // Limit (in microseconds) on the amount of CPU time that a process 53 | // scheduled under a real-time scheduling policy may consume without making 54 | // a blocking system call. 55 | RealtimeTimeout int 56 | } 57 | 58 | const ( 59 | limitsFields = 3 60 | limitsUnlimited = "unlimited" 61 | ) 62 | 63 | var ( 64 | limitsDelimiter = regexp.MustCompile(" +") 65 | ) 66 | 67 | // NewLimits returns the current soft limits of the process. 68 | func (p Proc) NewLimits() (ProcLimits, error) { 69 | f, err := os.Open(p.path("limits")) 70 | if err != nil { 71 | return ProcLimits{}, err 72 | } 73 | defer f.Close() 74 | 75 | var ( 76 | l = ProcLimits{} 77 | s = bufio.NewScanner(f) 78 | ) 79 | for s.Scan() { 80 | fields := limitsDelimiter.Split(s.Text(), limitsFields) 81 | if len(fields) != limitsFields { 82 | return ProcLimits{}, fmt.Errorf( 83 | "couldn't parse %s line %s", f.Name(), s.Text()) 84 | } 85 | 86 | switch fields[0] { 87 | case "Max cpu time": 88 | l.CPUTime, err = parseInt(fields[1]) 89 | case "Max file size": 90 | l.FileSize, err = parseInt(fields[1]) 91 | case "Max data size": 92 | l.DataSize, err = parseInt(fields[1]) 93 | case "Max stack size": 94 | l.StackSize, err = parseInt(fields[1]) 95 | case "Max core file size": 96 | l.CoreFileSize, err = parseInt(fields[1]) 97 | case "Max resident set": 98 | l.ResidentSet, err = parseInt(fields[1]) 99 | case "Max processes": 100 | l.Processes, err = parseInt(fields[1]) 101 | case "Max open files": 102 | l.OpenFiles, err = parseInt(fields[1]) 103 | case "Max locked memory": 104 | l.LockedMemory, err = parseInt(fields[1]) 105 | case "Max address space": 106 | l.AddressSpace, err = parseInt(fields[1]) 107 | case "Max file locks": 108 | l.FileLocks, err = parseInt(fields[1]) 109 | case "Max pending signals": 110 | l.PendingSignals, err = parseInt(fields[1]) 111 | case "Max msgqueue size": 112 | l.MsqqueueSize, err = parseInt(fields[1]) 113 | case "Max nice priority": 114 | l.NicePriority, err = parseInt(fields[1]) 115 | case "Max realtime priority": 116 | l.RealtimePriority, err = parseInt(fields[1]) 117 | case "Max realtime timeout": 118 | l.RealtimeTimeout, err = parseInt(fields[1]) 119 | } 120 | if err != nil { 121 | return ProcLimits{}, err 122 | } 123 | } 124 | 125 | return l, s.Err() 126 | } 127 | 128 | func parseInt(s string) (int, error) { 129 | if s == limitsUnlimited { 130 | return -1, nil 131 | } 132 | i, err := strconv.ParseInt(s, 10, 32) 133 | if err != nil { 134 | return 0, fmt.Errorf("couldn't parse value %s: %s", s, err) 135 | } 136 | return int(i), nil 137 | } 138 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_stat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | ) 9 | 10 | // Originally, this USER_HZ value was dynamically retrieved via a sysconf call 11 | // which required cgo. However, that caused a lot of problems regarding 12 | // cross-compilation. Alternatives such as running a binary to determine the 13 | // value, or trying to derive it in some other way were all problematic. After 14 | // much research it was determined that USER_HZ is actually hardcoded to 100 on 15 | // all Go-supported platforms as of the time of this writing. This is why we 16 | // decided to hardcode it here as well. It is not impossible that there could 17 | // be systems with exceptions, but they should be very exotic edge cases, and 18 | // in that case, the worst outcome will be two misreported metrics. 19 | // 20 | // See also the following discussions: 21 | // 22 | // - https://github.com/prometheus/node_exporter/issues/52 23 | // - https://github.com/prometheus/procfs/pull/2 24 | // - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue 25 | const userHZ = 100 26 | 27 | // ProcStat provides status information about the process, 28 | // read from /proc/[pid]/stat. 29 | type ProcStat struct { 30 | // The process ID. 31 | PID int 32 | // The filename of the executable. 33 | Comm string 34 | // The process state. 35 | State string 36 | // The PID of the parent of this process. 37 | PPID int 38 | // The process group ID of the process. 39 | PGRP int 40 | // The session ID of the process. 41 | Session int 42 | // The controlling terminal of the process. 43 | TTY int 44 | // The ID of the foreground process group of the controlling terminal of 45 | // the process. 46 | TPGID int 47 | // The kernel flags word of the process. 48 | Flags uint 49 | // The number of minor faults the process has made which have not required 50 | // loading a memory page from disk. 51 | MinFlt uint 52 | // The number of minor faults that the process's waited-for children have 53 | // made. 54 | CMinFlt uint 55 | // The number of major faults the process has made which have required 56 | // loading a memory page from disk. 57 | MajFlt uint 58 | // The number of major faults that the process's waited-for children have 59 | // made. 60 | CMajFlt uint 61 | // Amount of time that this process has been scheduled in user mode, 62 | // measured in clock ticks. 63 | UTime uint 64 | // Amount of time that this process has been scheduled in kernel mode, 65 | // measured in clock ticks. 66 | STime uint 67 | // Amount of time that this process's waited-for children have been 68 | // scheduled in user mode, measured in clock ticks. 69 | CUTime uint 70 | // Amount of time that this process's waited-for children have been 71 | // scheduled in kernel mode, measured in clock ticks. 72 | CSTime uint 73 | // For processes running a real-time scheduling policy, this is the negated 74 | // scheduling priority, minus one. 75 | Priority int 76 | // The nice value, a value in the range 19 (low priority) to -20 (high 77 | // priority). 78 | Nice int 79 | // Number of threads in this process. 80 | NumThreads int 81 | // The time the process started after system boot, the value is expressed 82 | // in clock ticks. 83 | Starttime uint64 84 | // Virtual memory size in bytes. 85 | VSize int 86 | // Resident set size in pages. 87 | RSS int 88 | 89 | fs FS 90 | } 91 | 92 | // NewStat returns the current status information of the process. 93 | func (p Proc) NewStat() (ProcStat, error) { 94 | f, err := os.Open(p.path("stat")) 95 | if err != nil { 96 | return ProcStat{}, err 97 | } 98 | defer f.Close() 99 | 100 | data, err := ioutil.ReadAll(f) 101 | if err != nil { 102 | return ProcStat{}, err 103 | } 104 | 105 | var ( 106 | ignore int 107 | 108 | s = ProcStat{PID: p.PID, fs: p.fs} 109 | l = bytes.Index(data, []byte("(")) 110 | r = bytes.LastIndex(data, []byte(")")) 111 | ) 112 | 113 | if l < 0 || r < 0 { 114 | return ProcStat{}, fmt.Errorf( 115 | "unexpected format, couldn't extract comm: %s", 116 | data, 117 | ) 118 | } 119 | 120 | s.Comm = string(data[l+1 : r]) 121 | _, err = fmt.Fscan( 122 | bytes.NewBuffer(data[r+2:]), 123 | &s.State, 124 | &s.PPID, 125 | &s.PGRP, 126 | &s.Session, 127 | &s.TTY, 128 | &s.TPGID, 129 | &s.Flags, 130 | &s.MinFlt, 131 | &s.CMinFlt, 132 | &s.MajFlt, 133 | &s.CMajFlt, 134 | &s.UTime, 135 | &s.STime, 136 | &s.CUTime, 137 | &s.CSTime, 138 | &s.Priority, 139 | &s.Nice, 140 | &s.NumThreads, 141 | &ignore, 142 | &s.Starttime, 143 | &s.VSize, 144 | &s.RSS, 145 | ) 146 | if err != nil { 147 | return ProcStat{}, err 148 | } 149 | 150 | return s, nil 151 | } 152 | 153 | // VirtualMemory returns the virtual memory size in bytes. 154 | func (s ProcStat) VirtualMemory() int { 155 | return s.VSize 156 | } 157 | 158 | // ResidentMemory returns the resident memory size in bytes. 159 | func (s ProcStat) ResidentMemory() int { 160 | return s.RSS * os.Getpagesize() 161 | } 162 | 163 | // StartTime returns the unix timestamp of the process in seconds. 164 | func (s ProcStat) StartTime() (float64, error) { 165 | stat, err := s.fs.NewStat() 166 | if err != nil { 167 | return 0, err 168 | } 169 | return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil 170 | } 171 | 172 | // CPUTime returns the total CPU user and system time in seconds. 173 | func (s ProcStat) CPUTime() float64 { 174 | return float64(s.UTime+s.STime) / userHZ 175 | } 176 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/stat.go: -------------------------------------------------------------------------------- 1 | package procfs 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // Stat represents kernel/system statistics. 12 | type Stat struct { 13 | // Boot time in seconds since the Epoch. 14 | BootTime int64 15 | } 16 | 17 | // NewStat returns kernel/system statistics read from /proc/stat. 18 | func NewStat() (Stat, error) { 19 | fs, err := NewFS(DefaultMountPoint) 20 | if err != nil { 21 | return Stat{}, err 22 | } 23 | 24 | return fs.NewStat() 25 | } 26 | 27 | // NewStat returns an information about current kernel/system statistics. 28 | func (fs FS) NewStat() (Stat, error) { 29 | f, err := os.Open(fs.Path("stat")) 30 | if err != nil { 31 | return Stat{}, err 32 | } 33 | defer f.Close() 34 | 35 | s := bufio.NewScanner(f) 36 | for s.Scan() { 37 | line := s.Text() 38 | if !strings.HasPrefix(line, "btime") { 39 | continue 40 | } 41 | fields := strings.Fields(line) 42 | if len(fields) != 2 { 43 | return Stat{}, fmt.Errorf("couldn't parse %s line %s", f.Name(), line) 44 | } 45 | i, err := strconv.ParseInt(fields[1], 10, 32) 46 | if err != nil { 47 | return Stat{}, fmt.Errorf("couldn't parse %s: %s", fields[1], err) 48 | } 49 | return Stat{BootTime: i}, nil 50 | } 51 | if err := s.Err(); err != nil { 52 | return Stat{}, fmt.Errorf("couldn't parse %s: %s", f.Name(), err) 53 | } 54 | 55 | return Stat{}, fmt.Errorf("couldn't parse %s, missing btime", f.Name()) 56 | } 57 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Pull Requests 4 | 5 | 1. Everything (within reason) must have BDD-style tests. 6 | 2. Test driving (TDD) is very strongly encouraged. 7 | 3. Follow all existing patterns and conventions in the codebase. 8 | 4. Before issuing a pull-request, please rebase your branch against master. 9 | If you are okay with the maintainer rebasing your pull request, please say so. 10 | 5. After issuing your pull request, check [Travis CI](https://travis-ci.org/sclevine/agouti) to make sure that all tests still pass. 11 | 12 | ## Development Setup 13 | 14 | * Clone the repository. 15 | * Follow the instructions on agouti.org to install Ginkgo, Gomega, PhantomJS, ChromeDriver, and Selenium. 16 | * Run all of the tests using: `ginkgo -r .` 17 | * Start developing! 18 | 19 | ## Method Naming Conventions 20 | 21 | ### Agouti package (*Page, *Selection) 22 | 23 | These are largely context-dependent, but in general: 24 | * `Name` - Methods that do not have a corresponding getter/setter should not start with "Get", "Is", or "Set". 25 | * `GetName` - Non-boolean methods that get data and have a corresponding `SetName` method should start with "Get". 26 | * `IsName` - Boolean methods that get data and have a corresponding `SetName` method should start with "Is". 27 | * `SetName` - Methods that set data and have a corresponding `GetName` method should start with "Set". 28 | * `ReadName` - Methods that exhaust and return data should start with "Read". 29 | * `EnterName` - Methods that enter data without replacing it should start with "Enter". 30 | 31 | ### API package (*Session, *Element, *Window) 32 | 33 | All API method names should be as close to their endpoint names as possible. 34 | * `GetName` for all GET requests returning a non-boolean 35 | * `IsName` for all GET requests returning a boolean 36 | * `SetName` for POST requests that change the browser state 37 | * `NewNames` for POST requests that return and exhaust some browser state (ex. logs) 38 | * `Name` for POST requests that perform some action or retrieve data 39 | * `GetNameElement` for all POST requests returning an element 40 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Stephen Levine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/README.md: -------------------------------------------------------------------------------- 1 | Agouti 2 | ====== 3 | 4 | [![Build Status](https://api.travis-ci.org/sclevine/agouti.png?branch=master)](http://travis-ci.org/sclevine/agouti) 5 | [![GoDoc](https://godoc.org/github.com/sclevine/agouti?status.svg)](https://godoc.org/github.com/sclevine/agouti) 6 | 7 | [![#agouti IRC on Freenode](https://kiwiirc.com/buttons/chat.freenode.net/agouti.png)](https://kiwiirc.com/client/chat.freenode.net/#agouti) 8 | 9 | Agouti is a library for writing browser-based acceptance tests in Google Go. It provides [Gomega](https://github.com/onsi/gomega) matchers and plays nicely with [Ginkgo](https://github.com/onsi/ginkgo). See [agouti.org](http://agouti.org) and the [GoDoc](https://godoc.org/github.com/sclevine/agouti) for documentation. Have questions? Check out the [Agouti mailing list](https://groups.google.com/d/forum/agouti) or the #agouti IRC channel on Freenode. 10 | 11 | The [integration tests](https://github.com/sclevine/agouti/blob/master/internal/integration/) are a great place to see everything in action and get started quickly! 12 | 13 |

14 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/THANKS.md: -------------------------------------------------------------------------------- 1 | Many thanks to: 2 | 3 | * Zach Gershman and Pete Alfvin for helping me get this project off the ground. 4 | * Onsi Fakhouri for answering endless questions and contributing. 5 | * Abby Sturges for the wonderful logo on agouti.org! 6 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/agouti.go: -------------------------------------------------------------------------------- 1 | // Package agouti is a universal WebDriver client for Go. 2 | // It extends the agouti/api package to provide a feature-rich interface for 3 | // controlling a web browser. 4 | package agouti 5 | 6 | import ( 7 | "fmt" 8 | "path/filepath" 9 | "runtime" 10 | ) 11 | 12 | // PhantomJS returns an instance of a PhantomJS WebDriver. 13 | // 14 | // Provided Options will apply as default arguments for new pages. 15 | // New pages will accept invalid SSL certificates by default. This 16 | // may be disabled using the RejectInvalidSSL Option. 17 | // 18 | // The RejectInvalidSSL Option must be provided to the PhantomJS function 19 | // (and not the NewPage method) for this Option to take effect on any 20 | // PhantomJS page. 21 | func PhantomJS(options ...Option) *WebDriver { 22 | command := []string{"phantomjs", "--webdriver={{.Address}}"} 23 | defaultOptions := config{}.Merge(options) 24 | if !defaultOptions.RejectInvalidSSL { 25 | command = append(command, "--ignore-ssl-errors=true") 26 | } 27 | return NewWebDriver("http://{{.Address}}", command, options...) 28 | } 29 | 30 | // ChromeDriver returns an instance of a ChromeDriver WebDriver. 31 | // 32 | // Provided Options will apply as default arguments for new pages. 33 | // New pages will accept invalid SSL certificates by default. This 34 | // may be disabled using the RejectInvalidSSL Option. 35 | func ChromeDriver(options ...Option) *WebDriver { 36 | var binaryName string 37 | if runtime.GOOS == "windows" { 38 | binaryName = "chromedriver.exe" 39 | } else { 40 | binaryName = "chromedriver" 41 | } 42 | command := []string{binaryName, "--port={{.Port}}"} 43 | return NewWebDriver("http://{{.Address}}", command, options...) 44 | } 45 | 46 | // Selenium returns an instance of a Selenium WebDriver. 47 | // 48 | // Provided Options will apply as default arguments for new pages. 49 | // New pages will accept invalid SSL certificates by default. This 50 | // may be disabled using the RejectInvalidSSL Option. 51 | func Selenium(options ...Option) *WebDriver { 52 | command := []string{"selenium-server", "-port", "{{.Port}}"} 53 | return NewWebDriver("http://{{.Address}}/wd/hub", command, options...) 54 | } 55 | 56 | // Selendroid returns an instance of a Selendroid WebDriver. 57 | // 58 | // Provided Options will apply as default arguments for new pages. 59 | // New pages will accept invalid SSL certificates by default. This 60 | // may be disabled using the RejectInvalidSSL Option. 61 | // 62 | // The jarFile is a relative or absolute path to Selendroid JAR file. 63 | // Selendroid will return nil if an invalid path is provided. 64 | func Selendroid(jarFile string, options ...Option) *WebDriver { 65 | absJARPath, err := filepath.Abs(jarFile) 66 | if err != nil { 67 | return nil 68 | } 69 | 70 | command := []string{ 71 | "java", 72 | "-jar", absJARPath, 73 | "-port", "{{.Port}}", 74 | } 75 | options = append([]Option{Timeout(90), Browser("android")}, options...) 76 | return NewWebDriver("http://{{.Address}}/wd/hub", command, options...) 77 | } 78 | 79 | // SauceLabs opens a Sauce Labs session and returns a *Page. Does not support Sauce Connect. 80 | // 81 | // This method takes the same Options as NewPage. Passing the Desired Option will 82 | // completely override the provided name, platform, browser, and version. 83 | func SauceLabs(name, platform, browser, version, username, accessKey string, options ...Option) (*Page, error) { 84 | url := fmt.Sprintf("http://%s:%s@ondemand.saucelabs.com/wd/hub", username, accessKey) 85 | capabilities := NewCapabilities().Browser(name).Platform(platform).Version(version) 86 | capabilities["name"] = name 87 | return NewPage(url, append([]Option{Desired(capabilities)}, options...)...) 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/api.go: -------------------------------------------------------------------------------- 1 | // Package api provides a generic, low-level WebDriver API client for Go. 2 | // All methods map directly to endpoints of the WebDriver Wire Protocol: 3 | // https://code.google.com/p/selenium/wiki/JsonWireProtocol 4 | // 5 | // This package was previously internal to the agouti package. It currently 6 | // does not have a fixed API, but this will change in the near future 7 | // (with the addition of adequate documentation). 8 | package api 9 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/element.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "errors" 5 | "path" 6 | "strings" 7 | ) 8 | 9 | type Element struct { 10 | ID string 11 | Session *Session 12 | } 13 | 14 | func (e *Element) Send(method, endpoint string, body, result interface{}) error { 15 | return e.Session.Send(method, path.Join("element", e.ID, endpoint), body, result) 16 | } 17 | 18 | func (e *Element) GetID() string { 19 | return e.ID 20 | } 21 | 22 | func (e *Element) GetElement(selector Selector) (*Element, error) { 23 | var result struct{ Element string } 24 | 25 | if err := e.Send("POST", "element", selector, &result); err != nil { 26 | return nil, err 27 | } 28 | 29 | return &Element{result.Element, e.Session}, nil 30 | } 31 | 32 | func (e *Element) GetElements(selector Selector) ([]*Element, error) { 33 | var results []struct{ Element string } 34 | 35 | if err := e.Send("POST", "elements", selector, &results); err != nil { 36 | return nil, err 37 | } 38 | 39 | elements := []*Element{} 40 | for _, result := range results { 41 | elements = append(elements, &Element{result.Element, e.Session}) 42 | } 43 | 44 | return elements, nil 45 | } 46 | 47 | func (e *Element) GetText() (string, error) { 48 | var text string 49 | if err := e.Send("GET", "text", nil, &text); err != nil { 50 | return "", err 51 | } 52 | return text, nil 53 | } 54 | 55 | func (e *Element) GetName() (string, error) { 56 | var name string 57 | if err := e.Send("GET", "name", nil, &name); err != nil { 58 | return "", err 59 | } 60 | return name, nil 61 | } 62 | 63 | func (e *Element) GetAttribute(attribute string) (string, error) { 64 | var value string 65 | if err := e.Send("GET", path.Join("attribute", attribute), nil, &value); err != nil { 66 | return "", err 67 | } 68 | return value, nil 69 | } 70 | 71 | func (e *Element) GetCSS(property string) (string, error) { 72 | var value string 73 | if err := e.Send("GET", path.Join("css", property), nil, &value); err != nil { 74 | return "", err 75 | } 76 | return value, nil 77 | } 78 | 79 | func (e *Element) Click() error { 80 | return e.Send("POST", "click", nil, nil) 81 | } 82 | 83 | func (e *Element) Clear() error { 84 | return e.Send("POST", "clear", nil, nil) 85 | } 86 | 87 | func (e *Element) Value(text string) error { 88 | splitText := strings.Split(text, "") 89 | request := struct { 90 | Value []string `json:"value"` 91 | }{splitText} 92 | return e.Send("POST", "value", request, nil) 93 | } 94 | 95 | func (e *Element) IsSelected() (bool, error) { 96 | var selected bool 97 | if err := e.Send("GET", "selected", nil, &selected); err != nil { 98 | return false, err 99 | } 100 | return selected, nil 101 | } 102 | 103 | func (e *Element) IsDisplayed() (bool, error) { 104 | var displayed bool 105 | if err := e.Send("GET", "displayed", nil, &displayed); err != nil { 106 | return false, err 107 | } 108 | return displayed, nil 109 | } 110 | 111 | func (e *Element) IsEnabled() (bool, error) { 112 | var enabled bool 113 | if err := e.Send("GET", "enabled", nil, &enabled); err != nil { 114 | return false, err 115 | } 116 | return enabled, nil 117 | } 118 | 119 | func (e *Element) Submit() error { 120 | return e.Send("POST", "submit", nil, nil) 121 | } 122 | 123 | func (e *Element) IsEqualTo(other *Element) (bool, error) { 124 | if other == nil { 125 | return false, errors.New("nil element is invalid") 126 | } 127 | var equal bool 128 | if err := e.Send("GET", path.Join("equals", other.ID), nil, &equal); err != nil { 129 | return false, err 130 | } 131 | return equal, nil 132 | } 133 | 134 | func (e *Element) GetLocation() (x, y int, err error) { 135 | var location struct { 136 | X float64 `json:"x"` 137 | Y float64 `json:"y"` 138 | } 139 | if err := e.Send("GET", "location", nil, &location); err != nil { 140 | return 0, 0, err 141 | } 142 | return round(location.X), round(location.Y), nil 143 | } 144 | 145 | func round(number float64) int { 146 | return int(number + 0.5) 147 | } 148 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/internal/bus/client.go: -------------------------------------------------------------------------------- 1 | package bus 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "strings" 10 | ) 11 | 12 | type Client struct { 13 | SessionURL string 14 | HTTPClient *http.Client 15 | } 16 | 17 | func (c *Client) Send(method, endpoint string, body interface{}, result interface{}) error { 18 | requestBody, err := bodyToJSON(body) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | requestURL := strings.TrimSuffix(c.SessionURL+"/"+endpoint, "/") 24 | responseBody, err := c.makeRequest(requestURL, method, requestBody) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | if result != nil { 30 | bodyValue := struct{ Value interface{} }{result} 31 | if err := json.Unmarshal(responseBody, &bodyValue); err != nil { 32 | return fmt.Errorf("unexpected response: %s", responseBody) 33 | } 34 | } 35 | 36 | return nil 37 | } 38 | 39 | func bodyToJSON(body interface{}) ([]byte, error) { 40 | if body == nil { 41 | return nil, nil 42 | } 43 | bodyJSON, err := json.Marshal(body) 44 | if err != nil { 45 | return nil, fmt.Errorf("invalid request body: %s", err) 46 | } 47 | return bodyJSON, nil 48 | } 49 | 50 | func (c *Client) makeRequest(url, method string, body []byte) ([]byte, error) { 51 | request, err := http.NewRequest(method, url, bytes.NewReader(body)) 52 | if err != nil { 53 | return nil, fmt.Errorf("invalid request: %s", err) 54 | } 55 | 56 | if body != nil { 57 | request.Header.Add("Content-Type", "application/json") 58 | } 59 | 60 | response, err := c.HTTPClient.Do(request) 61 | if err != nil { 62 | return nil, fmt.Errorf("request failed: %s", err) 63 | } 64 | 65 | responseBody, err := ioutil.ReadAll(response.Body) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | if response.StatusCode < 200 || response.StatusCode > 299 { 71 | return nil, parseResponseError(responseBody) 72 | } 73 | 74 | return responseBody, nil 75 | } 76 | 77 | func parseResponseError(body []byte) error { 78 | var errBody struct{ Value struct{ Message string } } 79 | if err := json.Unmarshal(body, &errBody); err != nil { 80 | return fmt.Errorf("request unsuccessful: %s", body) 81 | } 82 | 83 | var errMessage struct{ ErrorMessage string } 84 | if err := json.Unmarshal([]byte(errBody.Value.Message), &errMessage); err != nil { 85 | return fmt.Errorf("request unsuccessful: %s", errBody.Value.Message) 86 | } 87 | 88 | return fmt.Errorf("request unsuccessful: %s", errMessage.ErrorMessage) 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/internal/bus/connect.go: -------------------------------------------------------------------------------- 1 | package bus 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "net/http" 11 | ) 12 | 13 | func Connect(url string, capabilities map[string]interface{}, httpClient *http.Client) (*Client, error) { 14 | requestBody, err := capabilitiesToJSON(capabilities) 15 | if err != nil { 16 | return nil, err 17 | } 18 | 19 | if httpClient == nil { 20 | httpClient = http.DefaultClient 21 | } 22 | 23 | sessionID, err := openSession(url, requestBody, httpClient) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | sessionURL := fmt.Sprintf("%s/session/%s", url, sessionID) 29 | return &Client{sessionURL, httpClient}, nil 30 | } 31 | 32 | func capabilitiesToJSON(capabilities map[string]interface{}) (io.Reader, error) { 33 | if capabilities == nil { 34 | capabilities = map[string]interface{}{} 35 | } 36 | desiredCapabilities := struct { 37 | DesiredCapabilities map[string]interface{} `json:"desiredCapabilities"` 38 | }{capabilities} 39 | 40 | capabiltiesJSON, err := json.Marshal(desiredCapabilities) 41 | if err != nil { 42 | return nil, err 43 | } 44 | return bytes.NewReader(capabiltiesJSON), err 45 | } 46 | 47 | func openSession(url string, body io.Reader, httpClient *http.Client) (sessionID string, err error) { 48 | request, err := http.NewRequest("POST", fmt.Sprintf("%s/session", url), body) 49 | if err != nil { 50 | return "", err 51 | } 52 | 53 | request.Header.Add("Content-Type", "application/json") 54 | 55 | response, err := httpClient.Do(request) 56 | if err != nil { 57 | return "", err 58 | } 59 | 60 | var sessionResponse struct{ SessionID string } 61 | responseBody, err := ioutil.ReadAll(response.Body) 62 | if err != nil { 63 | return "", err 64 | } 65 | 66 | if err := json.Unmarshal(responseBody, &sessionResponse); err != nil { 67 | return "", err 68 | } 69 | 70 | if sessionResponse.SessionID == "" { 71 | return "", errors.New("failed to retrieve a session ID") 72 | } 73 | 74 | return sessionResponse.SessionID, nil 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/internal/service/build.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "os/exec" 7 | "text/template" 8 | ) 9 | 10 | func buildURL(url string, address addressInfo) (string, error) { 11 | urlTemplate, err := template.New("URL").Parse(url) 12 | if err != nil { 13 | return "", err 14 | } 15 | urlBuffer := &bytes.Buffer{} 16 | if err := urlTemplate.Execute(urlBuffer, address); err != nil { 17 | return "", err 18 | } 19 | return urlBuffer.String(), nil 20 | } 21 | 22 | func buildCommand(arguments []string, address addressInfo) (*exec.Cmd, error) { 23 | if len(arguments) == 0 { 24 | return nil, errors.New("empty command") 25 | } 26 | 27 | command := []string{} 28 | for _, argument := range arguments { 29 | argTemplate, err := template.New("command").Parse(argument) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | argBuffer := &bytes.Buffer{} 35 | if err := argTemplate.Execute(argBuffer, address); err != nil { 36 | return nil, err 37 | } 38 | command = append(command, argBuffer.String()) 39 | } 40 | 41 | return exec.Command(command[0], command[1:]...), nil 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/internal/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "os" 9 | "os/exec" 10 | "runtime" 11 | "strings" 12 | "syscall" 13 | "time" 14 | ) 15 | 16 | type Service struct { 17 | URLTemplate string 18 | CmdTemplate []string 19 | url string 20 | command *exec.Cmd 21 | } 22 | 23 | type addressInfo struct { 24 | Address string 25 | Host string 26 | Port string 27 | } 28 | 29 | func (s *Service) URL() string { 30 | return s.url 31 | } 32 | 33 | func (s *Service) Start(debug bool) error { 34 | if s.command != nil { 35 | return errors.New("already running") 36 | } 37 | 38 | address, err := freeAddress() 39 | if err != nil { 40 | return fmt.Errorf("failed to locate a free port: %s", err) 41 | } 42 | 43 | url, err := buildURL(s.URLTemplate, address) 44 | if err != nil { 45 | return fmt.Errorf("failed to parse URL: %s", err) 46 | } 47 | 48 | command, err := buildCommand(s.CmdTemplate, address) 49 | if err != nil { 50 | return fmt.Errorf("failed to parse command: %s", err) 51 | } 52 | 53 | if debug { 54 | command.Stdout = os.Stdout 55 | command.Stderr = os.Stderr 56 | } 57 | 58 | if err := command.Start(); err != nil { 59 | err = fmt.Errorf("failed to run command: %s", err) 60 | if debug { 61 | os.Stderr.WriteString("ERROR: " + err.Error() + "\n") 62 | } 63 | return err 64 | } 65 | 66 | s.command = command 67 | s.url = url 68 | 69 | return nil 70 | } 71 | 72 | func (s *Service) Stop() error { 73 | if s.command == nil { 74 | return errors.New("already stopped") 75 | } 76 | 77 | var err error 78 | if runtime.GOOS == "windows" { 79 | err = s.command.Process.Kill() 80 | } else { 81 | err = s.command.Process.Signal(syscall.SIGTERM) 82 | } 83 | if err != nil { 84 | return fmt.Errorf("failed to stop command: %s", err) 85 | } 86 | 87 | s.command.Wait() 88 | s.command = nil 89 | s.url = "" 90 | 91 | return nil 92 | } 93 | 94 | func freeAddress() (addressInfo, error) { 95 | listener, err := net.Listen("tcp", "127.0.0.1:0") 96 | if err != nil { 97 | return addressInfo{}, err 98 | } 99 | defer listener.Close() 100 | 101 | address := listener.Addr().String() 102 | addressParts := strings.SplitN(address, ":", 2) 103 | return addressInfo{address, addressParts[0], addressParts[1]}, nil 104 | } 105 | 106 | func (s *Service) WaitForBoot(timeout time.Duration) error { 107 | timeoutChan := time.After(timeout) 108 | failedChan := make(chan struct{}, 1) 109 | startedChan := make(chan struct{}) 110 | 111 | go func() { 112 | up := s.checkStatus() 113 | for !up { 114 | select { 115 | case <-failedChan: 116 | return 117 | default: 118 | time.Sleep(500 * time.Millisecond) 119 | up = s.checkStatus() 120 | } 121 | } 122 | startedChan <- struct{}{} 123 | }() 124 | 125 | select { 126 | case <-timeoutChan: 127 | failedChan <- struct{}{} 128 | return errors.New("failed to start before timeout") 129 | case <-startedChan: 130 | return nil 131 | } 132 | } 133 | 134 | func (s *Service) checkStatus() bool { 135 | client := &http.Client{} 136 | request, _ := http.NewRequest("GET", fmt.Sprintf("%s/status", s.url), nil) 137 | response, err := client.Do(request) 138 | if err == nil && response.StatusCode == 200 { 139 | return true 140 | } 141 | return false 142 | } 143 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/offset.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | type Offset interface { 4 | x() (x int, present bool) 5 | y() (y int, present bool) 6 | position() (x int, y int) 7 | } 8 | 9 | type XYOffset struct { 10 | X int 11 | Y int 12 | } 13 | 14 | func (o XYOffset) x() (x int, present bool) { 15 | return o.X, true 16 | } 17 | 18 | func (o XYOffset) y() (y int, present bool) { 19 | return o.Y, true 20 | } 21 | 22 | func (o XYOffset) position() (x int, y int) { 23 | return o.X, o.Y 24 | } 25 | 26 | type XOffset int 27 | 28 | func (o XOffset) x() (x int, present bool) { 29 | return int(o), true 30 | } 31 | 32 | func (XOffset) y() (y int, present bool) { 33 | return 0, false 34 | } 35 | 36 | func (o XOffset) position() (x int, y int) { 37 | return int(o), 0 38 | } 39 | 40 | type YOffset int 41 | 42 | func (YOffset) x() (x int, present bool) { 43 | return 0, false 44 | } 45 | 46 | func (o YOffset) y() (y int, present bool) { 47 | return int(o), true 48 | } 49 | 50 | func (o YOffset) position() (x int, y int) { 51 | return 0, int(o) 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/speed.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "math" 4 | 5 | type Speed interface { 6 | vector() (x, y int) 7 | scalar() uint 8 | } 9 | 10 | type VectorSpeed struct { 11 | X int 12 | Y int 13 | } 14 | 15 | func (s VectorSpeed) vector() (x, y int) { 16 | return s.X, s.Y 17 | } 18 | 19 | func (s VectorSpeed) scalar() uint { 20 | return uint(math.Hypot(float64(s.X), float64(s.Y))) 21 | } 22 | 23 | type ScalarSpeed uint 24 | 25 | func (s ScalarSpeed) vector() (x, y int) { 26 | scalar := int(float64(s) / math.Sqrt2) 27 | return scalar, scalar 28 | } 29 | 30 | func (s ScalarSpeed) scalar() uint { 31 | return uint(s) 32 | } 33 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/types.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | type Log struct { 4 | Message string 5 | Level string 6 | Timestamp int64 7 | } 8 | 9 | // A Cookie defines a web cookie 10 | type Cookie struct { 11 | // Name is the name of the cookie (required) 12 | Name string `json:"name"` 13 | 14 | // Value is the value of the cookie (required) 15 | Value string `json:"value"` 16 | 17 | // Path is the path of the cookie (default: "/") 18 | Path string `json:"path,omitempty"` 19 | 20 | // Domain is the domain of the cookie (default: current page domain) 21 | Domain string `json:"domain,omitempty"` 22 | 23 | // Secure is set to true for secure cookies (default: false) 24 | Secure bool `json:"secure,omitempty"` 25 | 26 | // HTTPOnly is set to true for HTTP-Only cookies (default: false) 27 | HTTPOnly bool `json:"httpOnly,omitempty"` 28 | 29 | // Expiry is the time when the cookie expires 30 | Expiry int64 `json:"expiry,omitempty"` 31 | } 32 | 33 | type Selector struct { 34 | Using string `json:"using"` 35 | Value string `json:"value"` 36 | } 37 | 38 | type Button int 39 | 40 | const ( 41 | LeftButton Button = iota 42 | MiddleButton 43 | RightButton 44 | ) 45 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/webdriver.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/sclevine/agouti/api/internal/service" 9 | ) 10 | 11 | type WebDriver struct { 12 | Timeout time.Duration 13 | Debug bool 14 | HTTPClient *http.Client 15 | service driverService 16 | sessions []*Session 17 | } 18 | 19 | type driverService interface { 20 | URL() string 21 | Start(debug bool) error 22 | Stop() error 23 | WaitForBoot(timeout time.Duration) error 24 | } 25 | 26 | func NewWebDriver(url string, command []string) *WebDriver { 27 | driverService := &service.Service{ 28 | URLTemplate: url, 29 | CmdTemplate: command, 30 | } 31 | 32 | return &WebDriver{ 33 | Timeout: 10 * time.Second, 34 | service: driverService, 35 | } 36 | } 37 | 38 | func (w *WebDriver) URL() string { 39 | return w.service.URL() 40 | } 41 | 42 | func (w *WebDriver) Open(desiredCapabilites map[string]interface{}) (*Session, error) { 43 | url := w.service.URL() 44 | if url == "" { 45 | return nil, fmt.Errorf("service not started") 46 | } 47 | 48 | session, err := OpenWithClient(url, desiredCapabilites, w.HTTPClient) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | w.sessions = append(w.sessions, session) 54 | return session, nil 55 | } 56 | 57 | func (w *WebDriver) Start() error { 58 | if err := w.service.Start(w.Debug); err != nil { 59 | return fmt.Errorf("failed to start service: %s", err) 60 | } 61 | 62 | if err := w.service.WaitForBoot(w.Timeout); err != nil { 63 | w.service.Stop() 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | 70 | func (w *WebDriver) Stop() error { 71 | for _, session := range w.sessions { 72 | session.Delete() 73 | } 74 | 75 | if err := w.service.Stop(); err != nil { 76 | return fmt.Errorf("failed to stop service: %s", err) 77 | } 78 | 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/api/window.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "path" 4 | 5 | type Window struct { 6 | ID string 7 | Session *Session 8 | } 9 | 10 | func (w *Window) Send(method, endpoint string, body, result interface{}) error { 11 | return w.Session.Send(method, path.Join("window", w.ID, endpoint), body, result) 12 | } 13 | 14 | func (w *Window) SetSize(width, height int) error { 15 | request := struct { 16 | Width int `json:"width"` 17 | Height int `json:"height"` 18 | }{width, height} 19 | 20 | return w.Send("POST", "size", request, nil) 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/capabilities.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import "encoding/json" 4 | 5 | // A Capabilities instance defines the desired capabilities the WebDriver 6 | // should use to configure a Page. 7 | // 8 | // For example, to open Firefox with JavaScript disabled: 9 | // capabilities := agouti.NewCapabilities().Browser("firefox").Without("javascriptEnabled") 10 | // driver.NewPage(agouti.Desired(capabilities)) 11 | // See: https://code.google.com/p/selenium/wiki/DesiredCapabilities 12 | // 13 | // All methods called on this instance will modify the original instance. 14 | type Capabilities map[string]interface{} 15 | 16 | // NewCapabilities returns a Capabilities instance with any provided features enabled. 17 | func NewCapabilities(features ...string) Capabilities { 18 | c := Capabilities{} 19 | for _, feature := range features { 20 | c.With(feature) 21 | } 22 | return c 23 | } 24 | 25 | // Browser sets the desired browser name. 26 | // Possible values: 27 | // {android|chrome|firefox|htmlunit|internet explorer|iPhone|iPad|opera|safari} 28 | func (c Capabilities) Browser(name string) Capabilities { 29 | c["browserName"] = name 30 | return c 31 | } 32 | 33 | // Version sets the desired browser version (ex. "3.6"). 34 | func (c Capabilities) Version(version string) Capabilities { 35 | c["version"] = version 36 | return c 37 | } 38 | 39 | // Platform sets the desired browser platform. 40 | // Possible values: 41 | // {WINDOWS|XP|VISTA|MAC|LINUX|UNIX|ANDROID|ANY}. 42 | func (c Capabilities) Platform(platform string) Capabilities { 43 | c["platform"] = platform 44 | return c 45 | } 46 | 47 | // With enables the provided feature (ex. "trustAllSSLCertificates"). 48 | func (c Capabilities) With(feature string) Capabilities { 49 | c[feature] = true 50 | return c 51 | } 52 | 53 | // Without disables the provided feature (ex. "javascriptEnabled"). 54 | func (c Capabilities) Without(feature string) Capabilities { 55 | c[feature] = false 56 | return c 57 | } 58 | 59 | // JSON returns a JSON string representing the desired capabilities. 60 | func (c Capabilities) JSON() (string, error) { 61 | capabilitiesJSON, err := json.Marshal(c) 62 | return string(capabilitiesJSON), err 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/internal/element/repository.go: -------------------------------------------------------------------------------- 1 | package element 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/sclevine/agouti/api" 8 | "github.com/sclevine/agouti/internal/target" 9 | ) 10 | 11 | type Repository struct { 12 | Client Client 13 | Selectors target.Selectors 14 | } 15 | 16 | type Client interface { 17 | GetElement(selector api.Selector) (*api.Element, error) 18 | GetElements(selector api.Selector) ([]*api.Element, error) 19 | } 20 | 21 | type Element interface { 22 | Client 23 | GetID() string 24 | GetText() (string, error) 25 | GetName() (string, error) 26 | GetAttribute(attribute string) (string, error) 27 | GetCSS(property string) (string, error) 28 | IsSelected() (bool, error) 29 | IsDisplayed() (bool, error) 30 | IsEnabled() (bool, error) 31 | IsEqualTo(other *api.Element) (bool, error) 32 | Click() error 33 | Clear() error 34 | Value(text string) error 35 | Submit() error 36 | GetLocation() (x, y int, err error) 37 | } 38 | 39 | func (e *Repository) GetAtLeastOne() ([]Element, error) { 40 | elements, err := e.Get() 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | if len(elements) == 0 { 46 | return nil, errors.New("no elements found") 47 | } 48 | 49 | return elements, nil 50 | } 51 | 52 | func (e *Repository) GetExactlyOne() (Element, error) { 53 | elements, err := e.GetAtLeastOne() 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | if len(elements) > 1 { 59 | return nil, fmt.Errorf("method does not support multiple elements (%d)", len(elements)) 60 | } 61 | 62 | return elements[0], nil 63 | } 64 | 65 | func (e *Repository) Get() ([]Element, error) { 66 | if len(e.Selectors) == 0 { 67 | return nil, errors.New("empty selection") 68 | } 69 | 70 | lastElements, err := retrieveElements(e.Client, e.Selectors[0]) 71 | if err != nil { 72 | return nil, err 73 | } 74 | 75 | for _, selector := range e.Selectors[1:] { 76 | elements := []Element{} 77 | for _, element := range lastElements { 78 | subElements, err := retrieveElements(element, selector) 79 | if err != nil { 80 | return nil, err 81 | } 82 | 83 | elements = append(elements, subElements...) 84 | } 85 | lastElements = elements 86 | } 87 | return lastElements, nil 88 | } 89 | 90 | func retrieveElements(client Client, selector target.Selector) ([]Element, error) { 91 | if selector.Single { 92 | elements, err := client.GetElements(selector.API()) 93 | if err != nil { 94 | return nil, err 95 | } 96 | 97 | if len(elements) == 0 { 98 | return nil, errors.New("element not found") 99 | } else if len(elements) > 1 { 100 | return nil, errors.New("ambiguous find") 101 | } 102 | 103 | return []Element{Element(elements[0])}, nil 104 | } 105 | 106 | if selector.Indexed && selector.Index > 0 { 107 | elements, err := client.GetElements(selector.API()) 108 | if err != nil { 109 | return nil, err 110 | } 111 | 112 | if selector.Index >= len(elements) { 113 | return nil, errors.New("element index out of range") 114 | } 115 | 116 | return []Element{Element(elements[selector.Index])}, nil 117 | } 118 | 119 | if selector.Indexed && selector.Index == 0 { 120 | element, err := client.GetElement(selector.API()) 121 | if err != nil { 122 | return nil, err 123 | } 124 | return []Element{Element(element)}, nil 125 | } 126 | 127 | elements, err := client.GetElements(selector.API()) 128 | if err != nil { 129 | return nil, err 130 | } 131 | 132 | newElements := []Element{} 133 | for _, element := range elements { 134 | newElements = append(newElements, element) 135 | } 136 | 137 | return newElements, nil 138 | } 139 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/internal/target/selector.go: -------------------------------------------------------------------------------- 1 | package target 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sclevine/agouti/api" 7 | ) 8 | 9 | type Type string 10 | 11 | const ( 12 | CSS Type = "CSS: %s" 13 | XPath Type = "XPath: %s" 14 | Link Type = `Link: "%s"` 15 | Label Type = `Label: "%s"` 16 | Button Type = `Button: "%s"` 17 | Name Type = `Name: "%s"` 18 | A11yID Type = "Accessibility ID: %s" 19 | AndroidAut Type = "Android UIAut.: %s" 20 | IOSAut Type = "iOS UIAut.: %s" 21 | Class Type = "Class: %s" 22 | ID Type = "ID: %s" 23 | 24 | labelXPath = `//input[@id=(//label[normalize-space()="%s"]/@for)] | //label[normalize-space()="%[1]s"]/input` 25 | buttonXPath = `//input[@type="submit" or @type="button"][normalize-space(@value)="%s"] | //button[normalize-space()="%[1]s"]` 26 | ) 27 | 28 | func (t Type) format(value string) string { 29 | return fmt.Sprintf(string(t), value) 30 | } 31 | 32 | type Selector struct { 33 | Type Type 34 | Value string 35 | Index int 36 | Indexed bool 37 | Single bool 38 | } 39 | 40 | func (s Selector) String() string { 41 | var suffix string 42 | 43 | if s.Single { 44 | suffix = " [single]" 45 | } else if s.Indexed { 46 | suffix = fmt.Sprintf(" [%d]", s.Index) 47 | } 48 | 49 | return s.Type.format(s.Value) + suffix 50 | } 51 | 52 | func (s Selector) API() api.Selector { 53 | return api.Selector{Using: s.apiType(), Value: s.value()} 54 | } 55 | 56 | func (s Selector) apiType() string { 57 | switch s.Type { 58 | case CSS: 59 | return "css selector" 60 | case Class: 61 | return "class name" 62 | case ID: 63 | return "id" 64 | case Link: 65 | return "link text" 66 | case Name: 67 | return "name" 68 | case A11yID: 69 | return "accessibility id" 70 | case AndroidAut: 71 | return "-android uiautomator" 72 | case IOSAut: 73 | return "-ios uiautomation" 74 | } 75 | return "xpath" 76 | } 77 | 78 | func (s Selector) value() string { 79 | switch s.Type { 80 | case Label: 81 | return fmt.Sprintf(labelXPath, s.Value) 82 | case Button: 83 | return fmt.Sprintf(buttonXPath, s.Value) 84 | } 85 | return s.Value 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/internal/target/selectors.go: -------------------------------------------------------------------------------- 1 | package target 2 | 3 | import "strings" 4 | 5 | type Selectors []Selector 6 | 7 | func (s Selectors) canMergeType(selectorType Type) bool { 8 | if len(s) == 0 { 9 | return false 10 | } 11 | last := s[len(s)-1] 12 | bothCSS := selectorType == CSS && last.Type == CSS 13 | return bothCSS && !last.Indexed && !last.Single 14 | } 15 | 16 | func (s Selectors) Append(selectorType Type, value string) Selectors { 17 | selector := Selector{Type: selectorType, Value: value} 18 | 19 | if s.canMergeType(selectorType) { 20 | lastIndex := len(s) - 1 21 | selector.Value = s[lastIndex].Value + " " + selector.Value 22 | return s[:lastIndex].append(selector) 23 | } 24 | return s.append(selector) 25 | } 26 | 27 | func (s Selectors) Single() Selectors { 28 | lastIndex := len(s) - 1 29 | if lastIndex < 0 { 30 | return nil 31 | } 32 | 33 | selector := s[lastIndex] 34 | selector.Single = true 35 | selector.Indexed = false 36 | return s[:lastIndex].append(selector) 37 | } 38 | 39 | func (s Selectors) At(index int) Selectors { 40 | lastIndex := len(s) - 1 41 | if lastIndex < 0 { 42 | return nil 43 | } 44 | 45 | selector := s[lastIndex] 46 | selector.Single = false 47 | selector.Indexed = true 48 | selector.Index = index 49 | return s[:lastIndex].append(selector) 50 | } 51 | 52 | func (s Selectors) String() string { 53 | var tags []string 54 | 55 | for _, selector := range s { 56 | tags = append(tags, selector.String()) 57 | } 58 | 59 | return strings.Join(tags, " | ") 60 | } 61 | 62 | func (s Selectors) append(selector Selector) Selectors { 63 | selectorsCopy := append(Selectors(nil), s...) 64 | return append(selectorsCopy, selector) 65 | } 66 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/multiselection.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import "github.com/sclevine/agouti/internal/target" 4 | 5 | // A MultiSelection is a Selection that may be indexed using the At() method. 6 | // All Selection methods are available on a MultiSelection. 7 | // 8 | // A Selection returned by At() may still refer to multiple elements if any 9 | // parent of the MultiSelection refers to multiple elements. 10 | // 11 | // Examples: 12 | // selection.All("section").All("form").At(1).Submit() 13 | // Submits the second form in each section. 14 | // selection.All("div").Find("h1").Click() 15 | // Clicks one h1 in each div, failing if any div does not contain exactly one h1. 16 | type MultiSelection struct { 17 | Selection 18 | } 19 | 20 | func newMultiSelection(session apiSession, selectors target.Selectors) *MultiSelection { 21 | return &MultiSelection{*newSelection(session, selectors)} 22 | } 23 | 24 | // At finds an element at the provided index. It only applies to the immediate selection, 25 | // meaning that the returned selection may still refer to multiple elements if any parent 26 | // of the immediate selection is also a *MultiSelection. 27 | func (s *MultiSelection) At(index int) *Selection { 28 | return newSelection(s.session, s.selectors.At(index)) 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/options.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | type config struct { 9 | Timeout time.Duration 10 | DesiredCapabilities Capabilities 11 | BrowserName string 12 | RejectInvalidSSL bool 13 | Debug bool 14 | HTTPClient *http.Client 15 | } 16 | 17 | // An Option specifies configuration for a new WebDriver or Page. 18 | type Option func(*config) 19 | 20 | // Browser provides an Option for specifying a browser. 21 | func Browser(name string) Option { 22 | return func(c *config) { 23 | c.BrowserName = name 24 | } 25 | } 26 | 27 | // Timeout provides an Option for specifying a timeout in seconds. 28 | func Timeout(seconds int) Option { 29 | return func(c *config) { 30 | c.Timeout = time.Duration(seconds) * time.Second 31 | } 32 | } 33 | 34 | // Desired provides an Option for specifying desired WebDriver Capabilities. 35 | func Desired(capabilities Capabilities) Option { 36 | return func(c *config) { 37 | c.DesiredCapabilities = capabilities 38 | } 39 | } 40 | 41 | // RejectInvalidSSL is an Option specifying that the WebDriver should reject 42 | // invalid SSL certificates. All WebDrivers should accept invalid SSL certificates 43 | // by default. See: http://www.w3.org/TR/webdriver/#invalid-ssl-certificates 44 | var RejectInvalidSSL Option = func(c *config) { 45 | c.RejectInvalidSSL = true 46 | } 47 | 48 | // Debug is an Option that connects the running WebDriver to stdout and stdin. 49 | var Debug Option = func(c *config) { 50 | c.Debug = true 51 | } 52 | 53 | // HTTPClient provides an Option for specifying a *http.Client 54 | func HTTPClient(client *http.Client) Option { 55 | return func(c *config) { 56 | c.HTTPClient = client 57 | } 58 | } 59 | 60 | func (c config) Merge(options []Option) *config { 61 | for _, option := range options { 62 | option(&c) 63 | } 64 | return &c 65 | } 66 | 67 | func (c *config) Capabilities() Capabilities { 68 | merged := Capabilities{"acceptSslCerts": true} 69 | for feature, value := range c.DesiredCapabilities { 70 | merged[feature] = value 71 | } 72 | if c.BrowserName != "" { 73 | merged.Browser(c.BrowserName) 74 | } 75 | if c.RejectInvalidSSL { 76 | merged.Without("acceptSslCerts") 77 | } 78 | return merged 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/selection.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sclevine/agouti/api" 7 | "github.com/sclevine/agouti/internal/element" 8 | "github.com/sclevine/agouti/internal/target" 9 | ) 10 | 11 | // Selection instances refer to a selection of elements. 12 | // All Selection methods are also MultiSelection methods. 13 | // 14 | // Methods that take selectors apply their selectors to each element in the 15 | // selection they are called on. If the selection they are called on refers to multiple 16 | // elements, the resulting selection will refer to at least that many elements. 17 | // 18 | // Examples: 19 | // 20 | // selection.Find("table").All("tr").At(2).First("td input[type=checkbox]").Check() 21 | // Checks the first checkbox in the third row of the only table. 22 | // selection.Find("table").All("tr").Find("td").All("input[type=checkbox]").Check() 23 | // Checks all checkboxes in the first-and-only cell of each row in the only table. 24 | type Selection struct { 25 | selectable 26 | elements elementRepository 27 | } 28 | 29 | type elementRepository interface { 30 | Get() ([]element.Element, error) 31 | GetAtLeastOne() ([]element.Element, error) 32 | GetExactlyOne() (element.Element, error) 33 | } 34 | 35 | func newSelection(session apiSession, selectors target.Selectors) *Selection { 36 | return &Selection{ 37 | selectable{session, selectors}, 38 | &element.Repository{ 39 | Client: session, 40 | Selectors: selectors, 41 | }, 42 | } 43 | } 44 | 45 | // String returns a string representation of the selection, ex. 46 | // selection 'CSS: .some-class | XPath: //table [3] | Link "click me" [single]' 47 | func (s *Selection) String() string { 48 | return fmt.Sprintf("selection '%s'", s.selectors) 49 | } 50 | 51 | // Elements returns a []*api.Element that can be used to send direct commands 52 | // to WebDriver elements. See: https://code.google.com/p/selenium/wiki/JsonWireProtocol 53 | func (s *Selection) Elements() ([]*api.Element, error) { 54 | elements, err := s.elements.Get() 55 | if err != nil { 56 | return nil, err 57 | } 58 | apiElements := []*api.Element{} 59 | for _, selectedElement := range elements { 60 | apiElements = append(apiElements, selectedElement.(*api.Element)) 61 | } 62 | return apiElements, nil 63 | } 64 | 65 | // Count returns the number of elements that the selection refers to. 66 | func (s *Selection) Count() (int, error) { 67 | elements, err := s.elements.Get() 68 | if err != nil { 69 | return 0, fmt.Errorf("failed to select elements from %s: %s", s, err) 70 | } 71 | 72 | return len(elements), nil 73 | } 74 | 75 | // EqualsElement returns whether or not two selections of exactly 76 | // one element refer to the same element. 77 | func (s *Selection) EqualsElement(other interface{}) (bool, error) { 78 | otherSelection, ok := other.(*Selection) 79 | if !ok { 80 | multiSelection, ok := other.(*MultiSelection) 81 | if !ok { 82 | return false, fmt.Errorf("must be *Selection or *MultiSelection") 83 | } 84 | otherSelection = &multiSelection.Selection 85 | } 86 | 87 | selectedElement, err := s.elements.GetExactlyOne() 88 | if err != nil { 89 | return false, fmt.Errorf("failed to select element from %s: %s", s, err) 90 | } 91 | 92 | otherElement, err := otherSelection.elements.GetExactlyOne() 93 | if err != nil { 94 | return false, fmt.Errorf("failed to select element from %s: %s", other, err) 95 | } 96 | 97 | equal, err := selectedElement.IsEqualTo(otherElement.(*api.Element)) 98 | if err != nil { 99 | return false, fmt.Errorf("failed to compare %s to %s: %s", s, other, err) 100 | } 101 | 102 | return equal, nil 103 | } 104 | 105 | // MouseToElement moves the mouse over exactly one element in the selection. 106 | func (s *Selection) MouseToElement() error { 107 | selectedElement, err := s.elements.GetExactlyOne() 108 | if err != nil { 109 | return fmt.Errorf("failed to select element from %s: %s", s, err) 110 | } 111 | 112 | if err := s.session.MoveTo(selectedElement.(*api.Element), nil); err != nil { 113 | return fmt.Errorf("failed to move mouse to element for %s: %s", s, err) 114 | } 115 | 116 | return nil 117 | } 118 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/selection_frames.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sclevine/agouti/api" 7 | ) 8 | 9 | // SwitchToFrame focuses on the frame specified by the selection. All new and 10 | // existing selections will refer to the new frame. All further Page methods 11 | // will apply to this frame as well. 12 | func (s *Selection) SwitchToFrame() error { 13 | selectedElement, err := s.elements.GetExactlyOne() 14 | if err != nil { 15 | return fmt.Errorf("failed to select element from %s: %s", s, err) 16 | } 17 | 18 | if err := s.session.Frame(selectedElement.(*api.Element)); err != nil { 19 | return fmt.Errorf("failed to switch to frame referred to by %s: %s", s, err) 20 | } 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/selection_properties.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sclevine/agouti/internal/element" 7 | ) 8 | 9 | // Text returns the entirety of the text content for exactly one element. 10 | func (s *Selection) Text() (string, error) { 11 | selectedElement, err := s.elements.GetExactlyOne() 12 | if err != nil { 13 | return "", fmt.Errorf("failed to select element from %s: %s", s, err) 14 | } 15 | 16 | text, err := selectedElement.GetText() 17 | if err != nil { 18 | return "", fmt.Errorf("failed to retrieve text for %s: %s", s, err) 19 | } 20 | return text, nil 21 | } 22 | 23 | // Active returns true if the single element that the selection refers to is active. 24 | func (s *Selection) Active() (bool, error) { 25 | selectedElement, err := s.elements.GetExactlyOne() 26 | if err != nil { 27 | return false, fmt.Errorf("failed to select element from %s: %s", s, err) 28 | } 29 | 30 | activeElement, err := s.session.GetActiveElement() 31 | if err != nil { 32 | return false, fmt.Errorf("failed to retrieve active element: %s", err) 33 | } 34 | 35 | equal, err := selectedElement.IsEqualTo(activeElement) 36 | if err != nil { 37 | return false, fmt.Errorf("failed to compare selection to active element: %s", err) 38 | } 39 | 40 | return equal, nil 41 | } 42 | 43 | type propertyMethod func(element element.Element, property string) (string, error) 44 | 45 | func (s *Selection) hasProperty(method propertyMethod, property, name string) (string, error) { 46 | selectedElement, err := s.elements.GetExactlyOne() 47 | if err != nil { 48 | return "", fmt.Errorf("failed to select element from %s: %s", s, err) 49 | } 50 | 51 | value, err := method(selectedElement, property) 52 | if err != nil { 53 | return "", fmt.Errorf("failed to retrieve %s value for %s: %s", name, s, err) 54 | } 55 | return value, nil 56 | } 57 | 58 | // Attribute returns an attribute value for exactly one element. 59 | func (s *Selection) Attribute(attribute string) (string, error) { 60 | return s.hasProperty(element.Element.GetAttribute, attribute, "attribute") 61 | } 62 | 63 | // CSS returns a CSS style property value for exactly one element. 64 | func (s *Selection) CSS(property string) (string, error) { 65 | return s.hasProperty(element.Element.GetCSS, property, "CSS property") 66 | } 67 | 68 | type stateMethod func(element element.Element) (bool, error) 69 | 70 | func (s *Selection) hasState(method stateMethod, name string) (bool, error) { 71 | elements, err := s.elements.GetAtLeastOne() 72 | if err != nil { 73 | return false, fmt.Errorf("failed to select elements from %s: %s", s, err) 74 | } 75 | 76 | for _, selectedElement := range elements { 77 | pass, err := method(selectedElement) 78 | if err != nil { 79 | return false, fmt.Errorf("failed to determine whether %s is %s: %s", s, name, err) 80 | } 81 | if !pass { 82 | return false, nil 83 | } 84 | } 85 | 86 | return true, nil 87 | } 88 | 89 | // Selected returns true if all of the elements that the selection refers to are selected. 90 | func (s *Selection) Selected() (bool, error) { 91 | return s.hasState(element.Element.IsSelected, "selected") 92 | } 93 | 94 | // Visible returns true if all of the elements that the selection refers to are visible. 95 | func (s *Selection) Visible() (bool, error) { 96 | return s.hasState(element.Element.IsDisplayed, "visible") 97 | } 98 | 99 | // Enabled returns true if all of the elements that the selection refers to are enabled. 100 | func (s *Selection) Enabled() (bool, error) { 101 | return s.hasState(element.Element.IsEnabled, "enabled") 102 | } 103 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/types.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | type Tap int 4 | 5 | const ( 6 | SingleTap Tap = iota 7 | DoubleTap 8 | LongTap 9 | ) 10 | 11 | func (t Tap) String() string { 12 | switch t { 13 | case SingleTap: 14 | return "tap" 15 | case DoubleTap: 16 | return "double tap" 17 | case LongTap: 18 | return "long tap" 19 | } 20 | return "perform tap" 21 | } 22 | 23 | type Touch int 24 | 25 | const ( 26 | HoldFinger Touch = iota 27 | ReleaseFinger 28 | MoveFinger 29 | ) 30 | 31 | func (t Touch) String() string { 32 | switch t { 33 | case HoldFinger: 34 | return "hold finger down" 35 | case ReleaseFinger: 36 | return "release finger" 37 | case MoveFinger: 38 | return "move finger" 39 | } 40 | return "perform touch" 41 | } 42 | 43 | type Button int 44 | 45 | const ( 46 | LeftButton Button = iota 47 | MiddleButton 48 | RightButton 49 | ) 50 | 51 | func (b Button) String() string { 52 | switch b { 53 | case LeftButton: 54 | return "left mouse button" 55 | case MiddleButton: 56 | return "middle mouse button" 57 | case RightButton: 58 | return "right mouse button" 59 | } 60 | return "unknown" 61 | } 62 | 63 | type Click int 64 | 65 | const ( 66 | SingleClick Click = iota 67 | HoldClick 68 | ReleaseClick 69 | ) 70 | 71 | func (c Click) String() string { 72 | switch c { 73 | case SingleClick: 74 | return "single click" 75 | case HoldClick: 76 | return "hold" 77 | case ReleaseClick: 78 | return "release" 79 | } 80 | return "unknown" 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/sclevine/agouti/webdriver.go: -------------------------------------------------------------------------------- 1 | package agouti 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/sclevine/agouti/api" 7 | ) 8 | 9 | // A WebDriver controls a WebDriver process. This struct embeds api.WebDriver, 10 | // which provides Start and Stop methods for starting and stopping the process. 11 | type WebDriver struct { 12 | *api.WebDriver 13 | defaultOptions *config 14 | } 15 | 16 | // NewWebDriver returns an instance of a WebDriver specified by 17 | // a templated URL and command. The URL should be the location of the 18 | // WebDriver Wire Protocol web service brought up by the command. The 19 | // command should be provided as a list of arguments (each of which are 20 | // templated). 21 | // 22 | // The Timeout Option specifies how many seconds to wait for the web service 23 | // to become available. The default timeout is 5 seconds. 24 | // 25 | // The HTTPClient Option specifies a *http.Client to use for all WebDriver 26 | // communications. The default client is http.DefaultClient. 27 | // 28 | // Any other provided Options are treated as default Options for new pages. 29 | // 30 | // Valid template parameters are: 31 | // {{.Host}} - local address to bind to (usually 127.0.0.1) 32 | // {{.Port}} - arbitrary free port on the local address 33 | // {{.Address}} - {{.Host}}:{{.Port}} 34 | // 35 | // Selenium JAR example: 36 | // command := []string{"java", "-jar", "selenium-server.jar", "-port", "{{.Port}}"} 37 | // agouti.NewWebDriver("http://{{.Address}}/wd/hub", command) 38 | func NewWebDriver(url string, command []string, options ...Option) *WebDriver { 39 | apiWebDriver := api.NewWebDriver(url, command) 40 | defaultOptions := config{Timeout: apiWebDriver.Timeout}.Merge(options) 41 | apiWebDriver.Timeout = defaultOptions.Timeout 42 | apiWebDriver.Debug = defaultOptions.Debug 43 | apiWebDriver.HTTPClient = defaultOptions.HTTPClient 44 | return &WebDriver{apiWebDriver, defaultOptions} 45 | } 46 | 47 | // NewPage returns a *Page that corresponds to a new WebDriver session. 48 | // Provided Options configure the page. For instance, to disable JavaScript: 49 | // capabilities := agouti.NewCapabilities().Without("javascriptEnabled") 50 | // driver.NewPage(agouti.Desired(capabilities)) 51 | // For Selenium, a Browser Option (or a Desired Option with Capabilities that 52 | // specify a Browser) must be provided. For instance: 53 | // seleniumDriver.NewPage(agouti.Browser("safari")) 54 | // Specific Options (such as Browser) have precedence over Capabilities 55 | // specified by the Desired Option. 56 | // 57 | // The HTTPClient Option will be ignored if passed to this function. New pages 58 | // will always use the *http.Client provided to their WebDriver, or 59 | // http.DefaultClient if none was provided. 60 | func (w *WebDriver) NewPage(options ...Option) (*Page, error) { 61 | newOptions := w.defaultOptions.Merge(options) 62 | session, err := w.Open(newOptions.Capabilities()) 63 | if err != nil { 64 | return nil, fmt.Errorf("failed to connect to WebDriver: %s", err) 65 | } 66 | 67 | return newPage(session), nil 68 | } 69 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "htjvdG/znrHmFYRQBqA2vHrJsF4=", 7 | "path": "github.com/Sirupsen/logrus", 8 | "revision": "f3cfb454f4c209e6668c95216c4744b8fddb2356", 9 | "revisionTime": "2016-06-01T11:32:10Z" 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": "M/1HiQFl2DyE+q3pFf8swvAQ3MY=", 19 | "path": "github.com/golang/protobuf/proto", 20 | "revision": "3852dcfda249c2097355a6aabb199a28d97b30df", 21 | "revisionTime": "2016-06-29T21:10:53Z" 22 | }, 23 | { 24 | "checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=", 25 | "path": "github.com/matttproud/golang_protobuf_extensions/pbutil", 26 | "revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c", 27 | "revisionTime": "2016-04-24T11:30:07Z" 28 | }, 29 | { 30 | "checksumSHA1": "OpY4giv8kPIYbaunD7BSgCynj78=", 31 | "path": "github.com/prometheus/client_golang/prometheus", 32 | "revision": "9f1ed1ed4a5f754c9b626e5cf8ec1ea7d622e017", 33 | "revisionTime": "2016-06-27T14:36:20Z" 34 | }, 35 | { 36 | "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=", 37 | "path": "github.com/prometheus/client_model/go", 38 | "revision": "fa8ad6fec33561be4280a8f0514318c79d7f6cb6", 39 | "revisionTime": "2015-02-12T10:17:44Z" 40 | }, 41 | { 42 | "checksumSHA1": "68MLX78PD6yqD2VCtHazVkBaj/w=", 43 | "path": "github.com/prometheus/common/expfmt", 44 | "revision": "4402f4e5ea79ec15f3c574773b6a5198fbea215f", 45 | "revisionTime": "2016-06-23T15:14:27Z" 46 | }, 47 | { 48 | "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=", 49 | "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", 50 | "revision": "4402f4e5ea79ec15f3c574773b6a5198fbea215f", 51 | "revisionTime": "2016-06-23T15:14:27Z" 52 | }, 53 | { 54 | "checksumSHA1": "qHoBp/PVBcLedTNZrF3toV9QGa0=", 55 | "path": "github.com/prometheus/common/log", 56 | "revision": "4402f4e5ea79ec15f3c574773b6a5198fbea215f", 57 | "revisionTime": "2016-06-23T15:14:27Z" 58 | }, 59 | { 60 | "checksumSHA1": "Jx0GXl5hGnO25s3ryyvtdWHdCpw=", 61 | "path": "github.com/prometheus/common/model", 62 | "revision": "4402f4e5ea79ec15f3c574773b6a5198fbea215f", 63 | "revisionTime": "2016-06-23T15:14:27Z" 64 | }, 65 | { 66 | "checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=", 67 | "path": "github.com/prometheus/common/version", 68 | "revision": "4402f4e5ea79ec15f3c574773b6a5198fbea215f", 69 | "revisionTime": "2016-06-23T15:14:27Z" 70 | }, 71 | { 72 | "checksumSHA1": "W218eJZPXJG783fUr/z6IaAZyes=", 73 | "path": "github.com/prometheus/procfs", 74 | "revision": "abf152e5f3e97f2fafac028d2cc06c1feb87ffa5", 75 | "revisionTime": "2016-04-11T19:08:41Z" 76 | }, 77 | { 78 | "checksumSHA1": "jhys1vVeyY6GdVDIiRkA5I1GRiI=", 79 | "path": "github.com/sclevine/agouti", 80 | "revision": "e5378e70dca437a9e16cc6d71a85aa0045dd94c7", 81 | "revisionTime": "2016-02-24T21:38:56Z" 82 | }, 83 | { 84 | "checksumSHA1": "cevMax2kqFXdc0OwxRjn28NEX+g=", 85 | "path": "github.com/sclevine/agouti/api", 86 | "revision": "e5378e70dca437a9e16cc6d71a85aa0045dd94c7", 87 | "revisionTime": "2016-02-24T21:38:56Z" 88 | }, 89 | { 90 | "checksumSHA1": "Yl+nKbowoSkeEZVjG8JUr1xum3w=", 91 | "path": "github.com/sclevine/agouti/api/internal/bus", 92 | "revision": "e5378e70dca437a9e16cc6d71a85aa0045dd94c7", 93 | "revisionTime": "2016-02-24T21:38:56Z" 94 | }, 95 | { 96 | "checksumSHA1": "D/zRQi9pX42xYVX1p3mZrNDGRX4=", 97 | "path": "github.com/sclevine/agouti/api/internal/service", 98 | "revision": "e5378e70dca437a9e16cc6d71a85aa0045dd94c7", 99 | "revisionTime": "2016-02-24T21:38:56Z" 100 | }, 101 | { 102 | "checksumSHA1": "Ac+sqfWJvIqAoFnDzZRH8HP/1gg=", 103 | "path": "github.com/sclevine/agouti/internal/element", 104 | "revision": "e5378e70dca437a9e16cc6d71a85aa0045dd94c7", 105 | "revisionTime": "2016-02-24T21:38:56Z" 106 | }, 107 | { 108 | "checksumSHA1": "rsdZ0GsD51gqfRPf3NFox3xw8eM=", 109 | "path": "github.com/sclevine/agouti/internal/target", 110 | "revision": "e5378e70dca437a9e16cc6d71a85aa0045dd94c7", 111 | "revisionTime": "2016-02-24T21:38:56Z" 112 | } 113 | ], 114 | "rootPath": "github.com/mattbostock/webdriver_exporter" 115 | } 116 | --------------------------------------------------------------------------------