├── server ├── src │ ├── log.json │ ├── data │ │ └── sample_data.json │ ├── Dockerfile │ ├── conf.json │ ├── logger │ │ └── logger.go │ ├── util │ │ ├── ds.go │ │ ├── context.go │ │ └── sanitizer.go │ ├── app │ │ ├── cors.go │ │ ├── middleware.go │ │ └── handler.go │ ├── ds │ │ ├── trie │ │ │ ├── algo.go │ │ │ └── trie.go │ │ ├── ds.go │ │ └── hashmap │ │ │ └── hashmap.go │ ├── Makefile │ ├── go.mod │ ├── conf │ │ └── conf.go │ ├── docker-compose.yml │ ├── server.go │ └── go.sum ├── monitoring │ ├── grafana_config.ini │ ├── grafana_datasources.yml │ ├── grafana_dashboard.yml │ ├── prometheus.yml │ ├── docker-compose.yml │ └── custom_dashboard.json ├── tests │ ├── curl_latency │ ├── test.sh │ ├── tests.js │ ├── test-battle.js │ └── test_data.json ├── infra │ ├── ingress.yml │ └── deployment.yaml └── notes │ └── server-latency ├── client └── typeahead-search-app │ ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ └── index.html │ ├── src │ ├── config │ │ └── constants.js │ ├── setupTests.js │ ├── index.css │ ├── components │ │ ├── About.js │ │ ├── Navbar.js │ │ └── MainContent.js │ ├── reportWebVitals.js │ ├── services │ │ └── httpService.js │ └── index.js │ ├── .gitignore │ ├── Dockerfile │ ├── package.json │ └── README.md ├── runningStats.txt ├── curl-format.txt ├── azure-pipelines.yml └── README.md /server/src/log.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/typeahead-search-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /server/monitoring/grafana_config.ini: -------------------------------------------------------------------------------- 1 | [paths] 2 | provisioning = /etc/grafana/provisioning 3 | 4 | [server] 5 | enable_gzip = true -------------------------------------------------------------------------------- /client/typeahead-search-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shubham8287/flash/HEAD/client/typeahead-search-app/public/favicon.ico -------------------------------------------------------------------------------- /server/src/data/sample_data.json: -------------------------------------------------------------------------------- 1 | [ 2 | "a", 3 | "aa", 4 | "aaa", 5 | "aah", 6 | "aaa", 7 | "aahed", 8 | "aahs", 9 | "aal", 10 | "aalii", 11 | "aaliis" 12 | ] -------------------------------------------------------------------------------- /server/src/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.19-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY go.mod ./ 6 | RUN go mod download 7 | 8 | COPY ./ ./ 9 | 10 | EXPOSE 8080 11 | RUN echo $ 12 | 13 | CMD go run server.go -------------------------------------------------------------------------------- /server/src/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "//algo": "map", 3 | "algo": "trie", 4 | "//data_path": "./data/sample_data.json", 5 | "data_path": "./data/words_dictionary.json", 6 | "logging": true, 7 | "//logging": false 8 | } -------------------------------------------------------------------------------- /client/typeahead-search-app/src/config/constants.js: -------------------------------------------------------------------------------- 1 | const constant = { 2 | "serverUrl" : "http://localhost", 3 | "serverPort" : "4000", 4 | "findApi" : "/find", 5 | "insertApi" : "/insert" 6 | }; 7 | 8 | export default constant; -------------------------------------------------------------------------------- /server/src/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "github.com/sirupsen/logrus" 5 | ) 6 | 7 | var Log *logrus.Logger 8 | 9 | func init() { 10 | Log = logrus.New() 11 | Log.SetFormatter(&logrus.JSONFormatter{}) 12 | } 13 | -------------------------------------------------------------------------------- /client/typeahead-search-app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /runningStats.txt: -------------------------------------------------------------------------------- 1 | 2 | Latency test with below command 3 | 4 | `ab -n 100 -c 1 -k https://flashy.azurewebsites.net/find?prefix=pop` 5 | 6 | 50% 102 7 | 66% 103 8 | 75% 103 9 | 80% 103 10 | 90% 103 11 | 95% 109 12 | 98% 205 13 | 99% 222 14 | 100% 222 -------------------------------------------------------------------------------- /server/monitoring/grafana_datasources.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: 'prometheus' 5 | type: 'prometheus' 6 | access: 'proxy' 7 | url: 'http://prometheus:9090' 8 | - name: 'perfstat' 9 | type: 'prometheus' 10 | access: 'proxy' 11 | url: 'http://perfstat:8880/metrics' -------------------------------------------------------------------------------- /server/src/util/ds.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | type Response struct { 4 | Prefix string `json:"prefix"` 5 | Matches []string `json:"matches"` 6 | } 7 | 8 | // TODO: sort by frequency 9 | func FilterMatchingStrings(wordList []string) []string { 10 | if len(wordList) < 20 { 11 | return wordList 12 | } 13 | return wordList[0:20] 14 | } 15 | -------------------------------------------------------------------------------- /curl-format.txt: -------------------------------------------------------------------------------- 1 | time_namelookup: %{time_namelookup}s\n 2 | time_connect: %{time_connect}s\n 3 | time_appconnect: %{time_appconnect}s\n 4 | time_pretransfer: %{time_pretransfer}s\n 5 | time_redirect: %{time_redirect}s\n 6 | time_starttransfer: %{time_starttransfer}s\n 7 | ----------\n 8 | time_total: %{time_total}s\n 9 | -------------------------------------------------------------------------------- /server/tests/curl_latency: -------------------------------------------------------------------------------- 1 | time_namelookup: %{time_namelookup}s\n 2 | time_connect: %{time_connect}s\n 3 | time_appconnect: %{time_appconnect}s\n 4 | time_pretransfer: %{time_pretransfer}s\n 5 | time_redirect: %{time_redirect}s\n 6 | time_starttransfer: %{time_starttransfer}s\n 7 | ----------\n 8 | time_total: %{time_total}s\n 9 | -------------------------------------------------------------------------------- /client/typeahead-search-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /client/typeahead-search-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /client/typeahead-search-app/src/components/About.js: -------------------------------------------------------------------------------- 1 | function About() { 2 | return ( 3 | <> 4 |
5 |
6 |

About Project

7 |

FLASH is experiment around type ahead seach :-)

