pax_global_header00006660000000000000000000000064141576221560014523gustar00rootroot0000000000000052 comment=6eec62552b2b684091eb7a1f70342060510595af prometheus-smokeping-prober-0.5.0/000077500000000000000000000000001415762215600172015ustar00rootroot00000000000000prometheus-smokeping-prober-0.5.0/.circleci/000077500000000000000000000000001415762215600210345ustar00rootroot00000000000000prometheus-smokeping-prober-0.5.0/.circleci/config.yml000066400000000000000000000030311415762215600230210ustar00rootroot00000000000000--- version: 2.1 orbs: prometheus: prometheus/prometheus@0.15.0 executors: # This must match .promu.yml. golang: docker: - image: circleci/golang:1.17 jobs: test: executor: golang steps: - checkout - run: go mod download - run: make promu - run: make style lint unused test build - run: rm -v smokeping_prober workflows: version: 2 smokeping_prober: jobs: - test: filters: tags: only: /.*/ - prometheus/build: name: build parallelism: 3 promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386" filters: tags: ignore: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/ branches: ignore: /^(master|release-.*|.*build-all.*)$/ - prometheus/build: name: build_all parallelism: 3 filters: branches: only: /^(master|release-.*|.*build-all.*)$/ tags: only: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/ - prometheus/publish_master: docker_hub_organization: superque quay_io_organization: superq requires: - test - build_all filters: branches: only: master - prometheus/publish_release: docker_hub_organization: superque quay_io_organization: superq requires: - test - build_all filters: tags: only: /^v.*/ branches: ignore: /.*/ prometheus-smokeping-prober-0.5.0/.gitignore000066400000000000000000000000751415762215600211730ustar00rootroot00000000000000smokeping_prober /.build /.deps /.release /.tarballs /vendor prometheus-smokeping-prober-0.5.0/.golangci.yml000066400000000000000000000001151415762215600215620ustar00rootroot00000000000000--- linters-settings: errcheck: exclude: scripts/errcheck_excludes.txt prometheus-smokeping-prober-0.5.0/.promu.yml000066400000000000000000000010531415762215600211430ustar00rootroot00000000000000go: # This must match .circle/config.yml. version: 1.17 repository: path: github.com/superq/smokeping_prober build: flags: -a -tags 'netgo static_build' ldflags: | -X github.com/prometheus/common/version.Version={{.Version}} -X github.com/prometheus/common/version.Revision={{.Revision}} -X github.com/prometheus/common/version.Branch={{.Branch}} -X github.com/prometheus/common/version.BuildUser={{user}}@{{host}} -X github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}} tarball: files: - LICENSE prometheus-smokeping-prober-0.5.0/CHANGELOG.md000066400000000000000000000014101415762215600210060ustar00rootroot00000000000000## master / unreleased * [CHANGE] * [FEATURE] * [ENHANCEMENT] * [BUGFIX] # 0.5.0 / 2021-12-19 * [FEATURE] Support loading targets from a config file #54 # 0.4.2 / 2021-04-10 * [BUGFIX] Fix sequence number wrapping #53 # 0.4.1 / 2021-02-02 * [ENHANCEMENT] Smooth out pingers over the interval #48 * [BUGFIX] Fix memory leak #49 ## 0.4.0 / 2021-01-31 * [FEATURE] Add support for duplicate packet detection #47 ## 0.3.1 / 2020-06-04 Rebuild with latest Go / vendoring. ## 0.3.0 / 2019-06-25 * [FEATURE] Enable pprof * [FEATURE] Add TTL monitoring #20 * [ENHANCEMENT] Update to latest upstream go-ping library #20 ## 0.2.0 / 2019-05-14 * [FEATURE] Add example rules file. #12 * [FEATURE] Allow setting buckets from flag. #17 ## 0.1.0 / 2018-11-08 Initial release prometheus-smokeping-prober-0.5.0/Dockerfile000066400000000000000000000004351415762215600211750ustar00rootroot00000000000000ARG ARCH="amd64" ARG OS="linux" FROM quay.io/prometheus/busybox-${OS}-${ARCH}:latest LABEL maintainer="Ben Kochie " ARG ARCH="amd64" ARG OS="linux" COPY .build/${OS}-${ARCH}/smokeping_prober /bin/smokeping_prober EXPOSE 9374 ENTRYPOINT [ "/bin/smokeping_prober" ] prometheus-smokeping-prober-0.5.0/LICENSE000066400000000000000000000261351415762215600202150ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. prometheus-smokeping-prober-0.5.0/Makefile000066400000000000000000000013171415762215600206430ustar00rootroot00000000000000# Copyright 2018 The Prometheus Authors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. DOCKER_ARCHS ?= amd64 armv7 arm64 DOCKER_REPO ?= quay.io/superq DOCKER_IMAGE_NAME ?= smokeping-prober include Makefile.common prometheus-smokeping-prober-0.5.0/Makefile.common000066400000000000000000000244531415762215600221400ustar00rootroot00000000000000# Copyright 2018 The Prometheus Authors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # A common Makefile that includes rules to be reused in different prometheus projects. # !!! Open PRs only against the prometheus/prometheus/Makefile.common repository! # Example usage : # Create the main Makefile in the root project directory. # include Makefile.common # customTarget: # @echo ">> Running customTarget" # # Ensure GOBIN is not set during build so that promu is installed to the correct path unexport GOBIN GO ?= go GOFMT ?= $(GO)fmt FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) GOOPTS ?= GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) GO_VERSION ?= $(shell $(GO) version) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') GOVENDOR := GO111MODULE := ifeq (, $(PRE_GO_111)) ifneq (,$(wildcard go.mod)) # Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). GO111MODULE := on ifneq (,$(wildcard vendor)) # Always use the local vendor/ directory to satisfy the dependencies. GOOPTS := $(GOOPTS) -mod=vendor endif endif else ifneq (,$(wildcard go.mod)) ifneq (,$(wildcard vendor)) $(warning This repository requires Go >= 1.11 because of Go modules) $(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)') endif else # This repository isn't using Go modules (yet). GOVENDOR := $(FIRST_GOPATH)/bin/govendor endif endif PROMU := $(FIRST_GOPATH)/bin/promu pkgs = ./... ifeq (arm, $(GOHOSTARCH)) GOHOSTARM ?= $(shell GOARM= $(GO) env GOARM) GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)v$(GOHOSTARM) else GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH) endif GOTEST := $(GO) test GOTEST_DIR := ifneq ($(CIRCLE_JOB),) ifneq ($(shell which gotestsum),) GOTEST_DIR := test-results GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- endif endif PROMU_VERSION ?= 0.13.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= GOLANGCI_LINT_VERSION ?= v1.42.0 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) # If we're in CI and there is an Actions file, that means the linter # is being run in Actions, so we don't need to run it here. ifeq (,$(CIRCLE_JOB)) GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint else ifeq (,$(wildcard .github/workflows/golangci-lint.yml)) GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint endif endif endif PREFIX ?= $(shell pwd) BIN_DIR ?= $(shell pwd) DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD)) DOCKERFILE_PATH ?= ./Dockerfile DOCKERBUILD_CONTEXT ?= ./ DOCKER_REPO ?= prom DOCKER_ARCHS ?= amd64 BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS)) ifeq ($(GOHOSTARCH),amd64) ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) # Only supported on amd64 test-flags := -race endif endif # This rule is used to forward a target like "build" to "common-build". This # allows a new "build" target to be defined in a Makefile which includes this # one and override "common-build" without override warnings. %: common-% ; .PHONY: common-all common-all: precheck style check_license lint yamllint unused build test .PHONY: common-style common-style: @echo ">> checking code style" @fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \ if [ -n "$${fmtRes}" ]; then \ echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \ echo "Please ensure you are using $$($(GO) version) for formatting code."; \ exit 1; \ fi .PHONY: common-check_license common-check_license: @echo ">> checking license header" @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ done); \ if [ -n "$${licRes}" ]; then \ echo "license header checking failed:"; echo "$${licRes}"; \ exit 1; \ fi .PHONY: common-deps common-deps: @echo ">> getting dependencies" ifdef GO111MODULE GO111MODULE=$(GO111MODULE) $(GO) mod download else $(GO) get $(GOOPTS) -t ./... endif .PHONY: update-go-deps update-go-deps: @echo ">> updating Go dependencies" @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ $(GO) get -d $$m; \ done GO111MODULE=$(GO111MODULE) $(GO) mod tidy ifneq (,$(wildcard vendor)) GO111MODULE=$(GO111MODULE) $(GO) mod vendor endif .PHONY: common-test-short common-test-short: $(GOTEST_DIR) @echo ">> running short tests" GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) .PHONY: common-test common-test: $(GOTEST_DIR) @echo ">> running all tests" GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) $(GOTEST_DIR): @mkdir -p $@ .PHONY: common-format common-format: @echo ">> formatting code" GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) .PHONY: common-vet common-vet: @echo ">> vetting code" GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) .PHONY: common-lint common-lint: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint" ifdef GO111MODULE # 'go list' needs to be executed before staticcheck to prepopulate the modules cache. # Otherwise staticcheck might fail randomly for some reason not yet explained. GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) else $(GOLANGCI_LINT) run $(pkgs) endif endif .PHONY: common-yamllint common-yamllint: @echo ">> running yamllint on all YAML files in the repository" ifeq (, $(shell which yamllint)) @echo "yamllint not installed so skipping" else yamllint . endif # For backward-compatibility. .PHONY: common-staticcheck common-staticcheck: lint .PHONY: common-unused common-unused: $(GOVENDOR) ifdef GOVENDOR @echo ">> running check for unused packages" @$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages' else ifdef GO111MODULE @echo ">> running check for unused/missing packages in go.mod" GO111MODULE=$(GO111MODULE) $(GO) mod tidy ifeq (,$(wildcard vendor)) @git diff --exit-code -- go.sum go.mod else @echo ">> running check for unused packages in vendor/" GO111MODULE=$(GO111MODULE) $(GO) mod vendor @git diff --exit-code -- go.sum go.mod vendor/ endif endif endif .PHONY: common-build common-build: promu @echo ">> building binaries" GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) .PHONY: common-tarball common-tarball: promu @echo ">> building release tarball" $(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR) .PHONY: common-docker $(BUILD_DOCKER_ARCHS) common-docker: $(BUILD_DOCKER_ARCHS) $(BUILD_DOCKER_ARCHS): common-docker-%: docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \ -f $(DOCKERFILE_PATH) \ --build-arg ARCH="$*" \ --build-arg OS="linux" \ $(DOCKERBUILD_CONTEXT) .PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) common-docker-publish: $(PUBLISH_DOCKER_ARCHS) $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION))) .PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) common-docker-tag-latest: $(TAG_DOCKER_ARCHS) $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" .PHONY: common-docker-manifest common-docker-manifest: DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG)) DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" .PHONY: promu promu: $(PROMU) $(PROMU): $(eval PROMU_TMP := $(shell mktemp -d)) curl -s -L $(PROMU_URL) | tar -xvzf - -C $(PROMU_TMP) mkdir -p $(FIRST_GOPATH)/bin cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu rm -r $(PROMU_TMP) .PHONY: proto proto: @echo ">> generating code from proto files" @./scripts/genproto.sh ifdef GOLANGCI_LINT $(GOLANGCI_LINT): mkdir -p $(FIRST_GOPATH)/bin curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_LINT_VERSION)/install.sh \ | sed -e '/install -d/d' \ | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) endif ifdef GOVENDOR .PHONY: $(GOVENDOR) $(GOVENDOR): GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor endif .PHONY: precheck precheck:: define PRECHECK_COMMAND_template = precheck:: $(1)_precheck PRECHECK_COMMAND_$(1) ?= $(1) $$(strip $$(PRECHECK_OPTIONS_$(1))) .PHONY: $(1)_precheck $(1)_precheck: @if ! $$(PRECHECK_COMMAND_$(1)) 1>/dev/null 2>&1; then \ echo "Execution of '$$(PRECHECK_COMMAND_$(1))' command failed. Is $(1) installed?"; \ exit 1; \ fi endef prometheus-smokeping-prober-0.5.0/README.md000066400000000000000000000051021415762215600204560ustar00rootroot00000000000000# smokeping_prober Prometheus style "smokeping" prober. ![Example Graph](example-graph.png) ## Overview This prober sends a series of ICMP (or UDP) pings to a target and records the responses in Prometheus histogram metrics. ``` usage: smokeping_prober [] [...] Flags: -h, --help Show context-sensitive help (also try --help-long and --help-man). --config.file="smokeping_prober.yml" Optional smokeping_prober configuration file. --web.listen-address=":9374" Address on which to expose metrics and web interface. --web.telemetry-path="/metrics" Path under which to expose metrics. --buckets="5e-05,0.0001,0.0002,0.0004,0.0008,0.0016,0.0032,0.0064,0.0128,0.0256,0.0512,0.1024,0.2048,0.4096,0.8192,1.6384,3.2768,6.5536,13.1072,26.2144" A comma delimited list of buckets to use -i, --ping.interval=1s Ping interval duration --privileged Run in privileged ICMP mode --log.level="info" Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal] --log.format="logger:stderr" Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true" --version Show application version. Args: [] List of hosts to ping ``` ## Configuration The prober can take a list of targets and parameters from the command line or from a yaml config file. Example config: ```yaml --- targets: - hosts: - host1 - host2 interval: 1s # Duration, Default 1s. network: ip # One of ip, ip4, ip6. Default: ip (automatic IPv4/IPv6) protocol: icmp # One of icmp, udp. Default: icmp (Requires privileged operation) ``` In each host group the `interval`, `network`, and `protocol` are optional. The interval Duration is in [Go time.ParseDuration()](https://golang.org/pkg/time/#ParseDuration) syntax. NOTE: The config is only read on startup, SIGHUP is not supported (yet). ## Building and running Requires Go >= 1.14 ```console go get github.com/superq/smokeping_prober sudo setcap cap_net_raw=+ep ${GOPATH}/bin/smokeping_prober ``` ## Metrics Metric Name | Type | Description ----------------------------------------|------------|------------------------------------------- smokeping\_requests\_total | Counter | Counter of pings sent. smokeping\_response\_duration\_seconds | Histogram | Ping response duration. prometheus-smokeping-prober-0.5.0/VERSION000066400000000000000000000000061415762215600202450ustar00rootroot000000000000000.5.0 prometheus-smokeping-prober-0.5.0/collector.go000066400000000000000000000075051415762215600215250ustar00rootroot00000000000000// Copyright 2018 Ben Kochie // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "github.com/go-ping/ping" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) const ( namespace = "smokeping" ) var ( labelNames = []string{"ip", "host"} pingResponseTtl = promauto.NewGaugeVec( prometheus.GaugeOpts{ Namespace: namespace, Name: "response_ttl", Help: "The last response Time To Live (TTL).", }, labelNames, ) pingResponseDuplicates = promauto.NewCounterVec( prometheus.CounterOpts{ Namespace: namespace, Name: "response_duplicates_total", Help: "The number of duplicated response packets.", }, labelNames, ) ) func newPingResponseHistogram(buckets []float64) *prometheus.HistogramVec { return prometheus.NewHistogramVec( prometheus.HistogramOpts{ Namespace: namespace, Name: "response_duration_seconds", Help: "A histogram of latencies for ping responses.", Buckets: prometheus.ExponentialBuckets(0.00025, 2, 16), }, labelNames, ) } // SmokepingCollector collects metrics from the pinger. type SmokepingCollector struct { pingers *[]*ping.Pinger requestsSent *prometheus.Desc } func NewSmokepingCollector(pingers *[]*ping.Pinger, pingResponseSeconds prometheus.HistogramVec) *SmokepingCollector { for _, pinger := range *pingers { // Init all metrics to 0s. ipAddr := pinger.IPAddr().String() pingResponseDuplicates.WithLabelValues(ipAddr, pinger.Addr()) pingResponseSeconds.WithLabelValues(ipAddr, pinger.Addr()) pingResponseTtl.WithLabelValues(ipAddr, pinger.Addr()) // Setup handler functions. pinger.OnRecv = func(pkt *ping.Packet) { pingResponseSeconds.WithLabelValues(pkt.IPAddr.String(), pkt.Addr).Observe(pkt.Rtt.Seconds()) pingResponseTtl.WithLabelValues(pkt.IPAddr.String(), pkt.Addr).Set(float64(pkt.Ttl)) level.Debug(logger).Log("msg", "Echo reply", "ip_addr", pkt.IPAddr, "bytes_received", pkt.Nbytes, "icmp_seq", pkt.Seq, "time", pkt.Rtt, "ttl", pkt.Ttl) } pinger.OnDuplicateRecv = func(pkt *ping.Packet) { pingResponseDuplicates.WithLabelValues(pkt.IPAddr.String(), pkt.Addr).Inc() level.Debug(logger).Log("msg", "Echo reply (DUP!)", "ip_addr", pkt.IPAddr, "bytes_received", pkt.Nbytes, "icmp_seq", pkt.Seq, "time", pkt.Rtt, "ttl", pkt.Ttl) } pinger.OnFinish = func(stats *ping.Statistics) { level.Debug(logger).Log("msg", "Ping statistics", "addr", stats.Addr, "packets_sent", stats.PacketsSent, "packets_received", stats.PacketsRecv, "packet_loss_percent", stats.PacketLoss, "min_rtt", stats.MinRtt, "avg_rtt", stats.AvgRtt, "max_rtt", stats.MaxRtt, "stddev_rtt", stats.StdDevRtt) } } return &SmokepingCollector{ pingers: pingers, requestsSent: prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "requests_total"), "Number of ping requests sent", labelNames, nil, ), } } func (s *SmokepingCollector) Describe(ch chan<- *prometheus.Desc) { ch <- s.requestsSent } func (s *SmokepingCollector) Collect(ch chan<- prometheus.Metric) { for _, pinger := range *s.pingers { stats := pinger.Statistics() ch <- prometheus.MustNewConstMetric( s.requestsSent, prometheus.CounterValue, float64(stats.PacketsSent), stats.IPAddr.String(), stats.Addr, ) } } prometheus-smokeping-prober-0.5.0/config/000077500000000000000000000000001415762215600204465ustar00rootroot00000000000000prometheus-smokeping-prober-0.5.0/config/config.go000066400000000000000000000056321415762215600222500ustar00rootroot00000000000000// Copyright 2021 Ben Kochie // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package config import ( "fmt" "os" "sync" "time" yaml "gopkg.in/yaml.v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) const namespace = "smokeping_prober" var ( configReloadSuccess = promauto.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "config_last_reload_successful", Help: "Blackbox exporter config loaded successfully.", }) configReloadSeconds = promauto.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "config_last_reload_success_timestamp_seconds", Help: "Timestamp of the last successful configuration reload.", }) // DefaultTargetGroup sets the default configuration for the TargetGroup DefaultTargetGroup = TargetGroup{ Interval: time.Second, Network: "ip", Protocol: "icmp", } ) type Config struct { Targets []TargetGroup `yaml:"targets"` } type SafeConfig struct { sync.RWMutex C *Config } func (sc *SafeConfig) ReloadConfig(confFile string) (err error) { var c = &Config{} defer func() { if err != nil { configReloadSuccess.Set(0) } else { configReloadSuccess.Set(1) configReloadSeconds.SetToCurrentTime() } }() yamlReader, err := os.Open(confFile) if err != nil { return fmt.Errorf("error reading config file: %w", err) } defer yamlReader.Close() decoder := yaml.NewDecoder(yamlReader) if err = decoder.Decode(c); err != nil { return fmt.Errorf("error parsing config file: %w", err) } sc.Lock() sc.C = c sc.Unlock() return nil } type TargetGroup struct { Hosts []string `yaml:"hosts"` Interval time.Duration `yaml:"interval,omitempty"` Network string `yaml:"network,omitempty"` Protocol string `yaml:"protocol,omitempty"` // TODO: Needs work to fix MetricFamily consistency. // Labels map[string]string `yaml:"labels,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (s *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { type plain Config if err := unmarshal((*plain)(s)); err != nil { return err } return nil } // UnmarshalYAML implements the yaml.Unmarshaler interface. func (s *TargetGroup) UnmarshalYAML(unmarshal func(interface{}) error) error { *s = DefaultTargetGroup type plain TargetGroup if err := unmarshal((*plain)(s)); err != nil { return err } return nil } prometheus-smokeping-prober-0.5.0/dashboard.json000066400000000000000000000102101415762215600220150ustar00rootroot00000000000000{ "__inputs": [ { "name": "DS_PROMETHEUS", "label": "Prometheus", "description": "", "type": "datasource", "pluginId": "prometheus", "pluginName": "Prometheus" } ], "__requires": [ { "type": "grafana", "id": "grafana", "name": "Grafana", "version": "6.4.0" }, { "type": "panel", "id": "heatmap", "name": "Heatmap", "version": "" }, { "type": "datasource", "id": "prometheus", "name": "Prometheus", "version": "1.0.0" } ], "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "gnetId": null, "graphTooltip": 0, "id": null, "iteration": 1573496641574, "links": [], "panels": [ { "cards": { "cardPadding": null, "cardRound": null }, "color": { "cardColor": "#b4ff00", "colorScale": "sqrt", "colorScheme": "interpolateOranges", "exponent": 0.5, "mode": "opacity" }, "dataFormat": "tsbuckets", "datasource": "${DS_PROMETHEUS}", "gridPos": { "h": 17, "w": 24, "x": 0, "y": 0 }, "heatmap": {}, "hideZeroBuckets": false, "highlightCards": true, "id": 2, "legend": { "show": false }, "links": [], "options": {}, "reverseYBuckets": false, "targets": [ { "expr": "sum(rate(smokeping_response_duration_seconds_bucket{instance=~\"$prober\",host=\"$target\"}[5m])) by (le)", "format": "heatmap", "intervalFactor": 1, "legendFormat": "{{le}}", "refId": "A" } ], "title": "Smokeping", "tooltip": { "show": true, "showHistogram": false }, "type": "heatmap", "xAxis": { "show": true }, "xBucketNumber": null, "xBucketSize": null, "yAxis": { "decimals": 0, "format": "s", "logBase": 1, "max": null, "min": "0", "show": true, "splitFactor": null }, "yBucketBound": "auto", "yBucketNumber": null, "yBucketSize": null } ], "refresh": "30s", "schemaVersion": 20, "style": "dark", "tags": [], "templating": { "list": [ { "allValue": null, "current": {}, "datasource": "${DS_PROMETHEUS}", "definition": "", "hide": 0, "includeAll": false, "label": null, "multi": true, "name": "prober", "options": [], "query": "label_values(smokeping_prober_build_info, instance)", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false }, { "allValue": null, "current": {}, "datasource": "${DS_PROMETHEUS}", "definition": "label_values(smokeping_response_duration_seconds_bucket, host)", "hide": 0, "includeAll": false, "label": null, "multi": false, "name": "target", "options": [], "query": "label_values(smokeping_response_duration_seconds_bucket, host)", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "tagValuesQuery": "", "tags": [], "tagsQuery": "", "type": "query", "useTags": false } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": { "refresh_intervals": [ "5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ], "time_options": [ "5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d" ] }, "timezone": "", "title": "Smokeping", "uid": "i5aRaLaik", "version": 11 } prometheus-smokeping-prober-0.5.0/example-graph.png000066400000000000000000002471761415762215600224620ustar00rootroot00000000000000PNG  IHDR!AsBITOtEXtSoftwaregnome-screenshot> IDATxyg&3d{]9TPPGGGmT Z+'QUQ<(r)7,,}'I~2;d]d2|'3REť= {aL0&^q2Ld2L& ?EfV|N(c!))L&S B'2[hQQ51XDR) 4z諯no%0*!acʂSN^~i?^Bȼ>- `% aHB_O=[!Z-7rԨ3n/**3w9!O>Ԋ+23jNLQT] @_K&q(P(!>oͧkԬ<묳 v{yEynnn"|xwgpdǎ077ϳ-Nc׮]LBȹG>4xn&aa*`Νb#˲>w;<ۿo63k4M6qBgi89j$!dM{w]}vԩSsee~L&8]@BEQwO~r [6o`ܸ[}k/So&eŇ<Ͽ+.!d997Ο?vxMvsl߶G C!dժU\s9+Vi7--kk./ƦnM|q1b) !\vȑGymcC#!j߾ŋ]|񏗽LOB>w0Cnm'?)>|ǎ#//o„ u*#]U @0&~7gE}˿.ݮ;w~5H?MQ,6~p O2Yp|2ao) -{ C>7t Z)6f;v,!d` -y~ɷnYdSL~.}jP(?'$.^VsR&BȊ+gyȑ#O?rƑe/|AAg)6.y~ɲenwEEּu]7gμXNE|yp 6t̘1q_'S/$S~k$T~A0!kY66eNG$r X5joԩSoOV<ۋ9tBhߘٜ/BN;K/u' ]LD?Op,\3jrj!@N2Ə9%KK&ee*V ti}j-ZXVZٻcǎNqIfǫ=n)מq x}ko.hJ{]`@>|NVE,ßu9FQݞ.Ne>!7 $.f=@˜ {aL0&^d/ Ƅ cB1!@˜ {aL0&^d/ Ƅ cB1!@ʊ1ayE%\0LSVVV?qVV '?wF7\Wu XژU{n߾aU'SmLXXXk'u1byG+**Nߞ{~s3fqEQ=hiiوF<أF:n5 bwayq\uuhGck֬).)v=k֬iiiJ)2&j,Bt:!dCP<OLBxŗ!['sgBNW= SdL8wޜK? ,zo۶].))RT*ՙgh4z{T44jmkkxSCX ô98!PUTTxB@'`2)ZFqb=v@$"c§zFVBFyw̚9Kl:$!=<&I5b|NN!$^ЅFq] MFU"H45LRīLBH0H$FQj}4RUYV'8Npb @@Պ|(Q!$H‘Hl6K //4RST:t T*k\.멬:.677BJ-l6&'ǜk5W:BE|)`Hu܃Iav:]~cbRB`0W,,X{uuZfb1)o˳JM$nnH@ ()):v{Ie*xDjillRŽW[[ćdZ%ln_{<744lVhGZZZ ZHy6gAC]abz (rJD:ww=BZP[#˃ҜHtdfi}{yNӃD9m!$YTQ^}}FR"Qn8=.4f"2l6[,)9˕j1:]Az=.WAxiiWABOrZZZ,|9if;pL-%>z!/ |Ap{fsa1 ]PR7A81,smmpv|DMM4M;,ǣB?9~wzT é6&lllx )}®-_Dp8JY}\+PuB9 Ƅ cB1!@˜ {aL0&^d/ Ƅ cB1!@bd.fq^wmv]lQQرc5Mu[n& Ì?*˭VQve*b\Դo޾ESP +.\@Q%3g/g/{fs` oz׋?y34hys z' ͛;rE/Jp7xG~1!\ ~=wH$BQC?8k/\H$m3Xr%!d1_YYYSS5?Zmg5L4)fԐCֶcc2 y;vF"BH2\ &l6~e?|8M'_;hgV=={fW~أ [)e̙U#G-p7yse0].ڵk|wkBIO12_|ӵ^{7F E?qgÇ9v&Re/ڽٿ<+駟y@^x?{㋾ҳvѣfsE>җu>_{tr7߼l}Qg  GI$<cY5MӄCx<ކzZCQԑ=-WAptP! st(^ftt:4xM)rby$QN'ϛ ANW2$ֳRT r:]ZJw:]zNz=}D1%BIr9_mw: ǝN!}!$8.a!!Aqmz>˭}A\{XL<"P!IEyZ-'+t BBVt(>DNexpXZ IDAT@ t8Ο^1 S}Hyx<.!.Gw@ӕH>[NMwGN˪ B"^o 0 #B $]AiZz}Oʞx᰼<ǝHԜӃe ED=<27y4uzd_i4^"^)ʋŔ9("/tiʜ 2E 0 uru72l tS)z}RNibNr4!//czT,Ry]LAz<)9z3tXD7"DJHRdVtj.=staA5rqEN Iʂi0Sө7-RrINb`#Òat ȿtA}!AH|&ҧ4c_8s#GpbE1{ gn))HwgnG41uX`0DŽP(csGXxݺuv1ydV !m޴fҙ/ywPM}H'.)-v9[|'V"aP :vyZ-Yfn߾r1\jo|g?ٜ/] ӧ0ի?% g߱ k^q]Lo;fܑ06} y{R ]dΜ=aÆ 6L&Vr p Ou|k> tL@˜ {aL0&^d/ Ƅ cB1!@˜ {aL>Ì?JޮRƎSV6([u^̄jǏWXXz6|/BZIccþ}2ju}}M䱾OSHߌ  4w!C^|8g/~’kڻh2ͺUVⲣIAA`YjPY٭[Ezu9LVDŽ3gͼ暫_55͝F-`L8jԨG~jn6N~tMSMٚ:̸cF,5P(D ̞Ç|?r &NfѢ'Z!dСyW_s{+; pjC=֛o%={q@HҞD׍3w("$WV6hС90 sウ!D#s8 $TWW+*qM7St?OzNF}pp-=ч~0BHmm]gRQQ0LuuǷ ! #4iV}m۶o۶]zjsrM-鋸Yg}믽t:9m֬,**(#'4M=KQ4Mhiwi:4h2t,K,/N+FY^E<Ch4-DRuhRV,F"QgŤYN_3EӴbSfӺ`6.F)1TRًcZ;sK[t772wgnU/4ņ'T~A !ܻy-[{˳sG[QQqEXnwo*frE>ЃLuKKp?YoK-e/^IΙ{1ϧx7_/_}s۳7b!`S`(?x`8ZPVVVT<ىlll,gܹKq Ykذ@y S!*~w '_kXvy`W;aBH"8ϋ풉'b><q=BBHuuW^z6n$@ӴjZIJ,]):`0Xh46е !''eY6Ѕ ikQh,`ld22 .P( dǣZnݺuX2eʂ zF"BZ'(p\8Ov啗x\C+..;g=tO,Z|-Ӯnv'?yݕ]PE99&7@h4&fDa|l"L&S"Hq5Nd2cL")Ge옐(f/_~ŕW\|=675B -_R5t\F6l5/o'?=[ // 2d…nŲt)Aصk%%ńH$p8l<# :>󕔔HxG;u8 H----,/K666Z">L$MMM999FQlynt:% ;NͦѴ.**Tz>_?.;u֖L&;---,Zse5z,f9`h//ZV';|4HiAN+kmm%ܬhrs;khh0999 Ñ򢭭mVkVˉ-Prj{bx`I<'󅅅Ƚ_}U"_jjj8.7Yyxbz%Y9N{*((`YHy>חZ^Ǿ*r8J-v]Rj9d2h2L&ӑ{jy #{Zaaô׻ -*mLFc{y!4%HJyAӔ (rZVV-Zu:)]~ZXSAhnnh4]AͽBzNATԫ 480r\Aϖ-߹\byNӃ^^Vc <H$z]Vno!:+SbEE2SNYV!ÒKuX= Z{G? ,(g.:,w0v谎iFK uXn;RtX= b1RrF2D9s6,vCj̭Khj37.JD<12[W$2 Dx\-cxjb$ɤE[ljDBqQT| ]Z9]sdåocAHJA'ki*i+<3JђRbOK//Ӟ,/>8/]7kOj<O۸x\p1Y3G<[AAqB~|wW<#.:~Y#rrLV̙sFy~k_|%y~_QcΧ(O!oq=/\tS^F5͛<_ ϛS~x'^vO|>/>ܴikdRoS{vzq@HӦM+++=tYg(_` uo8&O|ι ZvO8IpY#vޝL&>8ABZ$$nÏ39a:qn|PaaqpmEy׬>p:6kLeshɤ^J24= zU 9h-IoJT_Fb0YV-=i`3L6e`ЫT*Y`STj^S'jcE׫P(OSZkeYAOQKWY _q*U~r$NcYVb04ce-uʸ)kOQ')4M .:[juG E몣E\W]aEyjuƍ(Etި2i-ړMqf*c,Z-H$S[2!}OHyqOS+bp65 ҃ = |ZL9UONDzʽ1}OI[!=4eZN)z!}202 U2rG0XVEy:]ʦ$rk'h4(O҃X{Ե~Ue dX{5q\ZْC.!AH-ʹuAE%9!7J]:NK4ړlh4dRٟZNQa)4autXZ6-f>02PgnZ-37r|ܴZmZzy֓KQ48R2/BFs_W^WUUQYVs,ly+V?^Kr{[T*˲MO=Tު;܊.pŊw[!do6lhẑFB~#bo_|sΨh,w^ߡC^N=p!  t!pBiz3] ly;wR!k 64455t!p=ZuBN~?i-I&͸ݻvoٲE1euuZpacCcIIysy]<%rk-;lQZSQQi_t3!3X7p4/+x=7llllڶm{goAʺx6[lٌ857b[ <+ð EY@'l(ǘD6[`P\Sx<h`$ BFkW]}u]]taGH$lV ?}~B﫮<uں>Vg޽{67?fLee>H$!lРg>T,zÆ999W^uԟOO.jUUU(ɉbXL,B4iZl4QTX,*,(qH$"%'Iy2D„%HD"aҊ!x<(ʋF-/V^Xňɋ˓#'/F,a.^yh4"uߨ Ayb1bh4'$p8b1Mz)3w{Zߖw"WeBtd8^!-XWTH$HT#diʞ)=iiiyNirwސix>Ћ =;D"Q\UB"!֦X1CPTTqv{<Aa!ceZLN;`0ڪȩ>+=fƍӃ i$inQU^^&JwXAhjj`6;K/HN{MV8pC8s;>gnf&}rvTOr v1tPq\QQQs saÆBxa׷*=E4i"!djzĈҳcf!**LVWW>ѣGŻ8V'9s˳X,s7èV2x৞z# !cQϹw!ZϺ6mSxo8.b1so!ٳg IDAT]g3d`^7iҤs=BO˛&V#>ܯѿzG~{ !mmE?j'gX݃w}sH$~<4.񦦶63O?#H >WSTv{_ӧN.j4͛7/y~]-'Bnj;rssF&ܱ˯644̟qf+).YVk4~Txy`08߈lذaÆ &Iպ\.OD@1rdH$ҢYnJ&y@ }>I>!0&^d/ Ƅ cB1!@˜ {aL0&^d/  PTcǎ)+:p`gSj4qx=ޭ[vBN7n\Ļw[;VTWߺu|Ç:aUlҧ ׿cBżx\k޽Fi֝wZOY^Qp...9k__,U6[cK/H$үo$ҿc[oj6vB~~iӦ}C)].9s#EQ=Y3rmss_"O7mDϷ_{cʕc`~eeeMM̈́ /7gϞ=-W^IΊ~}'ٳ!!䛯O6T1&dfM;w/%߬0af tMhre?|M'_;EiYi29\.gIIizM buXRIFAj"z`0\LAh4au}KB'G9źbR h4Y(׻ܬV xAI376d@V,!P/(ZO1}sG[QQqEX{+z?wW|#G|| **jeY-oŊw_k⳿// ccv׿>{׿W_sFEc{fMuQyeee8n!ҲÑHtkBqq˪kkk8!4=tЖ;е jUUUI'N;2 )nSX,<<{!{GE'_kXvy`;*:3~oذQ(֯VB8?͛B&M4wڽe)ŢcTL"TT:}LX]]}ŕWx6666m۶T*UeeeۢјVոFZd{d'0!d9Z`0L&See%Ƅ MNla1&\nݺuX2eʂ zߚq^N&JJJG3=(o{!!>21clٲeĉ?vҬ !Z%1c3Y'-i]7uv՟#!D`0.c>d2ItÇkft8 \cXnEK&999RQTFcǝ.Kza2t;k{7$ mAڢ֊m U!X ģD+Z+_bk[/D ZNA!HwLfg7@χLf;yg>;X,fYi!Hl6Rd2y^uCtyHݦD^$IXjLy6!<өދg\&uEs6myTZnv"D9%Qeiˋ&EWd2gW׳,Nrl6L&òz.JrBVEݻptYY=鋢ǵE )T/GA͆PJ$IKZ'Q7lNy@w*DhԴbx<.D! e2 @p剢=)}l00L=S'h(JM Mx~yOZa0C`d2_@%˭ ^:e$j3L(q\DcePh,JjD8SB 9o!YW^r}>.)- ԁ$N']c1zm_mWAOaw VE=,A۩-y%%^\ ͦRp D"LF.P$=*Ap].WA!J"(Ibxvy$I_.Bh۶|1aċ~[?Эn-_ƛnT>znj9zh?zU+Ws+w3˟QjsI++WVݠ[ҭ[?@r9nD◿ŋ_>d(Dmڸl6]z$I<Ͽşx|jg̘βhܹs窕+{k@һsBWZf˲l*>۷wﴫVhExkС?'$ "T7ϛ$I;Zy]]]]]04M }LQY#Ldw֐L&$3 0p.sB`N `9! \0' 0p.E͌?h4uѣ;,?"bҤIUUU ;x/,\-I\zСç9Vu s… \+kjo[z~dm2j˞^m6x'f]Kmm;_jn3g]?k֬zջsB;tжdK/iW@͝;?ᦍAg=x׏@įwݡ g͚v;:7*+ك?ݲe5׌~ {٨w7q/y5WGʄ!x? Lf>AB(4ibUǎP&C@ `0u-_p]6\da'IR.!lF}Q{A~1'4˯bɒEQKg|y,WpҤ+.bw8%*IH,A$IބD"$I\n% fá$) vu,|$u&m2X %%R^yyD"q\IIB1Y^O~yq0X,v][X,J h^y qCQjyd2YZZFORlLP<y><! l//XV/Ivd2r1({hT+ ( p hsZmNqey=4Mwu'NlnWAPƀŕX,&IAKt:NwB60`i XAbi :`)ώfju8`fh{Zh4dV.$^tWn$WnFqǏhll'Wn X̕ X! B^zIiͽC@'Dž&!&NXq{ccc0qk 裏<#C^8iң>e5k5s֝w[fΚY;jyrK1ʃ cs9FdE\ѭaZXeV0Catr9F[$IAhrU\$m 1^8N² c'lsܳgIӧrna6׿K.njj5"v^_} xcƨm;'WΞ}re7=:1Ng3ֻv~̝{M? !tСeO?`'>0k֬ypJ:dɒ{;Q]]]]]07O٬_|P%b(,#;,h7L&).0' 0p."0 IDATsB`N `9! \0' 0p}m &MTUUŰKÇ߾};˲+/pbnjj!I}6't8O>l޵kb}WV~?(;{vNx5,X8MGghF}?X g͚v;:7".ҟ=-[EQovG$i0qh4bh4bi4;Z !j[ $I/H-F <5-dAyѨ+ ˲3M$پimJ1Z{ шP{y$IPԺ.O0 78޾'tEFW^F$CC/O)FB=RBㄶhVO#ѨhE^ EQžY:8yQ!IT~K lOk;p eO3EQʣ(*oC Ei]=} }3 A08-r BN=;T3nD0h7Z^)׽SnHޣtKWL=M?"tup P BgaXQA(8i {Zׇ2O=MN; N# ɞrՕ@ޕ[ᾂ+7T|A[/J*#vذl%CVcb8qºu]˦<n}S$QZ&MG^v"B讻ꪫ(Nz}K/fMkv VdHU'啔v`&z88k%IJŮa^!t:/8U]=@QRl['xl愋U^^`BBÆ s+BMu[ <,gꕲ,7|s:)|6SGy%e^!ҧng 7[ @gs‰'*BPccc0qbsBPCC \.'r\nΜ[H6q%,ˮYϿPSS33gt꿊%IѣMh4N:!`EEdFQX_PY9X}h;b ~H$2D]s EiAjˉE-MMM645x\Ng볾57())-l.l/!J%#R}^<aê \ jĉTm9zxn+- efsLpdALJx<:D* V[[//o{MMǬVS^ʲ|htZ'N4xmr9&ͦRp d2١C; Bss3Ivru]NBT*VU VEaH.!KRATQYݱcgwia00UUڜ+*;~јW.(;֭ T~04M'A0-X].۝Scb0D رcKANN++_q;h:_^@j: s'N xKA:tA$)oD8ȈPQQn2uX,wUv8:2l(i":0'Җ-[ )0~CԯXAhiir95$2݀eUЖӞ^ /lhh8WngMqtZNˀ B/9$I]bte2'NA8_:e';w $U7iEb6O8+"c۶~sرcB$IΜyܶCj3f1++BF3fȑ#B , 8ֽ2vnFI;z̘G\'\rU.aFD4J/{z{BGS_9LӴG8ٜP!r'NhVL&]'s}}B}0p.sB`N `9! \0' 0p.Eu!zǎz۷ogYV."u<ϟz/wc/XRuN?(;{vN8i҅?{g@o;d2GY+)5>×]vkk(Ewo׏̫j?>S9\oz}m}_{'Cqc=Ϻ]yL&7lU(j?aϮwۼCڵk(=vnMP(?644 L&u]7nXN-[674fW_Ȳ2Mgf8_}7|k >æ&G$z%^?_fJeMWԕ-+O%Sڕ3:d';?K/KǍɎO71.{?o oL?^1ln9T)2Lm0M8N ^ ÚL&oKd0LR]`Fh4 md(JӀLFlo0l6DT ٬)F&l$i6іa`0'dɬ-0DbpD+8N+ bʬ-O 6tfSAyF]yfQS"je "rh&I`Еg2R9j1a&nJ#I*vg_ɺ}araO3M=ͤiʡ=  'fswКS<٬- ,t:A$Aw(I4;\Xd? h0ԝAP .f25AP< ǕAP^ANNuW-ðT*%rajyXg. `iAw({d4v X ԭ ԀeZl6[(,V^O,YNWa[A(ipsړ +7qr}rasz_i)zr;q B BmD!dzi:?~w<[o,}b֭h)gD _Mϳ+~s߽۷_SN%˗?i&е^+]~ЕW^h?q}2|/^ZqcY;x`ȑ5L =6zhCCC.u-_4 G/8>zW[bX__YYپ}` 5jd:niu!JB8Aٳճfzg2 w$II-((E?x?:ڗv#LOzZ<Qe=m ~+WZZ²6z)yv r ð Ţ> 8p8dY9!P,xpp8'9!IK'\NwoWfsEW%IBLK!r\-<}`0au^",\.qD dV2)5}DnSI`eYá٬ C]s&$no7J8aZՖD"a0PfE-&LLFuNfzl<DZc cj9fAԖNmXtԋ]IRdRov+Y,1<ͪ>2,䕗8SvB$I3  dٜfS?P2$v!d)jh8f/X,g6 8.ӕ0 _^SSR)ǬSzhTd$1imA(NA`Y]O+R,P,Ah+Ϥ}zLQWb0]TH3rB9żN W^<7*N! -OǭVkSSS,i z- ˲]{Va =z^: qÇ pVa:]X ހ$(JmyA] +7-pvf4L\4崟,+˒a7s‹/\\^޾;n6;rnW[y>Wl&D:#Rx<Ň}U ARGnպx?qīs9&_oHSp d2١C; Bss3IvۥA!J"hU`=aê Ñ\. B `;A0,:t;A0pa*mN?~h+OQV P 4LvEKÐbAht\nw^N}>:T+A(++X: B"鮃BeegA8vuAGSKJ|_~y X6 !Iê4X_____o1'Lس٥oǎ;v y>7fV2}B5ǏWDNh)^zKq%vmeWa^1c=zo }5|DSO-U_◿@| B,Z|oðL&^ғşx|jg̘βhܹs窕+O]@/愢(Nj徽{/uRÿ~jlh4Z 6o޼yfig/liS}?psd2L40LKp}0p.sB`N `9! \0' 0p.E'NX=Ç:tH#F? vV'Od.yÇPp9l~GkjF߿j.X07V*?a f ={=IGw/[\.jӦM0'97T`'B?k{w>|7xvBG^麺["Vsn;r8gٜʄ!kZ]}pW\6lxWсWlݲj8Ig\ xvżՌ G֮]KG鹵skjB/!d2qlvlٲݍJ*#vי .x{߾}1I~_?[;/}Íee|G,-- #X ͩK]s~'νax8`t,v7SU;!tϒz%~7/*(F !$Iseq!4rdM<8q`0myAey$F8dAbFQe HR^ʲq,A$:W!I y<(${cpֱlcذasB0@:E0 #}q IDAT>6W*<Ҙ1FSRq(wھknu]Xpl'+$!rYRNO.}[n>}Fmmm0ܰ~úu BxD"B,tq7#GKJ|T*NS|"`T]3MӒ$|>%$m[sl6;!n~,!|8ufs Mǽ^z;$v*JqKKKԖh4*-P(]y+)vBW^29$;&jhNQmyGy=^㸏>numN ʀ(U,B(h4/,ˡ~^ߝ\ajiiillѕ-V0 ѕ۩X(gT*%vԌXm>\9X///.Y^Q/ߏJ e5kjjj&_Ǖ/B(m-O s*FiŢ'H \Q#'H=a)-A[^4yza!b4J˲h&B(m4Դ$hZ-zd"WOXʦYSOXJ B_dmF t *cm1(M(JJK&FiɨD"I1ժd*T8N9#`q\$B#$3MڧңQZ%My|4Jc&*0h(JZK(m2ԉD"6Ms)Wʋ B4'\r_0FiI1u}2 o ,3gNie}!aϦIRևC: 6L(˜Ԗ0L~v͵}o۪19G F( Z2sg3*-#-堶<Ðh69E}N1 rkyJHX: B2.y дrAhgS&Q-(5Nbs䁌ضj*fΜ#r8qh邜Jj̙SNQR̙S>qO[_MZ+DG%IR Y$I֌QJL0o &}6'3w(np̘}6oN&YTRs8 .lB4MOr{lS|6Rɮ6Xn[|ٍ7ݨwznj9z{ٳ^x|'os~_{=/2B(_Pccc=>w?i-Bew_qXǗλvƌ,Ɲ;wZlNxfvow{<G"y~gGݎu;vbFE Bh?/iW]ԗuuuuuul64 puPJRiV2L&{* 0p.sB`N `9! \0' 0p. @Ǐ3Muuu#F? v]xDE}9'Z o_xusf0k??0ٳgoѓKT~4uԻ3 QodxhS_8ٜr:m#jj?>|7xvBG^麺[:sM=;j]j孷_>'j}6'4L_;n+.b6LK/U~qܸ,e2BH9>[ny`p ֽ&EaXYYi's:&Iw XFpln$I(0 s8$澮 6pœ(H09a_^^m)(7_|Ϣ/:tcYv͚O9k^juᒢ(y<drB1 DJJ|F !4rdͱc}d2ez=VRw6[kyDžB!׫^rh4ZZZb0NxEE$z"O2 E4DZBBXiio4=N8a۝N򒒍W5CDb\ mZbJ\OD?_3fdl#^_:Q6'~hW&>DmώV}cno&iP[^>O(/݄a r[>sMG9 ]JM^ SecjBoMpO)lm~r>7/ju-1:d}kyNLǷ>&]Moq^6\5Vya؍izj,"ސ~vwGNuӳldsrL-KmY9tGL4]_auV'_<#UZʱo&>ȭ啈CjxsJqTՏ V7h/p V[Xcxם/-]G=7wqTپUd$6ƍf8`0% l troroh05(l-a nƲb-ڮٝ~Ḍؖγg3眝YW:-//43 +Ḹׯ-;.Zrɽ@ٗ5_TwTPwʫ8H__M3:}W]ʦfz߬~T-~~ZSg?^yN`0 a uG>?LI>w5hI |Uw֭ b ~Rpe'Ou+ m7yݞ>^{_V6eYZVUdgOr;w:³g_rxJ+ϼڟߪ;ړ+.{6}z$iN9+gGz{K|F?;oQTU>_oH58"k9+~x߫;΋g͜z|-Iy?/39{f%2UHtfz# XBx<ios1 XʽvEϥMOH|̘$1~_QQ!EҋD"PD]Nh4VZMϗL&3.ۍ6>eRsfZS rdR"<z,kLO_H8 k XjrȞeioo`t8 A.nj1sCS9s;DGGiKO7`w斫Nyt CNsB0_u+rzG*u+(&2VFD\n۶_lP!DĜٳ>3W_}'p}_$IVUWoEh0̙;w_EIRKYIApDQE$I]&EQ} (eFDׄŌ˧ɤ IidKJ&YFdRd$I]U>.=9|$[d2ݵCez$%o6Lfx)X>O+Lfe %j@ R R2ad¢S6.p0i#&HaL =Ɍ/JiH'CaX)m4"KB 0"%)h5"sF2e!dAfj#FB* ,<Bi' Gh^Cem≠}#AӔʲp8|[֕74oB%uf*71,U^uU,"N;::kܮd+B}Usݿ?s!˅3wEQK.Ytݮgcm@{[qK<0͛y|&|_|š~޾yyƷn|ѼSSSSSiSs-[fj0~?1'Tö/yö;kB`M `5!L^& ք0y&/XkB`M `";XayΝ;<ifϞk.}x&,2;|(Op8~AXM5lF5^zҋ/^񦕇=5^kBɄ @$%I~M8{Μ /`CW\権o5k>jjz<5O?ֆbYnfoذaf" fB(Y֞X,wA9$a?n?۸a˖]z> 6\s5w˖#ni3{ywTԕ+o(weA&'4?efxE'ҼAFXeY1L&0(Zql6d$n6Dhلa4m2uiG HFL&M0LA((2M;MSuc˲o e2Ei#faȘ;bXDe~> {Hp#aI5#_]HkݫW[^q.miT!dawn=W_@-Pp+4˜ߝz,hE?ەLȇ~^m7[6}{%[::O'FHԝr56$ٹ`HN/NF0آ-n={z 펾-i#7־ B,e<r}+HDdI`=IO eY?RTFU F]zdB9{T3x(U9vpUbF3 dԞr ?ПF&``aq}!ӲahI4e0 !;=MkRitDi+BKO]e /C+,*V7$1Xaø袋XZ[[+2ao75:x),X;Vˇ>D-^ƛV~hڵ#.\xm\p8 ϭoZk_5k&H޵{ Dޑ_ &\UUq_ &2w"`Bq|ڴc{zzȯ@AA~QQю;uPIkz{;B8AM넑Hx玝MM7Ȳ|΢W\ _z[޵K@ڽgvbE. --==[np(fw Lf,:yH$G~5$IiaNgBfw.`B٬vք@QPo6ujX0 #>G554'd2͛1U,AK$n!{}|GK,}'yv_H$8.(r\L;K&Sv  KIx3&8.Hߜ#2ŒbC$ BANO{kųHFIO6%=m2Jzڻr8Kdދe#T&-($Š0’x\GHDGDQȸ(V)@eܭa:Ih$MI4n s,)k.""4dg#)tƮm˼c<i<32OCf)Is;Ɍ6=6+=F"rF["el=DY2[*&) ,aAkLLФGXFd8V,Vd4G! _U0TYYEϮS]!B թa**X94C]ƲTYY&%mzc;Q(uեهrLBjuGeŠ,[PPFm6{^^1||{ غN9Suo|M=Jwhyϝzx'{9 ڿ+YO)%m2$I2a[\M_|@]/4٫Hn,Q<)qz t^8%S~i)k6HNmis^)73*/s{o?_Bwʓ?ܫ*{zb||_]J,Xw7tG~brWqW}ޛLg~pdATWbOV#}uu0ujA8p;??bIs}}"1uN[h_.:?;:z I[vIT>eJ4sֻ-uPdYt8lv{*d2ݓX,L)2R xee%#:`0Hdꫭ~/3= d===$L&s~~ƈpv`zA7`!"HT}FF$I*)n$#B"lƈ5`X+t$aр1ІԹ={Fcn |#B] _مx<חNKKi:N++G|>$^v!xF!tuu|eS)ݦI/y Dޥ-rԩ uJxQQ:.ɤ`&̍}- A[مxDYYF82en;rv. X>OWD\^xvgU#.!$ɪ( 9s}D3ׄ \vǽZ"/;nժ(?>}Bl"JJͽ{[uWZGb1Z?x L`qM;ƺK5@ #(>!W^qW\qBW_sܷK.ya͛7?c7ׄW^~_#IjsGMMMbӦf/nٲElnnnnnZz#&PG~AȯoQ8<`M `5!L^& ք0y&/XkB`M `5!L^x'06lb,H<+*+B8 G &a 矿xϞo9ϯno憎yh?fWyEŲ~pׯ3ׄ'r}cPmmCw_uе^cۯ_q}0" <qM/ Dz<JMg'r(~G7=g΅^+_QsT͚5~e55S=ikkC,[WW7kL7lذux"Lf!Ba!\.֭[M`Ϯe;9;'"IǛMp8,IRLvҥK**+6yO?N5k-_|qӼy8ƷB7{7>8-[v]$imm*=Y@4B1q!tI,Ia0 S^8˲4MHE4I,KQ!I``I2(e$3#,A&a4M, *)0 3R2.$Kemz$I,aEQ.=e hzYufz.=I?IH~~`T$vb[Gn'(DkXڒq!DӴn:w%Dz$OHH.^#R@I%HRz`{җ@Ix$emz~9R|+@[Sw\'xv.%c۹OHZQg4'%"ʒK O899-:Mzm<mGqrO䰺oKzR4kKzR8l X#HHNĶǂ!)9R%{(K>> mI;]0r(?7(4 }!ujY)b:ڶS +4%̪uuJu }vwf[e; ,A#4;b1~;:q>2i9ڊe uO,/'l:SnY:%tuJQh aҭaܜN( F3`A374B錃˲j=\wN`B88B XJb!d^;o3g/e8я~Tp5k|>II?OWW,XpgVu"/^|M+W?zB .[.]zY8~75/Κ5O$vڝ38LsüL&#;0!S9މ Z _J!t:٣N$7uju4sab9Y$d29H$ j";"IWSN!B8?6q[o֜{.?Bh=M[[[( 4nݺm|&O í0e);0!8v$կ $aX~~>Iyyy fj5!PZv{뉻&4ͿoJJJC] &IЫ8P x|XVeѨ `&I!.6xo$#S=p,Ytnkc/b{{{4: eO&pjt 敿hj_ӧW̜Y '֖:f5rƙ͉ p}\y%wUIҥ~={j\O?u@3MX`EԩSN9RwΘQyq/N邏kfт.Z>M%KNkmٺ5uh_~o^%b=w'|S"3Θ{_Jk_}zݬYG]+;:e1NooV# ~|d2񁁨nWo nuFy>PwGdY!--NP2ʙ `zB02ouǣьbqNS@2t8eYL/HŒ>~aҌH H$")9Q^(Flڞ$Ɍ|>LFM^v!$|$2ƴqLH&H[0 X,ΪD &YpH~5h63 !;\`(5=}!p\,p(j`3YҭG$)NVkt=m:M&1\f 2jB@=M`!X՛VpX3 !Nu@!|#{0/Z4㏿9֏Ϛ)˲vܞ`K^L$'\{w ?=eo[K8m9'մϗJ<ӧ9tܣ^ysAHu9s:6>cmVnQ#?ɬ lXS\t=_n޹sg*=袓7mVW{N?$]?/7{vS+D** N;ط ?(3g?jc_~SuGXL$XyL5b{-7ոB BjDWƶ/{f/r#|q4$8NQeFԩ ޗO;xQzOΚz&m/<\{VG}ͩ[~C4}e˖J^Pݳ'u'mqIu}Cݗ_J=%Mw5O>V…ϟW#gX-;k׮Jv/Sgj27/}uL]Qokp}%RV^[PiӮl7\MygY?͙5k/F.4YBo+?{˖}}'Xqc꺱 }}n3O|-I:FqNMYxIL|H$}?H(3B D_ !Yd1XP_n $N%g$mtۊ ur\WL-`W^o ڻңA+I~rLF4؟,}}næNd_i6㸸e``Ӌx> }b3wtۇ0i|hLEI8!IR}! )&!%Is;v=|D]P 'P]""H$Iu_@0 /@9S$!mzniu>bU[Ož>w^C*d2XsbRX,v{0 ST8$I? O;ѧgeYMO-T UG* ՅD/z$e@yWWQDsJQ)0+BUBxr r[Vl8{啕 u6nLXW^Pkc&c:93fTkK/=MDu/niVhL$ w]nڔLt}C~HMyvxu.o}}0sfU}C?A]vK^| 5%}FwBܰrܰ>0nCoҳٹ3PflkK--N-oï]T[͞]UP]ՠb IDATMxjsƙǝI? /8,]uw`{:WޗoH--ho{olޜnoI mёZZ7M̙'jj.̍5к>HwufgnyY3mڴ4s3¶m5QG7ԵimM+oӝB8_DMӎ>L:ŋsL+ؗ_C.Qag\ߔ^c7ܜ*oͯݱ#US\PkwW[[.okjחZc+ Mg͸y5a$a x7r=Pwok,=|"SVNk$j4̝]? &p…78jj=kK&zKuuunӦ]\w֎qLżjՃ?6}zGG$0M5 'a]w5h,_~=Bn4j(J>쩧ܷK.ya͛7?3`" =Tgu8P˼TԔ{ӦE眫nnٲElnnnnnZ h" Gyu0 ,`M `5!L^& ք0y&/XkB`M `5!L^x'0S~8w? H|ѿvtt{t?q7o`hٲk{O>\s5E-_!t͘1g|GLꪫ'}ݡ$Ie B,˲a8aa(eYy=MF# Fw`YHS#F#@:b6$I7Z,dRjn7b|"!(lhO&S-C$‰4T2 C1 Ԉ@$Ո"tbaAt2V<*=ǬV@\D%B̆1IQz7BCHR#ΠFq@檪ʽ{<׈aD޵<\i Liw-KB2c@E w9$ H KjvrDD0 nPZO2:?9C!$#M.^]ZI0@)6=ǧM;?z#aHoiCRH$IRRN5`uvO$S=K ;ls"M&fN&rzG]\(DKn7q\BMsB8Ak v(Oz<YǪUp݇ŋx^}… oK^M~zfݻvg&ኊr+X0nOj0 R ?B8WWWyp82޹ ז6 LnL,'X,F~ '轣#:E(}om$ewR'#v٣ݴXpuѹ`KsKOO֭ۆz7 Ê f,{0j-(W4a'I2LR0 `fZ%I2 fj-**5!PX6$vPu NPee݌㏻/R^ \,>)#S=p,Ytnkc/Ν߄x<^XXy>9hA߿ Rm;00000PTTC;($Iڋ$I5v jU?X,&IBgX65x ˣiZmp8TPP{7euGP(H? ˲әi/)nhXYVѨDɤϗ^<NgEpaaz#P$bEEEꎂ`2LϏKzi\.ɤ'L/;ðq`tRDh$),,TΑH8t (ifi3f93=јjD"0IԦiھ({qHaYjM'˲֦'BfS' !q\(^v!áx\WAI3 GÑn=òZJz gR K:-//E񫯾ήBЦDhfzDbB(j:=`YvBSm!S>ðT:wu9NWA3Ḿ1 ](x9 A[مSeY޺ur7BC AIoV0$e¡00B+Ft.Ԁ;GMflr:q,y7 A?`q\< k4NO7sCF!tOPf8 !#%]q=.{+.?~u.+d2q&ŕ"9.nj$ugDx3xpu8..ڧdKTE⒤$9. _tхyxG#lMHY?9ɿ=/*ߑ̹ V?z+jY/[f]3mmm!ef͞i6[~ }~*'Gؚe۷] ߟL&_簟|Ivmܰeˮmhhz=|Ɇ 暻~}eB7޴rƌ=;fʕ7P;I4M+0k~J3 a!aAAQ4AMS$IeFh8^ D:a0A%=52+=atɐiZe]2c$ӻV&$C.m= A(I fO(T[0 gDʈd/BaI2#E%I!סԧ$dvO>6MS8Nh# 3-G h:ZQY dhDi2#="$ʌ( 8}zم0bO~EQB(ha]z\(=mMYf&8]c8Xc840TV8hPOѝrsFZҝӲ,]2C40.7W! nE٭/F+|(3{>Tt@Q 7)wtVi${%C _hwOjFԡePk37gnVXTnHb!dÎG?Q}Ýk֬%%^?]]]W.X;Vˇ>D-^ƛV~hڵ#.\xm\p8 ϭoZk_5k&H޵{ D)llkkx&2w"`Bq|ڴc{zzx&;v) >v``o[H!vPY:?89o[s~]~={5.:wQ0linݺuP{q| -7ɉeY3/$$IJő_ & ÜEEz<'˴!OQ#`Y@l<)Ngm{{]EEFQDQ[ZZLө[C(WH*z'H!f3I|B):`0}0=NŢDq=eJ:^oiia0 sھp݂ ^LI^ggdW6eYt8lv{dwwOAlNqq5eL/F,h4VY9\!ȅp! AWH$+//U"`Jݑq\>I,re(<ϷlM!h4^o<//֩ !8ށ DQU!.mQ XtVv!ȅ`4$"݀eR aNRsF}mmmavxfn>GevP,]!"GؚpX4z3&uSԩU(z<!IUUEQlmmmmm5 s=x)u;L&曗,;0w܋.^ڜzt4,U^uUNs3i_`l(Q?쳧zz/_t l޼> u %Iz'yY 8&usӦE眫nnٲElnnnnnZ#q5yu0{AkB`M `5!L^& ք0y&/XkB`M `";(--9klr-<ϏwFpD:^\ǟx8nW>ҲN HGؚxٲe/+uݿ_l,] HGؽ$IKowyԩٯ=g΅^+_QsT͚5~e55S=ikkC,[WW7kL7lذuS8!Lf!BagPhdR$Iʫ~駟^9}ڱK.O?N;}֬_|M?3jD|̛?OALM#I`'MMә f'AaKdpe Plj̶ VmzL 6+=FhC\9="in~$iZKC\5 0յk=Pj[$̃;umarvO3جjzr(uGX4}p `M!TM`0hV꡴٬AÑP$i0 _rvz,f\}덲aMb:tcYӦy!(7b!NuWMðH$"ajzgBҟӔPÌPctШ L&lxܹˀ;0,PtTpt,01gnN3H|b\fnN37M2Xfnf:8B XJb!d^ v(Oz<YǪUp݇ŋx^}… oK^M~zfݻv!ښh4>0UUmmm\P^^Ft[NL8OvlOOo \PP_TTcNLfG];007މH$ wTu+EQZH$yy߂:I$mذqOW]*<+u]OәLT*͟?"b25UphΝc\.,oJ2opBsECCC$wu͵G5kVr̖{BabQ%IdGGr<43g|>/y0g2BXX`l ɲ!F\\\\\\\\\\\.`*),CឞJ2?z>dɒ̟I؜/^֬$/Iؽ~W7\.ڹ}˖9_O'?UW_} CGyDW#?ݻ !ǝwy@ ( / 1|k !$ O_=ީkW/aݍv)_ye顗^|If/Ra\u7,]GdN>ᢋ.z衇ߎFUU4McY뺢 ihQw.?E^4xAQ]Y5[dY&X[$cHRr݌VɲrQ͸\MQ>-oJAh^Ӻ\~{TjzrNq˛rPN MӋwϞ٬003 B[[W_ui a1?`™I'-f?`5,?s;FNb1G]1v欳Zdɿ|Χj5By? ůO=[!PyP(,[lm[n%ڵk=,F7A=,| q.v2-vES؊|>D"jUi)ЊiCi2g h 8VZM^M' Ry3uW:Vs,z=O4}xZz::ۊe= W\JjZ ,+X[#s9k^^^74~fB_z0 Boo97ϽΝ[Zp%IN4oeX,V銢Nw-"6? xVvsɂ ͖t:v#ْL^o(ě( әp8zI B.+r>_loo3/mR4k-Ĺ\N6%j$-CCC <_WѢ(p& qHyj5Q#r\(ԕW(Yc[/Bb<O8 utBR l6j[[!j;vf-/bY6M\^(ěÀQ^46o'E1[{ZT.ʳU d5m<0MSTjPhZL@ 0+UUM9PTB}ybq*ApAAMP*J=-/Iue2B<0$i;wrZ3bT:gUKlB(=B!qj{&QUͼ[ULF BWdۭiR.3XmA~łyD0,hYBj^zWz&#hn)Odj#Tb� #JLF8<l.XNhy9UU!Dr.ms/d2k5XEQ2j�!T*ڂ7B$lv[0>Q̜:5f>_zZ.EZ^.uRӬ30!Z&kNs9{r|ZBr,qՋeYs/E[BP'R^=f)EZm<#n7B!/MI 50NN lo3/9iZL&+#Afy M!4o0`z] 6.2`U2w 4id2`j rJH{NegN -yG ؃ 9`|>YɆsaV 7Afs4 /e2i/DM6Vaj6  晛$lSfgniLr\*sJ* \|+VK7n ٫iZooooo=yC_2@;s=y800}{(SNs=۷g^8U7}SO۞=d2/_jZ%XqWd2H ~SpnP(B::Nazy]]W\q7_ޚwplh9 |MBH[[xa뮿tw&<^r%??w,KkR4o 7\w՚M8F vͭjo5r}/̜9s !˖/nzIBe˖3}+Vx* !D6mꚷh"#mݺtR[{ZgV^ݻz`߾>GNN/EQ7FX;oB%I?w~p(v{{w[%}a,opႅ󍟯ڥK>O2̉']{ 0oǫhG&4M9(B5zMlZfkql-TuշЎb5\$sl1B\.ī(bb-4^17.h(2gw4id{5V_L)͆[\&=moyOk=Yvniڶ+38K&Өנ\{x1Q'_.WÝk =bR4{߹c-.عZ4gy3mo.kbHTtNr<= 4*Oi}IOu^L˞a;ssΝgn r:37gBO#je>5 Šm.s=g"++v~~5k9.y{߻ƛP替v٥'I_=x.;wKFˍ7[pk@O۶uۏ~Բed/oe bѢr2888 ǟ@ `ݻwbuk5޽g @f] xGGǟdfNZT*]!v1-qlX%.\.zTUuݺZ_i*!vnBkgUE1'܏^ye``p]&X X-*d>7b1Ih Pa.ZMӁ@ ǫH$0'n_ DžJ\.We-1}Oj5kB^xW{DQdYbKTDB<|(DQB!8M?0S,|[[Gs0D"aۍ@Q@ ysB0|eqb9R='}ߝUH8io\\̙MVmmqchQvi~[( œ9sC|6cwka$Ia%~o81>88 Ѣ(J*F>hVL[[ˎ̜r65)/ Ů!+IYKӵZ}l>L&E- p8lnD"dYbُ(Lؗ͜J\.7k,N|>W,Νc(dY744D>v%H, CP}y@ 0Z44^g(vc|>?{l92tvv{G_|E]Y/ &8F#㕧j2D"~h$)N1Wb!/ԗ7W MS:::͖T*rRźj>#- wmRmZx,yO4UQAU'灥fiiG&AдAu{ܱWL0b?ʩ((ǣZmi Q:s3z!.N,;BZb]]>}?O=ԗ^|rW\{Q7sgqƓOl2͛?~rt^>H$0̪Uy>ć sE_d|/Yo߾UK\'rg.rS~'0{>EQr6}/7? ֭˲텍o-m/|n|he^5\R$ewرn-1'$<쯟O IDAT{<ϻnAOo}V2#?~x$ c]S !Zi!y+~2'4w'!\.OɲJvu_P\lj>!L1', ׯ.ֽG(=̈33333333{ s<ド~l㧞z*oQ|z?pi|gl67UZ: ?/tYg-+V~[tҢ^y㩎 _E'~?{j 8uEݟf 0]/My?K~p!WjY^smRin57pLi ì[_>2-{_4Be˖3}+Vx* !D6mꚷh"ے#mݺtR[{ZgV^ݻz`߾>G}Nx%h?Ko~sVg8rݽ-OBN>0S7[NXp~~ҥK{'L֮aɲZor?M,r& K` -j5ksf~eYkK g@vS. 5vlY'x^gyn=b(r,-0L ২{zkZg}mTؒm:^/Ap4k3YwnÞfVۖ8o}ӜA0:d`];zlAhS| cΞ6 X3z=^/g/QsÈ+!v8aAJ2!׺'sqIRV9`z zZsrA`# mp׺X8 B}yL4A€e9!9`o89GgOo=zj5x0Z}y>[ybȀei-hj X^3F:Lי̍37&3`3gكpPBQX͒%o}{}w~BY{ivŗ|{oM7ćB7.߹_2Znq݂]BO~ض~G-{$y/Sxu˕)_8 ޽[_ 3@W\dz{.ZMӋw``0Nw-y8X'T* &8n9BbZ:!q7|K?k{vz5MSvcNuqb7{Gs200s^Iy],- J֏ `&8.ʲ$JW nFӴ/X,J ZB(ć cNx ]X.o( |>OȲuח^/!R*!(OQq(\y}dժLR2Z*1+R,7r +JӢX^M$={6~n۷h4j<4mh$ yp0f~aRRCgwB5;l>[p!IZ#5l9pqmmmf޽{Cp41z@,5$U>=ryh(=g,s|>/y̛3X,,X0dY;w.!$W uvmxH$'̓(ܹa>_ L&s6c)M~{ dKj x| (? dsgO4`قZ__݈ @a֬N7l6k B+V\44mr:`5M XsZVI Xw_rX t !KyGurۀ70ө5<ϻ޽{܎Ιap0A䰜dlA8BN(Un|2gl!}DQܵkEQ{gW8eϞ݅BP(|ɯizx9 7fn{{4|y-f焕Jg|g4W\&=Opj{======<{^Al8✰r\.>%r*Bn15x(sZoQsb~BZ1sEg=Uqœ`œ`œ`œ`œ`œ`œ`œ`rOwcO|;kGV3㧞z*oQ|z?pi|gl67ZeNxk>ۢ(^r{ƛ$I"XqWd2H ~SpnP(B::Nazy]]W\q7_ޚwplh9ᩧO|;| !-c63 s׽݄_K.r箖ei5V*Zi~?Lj>T>ēƄ;4Z`>!dٲEMO>iu۶s=1<χ^{kg|=w/^8_cUb;^.q^Ci,K4!$zMUe)2^O4qlqFZ,ts0v^kaX]¹\.!EQq,Me9<e㲵8Z8,(a^[y+fʄU y~…9!Xmm~dY.ʫVrY^,3WT*ED~"7VlosB!s_r%'͕JYŒHl1$[?f 2^/sW_^м^/IRT'bRW^\$z>W,4M ÄWvܥSq}MrN_up$rdKqpE1L $ g6WeJ%(j"ǣHN : B>[gE7K|>A030\.s]֜4-r29$kӪ[sjS-9Z\tɀe "ˍ@ev$gقLxAK$RXU.Wl9g2 `ꃐ:`|>YI#Xd,c 6B8:Veji^o iĂun ٫iZooooo=y#&ZLK|嬳^_.Y}"!==jMn=眳8'd͛7c8nҥy㋈Ng}v$afժ<C {/2>b,ٷozө%/[XjBȽ{ w)*=/d旛B}eYEQ^ƍ6X!y?SUu۶w}|k>Kw\u .X)I˲;vXG'xX,~뛷@ dlg?}< ꄿ]~) W4`c-1'r\.>%˲}ܦn15x(sZ0-fĜX,_~r;z(DQ|_Ow-gF\'0'0'0'0'0'0'0'0']@ p /$Ix<~ꩧ|p```EQ̧8ٙzofsGjcU i^yWfϾnXqWd2H ~SpnP(B::Nazy]]W\q7_ޚp,i{Go[gOmlkg{?]k[Z9wɥ^eYZsU~붫7߼zǪV7_gk_}htӓO –-[4_si~zk¡}u7͢^Oo{w[c;^|%-X8ڵ_ |i K.}џd2O袋zzVs\ZVESEYX, - Ѵ,!4MOТiEQk3ɖq(nVqV^ X`;SJw  IDATvecӺ2 Ψ 򎡞F=p d[ø˞v$kkwttܹUqӎN:iQPQA8&ʛƞvx9BbZ G"|ڒ!H!/EQh$zPXlٶ۶nJٵkמ{$YnJcyaM8^|@ .I{4Pa.ZMӁ@ {/IC6uzrxxv%Jy^獇 Ao2< C7rz!Il6F=RBͼ*m9v"˲fBVbc`nw8hQ%+ZrX,0fyBf^F/J\Q.S<N=&+/L~FNZ`vu49uZ^X,dy0P a79AN 2{N=nN (rUU M{˲fy hN75 XsJtV۹s ay B(zG3Fyfu#1`كP*KAR,k&-  Ȁe;5XG2MS=-Ͳ }j>;bd0V̍D"gn X͙(X!˪j]V!HZʄNBH"H &!H\D2tf_!Ha W]_m/p՚LE1bո ˒(Vuf"UպIպ?XJժ(VUuEkXUձ VŪR)XS{y,Z$jjUVEkyZM 6SUQj!kym%I ,۶hXgg;4]Dɲj BeEQm-έW/(ZVcW:vGߝ| pi9[d%"tҢ%KR==jMn=眳8'd͛7c8nҥy;}ّHaU>|1  .ȸ/Yo߾UK|-_J.2BȽ{ w)*='%~P(nݗXUm/lxkx3UUm{{w׿C.~UW$,cǎ1@Kh9_s>2޳b[߼L&c/?H$_(T'2=wNQT>'\jqyOOOOO^WJ@9ZbN8r\.7|JT*5Xo+bZ(ƻx'i1#ba=݅cC!szh93:!49!̅9!̅9!̅9!̅9!̅9!̅9!<:gL$m6 "WuWTTP,(Z r*x~A9D(rRZڦwӦm@Nڴ@Ky=#dgN_7; /+%ϝ>wa1dKu#b)}YrL&dϞ=B0<@k|fMN p3 ԯ_m[544BN)99Y2VYݻKF=wv$w>gLڽ{M~TYY0uؾXdgx(Z4T&q湬FnqύajqϭPa/NVkn?nwWsٔqܑ#G/[QUU5py^~rS%%%o?O?T<7}(<SB>xq ^zZӧN_CI 8pkQTqqsssM&sG>!66F&@'4ڵ}N~Dߗ\WWW\@e4!4yBu3gNϟj]Ws_;/p$ltnIɴ(''o7CP桢cDzNbLJ U-2x'\lZV[G>!44e9( &vt,5M\\g AӅT*)J 5CǼCyyys1c)Zl6Bd+\)rJ[cO>9GF~/noYY' !:}QXX( ї|]|EbYvݺu듒 i5xt^}yyy9911a0TWW׈UTT444tÒ.),,86<<]RBBBk.]kZCJBIC422G*66}6`sr,>#].u2BL.pB```ppp\  %XS*k(--p_][[[YYթSjC||Y,qxP/rN. kvᙋKHqNb׋WVVqqW^YYj!T*e'B\W^AEBFj.gx(44DV %fI/W(.ʺ(CP]mܹ>ʺΝ;Qiinv3 qe(WuBV\Zz6H Q.g2KJJ""" -&B}}Ce[NV4&DƊh]G&I%%zDP?#b9t$8O=l6ƊWd.^,FI*"}܃p8gorRsaY6)9a˕?vǷiiiMN}ª!C?7*jĈ>޽-[{߽ݻwĸmrRsV8 8NV-_O&CBBRupG׎-\'!e׮mxOՖ̙fþu77)t'vk_yyONƢœby~[7h: !2>uB㏍P(l6<"M'F ZZZښ/+\bZ[[E*_ڏ_ իWсa2m9~q>!BO'_/  }B>!BO'_Rvqw\<7`f6[r9M_o,')rp+7Z2󼸄yL&.lj (g+%E+<ðf (ð 8eYB8<"2qx.7%+QPYV -q0lSJ!8'kq)rxIx / 0 PHVedD2LTUU,+I“dU)\w0EQrd1'JcYmͲrIE<4BE[*%Km1dI5 F) q0-&!Ե%{U2 S[klM"HV%˲ Dpy'\ke"ã(ҚUp:@sG }B>!BO'_/  }B>!b;:ֻw/gffJʻwۺRu34sa_ll'3+GFFvU2l6[mK ;ԩSW|'շo_eerwa1dKugZ\\\BB-U[HHHϞ=O.--#K>QVVކCcYgΜؘ_ZRRϻvzW3EQ}IHLY~$?PsFttL߾}NoAϝi9ԧO8z칳gϊ%&&ݓas9Gkn ^Tp+-a#՚W(ʌiÇ+.Ozjx2ɓ4EvKݲ{s Zf%3OSR6By)M˘^WW׮3;9kVys]ޥKL''';ιs_(*,2={xQQaaz$<Y`h JKK!dJKJ.|]O|ԩk BB~&B\^X?ٌq۶n3̈́-[KL_nR?2erYYُt(۶ut:N=_pͲOdϜ13?{1iSӧO3a*JBH=.ydܼy?!E].צ?R}[ JJ6|h/!_R9W!=> +**>?B(R(*BRRRv;qGYlEUUUG\15X։لF{|xC""M<ٹs3fL jR%yyy\G?29kFߠyc6QFqG?B;-m!71mj~~;$,B/9lB9\Z_E=+.<3kOdc<]ȍhkؙ̯o#rrrM~|zW^yEVKq8;ѣNJSF9`BMK7 /:~DVV֘я^|)11q;`~*i%p\oX(8aophfF\@m)**\|Ŕ)SFibپ}ÿ478q?py/;r#ƷW}}*1˺T*k| 6mzᅹuuҧG <8--mS2.(E+ebS(ڵ+&&z&OI6lܸq„uMR /?w]ջw~;LrrUn/Zh٫׼r~jĉu7zc{ѣ>SҵZ c_}Ғ_~Լdx4їo|@iM1pDѸ`BB1 4hEԗ{C;p\￿qӦT*`P(fl+)Bta:d0DFDFBN}vFdXM&ӤIOUVTx>֓z@BBCuK8ӻk_9WGDDnj(.xPE@W'44t!NnGGGu~Ʋ_~Ԥ+/6iZ.&3MS31=H 1NZZĆ1Æ +,,yb_~_߅?^o6[O4u8dz9*"/ºe*lG~r|^ֱ,Bȑ#'L ?99nN l6[uu2d0EQdsKLraJJ !D_'?&"bccÏa'W(j D!C<ӧϜ8ΒVYp޽߯|kCH:ǘa޽n/~Rvq7?_ ŅΝ=8EEΝt̩oXv$KN3*:ZNTԮz}ɟȑ\9kFddʷޖ<|GnaaaÇ_paa:t:'OoV񆆆GǬ]NxPΝ2eWTT eV=z²]fL\~2 %%9,LҥG'5MUU*bc#o<>/>b=&=i .*U1cF1bΟ?ѳM 2l6Wl6l6lߟw[iӧ۷ ?tfy}=wd2uz3jkk֯t:ƌò{n7U>Vt.z9<9kۖh# l۽rgAQԠA&Lou|CӦM:]hXNcYba=ۺfY6}rz.]/_!\\"!^TpͬV3!*,<]t!j cǍ7np=+ { < :X֊+ܯv玭[ /8/<B+6}={ȩ6Tx Ņ kV9~'|׷;!LdYYVywN1}ۄtbƏ?x)'8rHm6۾ZN:_ YIaii OUĒK}Yofo,ŕ<2j(Ն͛?ݶv)K.ѣp{vi:cZ_r7˲Vu޽kVugՈ>}Z=!N董V*--:tȔgO#!BO؎ڗbv8d/' _pQ '_/ '&BȠAZ32q(#_!Dt\<F!f8yBp;"$.u(H(Bbm3f !348.n2T!f(."[EEїNJEAQE'_x7IENDB`prometheus-smokeping-prober-0.5.0/example-rules.yml000066400000000000000000000012311415762215600225040ustar00rootroot00000000000000--- groups: - name: Smokeping interval: 30s rules: - record: instance:smokeping_probe_success:ratio1m expr: increase(smokeping_response_duration_seconds_count[1m]) / increase(smokeping_requests_total[1m]) - record: instance:smokeping_response_duration_seconds:q50 expr: histogram_quantile(0.50, rate(smokeping_response_duration_seconds_bucket[1m])) - record: instance:smokeping_response_duration_seconds:q90 expr: histogram_quantile(0.90, rate(smokeping_response_duration_seconds_bucket[1m])) - record: instance:smokeping_response_duration_seconds:q99 expr: histogram_quantile(0.99, rate(smokeping_response_duration_seconds_bucket[1m])) prometheus-smokeping-prober-0.5.0/go.mod000066400000000000000000000005431415762215600203110ustar00rootroot00000000000000module github.com/superq/smokeping_prober go 1.14 require ( github.com/go-kit/log v0.2.0 github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 github.com/prometheus/client_golang v1.11.0 github.com/prometheus/common v0.32.1 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/yaml.v2 v2.4.0 ) prometheus-smokeping-prober-0.5.0/go.sum000066400000000000000000001353261415762215600203460ustar00rootroot00000000000000cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= prometheus-smokeping-prober-0.5.0/main.go000066400000000000000000000144421415762215600204610ustar00rootroot00000000000000// Copyright 2018 Ben Kochie // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "errors" "fmt" "math" "net/http" _ "net/http/pprof" "os" "strconv" "strings" "time" "github.com/go-ping/ping" "github.com/superq/smokeping_prober/config" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/promlog" "github.com/prometheus/common/promlog/flag" "github.com/prometheus/common/version" "golang.org/x/sync/errgroup" "gopkg.in/alecthomas/kingpin.v2" ) var ( // Generated with: prometheus.ExponentialBuckets(0.00005, 2, 20) defaultBuckets = "5e-05,0.0001,0.0002,0.0004,0.0008,0.0016,0.0032,0.0064,0.0128,0.0256,0.0512,0.1024,0.2048,0.4096,0.8192,1.6384,3.2768,6.5536,13.1072,26.2144" logger log.Logger sc = &config.SafeConfig{ C: &config.Config{}, } ) type hostList []string func (h *hostList) Set(value string) error { if value == "" { return fmt.Errorf("'%s' is not valid hostname", value) } else { *h = append(*h, value) return nil } } func (h *hostList) String() string { return "" } func (h *hostList) IsCumulative() bool { return true } func HostList(s kingpin.Settings) (target *[]string) { target = new([]string) s.SetValue((*hostList)(target)) return } func init() { prometheus.MustRegister(version.NewCollector("smokeping_prober")) } func parseBuckets(buckets string) ([]float64, error) { bucketstrings := strings.Split(buckets, ",") bucketlist := make([]float64, len(bucketstrings)) for i := range bucketstrings { value, err := strconv.ParseFloat(bucketstrings[i], 64) if err != nil { return nil, err } bucketlist[i] = value } return bucketlist, nil } func main() { var ( configFile = kingpin.Flag("config.file", "Optional smokeping_prober configuration yaml file.").String() listenAddress = kingpin.Flag("web.listen-address", "Address on which to expose metrics and web interface.").Default(":9374").String() metricsPath = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").String() buckets = kingpin.Flag("buckets", "A comma delimited list of buckets to use").Default(defaultBuckets).String() interval = kingpin.Flag("ping.interval", "Ping interval duration").Short('i').Default("1s").Duration() privileged = kingpin.Flag("privileged", "Run in privileged ICMP mode").Default("true").Bool() hosts = HostList(kingpin.Arg("hosts", "List of hosts to ping")) ) promlogConfig := &promlog.Config{} flag.AddFlags(kingpin.CommandLine, promlogConfig) kingpin.Version(version.Print("smokeping_prober")) kingpin.HelpFlag.Short('h') kingpin.Parse() logger = promlog.New(promlogConfig) level.Info(logger).Log("msg", "Starting smokeping_prober", "version", version.Info()) level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext()) if err := sc.ReloadConfig(*configFile); err != nil { if errors.Is(err, os.ErrNotExist) { level.Info(logger).Log("msg", "ignoring missing config file", "filename", *configFile) } else { level.Error(logger).Log("msg", "error loading config", "filename", err.Error()) return } } bucketlist, err := parseBuckets(*buckets) if err != nil { level.Error(logger).Log("msg", "Failed to parse buckets", "err", err) return } pingResponseSeconds := newPingResponseHistogram(bucketlist) prometheus.MustRegister(pingResponseSeconds) pingers := make([]*ping.Pinger, len(*hosts)) var pinger *ping.Pinger var host string for i, host := range *hosts { pinger = ping.New(host) err := pinger.Resolve() if err != nil { level.Error(logger).Log("msg", "Failed to resolve pinger", "err", err) return } level.Info(logger).Log("msg", "Pinger resolved", "host", host, "ip_addr", pinger.IPAddr()) pinger.Interval = *interval pinger.Timeout = time.Duration(math.MaxInt64) pinger.RecordRtts = false pinger.SetPrivileged(*privileged) pingers[i] = pinger } maxInterval := *interval sc.Lock() for _, targetGroup := range sc.C.Targets { if targetGroup.Interval > maxInterval { maxInterval = targetGroup.Interval } for _, host = range targetGroup.Hosts { pinger = ping.New(host) pinger.Interval = targetGroup.Interval pinger.SetNetwork(targetGroup.Network) if targetGroup.Protocol == "icmp" { pinger.SetPrivileged(true) } err := pinger.Resolve() if err != nil { level.Error(logger).Log("msg", "failed to resolve pinger", "error", err.Error()) return } pingers = append(pingers, pinger) } } sc.Unlock() if len(pingers) == 0 { level.Error(logger).Log("msg", "no targets specified on command line or in config file") return } splay := time.Duration(interval.Nanoseconds() / int64(len(pingers))) level.Info(logger).Log("msg", fmt.Sprintf("Waiting %s between starting pingers", splay)) g := new(errgroup.Group) for _, pinger := range pingers { level.Info(logger).Log("msg", "Starting prober", "address", pinger.Addr(), "interval", pinger.Interval) g.Go(pinger.Run) time.Sleep(splay) } prometheus.MustRegister(NewSmokepingCollector(&pingers, *pingResponseSeconds)) http.Handle(*metricsPath, promhttp.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` Smokeping Exporter

Smokeping Exporter

Metrics

`)) }) level.Info(logger).Log("msg", "Listening on", "address", *listenAddress) if err := http.ListenAndServe(*listenAddress, nil); err != nil { level.Error(logger).Log("err", err) os.Exit(1) } for _, pinger := range pingers { pinger.Stop() } if err = g.Wait(); err != nil { level.Error(logger).Log("msg", "pingers failed", "error", err) os.Exit(1) } } prometheus-smokeping-prober-0.5.0/scripts/000077500000000000000000000000001415762215600206705ustar00rootroot00000000000000prometheus-smokeping-prober-0.5.0/scripts/errcheck_excludes.txt000066400000000000000000000002531415762215600251130ustar00rootroot00000000000000// Used in HTTP handlers, any error is handled by the server itself. (net/http.ResponseWriter).Write // Never check for logger errors. (github.com/go-kit/log.Logger).Log prometheus-smokeping-prober-0.5.0/smokeping_prober.yml000066400000000000000000000000671415762215600232740ustar00rootroot00000000000000--- targets: - hosts: - localhost interval: '0.5s'