wangkang 3 months ago
parent
commit
0bb403cf52
100 changed files with 13798 additions and 279 deletions
  1. 14 0
      Makefile
  2. 111 0
      config/config.go
  3. 7 2
      go.mod
  4. 90 94
      go.sum
  5. 35 3
      handler/article.go
  6. 61 170
      logger/log.go
  7. 0 10
      logger/logger.go
  8. 1 0
      router/router.go
  9. 43 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/counter.go
  10. 67 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/gauge.go
  11. 37 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/histogram.go
  12. 162 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/interface.go
  13. 6 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/observer.go
  14. 192 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/prometheus.go
  15. 37 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/summary.go
  16. 16 0
      vendor/git.finogeeks.club/monitor/go-client/monitor/timer.go
  17. 20 0
      vendor/github.com/beorn7/perks/LICENSE
  18. 2388 0
      vendor/github.com/beorn7/perks/quantile/exampledata.txt
  19. 316 0
      vendor/github.com/beorn7/perks/quantile/stream.go
  20. 8 0
      vendor/github.com/cespare/xxhash/v2/.travis.yml
  21. 22 0
      vendor/github.com/cespare/xxhash/v2/LICENSE.txt
  22. 55 0
      vendor/github.com/cespare/xxhash/v2/README.md
  23. 3 0
      vendor/github.com/cespare/xxhash/v2/go.mod
  24. 0 0
      vendor/github.com/cespare/xxhash/v2/go.sum
  25. 236 0
      vendor/github.com/cespare/xxhash/v2/xxhash.go
  26. 13 0
      vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go
  27. 215 0
      vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s
  28. 76 0
      vendor/github.com/cespare/xxhash/v2/xxhash_other.go
  29. 15 0
      vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
  30. 46 0
      vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
  31. 26 0
      vendor/github.com/gin-contrib/sse/.travis.yml
  32. 21 0
      vendor/github.com/gin-contrib/sse/LICENSE
  33. 58 0
      vendor/github.com/gin-contrib/sse/README.md
  34. 5 0
      vendor/github.com/gin-contrib/sse/go.mod
  35. 7 0
      vendor/github.com/gin-contrib/sse/go.sum
  36. 116 0
      vendor/github.com/gin-contrib/sse/sse-decoder.go
  37. 110 0
      vendor/github.com/gin-contrib/sse/sse-encoder.go
  38. 24 0
      vendor/github.com/gin-contrib/sse/writer.go
  39. 7 0
      vendor/github.com/gin-gonic/gin/.gitignore
  40. 42 0
      vendor/github.com/gin-gonic/gin/.travis.yml
  41. 231 0
      vendor/github.com/gin-gonic/gin/AUTHORS.md
  42. 604 0
      vendor/github.com/gin-gonic/gin/BENCHMARKS.md
  43. 303 0
      vendor/github.com/gin-gonic/gin/CHANGELOG.md
  44. 46 0
      vendor/github.com/gin-gonic/gin/CODE_OF_CONDUCT.md
  45. 13 0
      vendor/github.com/gin-gonic/gin/CONTRIBUTING.md
  46. 21 0
      vendor/github.com/gin-gonic/gin/LICENSE
  47. 80 0
      vendor/github.com/gin-gonic/gin/Makefile
  48. 2136 0
      vendor/github.com/gin-gonic/gin/README.md
  49. 87 0
      vendor/github.com/gin-gonic/gin/auth.go
  50. 114 0
      vendor/github.com/gin-gonic/gin/binding/binding.go
  51. 51 0
      vendor/github.com/gin-gonic/gin/binding/default_validator.go
  52. 63 0
      vendor/github.com/gin-gonic/gin/binding/form.go
  53. 350 0
      vendor/github.com/gin-gonic/gin/binding/form_mapping.go
  54. 34 0
      vendor/github.com/gin-gonic/gin/binding/header.go
  55. 56 0
      vendor/github.com/gin-gonic/gin/binding/json.go
  56. 35 0
      vendor/github.com/gin-gonic/gin/binding/msgpack.go
  57. 66 0
      vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go
  58. 36 0
      vendor/github.com/gin-gonic/gin/binding/protobuf.go
  59. 21 0
      vendor/github.com/gin-gonic/gin/binding/query.go
  60. 18 0
      vendor/github.com/gin-gonic/gin/binding/uri.go
  61. 33 0
      vendor/github.com/gin-gonic/gin/binding/xml.go
  62. 35 0
      vendor/github.com/gin-gonic/gin/binding/yaml.go
  63. 5 0
      vendor/github.com/gin-gonic/gin/codecov.yml
  64. 1071 0
      vendor/github.com/gin-gonic/gin/context.go
  65. 11 0
      vendor/github.com/gin-gonic/gin/context_appengine.go
  66. 103 0
      vendor/github.com/gin-gonic/gin/debug.go
  67. 21 0
      vendor/github.com/gin-gonic/gin/deprecated.go
  68. 6 0
      vendor/github.com/gin-gonic/gin/doc.go
  69. 169 0
      vendor/github.com/gin-gonic/gin/errors.go
  70. 45 0
      vendor/github.com/gin-gonic/gin/fs.go
  71. 490 0
      vendor/github.com/gin-gonic/gin/gin.go
  72. 18 0
      vendor/github.com/gin-gonic/gin/go.mod
  73. 42 0
      vendor/github.com/gin-gonic/gin/go.sum
  74. 22 0
      vendor/github.com/gin-gonic/gin/internal/json/json.go
  75. 23 0
      vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go
  76. 271 0
      vendor/github.com/gin-gonic/gin/logger.go
  77. 89 0
      vendor/github.com/gin-gonic/gin/mode.go
  78. 123 0
      vendor/github.com/gin-gonic/gin/path.go
  79. 151 0
      vendor/github.com/gin-gonic/gin/recovery.go
  80. 25 0
      vendor/github.com/gin-gonic/gin/render/data.go
  81. 92 0
      vendor/github.com/gin-gonic/gin/render/html.go
  82. 191 0
      vendor/github.com/gin-gonic/gin/render/json.go
  83. 35 0
      vendor/github.com/gin-gonic/gin/render/msgpack.go
  84. 36 0
      vendor/github.com/gin-gonic/gin/render/protobuf.go
  85. 45 0
      vendor/github.com/gin-gonic/gin/render/reader.go
  86. 29 0
      vendor/github.com/gin-gonic/gin/render/redirect.go
  87. 41 0
      vendor/github.com/gin-gonic/gin/render/render.go
  88. 40 0
      vendor/github.com/gin-gonic/gin/render/text.go
  89. 28 0
      vendor/github.com/gin-gonic/gin/render/xml.go
  90. 36 0
      vendor/github.com/gin-gonic/gin/render/yaml.go
  91. 126 0
      vendor/github.com/gin-gonic/gin/response_writer.go
  92. 230 0
      vendor/github.com/gin-gonic/gin/routergroup.go
  93. 16 0
      vendor/github.com/gin-gonic/gin/test_helpers.go
  94. 651 0
      vendor/github.com/gin-gonic/gin/tree.go
  95. 151 0
      vendor/github.com/gin-gonic/gin/utils.go
  96. 8 0
      vendor/github.com/gin-gonic/gin/version.go
  97. 24 0
      vendor/github.com/go-playground/locales/.gitignore
  98. 21 0
      vendor/github.com/go-playground/locales/LICENSE
  99. 172 0
      vendor/github.com/go-playground/locales/README.md
  100. 0 0
      vendor/github.com/go-playground/locales/currency/currency.go

+ 14 - 0
Makefile

@@ -0,0 +1,14 @@
+MOD_NAME=web_test_cgi
+BINARY_NAME=web_test_cgi
+
+install:
+	@go mod init $(MOD_NAME)
+	@go build -o $(BINARY_NAME) -v main.go
+	@go mod vendor
+
+.PHONY:clean
+
+clean:
+	- rm $(BINARY_NAME)
+	- rm go.mod
+	- rm go.sum

+ 111 - 0
config/config.go

@@ -0,0 +1,111 @@
+package config
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+)
+
+var Cfg *Config
+
+func init() {
+	Cfg = getConfig()
+}
+
+type Config struct {
+	ServerName string //服务名
+	HttpPort   string //服务端口
+	Mode       string //路由模式 test、realese、debug
+	LogMode    string //日志级别 默认debug
+
+	MongoURL string //mongo url
+	DBName   string //数据库名
+
+	RedisUrl          string
+	RedisPassword     string
+	BasicSeqKey       string
+	BasicLatestVerKey string
+
+	KafkaAddr   string
+	NotifyTopic string
+
+	NetDiskHost           string //网盘host
+	NetDiskUploadURL      string //上传文件api
+	EntryURL              string
+	NetDiskDownloadURLPRE string //网盘下载前缀
+	ZipKinURL             string
+
+	BasicNeedCheckDir []string //基础库校验文件名
+}
+
+func getConfig() *Config {
+	cfg := &Config{}
+	cfg.ServerName = getEnv("SERVER_NAME", "mop-basic-pack-svr") //服务名
+	cfg.HttpPort = getEnv("HTTP_PORT", "8080")                   //服务端口
+	cfg.Mode = getEnv("ROUTE_MODE", "test")                      //路由模式 test、realese、debug
+	cfg.LogMode = getEnv("LOG_MODE", "debug")                    //日志级别 默认debug
+
+	cfg.MongoURL = getEnv("MONGO_URL", "mongodb://127.0.0.1:27017") //mongo url
+	cfg.DBName = getEnv("DB_NAME", "mop-basic-pack")                //数据库名
+
+	cfg.RedisUrl = getEnv("REDIS_URL", "redis://127.0.0.1:6379/14")
+	cfg.RedisPassword = getEnv("REDIS_PASSWORD", "")
+	cfg.BasicSeqKey = getEnv("BASIC_SEQ_KEY", "mop_basic_pack_sequence_key")
+	cfg.BasicLatestVerKey = getEnv("BASIC_LATEST_VER_KEY", "mop_latest_basic_pack_key")
+
+	cfg.KafkaAddr = getEnv("KAFKA_ADDR", "127.0.0.1:2181")
+	cfg.NotifyTopic = getEnv("NOTIFY_TOPIC", "mop_notify_data_topic")
+
+	cfg.NetDiskHost = getEnv("NETDISK_HOST", "http://netdisk:9999")                                         //网盘host
+	cfg.NetDiskUploadURL = getEnv("NETDISK_UPLOAD_URL", "/api/v1/netdisk/upload/self?type=file&content={}") //上传文件api
+	cfg.EntryURL = getEnv("ENTRY_URL", "")
+	cfg.NetDiskDownloadURLPRE = getEnv("NETDISK_DOWNLOAD_URL_PRE", "/api/v1/netdisk/download/") //网盘下载前缀
+	cfg.ZipKinURL = getEnv("ZIPKIN_URL", "")
+
+	cfg.BasicNeedCheckDir = getEnvList("BASIC_NEED_CHECK_DIR", []string{"css/", "script/"})
+	return cfg
+}
+
+func getEnv(key, fallback string) string {
+	if value, ok := os.LookupEnv(key); ok {
+		return value
+	}
+	return fallback
+}
+
+func getEnvInt(key string, fallback int) int {
+	value := getEnv(key, "")
+	if value == "" {
+		return fallback
+	}
+	valueInt, err := strconv.Atoi(value)
+	if err != nil {
+		panic(fmt.Sprintf("[%s] format error!", key))
+	}
+	return valueInt
+}
+
+func getEnvBool(key string, fallback bool) bool {
+	value := getEnv(key, "")
+	if value == "" {
+		return fallback
+	}
+	switch key {
+	case "false":
+		return false
+	case "true":
+		return true
+	default:
+		panic(fmt.Sprintf("[%s] format error!", key))
+	}
+	return fallback
+}
+
+func getEnvList(key string, fallback []string) []string {
+	value := getEnv(key, "")
+	if value == "" {
+		return fallback
+	}
+	return strings.Split(value, ",") //用逗号分割
+}