8 |
9 |
10 | 11 | ) 12 | } 13 | 14 | export default About; -------------------------------------------------------------------------------- /client/typeahead-search-app/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /server/monitoring/grafana_dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: Default # A uniquely identifiable name for the provider 5 | folder: Services # The folder where to place the dashboards 6 | type: file 7 | options: 8 | path: 9 | # Default path for Windows: C:/Program Files/GrafanaLabs/grafana/public/dashboards 10 | # Default path for Linux is: /var/lib/grafana/dashboards -------------------------------------------------------------------------------- /client/typeahead-search-app/src/services/httpService.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import constant from '../config/constants'; 3 | 4 | function fetchSuggestions(data) { 5 | const findApi = constant.serverUrl + ":" + constant.serverPort + constant.findApi; 6 | const retData = axios 7 | .get(findApi, { params: { prefix: data }}) 8 | .catch((error) => { 9 | console.error(error); 10 | }); 11 | return retData; 12 | } 13 | export default fetchSuggestions; -------------------------------------------------------------------------------- /client/typeahead-search-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16 2 | 3 | # Create app directory 4 | WORKDIR /usr/src/app 5 | 6 | # Install app dependencies 7 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 8 | # where available (npm@5+) 9 | COPY package*.json ./ 10 | 11 | RUN npm install 12 | # If you are building your code for production 13 | # RUN npm ci --only=production 14 | 15 | # Bundle app source 16 | COPY . . 17 | 18 | EXPOSE 3000 19 | CMD [ "npm", "start" ] 20 | -------------------------------------------------------------------------------- /server/tests/test.sh: -------------------------------------------------------------------------------- 1 | DATA_PATH='../src/data/words_dictionary.json' 2 | TEST_DATA_PATH='./test_data.json' 3 | echo "[" > $TEST_DATA_PATH 4 | totalLines=$(wc -l < $DATA_PATH) 5 | 6 | for i in `eval echo {2.."$1"}` 7 | do 8 | pickedLine=$(sed -n "$((($RANDOM*$RANDOM)%$totalLines))"p $DATA_PATH) 9 | echo $pickedLine >> $TEST_DATA_PATH 10 | done 11 | 12 | pickedLine=$(sed -n "$((($RANDOM*$RANDOM)%$totalLines))"p $DATA_PATH) 13 | echo $pickedLine | sed -e 's/\",/"/g' >> $TEST_DATA_PATH 14 | 15 | echo "]" >> $TEST_DATA_PATH -------------------------------------------------------------------------------- /server/src/app/cors.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import "net/http" 4 | 5 | func enableCors(w *http.ResponseWriter) { 6 | (*w).Header().Set("Access-Control-Allow-Origin", "*") 7 | } 8 | 9 | func setupResponse(w *http.ResponseWriter) { 10 | (*w).Header().Set("Access-Control-Allow-Origin", "*") 11 | (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") 12 | (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") 13 | (*w).Header().Set("Content-Type", "application/json") 14 | } 15 | -------------------------------------------------------------------------------- /server/infra/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: flash-ingress 5 | namespace: ingress-basic 6 | annotations: 7 | kubernetes.io/ingress.class: nginx 8 | nginx.ingress.kubernetes.io/ssl-redirect: "false" 9 | nginx.ingress.kubernetes.io/use-regex: "true" 10 | nginx.ingress.kubernetes.io/rewrite-target: /$1 11 | spec: 12 | rules: 13 | - http: 14 | paths: 15 | - path: /?(.*) 16 | pathType: Prefix 17 | backend: 18 | service: 19 | name: flash 20 | port: 21 | number: 80 22 | -------------------------------------------------------------------------------- /server/src/app/middleware.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "context" 5 | "flash/util" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/google/uuid" 10 | ) 11 | 12 | func Middleware(next http.HandlerFunc) http.HandlerFunc { 13 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 14 | ctx := r.Context() 15 | reqID := uuid.New() 16 | ctx = context.WithValue(ctx, util.REQUEST_ID, reqID.String()) 17 | ctx = context.WithValue(ctx, util.LAST_LOG_TIME, time.Now()) 18 | r = r.WithContext(ctx) 19 | // Log.WithField("request_id", reqID).Info("request_id_generated") 20 | next.ServeHTTP(w, r) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /client/typeahead-search-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /server/infra/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: flash 5 | labels: 6 | app: flash 7 | spec: 8 | replicas: 2 9 | selector: 10 | matchLabels: 11 | app: flash 12 | template: 13 | metadata: 14 | labels: 15 | app: flash 16 | spec: 17 | containers: 18 | - name: flash 19 | image: flashy.azurecr.io/flashy:latest 20 | ports: 21 | - containerPort: 8080 22 | --- 23 | apiVersion: v1 24 | kind: Service 25 | metadata: 26 | name: flash 27 | spec: 28 | selector: 29 | app: flash 30 | ports: 31 | - port: 80 32 | targetPort: 8080 33 | -------------------------------------------------------------------------------- /server/src/ds/trie/algo.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | func (t *trie) generateAllWordsWithPrefix(currentNode *trieNode, currentString string) []string { 4 | matchingStrings := []string{} 5 | usingDFS(currentNode, &matchingStrings, currentString) 6 | return matchingStrings 7 | } 8 | 9 | func usingDFS(currentNode *trieNode, matchingStrings *[]string, currentString string) { 10 | if currentNode.isWordEnd { 11 | *matchingStrings = append(*matchingStrings, (currentString)) 12 | } 13 | for i := 0; i < 26; i++ { 14 | if currentNode.childrens[i] != nil { 15 | usingDFS(currentNode.childrens[i], matchingStrings, currentString+(string(i+int('a')))) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /server/src/util/context.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "context" 5 | "time" 6 | ) 7 | 8 | const REQUEST_ID = "requestID" 9 | const LAST_LOG_TIME = "lastUpdateTimestamp" 10 | 11 | func SetElapsedTimeStamp(ctx context.Context) time.Duration { 12 | 13 | last_time := ctx.Value(LAST_LOG_TIME) 14 | cur_time := time.Now() 15 | elapsed_time := cur_time.Sub(last_time.(time.Time)) 16 | ctx = context.WithValue(ctx, REQUEST_ID, last_time) 17 | 18 | return elapsed_time 19 | } 20 | 21 | func GetRequestID(ctx context.Context) string { 22 | 23 | reqID := ctx.Value(REQUEST_ID) 24 | 25 | if ret, ok := reqID.(string); ok { 26 | return ret 27 | } 28 | 29 | return "" 30 | } 31 | -------------------------------------------------------------------------------- /client/typeahead-search-app/src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import { Navbar, Nav, Container, NavDropdown } from 'react-bootstrap'; 2 | 3 | function NavbarTop() { 4 | return ( 5 | 6 | 7 | FLASH 8 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | ) 20 | } 21 | 22 | 23 | export default NavbarTop; 24 | -------------------------------------------------------------------------------- /server/src/Makefile: -------------------------------------------------------------------------------- 1 | 2 | dep: 3 | sudo apt-get -y update 4 | sudo apt-get -y install \ 5 | ca-certificates \ 6 | curl \ 7 | gnupg \ 8 | lsb-release 9 | sudo mkdir -p /etc/apt/keyrings 10 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg 11 | echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 12 | sudo apt-get -y update 13 | sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-compose 14 | sudo service docker start 15 | 16 | 17 | mon: 18 | cd ../monitoring; sudo docker-compose up; 19 | 20 | run: 21 | sudo docker-compose up 22 | -------------------------------------------------------------------------------- /server/src/util/sanitizer.go: -------------------------------------------------------------------------------- 1 | package util 2 | import ( 3 | "strings" 4 | "regexp" 5 | ) 6 | 7 | // Sanitized the input prefix recieved. 8 | func SanitizeString(prefix string) string { 9 | // regex expression 10 | nonSpecialCharacterRegex := regexp.MustCompile(`[^a-zA-Z/-]+`) 11 | 12 | var sanitizedPrefix string = ""; 13 | 14 | // trim the string 15 | sanitizedPrefix = strings.TrimSpace(prefix) 16 | 17 | // add "-" for in -between spaces 18 | sanitizedPrefix = strings.ReplaceAll(sanitizedPrefix, " ", "-") 19 | 20 | // remove special characters 21 | sanitizedPrefix = nonSpecialCharacterRegex.ReplaceAllString(sanitizedPrefix, "") 22 | 23 | // lowercase all the upercase letters 24 | sanitizedPrefix = strings.ToLower(sanitizedPrefix) 25 | 26 | // return the sanitized string 27 | return sanitizedPrefix 28 | } 29 | -------------------------------------------------------------------------------- /server/src/go.mod: -------------------------------------------------------------------------------- 1 | module flash 2 | 3 | go 1.19 4 | 5 | replace flash/app => ./app 6 | 7 | require ( 8 | github.com/sirupsen/logrus v1.8.1 // indirect 9 | golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 // indirect 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v1.0.1 // indirect 14 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 15 | github.com/golang/protobuf v1.5.2 // indirect 16 | github.com/google/uuid v1.3.0 // indirect 17 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 18 | github.com/prometheus/client_golang v1.13.0 // indirect 19 | github.com/prometheus/client_model v0.2.0 // indirect 20 | github.com/prometheus/common v0.37.0 // indirect 21 | github.com/prometheus/procfs v0.8.0 // indirect 22 | github.com/slok/go-http-metrics v0.10.0 // indirect 23 | google.golang.org/protobuf v1.28.1 // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /client/typeahead-search-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import { BrowserRouter,Routes,Route } from "react-router-dom"; 5 | import reportWebVitals from './reportWebVitals'; 6 | import NavbarTop from './components/Navbar'; 7 | import MainContent from './components/MainContent'; 8 | import About from './components/About'; 9 | 10 | ReactDOM.render( 11 | 12 | 13 | 14 | 15 | } /> 16 | } /> 17 | 18 | 19 | , 20 | document.getElementById('root') 21 | ); 22 | 23 | // If you want to start measuring performance in your app, pass a function 24 | // to log results (for example: reportWebVitals(console.log)) 25 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 26 | reportWebVitals(); 27 | -------------------------------------------------------------------------------- /server/src/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "encoding/json" 5 | . "flash/logger" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | 10 | "github.com/sirupsen/logrus" 11 | ) 12 | 13 | const CONFIGPATH = "./conf.json" 14 | 15 | type Config struct { 16 | Algo string `json:"algo"` 17 | DataPath string `json:"data_path"` 18 | LoggingEnabled bool `json:"logging"` 19 | } 20 | 21 | var configInstance Config 22 | 23 | func readConfig() Config { 24 | Log.Info("config_reading_start") 25 | jsonFile, err := os.Open(CONFIGPATH) 26 | if err != nil { 27 | fmt.Println("error:", err) 28 | } 29 | byteValue, _ := ioutil.ReadAll(jsonFile) 30 | defer jsonFile.Close() 31 | 32 | config := Config{} 33 | json.Unmarshal(byteValue, &config) 34 | Log.WithFields(logrus.Fields{ 35 | "algorithm": config.Algo, 36 | "data_path": config.DataPath, 37 | "logging_enabled": config.LoggingEnabled, 38 | }).Info("config_reading_done") 39 | 40 | return config 41 | } 42 | 43 | func Get() Config { 44 | if configInstance == (Config{}) { 45 | configInstance = readConfig() 46 | } 47 | return configInstance 48 | } 49 | -------------------------------------------------------------------------------- /server/src/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | # perfstat: 5 | # container_name: perfstat 6 | # image: flaviostutz/perfstat 7 | # privileged: true 8 | # volumes: 9 | # - /etc/hostname:/etc/hostname 10 | # ports: 11 | # - 8880:8880 12 | # deploy: 13 | # mode: global 14 | # networks: 15 | # - app 16 | 17 | node-exporter: 18 | image: prom/node-exporter:latest 19 | container_name: node-exporter 20 | restart: unless-stopped 21 | volumes: 22 | - /proc:/host/proc:ro 23 | - /sys:/host/sys:ro 24 | - /:/rootfs:ro 25 | command: 26 | - '--path.procfs=/host/proc' 27 | - '--path.rootfs=/rootfs' 28 | - '--path.sysfs=/host/sys' 29 | - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' 30 | ports: 31 | - 9100:9100 32 | # networks: 33 | # - app 34 | 35 | 36 | flash: 37 | container_name: flash 38 | build: . 39 | ports: 40 | - 8080:8080 41 | - 8081:8081 42 | # networks: 43 | # - app 44 | 45 | # networks: 46 | # app: 47 | # driver: bridge -------------------------------------------------------------------------------- /server/monitoring/prometheus.yml: -------------------------------------------------------------------------------- 1 | ## prometheus.yml ## 2 | 3 | # global settings 4 | global: 5 | scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. 6 | evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. 7 | # scrape_timeout is set to the global default (10s). 8 | 9 | 10 | 11 | # A scrape configuration containing exactly one endpoint to scrape: 12 | # Here it's Prometheus itself. 13 | scrape_configs: 14 | # The job name is added as a label `job=` to any timeseries scraped from this config. 15 | - job_name: 'flash' 16 | metrics_path: '/' 17 | scrape_interval: 5s 18 | static_configs: 19 | - targets: ['10.1.0.4:8081'] 20 | 21 | - job_name: 'nodejs' 22 | metrics_path: '/metrics' 23 | scrape_interval: 5s 24 | static_configs: 25 | - targets: ['10.1.0.4:8080'] 26 | 27 | - job_name: "node" 28 | scrape_interval: 5s 29 | static_configs: 30 | - targets: ["10.1.0.4:9100"] 31 | 32 | # - job_name: 'perfstat' 33 | # metrics_path: '/metrics' 34 | # scrape_interval: 5s 35 | # static_configs: 36 | # - targets: ['perfstat:8880'] -------------------------------------------------------------------------------- /client/typeahead-search-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typeahead-search-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.2", 7 | "@testing-library/react": "^12.1.3", 8 | "@testing-library/user-event": "^13.5.0", 9 | "axios": "^0.26.0", 10 | "bootstrap": "^5.1.3", 11 | "react": "^17.0.2", 12 | "react-autosuggest": "^10.1.0", 13 | "react-bootstrap": "^2.1.2", 14 | "react-dom": "^17.0.2", 15 | "react-router-dom": "^6.2.1", 16 | "react-scripts": "5.0.0", 17 | "web-vitals": "^2.1.4" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /server/monitoring/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | volumes: 4 | prometheus_data: {} 5 | grafana_data: {} 6 | 7 | services: 8 | 9 | prometheus: 10 | container_name: prometheus 11 | hostname: prometheus 12 | image: prom/prometheus 13 | volumes: 14 | - ./prometheus.yml:/etc/prometheus/prometheus.yml 15 | - prometheus_data:/prometheus 16 | command: 17 | - '--config.file=/etc/prometheus/prometheus.yml' 18 | - '--storage.tsdb.path=/prometheus' 19 | - '--web.console.libraries=/etc/prometheus/console_libraries' 20 | - '--web.console.templates=/etc/prometheus/consoles' 21 | - '--web.enable-lifecycle' 22 | ports: 23 | - 9090:9090 24 | # networks: 25 | # - src_app 26 | 27 | grafana: 28 | container_name: grafana 29 | hostname: grafana 30 | image: grafana/grafana 31 | volumes: 32 | - ./grafana_datasources.yml:/etc/grafana/provisioning/datasources/all.yaml 33 | # - ./grafana_config.ini:/etc/grafana/config.ini 34 | - grafana_data:/var/lib/grafana 35 | # networks: 36 | # - src_app 37 | ports: 38 | - 3000:3000 39 | # networks: 40 | # src_app: 41 | # external: true 42 | -------------------------------------------------------------------------------- /server/tests/tests.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http'; 2 | import { SharedArray } from 'k6/data'; 3 | import { sleep, check, randomSeed } from 'k6'; 4 | 5 | const BASE_URL = "http://192.168.1.69:8080" 6 | 7 | export const options = { 8 | stages: [ 9 | { duration: '1s', target: 20000 }, 10 | { duration: '120s', target: 20000 } 11 | ], 12 | }; 13 | 14 | const testQueries = new SharedArray('users', function () { 15 | const f = JSON.parse(open('./test_data.json')); 16 | return f; 17 | }); 18 | 19 | export default function () { 20 | const rndIndex = Math.floor((Math.random()*10000000)%testQueries.length) 21 | const res = http.get(BASE_URL+'/find?prefix='+ testQueries[rndIndex]); 22 | //const res = http.get(BASE_URL+'/isAlive'); 23 | check(res, { 'status was 200': (r) => isFine(JSON.parse(r.body), testQueries[rndIndex]) }); 24 | // check(res, { 'status was 200': (r) => true }); 25 | sleep(1); 26 | } 27 | 28 | function isFine(body, prefix) { 29 | if(body.prefix != prefix) { 30 | return false; 31 | } 32 | let allMatches = true 33 | body.matches.map(m => { 34 | allMatches &= m.startsWith(prefix); 35 | }) 36 | return allMatches; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /server/src/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flash/app" 5 | . "flash/logger" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/prometheus/client_golang/prometheus/promhttp" 10 | metrics "github.com/slok/go-http-metrics/metrics/prometheus" 11 | "github.com/slok/go-http-metrics/middleware" 12 | "github.com/slok/go-http-metrics/middleware/std" 13 | ) 14 | 15 | const ( 16 | PORT = ":8080" 17 | metricsAddr = ":8081" 18 | ) 19 | 20 | func handleRequests() { 21 | mdlw := middleware.New(middleware.Config{ 22 | Recorder: metrics.NewRecorder(metrics.Config{}), 23 | }) 24 | mux := http.NewServeMux() 25 | mux.HandleFunc("/", app.HomeReq) 26 | mux.HandleFunc("/isAlive", app.Middleware(app.PingReq)) 27 | mux.HandleFunc("/find", app.FindReq) 28 | mux.HandleFunc("/insert", app.InsertReq) 29 | 30 | serv := std.Handler("", mdlw, mux) 31 | // http.Handle("/metrics", promhttp.Handler()) 32 | // Serve our metrics. 33 | go func() { 34 | log.Printf("metrics listening at %s", metricsAddr) 35 | if err := http.ListenAndServe(metricsAddr, promhttp.Handler()); err != nil { 36 | log.Panicf("error while serving metrics: %s", err) 37 | } 38 | }() 39 | Log.Fatal(http.ListenAndServe(PORT, serv)) 40 | } 41 | 42 | func main() { 43 | handleRequests() 44 | } -------------------------------------------------------------------------------- /server/tests/test-battle.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http'; 2 | import { SharedArray } from 'k6/data'; 3 | import { sleep, check, randomSeed } from 'k6'; 4 | 5 | const BASE_URL = "http://10.1.0.4:8080" 6 | 7 | export const options = { 8 | stages: [ 9 | { duration: '1s', target: 10000 }, 10 | { duration: '60s', target: 10000 } 11 | ], 12 | }; 13 | 14 | const testQueries = new SharedArray('users', function () { 15 | const f = JSON.parse(open('./test_data.json')); 16 | return f; 17 | }); 18 | 19 | export default function () { 20 | const rndIndex = Math.floor((Math.random()*10000000)%testQueries.length) 21 | const res = http.get(BASE_URL+'/insert?key='+ testQueries[rndIndex]+'&value='+ testQueries[rndIndex]); 22 | //const res = http.get(BASE_URL+'/isAlive'); 23 | // check(res, { 'status was 200': (r) => isFine(JSON.parse(r.body), testQueries[rndIndex]) }); 24 | //console.log(res.body,testQueries[rndIndex]) 25 | check(res, { 'status was 200': (r) => r.body==testQueries[rndIndex] }); 26 | sleep(1); 27 | } 28 | 29 | function isFine(body, prefix) { 30 | if(body.prefix != prefix) { 31 | return false; 32 | } 33 | let allMatches = true 34 | body.matches.map(m => { 35 | allMatches &= m.startsWith(prefix); 36 | }) 37 | return allMatches; 38 | 39 | } -------------------------------------------------------------------------------- /server/src/ds/ds.go: -------------------------------------------------------------------------------- 1 | package ds 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "flash/conf" 7 | "flash/ds/hashmap" 8 | "flash/ds/trie" 9 | . "flash/logger" 10 | "fmt" 11 | "io/ioutil" 12 | "time" 13 | ) 14 | 15 | type DataStructure interface { 16 | Find(string) []string 17 | Insert(string) 18 | } 19 | 20 | var bucketData DataStructure = nil 21 | var configuration conf.Config = conf.Get() 22 | 23 | func init() { 24 | if configuration.Algo == "map" { 25 | bucketData = hashmap.Get() 26 | } else { 27 | bucketData = trie.Get() 28 | } 29 | fillData(bucketData) 30 | } 31 | 32 | func fillData(bucketData DataStructure) { 33 | Log.Info("file_reading_started") 34 | fileData, err := ioutil.ReadFile(configuration.DataPath) 35 | if err != nil { 36 | fmt.Print(err) 37 | } 38 | 39 | var intialWordSet = []string{} 40 | err = json.Unmarshal(fileData, &intialWordSet) 41 | if err != nil { 42 | fmt.Println("error:", err) 43 | } 44 | Log.Info("file_reading_done") 45 | start := time.Now() 46 | for i := 0; i < len(intialWordSet); i++ { 47 | bucketData.Insert(intialWordSet[i]) 48 | } 49 | t := time.Now() 50 | Log.WithField("time_elapsed", t.Sub(start)).Info("Initialiazing_data_in_ds_done") 51 | } 52 | 53 | func GetDs(ctx context.Context) DataStructure { 54 | if bucketData != nil { 55 | return bucketData 56 | } 57 | return bucketData 58 | } 59 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Docker 2 | # Build and push an image to Azure Container Registry 3 | # https://docs.microsoft.com/azure/devops/pipelines/languages/docker 4 | 5 | trigger: 6 | - main 7 | 8 | resources: 9 | - repo: self 10 | 11 | variables: 12 | # Container registry service connection established during pipeline creation 13 | dockerRegistryServiceConnection: '8a2c981b-7611-490d-82fd-6894b63187ce' 14 | imageRepository: 'flashy' 15 | containerRegistry: 'flashy.azurecr.io' 16 | dockerfilePath: '$(Build.SourcesDirectory)/server/src/Dockerfile' 17 | tag: '$(Build.BuildId)' 18 | dockerContext: $(Build.SourcesDirectory)/server/src/ 19 | # Agent VM image name 20 | vmImageName: 'ubuntu-latest' 21 | 22 | stages: 23 | - stage: Build 24 | 25 | displayName: Build and push stage 26 | jobs: 27 | - job: Build 28 | displayName: Build 29 | pool: 30 | vmImage: $(vmImageName) 31 | steps: 32 | - task: Docker@2 33 | displayName: Build and push an image to container registry 34 | inputs: 35 | command: buildAndPush 36 | repository: $(imageRepository) 37 | dockerfile: $(dockerfilePath) 38 | buildContext: $(dockerContext) 39 | containerRegistry: $(dockerRegistryServiceConnection) 40 | tags: | 41 | $(tag) 42 | - task: PublishPipelineArtifact@1 43 | inputs: 44 | artifactName: 'repo' 45 | path: $(Build.Repository.LocalPath) 46 | -------------------------------------------------------------------------------- /server/src/ds/trie/trie.go: -------------------------------------------------------------------------------- 1 | package trie 2 | 3 | import ( 4 | "flash/util" 5 | ) 6 | 7 | const ( 8 | //ALBHABET_SIZE total characters in english alphabet 9 | ALBHABET_SIZE = 26 10 | ) 11 | 12 | type trieNode struct { 13 | childrens [ALBHABET_SIZE]*trieNode 14 | isWordEnd bool 15 | } 16 | 17 | type trie struct { 18 | root *trieNode 19 | } 20 | 21 | var trieInstance *trie = nil 22 | 23 | func Get() *trie { 24 | if trieInstance == nil { 25 | trieInstance = &trie{ 26 | root: &trieNode{}, 27 | } 28 | } 29 | return trieInstance 30 | } 31 | 32 | func (t *trie) Insert(word string) { 33 | // sanitize the input string 34 | word = util.SanitizeString(word) 35 | 36 | wordLength := len(word) 37 | currentNode := t.root 38 | for i := 0; i < wordLength; i++ { 39 | index := word[i] - 'a' 40 | if currentNode.childrens[index] == nil { 41 | currentNode.childrens[index] = &trieNode{} 42 | } 43 | currentNode = currentNode.childrens[index] 44 | } 45 | currentNode.isWordEnd = true 46 | } 47 | 48 | func (t *trie) Find(word string) []string { 49 | wordLength := len(word) 50 | currentNode := t.root 51 | for i := 0; i < wordLength; i++ { 52 | index := word[i] - 'a' 53 | if currentNode.childrens[index] == nil { 54 | //t.Insert(word) 55 | return []string{} 56 | } 57 | currentNode = currentNode.childrens[index] 58 | } 59 | 60 | matchingStrings := t.generateAllWordsWithPrefix(currentNode, word) 61 | response := util.FilterMatchingStrings(matchingStrings) 62 | 63 | return response 64 | } 65 | -------------------------------------------------------------------------------- /server/src/app/handler.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/json" 5 | "flash/conf" 6 | "flash/ds" 7 | "flash/logger" 8 | "flash/util" 9 | "fmt" 10 | "html" 11 | "net/http" 12 | 13 | "github.com/sirupsen/logrus" 14 | ) 15 | 16 | var config conf.Config = conf.Get() 17 | 18 | func HomeReq(w http.ResponseWriter, r *http.Request) { 19 | fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) 20 | } 21 | 22 | func PingReq(w http.ResponseWriter, r *http.Request) { 23 | fmt.Fprintf(w, "Boss is always fine") 24 | } 25 | 26 | func FindReq(w http.ResponseWriter, r *http.Request) { 27 | ctx := r.Context() 28 | searchBucket := ds.GetDs(ctx) 29 | setupResponse(&w) 30 | prefix := r.FormValue("prefix") 31 | 32 | // sanitize the incoming "prefix" query param 33 | sanitizedPrefix := util.SanitizeString(prefix) 34 | 35 | matches := searchBucket.Find(sanitizedPrefix) 36 | 37 | if config.LoggingEnabled == true { 38 | logger.Log.WithFields(logrus.Fields{ 39 | "request_id": util.GetRequestID(ctx), 40 | // "time_elapsed": util.SetElapsedTimeStamp(ctx), 41 | }).Info("find_matches_received") 42 | 43 | } 44 | response := util.Response{ 45 | Prefix: sanitizedPrefix, 46 | Matches: matches, 47 | } 48 | json.NewEncoder(w).Encode(response) 49 | } 50 | 51 | func InsertReq(w http.ResponseWriter, r *http.Request) { 52 | ctx := r.Context() 53 | searchBucket := ds.GetDs(ctx) 54 | setupResponse(&w) 55 | prefix := r.FormValue("prefix") 56 | 57 | // sanitize the incoming "prefix" query param. 58 | sanitizedPrefix := util.SanitizeString(prefix) 59 | 60 | searchBucket.Insert(sanitizedPrefix) 61 | 62 | response := util.Response{ 63 | Prefix: sanitizedPrefix, 64 | } 65 | json.NewEncoder(w).Encode(response) 66 | } 67 | -------------------------------------------------------------------------------- /client/typeahead-search-app/src/components/MainContent.js: -------------------------------------------------------------------------------- 1 | 2 | import {Container} from 'react-bootstrap'; 3 | import { useState } from 'react'; 4 | import fetchSuggestions from '../services/httpService'; 5 | import Autosuggest from 'react-autosuggest'; 6 | 7 | function MainContent () { 8 | const [value, setValue] = useState(''); 9 | const [suggestedValue, setSuggestedValue] = useState(''); 10 | 11 | const onChange = (event, { newValue }) => { 12 | setValue(newValue); 13 | }; 14 | 15 | // You already implemented this logic above, so just use it. 16 | const onSuggestionsFetchRequested = async ({ value }) => { 17 | let returnData = await fetchSuggestions(value); 18 | setSuggestedValue(returnData.data.matches); 19 | }; 20 | 21 | // Autosuggest will call this function every time you need to clear suggestions. 22 | const onSuggestionsClearRequested = () => 23 | { 24 | setSuggestedValue(''); 25 | }; 26 | 27 | const getSuggestionValue = suggestion => suggestion; 28 | 29 | // Use your imagination to render suggestions. 30 | const renderSuggestion = function (suggestion) { 31 | return ( 32 |
33 | {suggestion} 34 |
35 | ); 36 | } 37 | 38 | 39 | // Autosuggest will pass through all these props to the input. 40 | const inputProps = { 41 | placeholder: 'Type your query', 42 | value, 43 | onChange: onChange 44 | }; 45 | 46 | return ( 47 | <> 48 | 49 | 57 | 58 | 59 | ) 60 | } 61 | 62 | export default MainContent; -------------------------------------------------------------------------------- /client/typeahead-search-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 19 | 25 | 26 | 35 | React App 36 | 37 | 38 | 39 |
40 | 50 | 51 | 52 | 53 | 54 | 57 | 58 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /server/src/ds/hashmap/hashmap.go: -------------------------------------------------------------------------------- 1 | package hashmap 2 | 3 | import ( 4 | "flash/util" 5 | ) 6 | 7 | type bucketType map[string][]Item 8 | 9 | var bucket bucketType = nil 10 | 11 | // sample bucket 12 | // [a:[{2 aaa} {2 aa} {1 a} {1 aah} {1 aahed} {1 aahs} {1 aal} {1 aalii} {1 aaliis}] 13 | // aa:[[{2 aaa} {2 aa} {1 aah} {1 aahed} {1 aahs} {1 aal} {1 aalii} {1 aaliis}] 14 | // aaa:[{2 aaa}] aah:[{1 aah} {1 aahed} {1 aahs}] aahe:[{1 aahed}] 15 | // aahed:[{1 aahed}] aahs:[{1 aahs}] aal:[{1 aal} {1 aalii} {1 aaliis}] 16 | // aali:[{1 aalii} {1 aaliis}] aalii:[{1 aalii} {1 aaliis}] 17 | // aaliis:[{1 aaliis}] 18 | // w:[{4 waskodimagama} {3 wask}] 19 | // wa:[{4 waskodimagama} {3 wask}] 20 | // was:[{4 waskodimagama} {3 wask}] 21 | // wask:[{4 waskodimagama} {3 wask}] 22 | // wasko:[{4 waskodimagama}] 23 | // waskod:[{4 waskodimagama}] 24 | // waskodi:[{4 waskodimagama}] 25 | // waskodim:[{4 waskodimagama}] 26 | // waskodima:[{4 waskodimagama}] 27 | // waskodimag:[{4 waskodimagama}] 28 | // waskodimaga:[{4 waskodimagama}] 29 | // waskodimagam:[{4 waskodimagama}] 30 | // waskodimagama:[{4 waskodimagama}] 31 | // ] 32 | type Item struct { 33 | freq int 34 | word string 35 | } 36 | 37 | func Get() *bucketType { 38 | if bucket == nil { 39 | bucket = make(bucketType) 40 | } 41 | return &bucket 42 | } 43 | 44 | func (b *bucketType) Find(prefix string) []string { 45 | return filterMatchingWordItem(bucket[prefix]) 46 | } 47 | 48 | func (b *bucketType) Insert(word string) { 49 | // sanitize the input string 50 | word = util.SanitizeString(word) 51 | 52 | var prefixWord string 53 | for i := 0; i < len(word); i++ { 54 | prefixWord += string(word[i]) 55 | _, ok := bucket[prefixWord] 56 | if ok { 57 | idx, ok := findWord(bucket[prefixWord], word) 58 | if ok { 59 | newWordItem := bucket[prefixWord][idx] 60 | bucket[prefixWord] = removeWordItem(bucket[prefixWord], idx) 61 | newWordItem.freq++ 62 | bucket[prefixWord] = insertWordItem(bucket[prefixWord], newWordItem) 63 | } else { 64 | freq := 1 65 | if len(bucket[prefixWord]) != 0 { 66 | freq = bucket[prefixWord][len(bucket[prefixWord])-1].freq 67 | } 68 | newWordItem := Item{ 69 | word: word, 70 | freq: freq, 71 | } 72 | bucket[prefixWord] = insertWordItem(bucket[prefixWord], newWordItem) 73 | } 74 | } else { 75 | bucket[prefixWord] = append(bucket[prefixWord], Item{ 76 | word: word, 77 | freq: 1, 78 | }) 79 | } 80 | } 81 | } 82 | 83 | func filterMatchingWordItem(wordList []Item) []string { 84 | var matchingStrings []string 85 | for i := 0; i < len(wordList) && i < 20; i++ { 86 | matchingStrings = append(matchingStrings, wordList[i].word) 87 | } 88 | return matchingStrings 89 | } 90 | 91 | func findWord(wordList []Item, word string) (int, bool) { 92 | for i := 0; i < len(wordList); i++ { 93 | if wordList[i].word == word { 94 | return i, true 95 | } 96 | } 97 | return -1, false 98 | } 99 | 100 | func removeWordItem(wordList []Item, idx int) []Item { 101 | return append(wordList[:idx], wordList[idx+1:]...) 102 | } 103 | 104 | func insertWordItem(wordList []Item, newWord Item) []Item { 105 | if len(wordList) == 100 { 106 | wordList = wordList[:99] 107 | } 108 | pos := len(wordList) 109 | for i := len(wordList) - 1; i >= 0; i-- { 110 | if wordList[i].freq >= newWord.freq { 111 | break 112 | } 113 | pos-- 114 | } 115 | wordList = append(wordList, newWord) 116 | copy(wordList[pos+1:], wordList[pos:]) 117 | wordList[pos] = newWord 118 | return wordList 119 | 120 | } 121 | -------------------------------------------------------------------------------- /client/typeahead-search-app/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flash 2 | Flash is highly optimised typeahead(search recommendation) server. We are building it with an aim to learn and teach various tradeoffs/practices. 3 | While building it, we will use different data structures/storage devices/protocols/deployment strategies and compare them from different aspects. 4 | 5 | ## Design perspective 6 | 1. ### Expection with the server? 7 | keeping in mind the fact that we are designing for Humans. Average time at which humans respond is 200ms( interval b/w consecutive key stokes), So we need to keep this in mind and keep our latency < 200ms always and..... Amazon search recommendation api calls responds in around ~100ms. 8 | 9 | 2. ### Where are we storing our dataset (strings which server will recommend)? 10 | 11 | Lookup time for Memory, SSD, and HDD is 100ns, 150us, 10 ms respective. 12 | It makes sense for us to keep all data in memory itself for low latency. We can do sharding on range bases, if data grows more than the size of 1 node. further we can use disk to take backup by taking periodic snapshot of data, for fault tolerance on poweroff. Later, we can also try to use SSD for storage and see how trade off b/w cost vs latency works. 13 | 14 | 15 | 2. ### Which Data structure to choose for hold strings in memory? 16 | 17 | Our usecase is to fetch popular strings with same prefix. Trie looks intuitive here, but I feel we could perform better with hashmap as with hashmap it will be easy for us to shard, Maps are native for memory, and for every prefix as key, we can use a priority queue as value which contains all popular strings with same prefix as key. Doing this with trie will be little harder. But it's going to be interesting to compare both DS. Making an algorithm to scale them. 18 | 19 | 20 | 3. ### Are we taking care of protocol too? 21 | yes, Idea is to make api call to server with every key stroke in search box and return all strings with same prefix as response, means server will be in heavy read load. 22 | We can use websockets to faster resonse from server and not setting up TCP connection for every keystroke but I feel using ws is going to be overkill as we don't need duplex connection. We can start with HTTP and do some optimisations like adding "Connection: keep-alive" header to tell server to not close connection for subsequent connections. 23 | 24 | 4. ### Deployment Strategies. 25 | As latency is most important factor, We can try to deploy in various regions and using a load balancer to route to closes geolocation server. We need low latency, with high avaibility and less or eventual consistency that means it's fine if users in different region see different suggestions for their prefix. I feel deployment is dominant part in keeping latency low, We can do benchmarking after adding every new component(load balancer, sharding) to understand their affects. 26 | 27 | 5. ### Why Go? 28 | Keeping perfomance in mind, I chose GO over any iterperative language. Rust might be even better choice, but as I don't have enough knowledge with Rust rigth now so may be We an migrate it later. 29 | 30 | 6. ### Lot to add. 31 | 32 | 33 | ### To build server: 34 | ``` 35 | git clone https://github.com/Shubham8287/flash 36 | cd flash/server/src 37 | make run # start flash and node expoerter server 38 | make mon # to setup monitoring 39 | ``` 40 | 41 | ### Check if server is up: 42 | `curl localhost:8080/isAlive` 43 | You should get response - `Boss is always fine` 44 | 45 | To run actual Api hit - `localhost:8080/find?prefix=yo` 46 | you will get a response of top matching string starting with prefix "yo" 47 | ``` 48 | {"prefix":"yo","matches":["yo","yob","yobbo","yobboes","yobbos","yobi","yobs","yocco","yochel","yock","yocked","yockel","yockernut","yocking","yocks","yod","yode","yodel","yodeled","yodeler"]} 49 | ``` 50 | 51 | ### To profile: 52 | - import `_ "net/http/pprof"` 53 | - run `go tool pprof -http : http://localhost:8080/debug/pprof/{allocs/goroutine/heap/profile/etc} 54 | > for healthcheck route in localhost, I am getting response ~1-2ms. 55 | 56 | ## Handy commands 57 | - `go run ./...` - to run server 58 | - `lsof -i:[PORT]` - to know PID of proccess running on PORT. 59 | - `curl -w "@curl-format.txt" -s [URL]` - to know response time of your request with curl 60 | - `sudo pmap [PID]` - check total memory used by PID 61 | - `ab -n 100 -c 1 -k URL` - use apache bench to make n request with c concurrency. -k is to keep tcp connection open. 62 | 63 | -------------------------------------------------------------------------------- /server/notes/server-latency: -------------------------------------------------------------------------------- 1 | ## p95 with log and log in docker 2 | checks.........................: 100.00% ✓ 120993 ✗ 0 3 | data_received..................: 46 MB 736 kB/s 4 | data_sent......................: 12 MB 196 kB/s 5 | http_req_blocked...............: avg=496.3µs min=1.2µs med=2.8µs max=125.02ms p(90)=4.59µs p(95)=8.2µs 6 | http_req_connecting............: avg=400.74µs min=0s med=0s max=104.55ms p(90)=0s p(95)=0s 7 | http_req_duration..............: avg=6.23ms min=191.7µs med=1.04ms max=250.82ms p(90)=12.13ms p(95)=31.09ms 8 | { expected_response:true }...: avg=6.23ms min=191.7µs med=1.04ms max=250.82ms p(90)=12.13ms p(95)=31.09ms 9 | http_req_failed................: 0.00% ✓ 0 ✗ 120993 10 | http_req_receiving.............: avg=248.05µs min=10.8µs med=30.7µs max=126.15ms p(90)=131.3µs p(95)=226.6µs 11 | http_req_sending...............: avg=550.29µs min=4.4µs med=11.6µs max=104.49ms p(90)=272.7µs p(95)=815.42µs 12 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 13 | http_req_waiting...............: avg=5.43ms min=158.9µs med=892.31µs max=174.26ms p(90)=11.16ms p(95)=27.55ms 14 | http_reqs......................: 120993 1951.310417/s 15 | iteration_duration.............: avg=1s min=1s med=1s max=1.25s p(90)=1.01s p(95)=1.03s 16 | iterations.....................: 120993 1951.310417/s 17 | vus............................: 744 min=0 max=2000 18 | vus_max........................: 2000 min=1627 max=2000 19 | ## p95 with log as shell process 20 | checks.........................: 100.00% ✓ 81149 ✗ 0 21 | data_received..................: 31 MB 494 kB/s 22 | data_sent......................: 8.1 MB 131 kB/s 23 | http_req_blocked...............: avg=3.46ms min=1.2µs med=2.7µs max=550.29ms p(90)=4.4µs p(95)=11.3µs 24 | http_req_connecting............: avg=3.27ms min=0s med=0s max=372.12ms p(90)=0s p(95)=0s 25 | http_req_duration..............: avg=498.11ms min=172.8µs med=235.54ms max=4.95s p(90)=1.27s p(95)=2.1s 26 | { expected_response:true }...: avg=498.11ms min=172.8µs med=235.54ms max=4.95s p(90)=1.27s p(95)=2.1s 27 | http_req_failed................: 0.00% ✓ 0 ✗ 81149 28 | http_req_receiving.............: avg=1.02ms min=10.5µs med=24.2µs max=441.05ms p(90)=75.82µs p(95)=5.91ms 29 | http_req_sending...............: avg=2.2ms min=4.59µs med=11.1µs max=357.63ms p(90)=5.14ms p(95)=12.43ms 30 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 31 | http_req_waiting...............: avg=494.87ms min=146.7µs med=233.27ms max=4.94s p(90)=1.26s p(95)=2.1s 32 | http_reqs......................: 81149 1308.515824/s 33 | iteration_duration.............: avg=1.5s min=1s med=1.24s max=6.13s p(90)=2.27s p(95)=3.2s 34 | iterations.....................: 81149 1308.515824/s 35 | vus............................: 1090 min=0 max=2000 36 | vus_max........................: 2000 min=1350 max=2000 37 | 38 | 39 | ##ping on localhost 40 | ~0.05ms 41 | 42 | ## empty localhost server 43 | curl -w "@curl_latency" "http://localhost:8080/" -o /dev/null 44 | % Total % Received % Xferd Average Speed Time Time Time Current 45 | Dload Upload Total Spent Left Speed 46 | 100 10 100 10 0 0 22371 0 --:--:-- --:--:-- --:--:-- 10000 47 | time_namelookup: 0.000014s 48 | time_connect: 0.000218s 49 | time_appconnect: 0.000000s 50 | time_pretransfer: 0.000241s 51 | time_redirect: 0.000000s 52 | time_starttransfer: 0.000420s 53 | ---------- 54 | time_total: 0.000447s = ~0.5ms 55 | 56 | 57 | 58 | ## 400 req on healthcheck 59 | http_req_blocked...............: avg=27.45µs min=3.35µs med=7.67µs max=512.75µs p(90)=10.51µs p(95)=32.51µs 60 | http_req_connecting............: avg=13.33µs min=0s med=0s max=341.69µs p(90)=0s p(95)=0s 61 | http_req_duration..............: avg=504.75µs min=176.81µs med=506.77µs max=695.92µs p(90)=587.81µs p(95)=606.93µs 62 | { expected_response:true }...: avg=504.75µs min=176.81µs med=506.77µs max=695.92µs p(90)=587.81µs p(95)=606.93µs 63 | http_req_failed................: 0.00% ✓ 0 ✗ 419 64 | http_req_receiving.............: avg=87.42µs min=29.86µs med=85.93µs max=159.86µs p(90)=105.28µs p(95)=119.06µs 65 | http_req_sending...............: avg=39.28µs min=13.14µs med=34.53µs max=185.85µs p(90)=46.76µs p(95)=71.25µs 66 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 67 | http_req_waiting...............: avg=378.04µs min=118.38µs med=379.77µs max=503.55µs p(90)=447.63µs p(95)=466.73µs 68 | http_reqs......................: 419 19.062438/s 69 | iteration_duration.............: avg=1s min=1s med=1s max=1s p(90)=1s p(95)=1s 70 | iterations.....................: 419 19.062438/s 71 | = ~0.5ms 72 | 73 | ## 400k on healthcheck 74 | running (22.0s), 0000/2000 VUs, 41957 complete and 0 interrupted iterations 75 | default ✓ [======================================] 0000/2000 VUs 21s 76 | 77 | ✓ status was 200 78 | 79 | checks.........................: 100.00% ✓ 41957 ✗ 0 80 | data_received..................: 5.7 MB 259 kB/s 81 | data_sent......................: 3.7 MB 166 kB/s 82 | http_req_blocked...............: avg=34.45µs min=824ns med=4.54µs max=35.2ms p(90)=9.04µs p(95)=62.65µs 83 | http_req_connecting............: avg=23.12µs min=0s med=0s max=35.12ms p(90)=0s p(95)=0s 84 | http_req_duration..............: avg=435.42µs min=42.14µs med=301.79µs max=17.78ms p(90)=892.83µs p(95)=1.34ms 85 | { expected_response:true }...: avg=435.42µs min=42.14µs med=301.79µs max=17.78ms p(90)=892.83µs p(95)=1.34ms 86 | http_req_failed................: 0.00% ✓ 0 ✗ 41957 87 | http_req_receiving.............: avg=61.54µs min=5.73µs med=43.47µs max=4.45ms p(90)=77.57µs p(95)=108.81µs 88 | http_req_sending...............: avg=60.8µs min=3.77µs med=19.38µs max=4.21ms p(90)=59.33µs p(95)=227.02µs 89 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 90 | http_req_waiting...............: avg=313.06µs min=21.36µs med=220.16µs max=16.58ms p(90)=606.44µs p(95)=915.34µs 91 | http_reqs......................: 41957 1906.721746/s 92 | iteration_duration.............: avg=1s min=1s med=1s max=1.04s p(90)=1s p(95)=1s 93 | iterations.....................: 41957 1906.721746/s 94 | vus............................: 1402 min=655 max=2000 95 | vus_max........................: 2000 min=2000 max=2000 96 | =~1ms 97 | 98 | ## 400 req on /find 99 | checks.........................: 100.00% ✓ 419 ✗ 0 100 | data_received..................: 158 kB 7.2 kB/s 101 | data_sent......................: 43 kB 1.9 kB/s 102 | http_req_blocked...............: avg=26.56µs min=2.82µs med=7.48µs max=476.79µs p(90)=9.44µs p(95)=37.49µs 103 | http_req_connecting............: avg=12.94µs min=0s med=0s max=336.05µs p(90)=0s p(95)=0s 104 | http_req_duration..............: avg=647.24µs min=251.94µs med=636.5µs max=4.87ms p(90)=738.52µs p(95)=763.65µs 105 | { expected_response:true }...: avg=647.24µs min=251.94µs med=636.5µs max=4.87ms p(90)=738.52µs p(95)=763.65µs 106 | http_req_failed................: 0.00% ✓ 0 ✗ 419 107 | http_req_receiving.............: avg=103.85µs min=30.13µs med=101.21µs max=228.98µs p(90)=134.74µs p(95)=147.76µs 108 | http_req_sending...............: avg=42.72µs min=11.4µs med=38.57µs max=176.05µs p(90)=52.38µs p(95)=75.83µs 109 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 110 | http_req_waiting...............: avg=500.66µs min=210.4µs med=491.08µs max=4.67ms p(90)=580.4µs p(95)=596.82µs 111 | http_reqs......................: 419 19.057783/s 112 | iteration_duration.............: avg=1s min=1s med=1s max=1s p(90)=1s p(95)=1s 113 | 114 | = ~0.7ms 115 | 116 | 117 | ## 40k req on /find with no log or log to file 118 | checks.........................: 100.00% ✓ 41965 ✗ 0 119 | data_received..................: 16 MB 719 kB/s 120 | data_sent......................: 4.3 MB 193 kB/s 121 | http_req_blocked...............: avg=53.37µs min=884ns med=4.68µs max=41.27ms p(90)=9.12µs p(95)=85.36µs 122 | http_req_connecting............: avg=33µs min=0s med=0s max=41.2ms p(90)=0s p(95)=0s 123 | http_req_duration..............: avg=878.96µs min=49.81µs med=355.43µs max=47.86ms p(90)=1.52ms p(95)=2.49ms 124 | { expected_response:true }...: avg=878.96µs min=49.81µs med=355.43µs max=47.86ms p(90)=1.52ms p(95)=2.49ms 125 | http_req_failed................: 0.00% ✓ 0 ✗ 41965 126 | http_req_receiving.............: avg=93.99µs min=7.59µs med=47.66µs max=22.69ms p(90)=101.29µs p(95)=268.23µs 127 | http_req_sending...............: avg=130.65µs min=4.11µs med=20.52µs max=27.92ms p(90)=132.52µs p(95)=419.53µs 128 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 129 | http_req_waiting...............: avg=654.31µs min=32.52µs med=255.54µs max=41.91ms p(90)=1.03ms p(95)=1.75ms 130 | http_reqs......................: 41965 1907.081841/s 131 | iteration_duration.............: avg=1s min=1s med=1s max=1.06s p(90)=1s p(95)=1s 132 | iterations.....................: 41965 1907.081841/s 133 | vus............................: 1720 min=360 max=2000 134 | vus_max........................: 2000 min=2000 max=2000 135 | ~=20ms 136 | 137 | ## 40k with one log 138 | 139 | checks.........................: 100.00% ✓ 39073 ✗ 0 140 | data_received..................: 15 MB 672 kB/s 141 | data_sent......................: 4.0 MB 181 kB/s 142 | http_req_blocked...............: avg=137.9µs min=853ns med=4.76µs max=59.25ms p(90)=8.28µs p(95)=95.24µs 143 | http_req_connecting............: avg=69.23µs min=0s med=0s max=43.92ms p(90)=0s p(95)=47.52µs 144 | http_req_duration..............: avg=77.33ms min=74.23µs med=823.24µs max=2.45s p(90)=80.97ms p(95)=496.05ms 145 | { expected_response:true }...: avg=77.33ms min=74.23µs med=823.24µs max=2.45s p(90)=80.97ms p(95)=496.05ms 146 | http_req_failed................: 0.00% ✓ 0 ✗ 39073 147 | http_req_receiving.............: avg=178.46µs min=8.65µs med=47.89µs max=41.88ms p(90)=117.14µs p(95)=372.95µs 148 | http_req_sending...............: avg=470.57µs min=4.01µs med=21.35µs max=42.19ms p(90)=301.42µs p(95)=1.55ms 149 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 150 | http_req_waiting...............: avg=76.68ms min=53.56µs med=599.58µs max=2.45s p(90)=80.9ms p(95)=495.99ms 151 | http_reqs......................: 39073 1781.48041/s 152 | iteration_duration.............: avg=1.07s min=1s med=1s max=3.48s p(90)=1.08s p(95)=1.49s 153 | iterations.....................: 39073 1781.48041/s 154 | vus............................: 1266 min=850 max=2000 155 | vus_max........................: 2000 min=2000 max=2000 156 | 157 | ## 20k concurrent user making 92k requests with log 158 | running (25.8s), 00000/20000 VUs, 92370 complete and 0 interrupted iterations 159 | default ✓ [======================================] 00000/20000 VUs 21s 160 | 161 | ✓ status was 200 162 | 163 | checks.........................: 100.00% ✓ 92370 ✗ 0 164 | data_received..................: 35 MB 1.4 MB/s 165 | data_sent......................: 9.4 MB 364 kB/s 166 | http_req_blocked...............: avg=41.92ms min=862ns med=4.57µs max=864.37ms p(90)=150.95ms p(95)=275.75ms 167 | http_req_connecting............: avg=41.47ms min=0s med=0s max=837.2ms p(90)=150.41ms p(95)=263.59ms 168 | http_req_duration..............: avg=3.76s min=101.27µs med=3.97s max=11.95s p(90)=5.62s p(95)=6.51s 169 | { expected_response:true }...: avg=3.76s min=101.27µs med=3.97s max=11.95s p(90)=5.62s p(95)=6.51s 170 | http_req_failed................: 0.00% ✓ 0 ✗ 92370 171 | http_req_receiving.............: avg=417.99µs min=9.77µs med=44.74µs max=346.94ms p(90)=69.5µs p(95)=136.42µs 172 | http_req_sending...............: avg=3.64ms min=4.32µs med=22.07µs max=381.16ms p(90)=8.99ms p(95)=17.01ms 173 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 174 | http_req_waiting...............: avg=3.75s min=74.57µs med=3.97s max=11.95s p(90)=5.62s p(95)=6.51s 175 | http_reqs......................: 92370 3586.930593/s 176 | iteration_duration.............: avg=4.82s min=1s med=5.04s max=12.95s p(90)=6.64s p(95)=7.52s 177 | iterations.....................: 92370 3586.930593/s 178 | vus............................: 818 min=0 max=20000 179 | vus_max........................: 20000 min=1967 max=20000 180 | 181 | ## 20k concurrent user making 267k requests without log or log with file 182 | running (22.0s), 00000/20000 VUs, 267924 complete and 0 interrupted iterations 183 | default ✓ [======================================] 00000/20000 VUs 21s 184 | 185 | ✓ status was 200 186 | 187 | checks.........................: 100.00% ✓ 267924 ✗ 0 188 | data_received..................: 101 MB 4.6 MB/s 189 | data_sent......................: 27 MB 1.2 MB/s 190 | http_req_blocked...............: avg=31.6ms min=880ns med=2.56µs max=1.45s p(90)=9.05µs p(95)=196.52ms 191 | http_req_connecting............: avg=30.83ms min=0s med=0s max=1.29s p(90)=0s p(95)=196.32ms 192 | http_req_duration..............: avg=208.22ms min=59.11µs med=134.03ms max=2.04s p(90)=553.1ms p(95)=711.66ms 193 | { expected_response:true }...: avg=208.22ms min=59.11µs med=134.03ms max=2.04s p(90)=553.1ms p(95)=711.66ms 194 | http_req_failed................: 0.00% ✓ 0 ✗ 267924 195 | http_req_receiving.............: avg=947.42µs min=7.9µs med=20.98µs max=699.6ms p(90)=124.45µs p(95)=1ms 196 | http_req_sending...............: avg=8.67ms min=4.53µs med=15.93µs max=2.04s p(90)=20.23ms p(95)=33.49ms 197 | http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s 198 | http_req_waiting...............: avg=198.61ms min=40.07µs med=128.94ms max=1.27s p(90)=531.53ms p(95)=683.33ms 199 | http_reqs......................: 267924 12156.143024/s 200 | iteration_duration.............: avg=1.4s min=1s med=1.17s max=6.12s p(90)=2.14s p(95)=2.64s 201 | iterations.....................: 267924 12156.143024/s 202 | vus............................: 14593 min=0 max=20000 203 | vus_max........................: 20000 min=1666 max=20000 -------------------------------------------------------------------------------- /server/tests/test_data.json: -------------------------------------------------------------------------------- 1 | [ 2 | "appreciative", 3 | "unstainable", 4 | "semiflexion", 5 | "parrakeet", 6 | "empidonax", 7 | "bushfire", 8 | "moksha", 9 | "disillusioning", 10 | "set", 11 | "steppeland", 12 | "mimsy", 13 | "adeleidae", 14 | "nonjudgmental", 15 | "bulldogism", 16 | "ovipara", 17 | "turbidness", 18 | "dissectible", 19 | "athenaeums", 20 | "vertebriform", 21 | "erythroclasis", 22 | "ceroma", 23 | "disozonize", 24 | "nonstudiousness", 25 | "stomatode", 26 | "unpriority", 27 | "rhizautoicous", 28 | "muscicapine", 29 | "pollucite", 30 | "coclea", 31 | "portuguese", 32 | "inaneness", 33 | "perturbant", 34 | "sphenopsid", 35 | "strombite", 36 | "pearl", 37 | "anticonscriptive", 38 | "tantalum", 39 | "tritopine", 40 | "beneficience", 41 | "trafficks", 42 | "bumbledom", 43 | "antibubonic", 44 | "rhamninose", 45 | "catholicos", 46 | "fissipeds", 47 | "immensity", 48 | "chromosomic", 49 | "overmelodiously", 50 | "limuloidea", 51 | "intradermically", 52 | "rober", 53 | "bastide", 54 | "metoposcopy", 55 | "pointedly", 56 | "graphed", 57 | "beggaries", 58 | "symbolistic", 59 | "isomyarian", 60 | "camister", 61 | "heteronomic", 62 | "reiterance", 63 | "witching", 64 | "rencounter", 65 | "microns", 66 | "photuria", 67 | "expressage", 68 | "inkhorn", 69 | "nasosinusitis", 70 | "adib", 71 | "gild", 72 | "noncircumspectly", 73 | "bilobular", 74 | "fallage", 75 | "torpid", 76 | "tracks", 77 | "averting", 78 | "londonese", 79 | "thanatopsis", 80 | "intown", 81 | "medication", 82 | "unconfidentialness", 83 | "spuriousness", 84 | "liberaliser", 85 | "pigman", 86 | "amnesties", 87 | "handjar", 88 | "pejorism", 89 | "reavoid", 90 | "latiseptate", 91 | "syncretizing", 92 | "leptynite", 93 | "unpervaded", 94 | "hagiocracies", 95 | "holist", 96 | "carbaryl", 97 | "nonsuppositional", 98 | "joculator", 99 | "indra", 100 | "unspherical", 101 | "pretire", 102 | "vanadosilicate", 103 | "birchbark", 104 | "phycoerythrin", 105 | "nonrealism", 106 | "ergatomorphic", 107 | "wachna", 108 | "clergymen", 109 | "brahms", 110 | "gonophorous", 111 | "enneahedrons", 112 | "dogfighting", 113 | "unsulliedness", 114 | "wheedles", 115 | "psyches", 116 | "overembellishing", 117 | "podesta", 118 | "terpsichorean", 119 | "sequaces", 120 | "adelphous", 121 | "horselaugher", 122 | "waterblink", 123 | "visionarily", 124 | "unsupernatural", 125 | "unnecessary", 126 | "fault", 127 | "algerita", 128 | "squarehead", 129 | "activated", 130 | "dharnas", 131 | "craniacromial", 132 | "amidating", 133 | "untuckered", 134 | "trip", 135 | "splinterproof", 136 | "numbing", 137 | "conocephalus", 138 | "pyohemothorax", 139 | "antthrush", 140 | "meconidium", 141 | "seventieths", 142 | "stratagem", 143 | "bowings", 144 | "doubtful", 145 | "motacilla", 146 | "cerebrotomy", 147 | "allargando", 148 | "obsoletely", 149 | "ostler", 150 | "unprofuse", 151 | "kacha", 152 | "prealphabetically", 153 | "baysmelt", 154 | "schizogony", 155 | "vorticellae", 156 | "somnambulator", 157 | "tapping", 158 | "combinement", 159 | "androcracy", 160 | "prespecializing", 161 | "remediably", 162 | "cardiomyomalacia", 163 | "congrid", 164 | "nonsedimentable", 165 | "bolty", 166 | "arnotta", 167 | "autarkist", 168 | "andalusian", 169 | "densitometry", 170 | "gestic", 171 | "phenomenalist", 172 | "psychometric", 173 | "celeusma", 174 | "tashlik", 175 | "epithem", 176 | "ciliately", 177 | "supernationalist", 178 | "microcytic", 179 | "overgreedily", 180 | "theriomorph", 181 | "cranesbill", 182 | "trolled", 183 | "nonbookish", 184 | "transversality", 185 | "isopoda", 186 | "tankah", 187 | "ungainfulness", 188 | "doc", 189 | "instreaming", 190 | "jimjams", 191 | "mutedness", 192 | "alcedininae", 193 | "evirato", 194 | "ottawa", 195 | "crackly", 196 | "unbanded", 197 | "overmodifies", 198 | "sulphoselenide", 199 | "mighted", 200 | "meddlesomely", 201 | "helled", 202 | "glycolic", 203 | "gamesmanship", 204 | "hummocks", 205 | "warehousing", 206 | "pechys", 207 | "rhinobyon", 208 | "flaith", 209 | "nemeses", 210 | "overinstructiveness", 211 | "quadrinucleate", 212 | "ritornellos", 213 | "noncrystallizable", 214 | "chylifactory", 215 | "grab", 216 | "spasmophile", 217 | "inthrall", 218 | "garaging", 219 | "jalousies", 220 | "koninckite", 221 | "thoraces", 222 | "miscites", 223 | "groot", 224 | "lavages", 225 | "foretopman", 226 | "hypnesthetic", 227 | "betook", 228 | "tablefellowship", 229 | "wooded", 230 | "untraitorously", 231 | "luminificent", 232 | "chromatically", 233 | "overdisciplined", 234 | "toponymies", 235 | "mastoiditis", 236 | "drachmae", 237 | "abutilons", 238 | "ungruesome", 239 | "startups", 240 | "windplayer", 241 | "sarcophagic", 242 | "cader", 243 | "grouthead", 244 | "glaserite", 245 | "musicological", 246 | "infantas", 247 | "etiolates", 248 | "sizably", 249 | "incarnational", 250 | "gardenlike", 251 | "unbudgingly", 252 | "conventioner", 253 | "rickettsial", 254 | "tampions", 255 | "gynecomorphous", 256 | "almacigo", 257 | "nontropically", 258 | "lignosity", 259 | "intortillage", 260 | "hasidic", 261 | "bivouacked", 262 | "monogenically", 263 | "similary", 264 | "confessant", 265 | "pentalpha", 266 | "sweeteners", 267 | "ventriculite", 268 | "congreve", 269 | "antefurca", 270 | "externation", 271 | "tasbih", 272 | "colorimetrically", 273 | "redacted", 274 | "incur", 275 | "accidie", 276 | "gardenlike", 277 | "prithee", 278 | "bedazzles", 279 | "gyres", 280 | "domiciles", 281 | "veining", 282 | "sulphotelluride", 283 | "azine", 284 | "goldurn", 285 | "liss", 286 | "casketed", 287 | "phlegma", 288 | "roseous", 289 | "cheerers", 290 | "siphonapterous", 291 | "paragraphia", 292 | "boltage", 293 | "gad", 294 | "lax", 295 | "saccharobutyric", 296 | "strychninism", 297 | "veneris", 298 | "bellbirds", 299 | "japishly", 300 | "sontag", 301 | "vesica", 302 | "mutinied", 303 | "revocableness", 304 | "avarish", 305 | "pyrotechnician", 306 | "biacuminate", 307 | "satrapical", 308 | "drizzlier", 309 | "semiclerically", 310 | "abrachia", 311 | "pursuits", 312 | "directively", 313 | "unlethal", 314 | "peridiastole", 315 | "akee", 316 | "correctory", 317 | "diamondwise", 318 | "bribers", 319 | "akra", 320 | "reforward", 321 | "jinrikiman", 322 | "lightninged", 323 | "skeleton", 324 | "silicons", 325 | "chorded", 326 | "principling", 327 | "reaccredit", 328 | "communiqu", 329 | "fastigiated", 330 | "destining", 331 | "cabaan", 332 | "mosul", 333 | "dotards", 334 | "authenticalness", 335 | "phalangologist", 336 | "cruelhearted", 337 | "proved", 338 | "semitrailer", 339 | "trapeziums", 340 | "insessores", 341 | "consocies", 342 | "ashfall", 343 | "hent", 344 | "unarithmetical", 345 | "mormyrus", 346 | "hirsles", 347 | "teetering", 348 | "coconqueror", 349 | "expressage", 350 | "condivision", 351 | "guyots", 352 | "inequitate", 353 | "irreformable", 354 | "prowess", 355 | "catapult", 356 | "besnowed", 357 | "montanans", 358 | "necessariness", 359 | "fault", 360 | "sickish", 361 | "loup", 362 | "excise", 363 | "incorruptibly", 364 | "tharf", 365 | "septarium", 366 | "stringybark", 367 | "categorem", 368 | "octapody", 369 | "perpetuities", 370 | "tembeitera", 371 | "legibilities", 372 | "astonishedly", 373 | "nonbotanic", 374 | "akebia", 375 | "forages", 376 | "committent", 377 | "noachical", 378 | "plurennial", 379 | "semicrome", 380 | "araneid", 381 | "waired", 382 | "nd", 383 | "busway", 384 | "perh", 385 | "respreads", 386 | "mails", 387 | "bancus", 388 | "pillaging", 389 | "labyrinthitis", 390 | "tushy", 391 | "unbeheld", 392 | "succinctness", 393 | "cupromanganese", 394 | "unproscribable", 395 | "dijudicate", 396 | "phytographic", 397 | "unwatered", 398 | "marmor", 399 | "obvoluted", 400 | "beastbane", 401 | "recreates", 402 | "loopholed", 403 | "cystotomies", 404 | "quenches", 405 | "superimpersonally", 406 | "strutted", 407 | "dactylous", 408 | "suggestibleness", 409 | "siliquous", 410 | "pavois", 411 | "monopolylogue", 412 | "joinered", 413 | "wretchlessly", 414 | "toilets", 415 | "verrucoseness", 416 | "ophthalmometer", 417 | "sanskritist", 418 | "dice", 419 | "fundraising", 420 | "betag", 421 | "mixtilineal", 422 | "puyallup", 423 | "postings", 424 | "drowningly", 425 | "entailer", 426 | "flutiest", 427 | "tradesman", 428 | "buccinal", 429 | "rectification", 430 | "opposite", 431 | "jehovic", 432 | "faventine", 433 | "faculae", 434 | "astonished", 435 | "dolour", 436 | "pipers", 437 | "embracer", 438 | "dhan", 439 | "unceremoniousness", 440 | "nonsubmergible", 441 | "tidesurveyor", 442 | "agios", 443 | "unloaded", 444 | "malabarese", 445 | "adtevac", 446 | "hooven", 447 | "hastefully", 448 | "browned", 449 | "unepauleted", 450 | "encrusted", 451 | "hoc", 452 | "unjaded", 453 | "ditheism", 454 | "vamoosing", 455 | "holmic", 456 | "scension", 457 | "equidivision", 458 | "intercourse", 459 | "hance", 460 | "fabricant", 461 | "powwowism", 462 | "siamoise", 463 | "washaki", 464 | "tarhood", 465 | "dioceses", 466 | "verisimilitudinous", 467 | "havioured", 468 | "pilotings", 469 | "fugate", 470 | "misparsing", 471 | "sinistrality", 472 | "plashingly", 473 | "glumal", 474 | "fellowlike", 475 | "noctiluscence", 476 | "nonpainter", 477 | "behavers", 478 | "roomier", 479 | "entrained", 480 | "legatory", 481 | "scooch", 482 | "isobutene", 483 | "remnantal", 484 | "stickybeak", 485 | "yis", 486 | "satrapy", 487 | "ligustrin", 488 | "ripplier", 489 | "geopolitics", 490 | "jiggled", 491 | "plebicolar", 492 | "roguish", 493 | "pantherish", 494 | "keffel", 495 | "ultrastellar", 496 | "enzymology", 497 | "blastoporphyritic", 498 | "secretional", 499 | "caodaism", 500 | "cranker", 501 | "dictyosiphon", 502 | "azotometer", 503 | "antiaggressionist", 504 | "phlebectomy", 505 | "reyoked", 506 | "reavowed", 507 | "ppd", 508 | "knappish", 509 | "taciturnity", 510 | "gonadal", 511 | "unprocessed", 512 | "aphorist", 513 | "escharine", 514 | "objectify", 515 | "petallike", 516 | "pimenton", 517 | "planetesimal", 518 | "satura", 519 | "praedial", 520 | "unpremeditate", 521 | "unprayable", 522 | "denitrificator", 523 | "scares", 524 | "whimming", 525 | "lycanthropist", 526 | "roistered", 527 | "euspongia", 528 | "minahassa", 529 | "concubitus", 530 | "bleymes", 531 | "agatelike", 532 | "sadistic", 533 | "chemicoluminescent", 534 | "fabricators", 535 | "misfielding", 536 | "hedgewood", 537 | "somepart", 538 | "xerotripsis", 539 | "aristate", 540 | "psychostatically", 541 | "measled", 542 | "oilheating", 543 | "norleucine", 544 | "laddock", 545 | "gynaecomasty", 546 | "harnesslike", 547 | "vanfoss", 548 | "grades", 549 | "alcoholate", 550 | "abstrict", 551 | "schoolgirlishness", 552 | "douane", 553 | "overluxuriant", 554 | "unanguished", 555 | "deforcer", 556 | "fuddles", 557 | "otiant", 558 | "oogeny", 559 | "ternary", 560 | "reductant", 561 | "wakeup", 562 | "fucker", 563 | "lianoid", 564 | "cormus", 565 | "seraing", 566 | "euboic", 567 | "unexpressible", 568 | "unmeltable", 569 | "poalike", 570 | "checkbit", 571 | "snitchy", 572 | "ramosely", 573 | "bizarrely", 574 | "immunogenetics", 575 | "perniciousness", 576 | "tagetol", 577 | "murmurlessly", 578 | "fantods", 579 | "pentremites", 580 | "underrating", 581 | "levis", 582 | "brasier", 583 | "botchier", 584 | "wavefront", 585 | "gelsemic", 586 | "seismograms", 587 | "wans", 588 | "unpuffing", 589 | "evacue", 590 | "cavies", 591 | "funnies", 592 | "imaginativeness", 593 | "unbrown", 594 | "palustrine", 595 | "springtrap", 596 | "reshooting", 597 | "thecae", 598 | "unwired", 599 | "stercoraries", 600 | "waterleaf", 601 | "bacbakiri", 602 | "suprapubian", 603 | "juicing", 604 | "succulency", 605 | "preinspector", 606 | "dudler", 607 | "liveableness", 608 | "padcloth", 609 | "outbeaming", 610 | "zoonoses", 611 | "overshowered", 612 | "pyrotechnician", 613 | "potholders", 614 | "valleywise", 615 | "organographist", 616 | "hairbell", 617 | "semirattlesnake", 618 | "sulphobismuthite", 619 | "cathartically", 620 | "eruditely", 621 | "psoriases", 622 | "girthline", 623 | "embrica", 624 | "reservedly", 625 | "debited", 626 | "cryptopyic", 627 | "underprincipal", 628 | "reclaimers", 629 | "unforgiving", 630 | "outshifts", 631 | "fido", 632 | "cattlebush", 633 | "autoimmunize", 634 | "onymancy", 635 | "nondurable", 636 | "bromopnea", 637 | "rallentando", 638 | "discontinuity", 639 | "kapas", 640 | "duressor", 641 | "screams", 642 | "siderographist", 643 | "unritually", 644 | "commandeering", 645 | "passableness", 646 | "spurdog", 647 | "colyone", 648 | "hematogenous", 649 | "sternness", 650 | "untempested", 651 | "pudical", 652 | "toxiinfection", 653 | "cocoanut", 654 | "rebate", 655 | "frass", 656 | "swanpans", 657 | "darling", 658 | "romanos", 659 | "shema", 660 | "disquietedness", 661 | "lichenian", 662 | "detubation", 663 | "hemase", 664 | "degas", 665 | "deary", 666 | "pyramidion", 667 | "begaze", 668 | "subcrureus", 669 | "shrubless", 670 | "souse", 671 | "penorcon", 672 | "diakinetic", 673 | "elvanite", 674 | "quadruplicate", 675 | "unchoke", 676 | "cherubic", 677 | "operabilities", 678 | "ondagram", 679 | "amusive", 680 | "carrow", 681 | "counterindoctrination", 682 | "unbehoving", 683 | "plantarium", 684 | "reprosecute", 685 | "evetide", 686 | "podagras", 687 | "frayne", 688 | "emoluments", 689 | "bertha", 690 | "dysgenesic", 691 | "pycnic", 692 | "arefact", 693 | "sinistrorsal", 694 | "dependence", 695 | "pharmaceutics", 696 | "laughterful", 697 | "sympathetectomies", 698 | "parameterize", 699 | "beclog", 700 | "noniodized", 701 | "reclaim", 702 | "overmans", 703 | "repropitiation", 704 | "mentalistic", 705 | "episcopising", 706 | "fibrotuberculosis", 707 | "delichon", 708 | "vesicularly", 709 | "apostemate", 710 | "syzygium", 711 | "emersonian", 712 | "celioparacentesis", 713 | "schismatize", 714 | "ptychosperma", 715 | "featherbone", 716 | "thelphusidae", 717 | "outfled", 718 | "jolts", 719 | "forestries", 720 | "unrequisitioned", 721 | "currs", 722 | "castellatus", 723 | "proseminary", 724 | "livering", 725 | "diapasm", 726 | "chondriomere", 727 | "gell", 728 | "demulsion", 729 | "hellicate", 730 | "roughens", 731 | "argentine", 732 | "unavengingly", 733 | "condemns", 734 | "untrainable", 735 | "galavanting", 736 | "locators", 737 | "conations", 738 | "tunnellike", 739 | "shammas", 740 | "seedtime", 741 | "polarizable", 742 | "urophi", 743 | "reckonings", 744 | "orientated", 745 | "harkening", 746 | "mimeo", 747 | "unpropitiatedness", 748 | "unshanked", 749 | "virally", 750 | "ciphertexts", 751 | "philomelian", 752 | "septette", 753 | "miszealous", 754 | "octangular", 755 | "semihistoric", 756 | "passerby", 757 | "copaiva", 758 | "procontinuation", 759 | "mouflons", 760 | "viz", 761 | "treague", 762 | "monopitch", 763 | "stiffed", 764 | "hussydom", 765 | "unclify", 766 | "turcopole", 767 | "prospectuses", 768 | "soosoo", 769 | "mascagnite", 770 | "obstinacious", 771 | "confederatism", 772 | "quinquenerved", 773 | "recking", 774 | "trimorphism", 775 | "affirmly", 776 | "steersman", 777 | "hypodiploid", 778 | "alphabetizing", 779 | "undecillionth", 780 | "shogun", 781 | "realter", 782 | "quattie", 783 | "heinousness", 784 | "precompiling", 785 | "flossflower", 786 | "thecasporal", 787 | "infringer", 788 | "headier", 789 | "microseismicity", 790 | "comate", 791 | "cetologist", 792 | "enrober", 793 | "elastases", 794 | "reefing", 795 | "outprayed", 796 | "contortionistic", 797 | "kampongs", 798 | "intemerate", 799 | "peulvan", 800 | "rheo", 801 | "sailflying", 802 | "signa", 803 | "legumins", 804 | "relumines", 805 | "birls", 806 | "misween", 807 | "omnifying", 808 | "crotalo", 809 | "cheesecake", 810 | "hydragogy", 811 | "alkalemia", 812 | "metepisternal", 813 | "badon", 814 | "untoured", 815 | "skedaddled", 816 | "catechetic", 817 | "cased", 818 | "mesepimeral", 819 | "underdogs", 820 | "kaddish", 821 | "colourize", 822 | "machar", 823 | "striffen", 824 | "slurried", 825 | "lindo", 826 | "lurdanism", 827 | "sabbathize", 828 | "dehydrogenized", 829 | "martes", 830 | "cunctatious", 831 | "nabcheat", 832 | "hackles", 833 | "poetized", 834 | "overquarter", 835 | "redeny", 836 | "playwright", 837 | "diesel", 838 | "chartroom", 839 | "uncavernous", 840 | "formicoidea", 841 | "noneloquently", 842 | "supersevere", 843 | "raver", 844 | "shines", 845 | "nailhead", 846 | "allicient", 847 | "unbleeding", 848 | "hick", 849 | "hemadromograph", 850 | "delatinization", 851 | "manuscript", 852 | "symphily", 853 | "unlikeable", 854 | "stringendos", 855 | "myograph", 856 | "deltation", 857 | "caranga", 858 | "phaseal", 859 | "maracas", 860 | "txt", 861 | "epididymodeferentectomy", 862 | "polydental", 863 | "defibrillation", 864 | "nonfeudal", 865 | "inalacrity", 866 | "metabolised", 867 | "woodcraft", 868 | "monticuline", 869 | "pteraspidae", 870 | "palfrey", 871 | "subderivative", 872 | "nonservileness", 873 | "kjeldahlization", 874 | "witter", 875 | "autometry", 876 | "cai", 877 | "interlunar", 878 | "diplegia", 879 | "methodise", 880 | "nonmystic", 881 | "osmophore", 882 | "kilopound", 883 | "graft", 884 | "ejusdem", 885 | "prosubstantive", 886 | "androgyny", 887 | "cogeneric", 888 | "smee", 889 | "counterclockwise", 890 | "scantle", 891 | "moror", 892 | "slitlike", 893 | "gimel", 894 | "nitrosulphonic", 895 | "evolutionarily", 896 | "superdifficult", 897 | "precorruption", 898 | "tourneur", 899 | "repeg", 900 | "hortonolite", 901 | "reclinate", 902 | "unpredicableness", 903 | "merenchymatous", 904 | "bicameral", 905 | "unvirtue", 906 | "superquoted", 907 | "mercurially", 908 | "simblot", 909 | "revolvingly", 910 | "rearward", 911 | "faradaic", 912 | "interspinous", 913 | "sluggish", 914 | "haemothorax", 915 | "exegetically", 916 | "imidazole", 917 | "roughers", 918 | "solidifies", 919 | "monad", 920 | "coordinative", 921 | "disapprobation", 922 | "unperceptibly", 923 | "untroublable", 924 | "faraon", 925 | "rupture", 926 | "perpetuation", 927 | "basified", 928 | "juris", 929 | "juniors", 930 | "venipuncture", 931 | "overnervously", 932 | "whipstock", 933 | "shouldn", 934 | "dramaturgy", 935 | "abattis", 936 | "powderization", 937 | "mistide", 938 | "ricardianism", 939 | "tinwork", 940 | "stations", 941 | "chacona", 942 | "nidamental", 943 | "trancoidal", 944 | "aspidocephali", 945 | "thunderstricken", 946 | "thysanopterous", 947 | "pteroclidae", 948 | "pandiabolism", 949 | "noncaffeinic", 950 | "suffixer", 951 | "yohimbe", 952 | "tetracoralline", 953 | "stainably", 954 | "insufflator", 955 | "slouchiness", 956 | "squandered", 957 | "hypodermatically", 958 | "canthal", 959 | "counterpoising", 960 | "westernizing", 961 | "ighly", 962 | "poetastress", 963 | "enveigle", 964 | "hoarders", 965 | "merchantableness", 966 | "cystignathine", 967 | "tobogganeer", 968 | "collect", 969 | "hereness", 970 | "lacustrian", 971 | "imperializing", 972 | "cisandine", 973 | "relentlessness", 974 | "nonpedagogic", 975 | "marvin", 976 | "appense", 977 | "fibromyoma", 978 | "formulisation", 979 | "enthrallments", 980 | "inopportuneness", 981 | "boulimy", 982 | "headcloths", 983 | "surprisedly", 984 | "counterproof", 985 | "nonregressive", 986 | "vocative", 987 | "procurative", 988 | "nonpropitiable", 989 | "algiomuscular", 990 | "spilling", 991 | "domn", 992 | "ecorche", 993 | "scoreboards", 994 | "supersocial", 995 | "prisable", 996 | "agnathostomata", 997 | "ruttish", 998 | "hepatorrhea", 999 | "dewinesses", 1000 | "deposed", 1001 | "kiwanis" 1002 | ] 1003 | -------------------------------------------------------------------------------- /server/src/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 16 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 17 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 18 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 19 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 20 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 21 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 22 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 23 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 24 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 25 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 26 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 27 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 28 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 29 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 30 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 31 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 32 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 33 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 34 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 35 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 36 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 37 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 38 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 39 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 40 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 41 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 42 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 43 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 44 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 45 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 46 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 47 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 48 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 49 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 50 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 51 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 52 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 53 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 54 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 55 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 56 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 57 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 58 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 59 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 60 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 61 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 62 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 63 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 64 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 65 | github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 66 | github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= 67 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 68 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 69 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 70 | github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= 71 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 72 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 73 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 74 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 75 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 76 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 77 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 78 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 79 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 80 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 81 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 82 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 83 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 84 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 85 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 86 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 87 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 88 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 89 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 90 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 91 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 92 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 93 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 94 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 95 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 96 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 97 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 98 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 99 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 100 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 101 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 102 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 103 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 104 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 105 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 106 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 107 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 108 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 109 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 110 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 111 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 112 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 113 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 114 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 115 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 116 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 117 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 118 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 119 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 120 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 121 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 122 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 123 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 124 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 125 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 126 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 127 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 128 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 129 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 130 | github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 131 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 132 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 133 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 134 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 135 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 136 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 137 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 138 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 139 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 140 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 141 | github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 142 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 143 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 144 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 145 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 146 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 147 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 148 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 149 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 150 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 151 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 152 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 153 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 154 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 155 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 156 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 157 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 158 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 159 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 160 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 161 | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 162 | github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= 163 | github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= 164 | github.com/prometheus/client_golang v1.13.0 h1:b71QUfeo5M8gq2+evJdTPfZhYMAU0uKPkyPJ7TPsloU= 165 | github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= 166 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 167 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 168 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 169 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 170 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 171 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 172 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 173 | github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= 174 | github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= 175 | github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= 176 | github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= 177 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 178 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 179 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 180 | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 181 | github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 182 | github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= 183 | github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= 184 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 185 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 186 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 187 | github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 188 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 189 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 190 | github.com/slok/go-http-metrics v0.10.0 h1:rh0LaYEKza5eaYRGDXujKrOln57nHBi4TtVhmNEpbgM= 191 | github.com/slok/go-http-metrics v0.10.0/go.mod h1:lFqdaS4kWMfUKCSukjC47PdCeTk+hXDUVm8kLHRqJ38= 192 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 193 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 194 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 195 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 196 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 197 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 198 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 199 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 200 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 201 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 202 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 203 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 204 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 205 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 206 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 207 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 208 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 209 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 210 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 211 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 212 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 213 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 214 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 215 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 216 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 217 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 218 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 219 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 220 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 221 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 222 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 223 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 224 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 225 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 226 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 227 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 228 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 229 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 230 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 231 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 232 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 233 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 234 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 235 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 236 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 237 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 238 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 239 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 240 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 241 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 242 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 243 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 244 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 245 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 246 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 247 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 248 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 249 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 250 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 251 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 252 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 253 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 254 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 255 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 256 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 257 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 258 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 259 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 260 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 261 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 262 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 263 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 264 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 265 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 266 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 267 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 268 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 269 | golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 270 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 271 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 272 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 273 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 274 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 275 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 276 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 277 | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 278 | golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= 279 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 280 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 281 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 282 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 283 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 284 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 285 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 286 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 287 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 288 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 289 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 290 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 291 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 292 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 293 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 294 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 295 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 296 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 297 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 298 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 299 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 300 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 301 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= 302 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 303 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 304 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 305 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 306 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 307 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 308 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 309 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 310 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 311 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 312 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 313 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 314 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 315 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 316 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 317 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 318 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 319 | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 320 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 321 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 322 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 323 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 324 | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 325 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 326 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 327 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 328 | golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6 h1:cy1ko5847T/lJ45eyg/7uLprIE/amW5IXxGtEnQdYMI= 329 | golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 330 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 331 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 332 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 333 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 334 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 335 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 336 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 337 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 338 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 339 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 340 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 341 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 342 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 343 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 344 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 345 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 346 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 347 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 348 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 349 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 350 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 351 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 352 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 353 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 354 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 355 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 356 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 357 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 358 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 359 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 360 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 361 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 362 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 363 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 364 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 365 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 366 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 367 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 368 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 369 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 370 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 371 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 372 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 373 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 374 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 375 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 376 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 377 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 378 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 379 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 380 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 381 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 382 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 383 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 384 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 385 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 386 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 387 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 388 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 389 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 390 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 391 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 392 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 393 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 394 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 395 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 396 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 397 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 398 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 399 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 400 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 401 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 402 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 403 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 404 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 405 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 406 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 407 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 408 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 409 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 410 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 411 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 412 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 413 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 414 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 415 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 416 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 417 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 418 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 419 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 420 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 421 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 422 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 423 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 424 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 425 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 426 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 427 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 428 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 429 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 430 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 431 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 432 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 433 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 434 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 435 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 436 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 437 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 438 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 439 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 440 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 441 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 442 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 443 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 444 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 445 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 446 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 447 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 448 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 449 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 450 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 451 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 452 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 453 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 454 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 455 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 456 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 457 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 458 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 459 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 460 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 461 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 462 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 463 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 464 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 465 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 466 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 467 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 468 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 469 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 470 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 471 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 472 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 473 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 474 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 475 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 476 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 477 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 478 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 479 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 480 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 481 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 482 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 483 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 484 | -------------------------------------------------------------------------------- /server/monitoring/custom_dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": { 7 | "type": "grafana", 8 | "uid": "-- Grafana --" 9 | }, 10 | "enable": true, 11 | "hide": true, 12 | "iconColor": "rgba(0, 211, 255, 1)", 13 | "name": "Annotations & Alerts", 14 | "target": { 15 | "limit": 100, 16 | "matchAny": false, 17 | "tags": [], 18 | "type": "dashboard" 19 | }, 20 | "type": "dashboard" 21 | } 22 | ] 23 | }, 24 | "editable": true, 25 | "fiscalYearStartMonth": 0, 26 | "graphTooltip": 0, 27 | "id": 1, 28 | "links": [], 29 | "liveNow": false, 30 | "panels": [ 31 | { 32 | "collapsed": false, 33 | "gridPos": { 34 | "h": 1, 35 | "w": 24, 36 | "x": 0, 37 | "y": 0 38 | }, 39 | "id": 28, 40 | "panels": [], 41 | "title": "App", 42 | "type": "row" 43 | }, 44 | { 45 | "datasource": { 46 | "type": "prometheus", 47 | "uid": "P1809F7CD0C75ACF3" 48 | }, 49 | "fieldConfig": { 50 | "defaults": { 51 | "color": { 52 | "mode": "palette-classic" 53 | }, 54 | "custom": { 55 | "axisCenteredZero": false, 56 | "axisColorMode": "text", 57 | "axisLabel": "", 58 | "axisPlacement": "auto", 59 | "barAlignment": 0, 60 | "drawStyle": "line", 61 | "fillOpacity": 0, 62 | "gradientMode": "none", 63 | "hideFrom": { 64 | "legend": false, 65 | "tooltip": false, 66 | "viz": false 67 | }, 68 | "lineInterpolation": "linear", 69 | "lineWidth": 1, 70 | "pointSize": 5, 71 | "scaleDistribution": { 72 | "type": "linear" 73 | }, 74 | "showPoints": "auto", 75 | "spanNulls": false, 76 | "stacking": { 77 | "group": "A", 78 | "mode": "none" 79 | }, 80 | "thresholdsStyle": { 81 | "mode": "off" 82 | } 83 | }, 84 | "mappings": [], 85 | "thresholds": { 86 | "mode": "absolute", 87 | "steps": [ 88 | { 89 | "color": "green", 90 | "value": null 91 | }, 92 | { 93 | "color": "red", 94 | "value": 80 95 | } 96 | ] 97 | } 98 | }, 99 | "overrides": [] 100 | }, 101 | "gridPos": { 102 | "h": 11, 103 | "w": 12, 104 | "x": 0, 105 | "y": 1 106 | }, 107 | "id": 4, 108 | "options": { 109 | "legend": { 110 | "calcs": [], 111 | "displayMode": "list", 112 | "placement": "bottom", 113 | "showLegend": true 114 | }, 115 | "tooltip": { 116 | "mode": "single", 117 | "sort": "none" 118 | } 119 | }, 120 | "targets": [ 121 | { 122 | "datasource": { 123 | "type": "prometheus", 124 | "uid": "P1809F7CD0C75ACF3" 125 | }, 126 | "editorMode": "builder", 127 | "exemplar": false, 128 | "expr": "histogram_quantile(0.95, sum by(le) (rate(http_request_duration_seconds_bucket{handler=\"/find\"}[15s])))", 129 | "format": "time_series", 130 | "interval": "", 131 | "legendFormat": "95%", 132 | "range": true, 133 | "refId": "A" 134 | }, 135 | { 136 | "datasource": { 137 | "type": "prometheus", 138 | "uid": "P1809F7CD0C75ACF3" 139 | }, 140 | "editorMode": "builder", 141 | "expr": "histogram_quantile(0.5, sum by(le) (rate(http_request_duration_seconds_bucket{handler=\"/find\"}[15s])))", 142 | "format": "time_series", 143 | "hide": false, 144 | "interval": "", 145 | "legendFormat": "50%", 146 | "range": true, 147 | "refId": "B" 148 | } 149 | ], 150 | "title": "Percentiles", 151 | "type": "timeseries" 152 | }, 153 | { 154 | "datasource": { 155 | "type": "prometheus", 156 | "uid": "P1809F7CD0C75ACF3" 157 | }, 158 | "fieldConfig": { 159 | "defaults": { 160 | "color": { 161 | "mode": "palette-classic" 162 | }, 163 | "custom": { 164 | "axisCenteredZero": false, 165 | "axisColorMode": "text", 166 | "axisLabel": "", 167 | "axisPlacement": "auto", 168 | "barAlignment": 0, 169 | "drawStyle": "line", 170 | "fillOpacity": 0, 171 | "gradientMode": "none", 172 | "hideFrom": { 173 | "legend": false, 174 | "tooltip": false, 175 | "viz": false 176 | }, 177 | "lineInterpolation": "linear", 178 | "lineWidth": 1, 179 | "pointSize": 5, 180 | "scaleDistribution": { 181 | "type": "linear" 182 | }, 183 | "showPoints": "auto", 184 | "spanNulls": false, 185 | "stacking": { 186 | "group": "A", 187 | "mode": "none" 188 | }, 189 | "thresholdsStyle": { 190 | "mode": "off" 191 | } 192 | }, 193 | "mappings": [], 194 | "thresholds": { 195 | "mode": "absolute", 196 | "steps": [ 197 | { 198 | "color": "green", 199 | "value": null 200 | }, 201 | { 202 | "color": "red", 203 | "value": 80 204 | } 205 | ] 206 | } 207 | }, 208 | "overrides": [] 209 | }, 210 | "gridPos": { 211 | "h": 11, 212 | "w": 12, 213 | "x": 12, 214 | "y": 1 215 | }, 216 | "id": 2, 217 | "options": { 218 | "legend": { 219 | "calcs": [], 220 | "displayMode": "list", 221 | "placement": "bottom", 222 | "showLegend": true 223 | }, 224 | "tooltip": { 225 | "mode": "single", 226 | "sort": "none" 227 | } 228 | }, 229 | "targets": [ 230 | { 231 | "datasource": { 232 | "type": "prometheus", 233 | "uid": "P1809F7CD0C75ACF3" 234 | }, 235 | "editorMode": "builder", 236 | "expr": "rate(http_request_duration_seconds_count{code=\"200\", handler=\"/find\"}[15s])", 237 | "legendFormat": "__auto", 238 | "range": true, 239 | "refId": "A" 240 | } 241 | ], 242 | "title": "req/s (agg. on last 15 sec)", 243 | "type": "timeseries" 244 | }, 245 | { 246 | "datasource": { 247 | "type": "prometheus", 248 | "uid": "P1809F7CD0C75ACF3" 249 | }, 250 | "description": "", 251 | "fieldConfig": { 252 | "defaults": { 253 | "color": { 254 | "mode": "palette-classic" 255 | }, 256 | "custom": { 257 | "axisCenteredZero": false, 258 | "axisColorMode": "text", 259 | "axisLabel": "percentage", 260 | "axisPlacement": "auto", 261 | "barAlignment": 0, 262 | "drawStyle": "line", 263 | "fillOpacity": 70, 264 | "gradientMode": "none", 265 | "hideFrom": { 266 | "legend": false, 267 | "tooltip": false, 268 | "viz": false 269 | }, 270 | "lineInterpolation": "smooth", 271 | "lineWidth": 2, 272 | "pointSize": 5, 273 | "scaleDistribution": { 274 | "type": "linear" 275 | }, 276 | "showPoints": "never", 277 | "spanNulls": false, 278 | "stacking": { 279 | "group": "A", 280 | "mode": "percent" 281 | }, 282 | "thresholdsStyle": { 283 | "mode": "off" 284 | } 285 | }, 286 | "links": [], 287 | "mappings": [], 288 | "min": 0, 289 | "thresholds": { 290 | "mode": "absolute", 291 | "steps": [ 292 | { 293 | "color": "green", 294 | "value": null 295 | }, 296 | { 297 | "color": "red", 298 | "value": 80 299 | } 300 | ] 301 | }, 302 | "unit": "percentunit" 303 | }, 304 | "overrides": [ 305 | { 306 | "matcher": { 307 | "id": "byName", 308 | "options": "Idle - Waiting for something to happen" 309 | }, 310 | "properties": [ 311 | { 312 | "id": "color", 313 | "value": { 314 | "fixedColor": "#052B51", 315 | "mode": "fixed" 316 | } 317 | } 318 | ] 319 | }, 320 | { 321 | "matcher": { 322 | "id": "byName", 323 | "options": "Iowait - Waiting for I/O to complete" 324 | }, 325 | "properties": [ 326 | { 327 | "id": "color", 328 | "value": { 329 | "fixedColor": "#EAB839", 330 | "mode": "fixed" 331 | } 332 | } 333 | ] 334 | }, 335 | { 336 | "matcher": { 337 | "id": "byName", 338 | "options": "Irq - Servicing interrupts" 339 | }, 340 | "properties": [ 341 | { 342 | "id": "color", 343 | "value": { 344 | "fixedColor": "#BF1B00", 345 | "mode": "fixed" 346 | } 347 | } 348 | ] 349 | }, 350 | { 351 | "matcher": { 352 | "id": "byName", 353 | "options": "Nice - Niced processes executing in user mode" 354 | }, 355 | "properties": [ 356 | { 357 | "id": "color", 358 | "value": { 359 | "fixedColor": "#C15C17", 360 | "mode": "fixed" 361 | } 362 | } 363 | ] 364 | }, 365 | { 366 | "matcher": { 367 | "id": "byName", 368 | "options": "Softirq - Servicing softirqs" 369 | }, 370 | "properties": [ 371 | { 372 | "id": "color", 373 | "value": { 374 | "fixedColor": "#E24D42", 375 | "mode": "fixed" 376 | } 377 | } 378 | ] 379 | }, 380 | { 381 | "matcher": { 382 | "id": "byName", 383 | "options": "Steal - Time spent in other operating systems when running in a virtualized environment" 384 | }, 385 | "properties": [ 386 | { 387 | "id": "color", 388 | "value": { 389 | "fixedColor": "#FCE2DE", 390 | "mode": "fixed" 391 | } 392 | } 393 | ] 394 | }, 395 | { 396 | "matcher": { 397 | "id": "byName", 398 | "options": "System - Processes executing in kernel mode" 399 | }, 400 | "properties": [ 401 | { 402 | "id": "color", 403 | "value": { 404 | "fixedColor": "#508642", 405 | "mode": "fixed" 406 | } 407 | } 408 | ] 409 | }, 410 | { 411 | "matcher": { 412 | "id": "byName", 413 | "options": "User - Normal processes executing in user mode" 414 | }, 415 | "properties": [ 416 | { 417 | "id": "color", 418 | "value": { 419 | "fixedColor": "#5195CE", 420 | "mode": "fixed" 421 | } 422 | } 423 | ] 424 | } 425 | ] 426 | }, 427 | "gridPos": { 428 | "h": 12, 429 | "w": 12, 430 | "x": 0, 431 | "y": 12 432 | }, 433 | "id": 30, 434 | "links": [], 435 | "options": { 436 | "legend": { 437 | "calcs": [ 438 | "mean", 439 | "lastNotNull", 440 | "max", 441 | "min" 442 | ], 443 | "displayMode": "table", 444 | "placement": "bottom", 445 | "showLegend": true, 446 | "width": 250 447 | }, 448 | "tooltip": { 449 | "mode": "multi", 450 | "sort": "desc" 451 | } 452 | }, 453 | "pluginVersion": "9.2.0", 454 | "targets": [ 455 | { 456 | "datasource": { 457 | "type": "prometheus", 458 | "uid": "P1809F7CD0C75ACF3" 459 | }, 460 | "editorMode": "code", 461 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"system\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 462 | "format": "time_series", 463 | "interval": "", 464 | "intervalFactor": 1, 465 | "legendFormat": "System - Processes executing in kernel mode", 466 | "range": true, 467 | "refId": "A", 468 | "step": 240 469 | }, 470 | { 471 | "datasource": { 472 | "type": "prometheus", 473 | "uid": "P1809F7CD0C75ACF3" 474 | }, 475 | "editorMode": "code", 476 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"user\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 477 | "format": "time_series", 478 | "intervalFactor": 1, 479 | "legendFormat": "User - Normal processes executing in user mode", 480 | "range": true, 481 | "refId": "B", 482 | "step": 240 483 | }, 484 | { 485 | "datasource": { 486 | "type": "prometheus", 487 | "uid": "P1809F7CD0C75ACF3" 488 | }, 489 | "editorMode": "code", 490 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"nice\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 491 | "format": "time_series", 492 | "intervalFactor": 1, 493 | "legendFormat": "Nice - Niced processes executing in user mode", 494 | "range": true, 495 | "refId": "C", 496 | "step": 240 497 | }, 498 | { 499 | "datasource": { 500 | "type": "prometheus", 501 | "uid": "P1809F7CD0C75ACF3" 502 | }, 503 | "editorMode": "code", 504 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"iowait\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 505 | "format": "time_series", 506 | "intervalFactor": 1, 507 | "legendFormat": "Iowait - Waiting for I/O to complete", 508 | "range": true, 509 | "refId": "E", 510 | "step": 240 511 | }, 512 | { 513 | "datasource": { 514 | "type": "prometheus", 515 | "uid": "P1809F7CD0C75ACF3" 516 | }, 517 | "editorMode": "code", 518 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"irq\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 519 | "format": "time_series", 520 | "intervalFactor": 1, 521 | "legendFormat": "Irq - Servicing interrupts", 522 | "range": true, 523 | "refId": "F", 524 | "step": 240 525 | }, 526 | { 527 | "datasource": { 528 | "type": "prometheus", 529 | "uid": "P1809F7CD0C75ACF3" 530 | }, 531 | "editorMode": "code", 532 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"softirq\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 533 | "format": "time_series", 534 | "intervalFactor": 1, 535 | "legendFormat": "Softirq - Servicing softirqs", 536 | "range": true, 537 | "refId": "G", 538 | "step": 240 539 | }, 540 | { 541 | "datasource": { 542 | "type": "prometheus", 543 | "uid": "P1809F7CD0C75ACF3" 544 | }, 545 | "editorMode": "code", 546 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"steal\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 547 | "format": "time_series", 548 | "intervalFactor": 1, 549 | "legendFormat": "Steal - Time spent in other operating systems when running in a virtualized environment", 550 | "range": true, 551 | "refId": "H", 552 | "step": 240 553 | }, 554 | { 555 | "datasource": { 556 | "type": "prometheus", 557 | "uid": "P1809F7CD0C75ACF3" 558 | }, 559 | "editorMode": "code", 560 | "expr": "sum by(instance) (irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\", mode=\"idle\"}[$__rate_interval])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])))", 561 | "format": "time_series", 562 | "hide": false, 563 | "intervalFactor": 1, 564 | "legendFormat": "Idle - Waiting for something to happen", 565 | "range": true, 566 | "refId": "J", 567 | "step": 240 568 | } 569 | ], 570 | "title": "CPU", 571 | "type": "timeseries" 572 | }, 573 | { 574 | "datasource": { 575 | "type": "prometheus", 576 | "uid": "P1809F7CD0C75ACF3" 577 | }, 578 | "fieldConfig": { 579 | "defaults": { 580 | "color": { 581 | "mode": "palette-classic" 582 | }, 583 | "custom": { 584 | "axisCenteredZero": false, 585 | "axisColorMode": "text", 586 | "axisLabel": "MB", 587 | "axisPlacement": "auto", 588 | "barAlignment": 0, 589 | "drawStyle": "line", 590 | "fillOpacity": 0, 591 | "gradientMode": "none", 592 | "hideFrom": { 593 | "legend": false, 594 | "tooltip": false, 595 | "viz": false 596 | }, 597 | "lineInterpolation": "linear", 598 | "lineWidth": 1, 599 | "pointSize": 5, 600 | "scaleDistribution": { 601 | "type": "linear" 602 | }, 603 | "showPoints": "auto", 604 | "spanNulls": false, 605 | "stacking": { 606 | "group": "A", 607 | "mode": "none" 608 | }, 609 | "thresholdsStyle": { 610 | "mode": "off" 611 | } 612 | }, 613 | "mappings": [], 614 | "thresholds": { 615 | "mode": "absolute", 616 | "steps": [ 617 | { 618 | "color": "green", 619 | "value": null 620 | }, 621 | { 622 | "color": "red", 623 | "value": 80 624 | } 625 | ] 626 | } 627 | }, 628 | "overrides": [] 629 | }, 630 | "gridPos": { 631 | "h": 10, 632 | "w": 12, 633 | "x": 12, 634 | "y": 12 635 | }, 636 | "id": 8, 637 | "options": { 638 | "legend": { 639 | "calcs": [], 640 | "displayMode": "list", 641 | "placement": "bottom", 642 | "showLegend": true 643 | }, 644 | "tooltip": { 645 | "mode": "single", 646 | "sort": "none" 647 | } 648 | }, 649 | "targets": [ 650 | { 651 | "datasource": { 652 | "type": "prometheus", 653 | "uid": "P1809F7CD0C75ACF3" 654 | }, 655 | "editorMode": "builder", 656 | "exemplar": false, 657 | "expr": "go_memstats_alloc_bytes", 658 | "instant": false, 659 | "legendFormat": "__auto", 660 | "range": true, 661 | "refId": "A" 662 | } 663 | ], 664 | "title": "Memory", 665 | "transformations": [ 666 | { 667 | "id": "calculateField", 668 | "options": { 669 | "binary": { 670 | "left": "{__name__=\"go_memstats_alloc_bytes\", instance=\"localhost:8081\", job=\"flash\"}", 671 | "operator": "/", 672 | "reducer": "sum", 673 | "right": "1048576" 674 | }, 675 | "mode": "binary", 676 | "reduce": { 677 | "reducer": "sum" 678 | }, 679 | "replaceFields": true 680 | } 681 | } 682 | ], 683 | "type": "timeseries" 684 | }, 685 | { 686 | "datasource": { 687 | "type": "prometheus", 688 | "uid": "P1809F7CD0C75ACF3" 689 | }, 690 | "fieldConfig": { 691 | "defaults": { 692 | "color": { 693 | "mode": "palette-classic" 694 | }, 695 | "custom": { 696 | "axisCenteredZero": false, 697 | "axisColorMode": "text", 698 | "axisLabel": "", 699 | "axisPlacement": "auto", 700 | "barAlignment": 0, 701 | "drawStyle": "line", 702 | "fillOpacity": 0, 703 | "gradientMode": "none", 704 | "hideFrom": { 705 | "legend": false, 706 | "tooltip": false, 707 | "viz": false 708 | }, 709 | "lineInterpolation": "linear", 710 | "lineWidth": 1, 711 | "pointSize": 5, 712 | "scaleDistribution": { 713 | "type": "linear" 714 | }, 715 | "showPoints": "auto", 716 | "spanNulls": false, 717 | "stacking": { 718 | "group": "A", 719 | "mode": "none" 720 | }, 721 | "thresholdsStyle": { 722 | "mode": "off" 723 | } 724 | }, 725 | "mappings": [], 726 | "thresholds": { 727 | "mode": "absolute", 728 | "steps": [ 729 | { 730 | "color": "green", 731 | "value": null 732 | }, 733 | { 734 | "color": "red", 735 | "value": 80 736 | } 737 | ] 738 | } 739 | }, 740 | "overrides": [] 741 | }, 742 | "gridPos": { 743 | "h": 10, 744 | "w": 12, 745 | "x": 12, 746 | "y": 22 747 | }, 748 | "id": 12, 749 | "options": { 750 | "legend": { 751 | "calcs": [], 752 | "displayMode": "list", 753 | "placement": "bottom", 754 | "showLegend": true 755 | }, 756 | "tooltip": { 757 | "mode": "single", 758 | "sort": "none" 759 | } 760 | }, 761 | "targets": [ 762 | { 763 | "datasource": { 764 | "type": "prometheus", 765 | "uid": "P1809F7CD0C75ACF3" 766 | }, 767 | "editorMode": "builder", 768 | "expr": "rate(go_gc_duration_seconds_count[15s])", 769 | "legendFormat": "__auto", 770 | "range": true, 771 | "refId": "A" 772 | } 773 | ], 774 | "title": "GC", 775 | "type": "timeseries" 776 | }, 777 | { 778 | "datasource": { 779 | "type": "prometheus", 780 | "uid": "P1809F7CD0C75ACF3" 781 | }, 782 | "fieldConfig": { 783 | "defaults": { 784 | "color": { 785 | "mode": "palette-classic" 786 | }, 787 | "custom": { 788 | "axisCenteredZero": false, 789 | "axisColorMode": "text", 790 | "axisLabel": "", 791 | "axisPlacement": "auto", 792 | "barAlignment": 0, 793 | "drawStyle": "line", 794 | "fillOpacity": 0, 795 | "gradientMode": "none", 796 | "hideFrom": { 797 | "legend": false, 798 | "tooltip": false, 799 | "viz": false 800 | }, 801 | "lineInterpolation": "linear", 802 | "lineWidth": 1, 803 | "pointSize": 5, 804 | "scaleDistribution": { 805 | "type": "linear" 806 | }, 807 | "showPoints": "auto", 808 | "spanNulls": false, 809 | "stacking": { 810 | "group": "A", 811 | "mode": "none" 812 | }, 813 | "thresholdsStyle": { 814 | "mode": "off" 815 | } 816 | }, 817 | "mappings": [], 818 | "thresholds": { 819 | "mode": "absolute", 820 | "steps": [ 821 | { 822 | "color": "green", 823 | "value": null 824 | }, 825 | { 826 | "color": "red", 827 | "value": 80 828 | } 829 | ] 830 | } 831 | }, 832 | "overrides": [] 833 | }, 834 | "gridPos": { 835 | "h": 10, 836 | "w": 12, 837 | "x": 0, 838 | "y": 24 839 | }, 840 | "id": 10, 841 | "options": { 842 | "legend": { 843 | "calcs": [], 844 | "displayMode": "list", 845 | "placement": "bottom", 846 | "showLegend": true 847 | }, 848 | "tooltip": { 849 | "mode": "single", 850 | "sort": "none" 851 | } 852 | }, 853 | "targets": [ 854 | { 855 | "datasource": { 856 | "type": "prometheus", 857 | "uid": "P1809F7CD0C75ACF3" 858 | }, 859 | "editorMode": "builder", 860 | "expr": "go_threads", 861 | "legendFormat": "__auto", 862 | "range": true, 863 | "refId": "A" 864 | } 865 | ], 866 | "title": "threads", 867 | "type": "timeseries" 868 | }, 869 | { 870 | "datasource": { 871 | "type": "prometheus", 872 | "uid": "P1809F7CD0C75ACF3" 873 | }, 874 | "fieldConfig": { 875 | "defaults": { 876 | "color": { 877 | "mode": "palette-classic" 878 | }, 879 | "custom": { 880 | "axisCenteredZero": false, 881 | "axisColorMode": "text", 882 | "axisLabel": "", 883 | "axisPlacement": "auto", 884 | "barAlignment": 0, 885 | "drawStyle": "line", 886 | "fillOpacity": 0, 887 | "gradientMode": "none", 888 | "hideFrom": { 889 | "legend": false, 890 | "tooltip": false, 891 | "viz": false 892 | }, 893 | "lineInterpolation": "linear", 894 | "lineWidth": 1, 895 | "pointSize": 5, 896 | "scaleDistribution": { 897 | "type": "linear" 898 | }, 899 | "showPoints": "auto", 900 | "spanNulls": false, 901 | "stacking": { 902 | "group": "A", 903 | "mode": "none" 904 | }, 905 | "thresholdsStyle": { 906 | "mode": "off" 907 | } 908 | }, 909 | "mappings": [], 910 | "thresholds": { 911 | "mode": "absolute", 912 | "steps": [ 913 | { 914 | "color": "green", 915 | "value": null 916 | }, 917 | { 918 | "color": "red", 919 | "value": 80 920 | } 921 | ] 922 | } 923 | }, 924 | "overrides": [] 925 | }, 926 | "gridPos": { 927 | "h": 10, 928 | "w": 12, 929 | "x": 0, 930 | "y": 34 931 | }, 932 | "id": 6, 933 | "options": { 934 | "legend": { 935 | "calcs": [], 936 | "displayMode": "list", 937 | "placement": "bottom", 938 | "showLegend": true 939 | }, 940 | "tooltip": { 941 | "mode": "single", 942 | "sort": "none" 943 | } 944 | }, 945 | "targets": [ 946 | { 947 | "datasource": { 948 | "type": "prometheus", 949 | "uid": "P1809F7CD0C75ACF3" 950 | }, 951 | "editorMode": "builder", 952 | "expr": "go_goroutines", 953 | "legendFormat": "__auto", 954 | "range": true, 955 | "refId": "A" 956 | } 957 | ], 958 | "title": "go routines count", 959 | "type": "timeseries" 960 | }, 961 | { 962 | "collapsed": false, 963 | "gridPos": { 964 | "h": 1, 965 | "w": 24, 966 | "x": 0, 967 | "y": 44 968 | }, 969 | "id": 26, 970 | "panels": [], 971 | "title": "Node", 972 | "type": "row" 973 | }, 974 | { 975 | "datasource": { 976 | "type": "prometheus", 977 | "uid": "P1809F7CD0C75ACF3" 978 | }, 979 | "description": "", 980 | "fieldConfig": { 981 | "defaults": { 982 | "color": { 983 | "mode": "palette-classic" 984 | }, 985 | "custom": { 986 | "axisCenteredZero": false, 987 | "axisColorMode": "text", 988 | "axisLabel": "IO read (-) / write (+)", 989 | "axisPlacement": "auto", 990 | "barAlignment": 0, 991 | "drawStyle": "line", 992 | "fillOpacity": 20, 993 | "gradientMode": "none", 994 | "hideFrom": { 995 | "legend": false, 996 | "tooltip": false, 997 | "viz": false 998 | }, 999 | "lineInterpolation": "linear", 1000 | "lineWidth": 1, 1001 | "pointSize": 5, 1002 | "scaleDistribution": { 1003 | "type": "linear" 1004 | }, 1005 | "showPoints": "never", 1006 | "spanNulls": false, 1007 | "stacking": { 1008 | "group": "A", 1009 | "mode": "none" 1010 | }, 1011 | "thresholdsStyle": { 1012 | "mode": "off" 1013 | } 1014 | }, 1015 | "links": [], 1016 | "mappings": [], 1017 | "thresholds": { 1018 | "mode": "absolute", 1019 | "steps": [ 1020 | { 1021 | "color": "green", 1022 | "value": null 1023 | }, 1024 | { 1025 | "color": "red", 1026 | "value": 80 1027 | } 1028 | ] 1029 | }, 1030 | "unit": "iops" 1031 | }, 1032 | "overrides": [ 1033 | { 1034 | "matcher": { 1035 | "id": "byRegexp", 1036 | "options": "/.*Read.*/" 1037 | }, 1038 | "properties": [ 1039 | { 1040 | "id": "custom.transform", 1041 | "value": "negative-Y" 1042 | } 1043 | ] 1044 | }, 1045 | { 1046 | "matcher": { 1047 | "id": "byRegexp", 1048 | "options": "/.*sda_.*/" 1049 | }, 1050 | "properties": [ 1051 | { 1052 | "id": "color", 1053 | "value": { 1054 | "fixedColor": "#7EB26D", 1055 | "mode": "fixed" 1056 | } 1057 | } 1058 | ] 1059 | }, 1060 | { 1061 | "matcher": { 1062 | "id": "byRegexp", 1063 | "options": "/.*sdb_.*/" 1064 | }, 1065 | "properties": [ 1066 | { 1067 | "id": "color", 1068 | "value": { 1069 | "fixedColor": "#EAB839", 1070 | "mode": "fixed" 1071 | } 1072 | } 1073 | ] 1074 | }, 1075 | { 1076 | "matcher": { 1077 | "id": "byRegexp", 1078 | "options": "/.*sdc_.*/" 1079 | }, 1080 | "properties": [ 1081 | { 1082 | "id": "color", 1083 | "value": { 1084 | "fixedColor": "#6ED0E0", 1085 | "mode": "fixed" 1086 | } 1087 | } 1088 | ] 1089 | }, 1090 | { 1091 | "matcher": { 1092 | "id": "byRegexp", 1093 | "options": "/.*sdd_.*/" 1094 | }, 1095 | "properties": [ 1096 | { 1097 | "id": "color", 1098 | "value": { 1099 | "fixedColor": "#EF843C", 1100 | "mode": "fixed" 1101 | } 1102 | } 1103 | ] 1104 | }, 1105 | { 1106 | "matcher": { 1107 | "id": "byRegexp", 1108 | "options": "/.*sde_.*/" 1109 | }, 1110 | "properties": [ 1111 | { 1112 | "id": "color", 1113 | "value": { 1114 | "fixedColor": "#E24D42", 1115 | "mode": "fixed" 1116 | } 1117 | } 1118 | ] 1119 | }, 1120 | { 1121 | "matcher": { 1122 | "id": "byRegexp", 1123 | "options": "/.*sda1.*/" 1124 | }, 1125 | "properties": [ 1126 | { 1127 | "id": "color", 1128 | "value": { 1129 | "fixedColor": "#584477", 1130 | "mode": "fixed" 1131 | } 1132 | } 1133 | ] 1134 | }, 1135 | { 1136 | "matcher": { 1137 | "id": "byRegexp", 1138 | "options": "/.*sda2_.*/" 1139 | }, 1140 | "properties": [ 1141 | { 1142 | "id": "color", 1143 | "value": { 1144 | "fixedColor": "#BA43A9", 1145 | "mode": "fixed" 1146 | } 1147 | } 1148 | ] 1149 | }, 1150 | { 1151 | "matcher": { 1152 | "id": "byRegexp", 1153 | "options": "/.*sda3_.*/" 1154 | }, 1155 | "properties": [ 1156 | { 1157 | "id": "color", 1158 | "value": { 1159 | "fixedColor": "#F4D598", 1160 | "mode": "fixed" 1161 | } 1162 | } 1163 | ] 1164 | }, 1165 | { 1166 | "matcher": { 1167 | "id": "byRegexp", 1168 | "options": "/.*sdb1.*/" 1169 | }, 1170 | "properties": [ 1171 | { 1172 | "id": "color", 1173 | "value": { 1174 | "fixedColor": "#0A50A1", 1175 | "mode": "fixed" 1176 | } 1177 | } 1178 | ] 1179 | }, 1180 | { 1181 | "matcher": { 1182 | "id": "byRegexp", 1183 | "options": "/.*sdb2.*/" 1184 | }, 1185 | "properties": [ 1186 | { 1187 | "id": "color", 1188 | "value": { 1189 | "fixedColor": "#BF1B00", 1190 | "mode": "fixed" 1191 | } 1192 | } 1193 | ] 1194 | }, 1195 | { 1196 | "matcher": { 1197 | "id": "byRegexp", 1198 | "options": "/.*sdb2.*/" 1199 | }, 1200 | "properties": [ 1201 | { 1202 | "id": "color", 1203 | "value": { 1204 | "fixedColor": "#BF1B00", 1205 | "mode": "fixed" 1206 | } 1207 | } 1208 | ] 1209 | }, 1210 | { 1211 | "matcher": { 1212 | "id": "byRegexp", 1213 | "options": "/.*sdb3.*/" 1214 | }, 1215 | "properties": [ 1216 | { 1217 | "id": "color", 1218 | "value": { 1219 | "fixedColor": "#E0752D", 1220 | "mode": "fixed" 1221 | } 1222 | } 1223 | ] 1224 | }, 1225 | { 1226 | "matcher": { 1227 | "id": "byRegexp", 1228 | "options": "/.*sdc1.*/" 1229 | }, 1230 | "properties": [ 1231 | { 1232 | "id": "color", 1233 | "value": { 1234 | "fixedColor": "#962D82", 1235 | "mode": "fixed" 1236 | } 1237 | } 1238 | ] 1239 | }, 1240 | { 1241 | "matcher": { 1242 | "id": "byRegexp", 1243 | "options": "/.*sdc2.*/" 1244 | }, 1245 | "properties": [ 1246 | { 1247 | "id": "color", 1248 | "value": { 1249 | "fixedColor": "#614D93", 1250 | "mode": "fixed" 1251 | } 1252 | } 1253 | ] 1254 | }, 1255 | { 1256 | "matcher": { 1257 | "id": "byRegexp", 1258 | "options": "/.*sdc3.*/" 1259 | }, 1260 | "properties": [ 1261 | { 1262 | "id": "color", 1263 | "value": { 1264 | "fixedColor": "#9AC48A", 1265 | "mode": "fixed" 1266 | } 1267 | } 1268 | ] 1269 | }, 1270 | { 1271 | "matcher": { 1272 | "id": "byRegexp", 1273 | "options": "/.*sdd1.*/" 1274 | }, 1275 | "properties": [ 1276 | { 1277 | "id": "color", 1278 | "value": { 1279 | "fixedColor": "#65C5DB", 1280 | "mode": "fixed" 1281 | } 1282 | } 1283 | ] 1284 | }, 1285 | { 1286 | "matcher": { 1287 | "id": "byRegexp", 1288 | "options": "/.*sdd2.*/" 1289 | }, 1290 | "properties": [ 1291 | { 1292 | "id": "color", 1293 | "value": { 1294 | "fixedColor": "#F9934E", 1295 | "mode": "fixed" 1296 | } 1297 | } 1298 | ] 1299 | }, 1300 | { 1301 | "matcher": { 1302 | "id": "byRegexp", 1303 | "options": "/.*sdd3.*/" 1304 | }, 1305 | "properties": [ 1306 | { 1307 | "id": "color", 1308 | "value": { 1309 | "fixedColor": "#EA6460", 1310 | "mode": "fixed" 1311 | } 1312 | } 1313 | ] 1314 | }, 1315 | { 1316 | "matcher": { 1317 | "id": "byRegexp", 1318 | "options": "/.*sde1.*/" 1319 | }, 1320 | "properties": [ 1321 | { 1322 | "id": "color", 1323 | "value": { 1324 | "fixedColor": "#E0F9D7", 1325 | "mode": "fixed" 1326 | } 1327 | } 1328 | ] 1329 | }, 1330 | { 1331 | "matcher": { 1332 | "id": "byRegexp", 1333 | "options": "/.*sdd2.*/" 1334 | }, 1335 | "properties": [ 1336 | { 1337 | "id": "color", 1338 | "value": { 1339 | "fixedColor": "#FCEACA", 1340 | "mode": "fixed" 1341 | } 1342 | } 1343 | ] 1344 | }, 1345 | { 1346 | "matcher": { 1347 | "id": "byRegexp", 1348 | "options": "/.*sde3.*/" 1349 | }, 1350 | "properties": [ 1351 | { 1352 | "id": "color", 1353 | "value": { 1354 | "fixedColor": "#F9E2D2", 1355 | "mode": "fixed" 1356 | } 1357 | } 1358 | ] 1359 | } 1360 | ] 1361 | }, 1362 | "gridPos": { 1363 | "h": 12, 1364 | "w": 12, 1365 | "x": 0, 1366 | "y": 45 1367 | }, 1368 | "id": 24, 1369 | "links": [], 1370 | "options": { 1371 | "legend": { 1372 | "calcs": [ 1373 | "mean", 1374 | "lastNotNull", 1375 | "max", 1376 | "min" 1377 | ], 1378 | "displayMode": "table", 1379 | "placement": "bottom", 1380 | "showLegend": true 1381 | }, 1382 | "tooltip": { 1383 | "mode": "single", 1384 | "sort": "none" 1385 | } 1386 | }, 1387 | "pluginVersion": "9.2.0", 1388 | "targets": [ 1389 | { 1390 | "datasource": { 1391 | "type": "prometheus", 1392 | "uid": "P1809F7CD0C75ACF3" 1393 | }, 1394 | "expr": "rate(node_disk_reads_completed_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", 1395 | "intervalFactor": 4, 1396 | "legendFormat": "{{device}} - Reads completed", 1397 | "refId": "A", 1398 | "step": 240 1399 | }, 1400 | { 1401 | "datasource": { 1402 | "type": "prometheus", 1403 | "uid": "P1809F7CD0C75ACF3" 1404 | }, 1405 | "expr": "rate(node_disk_writes_completed_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", 1406 | "intervalFactor": 1, 1407 | "legendFormat": "{{device}} - Writes completed", 1408 | "refId": "B", 1409 | "step": 240 1410 | } 1411 | ], 1412 | "title": "Disk IOps", 1413 | "type": "timeseries" 1414 | }, 1415 | { 1416 | "datasource": { 1417 | "type": "prometheus", 1418 | "uid": "P1809F7CD0C75ACF3" 1419 | }, 1420 | "description": "", 1421 | "fieldConfig": { 1422 | "defaults": { 1423 | "color": { 1424 | "mode": "palette-classic" 1425 | }, 1426 | "custom": { 1427 | "axisCenteredZero": false, 1428 | "axisColorMode": "text", 1429 | "axisLabel": "bytes", 1430 | "axisPlacement": "auto", 1431 | "barAlignment": 0, 1432 | "drawStyle": "line", 1433 | "fillOpacity": 40, 1434 | "gradientMode": "none", 1435 | "hideFrom": { 1436 | "legend": false, 1437 | "tooltip": false, 1438 | "viz": false 1439 | }, 1440 | "lineInterpolation": "linear", 1441 | "lineWidth": 1, 1442 | "pointSize": 5, 1443 | "scaleDistribution": { 1444 | "type": "linear" 1445 | }, 1446 | "showPoints": "never", 1447 | "spanNulls": false, 1448 | "stacking": { 1449 | "group": "A", 1450 | "mode": "normal" 1451 | }, 1452 | "thresholdsStyle": { 1453 | "mode": "off" 1454 | } 1455 | }, 1456 | "links": [], 1457 | "mappings": [], 1458 | "min": 0, 1459 | "thresholds": { 1460 | "mode": "absolute", 1461 | "steps": [ 1462 | { 1463 | "color": "green", 1464 | "value": null 1465 | }, 1466 | { 1467 | "color": "red", 1468 | "value": 80 1469 | } 1470 | ] 1471 | }, 1472 | "unit": "bytes" 1473 | }, 1474 | "overrides": [ 1475 | { 1476 | "matcher": { 1477 | "id": "byName", 1478 | "options": "Apps" 1479 | }, 1480 | "properties": [ 1481 | { 1482 | "id": "color", 1483 | "value": { 1484 | "fixedColor": "#629E51", 1485 | "mode": "fixed" 1486 | } 1487 | } 1488 | ] 1489 | }, 1490 | { 1491 | "matcher": { 1492 | "id": "byName", 1493 | "options": "Buffers" 1494 | }, 1495 | "properties": [ 1496 | { 1497 | "id": "color", 1498 | "value": { 1499 | "fixedColor": "#614D93", 1500 | "mode": "fixed" 1501 | } 1502 | } 1503 | ] 1504 | }, 1505 | { 1506 | "matcher": { 1507 | "id": "byName", 1508 | "options": "Cache" 1509 | }, 1510 | "properties": [ 1511 | { 1512 | "id": "color", 1513 | "value": { 1514 | "fixedColor": "#6D1F62", 1515 | "mode": "fixed" 1516 | } 1517 | } 1518 | ] 1519 | }, 1520 | { 1521 | "matcher": { 1522 | "id": "byName", 1523 | "options": "Cached" 1524 | }, 1525 | "properties": [ 1526 | { 1527 | "id": "color", 1528 | "value": { 1529 | "fixedColor": "#511749", 1530 | "mode": "fixed" 1531 | } 1532 | } 1533 | ] 1534 | }, 1535 | { 1536 | "matcher": { 1537 | "id": "byName", 1538 | "options": "Committed" 1539 | }, 1540 | "properties": [ 1541 | { 1542 | "id": "color", 1543 | "value": { 1544 | "fixedColor": "#508642", 1545 | "mode": "fixed" 1546 | } 1547 | } 1548 | ] 1549 | }, 1550 | { 1551 | "matcher": { 1552 | "id": "byName", 1553 | "options": "Free" 1554 | }, 1555 | "properties": [ 1556 | { 1557 | "id": "color", 1558 | "value": { 1559 | "fixedColor": "#0A437C", 1560 | "mode": "fixed" 1561 | } 1562 | } 1563 | ] 1564 | }, 1565 | { 1566 | "matcher": { 1567 | "id": "byName", 1568 | "options": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" 1569 | }, 1570 | "properties": [ 1571 | { 1572 | "id": "color", 1573 | "value": { 1574 | "fixedColor": "#CFFAFF", 1575 | "mode": "fixed" 1576 | } 1577 | } 1578 | ] 1579 | }, 1580 | { 1581 | "matcher": { 1582 | "id": "byName", 1583 | "options": "Inactive" 1584 | }, 1585 | "properties": [ 1586 | { 1587 | "id": "color", 1588 | "value": { 1589 | "fixedColor": "#584477", 1590 | "mode": "fixed" 1591 | } 1592 | } 1593 | ] 1594 | }, 1595 | { 1596 | "matcher": { 1597 | "id": "byName", 1598 | "options": "PageTables" 1599 | }, 1600 | "properties": [ 1601 | { 1602 | "id": "color", 1603 | "value": { 1604 | "fixedColor": "#0A50A1", 1605 | "mode": "fixed" 1606 | } 1607 | } 1608 | ] 1609 | }, 1610 | { 1611 | "matcher": { 1612 | "id": "byName", 1613 | "options": "Page_Tables" 1614 | }, 1615 | "properties": [ 1616 | { 1617 | "id": "color", 1618 | "value": { 1619 | "fixedColor": "#0A50A1", 1620 | "mode": "fixed" 1621 | } 1622 | } 1623 | ] 1624 | }, 1625 | { 1626 | "matcher": { 1627 | "id": "byName", 1628 | "options": "RAM_Free" 1629 | }, 1630 | "properties": [ 1631 | { 1632 | "id": "color", 1633 | "value": { 1634 | "fixedColor": "#E0F9D7", 1635 | "mode": "fixed" 1636 | } 1637 | } 1638 | ] 1639 | }, 1640 | { 1641 | "matcher": { 1642 | "id": "byName", 1643 | "options": "Slab" 1644 | }, 1645 | "properties": [ 1646 | { 1647 | "id": "color", 1648 | "value": { 1649 | "fixedColor": "#806EB7", 1650 | "mode": "fixed" 1651 | } 1652 | } 1653 | ] 1654 | }, 1655 | { 1656 | "matcher": { 1657 | "id": "byName", 1658 | "options": "Slab_Cache" 1659 | }, 1660 | "properties": [ 1661 | { 1662 | "id": "color", 1663 | "value": { 1664 | "fixedColor": "#E0752D", 1665 | "mode": "fixed" 1666 | } 1667 | } 1668 | ] 1669 | }, 1670 | { 1671 | "matcher": { 1672 | "id": "byName", 1673 | "options": "Swap" 1674 | }, 1675 | "properties": [ 1676 | { 1677 | "id": "color", 1678 | "value": { 1679 | "fixedColor": "#BF1B00", 1680 | "mode": "fixed" 1681 | } 1682 | } 1683 | ] 1684 | }, 1685 | { 1686 | "matcher": { 1687 | "id": "byName", 1688 | "options": "Swap - Swap memory usage" 1689 | }, 1690 | "properties": [ 1691 | { 1692 | "id": "color", 1693 | "value": { 1694 | "fixedColor": "#BF1B00", 1695 | "mode": "fixed" 1696 | } 1697 | } 1698 | ] 1699 | }, 1700 | { 1701 | "matcher": { 1702 | "id": "byName", 1703 | "options": "Swap_Cache" 1704 | }, 1705 | "properties": [ 1706 | { 1707 | "id": "color", 1708 | "value": { 1709 | "fixedColor": "#C15C17", 1710 | "mode": "fixed" 1711 | } 1712 | } 1713 | ] 1714 | }, 1715 | { 1716 | "matcher": { 1717 | "id": "byName", 1718 | "options": "Swap_Free" 1719 | }, 1720 | "properties": [ 1721 | { 1722 | "id": "color", 1723 | "value": { 1724 | "fixedColor": "#2F575E", 1725 | "mode": "fixed" 1726 | } 1727 | } 1728 | ] 1729 | }, 1730 | { 1731 | "matcher": { 1732 | "id": "byName", 1733 | "options": "Unused" 1734 | }, 1735 | "properties": [ 1736 | { 1737 | "id": "color", 1738 | "value": { 1739 | "fixedColor": "#EAB839", 1740 | "mode": "fixed" 1741 | } 1742 | } 1743 | ] 1744 | }, 1745 | { 1746 | "matcher": { 1747 | "id": "byName", 1748 | "options": "Unused - Free memory unassigned" 1749 | }, 1750 | "properties": [ 1751 | { 1752 | "id": "color", 1753 | "value": { 1754 | "fixedColor": "#052B51", 1755 | "mode": "fixed" 1756 | } 1757 | } 1758 | ] 1759 | }, 1760 | { 1761 | "matcher": { 1762 | "id": "byRegexp", 1763 | "options": "/.*Hardware Corrupted - *./" 1764 | }, 1765 | "properties": [ 1766 | { 1767 | "id": "custom.stacking", 1768 | "value": { 1769 | "group": false, 1770 | "mode": "normal" 1771 | } 1772 | } 1773 | ] 1774 | }, 1775 | { 1776 | "__systemRef": "hideSeriesFrom", 1777 | "matcher": { 1778 | "id": "byNames", 1779 | "options": { 1780 | "mode": "exclude", 1781 | "names": [ 1782 | "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working" 1783 | ], 1784 | "prefix": "All except:", 1785 | "readOnly": true 1786 | } 1787 | }, 1788 | "properties": [ 1789 | { 1790 | "id": "custom.hideFrom", 1791 | "value": { 1792 | "legend": false, 1793 | "tooltip": false, 1794 | "viz": true 1795 | } 1796 | } 1797 | ] 1798 | } 1799 | ] 1800 | }, 1801 | "gridPos": { 1802 | "h": 14, 1803 | "w": 12, 1804 | "x": 12, 1805 | "y": 45 1806 | }, 1807 | "id": 16, 1808 | "links": [], 1809 | "options": { 1810 | "legend": { 1811 | "calcs": [ 1812 | "mean", 1813 | "lastNotNull", 1814 | "max", 1815 | "min" 1816 | ], 1817 | "displayMode": "table", 1818 | "placement": "bottom", 1819 | "showLegend": true, 1820 | "width": 350 1821 | }, 1822 | "tooltip": { 1823 | "mode": "multi", 1824 | "sort": "none" 1825 | } 1826 | }, 1827 | "pluginVersion": "9.2.0", 1828 | "targets": [ 1829 | { 1830 | "datasource": { 1831 | "type": "prometheus", 1832 | "uid": "P1809F7CD0C75ACF3" 1833 | }, 1834 | "expr": "node_memory_MemTotal_bytes{instance=\"$node\",job=\"$job\"} - node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"} - node_memory_Buffers_bytes{instance=\"$node\",job=\"$job\"} - node_memory_Cached_bytes{instance=\"$node\",job=\"$job\"} - node_memory_Slab_bytes{instance=\"$node\",job=\"$job\"} - node_memory_PageTables_bytes{instance=\"$node\",job=\"$job\"} - node_memory_SwapCached_bytes{instance=\"$node\",job=\"$job\"}", 1835 | "format": "time_series", 1836 | "hide": false, 1837 | "intervalFactor": 1, 1838 | "legendFormat": "Apps - Memory used by user-space applications", 1839 | "refId": "A", 1840 | "step": 240 1841 | }, 1842 | { 1843 | "datasource": { 1844 | "type": "prometheus", 1845 | "uid": "P1809F7CD0C75ACF3" 1846 | }, 1847 | "expr": "node_memory_PageTables_bytes{instance=\"$node\",job=\"$job\"}", 1848 | "format": "time_series", 1849 | "hide": false, 1850 | "intervalFactor": 1, 1851 | "legendFormat": "PageTables - Memory used to map between virtual and physical memory addresses", 1852 | "refId": "B", 1853 | "step": 240 1854 | }, 1855 | { 1856 | "datasource": { 1857 | "type": "prometheus", 1858 | "uid": "P1809F7CD0C75ACF3" 1859 | }, 1860 | "expr": "node_memory_SwapCached_bytes{instance=\"$node\",job=\"$job\"}", 1861 | "format": "time_series", 1862 | "intervalFactor": 1, 1863 | "legendFormat": "SwapCache - Memory that keeps track of pages that have been fetched from swap but not yet been modified", 1864 | "refId": "C", 1865 | "step": 240 1866 | }, 1867 | { 1868 | "datasource": { 1869 | "type": "prometheus", 1870 | "uid": "P1809F7CD0C75ACF3" 1871 | }, 1872 | "expr": "node_memory_Slab_bytes{instance=\"$node\",job=\"$job\"}", 1873 | "format": "time_series", 1874 | "hide": false, 1875 | "intervalFactor": 1, 1876 | "legendFormat": "Slab - Memory used by the kernel to cache data structures for its own use (caches like inode, dentry, etc)", 1877 | "refId": "D", 1878 | "step": 240 1879 | }, 1880 | { 1881 | "datasource": { 1882 | "type": "prometheus", 1883 | "uid": "P1809F7CD0C75ACF3" 1884 | }, 1885 | "expr": "node_memory_Cached_bytes{instance=\"$node\",job=\"$job\"}", 1886 | "format": "time_series", 1887 | "hide": false, 1888 | "intervalFactor": 1, 1889 | "legendFormat": "Cache - Parked file data (file content) cache", 1890 | "refId": "E", 1891 | "step": 240 1892 | }, 1893 | { 1894 | "datasource": { 1895 | "type": "prometheus", 1896 | "uid": "P1809F7CD0C75ACF3" 1897 | }, 1898 | "expr": "node_memory_Buffers_bytes{instance=\"$node\",job=\"$job\"}", 1899 | "format": "time_series", 1900 | "hide": false, 1901 | "intervalFactor": 1, 1902 | "legendFormat": "Buffers - Block device (e.g. harddisk) cache", 1903 | "refId": "F", 1904 | "step": 240 1905 | }, 1906 | { 1907 | "datasource": { 1908 | "type": "prometheus", 1909 | "uid": "P1809F7CD0C75ACF3" 1910 | }, 1911 | "expr": "node_memory_MemFree_bytes{instance=\"$node\",job=\"$job\"}", 1912 | "format": "time_series", 1913 | "hide": false, 1914 | "intervalFactor": 1, 1915 | "legendFormat": "Unused - Free memory unassigned", 1916 | "refId": "G", 1917 | "step": 240 1918 | }, 1919 | { 1920 | "datasource": { 1921 | "type": "prometheus", 1922 | "uid": "P1809F7CD0C75ACF3" 1923 | }, 1924 | "expr": "(node_memory_SwapTotal_bytes{instance=\"$node\",job=\"$job\"} - node_memory_SwapFree_bytes{instance=\"$node\",job=\"$job\"})", 1925 | "format": "time_series", 1926 | "hide": false, 1927 | "intervalFactor": 1, 1928 | "legendFormat": "Swap - Swap space used", 1929 | "refId": "H", 1930 | "step": 240 1931 | }, 1932 | { 1933 | "datasource": { 1934 | "type": "prometheus", 1935 | "uid": "P1809F7CD0C75ACF3" 1936 | }, 1937 | "expr": "node_memory_HardwareCorrupted_bytes{instance=\"$node\",job=\"$job\"}", 1938 | "format": "time_series", 1939 | "hide": false, 1940 | "intervalFactor": 1, 1941 | "legendFormat": "Hardware Corrupted - Amount of RAM that the kernel identified as corrupted / not working", 1942 | "refId": "I", 1943 | "step": 240 1944 | } 1945 | ], 1946 | "title": "Memory Stack", 1947 | "type": "timeseries" 1948 | }, 1949 | { 1950 | "datasource": { 1951 | "type": "prometheus", 1952 | "uid": "P1809F7CD0C75ACF3" 1953 | }, 1954 | "description": "", 1955 | "fieldConfig": { 1956 | "defaults": { 1957 | "color": { 1958 | "mode": "palette-classic" 1959 | }, 1960 | "custom": { 1961 | "axisCenteredZero": false, 1962 | "axisColorMode": "text", 1963 | "axisLabel": "bytes", 1964 | "axisPlacement": "auto", 1965 | "barAlignment": 0, 1966 | "drawStyle": "line", 1967 | "fillOpacity": 40, 1968 | "gradientMode": "none", 1969 | "hideFrom": { 1970 | "legend": false, 1971 | "tooltip": false, 1972 | "viz": false 1973 | }, 1974 | "lineInterpolation": "linear", 1975 | "lineWidth": 1, 1976 | "pointSize": 5, 1977 | "scaleDistribution": { 1978 | "type": "linear" 1979 | }, 1980 | "showPoints": "never", 1981 | "spanNulls": false, 1982 | "stacking": { 1983 | "group": "A", 1984 | "mode": "none" 1985 | }, 1986 | "thresholdsStyle": { 1987 | "mode": "off" 1988 | } 1989 | }, 1990 | "links": [], 1991 | "mappings": [], 1992 | "min": 0, 1993 | "thresholds": { 1994 | "mode": "absolute", 1995 | "steps": [ 1996 | { 1997 | "color": "green", 1998 | "value": null 1999 | }, 2000 | { 2001 | "color": "red", 2002 | "value": 80 2003 | } 2004 | ] 2005 | }, 2006 | "unit": "bytes" 2007 | }, 2008 | "overrides": [] 2009 | }, 2010 | "gridPos": { 2011 | "h": 12, 2012 | "w": 12, 2013 | "x": 0, 2014 | "y": 57 2015 | }, 2016 | "id": 20, 2017 | "links": [], 2018 | "options": { 2019 | "legend": { 2020 | "calcs": [ 2021 | "mean", 2022 | "lastNotNull", 2023 | "max", 2024 | "min" 2025 | ], 2026 | "displayMode": "table", 2027 | "placement": "bottom", 2028 | "showLegend": true 2029 | }, 2030 | "tooltip": { 2031 | "mode": "multi", 2032 | "sort": "none" 2033 | } 2034 | }, 2035 | "pluginVersion": "9.2.0", 2036 | "targets": [ 2037 | { 2038 | "datasource": { 2039 | "type": "prometheus", 2040 | "uid": "P1809F7CD0C75ACF3" 2041 | }, 2042 | "expr": "node_filesystem_size_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'} - node_filesystem_avail_bytes{instance=\"$node\",job=\"$job\",device!~'rootfs'}", 2043 | "format": "time_series", 2044 | "intervalFactor": 1, 2045 | "legendFormat": "{{mountpoint}}", 2046 | "refId": "A", 2047 | "step": 240 2048 | } 2049 | ], 2050 | "title": "Disk Space Used", 2051 | "type": "timeseries" 2052 | }, 2053 | { 2054 | "datasource": { 2055 | "type": "prometheus", 2056 | "uid": "P1809F7CD0C75ACF3" 2057 | }, 2058 | "fieldConfig": { 2059 | "defaults": { 2060 | "color": { 2061 | "mode": "palette-classic" 2062 | }, 2063 | "custom": { 2064 | "axisCenteredZero": false, 2065 | "axisColorMode": "text", 2066 | "axisLabel": "bits out (-) / in (+)", 2067 | "axisPlacement": "auto", 2068 | "barAlignment": 0, 2069 | "drawStyle": "line", 2070 | "fillOpacity": 40, 2071 | "gradientMode": "none", 2072 | "hideFrom": { 2073 | "legend": false, 2074 | "tooltip": false, 2075 | "viz": false 2076 | }, 2077 | "lineInterpolation": "linear", 2078 | "lineWidth": 1, 2079 | "pointSize": 5, 2080 | "scaleDistribution": { 2081 | "type": "linear" 2082 | }, 2083 | "showPoints": "never", 2084 | "spanNulls": false, 2085 | "stacking": { 2086 | "group": "A", 2087 | "mode": "none" 2088 | }, 2089 | "thresholdsStyle": { 2090 | "mode": "off" 2091 | } 2092 | }, 2093 | "links": [], 2094 | "mappings": [], 2095 | "thresholds": { 2096 | "mode": "absolute", 2097 | "steps": [ 2098 | { 2099 | "color": "green", 2100 | "value": null 2101 | }, 2102 | { 2103 | "color": "red", 2104 | "value": 80 2105 | } 2106 | ] 2107 | }, 2108 | "unit": "bps" 2109 | }, 2110 | "overrides": [ 2111 | { 2112 | "matcher": { 2113 | "id": "byName", 2114 | "options": "receive_packets_eth0" 2115 | }, 2116 | "properties": [ 2117 | { 2118 | "id": "color", 2119 | "value": { 2120 | "fixedColor": "#7EB26D", 2121 | "mode": "fixed" 2122 | } 2123 | } 2124 | ] 2125 | }, 2126 | { 2127 | "matcher": { 2128 | "id": "byName", 2129 | "options": "receive_packets_lo" 2130 | }, 2131 | "properties": [ 2132 | { 2133 | "id": "color", 2134 | "value": { 2135 | "fixedColor": "#E24D42", 2136 | "mode": "fixed" 2137 | } 2138 | } 2139 | ] 2140 | }, 2141 | { 2142 | "matcher": { 2143 | "id": "byName", 2144 | "options": "transmit_packets_eth0" 2145 | }, 2146 | "properties": [ 2147 | { 2148 | "id": "color", 2149 | "value": { 2150 | "fixedColor": "#7EB26D", 2151 | "mode": "fixed" 2152 | } 2153 | } 2154 | ] 2155 | }, 2156 | { 2157 | "matcher": { 2158 | "id": "byName", 2159 | "options": "transmit_packets_lo" 2160 | }, 2161 | "properties": [ 2162 | { 2163 | "id": "color", 2164 | "value": { 2165 | "fixedColor": "#E24D42", 2166 | "mode": "fixed" 2167 | } 2168 | } 2169 | ] 2170 | }, 2171 | { 2172 | "matcher": { 2173 | "id": "byRegexp", 2174 | "options": "/.*Trans.*/" 2175 | }, 2176 | "properties": [ 2177 | { 2178 | "id": "custom.transform", 2179 | "value": "negative-Y" 2180 | } 2181 | ] 2182 | } 2183 | ] 2184 | }, 2185 | "gridPos": { 2186 | "h": 12, 2187 | "w": 12, 2188 | "x": 12, 2189 | "y": 59 2190 | }, 2191 | "id": 22, 2192 | "links": [], 2193 | "options": { 2194 | "legend": { 2195 | "calcs": [ 2196 | "mean", 2197 | "lastNotNull", 2198 | "max", 2199 | "min" 2200 | ], 2201 | "displayMode": "table", 2202 | "placement": "bottom", 2203 | "showLegend": true 2204 | }, 2205 | "tooltip": { 2206 | "mode": "multi", 2207 | "sort": "none" 2208 | } 2209 | }, 2210 | "pluginVersion": "9.2.0", 2211 | "targets": [ 2212 | { 2213 | "datasource": { 2214 | "type": "prometheus", 2215 | "uid": "P1809F7CD0C75ACF3" 2216 | }, 2217 | "expr": "rate(node_network_receive_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])*8", 2218 | "format": "time_series", 2219 | "intervalFactor": 1, 2220 | "legendFormat": "{{device}} - Receive", 2221 | "refId": "A", 2222 | "step": 240 2223 | }, 2224 | { 2225 | "datasource": { 2226 | "type": "prometheus", 2227 | "uid": "P1809F7CD0C75ACF3" 2228 | }, 2229 | "expr": "rate(node_network_transmit_bytes_total{instance=\"$node\",job=\"$job\"}[$__rate_interval])*8", 2230 | "format": "time_series", 2231 | "intervalFactor": 1, 2232 | "legendFormat": "{{device}} - Transmit", 2233 | "refId": "B", 2234 | "step": 240 2235 | } 2236 | ], 2237 | "title": "Network Traffic", 2238 | "type": "timeseries" 2239 | }, 2240 | { 2241 | "datasource": { 2242 | "type": "prometheus", 2243 | "uid": "P1809F7CD0C75ACF3" 2244 | }, 2245 | "description": "", 2246 | "fieldConfig": { 2247 | "defaults": { 2248 | "color": { 2249 | "mode": "palette-classic" 2250 | }, 2251 | "custom": { 2252 | "axisCenteredZero": false, 2253 | "axisColorMode": "text", 2254 | "axisLabel": "bytes read (-) / write (+)", 2255 | "axisPlacement": "auto", 2256 | "barAlignment": 0, 2257 | "drawStyle": "line", 2258 | "fillOpacity": 40, 2259 | "gradientMode": "none", 2260 | "hideFrom": { 2261 | "legend": false, 2262 | "tooltip": false, 2263 | "viz": false 2264 | }, 2265 | "lineInterpolation": "linear", 2266 | "lineWidth": 1, 2267 | "pointSize": 5, 2268 | "scaleDistribution": { 2269 | "type": "linear" 2270 | }, 2271 | "showPoints": "never", 2272 | "spanNulls": false, 2273 | "stacking": { 2274 | "group": "A", 2275 | "mode": "none" 2276 | }, 2277 | "thresholdsStyle": { 2278 | "mode": "off" 2279 | } 2280 | }, 2281 | "links": [], 2282 | "mappings": [], 2283 | "thresholds": { 2284 | "mode": "absolute", 2285 | "steps": [ 2286 | { 2287 | "color": "green" 2288 | }, 2289 | { 2290 | "color": "red", 2291 | "value": 80 2292 | } 2293 | ] 2294 | }, 2295 | "unit": "Bps" 2296 | }, 2297 | "overrides": [ 2298 | { 2299 | "matcher": { 2300 | "id": "byName", 2301 | "options": "io time" 2302 | }, 2303 | "properties": [ 2304 | { 2305 | "id": "color", 2306 | "value": { 2307 | "fixedColor": "#890F02", 2308 | "mode": "fixed" 2309 | } 2310 | } 2311 | ] 2312 | }, 2313 | { 2314 | "matcher": { 2315 | "id": "byRegexp", 2316 | "options": "/.*read*./" 2317 | }, 2318 | "properties": [ 2319 | { 2320 | "id": "custom.transform", 2321 | "value": "negative-Y" 2322 | } 2323 | ] 2324 | }, 2325 | { 2326 | "matcher": { 2327 | "id": "byRegexp", 2328 | "options": "/.*sda.*/" 2329 | }, 2330 | "properties": [ 2331 | { 2332 | "id": "color", 2333 | "value": { 2334 | "fixedColor": "#7EB26D", 2335 | "mode": "fixed" 2336 | } 2337 | } 2338 | ] 2339 | }, 2340 | { 2341 | "matcher": { 2342 | "id": "byRegexp", 2343 | "options": "/.*sdb.*/" 2344 | }, 2345 | "properties": [ 2346 | { 2347 | "id": "color", 2348 | "value": { 2349 | "fixedColor": "#EAB839", 2350 | "mode": "fixed" 2351 | } 2352 | } 2353 | ] 2354 | }, 2355 | { 2356 | "matcher": { 2357 | "id": "byRegexp", 2358 | "options": "/.*sdc.*/" 2359 | }, 2360 | "properties": [ 2361 | { 2362 | "id": "color", 2363 | "value": { 2364 | "fixedColor": "#6ED0E0", 2365 | "mode": "fixed" 2366 | } 2367 | } 2368 | ] 2369 | }, 2370 | { 2371 | "matcher": { 2372 | "id": "byRegexp", 2373 | "options": "/.*sdd.*/" 2374 | }, 2375 | "properties": [ 2376 | { 2377 | "id": "color", 2378 | "value": { 2379 | "fixedColor": "#EF843C", 2380 | "mode": "fixed" 2381 | } 2382 | } 2383 | ] 2384 | }, 2385 | { 2386 | "matcher": { 2387 | "id": "byRegexp", 2388 | "options": "/.*sde.*/" 2389 | }, 2390 | "properties": [ 2391 | { 2392 | "id": "color", 2393 | "value": { 2394 | "fixedColor": "#E24D42", 2395 | "mode": "fixed" 2396 | } 2397 | } 2398 | ] 2399 | }, 2400 | { 2401 | "matcher": { 2402 | "id": "byType", 2403 | "options": "time" 2404 | }, 2405 | "properties": [ 2406 | { 2407 | "id": "custom.axisPlacement", 2408 | "value": "hidden" 2409 | } 2410 | ] 2411 | } 2412 | ] 2413 | }, 2414 | "gridPos": { 2415 | "h": 12, 2416 | "w": 12, 2417 | "x": 12, 2418 | "y": 71 2419 | }, 2420 | "id": 18, 2421 | "links": [], 2422 | "options": { 2423 | "legend": { 2424 | "calcs": [ 2425 | "mean", 2426 | "lastNotNull", 2427 | "max", 2428 | "min" 2429 | ], 2430 | "displayMode": "table", 2431 | "placement": "bottom", 2432 | "showLegend": true 2433 | }, 2434 | "tooltip": { 2435 | "mode": "multi", 2436 | "sort": "none" 2437 | } 2438 | }, 2439 | "pluginVersion": "9.2.0", 2440 | "targets": [ 2441 | { 2442 | "datasource": { 2443 | "type": "prometheus", 2444 | "uid": "P1809F7CD0C75ACF3" 2445 | }, 2446 | "expr": "rate(node_disk_read_bytes_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", 2447 | "format": "time_series", 2448 | "hide": false, 2449 | "intervalFactor": 1, 2450 | "legendFormat": "{{device}} - Successfully read bytes", 2451 | "refId": "A", 2452 | "step": 240 2453 | }, 2454 | { 2455 | "datasource": { 2456 | "type": "prometheus", 2457 | "uid": "P1809F7CD0C75ACF3" 2458 | }, 2459 | "expr": "rate(node_disk_written_bytes_total{instance=\"$node\",job=\"$job\",device=~\"$diskdevices\"}[$__rate_interval])", 2460 | "format": "time_series", 2461 | "hide": false, 2462 | "intervalFactor": 1, 2463 | "legendFormat": "{{device}} - Successfully written bytes", 2464 | "refId": "B", 2465 | "step": 240 2466 | } 2467 | ], 2468 | "title": "I/O Usage Read / Write", 2469 | "type": "timeseries" 2470 | } 2471 | ], 2472 | "refresh": false, 2473 | "schemaVersion": 37, 2474 | "style": "dark", 2475 | "tags": [], 2476 | "templating": { 2477 | "list": [ 2478 | { 2479 | "current": { 2480 | "selected": false, 2481 | "text": "node", 2482 | "value": "node" 2483 | }, 2484 | "datasource": { 2485 | "type": "prometheus", 2486 | "uid": "P1809F7CD0C75ACF3" 2487 | }, 2488 | "definition": "label_values(node_uname_info, job)", 2489 | "hide": 0, 2490 | "includeAll": false, 2491 | "label": "Job", 2492 | "multi": false, 2493 | "name": "job", 2494 | "options": [], 2495 | "query": { 2496 | "query": "label_values(node_uname_info, job)", 2497 | "refId": "StandardVariableQuery" 2498 | }, 2499 | "refresh": 1, 2500 | "regex": "", 2501 | "skipUrlSync": false, 2502 | "sort": 1, 2503 | "type": "query" 2504 | }, 2505 | { 2506 | "current": { 2507 | "selected": false, 2508 | "text": "prometheus", 2509 | "value": "prometheus" 2510 | }, 2511 | "hide": 0, 2512 | "includeAll": false, 2513 | "label": "datasource", 2514 | "multi": false, 2515 | "name": "DS_PROMETHEUS", 2516 | "options": [], 2517 | "query": "prometheus", 2518 | "refresh": 1, 2519 | "regex": "", 2520 | "skipUrlSync": false, 2521 | "type": "datasource" 2522 | }, 2523 | { 2524 | "current": { 2525 | "selected": false, 2526 | "text": "10.1.0.4:9100", 2527 | "value": "10.1.0.4:9100" 2528 | }, 2529 | "datasource": { 2530 | "type": "prometheus", 2531 | "uid": "P1809F7CD0C75ACF3" 2532 | }, 2533 | "definition": "label_values(node_uname_info{job=\"$job\"}, instance)", 2534 | "hide": 0, 2535 | "includeAll": false, 2536 | "label": "Host:", 2537 | "multi": false, 2538 | "name": "node", 2539 | "options": [], 2540 | "query": { 2541 | "query": "label_values(node_uname_info{job=\"$job\"}, instance)", 2542 | "refId": "StandardVariableQuery" 2543 | }, 2544 | "refresh": 1, 2545 | "regex": "", 2546 | "skipUrlSync": false, 2547 | "sort": 1, 2548 | "type": "query" 2549 | }, 2550 | { 2551 | "current": { 2552 | "selected": false, 2553 | "text": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+", 2554 | "value": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+" 2555 | }, 2556 | "hide": 0, 2557 | "includeAll": false, 2558 | "multi": false, 2559 | "name": "diskdevices", 2560 | "options": [ 2561 | { 2562 | "selected": true, 2563 | "text": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+", 2564 | "value": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+" 2565 | } 2566 | ], 2567 | "query": "[a-z]+|nvme[0-9]+n[0-9]+|mmcblk[0-9]+", 2568 | "skipUrlSync": false, 2569 | "type": "custom" 2570 | } 2571 | ] 2572 | }, 2573 | "time": { 2574 | "from": "now-30m", 2575 | "to": "now" 2576 | }, 2577 | "timepicker": {}, 2578 | "timezone": "", 2579 | "title": "http dashboard", 2580 | "uid": "70gF87v4k", 2581 | "version": 1, 2582 | "weekStart": "" 2583 | } --------------------------------------------------------------------------------