├── README.md ├── availability └── probing_101 │ ├── Makefile │ ├── postgres-stack │ ├── bin │ │ └── wait-for-postgres.sh │ ├── config │ │ ├── cloudprober-singletarget.cfg │ │ └── postgres-cloudprober.sh │ └── docker-compose.yml │ ├── probetestserver │ └── main.go │ └── stack │ ├── config │ ├── cloudprober-singletarget.cfg │ └── prometheus.yml │ └── docker-compose.yml ├── observability └── envoy-bolt-on-observability │ ├── config │ └── envoy.yaml │ └── docker-compose.yml └── performance └── analysis-methodology-simple-http ├── Dockerfile ├── Gopkg.lock ├── Gopkg.toml ├── Makefile ├── bin └── amd64 │ └── wait-for ├── cmd └── server │ └── main.go ├── config ├── dashboards.yml ├── dashboards │ ├── service.json │ └── service.json~ ├── grafana_prometheus_datasource.yml ├── postgres │ └── schema.sh └── prometheus.yml ├── docker-compose.yml ├── tests └── fixtures │ ├── age_match.json │ └── age_no_match.json └── vendor └── github.com ├── beorn7 └── perks │ ├── LICENSE │ └── quantile │ ├── exampledata.txt │ └── stream.go ├── golang └── protobuf │ ├── AUTHORS │ ├── CONTRIBUTORS │ ├── LICENSE │ └── proto │ ├── clone.go │ ├── decode.go │ ├── discard.go │ ├── encode.go │ ├── equal.go │ ├── extensions.go │ ├── lib.go │ ├── message_set.go │ ├── pointer_reflect.go │ ├── pointer_unsafe.go │ ├── properties.go │ ├── table_marshal.go │ ├── table_merge.go │ ├── table_unmarshal.go │ ├── text.go │ └── text_parser.go ├── lib └── pq │ ├── .gitignore │ ├── .travis.sh │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE.md │ ├── README.md │ ├── TESTS.md │ ├── array.go │ ├── buf.go │ ├── conn.go │ ├── conn_go18.go │ ├── connector.go │ ├── copy.go │ ├── doc.go │ ├── encode.go │ ├── error.go │ ├── go.mod │ ├── notify.go │ ├── oid │ ├── doc.go │ ├── gen.go │ └── types.go │ ├── rows.go │ ├── ssl.go │ ├── ssl_go1.7.go │ ├── ssl_permissions.go │ ├── ssl_renegotiation.go │ ├── ssl_windows.go │ ├── url.go │ ├── user_posix.go │ ├── user_windows.go │ └── uuid.go ├── matttproud └── golang_protobuf_extensions │ ├── LICENSE │ ├── NOTICE │ └── pbutil │ ├── .gitignore │ ├── Makefile │ ├── decode.go │ ├── doc.go │ └── encode.go └── prometheus ├── client_golang ├── LICENSE ├── NOTICE └── prometheus │ ├── .gitignore │ ├── README.md │ ├── collector.go │ ├── counter.go │ ├── desc.go │ ├── doc.go │ ├── expvar_collector.go │ ├── fnv.go │ ├── gauge.go │ ├── go_collector.go │ ├── histogram.go │ ├── http.go │ ├── internal │ └── metric.go │ ├── labels.go │ ├── metric.go │ ├── observer.go │ ├── process_collector.go │ ├── promhttp │ ├── delegator.go │ ├── delegator_1_8.go │ ├── delegator_pre_1_8.go │ ├── http.go │ ├── instrument_client.go │ ├── instrument_client_1_8.go │ └── instrument_server.go │ ├── registry.go │ ├── summary.go │ ├── timer.go │ ├── untyped.go │ ├── value.go │ ├── vec.go │ └── wrap.go ├── client_model ├── LICENSE ├── NOTICE ├── go │ └── metrics.pb.go └── ruby │ └── LICENSE ├── 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 └── model │ ├── alert.go │ ├── fingerprinting.go │ ├── fnv.go │ ├── labels.go │ ├── labelset.go │ ├── metric.go │ ├── model.go │ ├── signature.go │ ├── silence.go │ ├── time.go │ └── value.go └── procfs ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS.md ├── Makefile ├── NOTICE ├── README.md ├── buddyinfo.go ├── doc.go ├── fixtures.ttar ├── fs.go ├── internal └── util │ ├── parse.go │ └── sysreadfile_linux.go ├── ipvs.go ├── mdstat.go ├── mountstats.go ├── net_dev.go ├── nfs ├── nfs.go ├── parse.go ├── parse_nfs.go └── parse_nfsd.go ├── proc.go ├── proc_io.go ├── proc_limits.go ├── proc_ns.go ├── proc_stat.go ├── stat.go ├── ttar ├── xfrm.go └── xfs ├── parse.go └── xfs.go /README.md: -------------------------------------------------------------------------------- 1 | # sre-tutorials -------------------------------------------------------------------------------- /availability/probing_101/Makefile: -------------------------------------------------------------------------------- 1 | WD:=$(shell pwd) 2 | 3 | start-stack: 4 | docker volume prune -f 5 | cd stack \ 6 | && docker-compose down \ 7 | && docker-compose up 8 | 9 | start-postgres-stack: 10 | # start postgres 11 | docker stop postgres || true 12 | docker container rm postgres || true 13 | docker run \ 14 | -p "5432:5432" \ 15 | -e POSTGRES_USER=root \ 16 | -e POSTGRES_PASSWORD=root \ 17 | -v "$(WD)/postgres-stack/config:/docker-entrypoint-initdb.d" \ 18 | --name=postgres \ 19 | -d \ 20 | postgres:9.6 21 | 22 | # wait until initialized 23 | ./postgres-stack/bin/wait-for-postgres.sh 24 | 25 | # start cloudprober 26 | docker stop cloudprober || true 27 | docker container rm cloudprober || true 28 | docker run \ 29 | -p "9313:9313" \ 30 | -v "$(WD)/postgres-stack/config/cloudprober-singletarget.cfg:/etc/cloudprober.cfg" \ 31 | --network=host \ 32 | --name cloudprober \ 33 | -d \ 34 | cloudprober/cloudprober 35 | 36 | .PHONY: start-stack start-postgres-stack -------------------------------------------------------------------------------- /availability/probing_101/postgres-stack/bin/wait-for-postgres.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SCRIPT="[wait-for-postgres.sh]" 4 | EXPECTED="1-" 5 | export PGPASSWORD=root 6 | POSTGRES_STATUS=$(psql -h 127.0.0.1 -tA -U root -c "SELECT 1" | tr '\n' '-') 7 | 8 | # TODO ADD TIMEOUT 9 | 10 | until [ "$POSTGRES_STATUS" = "$EXPECTED" ]; do 11 | POSTGRES_STATUS=$(psql -h 127.0.0.1 -tA -U root -c "SELECT 1" | tr '\n' '-') 12 | echo "$SCRIPT polling postgres status, expected: $EXPECTED received: $POSTGRES_STATUS" 13 | sleep 1 14 | done 15 | 16 | echo "$SCRIPT Postgres Initialized" -------------------------------------------------------------------------------- /availability/probing_101/postgres-stack/config/cloudprober-singletarget.cfg: -------------------------------------------------------------------------------- 1 | probe { 2 | name: "test_server" 3 | type: HTTP 4 | targets { 5 | host_names: "localhost" 6 | } 7 | 8 | interval_msec: 100 9 | timeout_msec: 100 10 | 11 | http_probe { 12 | protocol: HTTP 13 | port: 5000 14 | } 15 | } 16 | 17 | surfacer { 18 | type: POSTGRES 19 | postgres_surfacer { 20 | connection_string: "postgresql://root:root@localhost/cloudprober?sslmode=disable" 21 | metrics_table_name: "metrics" 22 | } 23 | } -------------------------------------------------------------------------------- /availability/probing_101/postgres-stack/config/postgres-cloudprober.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | psql -c "create database cloudprober" 4 | 5 | psql -c "create schema cloudprober" 6 | 7 | psql cloudprober -c "CREATE TABLE metrics ( 8 | time TIMESTAMP WITH TIME ZONE, 9 | metric_name text NOT NULL, 10 | value DOUBLE PRECISION , 11 | labels jsonb, 12 | PRIMARY KEY (time, metric_name, labels) 13 | )" -------------------------------------------------------------------------------- /availability/probing_101/postgres-stack/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | cloudprober: 4 | image: cloudprober/cloudprober 5 | ports: 6 | - "9313:9313" 7 | volumes: 8 | - ./config/cloudprober-singletarget.cfg:/etc/cloudprober.cfg 9 | depends_on: 10 | - postgres 11 | postgres: 12 | image: postgres:9.6 13 | ports: 14 | - 5432:5432 15 | environment: 16 | POSTGRES_USER: root 17 | POSTGRES_PASSWORD: root 18 | volumes: 19 | - ./config:/docker-entrypoint-initdb.d 20 | -------------------------------------------------------------------------------- /availability/probing_101/probetestserver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "math/rand" 9 | "net/http" 10 | "os" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | var logger *log.Logger 16 | 17 | func init() { 18 | logger = log.New(os.Stdout, 19 | "DEBUG: ", 20 | log.Ldate|log.Ltime|log.Lshortfile) 21 | } 22 | 23 | func durationFromString(ds string) (time.Duration, error) { 24 | if ds == "" { 25 | ds = "0s" 26 | } 27 | return time.ParseDuration(ds) 28 | } 29 | 30 | type artificialFailureHandler struct { 31 | next http.Handler 32 | requestFailureRate int 33 | 34 | mu sync.Mutex 35 | numRequests int 36 | } 37 | 38 | func (h *artificialFailureHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 39 | logger.Printf("artificialFailureHandler.ServeHTTP()") 40 | h.mu.Lock() 41 | h.numRequests += 1 42 | h.mu.Unlock() 43 | 44 | if h.requestFailureRate > 0 && h.numRequests%h.requestFailureRate == 0 { 45 | panic(fmt.Errorf( 46 | "injected error, requests count: %d w/ rate of %d", h.numRequests, h.requestFailureRate, 47 | )) 48 | } 49 | 50 | h.next.ServeHTTP(w, r) 51 | } 52 | 53 | type handler struct{} 54 | 55 | func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 56 | logger.Printf("handler.ServeHTTP()") 57 | _, err := ioutil.ReadAll(r.Body) 58 | logger.Printf("received request for %q", r.URL) 59 | if err != nil { 60 | panic(err) 61 | } 62 | defer r.Body.Close() 63 | 64 | w.WriteHeader(http.StatusOK) 65 | w.Write([]byte(`OK`)) 66 | } 67 | 68 | type latencyHandler struct { 69 | next http.Handler 70 | } 71 | 72 | func (lh latencyHandler) RandDuration(max time.Duration, min time.Duration) time.Duration { 73 | if max.Nanoseconds() == 0 && min.Nanoseconds() == 0 { 74 | return 0 75 | } 76 | 77 | r := rand.Intn( 78 | int(max.Nanoseconds())-int(min.Nanoseconds())) + int(min.Nanoseconds()) 79 | 80 | return time.Duration(r) * time.Nanosecond 81 | } 82 | 83 | func (lh latencyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 84 | logger.Printf("latencyHandler.ServeHTTP()") 85 | 86 | minDuration, err := durationFromString(r.URL.Query().Get("minDuration")) 87 | if err != nil { 88 | panic(err) 89 | } 90 | 91 | maxDuration, err := durationFromString(r.URL.Query().Get("maxDuration")) 92 | if err != nil { 93 | panic(err) 94 | } 95 | if maxDuration.Nanoseconds() < minDuration.Nanoseconds() { 96 | panic(fmt.Errorf("maxDuration (%s) less than minDuration (%s)", 97 | maxDuration, minDuration)) 98 | } 99 | 100 | d := lh.RandDuration(maxDuration, minDuration) 101 | logger.Printf("sleeping for %s", d) 102 | time.Sleep(d) 103 | 104 | lh.next.ServeHTTP(w, r) 105 | } 106 | 107 | func main() { 108 | var requestFailureRate = flag.Int("request-failure-rate", 0, "set to determine how many requests "+ 109 | "should fail. The default are 0 artificially failed requests, a rate of 1 will mean every request, a rate of two will mean "+ 110 | "every other request, etc.") 111 | var addr = flag.String("addr", "127.0.0.1:5000", "addr/port for the tes") 112 | flag.Parse() 113 | 114 | h := &http.Server{ 115 | Addr: *addr, 116 | Handler: &artificialFailureHandler{ 117 | requestFailureRate: *requestFailureRate, 118 | next: latencyHandler{ 119 | next: handler{}, 120 | }, 121 | }, 122 | } 123 | 124 | logger.Printf("starting test server on: %q\n", *addr) 125 | 126 | if err := h.ListenAndServe(); err != nil { 127 | logger.Println(err) 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /availability/probing_101/stack/config/cloudprober-singletarget.cfg: -------------------------------------------------------------------------------- 1 | probe { 2 | name: "test_server" 3 | type: HTTP 4 | targets { 5 | host_names: "localhost" 6 | } 7 | 8 | interval_msec: 5000 9 | timeout_msec: 1000 10 | 11 | latency_unit: "s" 12 | 13 | latency_distribution: { 14 | explicit_buckets: ".01,.02,.04,.06,.08,.1,.2,.4,.6,.8,1,5,10" 15 | } 16 | 17 | http_probe { 18 | protocol: HTTP 19 | port: 5000 20 | relative_url: "/?minDuration=0ms&maxDuration=150ms" 21 | } 22 | } -------------------------------------------------------------------------------- /availability/probing_101/stack/config/prometheus.yml: -------------------------------------------------------------------------------- 1 | # my global config 2 | global: 3 | scrape_interval: 15s # By default, scrape targets every 15 seconds. 4 | evaluation_interval: 15s # By default, scrape targets every 15 seconds. 5 | # scrape_timeout is set to the global default (10s). 6 | 7 | # Attach these labels to any time series or alerts when communicating with 8 | # external systems (federation, remote storage, Alertmanager). 9 | external_labels: 10 | monitor: 'codelab-monitor' 11 | 12 | # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. 13 | rule_files: 14 | # - "first.rules" 15 | # - "second.rules" 16 | 17 | # A scrape configuration containing exactly one endpoint to scrape: 18 | # Here it's Prometheus itself. 19 | scrape_configs: 20 | # The job name is added as a label `job=` to any timeseries scraped from this config. 21 | - job_name: 'prometheus' 22 | 23 | # Override the global default and scrape targets from this job every 5 seconds. 24 | scrape_interval: 5s 25 | 26 | # metrics_path defaults to '/metrics' 27 | # scheme defaults to 'http'. 28 | 29 | static_configs: 30 | - targets: ['localhost:9090'] 31 | 32 | - job_name: "node" 33 | scrape_interval: "15s" 34 | static_configs: 35 | - targets: ['localhost:9100'] 36 | 37 | - job_name: 'cloudprober' 38 | scrape_interval: 10s 39 | static_configs: 40 | - targets: ['localhost:9313'] -------------------------------------------------------------------------------- /availability/probing_101/stack/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | prom: 4 | image: prom/prometheus:v2.1.0 5 | volumes: 6 | - ./config/prometheus.yml:/etc/prometheus/prometheus.yml 7 | command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" 8 | network_mode: "host" 9 | ports: 10 | - 9090:9090 11 | depends_on: 12 | - exporter 13 | - cloudprober 14 | 15 | cloudprober: 16 | image: cloudprober/cloudprober 17 | network_mode: "host" 18 | ports: 19 | - "9313:9313" 20 | volumes: 21 | - ./config/cloudprober-singletarget.cfg:/etc/cloudprober.cfg 22 | 23 | exporter: 24 | image: prom/node-exporter:latest 25 | network_mode: "host" 26 | ports: 27 | - "9100:9100" 28 | 29 | grafana: 30 | image: grafana/grafana 31 | network_mode: "host" 32 | ports: 33 | - "3000:3000" 34 | depends_on: 35 | - prom -------------------------------------------------------------------------------- /observability/envoy-bolt-on-observability/config/envoy.yaml: -------------------------------------------------------------------------------- 1 | static_resources: 2 | listeners: 3 | - name: listener_0 4 | address: 5 | socket_address: 6 | address: 0.0.0.0 7 | port_value: 10000 8 | filter_chains: 9 | - filters: 10 | - name: envoy.http_connection_manager 11 | typed_config: 12 | "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager 13 | use_remote_address: true 14 | stat_prefix: ingress_http 15 | codec_type: auto 16 | route_config: 17 | name: facebook_api 18 | virtual_hosts: 19 | - name: facebook_api 20 | domains: 21 | - "*" 22 | routes: 23 | - match: 24 | prefix: "/" 25 | route: 26 | cluster: facebook 27 | http_filters: 28 | - name: envoy.router 29 | 30 | clusters: 31 | - name: facebook 32 | connect_timeout: 1s 33 | type: STRICT_DNS 34 | lb_policy: ROUND_ROBIN 35 | load_assignment: 36 | cluster_name: facebook 37 | endpoints: 38 | - lb_endpoints: 39 | - endpoint: 40 | address: 41 | socket_address: 42 | address: 0.0.0.0 43 | port_value: 8080 44 | 45 | admin: 46 | access_log_path: "/dev/null" 47 | address: 48 | socket_address: 49 | address: 0.0.0.0 50 | port_value: 9901 -------------------------------------------------------------------------------- /observability/envoy-bolt-on-observability/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | envoy: 5 | image: envoyproxy/envoy 6 | network_mode: host 7 | volumes: 8 | - ./config/envoy.yaml:/tmp/envoy.yaml 9 | ports: 10 | - 10000:10000 11 | - 9901:9901 12 | command: envoy -c /tmp/envoy.yaml -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.10 2 | WORKDIR /go -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" 7 | name = "github.com/beorn7/perks" 8 | packages = ["quantile"] 9 | pruneopts = "UT" 10 | revision = "3a771d992973f24aa725d07868b467d1ddfceafb" 11 | 12 | [[projects]] 13 | digest = "1:97df918963298c287643883209a2c3f642e6593379f97ab400c2a2e219ab647d" 14 | name = "github.com/golang/protobuf" 15 | packages = ["proto"] 16 | pruneopts = "UT" 17 | revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" 18 | version = "v1.2.0" 19 | 20 | [[projects]] 21 | digest = "1:8ef506fc2bb9ced9b151dafa592d4046063d744c646c1bbe801982ce87e4bc24" 22 | name = "github.com/lib/pq" 23 | packages = [ 24 | ".", 25 | "oid", 26 | ] 27 | pruneopts = "UT" 28 | revision = "4ded0e9383f75c197b3a2aaa6d590ac52df6fd79" 29 | version = "v1.0.0" 30 | 31 | [[projects]] 32 | digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc" 33 | name = "github.com/matttproud/golang_protobuf_extensions" 34 | packages = ["pbutil"] 35 | pruneopts = "UT" 36 | revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" 37 | version = "v1.0.1" 38 | 39 | [[projects]] 40 | digest = "1:26663fafdea73a38075b07e8e9d82fc0056379d2be8bb4e13899e8fda7c7dd23" 41 | name = "github.com/prometheus/client_golang" 42 | packages = [ 43 | "prometheus", 44 | "prometheus/internal", 45 | "prometheus/promhttp", 46 | ] 47 | pruneopts = "UT" 48 | revision = "abad2d1bd44235a26707c172eab6bca5bf2dbad3" 49 | version = "v0.9.1" 50 | 51 | [[projects]] 52 | branch = "master" 53 | digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" 54 | name = "github.com/prometheus/client_model" 55 | packages = ["go"] 56 | pruneopts = "UT" 57 | revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" 58 | 59 | [[projects]] 60 | branch = "master" 61 | digest = "1:db712fde5d12d6cdbdf14b777f0c230f4ff5ab0be8e35b239fc319953ed577a4" 62 | name = "github.com/prometheus/common" 63 | packages = [ 64 | "expfmt", 65 | "internal/bitbucket.org/ww/goautoneg", 66 | "model", 67 | ] 68 | pruneopts = "UT" 69 | revision = "41aa239b4cce3c56ab88fc366ae8b0a6423fa239" 70 | 71 | [[projects]] 72 | branch = "master" 73 | digest = "1:ef74914912f99c79434d9c09658274678bc85080ebe3ab32bec3940ebce5e1fc" 74 | name = "github.com/prometheus/procfs" 75 | packages = [ 76 | ".", 77 | "internal/util", 78 | "nfs", 79 | "xfs", 80 | ] 81 | pruneopts = "UT" 82 | revision = "185b4288413d2a0dd0806f78c90dde719829e5ae" 83 | 84 | [solve-meta] 85 | analyzer-name = "dep" 86 | analyzer-version = 1 87 | input-imports = [ 88 | "github.com/lib/pq", 89 | "github.com/prometheus/client_golang/prometheus/promhttp", 90 | ] 91 | solver-name = "gps-cdcl" 92 | solver-version = 1 93 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [[constraint]] 29 | name = "github.com/prometheus/client_golang" 30 | version = "0.9.1" 31 | 32 | [prune] 33 | go-tests = true 34 | unused-packages = true 35 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/Makefile: -------------------------------------------------------------------------------- 1 | LOAD_TEST_RATE=50 2 | LOAD_TEST_TARGET=http://localhost:8080 3 | PKGS = $(shell go list ./... | grep -v /vendor/) 4 | 5 | fmt: 6 | go fmt $(PKGS) 7 | 8 | stack: 9 | docker-compose down && docker-compose up 10 | 11 | load-test: 12 | echo "POST $(LOAD_TEST_TARGET)" | vegeta attack -body tests/fixtures/age_no_match.json -rate=$(LOAD_TEST_RATE) -duration=0 | tee results.bin | vegeta report 13 | 14 | ping-server: 15 | curl \ 16 | -X POST \ 17 | -H "Content-Type: application/json" \ 18 | -d @tests/fixtures/age_no_match.json \ 19 | http://localhost:8080 -v 20 | 21 | .PHONY: stack load-test fmt test-unit 22 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/bin/amd64/wait-for: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dm03514/sre-tutorials/8ade66ae5b4c181b736315c7708dd5d11d0035dd/performance/analysis-methodology-simple-http/bin/amd64/wait-for -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/cmd/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/json" 6 | "flag" 7 | "fmt" 8 | _ "github.com/lib/pq" 9 | "github.com/prometheus/client_golang/prometheus" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | "html" 12 | "log" 13 | "net/http" 14 | "net/http/pprof" 15 | "time" 16 | ) 17 | 18 | func errToStatus(err error) string { 19 | if err != nil { 20 | return "error" 21 | } 22 | return "success" 23 | } 24 | 25 | var ( 26 | requestLatency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ 27 | Name: "http_request_seconds", 28 | Help: "Distribution of request lengths", 29 | }, []string{"path"}) 30 | 31 | findByAgeLatency = prometheus.NewHistogramVec(prometheus.HistogramOpts{ 32 | Name: "find_by_age_seconds", 33 | Help: "Distribution of find by age durations, status=success|error", 34 | }, []string{"status"}) 35 | 36 | findByAgeResultCount = prometheus.NewGaugeVec(prometheus.GaugeOpts{ 37 | Name: "find_by_age_results_count", 38 | Help: "# of results returned from find by age", 39 | }, []string{"status"}) 40 | ) 41 | 42 | func init() { 43 | prometheus.MustRegister(requestLatency) 44 | prometheus.MustRegister(findByAgeLatency) 45 | prometheus.MustRegister(findByAgeResultCount) 46 | } 47 | 48 | type Postgres struct { 49 | db *sql.DB 50 | } 51 | 52 | type PeopleResponse struct { 53 | People []Person 54 | } 55 | 56 | type Person struct { 57 | Address string 58 | FullName string 59 | Age int 60 | } 61 | 62 | type Payload struct { 63 | Age int 64 | } 65 | 66 | type Handler struct { 67 | Postgres *Postgres 68 | } 69 | 70 | func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 71 | start := time.Now() 72 | 73 | defer func() { 74 | diff := time.Since(start) 75 | // fmt.Fprintf(w, "Took: %s\n", diff) 76 | requestLatency.WithLabelValues(html.EscapeString(r.URL.Path)).Observe(diff.Seconds()) 77 | }() 78 | 79 | payload := Payload{} 80 | err := json.NewDecoder(r.Body).Decode(&payload) 81 | if err != nil { 82 | msg := fmt.Sprintf("received: %q. Expected message of format %+v", 83 | err, Payload{}) 84 | http.Error(w, msg, http.StatusInternalServerError) 85 | return 86 | } 87 | defer r.Body.Close() 88 | 89 | findStart := time.Now() 90 | people, err := h.Postgres.FindByAge(payload.Age) 91 | 92 | findByAgeLatency.WithLabelValues( 93 | errToStatus(err), 94 | ).Observe( 95 | time.Since(findStart).Seconds(), 96 | ) 97 | 98 | findByAgeResultCount.WithLabelValues(errToStatus(err)).Set(float64(len(people))) 99 | 100 | if err != nil { 101 | http.Error(w, err.Error(), http.StatusInternalServerError) 102 | return 103 | } 104 | 105 | resp := PeopleResponse{ 106 | People: people, 107 | } 108 | w.Header().Set("Content-Type", "application/json") 109 | json.NewEncoder(w).Encode(&resp) 110 | } 111 | 112 | func (p *Postgres) FindByAge(age int) ([]Person, error) { 113 | people := []Person{} 114 | 115 | q := `SELECT address, full_name, age FROM people WHERE age = $1` 116 | 117 | rows, err := p.db.Query(q, age) 118 | if err != nil { 119 | return people, nil 120 | } 121 | defer rows.Close() 122 | for rows.Next() { 123 | person := Person{} 124 | 125 | if err := rows.Scan(&person.Address, &person.FullName, &person.Address); err != nil { 126 | return people, err 127 | } 128 | 129 | people = append(people, person) 130 | } 131 | 132 | if err := rows.Err(); err != nil { 133 | return people, err 134 | } 135 | 136 | return people, nil 137 | } 138 | 139 | func NewPostges(dbConnectionString string) (*Postgres, error) { 140 | db, err := sql.Open("postgres", dbConnectionString) 141 | // db.SetMaxOpenConns(8) 142 | // db.SetMaxIdleConns(8) 143 | 144 | if err != nil { 145 | return nil, err 146 | } 147 | 148 | if err = db.Ping(); err != nil { 149 | return nil, err 150 | } 151 | 152 | return &Postgres{ 153 | db: db, 154 | }, nil 155 | } 156 | 157 | func AttachProfiler(router *http.ServeMux) { 158 | router.HandleFunc("/debug/pprof/", pprof.Index) 159 | router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) 160 | router.HandleFunc("/debug/pprof/profile", pprof.Profile) 161 | router.HandleFunc("/debug/pprof/symbol", pprof.Symbol) 162 | 163 | // Manually add support for paths linked to by index page at /debug/pprof/ 164 | router.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine")) 165 | router.Handle("/debug/pprof/heap", pprof.Handler("heap")) 166 | router.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate")) 167 | router.Handle("/debug/pprof/block", pprof.Handler("block")) 168 | } 169 | 170 | func main() { 171 | dbConnectionString := flag.String("db-connection-string", "", "") 172 | flag.Parse() 173 | 174 | postgres, err := NewPostges(*dbConnectionString) 175 | if err != nil { 176 | panic(err) 177 | } 178 | 179 | h := &Handler{ 180 | Postgres: postgres, 181 | } 182 | 183 | mux := http.NewServeMux() 184 | mux.Handle("/metrics", promhttp.Handler()) 185 | AttachProfiler(mux) 186 | mux.Handle("/", h) 187 | 188 | s := &http.Server{ 189 | Addr: ":8080", 190 | Handler: mux, 191 | ReadTimeout: 30 * time.Second, 192 | WriteTimeout: 30 * time.Second, 193 | MaxHeaderBytes: 1 << 20, 194 | } 195 | fmt.Printf("starting_server: %q\n", s.Addr) 196 | log.Fatal(s.ListenAndServe()) 197 | } 198 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/config/dashboards.yml: -------------------------------------------------------------------------------- 1 | - name: 'default' 2 | org_id: 1 3 | folder: '' 4 | type: file 5 | options: 6 | folder: /var/lib/grafana/dashboards -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/config/grafana_prometheus_datasource.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # list of datasources to insert/update depending 5 | # what's available in the database 6 | datasources: 7 | # name of the datasource. Required 8 | - name: Prom 9 | # datasource type. Required 10 | type: prometheus 11 | # access mode. proxy or direct (Server or Browser in the UI). Required 12 | access: browser 13 | # org id. will default to orgId 1 if not specified 14 | orgId: 1 15 | # url 16 | url: http://localhost:9090 17 | # database password, if used 18 | password: 19 | # database user, if used 20 | user: 21 | # database name, if used 22 | database: 23 | # enable/disable basic auth 24 | basicAuth: 25 | # basic auth username 26 | basicAuthUser: 27 | # basic auth password 28 | basicAuthPassword: 29 | # enable/disable with credentials headers 30 | withCredentials: 31 | # mark as default datasource. Max one per org 32 | isDefault: 33 | # fields that will be converted to json and stored in json_data 34 | jsonData: 35 | graphiteVersion: "1.1" 36 | tlsAuth: true 37 | tlsAuthWithCACert: true 38 | # json object of data that will be encrypted. 39 | secureJsonData: 40 | tlsCACert: "..." 41 | tlsClientCert: "..." 42 | tlsClientKey: "..." 43 | version: 1 44 | # allow users to edit datasources from the UI. 45 | editable: false -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/config/postgres/schema.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | psql -c "create database people" 4 | 5 | psql -c "create schema people" 6 | 7 | psql people -c "CREATE TABLE people ( 8 | last_updated_time TIMESTAMP WITH TIME ZONE default current_timestamp, 9 | address text NOT NULL, 10 | full_name text NOT NULL, 11 | age integer NOT NULL, 12 | PRIMARY KEY (full_name, address) 13 | )" 14 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/config/prometheus.yml: -------------------------------------------------------------------------------- 1 | # my global config 2 | global: 3 | scrape_interval: 15s # By default, scrape targets every 15 seconds. 4 | evaluation_interval: 15s # By default, scrape targets every 15 seconds. 5 | # scrape_timeout is set to the global default (10s). 6 | 7 | # Attach these labels to any time series or alerts when communicating with 8 | # external systems (federation, remote storage, Alertmanager). 9 | external_labels: 10 | monitor: 'codelab-monitor' 11 | 12 | # Load rules once and periodically evaluate them according to the global 'evaluation_interval'. 13 | rule_files: 14 | # - "first.rules" 15 | # - "second.rules" 16 | 17 | # A scrape configuration containing exactly one endpoint to scrape: 18 | # Here it's Prometheus itself. 19 | scrape_configs: 20 | # The job name is added as a label `job=` to any timeseries scraped from this config. 21 | - job_name: 'prometheus' 22 | 23 | # Override the global default and scrape targets from this job every 5 seconds. 24 | scrape_interval: 5s 25 | 26 | # metrics_path defaults to '/metrics' 27 | # scheme defaults to 'http'. 28 | 29 | static_configs: 30 | - targets: ['localhost:9090'] 31 | 32 | - job_name: "node" 33 | scrape_interval: "15s" 34 | static_configs: 35 | - targets: ['exporter:9100'] 36 | 37 | - job_name: "server" 38 | scrape_interval: "15s" 39 | static_configs: 40 | - targets: ['server:8080'] 41 | 42 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | server: 4 | build: . 5 | image: golang:1.10 6 | environment: 7 | - WAIT_FOR_POSTGRES_CONNECTION_STRING=postgresql://postgres:root@postgres/people?sslmode=disable 8 | command: bash -c "/tmp/wait-for postgres && go run /go/src/github.com/dm03514/analysis-methodology-simple-http/cmd/server/main.go -db-connection-string=postgresql://postgres:root@postgres/people?sslmode=disable" 9 | # command: go run /go/src/github.com/dm03514/analysis-methodology-simple-http/cmd/server/main.go -db-connection-string=postgresql://root:root@postgres/people?sslmode=disable 10 | volumes: 11 | - ./bin/amd64/wait-for:/tmp/wait-for 12 | - .:/go/src/github.com/dm03514/analysis-methodology-simple-http 13 | ports: 14 | - 8080:8080 15 | working_dir: /go 16 | depends_on: 17 | - postgres 18 | 19 | prom: 20 | image: prom/prometheus:v2.1.0 21 | volumes: 22 | - ./config/prometheus.yml:/etc/prometheus/prometheus.yml 23 | command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" 24 | # network_mode: host 25 | ports: 26 | - 9090:9090 27 | depends_on: 28 | - exporter 29 | 30 | postgres: 31 | image: postgres:9.6 32 | ports: 33 | - 5432:5432 34 | environment: 35 | POSTGRES_PASSWORD: root 36 | volumes: 37 | - ./config/postgres:/docker-entrypoint-initdb.d 38 | 39 | exporter: 40 | image: prom/node-exporter:latest 41 | ports: 42 | - 9100:9100 43 | 44 | grafana: 45 | image: grafana/grafana 46 | environment: 47 | - GF_USERS_DEFAULT_THEME=light 48 | - GF_AUTH_ANONYMOUS_ENABLED=true 49 | - GF_AUTH_ANONYMOUS_ORG_ROLE=Editor 50 | volumes: 51 | - ./config/grafana_prometheus_datasource.yml:/etc/grafana/provisioning/datasources/prometheus.yml 52 | - ./config/dashboards/service.json:/var/lib/grafana/dashboards/service.json 53 | - ./config/dashboards.yml:/etc/grafana/provisioning/dashboards/all.yml 54 | ports: 55 | - 3000:3000 56 | depends_on: 57 | - prom 58 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/tests/fixtures/age_match.json: -------------------------------------------------------------------------------- 1 | {"Age": 30} -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/tests/fixtures/age_no_match.json: -------------------------------------------------------------------------------- 1 | {"Age": 300} 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/golang/protobuf/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/golang/protobuf/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/golang/protobuf/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/.gitignore: -------------------------------------------------------------------------------- 1 | .db 2 | *.test 3 | *~ 4 | *.swp 5 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/.travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | client_configure() { 6 | sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key 7 | } 8 | 9 | pgdg_repository() { 10 | local sourcelist='sources.list.d/postgresql.list' 11 | 12 | curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo apt-key add - 13 | echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist" 14 | sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update 15 | } 16 | 17 | postgresql_configure() { 18 | sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null <<-config 19 | local all all trust 20 | hostnossl all pqgossltest 127.0.0.1/32 reject 21 | hostnossl all pqgosslcert 127.0.0.1/32 reject 22 | hostssl all pqgossltest 127.0.0.1/32 trust 23 | hostssl all pqgosslcert 127.0.0.1/32 cert 24 | host all all 127.0.0.1/32 trust 25 | hostnossl all pqgossltest ::1/128 reject 26 | hostnossl all pqgosslcert ::1/128 reject 27 | hostssl all pqgossltest ::1/128 trust 28 | hostssl all pqgosslcert ::1/128 cert 29 | host all all ::1/128 trust 30 | config 31 | 32 | xargs sudo install -o postgres -g postgres -m 600 -t /var/lib/postgresql/$PGVERSION/main/ <<-certificates 33 | certs/root.crt 34 | certs/server.crt 35 | certs/server.key 36 | certificates 37 | 38 | sort -VCu <<-versions || 39 | $PGVERSION 40 | 9.2 41 | versions 42 | sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null <<-config 43 | ssl_ca_file = 'root.crt' 44 | ssl_cert_file = 'server.crt' 45 | ssl_key_file = 'server.key' 46 | config 47 | 48 | echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null 49 | 50 | sudo service postgresql restart 51 | } 52 | 53 | postgresql_install() { 54 | xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages 55 | postgresql-$PGVERSION 56 | postgresql-server-dev-$PGVERSION 57 | postgresql-contrib-$PGVERSION 58 | packages 59 | } 60 | 61 | postgresql_uninstall() { 62 | sudo service postgresql stop 63 | xargs sudo apt-get -y --purge remove <<-packages 64 | libpq-dev 65 | libpq5 66 | postgresql 67 | postgresql-client-common 68 | postgresql-common 69 | packages 70 | sudo rm -rf /var/lib/postgresql 71 | } 72 | 73 | megacheck_install() { 74 | # Lock megacheck version at $MEGACHECK_VERSION to prevent spontaneous 75 | # new error messages in old code. 76 | go get -d honnef.co/go/tools/... 77 | git -C $GOPATH/src/honnef.co/go/tools/ checkout $MEGACHECK_VERSION 78 | go install honnef.co/go/tools/cmd/megacheck 79 | megacheck --version 80 | } 81 | 82 | golint_install() { 83 | go get github.com/golang/lint/golint 84 | } 85 | 86 | $1 87 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.8.x 5 | - 1.9.x 6 | - 1.10.x 7 | - master 8 | 9 | sudo: true 10 | 11 | env: 12 | global: 13 | - PGUSER=postgres 14 | - PQGOSSLTESTS=1 15 | - PQSSLCERTTEST_PATH=$PWD/certs 16 | - PGHOST=127.0.0.1 17 | - MEGACHECK_VERSION=2017.2.2 18 | matrix: 19 | - PGVERSION=10 20 | - PGVERSION=9.6 21 | - PGVERSION=9.5 22 | - PGVERSION=9.4 23 | - PGVERSION=9.3 24 | - PGVERSION=9.2 25 | - PGVERSION=9.1 26 | - PGVERSION=9.0 27 | 28 | before_install: 29 | - ./.travis.sh postgresql_uninstall 30 | - ./.travis.sh pgdg_repository 31 | - ./.travis.sh postgresql_install 32 | - ./.travis.sh postgresql_configure 33 | - ./.travis.sh client_configure 34 | - ./.travis.sh megacheck_install 35 | - ./.travis.sh golint_install 36 | - go get golang.org/x/tools/cmd/goimports 37 | 38 | before_script: 39 | - createdb pqgotest 40 | - createuser -DRS pqgossltest 41 | - createuser -DRS pqgosslcert 42 | 43 | script: 44 | - > 45 | goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' 46 | - go vet ./... 47 | - megacheck -go 1.8 ./... 48 | - golint ./... 49 | - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... 50 | - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... 51 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to pq 2 | 3 | `pq` has a backlog of pull requests, but contributions are still very 4 | much welcome. You can help with patch review, submitting bug reports, 5 | or adding new functionality. There is no formal style guide, but 6 | please conform to the style of existing code and general Go formatting 7 | conventions when submitting patches. 8 | 9 | ### Patch review 10 | 11 | Help review existing open pull requests by commenting on the code or 12 | proposed functionality. 13 | 14 | ### Bug reports 15 | 16 | We appreciate any bug reports, but especially ones with self-contained 17 | (doesn't depend on code outside of pq), minimal (can't be simplified 18 | further) test cases. It's especially helpful if you can submit a pull 19 | request with just the failing test case (you'll probably want to 20 | pattern it after the tests in 21 | [conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). 22 | 23 | ### New functionality 24 | 25 | There are a number of pending patches for new functionality, so 26 | additional feature patches will take a while to merge. Still, patches 27 | are generally reviewed based on usefulness and complexity in addition 28 | to time-in-queue, so if you have a knockout idea, take a shot. Feel 29 | free to open an issue discussion your proposed patch beforehand. 30 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2013, 'pq' Contributors 2 | Portions Copyright (C) 2011 Blake Mizerany 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/README.md: -------------------------------------------------------------------------------- 1 | # pq - A pure Go postgres driver for Go's database/sql package 2 | 3 | [![GoDoc](https://godoc.org/github.com/lib/pq?status.svg)](https://godoc.org/github.com/lib/pq) 4 | [![Build Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq) 5 | 6 | ## Install 7 | 8 | go get github.com/lib/pq 9 | 10 | ## Docs 11 | 12 | For detailed documentation and basic usage examples, please see the package 13 | documentation at . 14 | 15 | ## Tests 16 | 17 | `go test` is used for testing. See [TESTS.md](TESTS.md) for more details. 18 | 19 | ## Features 20 | 21 | * SSL 22 | * Handles bad connections for `database/sql` 23 | * Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`) 24 | * Scan binary blobs correctly (i.e. `bytea`) 25 | * Package for `hstore` support 26 | * COPY FROM support 27 | * pq.ParseURL for converting urls to connection strings for sql.Open. 28 | * Many libpq compatible environment variables 29 | * Unix socket support 30 | * Notifications: `LISTEN`/`NOTIFY` 31 | * pgpass support 32 | 33 | ## Future / Things you can help with 34 | 35 | * Better COPY FROM / COPY TO (see discussion in #181) 36 | 37 | ## Thank you (alphabetical) 38 | 39 | Some of these contributors are from the original library `bmizerany/pq.go` whose 40 | code still exists in here. 41 | 42 | * Andy Balholm (andybalholm) 43 | * Ben Berkert (benburkert) 44 | * Benjamin Heatwole (bheatwole) 45 | * Bill Mill (llimllib) 46 | * Bjørn Madsen (aeons) 47 | * Blake Gentry (bgentry) 48 | * Brad Fitzpatrick (bradfitz) 49 | * Charlie Melbye (cmelbye) 50 | * Chris Bandy (cbandy) 51 | * Chris Gilling (cgilling) 52 | * Chris Walsh (cwds) 53 | * Dan Sosedoff (sosedoff) 54 | * Daniel Farina (fdr) 55 | * Eric Chlebek (echlebek) 56 | * Eric Garrido (minusnine) 57 | * Eric Urban (hydrogen18) 58 | * Everyone at The Go Team 59 | * Evan Shaw (edsrzf) 60 | * Ewan Chou (coocood) 61 | * Fazal Majid (fazalmajid) 62 | * Federico Romero (federomero) 63 | * Fumin (fumin) 64 | * Gary Burd (garyburd) 65 | * Heroku (heroku) 66 | * James Pozdena (jpoz) 67 | * Jason McVetta (jmcvetta) 68 | * Jeremy Jay (pbnjay) 69 | * Joakim Sernbrant (serbaut) 70 | * John Gallagher (jgallagher) 71 | * Jonathan Rudenberg (titanous) 72 | * Joël Stemmer (jstemmer) 73 | * Kamil Kisiel (kisielk) 74 | * Kelly Dunn (kellydunn) 75 | * Keith Rarick (kr) 76 | * Kir Shatrov (kirs) 77 | * Lann Martin (lann) 78 | * Maciek Sakrejda (uhoh-itsmaciek) 79 | * Marc Brinkmann (mbr) 80 | * Marko Tiikkaja (johto) 81 | * Matt Newberry (MattNewberry) 82 | * Matt Robenolt (mattrobenolt) 83 | * Martin Olsen (martinolsen) 84 | * Mike Lewis (mikelikespie) 85 | * Nicolas Patry (Narsil) 86 | * Oliver Tonnhofer (olt) 87 | * Patrick Hayes (phayes) 88 | * Paul Hammond (paulhammond) 89 | * Ryan Smith (ryandotsmith) 90 | * Samuel Stauffer (samuel) 91 | * Timothée Peignier (cyberdelia) 92 | * Travis Cline (tmc) 93 | * TruongSinh Tran-Nguyen (truongsinh) 94 | * Yaismel Miranda (ympons) 95 | * notedit (notedit) 96 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/TESTS.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | ## Running Tests 4 | 5 | `go test` is used for testing. A running PostgreSQL 6 | server is required, with the ability to log in. The 7 | database to connect to test with is "pqgotest," on 8 | "localhost" but these can be overridden using [environment 9 | variables](https://www.postgresql.org/docs/9.3/static/libpq-envars.html). 10 | 11 | Example: 12 | 13 | PGHOST=/run/postgresql go test 14 | 15 | ## Benchmarks 16 | 17 | A benchmark suite can be run as part of the tests: 18 | 19 | go test -bench . 20 | 21 | ## Example setup (Docker) 22 | 23 | Run a postgres container: 24 | 25 | ``` 26 | docker run --expose 5432:5432 postgres 27 | ``` 28 | 29 | Run tests: 30 | 31 | ``` 32 | PGHOST=localhost PGPORT=5432 PGUSER=postgres PGSSLMODE=disable PGDATABASE=postgres go test 33 | ``` 34 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/buf.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | 7 | "github.com/lib/pq/oid" 8 | ) 9 | 10 | type readBuf []byte 11 | 12 | func (b *readBuf) int32() (n int) { 13 | n = int(int32(binary.BigEndian.Uint32(*b))) 14 | *b = (*b)[4:] 15 | return 16 | } 17 | 18 | func (b *readBuf) oid() (n oid.Oid) { 19 | n = oid.Oid(binary.BigEndian.Uint32(*b)) 20 | *b = (*b)[4:] 21 | return 22 | } 23 | 24 | // N.B: this is actually an unsigned 16-bit integer, unlike int32 25 | func (b *readBuf) int16() (n int) { 26 | n = int(binary.BigEndian.Uint16(*b)) 27 | *b = (*b)[2:] 28 | return 29 | } 30 | 31 | func (b *readBuf) string() string { 32 | i := bytes.IndexByte(*b, 0) 33 | if i < 0 { 34 | errorf("invalid message format; expected string terminator") 35 | } 36 | s := (*b)[:i] 37 | *b = (*b)[i+1:] 38 | return string(s) 39 | } 40 | 41 | func (b *readBuf) next(n int) (v []byte) { 42 | v = (*b)[:n] 43 | *b = (*b)[n:] 44 | return 45 | } 46 | 47 | func (b *readBuf) byte() byte { 48 | return b.next(1)[0] 49 | } 50 | 51 | type writeBuf struct { 52 | buf []byte 53 | pos int 54 | } 55 | 56 | func (b *writeBuf) int32(n int) { 57 | x := make([]byte, 4) 58 | binary.BigEndian.PutUint32(x, uint32(n)) 59 | b.buf = append(b.buf, x...) 60 | } 61 | 62 | func (b *writeBuf) int16(n int) { 63 | x := make([]byte, 2) 64 | binary.BigEndian.PutUint16(x, uint16(n)) 65 | b.buf = append(b.buf, x...) 66 | } 67 | 68 | func (b *writeBuf) string(s string) { 69 | b.buf = append(b.buf, (s + "\000")...) 70 | } 71 | 72 | func (b *writeBuf) byte(c byte) { 73 | b.buf = append(b.buf, c) 74 | } 75 | 76 | func (b *writeBuf) bytes(v []byte) { 77 | b.buf = append(b.buf, v...) 78 | } 79 | 80 | func (b *writeBuf) wrap() []byte { 81 | p := b.buf[b.pos:] 82 | binary.BigEndian.PutUint32(p, uint32(len(p))) 83 | return b.buf 84 | } 85 | 86 | func (b *writeBuf) next(c byte) { 87 | p := b.buf[b.pos:] 88 | binary.BigEndian.PutUint32(p, uint32(len(p))) 89 | b.pos = len(b.buf) + 1 90 | b.buf = append(b.buf, c, 0, 0, 0, 0) 91 | } 92 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/conn_go18.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package pq 4 | 5 | import ( 6 | "context" 7 | "database/sql" 8 | "database/sql/driver" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | ) 13 | 14 | // Implement the "QueryerContext" interface 15 | func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 16 | list := make([]driver.Value, len(args)) 17 | for i, nv := range args { 18 | list[i] = nv.Value 19 | } 20 | finish := cn.watchCancel(ctx) 21 | r, err := cn.query(query, list) 22 | if err != nil { 23 | if finish != nil { 24 | finish() 25 | } 26 | return nil, err 27 | } 28 | r.finish = finish 29 | return r, nil 30 | } 31 | 32 | // Implement the "ExecerContext" interface 33 | func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 34 | list := make([]driver.Value, len(args)) 35 | for i, nv := range args { 36 | list[i] = nv.Value 37 | } 38 | 39 | if finish := cn.watchCancel(ctx); finish != nil { 40 | defer finish() 41 | } 42 | 43 | return cn.Exec(query, list) 44 | } 45 | 46 | // Implement the "ConnBeginTx" interface 47 | func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 48 | var mode string 49 | 50 | switch sql.IsolationLevel(opts.Isolation) { 51 | case sql.LevelDefault: 52 | // Don't touch mode: use the server's default 53 | case sql.LevelReadUncommitted: 54 | mode = " ISOLATION LEVEL READ UNCOMMITTED" 55 | case sql.LevelReadCommitted: 56 | mode = " ISOLATION LEVEL READ COMMITTED" 57 | case sql.LevelRepeatableRead: 58 | mode = " ISOLATION LEVEL REPEATABLE READ" 59 | case sql.LevelSerializable: 60 | mode = " ISOLATION LEVEL SERIALIZABLE" 61 | default: 62 | return nil, fmt.Errorf("pq: isolation level not supported: %d", opts.Isolation) 63 | } 64 | 65 | if opts.ReadOnly { 66 | mode += " READ ONLY" 67 | } else { 68 | mode += " READ WRITE" 69 | } 70 | 71 | tx, err := cn.begin(mode) 72 | if err != nil { 73 | return nil, err 74 | } 75 | cn.txnFinish = cn.watchCancel(ctx) 76 | return tx, nil 77 | } 78 | 79 | func (cn *conn) watchCancel(ctx context.Context) func() { 80 | if done := ctx.Done(); done != nil { 81 | finished := make(chan struct{}) 82 | go func() { 83 | select { 84 | case <-done: 85 | _ = cn.cancel() 86 | finished <- struct{}{} 87 | case <-finished: 88 | } 89 | }() 90 | return func() { 91 | select { 92 | case <-finished: 93 | case finished <- struct{}{}: 94 | } 95 | } 96 | } 97 | return nil 98 | } 99 | 100 | func (cn *conn) cancel() error { 101 | c, err := dial(cn.dialer, cn.opts) 102 | if err != nil { 103 | return err 104 | } 105 | defer c.Close() 106 | 107 | { 108 | can := conn{ 109 | c: c, 110 | } 111 | err = can.ssl(cn.opts) 112 | if err != nil { 113 | return err 114 | } 115 | 116 | w := can.writeBuf(0) 117 | w.int32(80877102) // cancel request code 118 | w.int32(cn.processID) 119 | w.int32(cn.secretKey) 120 | 121 | if err := can.sendStartupPacket(w); err != nil { 122 | return err 123 | } 124 | } 125 | 126 | // Read until EOF to ensure that the server received the cancel. 127 | { 128 | _, err := io.Copy(ioutil.Discard, c) 129 | return err 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/connector.go: -------------------------------------------------------------------------------- 1 | // +build go1.10 2 | 3 | package pq 4 | 5 | import ( 6 | "context" 7 | "database/sql/driver" 8 | ) 9 | 10 | // Connector represents a fixed configuration for the pq driver with a given 11 | // name. Connector satisfies the database/sql/driver Connector interface and 12 | // can be used to create any number of DB Conn's via the database/sql OpenDB 13 | // function. 14 | // 15 | // See https://golang.org/pkg/database/sql/driver/#Connector. 16 | // See https://golang.org/pkg/database/sql/#OpenDB. 17 | type connector struct { 18 | name string 19 | } 20 | 21 | // Connect returns a connection to the database using the fixed configuration 22 | // of this Connector. Context is not used. 23 | func (c *connector) Connect(_ context.Context) (driver.Conn, error) { 24 | return (&Driver{}).Open(c.name) 25 | } 26 | 27 | // Driver returnst the underlying driver of this Connector. 28 | func (c *connector) Driver() driver.Driver { 29 | return &Driver{} 30 | } 31 | 32 | var _ driver.Connector = &connector{} 33 | 34 | // NewConnector returns a connector for the pq driver in a fixed configuration 35 | // with the given name. The returned connector can be used to create any number 36 | // of equivalent Conn's. The returned connector is intended to be used with 37 | // database/sql.OpenDB. 38 | // 39 | // See https://golang.org/pkg/database/sql/driver/#Connector. 40 | // See https://golang.org/pkg/database/sql/#OpenDB. 41 | func NewConnector(name string) (driver.Connector, error) { 42 | return &connector{name: name}, nil 43 | } 44 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/lib/pq 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/oid/doc.go: -------------------------------------------------------------------------------- 1 | // Package oid contains OID constants 2 | // as defined by the Postgres server. 3 | package oid 4 | 5 | // Oid is a Postgres Object ID. 6 | type Oid uint32 7 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/oid/gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Generate the table of OID values 4 | // Run with 'go run gen.go'. 5 | package main 6 | 7 | import ( 8 | "database/sql" 9 | "fmt" 10 | "log" 11 | "os" 12 | "os/exec" 13 | "strings" 14 | 15 | _ "github.com/lib/pq" 16 | ) 17 | 18 | // OID represent a postgres Object Identifier Type. 19 | type OID struct { 20 | ID int 21 | Type string 22 | } 23 | 24 | // Name returns an upper case version of the oid type. 25 | func (o OID) Name() string { 26 | return strings.ToUpper(o.Type) 27 | } 28 | 29 | func main() { 30 | datname := os.Getenv("PGDATABASE") 31 | sslmode := os.Getenv("PGSSLMODE") 32 | 33 | if datname == "" { 34 | os.Setenv("PGDATABASE", "pqgotest") 35 | } 36 | 37 | if sslmode == "" { 38 | os.Setenv("PGSSLMODE", "disable") 39 | } 40 | 41 | db, err := sql.Open("postgres", "") 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | rows, err := db.Query(` 46 | SELECT typname, oid 47 | FROM pg_type WHERE oid < 10000 48 | ORDER BY oid; 49 | `) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | oids := make([]*OID, 0) 54 | for rows.Next() { 55 | var oid OID 56 | if err = rows.Scan(&oid.Type, &oid.ID); err != nil { 57 | log.Fatal(err) 58 | } 59 | oids = append(oids, &oid) 60 | } 61 | if err = rows.Err(); err != nil { 62 | log.Fatal(err) 63 | } 64 | cmd := exec.Command("gofmt") 65 | cmd.Stderr = os.Stderr 66 | w, err := cmd.StdinPipe() 67 | if err != nil { 68 | log.Fatal(err) 69 | } 70 | f, err := os.Create("types.go") 71 | if err != nil { 72 | log.Fatal(err) 73 | } 74 | cmd.Stdout = f 75 | err = cmd.Start() 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.") 80 | fmt.Fprintln(w, "\npackage oid") 81 | fmt.Fprintln(w, "const (") 82 | for _, oid := range oids { 83 | fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID) 84 | } 85 | fmt.Fprintln(w, ")") 86 | fmt.Fprintln(w, "var TypeName = map[Oid]string{") 87 | for _, oid := range oids { 88 | fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name()) 89 | } 90 | fmt.Fprintln(w, "}") 91 | w.Close() 92 | cmd.Wait() 93 | } 94 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/rows.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "math" 5 | "reflect" 6 | "time" 7 | 8 | "github.com/lib/pq/oid" 9 | ) 10 | 11 | const headerSize = 4 12 | 13 | type fieldDesc struct { 14 | // The object ID of the data type. 15 | OID oid.Oid 16 | // The data type size (see pg_type.typlen). 17 | // Note that negative values denote variable-width types. 18 | Len int 19 | // The type modifier (see pg_attribute.atttypmod). 20 | // The meaning of the modifier is type-specific. 21 | Mod int 22 | } 23 | 24 | func (fd fieldDesc) Type() reflect.Type { 25 | switch fd.OID { 26 | case oid.T_int8: 27 | return reflect.TypeOf(int64(0)) 28 | case oid.T_int4: 29 | return reflect.TypeOf(int32(0)) 30 | case oid.T_int2: 31 | return reflect.TypeOf(int16(0)) 32 | case oid.T_varchar, oid.T_text: 33 | return reflect.TypeOf("") 34 | case oid.T_bool: 35 | return reflect.TypeOf(false) 36 | case oid.T_date, oid.T_time, oid.T_timetz, oid.T_timestamp, oid.T_timestamptz: 37 | return reflect.TypeOf(time.Time{}) 38 | case oid.T_bytea: 39 | return reflect.TypeOf([]byte(nil)) 40 | default: 41 | return reflect.TypeOf(new(interface{})).Elem() 42 | } 43 | } 44 | 45 | func (fd fieldDesc) Name() string { 46 | return oid.TypeName[fd.OID] 47 | } 48 | 49 | func (fd fieldDesc) Length() (length int64, ok bool) { 50 | switch fd.OID { 51 | case oid.T_text, oid.T_bytea: 52 | return math.MaxInt64, true 53 | case oid.T_varchar, oid.T_bpchar: 54 | return int64(fd.Mod - headerSize), true 55 | default: 56 | return 0, false 57 | } 58 | } 59 | 60 | func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) { 61 | switch fd.OID { 62 | case oid.T_numeric, oid.T__numeric: 63 | mod := fd.Mod - headerSize 64 | precision = int64((mod >> 16) & 0xffff) 65 | scale = int64(mod & 0xffff) 66 | return precision, scale, true 67 | default: 68 | return 0, 0, false 69 | } 70 | } 71 | 72 | // ColumnTypeScanType returns the value type that can be used to scan types into. 73 | func (rs *rows) ColumnTypeScanType(index int) reflect.Type { 74 | return rs.colTyps[index].Type() 75 | } 76 | 77 | // ColumnTypeDatabaseTypeName return the database system type name. 78 | func (rs *rows) ColumnTypeDatabaseTypeName(index int) string { 79 | return rs.colTyps[index].Name() 80 | } 81 | 82 | // ColumnTypeLength returns the length of the column type if the column is a 83 | // variable length type. If the column is not a variable length type ok 84 | // should return false. 85 | func (rs *rows) ColumnTypeLength(index int) (length int64, ok bool) { 86 | return rs.colTyps[index].Length() 87 | } 88 | 89 | // ColumnTypePrecisionScale should return the precision and scale for decimal 90 | // types. If not applicable, ok should be false. 91 | func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) { 92 | return rs.colTyps[index].PrecisionScale() 93 | } 94 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/ssl.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "crypto/tls" 5 | "crypto/x509" 6 | "io/ioutil" 7 | "net" 8 | "os" 9 | "os/user" 10 | "path/filepath" 11 | ) 12 | 13 | // ssl generates a function to upgrade a net.Conn based on the "sslmode" and 14 | // related settings. The function is nil when no upgrade should take place. 15 | func ssl(o values) (func(net.Conn) (net.Conn, error), error) { 16 | verifyCaOnly := false 17 | tlsConf := tls.Config{} 18 | switch mode := o["sslmode"]; mode { 19 | // "require" is the default. 20 | case "", "require": 21 | // We must skip TLS's own verification since it requires full 22 | // verification since Go 1.3. 23 | tlsConf.InsecureSkipVerify = true 24 | 25 | // From http://www.postgresql.org/docs/current/static/libpq-ssl.html: 26 | // 27 | // Note: For backwards compatibility with earlier versions of 28 | // PostgreSQL, if a root CA file exists, the behavior of 29 | // sslmode=require will be the same as that of verify-ca, meaning the 30 | // server certificate is validated against the CA. Relying on this 31 | // behavior is discouraged, and applications that need certificate 32 | // validation should always use verify-ca or verify-full. 33 | if sslrootcert, ok := o["sslrootcert"]; ok { 34 | if _, err := os.Stat(sslrootcert); err == nil { 35 | verifyCaOnly = true 36 | } else { 37 | delete(o, "sslrootcert") 38 | } 39 | } 40 | case "verify-ca": 41 | // We must skip TLS's own verification since it requires full 42 | // verification since Go 1.3. 43 | tlsConf.InsecureSkipVerify = true 44 | verifyCaOnly = true 45 | case "verify-full": 46 | tlsConf.ServerName = o["host"] 47 | case "disable": 48 | return nil, nil 49 | default: 50 | return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) 51 | } 52 | 53 | err := sslClientCertificates(&tlsConf, o) 54 | if err != nil { 55 | return nil, err 56 | } 57 | err = sslCertificateAuthority(&tlsConf, o) 58 | if err != nil { 59 | return nil, err 60 | } 61 | sslRenegotiation(&tlsConf) 62 | 63 | return func(conn net.Conn) (net.Conn, error) { 64 | client := tls.Client(conn, &tlsConf) 65 | if verifyCaOnly { 66 | err := sslVerifyCertificateAuthority(client, &tlsConf) 67 | if err != nil { 68 | return nil, err 69 | } 70 | } 71 | return client, nil 72 | }, nil 73 | } 74 | 75 | // sslClientCertificates adds the certificate specified in the "sslcert" and 76 | // "sslkey" settings, or if they aren't set, from the .postgresql directory 77 | // in the user's home directory. The configured files must exist and have 78 | // the correct permissions. 79 | func sslClientCertificates(tlsConf *tls.Config, o values) error { 80 | // user.Current() might fail when cross-compiling. We have to ignore the 81 | // error and continue without home directory defaults, since we wouldn't 82 | // know from where to load them. 83 | user, _ := user.Current() 84 | 85 | // In libpq, the client certificate is only loaded if the setting is not blank. 86 | // 87 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1036-L1037 88 | sslcert := o["sslcert"] 89 | if len(sslcert) == 0 && user != nil { 90 | sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt") 91 | } 92 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1045 93 | if len(sslcert) == 0 { 94 | return nil 95 | } 96 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1050:L1054 97 | if _, err := os.Stat(sslcert); os.IsNotExist(err) { 98 | return nil 99 | } else if err != nil { 100 | return err 101 | } 102 | 103 | // In libpq, the ssl key is only loaded if the setting is not blank. 104 | // 105 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L1123-L1222 106 | sslkey := o["sslkey"] 107 | if len(sslkey) == 0 && user != nil { 108 | sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key") 109 | } 110 | 111 | if len(sslkey) > 0 { 112 | if err := sslKeyPermissions(sslkey); err != nil { 113 | return err 114 | } 115 | } 116 | 117 | cert, err := tls.LoadX509KeyPair(sslcert, sslkey) 118 | if err != nil { 119 | return err 120 | } 121 | 122 | tlsConf.Certificates = []tls.Certificate{cert} 123 | return nil 124 | } 125 | 126 | // sslCertificateAuthority adds the RootCA specified in the "sslrootcert" setting. 127 | func sslCertificateAuthority(tlsConf *tls.Config, o values) error { 128 | // In libpq, the root certificate is only loaded if the setting is not blank. 129 | // 130 | // https://github.com/postgres/postgres/blob/REL9_6_2/src/interfaces/libpq/fe-secure-openssl.c#L950-L951 131 | if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 { 132 | tlsConf.RootCAs = x509.NewCertPool() 133 | 134 | cert, err := ioutil.ReadFile(sslrootcert) 135 | if err != nil { 136 | return err 137 | } 138 | 139 | if !tlsConf.RootCAs.AppendCertsFromPEM(cert) { 140 | return fmterrorf("couldn't parse pem in sslrootcert") 141 | } 142 | } 143 | 144 | return nil 145 | } 146 | 147 | // sslVerifyCertificateAuthority carries out a TLS handshake to the server and 148 | // verifies the presented certificate against the CA, i.e. the one specified in 149 | // sslrootcert or the system CA if sslrootcert was not specified. 150 | func sslVerifyCertificateAuthority(client *tls.Conn, tlsConf *tls.Config) error { 151 | err := client.Handshake() 152 | if err != nil { 153 | return err 154 | } 155 | certs := client.ConnectionState().PeerCertificates 156 | opts := x509.VerifyOptions{ 157 | DNSName: client.ConnectionState().ServerName, 158 | Intermediates: x509.NewCertPool(), 159 | Roots: tlsConf.RootCAs, 160 | } 161 | for i, cert := range certs { 162 | if i == 0 { 163 | continue 164 | } 165 | opts.Intermediates.AddCert(cert) 166 | } 167 | _, err = certs[0].Verify(opts) 168 | return err 169 | } 170 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/ssl_go1.7.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package pq 4 | 5 | import "crypto/tls" 6 | 7 | // Accept renegotiation requests initiated by the backend. 8 | // 9 | // Renegotiation was deprecated then removed from PostgreSQL 9.5, but 10 | // the default configuration of older versions has it enabled. Redshift 11 | // also initiates renegotiations and cannot be reconfigured. 12 | func sslRenegotiation(conf *tls.Config) { 13 | conf.Renegotiation = tls.RenegotiateFreelyAsClient 14 | } 15 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/ssl_permissions.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package pq 4 | 5 | import "os" 6 | 7 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 8 | // The key file should have very little access. 9 | // 10 | // libpq does not check key file permissions on Windows. 11 | func sslKeyPermissions(sslkey string) error { 12 | info, err := os.Stat(sslkey) 13 | if err != nil { 14 | return err 15 | } 16 | if info.Mode().Perm()&0077 != 0 { 17 | return ErrSSLKeyHasWorldPermissions 18 | } 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/ssl_renegotiation.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package pq 4 | 5 | import "crypto/tls" 6 | 7 | // Renegotiation is not supported by crypto/tls until Go 1.7. 8 | func sslRenegotiation(*tls.Config) {} 9 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/ssl_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package pq 4 | 5 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 6 | // The key file should have very little access. 7 | // 8 | // libpq does not check key file permissions on Windows. 9 | func sslKeyPermissions(string) error { return nil } 10 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/url.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | nurl "net/url" 7 | "sort" 8 | "strings" 9 | ) 10 | 11 | // ParseURL no longer needs to be used by clients of this library since supplying a URL as a 12 | // connection string to sql.Open() is now supported: 13 | // 14 | // sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") 15 | // 16 | // It remains exported here for backwards-compatibility. 17 | // 18 | // ParseURL converts a url to a connection string for driver.Open. 19 | // Example: 20 | // 21 | // "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" 22 | // 23 | // converts to: 24 | // 25 | // "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" 26 | // 27 | // A minimal example: 28 | // 29 | // "postgres://" 30 | // 31 | // This will be blank, causing driver.Open to use all of the defaults 32 | func ParseURL(url string) (string, error) { 33 | u, err := nurl.Parse(url) 34 | if err != nil { 35 | return "", err 36 | } 37 | 38 | if u.Scheme != "postgres" && u.Scheme != "postgresql" { 39 | return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) 40 | } 41 | 42 | var kvs []string 43 | escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) 44 | accrue := func(k, v string) { 45 | if v != "" { 46 | kvs = append(kvs, k+"="+escaper.Replace(v)) 47 | } 48 | } 49 | 50 | if u.User != nil { 51 | v := u.User.Username() 52 | accrue("user", v) 53 | 54 | v, _ = u.User.Password() 55 | accrue("password", v) 56 | } 57 | 58 | if host, port, err := net.SplitHostPort(u.Host); err != nil { 59 | accrue("host", u.Host) 60 | } else { 61 | accrue("host", host) 62 | accrue("port", port) 63 | } 64 | 65 | if u.Path != "" { 66 | accrue("dbname", u.Path[1:]) 67 | } 68 | 69 | q := u.Query() 70 | for k := range q { 71 | accrue(k, q.Get(k)) 72 | } 73 | 74 | sort.Strings(kvs) // Makes testing easier (not a performance concern) 75 | return strings.Join(kvs, " "), nil 76 | } 77 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/user_posix.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | 3 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun 4 | 5 | package pq 6 | 7 | import ( 8 | "os" 9 | "os/user" 10 | ) 11 | 12 | func userCurrent() (string, error) { 13 | u, err := user.Current() 14 | if err == nil { 15 | return u.Username, nil 16 | } 17 | 18 | name := os.Getenv("USER") 19 | if name != "" { 20 | return name, nil 21 | } 22 | 23 | return "", ErrCouldNotDetectUsername 24 | } 25 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/user_windows.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | package pq 3 | 4 | import ( 5 | "path/filepath" 6 | "syscall" 7 | ) 8 | 9 | // Perform Windows user name lookup identically to libpq. 10 | // 11 | // The PostgreSQL code makes use of the legacy Win32 function 12 | // GetUserName, and that function has not been imported into stock Go. 13 | // GetUserNameEx is available though, the difference being that a 14 | // wider range of names are available. To get the output to be the 15 | // same as GetUserName, only the base (or last) component of the 16 | // result is returned. 17 | func userCurrent() (string, error) { 18 | pw_name := make([]uint16, 128) 19 | pwname_size := uint32(len(pw_name)) - 1 20 | err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) 21 | if err != nil { 22 | return "", ErrCouldNotDetectUsername 23 | } 24 | s := syscall.UTF16ToString(pw_name) 25 | u := filepath.Base(s) 26 | return u, nil 27 | } 28 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/lib/pq/uuid.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | ) 7 | 8 | // decodeUUIDBinary interprets the binary format of a uuid, returning it in text format. 9 | func decodeUUIDBinary(src []byte) ([]byte, error) { 10 | if len(src) != 16 { 11 | return nil, fmt.Errorf("pq: unable to decode uuid; bad length: %d", len(src)) 12 | } 13 | 14 | dst := make([]byte, 36) 15 | dst[8], dst[13], dst[18], dst[23] = '-', '-', '-', '-' 16 | hex.Encode(dst[0:], src[0:4]) 17 | hex.Encode(dst[9:], src[4:6]) 18 | hex.Encode(dst[14:], src[6:8]) 19 | hex.Encode(dst[19:], src[8:10]) 20 | hex.Encode(dst[24:], src[10:16]) 21 | 22 | return dst, nil 23 | } 24 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt T. Proud (matt.proud@gmail.com) 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore: -------------------------------------------------------------------------------- 1 | cover.dat 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/NOTICE: -------------------------------------------------------------------------------- 1 | Prometheus instrumentation library for Go applications 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | 7 | 8 | The following components are included in this product: 9 | 10 | perks - a fork of https://github.com/bmizerany/perks 11 | https://github.com/beorn7/perks 12 | Copyright 2013-2015 Blake Mizerany, Björn Rabenstein 13 | See https://github.com/beorn7/perks/blob/master/README.md for license details. 14 | 15 | Go support for Protocol Buffers - Google's data interchange format 16 | http://github.com/golang/protobuf/ 17 | Copyright 2010 The Go Authors 18 | See source code for license details. 19 | 20 | Support for streaming Protocol Buffer messages for the Go language (golang). 21 | https://github.com/matttproud/golang_protobuf_extensions 22 | Copyright 2013 Matt T. Proud 23 | Licensed under the Apache License, Version 2.0 24 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/.gitignore: -------------------------------------------------------------------------------- 1 | command-line-arguments.test 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/README.md: -------------------------------------------------------------------------------- 1 | See [![go-doc](https://godoc.org/github.com/prometheus/client_golang/prometheus?status.svg)](https://godoc.org/github.com/prometheus/client_golang/prometheus). 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/collector.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Collector is the interface implemented by anything that can be used by 17 | // Prometheus to collect metrics. A Collector has to be registered for 18 | // collection. See Registerer.Register. 19 | // 20 | // The stock metrics provided by this package (Gauge, Counter, Summary, 21 | // Histogram, Untyped) are also Collectors (which only ever collect one metric, 22 | // namely itself). An implementer of Collector may, however, collect multiple 23 | // metrics in a coordinated fashion and/or create metrics on the fly. Examples 24 | // for collectors already implemented in this library are the metric vectors 25 | // (i.e. collection of multiple instances of the same Metric but with different 26 | // label values) like GaugeVec or SummaryVec, and the ExpvarCollector. 27 | type Collector interface { 28 | // Describe sends the super-set of all possible descriptors of metrics 29 | // collected by this Collector to the provided channel and returns once 30 | // the last descriptor has been sent. The sent descriptors fulfill the 31 | // consistency and uniqueness requirements described in the Desc 32 | // documentation. 33 | // 34 | // It is valid if one and the same Collector sends duplicate 35 | // descriptors. Those duplicates are simply ignored. However, two 36 | // different Collectors must not send duplicate descriptors. 37 | // 38 | // Sending no descriptor at all marks the Collector as “unchecked”, 39 | // i.e. no checks will be performed at registration time, and the 40 | // Collector may yield any Metric it sees fit in its Collect method. 41 | // 42 | // This method idempotently sends the same descriptors throughout the 43 | // lifetime of the Collector. It may be called concurrently and 44 | // therefore must be implemented in a concurrency safe way. 45 | // 46 | // If a Collector encounters an error while executing this method, it 47 | // must send an invalid descriptor (created with NewInvalidDesc) to 48 | // signal the error to the registry. 49 | Describe(chan<- *Desc) 50 | // Collect is called by the Prometheus registry when collecting 51 | // metrics. The implementation sends each collected metric via the 52 | // provided channel and returns once the last metric has been sent. The 53 | // descriptor of each sent metric is one of those returned by Describe 54 | // (unless the Collector is unchecked, see above). Returned metrics that 55 | // share the same descriptor must differ in their variable label 56 | // values. 57 | // 58 | // This method may be called concurrently and must therefore be 59 | // implemented in a concurrency safe way. Blocking occurs at the expense 60 | // of total performance of rendering all registered metrics. Ideally, 61 | // Collector implementations support concurrent readers. 62 | Collect(chan<- Metric) 63 | } 64 | 65 | // DescribeByCollect is a helper to implement the Describe method of a custom 66 | // Collector. It collects the metrics from the provided Collector and sends 67 | // their descriptors to the provided channel. 68 | // 69 | // If a Collector collects the same metrics throughout its lifetime, its 70 | // Describe method can simply be implemented as: 71 | // 72 | // func (c customCollector) Describe(ch chan<- *Desc) { 73 | // DescribeByCollect(c, ch) 74 | // } 75 | // 76 | // However, this will not work if the metrics collected change dynamically over 77 | // the lifetime of the Collector in a way that their combined set of descriptors 78 | // changes as well. The shortcut implementation will then violate the contract 79 | // of the Describe method. If a Collector sometimes collects no metrics at all 80 | // (for example vectors like CounterVec, GaugeVec, etc., which only collect 81 | // metrics after a metric with a fully specified label set has been accessed), 82 | // it might even get registered as an unchecked Collecter (cf. the Register 83 | // method of the Registerer interface). Hence, only use this shortcut 84 | // implementation of Describe if you are certain to fulfill the contract. 85 | // 86 | // The Collector example demonstrates a use of DescribeByCollect. 87 | func DescribeByCollect(c Collector, descs chan<- *Desc) { 88 | metrics := make(chan Metric) 89 | go func() { 90 | c.Collect(metrics) 91 | close(metrics) 92 | }() 93 | for m := range metrics { 94 | descs <- m.Desc() 95 | } 96 | } 97 | 98 | // selfCollector implements Collector for a single Metric so that the Metric 99 | // collects itself. Add it as an anonymous field to a struct that implements 100 | // Metric, and call init with the Metric itself as an argument. 101 | type selfCollector struct { 102 | self Metric 103 | } 104 | 105 | // init provides the selfCollector with a reference to the metric it is supposed 106 | // to collect. It is usually called within the factory function to create a 107 | // metric. See example. 108 | func (c *selfCollector) init(self Metric) { 109 | c.self = self 110 | } 111 | 112 | // Describe implements Collector. 113 | func (c *selfCollector) Describe(ch chan<- *Desc) { 114 | ch <- c.self.Desc() 115 | } 116 | 117 | // Collect implements Collector. 118 | func (c *selfCollector) Collect(ch chan<- Metric) { 119 | ch <- c.self 120 | } 121 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import ( 17 | "encoding/json" 18 | "expvar" 19 | ) 20 | 21 | type expvarCollector struct { 22 | exports map[string]*Desc 23 | } 24 | 25 | // NewExpvarCollector returns a newly allocated expvar Collector that still has 26 | // to be registered with a Prometheus registry. 27 | // 28 | // An expvar Collector collects metrics from the expvar interface. It provides a 29 | // quick way to expose numeric values that are already exported via expvar as 30 | // Prometheus metrics. Note that the data models of expvar and Prometheus are 31 | // fundamentally different, and that the expvar Collector is inherently slower 32 | // than native Prometheus metrics. Thus, the expvar Collector is probably great 33 | // for experiments and prototying, but you should seriously consider a more 34 | // direct implementation of Prometheus metrics for monitoring production 35 | // systems. 36 | // 37 | // The exports map has the following meaning: 38 | // 39 | // The keys in the map correspond to expvar keys, i.e. for every expvar key you 40 | // want to export as Prometheus metric, you need an entry in the exports 41 | // map. The descriptor mapped to each key describes how to export the expvar 42 | // value. It defines the name and the help string of the Prometheus metric 43 | // proxying the expvar value. The type will always be Untyped. 44 | // 45 | // For descriptors without variable labels, the expvar value must be a number or 46 | // a bool. The number is then directly exported as the Prometheus sample 47 | // value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values 48 | // that are not numbers or bools are silently ignored. 49 | // 50 | // If the descriptor has one variable label, the expvar value must be an expvar 51 | // map. The keys in the expvar map become the various values of the one 52 | // Prometheus label. The values in the expvar map must be numbers or bools again 53 | // as above. 54 | // 55 | // For descriptors with more than one variable label, the expvar must be a 56 | // nested expvar map, i.e. where the values of the topmost map are maps again 57 | // etc. until a depth is reached that corresponds to the number of labels. The 58 | // leaves of that structure must be numbers or bools as above to serve as the 59 | // sample values. 60 | // 61 | // Anything that does not fit into the scheme above is silently ignored. 62 | func NewExpvarCollector(exports map[string]*Desc) Collector { 63 | return &expvarCollector{ 64 | exports: exports, 65 | } 66 | } 67 | 68 | // Describe implements Collector. 69 | func (e *expvarCollector) Describe(ch chan<- *Desc) { 70 | for _, desc := range e.exports { 71 | ch <- desc 72 | } 73 | } 74 | 75 | // Collect implements Collector. 76 | func (e *expvarCollector) Collect(ch chan<- Metric) { 77 | for name, desc := range e.exports { 78 | var m Metric 79 | expVar := expvar.Get(name) 80 | if expVar == nil { 81 | continue 82 | } 83 | var v interface{} 84 | labels := make([]string, len(desc.variableLabels)) 85 | if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil { 86 | ch <- NewInvalidMetric(desc, err) 87 | continue 88 | } 89 | var processValue func(v interface{}, i int) 90 | processValue = func(v interface{}, i int) { 91 | if i >= len(labels) { 92 | copiedLabels := append(make([]string, 0, len(labels)), labels...) 93 | switch v := v.(type) { 94 | case float64: 95 | m = MustNewConstMetric(desc, UntypedValue, v, copiedLabels...) 96 | case bool: 97 | if v { 98 | m = MustNewConstMetric(desc, UntypedValue, 1, copiedLabels...) 99 | } else { 100 | m = MustNewConstMetric(desc, UntypedValue, 0, copiedLabels...) 101 | } 102 | default: 103 | return 104 | } 105 | ch <- m 106 | return 107 | } 108 | vm, ok := v.(map[string]interface{}) 109 | if !ok { 110 | return 111 | } 112 | for lv, val := range vm { 113 | labels[i] = lv 114 | processValue(val, i+1) 115 | } 116 | } 117 | processValue(v, 0) 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/fnv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | // 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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 internal 15 | 16 | import ( 17 | "sort" 18 | 19 | dto "github.com/prometheus/client_model/go" 20 | ) 21 | 22 | // metricSorter is a sortable slice of *dto.Metric. 23 | type metricSorter []*dto.Metric 24 | 25 | func (s metricSorter) Len() int { 26 | return len(s) 27 | } 28 | 29 | func (s metricSorter) Swap(i, j int) { 30 | s[i], s[j] = s[j], s[i] 31 | } 32 | 33 | func (s metricSorter) Less(i, j int) bool { 34 | if len(s[i].Label) != len(s[j].Label) { 35 | // This should not happen. The metrics are 36 | // inconsistent. However, we have to deal with the fact, as 37 | // people might use custom collectors or metric family injection 38 | // to create inconsistent metrics. So let's simply compare the 39 | // number of labels in this case. That will still yield 40 | // reproducible sorting. 41 | return len(s[i].Label) < len(s[j].Label) 42 | } 43 | for n, lp := range s[i].Label { 44 | vi := lp.GetValue() 45 | vj := s[j].Label[n].GetValue() 46 | if vi != vj { 47 | return vi < vj 48 | } 49 | } 50 | 51 | // We should never arrive here. Multiple metrics with the same 52 | // label set in the same scrape will lead to undefined ingestion 53 | // behavior. However, as above, we have to provide stable sorting 54 | // here, even for inconsistent metrics. So sort equal metrics 55 | // by their timestamp, with missing timestamps (implying "now") 56 | // coming last. 57 | if s[i].TimestampMs == nil { 58 | return false 59 | } 60 | if s[j].TimestampMs == nil { 61 | return true 62 | } 63 | return s[i].GetTimestampMs() < s[j].GetTimestampMs() 64 | } 65 | 66 | // NormalizeMetricFamilies returns a MetricFamily slice with empty 67 | // MetricFamilies pruned and the remaining MetricFamilies sorted by name within 68 | // the slice, with the contained Metrics sorted within each MetricFamily. 69 | func NormalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { 70 | for _, mf := range metricFamiliesByName { 71 | sort.Sort(metricSorter(mf.Metric)) 72 | } 73 | names := make([]string, 0, len(metricFamiliesByName)) 74 | for name, mf := range metricFamiliesByName { 75 | if len(mf.Metric) > 0 { 76 | names = append(names, name) 77 | } 78 | } 79 | sort.Strings(names) 80 | result := make([]*dto.MetricFamily, 0, len(names)) 81 | for _, name := range names { 82 | result = append(result, metricFamiliesByName[name]) 83 | } 84 | return result 85 | } 86 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/labels.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import ( 17 | "errors" 18 | "fmt" 19 | "strings" 20 | "unicode/utf8" 21 | 22 | "github.com/prometheus/common/model" 23 | ) 24 | 25 | // Labels represents a collection of label name -> value mappings. This type is 26 | // commonly used with the With(Labels) and GetMetricWith(Labels) methods of 27 | // metric vector Collectors, e.g.: 28 | // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) 29 | // 30 | // The other use-case is the specification of constant label pairs in Opts or to 31 | // create a Desc. 32 | type Labels map[string]string 33 | 34 | // reservedLabelPrefix is a prefix which is not legal in user-supplied 35 | // label names. 36 | const reservedLabelPrefix = "__" 37 | 38 | var errInconsistentCardinality = errors.New("inconsistent label cardinality") 39 | 40 | func makeInconsistentCardinalityError(fqName string, labels, labelValues []string) error { 41 | return fmt.Errorf( 42 | "%s: %q has %d variable labels named %q but %d values %q were provided", 43 | errInconsistentCardinality, fqName, 44 | len(labels), labels, 45 | len(labelValues), labelValues, 46 | ) 47 | } 48 | 49 | func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { 50 | if len(labels) != expectedNumberOfValues { 51 | return fmt.Errorf( 52 | "%s: expected %d label values but got %d in %#v", 53 | errInconsistentCardinality, expectedNumberOfValues, 54 | len(labels), labels, 55 | ) 56 | } 57 | 58 | for name, val := range labels { 59 | if !utf8.ValidString(val) { 60 | return fmt.Errorf("label %s: value %q is not valid UTF-8", name, val) 61 | } 62 | } 63 | 64 | return nil 65 | } 66 | 67 | func validateLabelValues(vals []string, expectedNumberOfValues int) error { 68 | if len(vals) != expectedNumberOfValues { 69 | return fmt.Errorf( 70 | "%s: expected %d label values but got %d in %#v", 71 | errInconsistentCardinality, expectedNumberOfValues, 72 | len(vals), vals, 73 | ) 74 | } 75 | 76 | for _, val := range vals { 77 | if !utf8.ValidString(val) { 78 | return fmt.Errorf("label value %q is not valid UTF-8", val) 79 | } 80 | } 81 | 82 | return nil 83 | } 84 | 85 | func checkLabelName(l string) bool { 86 | return model.LabelName(l).IsValid() && !strings.HasPrefix(l, reservedLabelPrefix) 87 | } 88 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/observer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | // Observer is the interface that wraps the Observe method, which is used by 17 | // Histogram and Summary to add observations. 18 | type Observer interface { 19 | Observe(float64) 20 | } 21 | 22 | // The ObserverFunc type is an adapter to allow the use of ordinary 23 | // functions as Observers. If f is a function with the appropriate 24 | // signature, ObserverFunc(f) is an Observer that calls f. 25 | // 26 | // This adapter is usually used in connection with the Timer type, and there are 27 | // two general use cases: 28 | // 29 | // The most common one is to use a Gauge as the Observer for a Timer. 30 | // See the "Gauge" Timer example. 31 | // 32 | // The more advanced use case is to create a function that dynamically decides 33 | // which Observer to use for observing the duration. See the "Complex" Timer 34 | // example. 35 | type ObserverFunc func(float64) 36 | 37 | // Observe calls f(value). It implements Observer. 38 | func (f ObserverFunc) Observe(value float64) { 39 | f(value) 40 | } 41 | 42 | // ObserverVec is an interface implemented by `HistogramVec` and `SummaryVec`. 43 | type ObserverVec interface { 44 | GetMetricWith(Labels) (Observer, error) 45 | GetMetricWithLabelValues(lvs ...string) (Observer, error) 46 | With(Labels) Observer 47 | WithLabelValues(...string) Observer 48 | CurryWith(Labels) (ObserverVec, error) 49 | MustCurryWith(Labels) ObserverVec 50 | 51 | Collector 52 | } 53 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator_pre_1_8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // +build !go1.8 15 | 16 | package promhttp 17 | 18 | import ( 19 | "io" 20 | "net/http" 21 | ) 22 | 23 | func newDelegator(w http.ResponseWriter, observeWriteHeaderFunc func(int)) delegator { 24 | d := &responseWriterDelegator{ 25 | ResponseWriter: w, 26 | observeWriteHeader: observeWriteHeaderFunc, 27 | } 28 | 29 | id := 0 30 | if _, ok := w.(http.CloseNotifier); ok { 31 | id += closeNotifier 32 | } 33 | if _, ok := w.(http.Flusher); ok { 34 | id += flusher 35 | } 36 | if _, ok := w.(http.Hijacker); ok { 37 | id += hijacker 38 | } 39 | if _, ok := w.(io.ReaderFrom); ok { 40 | id += readerFrom 41 | } 42 | 43 | return pickDelegator[id](d) 44 | } 45 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package promhttp 15 | 16 | import ( 17 | "net/http" 18 | "time" 19 | 20 | "github.com/prometheus/client_golang/prometheus" 21 | ) 22 | 23 | // The RoundTripperFunc type is an adapter to allow the use of ordinary 24 | // functions as RoundTrippers. If f is a function with the appropriate 25 | // signature, RountTripperFunc(f) is a RoundTripper that calls f. 26 | type RoundTripperFunc func(req *http.Request) (*http.Response, error) 27 | 28 | // RoundTrip implements the RoundTripper interface. 29 | func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { 30 | return rt(r) 31 | } 32 | 33 | // InstrumentRoundTripperInFlight is a middleware that wraps the provided 34 | // http.RoundTripper. It sets the provided prometheus.Gauge to the number of 35 | // requests currently handled by the wrapped http.RoundTripper. 36 | // 37 | // See the example for ExampleInstrumentRoundTripperDuration for example usage. 38 | func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc { 39 | return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { 40 | gauge.Inc() 41 | defer gauge.Dec() 42 | return next.RoundTrip(r) 43 | }) 44 | } 45 | 46 | // InstrumentRoundTripperCounter is a middleware that wraps the provided 47 | // http.RoundTripper to observe the request result with the provided CounterVec. 48 | // The CounterVec must have zero, one, or two non-const non-curried labels. For 49 | // those, the only allowed label names are "code" and "method". The function 50 | // panics otherwise. Partitioning of the CounterVec happens by HTTP status code 51 | // and/or HTTP method if the respective instance label names are present in the 52 | // CounterVec. For unpartitioned counting, use a CounterVec with zero labels. 53 | // 54 | // If the wrapped RoundTripper panics or returns a non-nil error, the Counter 55 | // is not incremented. 56 | // 57 | // See the example for ExampleInstrumentRoundTripperDuration for example usage. 58 | func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper) RoundTripperFunc { 59 | code, method := checkLabels(counter) 60 | 61 | return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { 62 | resp, err := next.RoundTrip(r) 63 | if err == nil { 64 | counter.With(labels(code, method, r.Method, resp.StatusCode)).Inc() 65 | } 66 | return resp, err 67 | }) 68 | } 69 | 70 | // InstrumentRoundTripperDuration is a middleware that wraps the provided 71 | // http.RoundTripper to observe the request duration with the provided 72 | // ObserverVec. The ObserverVec must have zero, one, or two non-const 73 | // non-curried labels. For those, the only allowed label names are "code" and 74 | // "method". The function panics otherwise. The Observe method of the Observer 75 | // in the ObserverVec is called with the request duration in 76 | // seconds. Partitioning happens by HTTP status code and/or HTTP method if the 77 | // respective instance label names are present in the ObserverVec. For 78 | // unpartitioned observations, use an ObserverVec with zero labels. Note that 79 | // partitioning of Histograms is expensive and should be used judiciously. 80 | // 81 | // If the wrapped RoundTripper panics or returns a non-nil error, no values are 82 | // reported. 83 | // 84 | // Note that this method is only guaranteed to never observe negative durations 85 | // if used with Go1.9+. 86 | func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper) RoundTripperFunc { 87 | code, method := checkLabels(obs) 88 | 89 | return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { 90 | start := time.Now() 91 | resp, err := next.RoundTrip(r) 92 | if err == nil { 93 | obs.With(labels(code, method, r.Method, resp.StatusCode)).Observe(time.Since(start).Seconds()) 94 | } 95 | return resp, err 96 | }) 97 | } 98 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client_1_8.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // +build go1.8 15 | 16 | package promhttp 17 | 18 | import ( 19 | "context" 20 | "crypto/tls" 21 | "net/http" 22 | "net/http/httptrace" 23 | "time" 24 | ) 25 | 26 | // InstrumentTrace is used to offer flexibility in instrumenting the available 27 | // httptrace.ClientTrace hook functions. Each function is passed a float64 28 | // representing the time in seconds since the start of the http request. A user 29 | // may choose to use separately buckets Histograms, or implement custom 30 | // instance labels on a per function basis. 31 | type InstrumentTrace struct { 32 | GotConn func(float64) 33 | PutIdleConn func(float64) 34 | GotFirstResponseByte func(float64) 35 | Got100Continue func(float64) 36 | DNSStart func(float64) 37 | DNSDone func(float64) 38 | ConnectStart func(float64) 39 | ConnectDone func(float64) 40 | TLSHandshakeStart func(float64) 41 | TLSHandshakeDone func(float64) 42 | WroteHeaders func(float64) 43 | Wait100Continue func(float64) 44 | WroteRequest func(float64) 45 | } 46 | 47 | // InstrumentRoundTripperTrace is a middleware that wraps the provided 48 | // RoundTripper and reports times to hook functions provided in the 49 | // InstrumentTrace struct. Hook functions that are not present in the provided 50 | // InstrumentTrace struct are ignored. Times reported to the hook functions are 51 | // time since the start of the request. Only with Go1.9+, those times are 52 | // guaranteed to never be negative. (Earlier Go versions are not using a 53 | // monotonic clock.) Note that partitioning of Histograms is expensive and 54 | // should be used judiciously. 55 | // 56 | // For hook functions that receive an error as an argument, no observations are 57 | // made in the event of a non-nil error value. 58 | // 59 | // See the example for ExampleInstrumentRoundTripperDuration for example usage. 60 | func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { 61 | return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { 62 | start := time.Now() 63 | 64 | trace := &httptrace.ClientTrace{ 65 | GotConn: func(_ httptrace.GotConnInfo) { 66 | if it.GotConn != nil { 67 | it.GotConn(time.Since(start).Seconds()) 68 | } 69 | }, 70 | PutIdleConn: func(err error) { 71 | if err != nil { 72 | return 73 | } 74 | if it.PutIdleConn != nil { 75 | it.PutIdleConn(time.Since(start).Seconds()) 76 | } 77 | }, 78 | DNSStart: func(_ httptrace.DNSStartInfo) { 79 | if it.DNSStart != nil { 80 | it.DNSStart(time.Since(start).Seconds()) 81 | } 82 | }, 83 | DNSDone: func(_ httptrace.DNSDoneInfo) { 84 | if it.DNSDone != nil { 85 | it.DNSDone(time.Since(start).Seconds()) 86 | } 87 | }, 88 | ConnectStart: func(_, _ string) { 89 | if it.ConnectStart != nil { 90 | it.ConnectStart(time.Since(start).Seconds()) 91 | } 92 | }, 93 | ConnectDone: func(_, _ string, err error) { 94 | if err != nil { 95 | return 96 | } 97 | if it.ConnectDone != nil { 98 | it.ConnectDone(time.Since(start).Seconds()) 99 | } 100 | }, 101 | GotFirstResponseByte: func() { 102 | if it.GotFirstResponseByte != nil { 103 | it.GotFirstResponseByte(time.Since(start).Seconds()) 104 | } 105 | }, 106 | Got100Continue: func() { 107 | if it.Got100Continue != nil { 108 | it.Got100Continue(time.Since(start).Seconds()) 109 | } 110 | }, 111 | TLSHandshakeStart: func() { 112 | if it.TLSHandshakeStart != nil { 113 | it.TLSHandshakeStart(time.Since(start).Seconds()) 114 | } 115 | }, 116 | TLSHandshakeDone: func(_ tls.ConnectionState, err error) { 117 | if err != nil { 118 | return 119 | } 120 | if it.TLSHandshakeDone != nil { 121 | it.TLSHandshakeDone(time.Since(start).Seconds()) 122 | } 123 | }, 124 | WroteHeaders: func() { 125 | if it.WroteHeaders != nil { 126 | it.WroteHeaders(time.Since(start).Seconds()) 127 | } 128 | }, 129 | Wait100Continue: func() { 130 | if it.Wait100Continue != nil { 131 | it.Wait100Continue(time.Since(start).Seconds()) 132 | } 133 | }, 134 | WroteRequest: func(_ httptrace.WroteRequestInfo) { 135 | if it.WroteRequest != nil { 136 | it.WroteRequest(time.Since(start).Seconds()) 137 | } 138 | }, 139 | } 140 | r = r.WithContext(httptrace.WithClientTrace(context.Background(), trace)) 141 | 142 | return next.RoundTrip(r) 143 | }) 144 | } 145 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/timer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package prometheus 15 | 16 | import "time" 17 | 18 | // Timer is a helper type to time functions. Use NewTimer to create new 19 | // instances. 20 | type Timer struct { 21 | begin time.Time 22 | observer Observer 23 | } 24 | 25 | // NewTimer creates a new Timer. The provided Observer is used to observe a 26 | // duration in seconds. Timer is usually used to time a function call in the 27 | // following way: 28 | // func TimeMe() { 29 | // timer := NewTimer(myHistogram) 30 | // defer timer.ObserveDuration() 31 | // // Do actual work. 32 | // } 33 | func NewTimer(o Observer) *Timer { 34 | return &Timer{ 35 | begin: time.Now(), 36 | observer: o, 37 | } 38 | } 39 | 40 | // ObserveDuration records the duration passed since the Timer was created with 41 | // NewTimer. It calls the Observe method of the Observer provided during 42 | // construction with the duration in seconds as an argument. ObserveDuration is 43 | // usually called with a defer statement. 44 | // 45 | // Note that this method is only guaranteed to never observe negative durations 46 | // if used with Go1.9+. 47 | func (t *Timer) ObserveDuration() { 48 | if t.observer != nil { 49 | t.observer.Observe(time.Since(t.begin).Seconds()) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | // UntypedOpts is an alias for Opts. See there for doc comments. 17 | type UntypedOpts Opts 18 | 19 | // UntypedFunc works like GaugeFunc but the collected metric is of type 20 | // "Untyped". UntypedFunc is useful to mirror an external metric of unknown 21 | // type. 22 | // 23 | // To create UntypedFunc instances, use NewUntypedFunc. 24 | type UntypedFunc interface { 25 | Metric 26 | Collector 27 | } 28 | 29 | // NewUntypedFunc creates a new UntypedFunc based on the provided 30 | // UntypedOpts. The value reported is determined by calling the given function 31 | // from within the Write method. Take into account that metric collection may 32 | // happen concurrently. If that results in concurrent calls to Write, like in 33 | // the case where an UntypedFunc is directly registered with Prometheus, the 34 | // provided function must be concurrency-safe. 35 | func NewUntypedFunc(opts UntypedOpts, function func() float64) UntypedFunc { 36 | return newValueFunc(NewDesc( 37 | BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), 38 | opts.Help, 39 | nil, 40 | opts.ConstLabels, 41 | ), UntypedValue, function) 42 | } 43 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/value.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 | "fmt" 18 | "sort" 19 | 20 | "github.com/golang/protobuf/proto" 21 | 22 | dto "github.com/prometheus/client_model/go" 23 | ) 24 | 25 | // ValueType is an enumeration of metric types that represent a simple value. 26 | type ValueType int 27 | 28 | // Possible values for the ValueType enum. 29 | const ( 30 | _ ValueType = iota 31 | CounterValue 32 | GaugeValue 33 | UntypedValue 34 | ) 35 | 36 | // valueFunc is a generic metric for simple values retrieved on collect time 37 | // from a function. It implements Metric and Collector. Its effective type is 38 | // determined by ValueType. This is a low-level building block used by the 39 | // library to back the implementations of CounterFunc, GaugeFunc, and 40 | // UntypedFunc. 41 | type valueFunc struct { 42 | selfCollector 43 | 44 | desc *Desc 45 | valType ValueType 46 | function func() float64 47 | labelPairs []*dto.LabelPair 48 | } 49 | 50 | // newValueFunc returns a newly allocated valueFunc with the given Desc and 51 | // ValueType. The value reported is determined by calling the given function 52 | // from within the Write method. Take into account that metric collection may 53 | // happen concurrently. If that results in concurrent calls to Write, like in 54 | // the case where a valueFunc is directly registered with Prometheus, the 55 | // provided function must be concurrency-safe. 56 | func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *valueFunc { 57 | result := &valueFunc{ 58 | desc: desc, 59 | valType: valueType, 60 | function: function, 61 | labelPairs: makeLabelPairs(desc, nil), 62 | } 63 | result.init(result) 64 | return result 65 | } 66 | 67 | func (v *valueFunc) Desc() *Desc { 68 | return v.desc 69 | } 70 | 71 | func (v *valueFunc) Write(out *dto.Metric) error { 72 | return populateMetric(v.valType, v.function(), v.labelPairs, out) 73 | } 74 | 75 | // NewConstMetric returns a metric with one fixed value that cannot be 76 | // changed. Users of this package will not have much use for it in regular 77 | // operations. However, when implementing custom Collectors, it is useful as a 78 | // throw-away metric that is generated on the fly to send it to Prometheus in 79 | // the Collect method. NewConstMetric returns an error if the length of 80 | // labelValues is not consistent with the variable labels in Desc or if Desc is 81 | // invalid. 82 | func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) { 83 | if desc.err != nil { 84 | return nil, desc.err 85 | } 86 | if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { 87 | return nil, err 88 | } 89 | return &constMetric{ 90 | desc: desc, 91 | valType: valueType, 92 | val: value, 93 | labelPairs: makeLabelPairs(desc, labelValues), 94 | }, nil 95 | } 96 | 97 | // MustNewConstMetric is a version of NewConstMetric that panics where 98 | // NewConstMetric would have returned an error. 99 | func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric { 100 | m, err := NewConstMetric(desc, valueType, value, labelValues...) 101 | if err != nil { 102 | panic(err) 103 | } 104 | return m 105 | } 106 | 107 | type constMetric struct { 108 | desc *Desc 109 | valType ValueType 110 | val float64 111 | labelPairs []*dto.LabelPair 112 | } 113 | 114 | func (m *constMetric) Desc() *Desc { 115 | return m.desc 116 | } 117 | 118 | func (m *constMetric) Write(out *dto.Metric) error { 119 | return populateMetric(m.valType, m.val, m.labelPairs, out) 120 | } 121 | 122 | func populateMetric( 123 | t ValueType, 124 | v float64, 125 | labelPairs []*dto.LabelPair, 126 | m *dto.Metric, 127 | ) error { 128 | m.Label = labelPairs 129 | switch t { 130 | case CounterValue: 131 | m.Counter = &dto.Counter{Value: proto.Float64(v)} 132 | case GaugeValue: 133 | m.Gauge = &dto.Gauge{Value: proto.Float64(v)} 134 | case UntypedValue: 135 | m.Untyped = &dto.Untyped{Value: proto.Float64(v)} 136 | default: 137 | return fmt.Errorf("encountered unknown type %v", t) 138 | } 139 | return nil 140 | } 141 | 142 | func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair { 143 | totalLen := len(desc.variableLabels) + len(desc.constLabelPairs) 144 | if totalLen == 0 { 145 | // Super fast path. 146 | return nil 147 | } 148 | if len(desc.variableLabels) == 0 { 149 | // Moderately fast path. 150 | return desc.constLabelPairs 151 | } 152 | labelPairs := make([]*dto.LabelPair, 0, totalLen) 153 | for i, n := range desc.variableLabels { 154 | labelPairs = append(labelPairs, &dto.LabelPair{ 155 | Name: proto.String(n), 156 | Value: proto.String(labelValues[i]), 157 | }) 158 | } 159 | labelPairs = append(labelPairs, desc.constLabelPairs...) 160 | sort.Sort(labelPairSorter(labelPairs)) 161 | return labelPairs 162 | } 163 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/client_golang/prometheus/wrap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | "fmt" 18 | "sort" 19 | 20 | "github.com/golang/protobuf/proto" 21 | 22 | dto "github.com/prometheus/client_model/go" 23 | ) 24 | 25 | // WrapRegistererWith returns a Registerer wrapping the provided 26 | // Registerer. Collectors registered with the returned Registerer will be 27 | // registered with the wrapped Registerer in a modified way. The modified 28 | // Collector adds the provided Labels to all Metrics it collects (as 29 | // ConstLabels). The Metrics collected by the unmodified Collector must not 30 | // duplicate any of those labels. 31 | // 32 | // WrapRegistererWith provides a way to add fixed labels to a subset of 33 | // Collectors. It should not be used to add fixed labels to all metrics exposed. 34 | // 35 | // The Collector example demonstrates a use of WrapRegistererWith. 36 | func WrapRegistererWith(labels Labels, reg Registerer) Registerer { 37 | return &wrappingRegisterer{ 38 | wrappedRegisterer: reg, 39 | labels: labels, 40 | } 41 | } 42 | 43 | // WrapRegistererWithPrefix returns a Registerer wrapping the provided 44 | // Registerer. Collectors registered with the returned Registerer will be 45 | // registered with the wrapped Registerer in a modified way. The modified 46 | // Collector adds the provided prefix to the name of all Metrics it collects. 47 | // 48 | // WrapRegistererWithPrefix is useful to have one place to prefix all metrics of 49 | // a sub-system. To make this work, register metrics of the sub-system with the 50 | // wrapping Registerer returned by WrapRegistererWithPrefix. It is rarely useful 51 | // to use the same prefix for all metrics exposed. In particular, do not prefix 52 | // metric names that are standardized across applications, as that would break 53 | // horizontal monitoring, for example the metrics provided by the Go collector 54 | // (see NewGoCollector) and the process collector (see NewProcessCollector). (In 55 | // fact, those metrics are already prefixed with “go_” or “process_”, 56 | // respectively.) 57 | func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer { 58 | return &wrappingRegisterer{ 59 | wrappedRegisterer: reg, 60 | prefix: prefix, 61 | } 62 | } 63 | 64 | type wrappingRegisterer struct { 65 | wrappedRegisterer Registerer 66 | prefix string 67 | labels Labels 68 | } 69 | 70 | func (r *wrappingRegisterer) Register(c Collector) error { 71 | return r.wrappedRegisterer.Register(&wrappingCollector{ 72 | wrappedCollector: c, 73 | prefix: r.prefix, 74 | labels: r.labels, 75 | }) 76 | } 77 | 78 | func (r *wrappingRegisterer) MustRegister(cs ...Collector) { 79 | for _, c := range cs { 80 | if err := r.Register(c); err != nil { 81 | panic(err) 82 | } 83 | } 84 | } 85 | 86 | func (r *wrappingRegisterer) Unregister(c Collector) bool { 87 | return r.wrappedRegisterer.Unregister(&wrappingCollector{ 88 | wrappedCollector: c, 89 | prefix: r.prefix, 90 | labels: r.labels, 91 | }) 92 | } 93 | 94 | type wrappingCollector struct { 95 | wrappedCollector Collector 96 | prefix string 97 | labels Labels 98 | } 99 | 100 | func (c *wrappingCollector) Collect(ch chan<- Metric) { 101 | wrappedCh := make(chan Metric) 102 | go func() { 103 | c.wrappedCollector.Collect(wrappedCh) 104 | close(wrappedCh) 105 | }() 106 | for m := range wrappedCh { 107 | ch <- &wrappingMetric{ 108 | wrappedMetric: m, 109 | prefix: c.prefix, 110 | labels: c.labels, 111 | } 112 | } 113 | } 114 | 115 | func (c *wrappingCollector) Describe(ch chan<- *Desc) { 116 | wrappedCh := make(chan *Desc) 117 | go func() { 118 | c.wrappedCollector.Describe(wrappedCh) 119 | close(wrappedCh) 120 | }() 121 | for desc := range wrappedCh { 122 | ch <- wrapDesc(desc, c.prefix, c.labels) 123 | } 124 | } 125 | 126 | type wrappingMetric struct { 127 | wrappedMetric Metric 128 | prefix string 129 | labels Labels 130 | } 131 | 132 | func (m *wrappingMetric) Desc() *Desc { 133 | return wrapDesc(m.wrappedMetric.Desc(), m.prefix, m.labels) 134 | } 135 | 136 | func (m *wrappingMetric) Write(out *dto.Metric) error { 137 | if err := m.wrappedMetric.Write(out); err != nil { 138 | return err 139 | } 140 | if len(m.labels) == 0 { 141 | // No wrapping labels. 142 | return nil 143 | } 144 | for ln, lv := range m.labels { 145 | out.Label = append(out.Label, &dto.LabelPair{ 146 | Name: proto.String(ln), 147 | Value: proto.String(lv), 148 | }) 149 | } 150 | sort.Sort(labelPairSorter(out.Label)) 151 | return nil 152 | } 153 | 154 | func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { 155 | constLabels := Labels{} 156 | for _, lp := range desc.constLabelPairs { 157 | constLabels[*lp.Name] = *lp.Value 158 | } 159 | for ln, lv := range labels { 160 | if _, alreadyUsed := constLabels[ln]; alreadyUsed { 161 | return &Desc{ 162 | fqName: desc.fqName, 163 | help: desc.help, 164 | variableLabels: desc.variableLabels, 165 | constLabelPairs: desc.constLabelPairs, 166 | err: fmt.Errorf("attempted wrapping with already existing label name %q", ln), 167 | } 168 | } 169 | constLabels[ln] = lv 170 | } 171 | // NewDesc will do remaining validations. 172 | newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) 173 | // Propagate errors if there was any. This will override any errer 174 | // created by NewDesc above, i.e. earlier errors get precedence. 175 | if desc.err != nil { 176 | newDesc.err = desc.err 177 | } 178 | return newDesc 179 | } 180 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/common/expfmt/expfmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package expfmt contains tools for reading and writing Prometheus metrics. 15 | package expfmt 16 | 17 | // Format specifies the HTTP content type of the different wire protocols. 18 | type Format string 19 | 20 | // Constants to assemble the Content-Type values for the different wire protocols. 21 | const ( 22 | TextVersion = "0.0.4" 23 | ProtoType = `application/vnd.google.protobuf` 24 | ProtoProtocol = `io.prometheus.client.MetricFamily` 25 | ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" 26 | 27 | // The Content-Type values for the different wire protocols. 28 | FmtUnknown Format = `` 29 | FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` 30 | FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` 31 | FmtProtoText Format = ProtoFmt + ` encoding=text` 32 | FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` 33 | ) 34 | 35 | const ( 36 | hdrContentType = "Content-Type" 37 | hdrAccept = "Accept" 38 | ) 39 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/common/model/labelset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | "sort" 20 | "strings" 21 | ) 22 | 23 | // A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet 24 | // may be fully-qualified down to the point where it may resolve to a single 25 | // Metric in the data store or not. All operations that occur within the realm 26 | // of a LabelSet can emit a vector of Metric entities to which the LabelSet may 27 | // match. 28 | type LabelSet map[LabelName]LabelValue 29 | 30 | // Validate checks whether all names and values in the label set 31 | // are valid. 32 | func (ls LabelSet) Validate() error { 33 | for ln, lv := range ls { 34 | if !ln.IsValid() { 35 | return fmt.Errorf("invalid name %q", ln) 36 | } 37 | if !lv.IsValid() { 38 | return fmt.Errorf("invalid value %q", lv) 39 | } 40 | } 41 | return nil 42 | } 43 | 44 | // Equal returns true iff both label sets have exactly the same key/value pairs. 45 | func (ls LabelSet) Equal(o LabelSet) bool { 46 | if len(ls) != len(o) { 47 | return false 48 | } 49 | for ln, lv := range ls { 50 | olv, ok := o[ln] 51 | if !ok { 52 | return false 53 | } 54 | if olv != lv { 55 | return false 56 | } 57 | } 58 | return true 59 | } 60 | 61 | // Before compares the metrics, using the following criteria: 62 | // 63 | // If m has fewer labels than o, it is before o. If it has more, it is not. 64 | // 65 | // If the number of labels is the same, the superset of all label names is 66 | // sorted alphanumerically. The first differing label pair found in that order 67 | // determines the outcome: If the label does not exist at all in m, then m is 68 | // before o, and vice versa. Otherwise the label value is compared 69 | // alphanumerically. 70 | // 71 | // If m and o are equal, the method returns false. 72 | func (ls LabelSet) Before(o LabelSet) bool { 73 | if len(ls) < len(o) { 74 | return true 75 | } 76 | if len(ls) > len(o) { 77 | return false 78 | } 79 | 80 | lns := make(LabelNames, 0, len(ls)+len(o)) 81 | for ln := range ls { 82 | lns = append(lns, ln) 83 | } 84 | for ln := range o { 85 | lns = append(lns, ln) 86 | } 87 | // It's probably not worth it to de-dup lns. 88 | sort.Sort(lns) 89 | for _, ln := range lns { 90 | mlv, ok := ls[ln] 91 | if !ok { 92 | return true 93 | } 94 | olv, ok := o[ln] 95 | if !ok { 96 | return false 97 | } 98 | if mlv < olv { 99 | return true 100 | } 101 | if mlv > olv { 102 | return false 103 | } 104 | } 105 | return false 106 | } 107 | 108 | // Clone returns a copy of the label set. 109 | func (ls LabelSet) Clone() LabelSet { 110 | lsn := make(LabelSet, len(ls)) 111 | for ln, lv := range ls { 112 | lsn[ln] = lv 113 | } 114 | return lsn 115 | } 116 | 117 | // Merge is a helper function to non-destructively merge two label sets. 118 | func (l LabelSet) Merge(other LabelSet) LabelSet { 119 | result := make(LabelSet, len(l)) 120 | 121 | for k, v := range l { 122 | result[k] = v 123 | } 124 | 125 | for k, v := range other { 126 | result[k] = v 127 | } 128 | 129 | return result 130 | } 131 | 132 | func (l LabelSet) String() string { 133 | lstrs := make([]string, 0, len(l)) 134 | for l, v := range l { 135 | lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v)) 136 | } 137 | 138 | sort.Strings(lstrs) 139 | return fmt.Sprintf("{%s}", strings.Join(lstrs, ", ")) 140 | } 141 | 142 | // Fingerprint returns the LabelSet's fingerprint. 143 | func (ls LabelSet) Fingerprint() Fingerprint { 144 | return labelSetToFingerprint(ls) 145 | } 146 | 147 | // FastFingerprint returns the LabelSet's Fingerprint calculated by a faster hashing 148 | // algorithm, which is, however, more susceptible to hash collisions. 149 | func (ls LabelSet) FastFingerprint() Fingerprint { 150 | return labelSetToFastFingerprint(ls) 151 | } 152 | 153 | // UnmarshalJSON implements the json.Unmarshaler interface. 154 | func (l *LabelSet) UnmarshalJSON(b []byte) error { 155 | var m map[LabelName]LabelValue 156 | if err := json.Unmarshal(b, &m); err != nil { 157 | return err 158 | } 159 | // encoding/json only unmarshals maps of the form map[string]T. It treats 160 | // LabelName as a string and does not call its UnmarshalJSON method. 161 | // Thus, we have to replicate the behavior here. 162 | for ln := range m { 163 | if !ln.IsValid() { 164 | return fmt.Errorf("%q is not a valid label name", ln) 165 | } 166 | } 167 | *l = LabelSet(m) 168 | return nil 169 | } 170 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/common/model/metric.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "regexp" 19 | "sort" 20 | "strings" 21 | ) 22 | 23 | var ( 24 | separator = []byte{0} 25 | // MetricNameRE is a regular expression matching valid metric 26 | // names. Note that the IsValidMetricName function performs the same 27 | // check but faster than a match with this regular expression. 28 | MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`) 29 | ) 30 | 31 | // A Metric is similar to a LabelSet, but the key difference is that a Metric is 32 | // a singleton and refers to one and only one stream of samples. 33 | type Metric LabelSet 34 | 35 | // Equal compares the metrics. 36 | func (m Metric) Equal(o Metric) bool { 37 | return LabelSet(m).Equal(LabelSet(o)) 38 | } 39 | 40 | // Before compares the metrics' underlying label sets. 41 | func (m Metric) Before(o Metric) bool { 42 | return LabelSet(m).Before(LabelSet(o)) 43 | } 44 | 45 | // Clone returns a copy of the Metric. 46 | func (m Metric) Clone() Metric { 47 | clone := make(Metric, len(m)) 48 | for k, v := range m { 49 | clone[k] = v 50 | } 51 | return clone 52 | } 53 | 54 | func (m Metric) String() string { 55 | metricName, hasName := m[MetricNameLabel] 56 | numLabels := len(m) - 1 57 | if !hasName { 58 | numLabels = len(m) 59 | } 60 | labelStrings := make([]string, 0, numLabels) 61 | for label, value := range m { 62 | if label != MetricNameLabel { 63 | labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value)) 64 | } 65 | } 66 | 67 | switch numLabels { 68 | case 0: 69 | if hasName { 70 | return string(metricName) 71 | } 72 | return "{}" 73 | default: 74 | sort.Strings(labelStrings) 75 | return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", ")) 76 | } 77 | } 78 | 79 | // Fingerprint returns a Metric's Fingerprint. 80 | func (m Metric) Fingerprint() Fingerprint { 81 | return LabelSet(m).Fingerprint() 82 | } 83 | 84 | // FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing 85 | // algorithm, which is, however, more susceptible to hash collisions. 86 | func (m Metric) FastFingerprint() Fingerprint { 87 | return LabelSet(m).FastFingerprint() 88 | } 89 | 90 | // IsValidMetricName returns true iff name matches the pattern of MetricNameRE. 91 | // This function, however, does not use MetricNameRE for the check but a much 92 | // faster hardcoded implementation. 93 | func IsValidMetricName(n LabelValue) bool { 94 | if len(n) == 0 { 95 | return false 96 | } 97 | for i, b := range n { 98 | if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) { 99 | return false 100 | } 101 | } 102 | return true 103 | } 104 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 definition in the Prometheus 63 | // 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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/.gitignore: -------------------------------------------------------------------------------- 1 | /fixtures/ 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Prometheus uses GitHub to manage reviews of pull requests. 4 | 5 | * If you have a trivial fix or improvement, go ahead and create a pull request, 6 | addressing (with `@...`) the maintainer of this repository (see 7 | [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request. 8 | 9 | * If you plan to do something more involved, first discuss your ideas 10 | on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers). 11 | This will avoid unnecessary work and surely give you and us a good deal 12 | of inspiration. 13 | 14 | * Relevant coding style guidelines are the [Go Code Review 15 | Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) 16 | and the _Formatting and style_ section of Peter Bourgon's [Go: Best 17 | Practices for Production 18 | Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style). 19 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | * Tobias Schmidt 2 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 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 | # Ensure GOBIN is not set during build so that promu is installed to the correct path 15 | unexport GOBIN 16 | 17 | GO ?= go 18 | GOFMT ?= $(GO)fmt 19 | FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) 20 | STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck 21 | pkgs = $(shell $(GO) list ./... | grep -v /vendor/) 22 | 23 | PREFIX ?= $(shell pwd) 24 | BIN_DIR ?= $(shell pwd) 25 | 26 | ifdef DEBUG 27 | bindata_flags = -debug 28 | endif 29 | 30 | STATICCHECK_IGNORE = 31 | 32 | all: format staticcheck build test 33 | 34 | style: 35 | @echo ">> checking code style" 36 | @! $(GOFMT) -d $(shell find . -path ./vendor -prune -o -name '*.go' -print) | grep '^' 37 | 38 | check_license: 39 | @echo ">> checking license header" 40 | @./scripts/check_license.sh 41 | 42 | test: fixtures/.unpacked sysfs/fixtures/.unpacked 43 | @echo ">> running all tests" 44 | @$(GO) test -race $(shell $(GO) list ./... | grep -v /vendor/ | grep -v examples) 45 | 46 | format: 47 | @echo ">> formatting code" 48 | @$(GO) fmt $(pkgs) 49 | 50 | vet: 51 | @echo ">> vetting code" 52 | @$(GO) vet $(pkgs) 53 | 54 | staticcheck: $(STATICCHECK) 55 | @echo ">> running staticcheck" 56 | @$(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) 57 | 58 | %/.unpacked: %.ttar 59 | ./ttar -C $(dir $*) -x -f $*.ttar 60 | touch $@ 61 | 62 | update_fixtures: fixtures.ttar sysfs/fixtures.ttar 63 | 64 | %fixtures.ttar: %/fixtures 65 | rm -v $(dir $*)fixtures/.unpacked 66 | ./ttar -C $(dir $*) -c -f $*fixtures.ttar fixtures/ 67 | 68 | $(FIRST_GOPATH)/bin/staticcheck: 69 | @GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck 70 | 71 | .PHONY: all style check_license format test vet staticcheck 72 | 73 | # Declaring the binaries at their default locations as PHONY targets is a hack 74 | # to ensure the latest version is downloaded on every make execution. 75 | # If this is not desired, copy/symlink these binaries to a different path and 76 | # set the respective environment variables. 77 | .PHONY: $(GOPATH)/bin/staticcheck 78 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/README.md: -------------------------------------------------------------------------------- 1 | # procfs 2 | 3 | This procfs package provides functions to retrieve system, kernel and process 4 | metrics from the pseudo-filesystem proc. 5 | 6 | *WARNING*: This package is a work in progress. Its API may still break in 7 | backwards-incompatible ways without warnings. Use it at your own risk. 8 | 9 | [![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs) 10 | [![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs) 11 | [![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs) 12 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/buddyinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "os" 21 | "strconv" 22 | "strings" 23 | ) 24 | 25 | // A BuddyInfo is the details parsed from /proc/buddyinfo. 26 | // The data is comprised of an array of free fragments of each size. 27 | // The sizes are 2^n*PAGE_SIZE, where n is the array index. 28 | type BuddyInfo struct { 29 | Node string 30 | Zone string 31 | Sizes []float64 32 | } 33 | 34 | // NewBuddyInfo reads the buddyinfo statistics. 35 | func NewBuddyInfo() ([]BuddyInfo, error) { 36 | fs, err := NewFS(DefaultMountPoint) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return fs.NewBuddyInfo() 42 | } 43 | 44 | // NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem. 45 | func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) { 46 | file, err := os.Open(fs.Path("buddyinfo")) 47 | if err != nil { 48 | return nil, err 49 | } 50 | defer file.Close() 51 | 52 | return parseBuddyInfo(file) 53 | } 54 | 55 | func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { 56 | var ( 57 | buddyInfo = []BuddyInfo{} 58 | scanner = bufio.NewScanner(r) 59 | bucketCount = -1 60 | ) 61 | 62 | for scanner.Scan() { 63 | var err error 64 | line := scanner.Text() 65 | parts := strings.Fields(line) 66 | 67 | if len(parts) < 4 { 68 | return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo") 69 | } 70 | 71 | node := strings.TrimRight(parts[1], ",") 72 | zone := strings.TrimRight(parts[3], ",") 73 | arraySize := len(parts[4:]) 74 | 75 | if bucketCount == -1 { 76 | bucketCount = arraySize 77 | } else { 78 | if bucketCount != arraySize { 79 | return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize) 80 | } 81 | } 82 | 83 | sizes := make([]float64, arraySize) 84 | for i := 0; i < arraySize; i++ { 85 | sizes[i], err = strconv.ParseFloat(parts[i+4], 64) 86 | if err != nil { 87 | return nil, fmt.Errorf("invalid value in buddyinfo: %s", err) 88 | } 89 | } 90 | 91 | buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes}) 92 | } 93 | 94 | return buddyInfo, scanner.Err() 95 | } 96 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/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 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/fs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "os" 19 | "path" 20 | 21 | "github.com/prometheus/procfs/nfs" 22 | "github.com/prometheus/procfs/xfs" 23 | ) 24 | 25 | // FS represents the pseudo-filesystem proc, which provides an interface to 26 | // kernel data structures. 27 | type FS string 28 | 29 | // DefaultMountPoint is the common mount point of the proc filesystem. 30 | const DefaultMountPoint = "/proc" 31 | 32 | // NewFS returns a new FS mounted under the given mountPoint. It will error 33 | // if the mount point can't be read. 34 | func NewFS(mountPoint string) (FS, error) { 35 | info, err := os.Stat(mountPoint) 36 | if err != nil { 37 | return "", fmt.Errorf("could not read %s: %s", mountPoint, err) 38 | } 39 | if !info.IsDir() { 40 | return "", fmt.Errorf("mount point %s is not a directory", mountPoint) 41 | } 42 | 43 | return FS(mountPoint), nil 44 | } 45 | 46 | // Path returns the path of the given subsystem relative to the procfs root. 47 | func (fs FS) Path(p ...string) string { 48 | return path.Join(append([]string{string(fs)}, p...)...) 49 | } 50 | 51 | // XFSStats retrieves XFS filesystem runtime statistics. 52 | func (fs FS) XFSStats() (*xfs.Stats, error) { 53 | f, err := os.Open(fs.Path("fs/xfs/stat")) 54 | if err != nil { 55 | return nil, err 56 | } 57 | defer f.Close() 58 | 59 | return xfs.ParseStats(f) 60 | } 61 | 62 | // NFSClientRPCStats retrieves NFS client RPC statistics. 63 | func (fs FS) NFSClientRPCStats() (*nfs.ClientRPCStats, error) { 64 | f, err := os.Open(fs.Path("net/rpc/nfs")) 65 | if err != nil { 66 | return nil, err 67 | } 68 | defer f.Close() 69 | 70 | return nfs.ParseClientRPCStats(f) 71 | } 72 | 73 | // NFSdServerRPCStats retrieves NFS daemon RPC statistics. 74 | func (fs FS) NFSdServerRPCStats() (*nfs.ServerRPCStats, error) { 75 | f, err := os.Open(fs.Path("net/rpc/nfsd")) 76 | if err != nil { 77 | return nil, err 78 | } 79 | defer f.Close() 80 | 81 | return nfs.ParseServerRPCStats(f) 82 | } 83 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/internal/util/parse.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 util 15 | 16 | import ( 17 | "io/ioutil" 18 | "strconv" 19 | "strings" 20 | ) 21 | 22 | // ParseUint32s parses a slice of strings into a slice of uint32s. 23 | func ParseUint32s(ss []string) ([]uint32, error) { 24 | us := make([]uint32, 0, len(ss)) 25 | for _, s := range ss { 26 | u, err := strconv.ParseUint(s, 10, 32) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | us = append(us, uint32(u)) 32 | } 33 | 34 | return us, nil 35 | } 36 | 37 | // ParseUint64s parses a slice of strings into a slice of uint64s. 38 | func ParseUint64s(ss []string) ([]uint64, error) { 39 | us := make([]uint64, 0, len(ss)) 40 | for _, s := range ss { 41 | u, err := strconv.ParseUint(s, 10, 64) 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | us = append(us, u) 47 | } 48 | 49 | return us, nil 50 | } 51 | 52 | // ReadUintFromFile reads a file and attempts to parse a uint64 from it. 53 | func ReadUintFromFile(path string) (uint64, error) { 54 | data, err := ioutil.ReadFile(path) 55 | if err != nil { 56 | return 0, err 57 | } 58 | return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) 59 | } 60 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 15 | 16 | package util 17 | 18 | import ( 19 | "bytes" 20 | "os" 21 | "syscall" 22 | ) 23 | 24 | // SysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly. 25 | // https://github.com/prometheus/node_exporter/pull/728/files 26 | func SysReadFile(file string) (string, error) { 27 | f, err := os.Open(file) 28 | if err != nil { 29 | return "", err 30 | } 31 | defer f.Close() 32 | 33 | // On some machines, hwmon drivers are broken and return EAGAIN. This causes 34 | // Go's ioutil.ReadFile implementation to poll forever. 35 | // 36 | // Since we either want to read data or bail immediately, do the simplest 37 | // possible read using syscall directly. 38 | b := make([]byte, 128) 39 | n, err := syscall.Read(int(f.Fd()), b) 40 | if err != nil { 41 | return "", err 42 | } 43 | 44 | return string(bytes.TrimSpace(b[:n])), nil 45 | } 46 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/mdstat.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "io/ioutil" 19 | "regexp" 20 | "strconv" 21 | "strings" 22 | ) 23 | 24 | var ( 25 | statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) 26 | buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`) 27 | ) 28 | 29 | // MDStat holds info parsed from /proc/mdstat. 30 | type MDStat struct { 31 | // Name of the device. 32 | Name string 33 | // activity-state of the device. 34 | ActivityState string 35 | // Number of active disks. 36 | DisksActive int64 37 | // Total number of disks the device consists of. 38 | DisksTotal int64 39 | // Number of blocks the device holds. 40 | BlocksTotal int64 41 | // Number of blocks on the device that are in sync. 42 | BlocksSynced int64 43 | } 44 | 45 | // ParseMDStat parses an mdstat-file and returns a struct with the relevant infos. 46 | func (fs FS) ParseMDStat() (mdstates []MDStat, err error) { 47 | mdStatusFilePath := fs.Path("mdstat") 48 | content, err := ioutil.ReadFile(mdStatusFilePath) 49 | if err != nil { 50 | return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 51 | } 52 | 53 | mdStates := []MDStat{} 54 | lines := strings.Split(string(content), "\n") 55 | for i, l := range lines { 56 | if l == "" { 57 | continue 58 | } 59 | if l[0] == ' ' { 60 | continue 61 | } 62 | if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") { 63 | continue 64 | } 65 | 66 | mainLine := strings.Split(l, " ") 67 | if len(mainLine) < 3 { 68 | return mdStates, fmt.Errorf("error parsing mdline: %s", l) 69 | } 70 | mdName := mainLine[0] 71 | activityState := mainLine[2] 72 | 73 | if len(lines) <= i+3 { 74 | return mdStates, fmt.Errorf( 75 | "error parsing %s: too few lines for md device %s", 76 | mdStatusFilePath, 77 | mdName, 78 | ) 79 | } 80 | 81 | active, total, size, err := evalStatusline(lines[i+1]) 82 | if err != nil { 83 | return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 84 | } 85 | 86 | // j is the line number of the syncing-line. 87 | j := i + 2 88 | if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line 89 | j = i + 3 90 | } 91 | 92 | // If device is syncing at the moment, get the number of currently 93 | // synced bytes, otherwise that number equals the size of the device. 94 | syncedBlocks := size 95 | if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") { 96 | syncedBlocks, err = evalBuildline(lines[j]) 97 | if err != nil { 98 | return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err) 99 | } 100 | } 101 | 102 | mdStates = append(mdStates, MDStat{ 103 | Name: mdName, 104 | ActivityState: activityState, 105 | DisksActive: active, 106 | DisksTotal: total, 107 | BlocksTotal: size, 108 | BlocksSynced: syncedBlocks, 109 | }) 110 | } 111 | 112 | return mdStates, nil 113 | } 114 | 115 | func evalStatusline(statusline string) (active, total, size int64, err error) { 116 | matches := statuslineRE.FindStringSubmatch(statusline) 117 | if len(matches) != 4 { 118 | return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline) 119 | } 120 | 121 | size, err = strconv.ParseInt(matches[1], 10, 64) 122 | if err != nil { 123 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 124 | } 125 | 126 | total, err = strconv.ParseInt(matches[2], 10, 64) 127 | if err != nil { 128 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 129 | } 130 | 131 | active, err = strconv.ParseInt(matches[3], 10, 64) 132 | if err != nil { 133 | return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err) 134 | } 135 | 136 | return active, total, size, nil 137 | } 138 | 139 | func evalBuildline(buildline string) (syncedBlocks int64, err error) { 140 | matches := buildlineRE.FindStringSubmatch(buildline) 141 | if len(matches) != 2 { 142 | return 0, fmt.Errorf("unexpected buildline: %s", buildline) 143 | } 144 | 145 | syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) 146 | if err != nil { 147 | return 0, fmt.Errorf("%s in buildline: %s", err, buildline) 148 | } 149 | 150 | return syncedBlocks, nil 151 | } 152 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/nfs/parse_nfs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 nfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "strings" 21 | 22 | "github.com/prometheus/procfs/internal/util" 23 | ) 24 | 25 | // ParseClientRPCStats returns stats read from /proc/net/rpc/nfs 26 | func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) { 27 | stats := &ClientRPCStats{} 28 | 29 | scanner := bufio.NewScanner(r) 30 | for scanner.Scan() { 31 | line := scanner.Text() 32 | parts := strings.Fields(scanner.Text()) 33 | // require at least 34 | if len(parts) < 2 { 35 | return nil, fmt.Errorf("invalid NFS metric line %q", line) 36 | } 37 | 38 | values, err := util.ParseUint64s(parts[1:]) 39 | if err != nil { 40 | return nil, fmt.Errorf("error parsing NFS metric line: %s", err) 41 | } 42 | 43 | switch metricLine := parts[0]; metricLine { 44 | case "net": 45 | stats.Network, err = parseNetwork(values) 46 | case "rpc": 47 | stats.ClientRPC, err = parseClientRPC(values) 48 | case "proc2": 49 | stats.V2Stats, err = parseV2Stats(values) 50 | case "proc3": 51 | stats.V3Stats, err = parseV3Stats(values) 52 | case "proc4": 53 | stats.ClientV4Stats, err = parseClientV4Stats(values) 54 | default: 55 | return nil, fmt.Errorf("unknown NFS metric line %q", metricLine) 56 | } 57 | if err != nil { 58 | return nil, fmt.Errorf("errors parsing NFS metric line: %s", err) 59 | } 60 | } 61 | 62 | if err := scanner.Err(); err != nil { 63 | return nil, fmt.Errorf("error scanning NFS file: %s", err) 64 | } 65 | 66 | return stats, nil 67 | } 68 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 nfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "strings" 21 | 22 | "github.com/prometheus/procfs/internal/util" 23 | ) 24 | 25 | // ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd 26 | func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) { 27 | stats := &ServerRPCStats{} 28 | 29 | scanner := bufio.NewScanner(r) 30 | for scanner.Scan() { 31 | line := scanner.Text() 32 | parts := strings.Fields(scanner.Text()) 33 | // require at least 34 | if len(parts) < 2 { 35 | return nil, fmt.Errorf("invalid NFSd metric line %q", line) 36 | } 37 | label := parts[0] 38 | 39 | var values []uint64 40 | var err error 41 | if label == "th" { 42 | if len(parts) < 3 { 43 | return nil, fmt.Errorf("invalid NFSd th metric line %q", line) 44 | } 45 | values, err = util.ParseUint64s(parts[1:3]) 46 | } else { 47 | values, err = util.ParseUint64s(parts[1:]) 48 | } 49 | if err != nil { 50 | return nil, fmt.Errorf("error parsing NFSd metric line: %s", err) 51 | } 52 | 53 | switch metricLine := parts[0]; metricLine { 54 | case "rc": 55 | stats.ReplyCache, err = parseReplyCache(values) 56 | case "fh": 57 | stats.FileHandles, err = parseFileHandles(values) 58 | case "io": 59 | stats.InputOutput, err = parseInputOutput(values) 60 | case "th": 61 | stats.Threads, err = parseThreads(values) 62 | case "ra": 63 | stats.ReadAheadCache, err = parseReadAheadCache(values) 64 | case "net": 65 | stats.Network, err = parseNetwork(values) 66 | case "rpc": 67 | stats.ServerRPC, err = parseServerRPC(values) 68 | case "proc2": 69 | stats.V2Stats, err = parseV2Stats(values) 70 | case "proc3": 71 | stats.V3Stats, err = parseV3Stats(values) 72 | case "proc4": 73 | stats.ServerV4Stats, err = parseServerV4Stats(values) 74 | case "proc4ops": 75 | stats.V4Ops, err = parseV4Ops(values) 76 | default: 77 | return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) 78 | } 79 | if err != nil { 80 | return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err) 81 | } 82 | } 83 | 84 | if err := scanner.Err(); err != nil { 85 | return nil, fmt.Errorf("error scanning NFSd file: %s", err) 86 | } 87 | 88 | return stats, nil 89 | } 90 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/proc_io.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "io/ioutil" 19 | "os" 20 | ) 21 | 22 | // ProcIO models the content of /proc//io. 23 | type ProcIO struct { 24 | // Chars read. 25 | RChar uint64 26 | // Chars written. 27 | WChar uint64 28 | // Read syscalls. 29 | SyscR uint64 30 | // Write syscalls. 31 | SyscW uint64 32 | // Bytes read. 33 | ReadBytes uint64 34 | // Bytes written. 35 | WriteBytes uint64 36 | // Bytes written, but taking into account truncation. See 37 | // Documentation/filesystems/proc.txt in the kernel sources for 38 | // detailed explanation. 39 | CancelledWriteBytes int64 40 | } 41 | 42 | // NewIO creates a new ProcIO instance from a given Proc instance. 43 | func (p Proc) NewIO() (ProcIO, error) { 44 | pio := ProcIO{} 45 | 46 | f, err := os.Open(p.path("io")) 47 | if err != nil { 48 | return pio, err 49 | } 50 | defer f.Close() 51 | 52 | data, err := ioutil.ReadAll(f) 53 | if err != nil { 54 | return pio, err 55 | } 56 | 57 | ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + 58 | "read_bytes: %d\nwrite_bytes: %d\n" + 59 | "cancelled_write_bytes: %d\n" 60 | 61 | _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, 62 | &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) 63 | 64 | return pio, err 65 | } 66 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/proc_limits.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "os" 20 | "regexp" 21 | "strconv" 22 | ) 23 | 24 | // ProcLimits represents the soft limits for each of the process's resource 25 | // limits. For more information see getrlimit(2): 26 | // http://man7.org/linux/man-pages/man2/getrlimit.2.html. 27 | type ProcLimits struct { 28 | // CPU time limit in seconds. 29 | CPUTime int64 30 | // Maximum size of files that the process may create. 31 | FileSize int64 32 | // Maximum size of the process's data segment (initialized data, 33 | // uninitialized data, and heap). 34 | DataSize int64 35 | // Maximum size of the process stack in bytes. 36 | StackSize int64 37 | // Maximum size of a core file. 38 | CoreFileSize int64 39 | // Limit of the process's resident set in pages. 40 | ResidentSet int64 41 | // Maximum number of processes that can be created for the real user ID of 42 | // the calling process. 43 | Processes int64 44 | // Value one greater than the maximum file descriptor number that can be 45 | // opened by this process. 46 | OpenFiles int64 47 | // Maximum number of bytes of memory that may be locked into RAM. 48 | LockedMemory int64 49 | // Maximum size of the process's virtual memory address space in bytes. 50 | AddressSpace int64 51 | // Limit on the combined number of flock(2) locks and fcntl(2) leases that 52 | // this process may establish. 53 | FileLocks int64 54 | // Limit of signals that may be queued for the real user ID of the calling 55 | // process. 56 | PendingSignals int64 57 | // Limit on the number of bytes that can be allocated for POSIX message 58 | // queues for the real user ID of the calling process. 59 | MsqqueueSize int64 60 | // Limit of the nice priority set using setpriority(2) or nice(2). 61 | NicePriority int64 62 | // Limit of the real-time priority set using sched_setscheduler(2) or 63 | // sched_setparam(2). 64 | RealtimePriority int64 65 | // Limit (in microseconds) on the amount of CPU time that a process 66 | // scheduled under a real-time scheduling policy may consume without making 67 | // a blocking system call. 68 | RealtimeTimeout int64 69 | } 70 | 71 | const ( 72 | limitsFields = 3 73 | limitsUnlimited = "unlimited" 74 | ) 75 | 76 | var ( 77 | limitsDelimiter = regexp.MustCompile(" +") 78 | ) 79 | 80 | // NewLimits returns the current soft limits of the process. 81 | func (p Proc) NewLimits() (ProcLimits, error) { 82 | f, err := os.Open(p.path("limits")) 83 | if err != nil { 84 | return ProcLimits{}, err 85 | } 86 | defer f.Close() 87 | 88 | var ( 89 | l = ProcLimits{} 90 | s = bufio.NewScanner(f) 91 | ) 92 | for s.Scan() { 93 | fields := limitsDelimiter.Split(s.Text(), limitsFields) 94 | if len(fields) != limitsFields { 95 | return ProcLimits{}, fmt.Errorf( 96 | "couldn't parse %s line %s", f.Name(), s.Text()) 97 | } 98 | 99 | switch fields[0] { 100 | case "Max cpu time": 101 | l.CPUTime, err = parseInt(fields[1]) 102 | case "Max file size": 103 | l.FileSize, err = parseInt(fields[1]) 104 | case "Max data size": 105 | l.DataSize, err = parseInt(fields[1]) 106 | case "Max stack size": 107 | l.StackSize, err = parseInt(fields[1]) 108 | case "Max core file size": 109 | l.CoreFileSize, err = parseInt(fields[1]) 110 | case "Max resident set": 111 | l.ResidentSet, err = parseInt(fields[1]) 112 | case "Max processes": 113 | l.Processes, err = parseInt(fields[1]) 114 | case "Max open files": 115 | l.OpenFiles, err = parseInt(fields[1]) 116 | case "Max locked memory": 117 | l.LockedMemory, err = parseInt(fields[1]) 118 | case "Max address space": 119 | l.AddressSpace, err = parseInt(fields[1]) 120 | case "Max file locks": 121 | l.FileLocks, err = parseInt(fields[1]) 122 | case "Max pending signals": 123 | l.PendingSignals, err = parseInt(fields[1]) 124 | case "Max msgqueue size": 125 | l.MsqqueueSize, err = parseInt(fields[1]) 126 | case "Max nice priority": 127 | l.NicePriority, err = parseInt(fields[1]) 128 | case "Max realtime priority": 129 | l.RealtimePriority, err = parseInt(fields[1]) 130 | case "Max realtime timeout": 131 | l.RealtimeTimeout, err = parseInt(fields[1]) 132 | } 133 | if err != nil { 134 | return ProcLimits{}, err 135 | } 136 | } 137 | 138 | return l, s.Err() 139 | } 140 | 141 | func parseInt(s string) (int64, error) { 142 | if s == limitsUnlimited { 143 | return -1, nil 144 | } 145 | i, err := strconv.ParseInt(s, 10, 64) 146 | if err != nil { 147 | return 0, fmt.Errorf("couldn't parse value %s: %s", s, err) 148 | } 149 | return i, nil 150 | } 151 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/proc_ns.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "os" 19 | "strconv" 20 | "strings" 21 | ) 22 | 23 | // Namespace represents a single namespace of a process. 24 | type Namespace struct { 25 | Type string // Namespace type. 26 | Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match. 27 | } 28 | 29 | // Namespaces contains all of the namespaces that the process is contained in. 30 | type Namespaces map[string]Namespace 31 | 32 | // NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the 33 | // process is a member. 34 | func (p Proc) NewNamespaces() (Namespaces, error) { 35 | d, err := os.Open(p.path("ns")) 36 | if err != nil { 37 | return nil, err 38 | } 39 | defer d.Close() 40 | 41 | names, err := d.Readdirnames(-1) 42 | if err != nil { 43 | return nil, fmt.Errorf("failed to read contents of ns dir: %v", err) 44 | } 45 | 46 | ns := make(Namespaces, len(names)) 47 | for _, name := range names { 48 | target, err := os.Readlink(p.path("ns", name)) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | fields := strings.SplitN(target, ":", 2) 54 | if len(fields) != 2 { 55 | return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target) 56 | } 57 | 58 | typ := fields[0] 59 | inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) 60 | if err != nil { 61 | return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err) 62 | } 63 | 64 | ns[name] = Namespace{typ, uint32(inode)} 65 | } 66 | 67 | return ns, nil 68 | } 69 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/proc_stat.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "bytes" 18 | "fmt" 19 | "io/ioutil" 20 | "os" 21 | ) 22 | 23 | // Originally, this USER_HZ value was dynamically retrieved via a sysconf call 24 | // which required cgo. However, that caused a lot of problems regarding 25 | // cross-compilation. Alternatives such as running a binary to determine the 26 | // value, or trying to derive it in some other way were all problematic. After 27 | // much research it was determined that USER_HZ is actually hardcoded to 100 on 28 | // all Go-supported platforms as of the time of this writing. This is why we 29 | // decided to hardcode it here as well. It is not impossible that there could 30 | // be systems with exceptions, but they should be very exotic edge cases, and 31 | // in that case, the worst outcome will be two misreported metrics. 32 | // 33 | // See also the following discussions: 34 | // 35 | // - https://github.com/prometheus/node_exporter/issues/52 36 | // - https://github.com/prometheus/procfs/pull/2 37 | // - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue 38 | const userHZ = 100 39 | 40 | // ProcStat provides status information about the process, 41 | // read from /proc/[pid]/stat. 42 | type ProcStat struct { 43 | // The process ID. 44 | PID int 45 | // The filename of the executable. 46 | Comm string 47 | // The process state. 48 | State string 49 | // The PID of the parent of this process. 50 | PPID int 51 | // The process group ID of the process. 52 | PGRP int 53 | // The session ID of the process. 54 | Session int 55 | // The controlling terminal of the process. 56 | TTY int 57 | // The ID of the foreground process group of the controlling terminal of 58 | // the process. 59 | TPGID int 60 | // The kernel flags word of the process. 61 | Flags uint 62 | // The number of minor faults the process has made which have not required 63 | // loading a memory page from disk. 64 | MinFlt uint 65 | // The number of minor faults that the process's waited-for children have 66 | // made. 67 | CMinFlt uint 68 | // The number of major faults the process has made which have required 69 | // loading a memory page from disk. 70 | MajFlt uint 71 | // The number of major faults that the process's waited-for children have 72 | // made. 73 | CMajFlt uint 74 | // Amount of time that this process has been scheduled in user mode, 75 | // measured in clock ticks. 76 | UTime uint 77 | // Amount of time that this process has been scheduled in kernel mode, 78 | // measured in clock ticks. 79 | STime uint 80 | // Amount of time that this process's waited-for children have been 81 | // scheduled in user mode, measured in clock ticks. 82 | CUTime uint 83 | // Amount of time that this process's waited-for children have been 84 | // scheduled in kernel mode, measured in clock ticks. 85 | CSTime uint 86 | // For processes running a real-time scheduling policy, this is the negated 87 | // scheduling priority, minus one. 88 | Priority int 89 | // The nice value, a value in the range 19 (low priority) to -20 (high 90 | // priority). 91 | Nice int 92 | // Number of threads in this process. 93 | NumThreads int 94 | // The time the process started after system boot, the value is expressed 95 | // in clock ticks. 96 | Starttime uint64 97 | // Virtual memory size in bytes. 98 | VSize int 99 | // Resident set size in pages. 100 | RSS int 101 | 102 | fs FS 103 | } 104 | 105 | // NewStat returns the current status information of the process. 106 | func (p Proc) NewStat() (ProcStat, error) { 107 | f, err := os.Open(p.path("stat")) 108 | if err != nil { 109 | return ProcStat{}, err 110 | } 111 | defer f.Close() 112 | 113 | data, err := ioutil.ReadAll(f) 114 | if err != nil { 115 | return ProcStat{}, err 116 | } 117 | 118 | var ( 119 | ignore int 120 | 121 | s = ProcStat{PID: p.PID, fs: p.fs} 122 | l = bytes.Index(data, []byte("(")) 123 | r = bytes.LastIndex(data, []byte(")")) 124 | ) 125 | 126 | if l < 0 || r < 0 { 127 | return ProcStat{}, fmt.Errorf( 128 | "unexpected format, couldn't extract comm: %s", 129 | data, 130 | ) 131 | } 132 | 133 | s.Comm = string(data[l+1 : r]) 134 | _, err = fmt.Fscan( 135 | bytes.NewBuffer(data[r+2:]), 136 | &s.State, 137 | &s.PPID, 138 | &s.PGRP, 139 | &s.Session, 140 | &s.TTY, 141 | &s.TPGID, 142 | &s.Flags, 143 | &s.MinFlt, 144 | &s.CMinFlt, 145 | &s.MajFlt, 146 | &s.CMajFlt, 147 | &s.UTime, 148 | &s.STime, 149 | &s.CUTime, 150 | &s.CSTime, 151 | &s.Priority, 152 | &s.Nice, 153 | &s.NumThreads, 154 | &ignore, 155 | &s.Starttime, 156 | &s.VSize, 157 | &s.RSS, 158 | ) 159 | if err != nil { 160 | return ProcStat{}, err 161 | } 162 | 163 | return s, nil 164 | } 165 | 166 | // VirtualMemory returns the virtual memory size in bytes. 167 | func (s ProcStat) VirtualMemory() int { 168 | return s.VSize 169 | } 170 | 171 | // ResidentMemory returns the resident memory size in bytes. 172 | func (s ProcStat) ResidentMemory() int { 173 | return s.RSS * os.Getpagesize() 174 | } 175 | 176 | // StartTime returns the unix timestamp of the process in seconds. 177 | func (s ProcStat) StartTime() (float64, error) { 178 | stat, err := s.fs.NewStat() 179 | if err != nil { 180 | return 0, err 181 | } 182 | return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil 183 | } 184 | 185 | // CPUTime returns the total CPU user and system time in seconds. 186 | func (s ProcStat) CPUTime() float64 { 187 | return float64(s.UTime+s.STime) / userHZ 188 | } 189 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/xfrm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 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 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "os" 20 | "strconv" 21 | "strings" 22 | ) 23 | 24 | // XfrmStat models the contents of /proc/net/xfrm_stat. 25 | type XfrmStat struct { 26 | // All errors which are not matched by other 27 | XfrmInError int 28 | // No buffer is left 29 | XfrmInBufferError int 30 | // Header Error 31 | XfrmInHdrError int 32 | // No state found 33 | // i.e. either inbound SPI, address, or IPSEC protocol at SA is wrong 34 | XfrmInNoStates int 35 | // Transformation protocol specific error 36 | // e.g. SA Key is wrong 37 | XfrmInStateProtoError int 38 | // Transformation mode specific error 39 | XfrmInStateModeError int 40 | // Sequence error 41 | // e.g. sequence number is out of window 42 | XfrmInStateSeqError int 43 | // State is expired 44 | XfrmInStateExpired int 45 | // State has mismatch option 46 | // e.g. UDP encapsulation type is mismatched 47 | XfrmInStateMismatch int 48 | // State is invalid 49 | XfrmInStateInvalid int 50 | // No matching template for states 51 | // e.g. Inbound SAs are correct but SP rule is wrong 52 | XfrmInTmplMismatch int 53 | // No policy is found for states 54 | // e.g. Inbound SAs are correct but no SP is found 55 | XfrmInNoPols int 56 | // Policy discards 57 | XfrmInPolBlock int 58 | // Policy error 59 | XfrmInPolError int 60 | // All errors which are not matched by others 61 | XfrmOutError int 62 | // Bundle generation error 63 | XfrmOutBundleGenError int 64 | // Bundle check error 65 | XfrmOutBundleCheckError int 66 | // No state was found 67 | XfrmOutNoStates int 68 | // Transformation protocol specific error 69 | XfrmOutStateProtoError int 70 | // Transportation mode specific error 71 | XfrmOutStateModeError int 72 | // Sequence error 73 | // i.e sequence number overflow 74 | XfrmOutStateSeqError int 75 | // State is expired 76 | XfrmOutStateExpired int 77 | // Policy discads 78 | XfrmOutPolBlock int 79 | // Policy is dead 80 | XfrmOutPolDead int 81 | // Policy Error 82 | XfrmOutPolError int 83 | XfrmFwdHdrError int 84 | XfrmOutStateInvalid int 85 | XfrmAcquireError int 86 | } 87 | 88 | // NewXfrmStat reads the xfrm_stat statistics. 89 | func NewXfrmStat() (XfrmStat, error) { 90 | fs, err := NewFS(DefaultMountPoint) 91 | if err != nil { 92 | return XfrmStat{}, err 93 | } 94 | 95 | return fs.NewXfrmStat() 96 | } 97 | 98 | // NewXfrmStat reads the xfrm_stat statistics from the 'proc' filesystem. 99 | func (fs FS) NewXfrmStat() (XfrmStat, error) { 100 | file, err := os.Open(fs.Path("net/xfrm_stat")) 101 | if err != nil { 102 | return XfrmStat{}, err 103 | } 104 | defer file.Close() 105 | 106 | var ( 107 | x = XfrmStat{} 108 | s = bufio.NewScanner(file) 109 | ) 110 | 111 | for s.Scan() { 112 | fields := strings.Fields(s.Text()) 113 | 114 | if len(fields) != 2 { 115 | return XfrmStat{}, fmt.Errorf( 116 | "couldn't parse %s line %s", file.Name(), s.Text()) 117 | } 118 | 119 | name := fields[0] 120 | value, err := strconv.Atoi(fields[1]) 121 | if err != nil { 122 | return XfrmStat{}, err 123 | } 124 | 125 | switch name { 126 | case "XfrmInError": 127 | x.XfrmInError = value 128 | case "XfrmInBufferError": 129 | x.XfrmInBufferError = value 130 | case "XfrmInHdrError": 131 | x.XfrmInHdrError = value 132 | case "XfrmInNoStates": 133 | x.XfrmInNoStates = value 134 | case "XfrmInStateProtoError": 135 | x.XfrmInStateProtoError = value 136 | case "XfrmInStateModeError": 137 | x.XfrmInStateModeError = value 138 | case "XfrmInStateSeqError": 139 | x.XfrmInStateSeqError = value 140 | case "XfrmInStateExpired": 141 | x.XfrmInStateExpired = value 142 | case "XfrmInStateInvalid": 143 | x.XfrmInStateInvalid = value 144 | case "XfrmInTmplMismatch": 145 | x.XfrmInTmplMismatch = value 146 | case "XfrmInNoPols": 147 | x.XfrmInNoPols = value 148 | case "XfrmInPolBlock": 149 | x.XfrmInPolBlock = value 150 | case "XfrmInPolError": 151 | x.XfrmInPolError = value 152 | case "XfrmOutError": 153 | x.XfrmOutError = value 154 | case "XfrmInStateMismatch": 155 | x.XfrmInStateMismatch = value 156 | case "XfrmOutBundleGenError": 157 | x.XfrmOutBundleGenError = value 158 | case "XfrmOutBundleCheckError": 159 | x.XfrmOutBundleCheckError = value 160 | case "XfrmOutNoStates": 161 | x.XfrmOutNoStates = value 162 | case "XfrmOutStateProtoError": 163 | x.XfrmOutStateProtoError = value 164 | case "XfrmOutStateModeError": 165 | x.XfrmOutStateModeError = value 166 | case "XfrmOutStateSeqError": 167 | x.XfrmOutStateSeqError = value 168 | case "XfrmOutStateExpired": 169 | x.XfrmOutStateExpired = value 170 | case "XfrmOutPolBlock": 171 | x.XfrmOutPolBlock = value 172 | case "XfrmOutPolDead": 173 | x.XfrmOutPolDead = value 174 | case "XfrmOutPolError": 175 | x.XfrmOutPolError = value 176 | case "XfrmFwdHdrError": 177 | x.XfrmFwdHdrError = value 178 | case "XfrmOutStateInvalid": 179 | x.XfrmOutStateInvalid = value 180 | case "XfrmAcquireError": 181 | x.XfrmAcquireError = value 182 | } 183 | 184 | } 185 | 186 | return x, s.Err() 187 | } 188 | -------------------------------------------------------------------------------- /performance/analysis-methodology-simple-http/vendor/github.com/prometheus/procfs/xfs/xfs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package xfs provides access to statistics exposed by the XFS filesystem. 15 | package xfs 16 | 17 | // Stats contains XFS filesystem runtime statistics, parsed from 18 | // /proc/fs/xfs/stat. 19 | // 20 | // The names and meanings of each statistic were taken from 21 | // http://xfs.org/index.php/Runtime_Stats and xfs_stats.h in the Linux 22 | // kernel source. Most counters are uint32s (same data types used in 23 | // xfs_stats.h), but some of the "extended precision stats" are uint64s. 24 | type Stats struct { 25 | // The name of the filesystem used to source these statistics. 26 | // If empty, this indicates aggregated statistics for all XFS 27 | // filesystems on the host. 28 | Name string 29 | 30 | ExtentAllocation ExtentAllocationStats 31 | AllocationBTree BTreeStats 32 | BlockMapping BlockMappingStats 33 | BlockMapBTree BTreeStats 34 | DirectoryOperation DirectoryOperationStats 35 | Transaction TransactionStats 36 | InodeOperation InodeOperationStats 37 | LogOperation LogOperationStats 38 | ReadWrite ReadWriteStats 39 | AttributeOperation AttributeOperationStats 40 | InodeClustering InodeClusteringStats 41 | Vnode VnodeStats 42 | Buffer BufferStats 43 | ExtendedPrecision ExtendedPrecisionStats 44 | } 45 | 46 | // ExtentAllocationStats contains statistics regarding XFS extent allocations. 47 | type ExtentAllocationStats struct { 48 | ExtentsAllocated uint32 49 | BlocksAllocated uint32 50 | ExtentsFreed uint32 51 | BlocksFreed uint32 52 | } 53 | 54 | // BTreeStats contains statistics regarding an XFS internal B-tree. 55 | type BTreeStats struct { 56 | Lookups uint32 57 | Compares uint32 58 | RecordsInserted uint32 59 | RecordsDeleted uint32 60 | } 61 | 62 | // BlockMappingStats contains statistics regarding XFS block maps. 63 | type BlockMappingStats struct { 64 | Reads uint32 65 | Writes uint32 66 | Unmaps uint32 67 | ExtentListInsertions uint32 68 | ExtentListDeletions uint32 69 | ExtentListLookups uint32 70 | ExtentListCompares uint32 71 | } 72 | 73 | // DirectoryOperationStats contains statistics regarding XFS directory entries. 74 | type DirectoryOperationStats struct { 75 | Lookups uint32 76 | Creates uint32 77 | Removes uint32 78 | Getdents uint32 79 | } 80 | 81 | // TransactionStats contains statistics regarding XFS metadata transactions. 82 | type TransactionStats struct { 83 | Sync uint32 84 | Async uint32 85 | Empty uint32 86 | } 87 | 88 | // InodeOperationStats contains statistics regarding XFS inode operations. 89 | type InodeOperationStats struct { 90 | Attempts uint32 91 | Found uint32 92 | Recycle uint32 93 | Missed uint32 94 | Duplicate uint32 95 | Reclaims uint32 96 | AttributeChange uint32 97 | } 98 | 99 | // LogOperationStats contains statistics regarding the XFS log buffer. 100 | type LogOperationStats struct { 101 | Writes uint32 102 | Blocks uint32 103 | NoInternalBuffers uint32 104 | Force uint32 105 | ForceSleep uint32 106 | } 107 | 108 | // ReadWriteStats contains statistics regarding the number of read and write 109 | // system calls for XFS filesystems. 110 | type ReadWriteStats struct { 111 | Read uint32 112 | Write uint32 113 | } 114 | 115 | // AttributeOperationStats contains statistics regarding manipulation of 116 | // XFS extended file attributes. 117 | type AttributeOperationStats struct { 118 | Get uint32 119 | Set uint32 120 | Remove uint32 121 | List uint32 122 | } 123 | 124 | // InodeClusteringStats contains statistics regarding XFS inode clustering 125 | // operations. 126 | type InodeClusteringStats struct { 127 | Iflush uint32 128 | Flush uint32 129 | FlushInode uint32 130 | } 131 | 132 | // VnodeStats contains statistics regarding XFS vnode operations. 133 | type VnodeStats struct { 134 | Active uint32 135 | Allocate uint32 136 | Get uint32 137 | Hold uint32 138 | Release uint32 139 | Reclaim uint32 140 | Remove uint32 141 | Free uint32 142 | } 143 | 144 | // BufferStats contains statistics regarding XFS read/write I/O buffers. 145 | type BufferStats struct { 146 | Get uint32 147 | Create uint32 148 | GetLocked uint32 149 | GetLockedWaited uint32 150 | BusyLocked uint32 151 | MissLocked uint32 152 | PageRetries uint32 153 | PageFound uint32 154 | GetRead uint32 155 | } 156 | 157 | // ExtendedPrecisionStats contains high precision counters used to track the 158 | // total number of bytes read, written, or flushed, during XFS operations. 159 | type ExtendedPrecisionStats struct { 160 | FlushBytes uint64 161 | WriteBytes uint64 162 | ReadBytes uint64 163 | } 164 | --------------------------------------------------------------------------------