+ 7 - 2
go.mod

@@ -4,7 +4,12 @@ go 1.12
 
 require (
 	git.finogeeks.club/monitor/go-client v0.0.0-20171124095506-52407144eb4a
-	github.com/gin-gonic/gin v1.4.0
+	github.com/gin-gonic/gin v1.5.0
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.1 // indirect
 	github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
-	github.com/spf13/viper v1.5.0
+	github.com/olivere/elastic/v7 v7.0.14
+	github.com/prometheus/client_golang v1.2.1 // indirect
+	github.com/sirupsen/logrus v1.4.2
+	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
 )

+ 90 - 94
go.sum

@@ -2,162 +2,158 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 git.finogeeks.club/monitor/go-client v0.0.0-20171124095506-52407144eb4a h1:WO7BekTJJKoviQ/5UkFUXsb8sVpq8RGxADMykqvjePA=
 git.finogeeks.club/monitor/go-client v0.0.0-20171124095506-52407144eb4a/go.mod h1:oaRPMqnXlBtiBMS+XooygnRAS5Dmk4i2neyhgLobHiE=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/aws/aws-sdk-go v1.30.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+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/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA=
+github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
-github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
-github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
-github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
-github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
-github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
+github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
 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-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-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
+github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
+github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
+github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 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/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-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/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
-github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
-github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
+github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
+github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
+github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
+github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 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/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 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/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
-github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
-github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/olivere/elastic/v7 v7.0.14 h1:89dYPg6kD3WJx42ZtO4U6WDIzRy69FvQqz/yRiwekuM=
+github.com/olivere/elastic/v7 v7.0.14/go.mod h1:+FgncZ8ho1QF3NlBo77XbuoTKYHhvEOfFZKIAfHnnDE=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 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/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 v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
-github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.2.1 h1:JnMpQc6ppsNgw9QPAGF6Dod479itz7lvlsMzzNayLOI=
+github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
-github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
+github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
-github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
-github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
+github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
-github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
-github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
-github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/viper v1.5.0 h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4=
-github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
 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/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
-github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
-github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+go.opencensus.io v0.22.3/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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+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-20181220203305-927f97764cc3/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-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190522155817-f3200d17e092/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-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 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/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-20181107165924-66b7b1311ac8/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-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
-golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+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-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 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/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 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/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
-gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
-gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
-gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
-gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
+gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 35 - 3
handler/article.go

@@ -1,18 +1,50 @@
 package handler
 
 import (
-	"web_test_cgi/model"
+	"context"
+	"fmt"
 	"github.com/gin-gonic/gin"
+	"github.com/olivere/elastic/v7"
 	"net/http"
+	"web_test_cgi/logger"
 )
 
+var urls = "efk-elasticsearch.efk:9200"
+
 func AddArticle(c *gin.Context) {
-	article := model.Article{}
-	c.BindJSON(&article)
 	c.JSON(http.StatusOK, gin.H{"message": "msg created"})
 
 }
 
 func GetArticles(c *gin.Context) {
+	//测试es
+	type City struct {
+		Name string `json:"name"`
+		Area int    `json:"area"`
+	}
+	type Person struct {
+		Name    string `json:"name"`
+		Age     int    `json:"age"`
+		Married bool   `json:"married"`
+		C       City   `json:"city"`
+	}
+	logger.GLog.Infof("urls:%s", urls)
+	client, err := elastic.NewClient(elastic.SetURL(urls))
+	if err != nil {
+		// Handle error
+		panic(err)
+	}
+
+	fmt.Println("connect to es success")
+	p1 := Person{Name: "rion", Age: 22, Married: false, C: City{Name: "shenzhen", Area: 10}}
+	put1, err := client.Index().
+		Index("user").
+		BodyJson(p1).
+		Do(context.Background())
+	if err != nil {
+		// Handle error
+		panic(err)
+	}
+	fmt.Printf("Indexed user %s to index %s, type %s\n", put1.Id, put1.Index, put1.Type)
 	c.JSON(http.StatusOK, gin.H{"name": "wangkang"})
 }

+ 61 - 170
logger/log.go

@@ -1,201 +1,92 @@
 package logger
 
 import (
-	"fmt"
-	"log"
+	"github.com/sirupsen/logrus"
 	"os"
 	"runtime"
+	"strconv"
+	"strings"
+	"web_test_cgi/config"
 )
 
+var GLog *logrus.Logger
 
