├── .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 | [](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 | [](https://godoc.org/github.com/prometheus/procfs)
10 | [](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 | [](http://travis-ci.org/sclevine/agouti)
5 | [](https://godoc.org/github.com/sclevine/agouti)
6 |
7 | [](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 |
--------------------------------------------------------------------------------