-
-// Logger is the server logger
-type Logger struct {
-	logger     *log.Logger
-	debug      bool
-	trace      bool
-	file       bool
-	infoLabel  string
-	errorLabel string
-	fatalLabel string
-	debugLabel string
-	traceLabel string
+func init() {
+	GLog = GetDefaultGinLog()
 }
 
-// NewStdLogger creates a logger with output directed to Stderr
-func NewStdLogger(time, file, debug, trace, colors, pid bool) *Logger {
-	flags := 0
-	if time {
-		flags = log.LstdFlags | log.Lmicroseconds
-	}
-
-	pre := ""
-	if pid {
-		pre = pidPrefix()
+func GetDefaultGinLog() *logrus.Logger {
+	l := logrus.New()
+	l.Formatter = &logrus.JSONFormatter{
+		TimestampFormat:  "2006-01-02 15:04:05",
+		DisableTimestamp: false,
+		FieldMap:         nil,
+		CallerPrettyfier: LogCallerFunc,
+		PrettyPrint:      false,
 	}
-
-	l := &Logger{
-		logger: log.New(os.Stdout, pre, flags),
-		debug:  debug,
-		trace:  trace,
-		file:   file,
-	}
-
-	if colors {
-		setColoredLabelFormats(l)
-	} else {
-		setPlainLabelFormats(l)
-	}
-
+	l.Out = os.Stdout
+	l.ReportCaller = true
+	l.Level = getModeByStr(config.Cfg.Mode)
 	return l
 }
 
-// NewFileLogger creates a logger with output directed to a file
-func NewFileLogger(filename string, time, file, debug, trace, pid bool) *Logger {
-	fileflags := os.O_WRONLY | os.O_APPEND | os.O_CREATE
-	f, err := os.OpenFile(filename, fileflags, 0660)
-	if err != nil {
-		log.Fatalf("error opening file: %v", err)
+func NewDefaultGinLog(traceId string) *logrus.Logger {
+	l := logrus.New()
+	l.Formatter = &logrus.JSONFormatter{
+		TimestampFormat:  "2006-01-02 15:04:05",
+		DisableTimestamp: false,
+		FieldMap:         nil,
+		CallerPrettyfier: LogCallerFunc,
+		PrettyPrint:      false,
 	}
-
-	flags := 0
-	if time {
-		flags = log.LstdFlags | log.Lmicroseconds
-	}
-
-	pre := ""
-	if pid {
-		pre = pidPrefix()
-	}
-
-	l := &Logger{
-		logger: log.New(f, pre, flags),
-		debug:  debug,
-		trace:  trace,
-		file:   file,
-	}
-
-	setPlainLabelFormats(l)
+	l.Out = os.Stdout
+	l.ReportCaller = true
+	l.Level = getModeByStr(config.Cfg.Mode)
+	traceIdHook := NewTraceIdHook(traceId)
+	l.AddHook(traceIdHook)
 	return l
 }
 
-// Generate the pid prefix string
-func pidPrefix() string {
-	return fmt.Sprintf("[%d] ", os.Getpid())
-}
-
-func setPlainLabelFormats(l *Logger) {
-	l.infoLabel = "[INF]"
-	l.debugLabel = "[DBG]"
-	l.errorLabel = "[ERR]"
-	l.fatalLabel = "[FTL]"
-	l.traceLabel = "[TRC]"
-}
-
-func setColoredLabelFormats(l *Logger) {
-	colorFormat := "[\x1b[%dm%s\x1b[0m]"
-	l.infoLabel = fmt.Sprintf(colorFormat, 32, "INF")
-	l.debugLabel = fmt.Sprintf(colorFormat, 36, "DBG")
-	l.errorLabel = fmt.Sprintf(colorFormat, 31, "ERR")
-	l.fatalLabel = fmt.Sprintf(colorFormat, 31, "FTL")
-	l.traceLabel = fmt.Sprintf(colorFormat, 33, "TRC")
-}
-
-// copy from go/src/log/log.go and modify by guojuntao, 2017/09/21
-// Cheap integer to fixed-width decimal ASCII.  Give a negative width to avoid zero-padding.
-func itoa(i int, wid int) string {
-	// Assemble decimal in reverse order.
-	var b [20]byte
-	bp := len(b) - 1
-	for i >= 10 || wid > 1 {
-		wid--
-		q := i / 10
-		b[bp] = byte('0' + i - q*10)
-		bp--
-		i = q
+func getModeByStr(s string) logrus.Level {
+	switch s {
+	case "debug":
+		return logrus.DebugLevel
+	case "info":
+		return logrus.InfoLevel
+	case "warn":
+		return logrus.WarnLevel
+	case "error":
+		return logrus.ErrorLevel
+	default:
+		return logrus.DebugLevel
 	}
-	// i < 10
-	b[bp] = byte('0' + i)
-	return string(b[bp:])
 }
 
-func (l *Logger) getFileLineFormat(calldepth int) string {
-	if l.file {
-		_, file, line, ok := runtime.Caller(calldepth)
-		if !ok {
-			file = "???"
-			line = 0
+//处理调用信息
+func LogCallerFunc(r *runtime.Frame) (function string, file string) {
+	if r != nil {
+		s := strings.Split(r.File, "/")
+		sLen := len(s)
+		if sLen >= 2 {
+			return "/" + s[sLen-1] + "/" + s[sLen-2] + ":" + strconv.Itoa(r.Line), ""
 		}
-		short := file
-		for i := len(file) - 1; i > 0; i-- {
-			if file[i] == '/' {
-				short = file[i+1:]
-				break
-			}
-		}
-		file = short
-		return " " + file + ":" + itoa(line, -1) + ":"
 	}
-	return ""
-}
-
-// Noticef logs a notice statement
-func (l *Logger) Noticef(format string, v ...interface{}) {
-	l.logger.Printf(l.infoLabel+l.getFileLineFormat(2)+" "+format, v...)
+	return "", ""
 }
 
-func (l *Logger) Noticeln(v ...interface{}) {
-	l.logger.Println(append([]interface{}{l.infoLabel + l.getFileLineFormat(2)}, v...)...)
+//添加traceId钩子,每一个请求有一个唯一id
+type TraceIdHook struct {
+	Id string
 }
 
-// Errorf logs an error statement
-func (l *Logger) Errorf(format string, v ...interface{}) {
-	l.logger.Printf(l.errorLabel+l.getFileLineFormat(2)+" "+format, v...)
+func NewTraceIdHook(traceId string) *TraceIdHook {
+	return &TraceIdHook{Id: traceId}
 }
 
-func (l *Logger) Errorln(v ...interface{}) {
-	l.logger.Println(append([]interface{}{l.errorLabel + l.getFileLineFormat(2)}, v...)...)
+func (t *TraceIdHook) Fire(entry *logrus.Entry) error {
+	entry.Data["trace-id"] = t.Id
+	return nil
 }
-
-// Fatalf logs a fatal error
-func (l *Logger) Fatalf(format string, v ...interface{}) {
-	l.logger.Fatalf(l.fatalLabel+l.getFileLineFormat(2)+" "+format, v...)
-}
-
-func (l *Logger) Fatalln(v ...interface{}) {
-	l.logger.Fatalln(append([]interface{}{l.fatalLabel + l.getFileLineFormat(2)}, v...)...)
+func (t *TraceIdHook) Levels() []logrus.Level {
+	return logrus.AllLevels
 }
-
-// Debugf logs a debug statement
-func (l *Logger) Debugf(format string, v ...interface{}) {
-	if l.debug {
-		l.logger.Printf(l.debugLabel+l.getFileLineFormat(2)+" "+format, v...)
-	}
-}
-
-func (l *Logger) Debugln(v ...interface{}) {
-	if l.debug {
-		l.logger.Println(append([]interface{}{l.debugLabel + l.getFileLineFormat(2)}, v...)...)
-	}
-}
-
-// Tracef logs a trace statement
-func (l *Logger) Tracef(format string, v ...interface{}) {
-	if l.trace {
-		l.logger.Printf(l.traceLabel+l.getFileLineFormat(2)+" "+format, v...)
-	}
-}
-
-func (l *Logger) Traceln(v ...interface{}) {
-	if l.trace {
-		l.logger.Println(append([]interface{}{l.traceLabel + l.getFileLineFormat(2)}, v...)...)
-	}
-}
-
-func (l *Logger) IsDebugEnabled() bool {
-	return l.debug
-}
-
-func (l *Logger) IsTraceEnabled() bool {
-	return l.trace
-}

+ 0 - 10
logger/logger.go

@@ -1,10 +0,0 @@
-package logger
-
-var l *Logger
-
-func init() {
-}
-
-func GetLogger() *Logger {
-	return l
-}

+ 1 - 0
router/router.go

@@ -15,6 +15,7 @@ func Load(g *gin.Engine) *gin.Engine {
 	g.Use(middleware.Options)
 	g.Use(middleware.Secure)
 
+
 	// 404 Handler
 	g.NoRoute(func(c *gin.Context) {
 		c.String(http.StatusNotFound, "The incorrect API route.")

+ 43 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/counter.go

@@ -0,0 +1,43 @@
+package monitor
+
+import (
+    "github.com/prometheus/client_golang/prometheus"
+)
+
+type counter struct {
+    prometheus.Counter
+    enable    bool
+}
+
+func (c *counter) Inc() {
+    if (c.enable) {
+        c.Counter.Inc()
+    }
+}
+
+func (c *counter) Add(v float64) {
+    if (c.enable) {
+        c.Counter.Add(v)
+    }
+}
+
+type labeledCounter struct {
+    *prometheus.CounterVec
+    enable    bool
+}
+
+func (c *labeledCounter) WithLabelValues(lvs ...string) Counter {
+    if (c.enable) {
+        return &counter{ c.CounterVec.WithLabelValues(lvs...), true }
+    } else {
+        return &counter{ enable: false }
+    }
+}
+
+func (c *labeledCounter) With(labels Labels) Counter {
+    if (c.enable) {
+        return &counter{ c.CounterVec.With(prometheus.Labels(labels)), true }
+    } else {
+        return &counter{ enable: false }
+    }
+}

+ 67 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/gauge.go

@@ -0,0 +1,67 @@
+package monitor
+
+import (
+    "github.com/prometheus/client_golang/prometheus"
+)
+
+type gauge struct {
+    prometheus.Gauge
+    enable    bool
+}
+
+func (g *gauge) Set(v float64) {
+    if (g.enable) {
+        g.Gauge.Set(v)
+    }
+}
+
+func (g *gauge) Inc() {
+    if (g.enable) {
+        g.Gauge.Inc()
+    }
+}
+
+func (g *gauge) Dec() {
+    if (g.enable) {
+        g.Gauge.Dec()
+    }
+}
+
+func (g *gauge) Add(v float64) {
+    if (g.enable) {
+        g.Gauge.Add(v)
+    }
+}
+
+func (g *gauge) Sub(v float64) {
+    if (g.enable) {
+        g.Gauge.Sub(v)
+    }
+}
+
+func (g *gauge) SetToCurrentTime() {
+    if (g.enable) {
+        g.Gauge.SetToCurrentTime()
+    }
+}
+
+type labeledGauge struct {
+    *prometheus.GaugeVec
+    enable    bool
+}
+
+func (g *labeledGauge) WithLabelValues(lvs ...string) Gauge {
+    if (g.enable) {
+        return &gauge{ g.GaugeVec.WithLabelValues(lvs...), true }
+    } else {
+        return &gauge{ enable: false }
+    }
+}
+
+func (g *labeledGauge) With(labels Labels) Gauge {
+    if (g.enable) {
+        return &gauge{ g.GaugeVec.With(prometheus.Labels(labels)), true }
+    } else {
+        return &gauge{ enable: false }
+    }
+}

+ 37 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/histogram.go

@@ -0,0 +1,37 @@
+package monitor
+
+import (
+    "github.com/prometheus/client_golang/prometheus"
+)
+
+type histogram struct {
+    prometheus.Observer
+    enable    bool
+}
+
+func (h *histogram) Observe(v float64) {
+    if (h.enable) {
+        h.Observer.Observe(v)
+    }
+}
+
+type labeledHistogram struct {
+    *prometheus.HistogramVec
+    enable    bool
+}
+
+func (h *labeledHistogram) WithLabelValues(lvs ...string) Histogram {
+    if (h.enable) {
+        return &histogram{ h.HistogramVec.WithLabelValues(lvs...), true }
+    } else {
+        return &histogram{ enable: false }
+    }
+}
+
+func (h *labeledHistogram) With(labels Labels) Histogram {
+    if (h.enable) {
+        return &histogram{ h.HistogramVec.With(prometheus.Labels(labels)), true }
+    } else {
+        return &histogram{ enable: false }
+    }
+}

+ 162 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/interface.go

@@ -0,0 +1,162 @@
+package monitor
+
+type Labels map[string]string
+
+type Monitor interface {
+    // NewCounter creates a new Counter based on the provided metric name.
+    NewCounter(metirc string) Counter
+    // NewLabeledCounter creates a new LabeledCounter based on the provided metric name and
+    // partitioned by the given label names. At least one label name must be
+    // provided.
+    NewLabeledCounter(metirc string, labelNames []string) LabeledCounter
+
+    // NewGauge creates a new Gauge based on the provided metric name.
+    NewGauge(metirc string) Gauge
+    // NewLabeledGauge creates a new LabeledGauge based on the provided metric name and
+    // partitioned by the given label names. At least one label name must be
+    // provided.
+    NewLabeledGauge(metirc string, labelNames []string) LabeledGauge
+
+    // NewSummary creates a new Summary based on the provided metric name.
+    //
+    // Quantile defines the quantile rank estimates with their respective
+    // absolute error. If Objectives[q] = e, then the value reported for q
+    // will be the φ-quantile value for some φ between q-e and q+e.  The
+    // default value is DefObjectives. It is used if Objectives is left at
+    // its zero value (i.e. nil). To create a Summary without Objectives,
+    // set it to an empty map (i.e. map[float64]float64{}). The default value is
+    // {0.5: 0.05, 0.9: 0.01, 0.99: 0.001} if pass nil.
+    NewSummary(metirc string, quantile map[float64]float64) Summary
+    // NewLabeledSummary creates a new LabeledSummary based on the provided metric name and
+    // partitioned by the given label names. At least one label name must be
+    // provided.
+    NewLabeledSummary(metirc string, labelNames []string, quantile map[float64]float64) LabeledSummary
+
+    // NewHistogram creates a new Histogram based on the provided metric name.
+    //
+    // Buckets defines the buckets into which observations are counted. Each
+    // element in the slice is the upper inclusive bound of a bucket. The
+    // values must be sorted in strictly increasing order. There is no need
+    // to add a highest bucket with +Inf bound, it will be added
+    // implicitly. The default value is {.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
+    // if pass nil.
+    NewHistogram(metirc string, buckets []float64) Histogram
+    // NewLabeledHistogram creates a new LabeledHistogram based on the provided metric name and
+    // partitioned by the given label names. At least one label name must be
+    // provided.
+    NewLabeledHistogram(metirc string, labelNames []string, buckets []float64) LabeledHistogram
+
+    // NewTimer creates a new Timer. The provided Observer is used to observe a
+    // duration in seconds. Timer is usually used to time a function call in the
+    // following way:
+    //    func TimeMe() {
+    //        timer := NewTimer(myHistogram)
+    //        defer timer.ObserveDuration()
+    //        // Do actual work.
+    //    }
+    NewTimer(o Observer) Timer
+}
+
+type Timer interface {
+    // ObserveDuration records the duration passed since the Timer was created with
+    // NewTimer. It calls the Observe method of the Observer provided during
+    // construction with the duration in seconds as an argument. ObserveDuration is
+    // usually called with a defer statement.
+    ObserveDuration()
+}
+
+// Observer is the interface that wraps the Observe method, which is used by
+// Histogram and Summary to add observations.
+type Observer interface {
+    Observe(float64)
+}
+
+// The ObserverFunc type is an adapter to allow the use of ordinary
+// functions as Observers. If f is a function with the appropriate
+// signature, ObserverFunc(f) is an Observer that calls f.
+//
+// This adapter is usually used in connection with the Timer type, and there are
+// two general use cases:
+//
+// The most common one is to use a Gauge as the Observer for a Timer.
+// See the "Gauge" Timer example.
+//
+// The more advanced use case is to create a function that dynamically decides
+// which Observer to use for observing the duration. See the "TestTimerComplex"
+// Timer example.
+type ObserverFunc func(float64)
+
+type Counter interface {
+    // Inc increments the counter by 1. Use Add to increment it by arbitrary
+    // non-negative values.
+    Inc()
+    // Add adds the given value to the counter. It panics if the value is <
+    // 0.
+    Add(float64)
+}
+
+type LabeledCounter interface {
+    // WithLabelValues allows shortcuts like
+    // counter.WithLabelValues("404", "GET").Add(42)
+    WithLabelValues(lvs ...string) Counter
+    // With allows shortcuts like
+    // counter.With(Labels{"code": "404", "method": "GET"}).Add(42)
+    With(labels Labels) Counter
+}
+
+type Gauge interface {
+    // Set sets the Gauge to an arbitrary value.
+    Set(float64)
+    // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
+    // values.
+    Inc()
+    // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
+    // values.
+    Dec()
+    // Add adds the given value to the Gauge. (The value can be negative,
+    // resulting in a decrease of the Gauge.)
+    Add(float64)
+    // Sub subtracts the given value from the Gauge. (The value can be
+    // negative, resulting in an increase of the Gauge.)
+    Sub(float64)
+
+    // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
+    SetToCurrentTime()
+}
+
+type LabeledGauge interface {
+    // WithLabelValues allows shortcuts like
+    // gauge.WithLabelValues("404", "GET").Add(42)
+    WithLabelValues(lvs ...string) Gauge
+    // With allows shortcuts like
+    // gauge.With(Labels{"code": "404", "method": "GET"}).Add(42)
+    With(labels Labels) Gauge
+}
+
+type Summary interface {
+    // Observe adds a single observation to the summary.
+    Observe(float64)
+}
+
+type LabeledSummary interface {
+    // WithLabelValues allows shortcuts like
+    // summary.WithLabelValues("404", "GET").Observe(42.21)
+    WithLabelValues(lvs ...string) Summary
+    // With allows shortcuts like
+    // summary.With(Labels{"code": "404", "method": "GET"}).Observe(42.21)
+    With(labels Labels) Summary
+}
+
+type Histogram interface {
+    // Observe adds a single observation to the histogram.
+    Observe(float64)
+}
+
+type LabeledHistogram interface {
+    // WithLabelValues allows shortcuts like
+    // histogram.WithLabelValues("404", "GET").Observe(42.21)
+    WithLabelValues(lvs ...string) Histogram
+    // With allows shortcuts like
+    // histogram.With(Labels{"code": "404", "method": "GET"}).Observe(42.21)
+    With(labels Labels) Histogram
+}

+ 6 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/observer.go

@@ -0,0 +1,6 @@
+package monitor
+
+// Observe calls f(value). It implements Observer.
+func (f ObserverFunc) Observe(v float64) {
+    f(v)
+}

+ 192 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/prometheus.go

@@ -0,0 +1,192 @@
+package monitor
+
+import (
+    "sync"
+    "os"
+    "net/http"
+    "log"
+    "github.com/prometheus/client_golang/prometheus"
+    "github.com/prometheus/client_golang/prometheus/promhttp"
+)
+
+type promMonitor struct {
+    enable      bool
+}
+
+// Singleton
+var once sync.Once
+var instance Monitor
+func GetInstance() Monitor {
+    once.Do(func() {
+        instance = newPrometheus()
+    })
+    return instance
+}
+
+func newPrometheus() *promMonitor {
+    e := os.Getenv("ENABLE_MONITOR")
+    if ("true" == e) {
+        port := ":9092"
+        path := "/metrics"
+
+        p := os.Getenv("MONITOR_PORT")
+        if ("" != p) {
+            port = ":" + p
+        }
+
+        pa := os.Getenv("MONITOR_PATH")
+        if ("" != pa) {
+            path = pa
+        }
+
+        go func() {
+            http.Handle(path, promhttp.Handler())
+            log.Fatal(http.ListenAndServe(port, nil))
+        }()
+
+        return &promMonitor{
+            enable: true,
+        }
+    } else {
+        return &promMonitor{
+            enable: false,
+        }
+    }
+}
+
+func (prom *promMonitor) NewCounter(metirc string) Counter {
+    if (prom.enable) {
+        cnt := prometheus.NewCounter(prometheus.CounterOpts{
+            Name: metirc,
+            Help: "nothing",
+        })
+
+        prometheus.MustRegister(cnt)
+        return &counter{ cnt, true }
+    } else {
+        return &counter{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewLabeledCounter(metirc string, labelNames []string) LabeledCounter {
+    if (prom.enable) {
+        cnt := prometheus.NewCounterVec(
+            prometheus.CounterOpts{
+                Name: metirc,
+                Help: "nothing",
+            },
+            labelNames,
+        )
+
+        prometheus.MustRegister(cnt)
+        return &labeledCounter{ cnt, true }
+    } else {
+        return &labeledCounter{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewGauge(metirc string) Gauge {
+    if (prom.enable) {
+        gau := prometheus.NewGauge(prometheus.GaugeOpts{
+            Name: metirc,
+            Help: "nothing",
+        })
+
+        prometheus.MustRegister(gau)
+        return &gauge{ gau, true }
+    } else {
+        return &gauge{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewLabeledGauge(metirc string, labelNames []string) LabeledGauge {
+    if (prom.enable) {
+        gau := prometheus.NewGaugeVec(
+            prometheus.GaugeOpts{
+                Name: metirc,
+                Help: "nothing",
+            },
+            labelNames,
+        )
+
+        prometheus.MustRegister(gau)
+        return &labeledGauge{ gau, true }
+    } else {
+        return &labeledGauge{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewSummary(metirc string, quantile map[float64]float64) Summary {
+    if (prom.enable) {
+        sum := prometheus.NewSummary(prometheus.SummaryOpts{
+            Name: metirc,
+            Help: "nothing",
+            Objectives: quantile,
+        })
+
+        prometheus.MustRegister(sum)
+        return &summary{ sum, true }
+    } else {
+        return &summary{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewLabeledSummary(metirc string, labelNames []string, quantile map[float64]float64) LabeledSummary {
+    if (prom.enable) {
+        sum := prometheus.NewSummaryVec(
+            prometheus.SummaryOpts{
+                Name: metirc,
+                Help: "nothing",
+                Objectives: quantile,
+            },
+            labelNames,
+        )
+
+        prometheus.MustRegister(sum)
+        return &labeledSummary{ sum, true }
+    } else {
+        return &labeledSummary{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewHistogram(metirc string, buckets []float64) Histogram {
+    if (prom.enable) {
+        his := prometheus.NewHistogram(prometheus.HistogramOpts{
+            Name: metirc,
+            Help: "nothing",
+            Buckets: buckets,
+        })
+
+        prometheus.MustRegister(his)
+        return &histogram{ his, true }
+    } else {
+        return &histogram{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewLabeledHistogram(metirc string, labelNames []string, buckets []float64) LabeledHistogram {
+    if (prom.enable) {
+        his := prometheus.NewHistogramVec(
+            prometheus.HistogramOpts{
+                Name: metirc,
+                Help: "nothing",
+                Buckets: buckets,
+            },
+            labelNames,
+        )
+
+        prometheus.MustRegister(his)
+        return &labeledHistogram{ his, true }
+    } else {
+        return &labeledHistogram{ enable: false }
+    }
+}
+
+func (prom *promMonitor) NewTimer(o Observer) Timer {
+    if (prom.enable) {
+        tim := prometheus.NewTimer(o)
+        return &timer{ tim, true }
+    } else {
+        return &timer{ enable: false }
+    }
+}

+ 37 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/summary.go

@@ -0,0 +1,37 @@
+package monitor
+
+import (
+    "github.com/prometheus/client_golang/prometheus"
+)
+
+type summary struct {
+    prometheus.Observer
+    enable    bool
+}
+
+func (s *summary) Observe(v float64) {
+    if (s.enable) {
+        s.Observer.Observe(v)
+    }
+}
+
+type labeledSummary struct {
+    *prometheus.SummaryVec
+    enable    bool
+}
+
+func (s *labeledSummary) WithLabelValues(lvs ...string) Summary {
+    if (s.enable) {
+        return &summary{ s.SummaryVec.WithLabelValues(lvs...), true }
+    } else {
+        return &summary{ enable: false }
+    }
+}
+
+func (s *labeledSummary) With(labels Labels) Summary {
+    if (s.enable) {
+        return &summary{ s.SummaryVec.With(prometheus.Labels(labels)), true }
+    } else {
+        return &summary{ enable: false }
+    }
+}

+ 16 - 0
vendor/git.finogeeks.club/monitor/go-client/monitor/timer.go

@@ -0,0 +1,16 @@
+package monitor
+
+import (
+    "github.com/prometheus/client_golang/prometheus"
+)
+
+type timer struct {
+    *prometheus.Timer
+    enable    bool
+}
+
+func (t *timer) ObserveDuration() {
+    if (t.enable) {
+        t.Timer.ObserveDuration()
+    }
+}

+ 20 - 0
vendor/github.com/beorn7/perks/LICENSE

@@ -0,0 +1,20 @@
+Copyright (C) 2013 Blake Mizerany
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large
+ 2388 - 0
vendor/github.com/beorn7/perks/quantile/exampledata.txt


+ 316 - 0
vendor/github.com/beorn7/perks/quantile/stream.go

@@ -0,0 +1,316 @@
+// Package quantile computes approximate quantiles over an unbounded data
+// stream within low memory and CPU bounds.
+//
+// A small amount of accuracy is traded to achieve the above properties.
+//
+// Multiple streams can be merged before calling Query to generate a single set
+// of results. This is meaningful when the streams represent the same type of
+// data. See Merge and Samples.
+//
+// For more detailed information about the algorithm used, see:
+//
+// Effective Computation of Biased Quantiles over Data Streams
+//
+// http://www.cs.rutgers.edu/~muthu/bquant.pdf
+package quantile
+
+import (
+	"math"
+	"sort"
+)
+
+// Sample holds an observed value and meta information for compression. JSON
+// tags have been added for convenience.
+type Sample struct {
+	Value float64 `json:",string"`
+	Width float64 `json:",string"`
+	Delta float64 `json:",string"`
+}
+
+// Samples represents a slice of samples. It implements sort.Interface.
+type Samples []Sample
+
+func (a Samples) Len() int           { return len(a) }
+func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
+func (a Samples) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+type invariant func(s *stream, r float64) float64
+
+// NewLowBiased returns an initialized Stream for low-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the lower ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewLowBiased(epsilon float64) *Stream {
+	ƒ := func(s *stream, r float64) float64 {
+		return 2 * epsilon * r
+	}
+	return newStream(ƒ)
+}
+
+// NewHighBiased returns an initialized Stream for high-biased quantiles
+// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
+// error guarantees can still be given even for the higher ranks of the data
+// distribution.
+//
+// The provided epsilon is a relative error, i.e. the true quantile of a value
+// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
+// properties.
+func NewHighBiased(epsilon float64) *Stream {
+	ƒ := func(s *stream, r float64) float64 {
+		return 2 * epsilon * (s.n - r)
+	}
+	return newStream(ƒ)
+}
+
+// NewTargeted returns an initialized Stream concerned with a particular set of
+// quantile values that are supplied a priori. Knowing these a priori reduces
+// space and computation time. The targets map maps the desired quantiles to
+// their absolute errors, i.e. the true quantile of a value returned by a query
+// is guaranteed to be within (Quantile±Epsilon).
+//
+// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
+func NewTargeted(targetMap map[float64]float64) *Stream {
+	// Convert map to slice to avoid slow iterations on a map.
+	// ƒ is called on the hot path, so converting the map to a slice
+	// beforehand results in significant CPU savings.
+	targets := targetMapToSlice(targetMap)
+
+	ƒ := func(s *stream, r float64) float64 {
+		var m = math.MaxFloat64
+		var f float64
+		for _, t := range targets {
+			if t.quantile*s.n <= r {
+				f = (2 * t.epsilon * r) / t.quantile
+			} else {
+				f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
+			}
+			if f < m {
+				m = f
+			}
+		}
+		return m
+	}
+	return newStream(ƒ)
+}
+
+type target struct {
+	quantile float64
+	epsilon  float64
+}
+
+func targetMapToSlice(targetMap map[float64]float64) []target {
+	targets := make([]target, 0, len(targetMap))
+
+	for quantile, epsilon := range targetMap {
+		t := target{
+			quantile: quantile,
+			epsilon:  epsilon,
+		}
+		targets = append(targets, t)
+	}
+
+	return targets
+}
+
+// Stream computes quantiles for a stream of float64s. It is not thread-safe by
+// design. Take care when using across multiple goroutines.
+type Stream struct {
+	*stream
+	b      Samples
+	sorted bool
+}
+
+func newStream(ƒ invariant) *Stream {
+	x := &stream{ƒ: ƒ}
+	return &Stream{x, make(Samples, 0, 500), true}
+}
+
+// Insert inserts v into the stream.
+func (s *Stream) Insert(v float64) {
+	s.insert(Sample{Value: v, Width: 1})
+}
+
+func (s *Stream) insert(sample Sample) {
+	s.b = append(s.b, sample)
+	s.sorted = false
+	if len(s.b) == cap(s.b) {
+		s.flush()
+	}
+}
+
+// Query returns the computed qth percentiles value. If s was created with
+// NewTargeted, and q is not in the set of quantiles provided a priori, Query
+// will return an unspecified result.
+func (s *Stream) Query(q float64) float64 {
+	if !s.flushed() {
+		// Fast path when there hasn't been enough data for a flush;
+		// this also yields better accuracy for small sets of data.
+		l := len(s.b)
+		if l == 0 {
+			return 0
+		}
+		i := int(math.Ceil(float64(l) * q))
+		if i > 0 {
+			i -= 1
+		}
+		s.maybeSort()
+		return s.b[i].Value
+	}
+	s.flush()
+	return s.stream.query(q)
+}
+
+// Merge merges samples into the underlying streams samples. This is handy when
+// merging multiple streams from separate threads, database shards, etc.
+//
+// ATTENTION: This method is broken and does not yield correct results. The
+// underlying algorithm is not capable of merging streams correctly.
+func (s *Stream) Merge(samples Samples) {
+	sort.Sort(samples)
+	s.stream.merge(samples)
+}
+
+// Reset reinitializes and clears the list reusing the samples buffer memory.
+func (s *Stream) Reset() {
+	s.stream.reset()
+	s.b = s.b[:0]
+}
+
+// Samples returns stream samples held by s.
+func (s *Stream) Samples() Samples {
+	if !s.flushed() {
+		return s.b
+	}
+	s.flush()
+	return s.stream.samples()
+}
+
+// Count returns the total number of samples observed in the stream
+// since initialization.
+func (s *Stream) Count() int {
+	return len(s.b) + s.stream.count()
+}
+
+func (s *Stream) flush() {
+	s.maybeSort()
+	s.stream.merge(s.b)
+	s.b = s.b[:0]
+}
+
+func (s *Stream) maybeSort() {
+	if !s.sorted {
+		s.sorted = true
+		sort.Sort(s.b)
+	}
+}
+
+func (s *Stream) flushed() bool {
+	return len(s.stream.l) > 0
+}
+
+type stream struct {
+	n float64
+	l []Sample
+	ƒ invariant
+}
+
+func (s *stream) reset() {
+	s.l = s.l[:0]
+	s.n = 0
+}
+
+func (s *stream) insert(v float64) {
+	s.merge(Samples{{v, 1, 0}})
+}
+
+func (s *stream) merge(samples Samples) {
+	// TODO(beorn7): This tries to merge not only individual samples, but
+	// whole summaries. The paper doesn't mention merging summaries at
+	// all. Unittests show that the merging is inaccurate. Find out how to
+	// do merges properly.
+	var r float64
+	i := 0
+	for _, sample := range samples {
+		for ; i < len(s.l); i++ {
+			c := s.l[i]
+			if c.Value > sample.Value {
+				// Insert at position i.
+				s.l = append(s.l, Sample{})
+				copy(s.l[i+1:], s.l[i:])
+				s.l[i] = Sample{
+					sample.Value,
+					sample.Width,
+					math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
+					// TODO(beorn7): How to calculate delta correctly?
+				}
+				i++
+				goto inserted
+			}
+			r += c.Width
+		}
+		s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
+		i++
+	inserted:
+		s.n += sample.Width
+		r += sample.Width
+	}
+	s.compress()
+}
+
+func (s *stream) count() int {
+	return int(s.n)
+}
+
+func (s *stream) query(q float64) float64 {
+	t := math.Ceil(q * s.n)
+	t += math.Ceil(s.ƒ(s, t) / 2)
+	p := s.l[0]
+	var r float64
+	for _, c := range s.l[1:] {
+		r += p.Width
+		if r+c.Width+c.Delta > t {
+			return p.Value
+		}
+		p = c
+	}
+	return p.Value
+}
+
+func (s *stream) compress() {
+	if len(s.l) < 2 {
+		return
+	}
+	x := s.l[len(s.l)-1]
+	xi := len(s.l) - 1
+	r := s.n - 1 - x.Width
+
+	for i := len(s.l) - 2; i >= 0; i-- {
+		c := s.l[i]
+		if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
+			x.Width += c.Width
+			s.l[xi] = x
+			// Remove element at i.
+			copy(s.l[i:], s.l[i+1:])
+			s.l = s.l[:len(s.l)-1]
+			xi -= 1
+		} else {
+			x = c
+			xi = i
+		}
+		r -= c.Width
+	}
+}
+
+func (s *stream) samples() Samples {
+	samples := make(Samples, len(s.l))
+	copy(samples, s.l)
+	return samples
+}

+ 8 - 0
vendor/github.com/cespare/xxhash/v2/.travis.yml

@@ -0,0 +1,8 @@
+language: go
+go:
+  - "1.x"
+  - master
+env:
+  - TAGS=""
+  - TAGS="-tags purego"
+script: go test $TAGS -v ./...

+ 22 - 0
vendor/github.com/cespare/xxhash/v2/LICENSE.txt

@@ -0,0 +1,22 @@
+Copyright (c) 2016 Caleb Spare
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 55 - 0
vendor/github.com/cespare/xxhash/v2/README.md

@@ -0,0 +1,55 @@
+# xxhash
+
+[![GoDoc](https://godoc.org/github.com/cespare/xxhash?status.svg)](https://godoc.org/github.com/cespare/xxhash)
+[![Build Status](https://travis-ci.org/cespare/xxhash.svg?branch=master)](https://travis-ci.org/cespare/xxhash)
+
+xxhash is a Go implementation of the 64-bit
+[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a
+high-quality hashing algorithm that is much faster than anything in the Go
+standard library.
+
+This package provides a straightforward API:
+
+```
+func Sum64(b []byte) uint64
+func Sum64String(s string) uint64
+type Digest struct{ ... }
+    func New() *Digest
+```
+
+The `Digest` type implements hash.Hash64. Its key methods are:
+
+```
+func (*Digest) Write([]byte) (int, error)
+func (*Digest) WriteString(string) (int, error)
+func (*Digest) Sum64() uint64
+```
+
+This implementation provides a fast pure-Go implementation and an even faster
+assembly implementation for amd64.
+
+## Benchmarks
+
+Here are some quick benchmarks comparing the pure-Go and assembly
+implementations of Sum64.
+
+| input size | purego | asm |
+| --- | --- | --- |
+| 5 B   |  979.66 MB/s |  1291.17 MB/s  |
+| 100 B | 7475.26 MB/s | 7973.40 MB/s  |
+| 4 KB  | 17573.46 MB/s | 17602.65 MB/s |
+| 10 MB | 17131.46 MB/s | 17142.16 MB/s |
+
+These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using
+the following commands under Go 1.11.2:
+
+```
+$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes'
+$ go test -benchtime 10s -bench '/xxhash,direct,bytes'
+```
+
+## Projects using this package
+
+- [InfluxDB](https://github.com/influxdata/influxdb)
+- [Prometheus](https://github.com/prometheus/prometheus)
+- [FreeCache](https://github.com/coocood/freecache)

+ 3 - 0
vendor/github.com/cespare/xxhash/v2/go.mod

@@ -0,0 +1,3 @@
+module github.com/cespare/xxhash/v2
+
+go 1.13

+ 0 - 0
vendor/github.com/cespare/xxhash/v2/go.sum


+ 236 - 0
vendor/github.com/cespare/xxhash/v2/xxhash.go

@@ -0,0 +1,236 @@
+// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
+// at http://cyan4973.github.io/xxHash/.
+package xxhash
+
+import (
+	"encoding/binary"
+	"errors"
+	"math/bits"
+)
+
+const (
+	prime1 uint64 = 11400714785074694791
+	prime2 uint64 = 14029467366897019727
+	prime3 uint64 = 1609587929392839161
+	prime4 uint64 = 9650029242287828579
+	prime5 uint64 = 2870177450012600261
+)
+
+// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where
+// possible in the Go code is worth a small (but measurable) performance boost
+// by avoiding some MOVQs. Vars are needed for the asm and also are useful for
+// convenience in the Go code in a few places where we need to intentionally
+// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the
+// result overflows a uint64).
+var (
+	prime1v = prime1
+	prime2v = prime2
+	prime3v = prime3
+	prime4v = prime4
+	prime5v = prime5
+)
+
+// Digest implements hash.Hash64.
+type Digest struct {
+	v1    uint64
+	v2    uint64
+	v3    uint64
+	v4    uint64
+	total uint64
+	mem   [32]byte
+	n     int // how much of mem is used
+}
+
+// New creates a new Digest that computes the 64-bit xxHash algorithm.
+func New() *Digest {
+	var d Digest
+	d.Reset()
+	return &d
+}
+
+// Reset clears the Digest's state so that it can be reused.
+func (d *Digest) Reset() {
+	d.v1 = prime1v + prime2
+	d.v2 = prime2
+	d.v3 = 0
+	d.v4 = -prime1v
+	d.total = 0
+	d.n = 0
+}
+
+// Size always returns 8 bytes.
+func (d *Digest) Size() int { return 8 }
+
+// BlockSize always returns 32 bytes.
+func (d *Digest) BlockSize() int { return 32 }
+
+// Write adds more data to d. It always returns len(b), nil.
+func (d *Digest) Write(b []byte) (n int, err error) {
+	n = len(b)
+	d.total += uint64(n)
+
+	if d.n+n < 32 {
+		// This new data doesn't even fill the current block.
+		copy(d.mem[d.n:], b)
+		d.n += n
+		return
+	}
+
+	if d.n > 0 {
+		// Finish off the partial block.
+		copy(d.mem[d.n:], b)
+		d.v1 = round(d.v1, u64(d.mem[0:8]))
+		d.v2 = round(d.v2, u64(d.mem[8:16]))
+		d.v3 = round(d.v3, u64(d.mem[16:24]))
+		d.v4 = round(d.v4, u64(d.mem[24:32]))
+		b = b[32-d.n:]
+		d.n = 0
+	}
+
+	if len(b) >= 32 {
+		// One or more full blocks left.
+		nw := writeBlocks(d, b)
+		b = b[nw:]
+	}
+
+	// Store any remaining partial block.
+	copy(d.mem[:], b)
+	d.n = len(b)
+
+	return
+}
+
+// Sum appends the current hash to b and returns the resulting slice.
+func (d *Digest) Sum(b []byte) []byte {
+	s := d.Sum64()
+	return append(
+		b,
+		byte(s>>56),
+		byte(s>>48),
+		byte(s>>40),
+		byte(s>>32),
+		byte(s>>24),
+		byte(s>>16),
+		byte(s>>8),
+		byte(s),
+	)
+}
+
+// Sum64 returns the current hash.
+func (d *Digest) Sum64() uint64 {
+	var h uint64
+
+	if d.total >= 32 {
+		v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
+		h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
+		h = mergeRound(h, v1)
+		h = mergeRound(h, v2)
+		h = mergeRound(h, v3)
+		h = mergeRound(h, v4)
+	} else {
+		h = d.v3 + prime5
+	}
+
+	h += d.total
+
+	i, end := 0, d.n
+	for ; i+8 <= end; i += 8 {
+		k1 := round(0, u64(d.mem[i:i+8]))
+		h ^= k1
+		h = rol27(h)*prime1 + prime4
+	}
+	if i+4 <= end {
+		h ^= uint64(u32(d.mem[i:i+4])) * prime1
+		h = rol23(h)*prime2 + prime3
+		i += 4
+	}
+	for i < end {
+		h ^= uint64(d.mem[i]) * prime5
+		h = rol11(h) * prime1
+		i++
+	}
+
+	h ^= h >> 33
+	h *= prime2
+	h ^= h >> 29
+	h *= prime3
+	h ^= h >> 32
+
+	return h
+}
+
+const (
+	magic         = "xxh\x06"
+	marshaledSize = len(magic) + 8*5 + 32
+)
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (d *Digest) MarshalBinary() ([]byte, error) {
+	b := make([]byte, 0, marshaledSize)
+	b = append(b, magic...)
+	b = appendUint64(b, d.v1)
+	b = appendUint64(b, d.v2)
+	b = appendUint64(b, d.v3)
+	b = appendUint64(b, d.v4)
+	b = appendUint64(b, d.total)
+	b = append(b, d.mem[:d.n]...)
+	b = b[:len(b)+len(d.mem)-d.n]
+	return b, nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (d *Digest) UnmarshalBinary(b []byte) error {
+	if len(b) < len(magic) || string(b[:len(magic)]) != magic {
+		return errors.New("xxhash: invalid hash state identifier")
+	}
+	if len(b) != marshaledSize {
+		return errors.New("xxhash: invalid hash state size")
+	}
+	b = b[len(magic):]
+	b, d.v1 = consumeUint64(b)
+	b, d.v2 = consumeUint64(b)
+	b, d.v3 = consumeUint64(b)
+	b, d.v4 = consumeUint64(b)
+	b, d.total = consumeUint64(b)
+	copy(d.mem[:], b)
+	b = b[len(d.mem):]
+	d.n = int(d.total % uint64(len(d.mem)))
+	return nil
+}
+
+func appendUint64(b []byte, x uint64) []byte {
+	var a [8]byte
+	binary.LittleEndian.PutUint64(a[:], x)
+	return append(b, a[:]...)
+}
+
+func consumeUint64(b []byte) ([]byte, uint64) {
+	x := u64(b)
+	return b[8:], x
+}
+
+func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
+func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
+
+func round(acc, input uint64) uint64 {
+	acc += input * prime2
+	acc = rol31(acc)
+	acc *= prime1
+	return acc
+}
+
+func mergeRound(acc, val uint64) uint64 {
+	val = round(0, val)
+	acc ^= val
+	acc = acc*prime1 + prime4
+	return acc
+}
+
+func rol1(x uint64) uint64  { return bits.RotateLeft64(x, 1) }
+func rol7(x uint64) uint64  { return bits.RotateLeft64(x, 7) }
+func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) }
+func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) }
+func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) }
+func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) }
+func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) }
+func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) }

+ 13 - 0
vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go

@@ -0,0 +1,13 @@
+// +build !appengine
+// +build gc
+// +build !purego
+
+package xxhash
+
+// Sum64 computes the 64-bit xxHash digest of b.
+//
+//go:noescape
+func Sum64(b []byte) uint64
+
+//go:noescape
+func writeBlocks(*Digest, []byte) int

+ 215 - 0
vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s

@@ -0,0 +1,215 @@
+// +build !appengine
+// +build gc
+// +build !purego
+
+#include "textflag.h"
+
+// Register allocation:
+// AX	h
+// CX	pointer to advance through b
+// DX	n
+// BX	loop end
+// R8	v1, k1
+// R9	v2
+// R10	v3
+// R11	v4
+// R12	tmp
+// R13	prime1v
+// R14	prime2v
+// R15	prime4v
+
+// round reads from and advances the buffer pointer in CX.
+// It assumes that R13 has prime1v and R14 has prime2v.
+#define round(r) \
+	MOVQ  (CX), R12 \
+	ADDQ  $8, CX    \
+	IMULQ R14, R12  \
+	ADDQ  R12, r    \
+	ROLQ  $31, r    \
+	IMULQ R13, r
+
+// mergeRound applies a merge round on the two registers acc and val.
+// It assumes that R13 has prime1v, R14 has prime2v, and R15 has prime4v.
+#define mergeRound(acc, val) \
+	IMULQ R14, val \
+	ROLQ  $31, val \
+	IMULQ R13, val \
+	XORQ  val, acc \
+	IMULQ R13, acc \
+	ADDQ  R15, acc
+
+// func Sum64(b []byte) uint64
+TEXT ·Sum64(SB), NOSPLIT, $0-32
+	// Load fixed primes.
+	MOVQ ·prime1v(SB), R13
+	MOVQ ·prime2v(SB), R14
+	MOVQ ·prime4v(SB), R15
+
+	// Load slice.
+	MOVQ b_base+0(FP), CX
+	MOVQ b_len+8(FP), DX
+	LEAQ (CX)(DX*1), BX
+
+	// The first loop limit will be len(b)-32.
+	SUBQ $32, BX
+
+	// Check whether we have at least one block.
+	CMPQ DX, $32
+	JLT  noBlocks
+
+	// Set up initial state (v1, v2, v3, v4).
+	MOVQ R13, R8
+	ADDQ R14, R8
+	MOVQ R14, R9
+	XORQ R10, R10
+	XORQ R11, R11
+	SUBQ R13, R11
+
+	// Loop until CX > BX.
+blockLoop:
+	round(R8)
+	round(R9)
+	round(R10)
+	round(R11)
+
+	CMPQ CX, BX
+	JLE  blockLoop
+
+	MOVQ R8, AX
+	ROLQ $1, AX
+	MOVQ R9, R12
+	ROLQ $7, R12
+	ADDQ R12, AX
+	MOVQ R10, R12
+	ROLQ $12, R12
+	ADDQ R12, AX
+	MOVQ R11, R12
+	ROLQ $18, R12
+	ADDQ R12, AX
+
+	mergeRound(AX, R8)
+	mergeRound(AX, R9)
+	mergeRound(AX, R10)
+	mergeRound(AX, R11)
+
+	JMP afterBlocks
+
+noBlocks:
+	MOVQ ·prime5v(SB), AX
+
+afterBlocks:
+	ADDQ DX, AX
+
+	// Right now BX has len(b)-32, and we want to loop until CX > len(b)-8.
+	ADDQ $24, BX
+
+	CMPQ CX, BX
+	JG   fourByte
+
+wordLoop:
+	// Calculate k1.
+	MOVQ  (CX), R8
+	ADDQ  $8, CX
+	IMULQ R14, R8
+	ROLQ  $31, R8
+	IMULQ R13, R8
+
+	XORQ  R8, AX
+	ROLQ  $27, AX
+	IMULQ R13, AX
+	ADDQ  R15, AX
+
+	CMPQ CX, BX
+	JLE  wordLoop
+
+fourByte:
+	ADDQ $4, BX
+	CMPQ CX, BX
+	JG   singles
+
+	MOVL  (CX), R8
+	ADDQ  $4, CX
+	IMULQ R13, R8
+	XORQ  R8, AX
+
+	ROLQ  $23, AX
+	IMULQ R14, AX
+	ADDQ  ·prime3v(SB), AX
+
+singles:
+	ADDQ $4, BX
+	CMPQ CX, BX
+	JGE  finalize
+
+singlesLoop:
+	MOVBQZX (CX), R12
+	ADDQ    $1, CX
+	IMULQ   ·prime5v(SB), R12
+	XORQ    R12, AX
+
+	ROLQ  $11, AX
+	IMULQ R13, AX
+
+	CMPQ CX, BX
+	JL   singlesLoop
+
+finalize:
+	MOVQ  AX, R12
+	SHRQ  $33, R12
+	XORQ  R12, AX
+	IMULQ R14, AX
+	MOVQ  AX, R12
+	SHRQ  $29, R12
+	XORQ  R12, AX
+	IMULQ ·prime3v(SB), AX
+	MOVQ  AX, R12
+	SHRQ  $32, R12
+	XORQ  R12, AX
+
+	MOVQ AX, ret+24(FP)
+	RET
+
+// writeBlocks uses the same registers as above except that it uses AX to store
+// the d pointer.
+
+// func writeBlocks(d *Digest, b []byte) int
+TEXT ·writeBlocks(SB), NOSPLIT, $0-40
+	// Load fixed primes needed for round.
+	MOVQ ·prime1v(SB), R13
+	MOVQ ·prime2v(SB), R14
+
+	// Load slice.
+	MOVQ b_base+8(FP), CX
+	MOVQ b_len+16(FP), DX
+	LEAQ (CX)(DX*1), BX
+	SUBQ $32, BX
+
+	// Load vN from d.
+	MOVQ d+0(FP), AX
+	MOVQ 0(AX), R8   // v1
+	MOVQ 8(AX), R9   // v2
+	MOVQ 16(AX), R10 // v3
+	MOVQ 24(AX), R11 // v4
+
+	// We don't need to check the loop condition here; this function is
+	// always called with at least one block of data to process.
+blockLoop:
+	round(R8)
+	round(R9)
+	round(R10)
+	round(R11)
+
+	CMPQ CX, BX
+	JLE  blockLoop
+
+	// Copy vN back to d.
+	MOVQ R8, 0(AX)
+	MOVQ R9, 8(AX)
+	MOVQ R10, 16(AX)
+	MOVQ R11, 24(AX)
+
+	// The number of bytes written is CX minus the old base pointer.
+	SUBQ b_base+8(FP), CX
+	MOVQ CX, ret+32(FP)
+
+	RET

+ 76 - 0
vendor/github.com/cespare/xxhash/v2/xxhash_other.go

@@ -0,0 +1,76 @@
+// +build !amd64 appengine !gc purego
+
+package xxhash
+
+// Sum64 computes the 64-bit xxHash digest of b.
+func Sum64(b []byte) uint64 {
+	// A simpler version would be
+	//   d := New()
+	//   d.Write(b)
+	//   return d.Sum64()
+	// but this is faster, particularly for small inputs.
+
+	n := len(b)
+	var h uint64
+
+	if n >= 32 {
+		v1 := prime1v + prime2
+		v2 := prime2
+		v3 := uint64(0)
+		v4 := -prime1v
+		for len(b) >= 32 {
+			v1 = round(v1, u64(b[0:8:len(b)]))
+			v2 = round(v2, u64(b[8:16:len(b)]))
+			v3 = round(v3, u64(b[16:24:len(b)]))
+			v4 = round(v4, u64(b[24:32:len(b)]))
+			b = b[32:len(b):len(b)]
+		}
+		h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
+		h = mergeRound(h, v1)
+		h = mergeRound(h, v2)
+		h = mergeRound(h, v3)
+		h = mergeRound(h, v4)
+	} else {
+		h = prime5
+	}
+
+	h += uint64(n)
+
+	i, end := 0, len(b)
+	for ; i+8 <= end; i += 8 {
+		k1 := round(0, u64(b[i:i+8:len(b)]))
+		h ^= k1
+		h = rol27(h)*prime1 + prime4
+	}
+	if i+4 <= end {
+		h ^= uint64(u32(b[i:i+4:len(b)])) * prime1
+		h = rol23(h)*prime2 + prime3
+		i += 4
+	}
+	for ; i < end; i++ {
+		h ^= uint64(b[i]) * prime5
+		h = rol11(h) * prime1
+	}
+
+	h ^= h >> 33
+	h *= prime2
+	h ^= h >> 29
+	h *= prime3
+	h ^= h >> 32
+
+	return h
+}
+
+func writeBlocks(d *Digest, b []byte) int {
+	v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
+	n := len(b)
+	for len(b) >= 32 {
+		v1 = round(v1, u64(b[0:8:len(b)]))
+		v2 = round(v2, u64(b[8:16:len(b)]))
+		v3 = round(v3, u64(b[16:24:len(b)]))
+		v4 = round(v4, u64(b[24:32:len(b)]))
+		b = b[32:len(b):len(b)]
+	}
+	d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4
+	return n - len(b)
+}

+ 15 - 0
vendor/github.com/cespare/xxhash/v2/xxhash_safe.go

@@ -0,0 +1,15 @@
+// +build appengine
+
+// This file contains the safe implementations of otherwise unsafe-using code.
+
+package xxhash
+
+// Sum64String computes the 64-bit xxHash digest of s.
+func Sum64String(s string) uint64 {
+	return Sum64([]byte(s))
+}
+
+// WriteString adds more data to d. It always returns len(s), nil.
+func (d *Digest) WriteString(s string) (n int, err error) {
+	return d.Write([]byte(s))
+}

+ 46 - 0
vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go

@@ -0,0 +1,46 @@
+// +build !appengine
+
+// This file encapsulates usage of unsafe.
+// xxhash_safe.go contains the safe implementations.
+
+package xxhash
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+// Notes:
+//
+// See https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/tcZYBzQqAQAJ
+// for some discussion about these unsafe conversions.
+//
+// In the future it's possible that compiler optimizations will make these
+// unsafe operations unnecessary: https://golang.org/issue/2205.
+//
+// Both of these wrapper functions still incur function call overhead since they
+// will not be inlined. We could write Go/asm copies of Sum64 and Digest.Write
+// for strings to squeeze out a bit more speed. Mid-stack inlining should
+// eventually fix this.
+
+// Sum64String computes the 64-bit xxHash digest of s.
+// It may be faster than Sum64([]byte(s)) by avoiding a copy.
+func Sum64String(s string) uint64 {
+	var b []byte
+	bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
+	bh.Len = len(s)
+	bh.Cap = len(s)
+	return Sum64(b)
+}
+
+// WriteString adds more data to d. It always returns len(s), nil.
+// It may be faster than Write([]byte(s)) by avoiding a copy.
+func (d *Digest) WriteString(s string) (n int, err error) {
+	var b []byte
+	bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
+	bh.Len = len(s)
+	bh.Cap = len(s)
+	return d.Write(b)
+}

+ 26 - 0
vendor/github.com/gin-contrib/sse/.travis.yml

@@ -0,0 +1,26 @@
+language: go
+sudo: false
+go:
+  - 1.8.x
+  - 1.9.x
+  - 1.10.x
+  - 1.11.x
+  - 1.12.x
+  - master
+
+git:
+  depth: 10
+
+matrix:
+  fast_finish: true
+  include:
+  - go: 1.11.x
+    env: GO111MODULE=on
+  - go: 1.12.x
+    env: GO111MODULE=on
+
+script:
+  - go test -v -covermode=count -coverprofile=coverage.out
+
+after_success:
+  - bash <(curl -s https://codecov.io/bash)

+ 21 - 0
vendor/github.com/gin-contrib/sse/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Manuel Martínez-Almeida
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 58 - 0
vendor/github.com/gin-contrib/sse/README.md

@@ -0,0 +1,58 @@
+# Server-Sent Events
+
+[![GoDoc](https://godoc.org/github.com/gin-contrib/sse?status.svg)](https://godoc.org/github.com/gin-contrib/sse)
+[![Build Status](https://travis-ci.org/gin-contrib/sse.svg)](https://travis-ci.org/gin-contrib/sse)
+[![codecov](https://codecov.io/gh/gin-contrib/sse/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-contrib/sse)
+[![Go Report Card](https://goreportcard.com/badge/github.com/gin-contrib/sse)](https://goreportcard.com/report/github.com/gin-contrib/sse)
+
+Server-sent events (SSE) is a technology where a browser receives automatic updates from a server via HTTP connection. The Server-Sent Events EventSource API is [standardized as part of HTML5[1] by the W3C](http://www.w3.org/TR/2009/WD-eventsource-20091029/).
+
+- [Read this great SSE introduction by the HTML5Rocks guys](http://www.html5rocks.com/en/tutorials/eventsource/basics/)
+- [Browser support](http://caniuse.com/#feat=eventsource)
+
+## Sample code
+
+```go
+import "github.com/gin-contrib/sse"
+
+func httpHandler(w http.ResponseWriter, req *http.Request) {
+	// data can be a primitive like a string, an integer or a float
+	sse.Encode(w, sse.Event{
+		Event: "message",
+		Data:  "some data\nmore data",
+	})
+
+	// also a complex type, like a map, a struct or a slice
+	sse.Encode(w, sse.Event{
+		Id:    "124",
+		Event: "message",
+		Data: map[string]interface{}{
+			"user":    "manu",
+			"date":    time.Now().Unix(),
+			"content": "hi!",
+		},
+	})
+}
+```
+```
+event: message
+data: some data\\nmore data
+
+id: 124
+event: message
+data: {"content":"hi!","date":1431540810,"user":"manu"}
+ 
+```
+
+## Content-Type
+
+```go
+fmt.Println(sse.ContentType)
+```
+```
+text/event-stream
+```
+
+## Decoding support
+
+There is a client-side implementation of SSE coming soon.

+ 5 - 0
vendor/github.com/gin-contrib/sse/go.mod

@@ -0,0 +1,5 @@
+module github.com/gin-contrib/sse
+
+go 1.12
+
+require github.com/stretchr/testify v1.3.0

+ 7 - 0
vendor/github.com/gin-contrib/sse/go.sum

@@ -0,0 +1,7 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

+ 116 - 0
vendor/github.com/gin-contrib/sse/sse-decoder.go

@@ -0,0 +1,116 @@
+// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
+// Use of this source code is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package sse
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+)
+
+type decoder struct {
+	events []Event
+}
+
+func Decode(r io.Reader) ([]Event, error) {
+	var dec decoder
+	return dec.decode(r)
+}
+
+func (d *decoder) dispatchEvent(event Event, data string) {
+	dataLength := len(data)
+	if dataLength > 0 {
+		//If the data buffer's last character is a U+000A LINE FEED (LF) character, then remove the last character from the data buffer.
+		data = data[:dataLength-1]
+		dataLength--
+	}
+	if dataLength == 0 && event.Event == "" {
+		return
+	}
+	if event.Event == "" {
+		event.Event = "message"
+	}
+	event.Data = data
+	d.events = append(d.events, event)
+}
+
+func (d *decoder) decode(r io.Reader) ([]Event, error) {
+	buf, err := ioutil.ReadAll(r)
+	if err != nil {
+		return nil, err
+	}
+
+	var currentEvent Event
+	var dataBuffer *bytes.Buffer = new(bytes.Buffer)
+	// TODO (and unit tests)
+	// Lines must be separated by either a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair,
+	// a single U+000A LINE FEED (LF) character,
+	// or a single U+000D CARRIAGE RETURN (CR) character.
+	lines := bytes.Split(buf, []byte{'\n'})
+	for _, line := range lines {
+		if len(line) == 0 {
+			// If the line is empty (a blank line). Dispatch the event.
+			d.dispatchEvent(currentEvent, dataBuffer.String())
+
+			// reset current event and data buffer
+			currentEvent = Event{}
+			dataBuffer.Reset()
+			continue
+		}
+		if line[0] == byte(':') {
+			// If the line starts with a U+003A COLON character (:), ignore the line.
+			continue
+		}
+
+		var field, value []byte
+		colonIndex := bytes.IndexRune(line, ':')
+		if colonIndex != -1 {
+			// If the line contains a U+003A COLON character character (:)
+			// Collect the characters on the line before the first U+003A COLON character (:),
+			// and let field be that string.
+			field = line[:colonIndex]
+			// Collect the characters on the line after the first U+003A COLON character (:),
+			// and let value be that string.
+			value = line[colonIndex+1:]
+			// If value starts with a single U+0020 SPACE character, remove it from value.
+			if len(value) > 0 && value[0] == ' ' {
+				value = value[1:]
+			}
+		} else {
+			// Otherwise, the string is not empty but does not contain a U+003A COLON character character (:)
+			// Use the whole line as the field name, and the empty string as the field value.
+			field = line
+			value = []byte{}
+		}
+		// The steps to process the field given a field name and a field value depend on the field name,
+		// as given in the following list. Field names must be compared literally,
+		// with no case folding performed.
+		switch string(field) {
+		case "event":
+			// Set the event name buffer to field value.
+			currentEvent.Event = string(value)
+		case "id":
+			// Set the event stream's last event ID to the field value.
+			currentEvent.Id = string(value)
+		case "retry":
+			// If the field value consists of only characters in the range U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9),
+			// then interpret the field value as an integer in base ten, and set the event stream's reconnection time to that integer.
+			// Otherwise, ignore the field.
+			currentEvent.Id = string(value)
+		case "data":
+			// Append the field value to the data buffer,
+			dataBuffer.Write(value)
+			// then append a single U+000A LINE FEED (LF) character to the data buffer.
+			dataBuffer.WriteString("\n")
+		default:
+			//Otherwise. The field is ignored.
+			continue
+		}
+	}
+	// Once the end of the file is reached, the user agent must dispatch the event one final time.
+	d.dispatchEvent(currentEvent, dataBuffer.String())
+
+	return d.events, nil
+}

+ 110 - 0
vendor/github.com/gin-contrib/sse/sse-encoder.go

@@ -0,0 +1,110 @@
+// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
+// Use of this source code is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package sse
+
+import (
+	"encoding/json"
+	"fmt"
+	"io"
+	"net/http"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// Server-Sent Events
+// W3C Working Draft 29 October 2009
+// http://www.w3.org/TR/2009/WD-eventsource-20091029/
+
+const ContentType = "text/event-stream"
+
+var contentType = []string{ContentType}
+var noCache = []string{"no-cache"}
+
+var fieldReplacer = strings.NewReplacer(
+	"\n", "\\n",
+	"\r", "\\r")
+
+var dataReplacer = strings.NewReplacer(
+	"\n", "\ndata:",
+	"\r", "\\r")
+
+type Event struct {
+	Event string
+	Id    string
+	Retry uint
+	Data  interface{}
+}
+
+func Encode(writer io.Writer, event Event) error {
+	w := checkWriter(writer)
+	writeId(w, event.Id)
+	writeEvent(w, event.Event)
+	writeRetry(w, event.Retry)
+	return writeData(w, event.Data)
+}
+
+func writeId(w stringWriter, id string) {
+	if len(id) > 0 {
+		w.WriteString("id:")
+		fieldReplacer.WriteString(w, id)
+		w.WriteString("\n")
+	}
+}
+
+func writeEvent(w stringWriter, event string) {
+	if len(event) > 0 {
+		w.WriteString("event:")
+		fieldReplacer.WriteString(w, event)
+		w.WriteString("\n")
+	}
+}
+
+func writeRetry(w stringWriter, retry uint) {
+	if retry > 0 {
+		w.WriteString("retry:")
+		w.WriteString(strconv.FormatUint(uint64(retry), 10))
+		w.WriteString("\n")
+	}
+}
+
+func writeData(w stringWriter, data interface{}) error {
+	w.WriteString("data:")
+	switch kindOfData(data) {
+	case reflect.Struct, reflect.Slice, reflect.Map:
+		err := json.NewEncoder(w).Encode(data)
+		if err != nil {
+			return err
+		}
+		w.WriteString("\n")
+	default:
+		dataReplacer.WriteString(w, fmt.Sprint(data))
+		w.WriteString("\n\n")
+	}
+	return nil
+}
+
+func (r Event) Render(w http.ResponseWriter) error {
+	r.WriteContentType(w)
+	return Encode(w, r)
+}
+
+func (r Event) WriteContentType(w http.ResponseWriter) {
+	header := w.Header()
+	header["Content-Type"] = contentType
+
+	if _, exist := header["Cache-Control"]; !exist {
+		header["Cache-Control"] = noCache
+	}
+}
+
+func kindOfData(data interface{}) reflect.Kind {
+	value := reflect.ValueOf(data)
+	valueType := value.Kind()
+	if valueType == reflect.Ptr {
+		valueType = value.Elem().Kind()
+	}
+	return valueType
+}

+ 24 - 0
vendor/github.com/gin-contrib/sse/writer.go

@@ -0,0 +1,24 @@
+package sse
+
+import "io"
+
+type stringWriter interface {
+	io.Writer
+	WriteString(string) (int, error)
+}
+
+type stringWrapper struct {
+	io.Writer
+}
+
+func (w stringWrapper) WriteString(str string) (int, error) {
+	return w.Writer.Write([]byte(str))
+}
+
+func checkWriter(writer io.Writer) stringWriter {
+	if w, ok := writer.(stringWriter); ok {
+		return w
+	} else {
+		return stringWrapper{writer}
+	}
+}

+ 7 - 0
vendor/github.com/gin-gonic/gin/.gitignore

@@ -0,0 +1,7 @@
+vendor/*
+!vendor/vendor.json
+coverage.out
+count.out
+test
+profile.out
+tmp.out

+ 42 - 0
vendor/github.com/gin-gonic/gin/.travis.yml

@@ -0,0 +1,42 @@
+language: go
+
+matrix:
+  fast_finish: true
+  include:
+  - go: 1.10.x
+  - go: 1.11.x
+    env: GO111MODULE=on
+  - go: 1.12.x
+    env: GO111MODULE=on
+  - go: 1.13.x