Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Newdigate <andrew@troupe.co>2017-06-12 17:11:09 +0300
committerAndrew Newdigate <andrew@troupe.co>2017-06-12 17:11:09 +0300
commita61cd57bbbf42d2e7bcb9ffdcadf159f31a32e94 (patch)
tree9fc6913ba7ea74b9f51dc855d8e828c8d5f74cee
parent3a0f99f97f03d262eb84ea939ab5e8dc7bd6dda3 (diff)
parente8f0485c7ac1afd2aeb2568fdc477162dc56f852 (diff)
Merge branch 'master' of gitlab.com:gitlab-org/gitaly into makefile-tidy
# Conflicts: # NOTICE
-rw-r--r--CHANGELOG.md9
-rw-r--r--Makefile2
-rw-r--r--NOTICE204
-rw-r--r--VERSION2
-rw-r--r--cmd/gitaly/main.go60
-rw-r--r--internal/config/logger.go6
-rw-r--r--internal/helper/fieldextractors/repository.go37
-rw-r--r--internal/service/middleware/loghandler/loghandler.go70
-rw-r--r--internal/service/middleware/sentryhandler/sentryhandler.go62
-rw-r--r--vendor/github.com/golang/protobuf/jsonpb/jsonpb.go1059
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go382
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/struct/struct.proto96
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/DOC.md164
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE (renamed from vendor/github.com/mwitkow/go-grpc-middleware/LICENSE)0
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md86
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go143
-rwxr-xr-xvendor/github.com/grpc-ecosystem/go-grpc-middleware/checkup.sh21
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go (renamed from vendor/github.com/mwitkow/go-grpc-middleware/doc.go)0
-rwxr-xr-xvendor/github.com/grpc-ecosystem/go-grpc-middleware/fixup.sh36
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/DOC.md74
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/README.md74
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/common.go26
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/doc.go33
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/DOC.md300
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/README.md300
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/client_interceptors.go65
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/context.go34
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/doc.go22
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/grpclogger.go15
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/noop.go16
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/options.go176
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/payload_interceptors.go147
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/server_interceptors.go105
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/DOC.md157
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/README.md157
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/context.go49
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/doc.go21
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/fieldextractor.go85
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/interceptors.go80
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/options.go32
-rwxr-xr-xvendor/github.com/grpc-ecosystem/go-grpc-middleware/test_all.sh14
-rw-r--r--vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go (renamed from vendor/github.com/mwitkow/go-grpc-middleware/wrappers.go)0
-rw-r--r--vendor/github.com/mwitkow/go-grpc-middleware/README.MD63
-rw-r--r--vendor/github.com/mwitkow/go-grpc-middleware/chain.go103
-rw-r--r--vendor/github.com/mwitkow/go-grpc-middleware/doc.md171
-rw-r--r--vendor/vendor.json42
46 files changed, 4160 insertions, 640 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b1986211..916bf728d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Gitaly changelog
+v0.11.2
+
+Skipping 0.11.1 intentionally, we messed up the tag.
+
+- Add context to structured logging messages
+ https://gitlab.com/gitlab-org/gitaly/merge_requests/184
+- Fix incorrect dependency in Makefile
+ https://gitlab.com/gitlab-org/gitaly/merge_requests/189
+
v0.11.0
- FindDefaultBranchName: decorate error
diff --git a/Makefile b/Makefile
index 5a0ff43b2..74eaf2fe9 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ ${BUILD_DIR}/_build:
tar -cf - --exclude _build --exclude .git . | (cd $@/src/${PKG} && tar -xf -)
touch $@
-build: clean-build ${BUILD_DIR}/_build $(shell find . -name '*.go' -not -path './vendor/*')
+build: clean-build ${BUILD_DIR}/_build $(shell find . -name '*.go' -not -path './vendor/*' -not -path './_build/*')
rm -f -- "${BIN_BUILD_DIR}/*"
go install -ldflags "-X main.version=${VERSION}" ${PKG}/cmd/...
cp ${BIN_BUILD_DIR}/* ${BUILD_DIR}/
diff --git a/NOTICE b/NOTICE
index 16b064573..f24a42935 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,6 +1,5 @@
The following components are included in Gitaly:
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LICENSE - go
Copyright (c) 2009 The Go Authors. All rights reserved.
@@ -53,6 +52,7 @@ implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LICENSE - gitlab.com/gitlab-org/gitaly
The MIT License (MIT)
@@ -878,208 +878,6 @@ LICENSE - gitlab.com/gitlab-org/gitaly/vendor/github.com/matttproud/golang_proto
NOTICE - gitlab.com/gitlab-org/gitaly/vendor/github.com/matttproud/golang_protobuf_extensions
Copyright 2012 Matt T. Proud (matt.proud@gmail.com)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LICENSE - gitlab.com/gitlab-org/gitaly/vendor/github.com/mwitkow/go-grpc-middleware
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LICENSE - gitlab.com/gitlab-org/gitaly/vendor/github.com/pmezard/go-difflib
Copyright (c) 2013, Patrick Mezard
All rights reserved.
diff --git a/VERSION b/VERSION
index d9df1bbc0..bc859cbd6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.11.0
+0.11.2
diff --git a/cmd/gitaly/main.go b/cmd/gitaly/main.go
index 3a2e9062f..5cc140e1e 100644
--- a/cmd/gitaly/main.go
+++ b/cmd/gitaly/main.go
@@ -10,17 +10,19 @@ import (
"gitlab.com/gitlab-org/gitaly/internal/config"
"gitlab.com/gitlab-org/gitaly/internal/connectioncounter"
+ "gitlab.com/gitlab-org/gitaly/internal/helper/fieldextractors"
"gitlab.com/gitlab-org/gitaly/internal/service"
- "gitlab.com/gitlab-org/gitaly/internal/service/middleware/loghandler"
"gitlab.com/gitlab-org/gitaly/internal/service/middleware/panichandler"
+ "gitlab.com/gitlab-org/gitaly/internal/service/middleware/sentryhandler"
+ "github.com/grpc-ecosystem/go-grpc-middleware"
+ "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
+ "github.com/grpc-ecosystem/go-grpc-middleware/tags"
"github.com/grpc-ecosystem/go-grpc-prometheus"
- "github.com/mwitkow/go-grpc-middleware"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
- "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/reflection"
)
@@ -74,6 +76,39 @@ func registerServerVersionPromGauge() {
gitlabBuildInfoGauge.Set(1)
}
+func newGRPCServer() *grpc.Server {
+ logrusEntry := log.NewEntry(log.StandardLogger())
+ grpc_logrus.ReplaceGrpcLogger(logrusEntry)
+
+ ctxTagOpts := []grpc_ctxtags.Option{
+ grpc_ctxtags.WithFieldExtractor(fieldextractors.RepositoryFieldExtractor),
+ }
+
+ server := grpc.NewServer(
+ grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
+ grpc_ctxtags.StreamServerInterceptor(ctxTagOpts...),
+ grpc_prometheus.StreamServerInterceptor,
+ grpc_logrus.StreamServerInterceptor(logrusEntry),
+ sentryhandler.StreamLogHandler,
+ panichandler.StreamPanicHandler, // Panic handler should remain last
+ )),
+ grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
+ grpc_ctxtags.UnaryServerInterceptor(ctxTagOpts...),
+ grpc_prometheus.UnaryServerInterceptor,
+ grpc_logrus.UnaryServerInterceptor(logrusEntry),
+ sentryhandler.UnaryLogHandler,
+ panichandler.UnaryPanicHandler, // Panic handler should remain last
+ )),
+ )
+
+ service.RegisterAll(server)
+ reflection.Register(server)
+
+ grpc_prometheus.Register(server)
+
+ return server
+}
+
func main() {
log.WithField("version", version).Info("Starting Gitaly")
registerServerVersionPromGauge()
@@ -85,7 +120,6 @@ func main() {
}
config.ConfigureLogging()
- grpclog.SetLogger(log.StandardLogger())
config.ConfigureSentry(version)
config.ConfigurePrometheus()
@@ -110,23 +144,7 @@ func main() {
listeners = append(listeners, connectioncounter.New("tcp", l))
}
- server := grpc.NewServer(
- grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
- loghandler.StreamLogHandler,
- grpc_prometheus.StreamServerInterceptor,
- panichandler.StreamPanicHandler, // Panic handler should remain last
- )),
- grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
- loghandler.UnaryLogHandler,
- grpc_prometheus.UnaryServerInterceptor,
- panichandler.UnaryPanicHandler, // Panic handler should remain last
- )),
- )
-
- service.RegisterAll(server)
- reflection.Register(server)
-
- grpc_prometheus.Register(server)
+ server := newGRPCServer()
serverError := make(chan error, len(listeners))
for _, listener := range listeners {
diff --git a/internal/config/logger.go b/internal/config/logger.go
index e6159e619..af675e38d 100644
--- a/internal/config/logger.go
+++ b/internal/config/logger.go
@@ -6,6 +6,10 @@ import (
log "github.com/Sirupsen/logrus"
)
+var (
+ debugLoggingEnabled = os.Getenv("GITALY_DEBUG") == "1"
+)
+
func init() {
// This ensures that any log statements that occur before
// the configuration has been loaded will be written to
@@ -28,7 +32,7 @@ func configureLoggingFormat() {
// ConfigureLogging uses the global conf and environmental vars to configure the logged
func ConfigureLogging() {
- if os.Getenv("GITALY_DEBUG") != "1" {
+ if debugLoggingEnabled {
log.SetLevel(log.DebugLevel)
} else {
log.SetLevel(log.InfoLevel)
diff --git a/internal/helper/fieldextractors/repository.go b/internal/helper/fieldextractors/repository.go
new file mode 100644
index 000000000..582a647d1
--- /dev/null
+++ b/internal/helper/fieldextractors/repository.go
@@ -0,0 +1,37 @@
+package fieldextractors
+
+import pb "gitlab.com/gitlab-org/gitaly-proto/go"
+
+func formatRepoRequest(repo *pb.Repository) map[string]interface{} {
+ if repo == nil {
+ // Signals that the client did not send a repo through, which
+ // will be useful for logging
+ return map[string]interface{}{
+ "repo": nil,
+ }
+ }
+
+ return map[string]interface{}{
+ "repoStorage": repo.StorageName,
+ "repoPath": repo.RelativePath,
+ }
+}
+
+type repositoryBasedRequest interface {
+ GetRepository() *pb.Repository
+}
+
+// RepositoryFieldExtractor will extract the repository fields from an incoming grpc request
+func RepositoryFieldExtractor(fullMethod string, req interface{}) map[string]interface{} {
+ if req == nil {
+ return nil
+ }
+
+ if repoReq, ok := req.(repositoryBasedRequest); ok {
+ return formatRepoRequest(repoReq.GetRepository())
+ }
+
+ // Add other request handlers here in future
+ return nil
+
+}
diff --git a/internal/service/middleware/loghandler/loghandler.go b/internal/service/middleware/loghandler/loghandler.go
deleted file mode 100644
index 73cc632d1..000000000
--- a/internal/service/middleware/loghandler/loghandler.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package loghandler
-
-import (
- "time"
-
- log "github.com/Sirupsen/logrus"
- raven "github.com/getsentry/raven-go"
-
- "math"
-
- "golang.org/x/net/context"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
-)
-
-// UnaryLogHandler handles access times and errors for unary RPC's
-func UnaryLogHandler(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
- start := time.Now()
- resp, err := handler(ctx, req)
- logRequest(info.FullMethod, start, err)
- return resp, err
-}
-
-// StreamLogHandler handles access times and errors for stream RPC's
-func StreamLogHandler(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
- start := time.Now()
- err := handler(srv, stream)
- logRequest(info.FullMethod, start, err)
- return err
-}
-
-func roundPositive(value float64) float64 {
- return math.Floor(value + 0.5)
-}
-
-// durationInSecondsRoundedToMilliseconds returns a duration, in seconds with a maximum resolution of a microsecond
-func durationInSecondsRoundedToMilliseconds(d time.Duration) float64 {
- return roundPositive(d.Seconds()*1e6) / 1e6
-}
-
-func logGrpcError(method string, err error) {
- grpcErrorCode := grpc.Code(err)
-
- if grpcErrorCode == codes.OK {
- return
- }
-
- raven.CaptureError(err, map[string]string{
- "grpcMethod": method,
- "code": grpcErrorCode.String(),
- }, nil)
-}
-
-func logRequest(method string, start time.Time, err error) {
- duration := durationInSecondsRoundedToMilliseconds(time.Since(start))
- fields := log.Fields{
- "method": method,
- "duration": duration,
- }
-
- if err != nil {
- grpcErrorCode := grpc.Code(err)
- fields["error"] = err
- fields["code"] = grpcErrorCode.String()
-
- logGrpcError(method, err)
- }
-
- log.WithFields(fields).Info("access")
-}
diff --git a/internal/service/middleware/sentryhandler/sentryhandler.go b/internal/service/middleware/sentryhandler/sentryhandler.go
new file mode 100644
index 000000000..f33f8ff4f
--- /dev/null
+++ b/internal/service/middleware/sentryhandler/sentryhandler.go
@@ -0,0 +1,62 @@
+package sentryhandler
+
+import (
+ "time"
+
+ raven "github.com/getsentry/raven-go"
+ "github.com/grpc-ecosystem/go-grpc-middleware/tags"
+
+ "fmt"
+
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+)
+
+// UnaryLogHandler handles access times and errors for unary RPC's
+func UnaryLogHandler(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ start := time.Now()
+ resp, err := handler(ctx, req)
+
+ if err != nil {
+ logGrpcErrorToSentry(ctx, info.FullMethod, start, err)
+ }
+
+ return resp, err
+}
+
+// StreamLogHandler handles access times and errors for stream RPC's
+func StreamLogHandler(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ start := time.Now()
+ err := handler(srv, stream)
+
+ if err != nil {
+ logGrpcErrorToSentry(stream.Context(), info.FullMethod, start, err)
+ }
+
+ return err
+}
+
+func stringMap(incoming map[string]interface{}) map[string]string {
+ result := make(map[string]string)
+ for i, v := range incoming {
+ result[i] = fmt.Sprintf("%v", v)
+ }
+ return result
+}
+
+func logGrpcErrorToSentry(ctx context.Context, method string, start time.Time, err error) {
+ grpcErrorCode := grpc.Code(err)
+
+ if grpcErrorCode == codes.OK {
+ return
+ }
+
+ tags := grpc_ctxtags.Extract(ctx)
+ ravenDetails := stringMap(tags.Values())
+ ravenDetails["grpc.code"] = grpcErrorCode.String()
+ ravenDetails["grpc.method"] = method
+ ravenDetails["system"] = "grpc"
+
+ raven.CaptureError(err, ravenDetails, nil)
+}
diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
new file mode 100644
index 000000000..c7a45d6f0
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go
@@ -0,0 +1,1059 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2015 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON.
+It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json.
+
+This package produces a different output than the standard "encoding/json" package,
+which does not operate correctly on protocol buffers.
+*/
+package jsonpb
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+
+ stpb "github.com/golang/protobuf/ptypes/struct"
+)
+
+// Marshaler is a configurable object for converting between
+// protocol buffer objects and a JSON representation for them.
+type Marshaler struct {
+ // Whether to render enum values as integers, as opposed to string values.
+ EnumsAsInts bool
+
+ // Whether to render fields with zero values.
+ EmitDefaults bool
+
+ // A string to indent each level by. The presence of this field will
+ // also cause a space to appear between the field separator and
+ // value, and for newlines to be appear between fields and array
+ // elements.
+ Indent string
+
+ // Whether to use the original (.proto) name for fields.
+ OrigName bool
+}
+
+// JSONPBMarshaler is implemented by protobuf messages that customize the
+// way they are marshaled to JSON. Messages that implement this should
+// also implement JSONPBUnmarshaler so that the custom format can be
+// parsed.
+type JSONPBMarshaler interface {
+ MarshalJSONPB(*Marshaler) ([]byte, error)
+}
+
+// JSONPBUnmarshaler is implemented by protobuf messages that customize
+// the way they are unmarshaled from JSON. Messages that implement this
+// should also implement JSONPBMarshaler so that the custom format can be
+// produced.
+type JSONPBUnmarshaler interface {
+ UnmarshalJSONPB(*Unmarshaler, []byte) error
+}
+
+// Marshal marshals a protocol buffer into JSON.
+func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
+ writer := &errWriter{writer: out}
+ return m.marshalObject(writer, pb, "", "")
+}
+
+// MarshalToString converts a protocol buffer object to JSON string.
+func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) {
+ var buf bytes.Buffer
+ if err := m.Marshal(&buf, pb); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+}
+
+type int32Slice []int32
+
+var nonFinite = map[string]float64{
+ `"NaN"`: math.NaN(),
+ `"Infinity"`: math.Inf(1),
+ `"-Infinity"`: math.Inf(-1),
+}
+
+// For sorting extensions ids to ensure stable output.
+func (s int32Slice) Len() int { return len(s) }
+func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
+func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+type wkt interface {
+ XXX_WellKnownType() string
+}
+
+// marshalObject writes a struct to the Writer.
+func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error {
+ if jsm, ok := v.(JSONPBMarshaler); ok {
+ b, err := jsm.MarshalJSONPB(m)
+ if err != nil {
+ return err
+ }
+ if typeURL != "" {
+ // we are marshaling this object to an Any type
+ var js map[string]*json.RawMessage
+ if err = json.Unmarshal(b, &js); err != nil {
+ return fmt.Errorf("type %T produced invalid JSON: %v", v, err)
+ }
+ turl, err := json.Marshal(typeURL)
+ if err != nil {
+ return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
+ }
+ js["@type"] = (*json.RawMessage)(&turl)
+ if b, err = json.Marshal(js); err != nil {
+ return err
+ }
+ }
+
+ out.write(string(b))
+ return out.err
+ }
+
+ s := reflect.ValueOf(v).Elem()
+
+ // Handle well-known types.
+ if wkt, ok := v.(wkt); ok {
+ switch wkt.XXX_WellKnownType() {
+ case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
+ "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
+ // "Wrappers use the same representation in JSON
+ // as the wrapped primitive type, ..."
+ sprop := proto.GetProperties(s.Type())
+ return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent)
+ case "Any":
+ // Any is a bit more involved.
+ return m.marshalAny(out, v, indent)
+ case "Duration":
+ // "Generated output always contains 3, 6, or 9 fractional digits,
+ // depending on required precision."
+ s, ns := s.Field(0).Int(), s.Field(1).Int()
+ d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond
+ x := fmt.Sprintf("%.9f", d.Seconds())
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, "000")
+ out.write(`"`)
+ out.write(x)
+ out.write(`s"`)
+ return out.err
+ case "Struct", "ListValue":
+ // Let marshalValue handle the `Struct.fields` map or the `ListValue.values` slice.
+ // TODO: pass the correct Properties if needed.
+ return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent)
+ case "Timestamp":
+ // "RFC 3339, where generated output will always be Z-normalized
+ // and uses 3, 6 or 9 fractional digits."
+ s, ns := s.Field(0).Int(), s.Field(1).Int()
+ t := time.Unix(s, ns).UTC()
+ // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
+ x := t.Format("2006-01-02T15:04:05.000000000")
+ x = strings.TrimSuffix(x, "000")
+ x = strings.TrimSuffix(x, "000")
+ out.write(`"`)
+ out.write(x)
+ out.write(`Z"`)
+ return out.err
+ case "Value":
+ // Value has a single oneof.
+ kind := s.Field(0)
+ if kind.IsNil() {
+ // "absence of any variant indicates an error"
+ return errors.New("nil Value")
+ }
+ // oneof -> *T -> T -> T.F
+ x := kind.Elem().Elem().Field(0)
+ // TODO: pass the correct Properties if needed.
+ return m.marshalValue(out, &proto.Properties{}, x, indent)
+ }
+ }
+
+ out.write("{")
+ if m.Indent != "" {
+ out.write("\n")
+ }
+
+ firstField := true
+
+ if typeURL != "" {
+ if err := m.marshalTypeURL(out, indent, typeURL); err != nil {
+ return err
+ }
+ firstField = false
+ }
+
+ for i := 0; i < s.NumField(); i++ {
+ value := s.Field(i)
+ valueField := s.Type().Field(i)
+ if strings.HasPrefix(valueField.Name, "XXX_") {
+ continue
+ }
+
+ // IsNil will panic on most value kinds.
+ switch value.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface:
+ if value.IsNil() {
+ continue
+ }
+ }
+
+ if !m.EmitDefaults {
+ switch value.Kind() {
+ case reflect.Bool:
+ if !value.Bool() {
+ continue
+ }
+ case reflect.Int32, reflect.Int64:
+ if value.Int() == 0 {
+ continue
+ }
+ case reflect.Uint32, reflect.Uint64:
+ if value.Uint() == 0 {
+ continue
+ }
+ case reflect.Float32, reflect.Float64:
+ if value.Float() == 0 {
+ continue
+ }
+ case reflect.String:
+ if value.Len() == 0 {
+ continue
+ }
+ case reflect.Map, reflect.Ptr, reflect.Slice:
+ if value.IsNil() {
+ continue
+ }
+ }
+ }
+
+ // Oneof fields need special handling.
+ if valueField.Tag.Get("protobuf_oneof") != "" {
+ // value is an interface containing &T{real_value}.
+ sv := value.Elem().Elem() // interface -> *T -> T
+ value = sv.Field(0)
+ valueField = sv.Type().Field(0)
+ }
+ prop := jsonProperties(valueField, m.OrigName)
+ if !firstField {
+ m.writeSep(out)
+ }
+ if err := m.marshalField(out, prop, value, indent); err != nil {
+ return err
+ }
+ firstField = false
+ }
+
+ // Handle proto2 extensions.
+ if ep, ok := v.(proto.Message); ok {
+ extensions := proto.RegisteredExtensions(v)
+ // Sort extensions for stable output.
+ ids := make([]int32, 0, len(extensions))
+ for id, desc := range extensions {
+ if !proto.HasExtension(ep, desc) {
+ continue
+ }
+ ids = append(ids, id)
+ }
+ sort.Sort(int32Slice(ids))
+ for _, id := range ids {
+ desc := extensions[id]
+ if desc == nil {
+ // unknown extension
+ continue
+ }
+ ext, extErr := proto.GetExtension(ep, desc)
+ if extErr != nil {
+ return extErr
+ }
+ value := reflect.ValueOf(ext)
+ var prop proto.Properties
+ prop.Parse(desc.Tag)
+ prop.JSONName = fmt.Sprintf("[%s]", desc.Name)
+ if !firstField {
+ m.writeSep(out)
+ }
+ if err := m.marshalField(out, &prop, value, indent); err != nil {
+ return err
+ }
+ firstField = false
+ }
+
+ }
+
+ if m.Indent != "" {
+ out.write("\n")
+ out.write(indent)
+ }
+ out.write("}")
+ return out.err
+}
+
+func (m *Marshaler) writeSep(out *errWriter) {
+ if m.Indent != "" {
+ out.write(",\n")
+ } else {
+ out.write(",")
+ }
+}
+
+func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error {
+ // "If the Any contains a value that has a special JSON mapping,
+ // it will be converted as follows: {"@type": xxx, "value": yyy}.
+ // Otherwise, the value will be converted into a JSON object,
+ // and the "@type" field will be inserted to indicate the actual data type."
+ v := reflect.ValueOf(any).Elem()
+ turl := v.Field(0).String()
+ val := v.Field(1).Bytes()
+
+ // Only the part of type_url after the last slash is relevant.
+ mname := turl
+ if slash := strings.LastIndex(mname, "/"); slash >= 0 {
+ mname = mname[slash+1:]
+ }
+ mt := proto.MessageType(mname)
+ if mt == nil {
+ return fmt.Errorf("unknown message type %q", mname)
+ }
+ msg := reflect.New(mt.Elem()).Interface().(proto.Message)
+ if err := proto.Unmarshal(val, msg); err != nil {
+ return err
+ }
+
+ if _, ok := msg.(wkt); ok {
+ out.write("{")
+ if m.Indent != "" {
+ out.write("\n")
+ }
+ if err := m.marshalTypeURL(out, indent, turl); err != nil {
+ return err
+ }
+ m.writeSep(out)
+ if m.Indent != "" {
+ out.write(indent)
+ out.write(m.Indent)
+ out.write(`"value": `)
+ } else {
+ out.write(`"value":`)
+ }
+ if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil {
+ return err
+ }
+ if m.Indent != "" {
+ out.write("\n")
+ out.write(indent)
+ }
+ out.write("}")
+ return out.err
+ }
+
+ return m.marshalObject(out, msg, indent, turl)
+}
+
+func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error {
+ if m.Indent != "" {
+ out.write(indent)
+ out.write(m.Indent)
+ }
+ out.write(`"@type":`)
+ if m.Indent != "" {
+ out.write(" ")
+ }
+ b, err := json.Marshal(typeURL)
+ if err != nil {
+ return err
+ }
+ out.write(string(b))
+ return out.err
+}
+
+// marshalField writes field description and value to the Writer.
+func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
+ if m.Indent != "" {
+ out.write(indent)
+ out.write(m.Indent)
+ }
+ out.write(`"`)
+ out.write(prop.JSONName)
+ out.write(`":`)
+ if m.Indent != "" {
+ out.write(" ")
+ }
+ if err := m.marshalValue(out, prop, v, indent); err != nil {
+ return err
+ }
+ return nil
+}
+
+// marshalValue writes the value to the Writer.
+func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error {
+ var err error
+ v = reflect.Indirect(v)
+
+ // Handle nil pointer
+ if v.Kind() == reflect.Invalid {
+ out.write("null")
+ return out.err
+ }
+
+ // Handle repeated elements.
+ if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
+ out.write("[")
+ comma := ""
+ for i := 0; i < v.Len(); i++ {
+ sliceVal := v.Index(i)
+ out.write(comma)
+ if m.Indent != "" {
+ out.write("\n")
+ out.write(indent)
+ out.write(m.Indent)
+ out.write(m.Indent)
+ }
+ if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil {
+ return err
+ }
+ comma = ","
+ }
+ if m.Indent != "" {
+ out.write("\n")
+ out.write(indent)
+ out.write(m.Indent)
+ }
+ out.write("]")
+ return out.err
+ }
+
+ // Handle well-known types.
+ // Most are handled up in marshalObject (because 99% are messages).
+ if wkt, ok := v.Interface().(wkt); ok {
+ switch wkt.XXX_WellKnownType() {
+ case "NullValue":
+ out.write("null")
+ return out.err
+ }
+ }
+
+ // Handle enumerations.
+ if !m.EnumsAsInts && prop.Enum != "" {
+ // Unknown enum values will are stringified by the proto library as their
+ // value. Such values should _not_ be quoted or they will be interpreted
+ // as an enum string instead of their value.
+ enumStr := v.Interface().(fmt.Stringer).String()
+ var valStr string
+ if v.Kind() == reflect.Ptr {
+ valStr = strconv.Itoa(int(v.Elem().Int()))
+ } else {
+ valStr = strconv.Itoa(int(v.Int()))
+ }
+ isKnownEnum := enumStr != valStr
+ if isKnownEnum {
+ out.write(`"`)
+ }
+ out.write(enumStr)
+ if isKnownEnum {
+ out.write(`"`)
+ }
+ return out.err
+ }
+
+ // Handle nested messages.
+ if v.Kind() == reflect.Struct {
+ return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent, "")
+ }
+
+ // Handle maps.
+ // Since Go randomizes map iteration, we sort keys for stable output.
+ if v.Kind() == reflect.Map {
+ out.write(`{`)
+ keys := v.MapKeys()
+ sort.Sort(mapKeys(keys))
+ for i, k := range keys {
+ if i > 0 {
+ out.write(`,`)
+ }
+ if m.Indent != "" {
+ out.write("\n")
+ out.write(indent)
+ out.write(m.Indent)
+ out.write(m.Indent)
+ }
+
+ b, err := json.Marshal(k.Interface())
+ if err != nil {
+ return err
+ }
+ s := string(b)
+
+ // If the JSON is not a string value, encode it again to make it one.
+ if !strings.HasPrefix(s, `"`) {
+ b, err := json.Marshal(s)
+ if err != nil {
+ return err
+ }
+ s = string(b)
+ }
+
+ out.write(s)
+ out.write(`:`)
+ if m.Indent != "" {
+ out.write(` `)
+ }
+
+ if err := m.marshalValue(out, prop, v.MapIndex(k), indent+m.Indent); err != nil {
+ return err
+ }
+ }
+ if m.Indent != "" {
+ out.write("\n")
+ out.write(indent)
+ out.write(m.Indent)
+ }
+ out.write(`}`)
+ return out.err
+ }
+
+ // Handle non-finite floats, e.g. NaN, Infinity and -Infinity.
+ if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
+ f := v.Float()
+ var sval string
+ switch {
+ case math.IsInf(f, 1):
+ sval = `"Infinity"`
+ case math.IsInf(f, -1):
+ sval = `"-Infinity"`
+ case math.IsNaN(f):
+ sval = `"NaN"`
+ }
+ if sval != "" {
+ out.write(sval)
+ return out.err
+ }
+ }
+
+ // Default handling defers to the encoding/json library.
+ b, err := json.Marshal(v.Interface())
+ if err != nil {
+ return err
+ }
+ needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64)
+ if needToQuote {
+ out.write(`"`)
+ }
+ out.write(string(b))
+ if needToQuote {
+ out.write(`"`)
+ }
+ return out.err
+}
+
+// Unmarshaler is a configurable object for converting from a JSON
+// representation to a protocol buffer object.
+type Unmarshaler struct {
+ // Whether to allow messages to contain unknown fields, as opposed to
+ // failing to unmarshal.
+ AllowUnknownFields bool
+}
+
+// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
+// This function is lenient and will decode any options permutations of the
+// related Marshaler.
+func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
+ inputValue := json.RawMessage{}
+ if err := dec.Decode(&inputValue); err != nil {
+ return err
+ }
+ return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil)
+}
+
+// Unmarshal unmarshals a JSON object stream into a protocol
+// buffer. This function is lenient and will decode any options
+// permutations of the related Marshaler.
+func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error {
+ dec := json.NewDecoder(r)
+ return u.UnmarshalNext(dec, pb)
+}
+
+// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
+// This function is lenient and will decode any options permutations of the
+// related Marshaler.
+func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
+ return new(Unmarshaler).UnmarshalNext(dec, pb)
+}
+
+// Unmarshal unmarshals a JSON object stream into a protocol
+// buffer. This function is lenient and will decode any options
+// permutations of the related Marshaler.
+func Unmarshal(r io.Reader, pb proto.Message) error {
+ return new(Unmarshaler).Unmarshal(r, pb)
+}
+
+// UnmarshalString will populate the fields of a protocol buffer based
+// on a JSON string. This function is lenient and will decode any options
+// permutations of the related Marshaler.
+func UnmarshalString(str string, pb proto.Message) error {
+ return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb)
+}
+
+// unmarshalValue converts/copies a value into the target.
+// prop may be nil.
+func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error {
+ targetType := target.Type()
+
+ // Allocate memory for pointer fields.
+ if targetType.Kind() == reflect.Ptr {
+ target.Set(reflect.New(targetType.Elem()))
+ return u.unmarshalValue(target.Elem(), inputValue, prop)
+ }
+
+ if jsu, ok := target.Addr().Interface().(JSONPBUnmarshaler); ok {
+ return jsu.UnmarshalJSONPB(u, []byte(inputValue))
+ }
+
+ // Handle well-known types.
+ if w, ok := target.Addr().Interface().(wkt); ok {
+ switch w.XXX_WellKnownType() {
+ case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value",
+ "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue":
+ // "Wrappers use the same representation in JSON
+ // as the wrapped primitive type, except that null is allowed."
+ // encoding/json will turn JSON `null` into Go `nil`,
+ // so we don't have to do any extra work.
+ return u.unmarshalValue(target.Field(0), inputValue, prop)
+ case "Any":
+ // Use json.RawMessage pointer type instead of value to support pre-1.8 version.
+ // 1.8 changed RawMessage.MarshalJSON from pointer type to value type, see
+ // https://github.com/golang/go/issues/14493
+ var jsonFields map[string]*json.RawMessage
+ if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
+ return err
+ }
+
+ val, ok := jsonFields["@type"]
+ if !ok || val == nil {
+ return errors.New("Any JSON doesn't have '@type'")
+ }
+
+ var turl string
+ if err := json.Unmarshal([]byte(*val), &turl); err != nil {
+ return fmt.Errorf("can't unmarshal Any's '@type': %q", *val)
+ }
+ target.Field(0).SetString(turl)
+
+ mname := turl
+ if slash := strings.LastIndex(mname, "/"); slash >= 0 {
+ mname = mname[slash+1:]
+ }
+ mt := proto.MessageType(mname)
+ if mt == nil {
+ return fmt.Errorf("unknown message type %q", mname)
+ }
+
+ m := reflect.New(mt.Elem()).Interface().(proto.Message)
+ if _, ok := m.(wkt); ok {
+ val, ok := jsonFields["value"]
+ if !ok {
+ return errors.New("Any JSON doesn't have 'value'")
+ }
+
+ if err := u.unmarshalValue(reflect.ValueOf(m).Elem(), *val, nil); err != nil {
+ return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err)
+ }
+ } else {
+ delete(jsonFields, "@type")
+ nestedProto, err := json.Marshal(jsonFields)
+ if err != nil {
+ return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err)
+ }
+
+ if err = u.unmarshalValue(reflect.ValueOf(m).Elem(), nestedProto, nil); err != nil {
+ return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err)
+ }
+ }
+
+ b, err := proto.Marshal(m)
+ if err != nil {
+ return fmt.Errorf("can't marshal proto %T into Any.Value: %v", m, err)
+ }
+ target.Field(1).SetBytes(b)
+
+ return nil
+ case "Duration":
+ ivStr := string(inputValue)
+ if ivStr == "null" {
+ target.Field(0).SetInt(0)
+ target.Field(1).SetInt(0)
+ return nil
+ }
+
+ unq, err := strconv.Unquote(ivStr)
+ if err != nil {
+ return err
+ }
+ d, err := time.ParseDuration(unq)
+ if err != nil {
+ return fmt.Errorf("bad Duration: %v", err)
+ }
+ ns := d.Nanoseconds()
+ s := ns / 1e9
+ ns %= 1e9
+ target.Field(0).SetInt(s)
+ target.Field(1).SetInt(ns)
+ return nil
+ case "Timestamp":
+ ivStr := string(inputValue)
+ if ivStr == "null" {
+ target.Field(0).SetInt(0)
+ target.Field(1).SetInt(0)
+ return nil
+ }
+
+ unq, err := strconv.Unquote(ivStr)
+ if err != nil {
+ return err
+ }
+ t, err := time.Parse(time.RFC3339Nano, unq)
+ if err != nil {
+ return fmt.Errorf("bad Timestamp: %v", err)
+ }
+ target.Field(0).SetInt(int64(t.Unix()))
+ target.Field(1).SetInt(int64(t.Nanosecond()))
+ return nil
+ case "Struct":
+ if string(inputValue) == "null" {
+ // Interpret a null struct as empty.
+ return nil
+ }
+ var m map[string]json.RawMessage
+ if err := json.Unmarshal(inputValue, &m); err != nil {
+ return fmt.Errorf("bad StructValue: %v", err)
+ }
+ target.Field(0).Set(reflect.ValueOf(map[string]*stpb.Value{}))
+ for k, jv := range m {
+ pv := &stpb.Value{}
+ if err := u.unmarshalValue(reflect.ValueOf(pv).Elem(), jv, prop); err != nil {
+ return fmt.Errorf("bad value in StructValue for key %q: %v", k, err)
+ }
+ target.Field(0).SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(pv))
+ }
+ return nil
+ case "ListValue":
+ if string(inputValue) == "null" {
+ // Interpret a null ListValue as empty.
+ return nil
+ }
+ var s []json.RawMessage
+ if err := json.Unmarshal(inputValue, &s); err != nil {
+ return fmt.Errorf("bad ListValue: %v", err)
+ }
+ target.Field(0).Set(reflect.ValueOf(make([]*stpb.Value, len(s), len(s))))
+ for i, sv := range s {
+ if err := u.unmarshalValue(target.Field(0).Index(i), sv, prop); err != nil {
+ return err
+ }
+ }
+ return nil
+ case "Value":
+ ivStr := string(inputValue)
+ if ivStr == "null" {
+ target.Field(0).Set(reflect.ValueOf(&stpb.Value_NullValue{}))
+ } else if v, err := strconv.ParseFloat(ivStr, 0); err == nil {
+ target.Field(0).Set(reflect.ValueOf(&stpb.Value_NumberValue{v}))
+ } else if v, err := strconv.Unquote(ivStr); err == nil {
+ target.Field(0).Set(reflect.ValueOf(&stpb.Value_StringValue{v}))
+ } else if v, err := strconv.ParseBool(ivStr); err == nil {
+ target.Field(0).Set(reflect.ValueOf(&stpb.Value_BoolValue{v}))
+ } else if err := json.Unmarshal(inputValue, &[]json.RawMessage{}); err == nil {
+ lv := &stpb.ListValue{}
+ target.Field(0).Set(reflect.ValueOf(&stpb.Value_ListValue{lv}))
+ return u.unmarshalValue(reflect.ValueOf(lv).Elem(), inputValue, prop)
+ } else if err := json.Unmarshal(inputValue, &map[string]json.RawMessage{}); err == nil {
+ sv := &stpb.Struct{}
+ target.Field(0).Set(reflect.ValueOf(&stpb.Value_StructValue{sv}))
+ return u.unmarshalValue(reflect.ValueOf(sv).Elem(), inputValue, prop)
+ } else {
+ return fmt.Errorf("unrecognized type for Value %q", ivStr)
+ }
+ return nil
+ }
+ }
+
+ // Handle enums, which have an underlying type of int32,
+ // and may appear as strings.
+ // The case of an enum appearing as a number is handled
+ // at the bottom of this function.
+ if inputValue[0] == '"' && prop != nil && prop.Enum != "" {
+ vmap := proto.EnumValueMap(prop.Enum)
+ // Don't need to do unquoting; valid enum names
+ // are from a limited character set.
+ s := inputValue[1 : len(inputValue)-1]
+ n, ok := vmap[string(s)]
+ if !ok {
+ return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum)
+ }
+ if target.Kind() == reflect.Ptr { // proto2
+ target.Set(reflect.New(targetType.Elem()))
+ target = target.Elem()
+ }
+ target.SetInt(int64(n))
+ return nil
+ }
+
+ // Handle nested messages.
+ if targetType.Kind() == reflect.Struct {
+ var jsonFields map[string]json.RawMessage
+ if err := json.Unmarshal(inputValue, &jsonFields); err != nil {
+ return err
+ }
+
+ consumeField := func(prop *proto.Properties) (json.RawMessage, bool) {
+ // Be liberal in what names we accept; both orig_name and camelName are okay.
+ fieldNames := acceptedJSONFieldNames(prop)
+
+ vOrig, okOrig := jsonFields[fieldNames.orig]
+ vCamel, okCamel := jsonFields[fieldNames.camel]
+ if !okOrig && !okCamel {
+ return nil, false
+ }
+ // If, for some reason, both are present in the data, favour the camelName.
+ var raw json.RawMessage
+ if okOrig {
+ raw = vOrig
+ delete(jsonFields, fieldNames.orig)
+ }
+ if okCamel {
+ raw = vCamel
+ delete(jsonFields, fieldNames.camel)
+ }
+ return raw, true
+ }
+
+ sprops := proto.GetProperties(targetType)
+ for i := 0; i < target.NumField(); i++ {
+ ft := target.Type().Field(i)
+ if strings.HasPrefix(ft.Name, "XXX_") {
+ continue
+ }
+
+ valueForField, ok := consumeField(sprops.Prop[i])
+ if !ok {
+ continue
+ }
+
+ if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil {
+ return err
+ }
+ }
+ // Check for any oneof fields.
+ if len(jsonFields) > 0 {
+ for _, oop := range sprops.OneofTypes {
+ raw, ok := consumeField(oop.Prop)
+ if !ok {
+ continue
+ }
+ nv := reflect.New(oop.Type.Elem())
+ target.Field(oop.Field).Set(nv)
+ if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {
+ return err
+ }
+ }
+ }
+ // Handle proto2 extensions.
+ if len(jsonFields) > 0 {
+ if ep, ok := target.Addr().Interface().(proto.Message); ok {
+ for _, ext := range proto.RegisteredExtensions(ep) {
+ name := fmt.Sprintf("[%s]", ext.Name)
+ raw, ok := jsonFields[name]
+ if !ok {
+ continue
+ }
+ delete(jsonFields, name)
+ nv := reflect.New(reflect.TypeOf(ext.ExtensionType).Elem())
+ if err := u.unmarshalValue(nv.Elem(), raw, nil); err != nil {
+ return err
+ }
+ if err := proto.SetExtension(ep, ext, nv.Interface()); err != nil {
+ return err
+ }
+ }
+ }
+ }
+ if !u.AllowUnknownFields && len(jsonFields) > 0 {
+ // Pick any field to be the scapegoat.
+ var f string
+ for fname := range jsonFields {
+ f = fname
+ break
+ }
+ return fmt.Errorf("unknown field %q in %v", f, targetType)
+ }
+ return nil
+ }
+
+ // Handle arrays (which aren't encoded bytes)
+ if targetType.Kind() == reflect.Slice && targetType.Elem().Kind() != reflect.Uint8 {
+ var slc []json.RawMessage
+ if err := json.Unmarshal(inputValue, &slc); err != nil {
+ return err
+ }
+ len := len(slc)
+ target.Set(reflect.MakeSlice(targetType, len, len))
+ for i := 0; i < len; i++ {
+ if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ // Handle maps (whose keys are always strings)
+ if targetType.Kind() == reflect.Map {
+ var mp map[string]json.RawMessage
+ if err := json.Unmarshal(inputValue, &mp); err != nil {
+ return err
+ }
+ target.Set(reflect.MakeMap(targetType))
+ var keyprop, valprop *proto.Properties
+ if prop != nil {
+ // These could still be nil if the protobuf metadata is broken somehow.
+ // TODO: This won't work because the fields are unexported.
+ // We should probably just reparse them.
+ //keyprop, valprop = prop.mkeyprop, prop.mvalprop
+ }
+ for ks, raw := range mp {
+ // Unmarshal map key. The core json library already decoded the key into a
+ // string, so we handle that specially. Other types were quoted post-serialization.
+ var k reflect.Value
+ if targetType.Key().Kind() == reflect.String {
+ k = reflect.ValueOf(ks)
+ } else {
+ k = reflect.New(targetType.Key()).Elem()
+ if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil {
+ return err
+ }
+ }
+
+ // Unmarshal map value.
+ v := reflect.New(targetType.Elem()).Elem()
+ if err := u.unmarshalValue(v, raw, valprop); err != nil {
+ return err
+ }
+ target.SetMapIndex(k, v)
+ }
+ return nil
+ }
+
+ // 64-bit integers can be encoded as strings. In this case we drop
+ // the quotes and proceed as normal.
+ isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64
+ if isNum && strings.HasPrefix(string(inputValue), `"`) {
+ inputValue = inputValue[1 : len(inputValue)-1]
+ }
+
+ // Non-finite numbers can be encoded as strings.
+ isFloat := targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64
+ if isFloat {
+ if num, ok := nonFinite[string(inputValue)]; ok {
+ target.SetFloat(num)
+ return nil
+ }
+ }
+
+ // Use the encoding/json for parsing other value types.
+ return json.Unmarshal(inputValue, target.Addr().Interface())
+}
+
+// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute.
+func jsonProperties(f reflect.StructField, origName bool) *proto.Properties {
+ var prop proto.Properties
+ prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
+ if origName || prop.JSONName == "" {
+ prop.JSONName = prop.OrigName
+ }
+ return &prop
+}
+
+type fieldNames struct {
+ orig, camel string
+}
+
+func acceptedJSONFieldNames(prop *proto.Properties) fieldNames {
+ opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName}
+ if prop.JSONName != "" {
+ opts.camel = prop.JSONName
+ }
+ return opts
+}
+
+// Writer wrapper inspired by https://blog.golang.org/errors-are-values
+type errWriter struct {
+ writer io.Writer
+ err error
+}
+
+func (w *errWriter) write(str string) {
+ if w.err != nil {
+ return
+ }
+ _, w.err = w.writer.Write([]byte(str))
+}
+
+// Map fields may have key types of non-float scalars, strings and enums.
+// The easiest way to sort them in some deterministic order is to use fmt.
+// If this turns out to be inefficient we can always consider other options,
+// such as doing a Schwartzian transform.
+//
+// Numeric keys are sorted in numeric order per
+// https://developers.google.com/protocol-buffers/docs/proto#maps.
+type mapKeys []reflect.Value
+
+func (s mapKeys) Len() int { return len(s) }
+func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s mapKeys) Less(i, j int) bool {
+ if k := s[i].Kind(); k == s[j].Kind() {
+ switch k {
+ case reflect.Int32, reflect.Int64:
+ return s[i].Int() < s[j].Int()
+ case reflect.Uint32, reflect.Uint64:
+ return s[i].Uint() < s[j].Uint()
+ }
+ }
+ return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface())
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go
new file mode 100644
index 000000000..35a8ec599
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go
@@ -0,0 +1,382 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: github.com/golang/protobuf/ptypes/struct/struct.proto
+
+/*
+Package structpb is a generated protocol buffer package.
+
+It is generated from these files:
+ github.com/golang/protobuf/ptypes/struct/struct.proto
+
+It has these top-level messages:
+ Struct
+ Value
+ ListValue
+*/
+package structpb
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+// The JSON representation for `NullValue` is JSON `null`.
+type NullValue int32
+
+const (
+ // Null value.
+ NullValue_NULL_VALUE NullValue = 0
+)
+
+var NullValue_name = map[int32]string{
+ 0: "NULL_VALUE",
+}
+var NullValue_value = map[string]int32{
+ "NULL_VALUE": 0,
+}
+
+func (x NullValue) String() string {
+ return proto.EnumName(NullValue_name, int32(x))
+}
+func (NullValue) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+func (NullValue) XXX_WellKnownType() string { return "NullValue" }
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
+type Struct struct {
+ // Unordered map of dynamically typed values.
+ Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+}
+
+func (m *Struct) Reset() { *m = Struct{} }
+func (m *Struct) String() string { return proto.CompactTextString(m) }
+func (*Struct) ProtoMessage() {}
+func (*Struct) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+func (*Struct) XXX_WellKnownType() string { return "Struct" }
+
+func (m *Struct) GetFields() map[string]*Value {
+ if m != nil {
+ return m.Fields
+ }
+ return nil
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
+type Value struct {
+ // The kind of value.
+ //
+ // Types that are valid to be assigned to Kind:
+ // *Value_NullValue
+ // *Value_NumberValue
+ // *Value_StringValue
+ // *Value_BoolValue
+ // *Value_StructValue
+ // *Value_ListValue
+ Kind isValue_Kind `protobuf_oneof:"kind"`
+}
+
+func (m *Value) Reset() { *m = Value{} }
+func (m *Value) String() string { return proto.CompactTextString(m) }
+func (*Value) ProtoMessage() {}
+func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+func (*Value) XXX_WellKnownType() string { return "Value" }
+
+type isValue_Kind interface {
+ isValue_Kind()
+}
+
+type Value_NullValue struct {
+ NullValue NullValue `protobuf:"varint,1,opt,name=null_value,json=nullValue,enum=google.protobuf.NullValue,oneof"`
+}
+type Value_NumberValue struct {
+ NumberValue float64 `protobuf:"fixed64,2,opt,name=number_value,json=numberValue,oneof"`
+}
+type Value_StringValue struct {
+ StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,oneof"`
+}
+type Value_BoolValue struct {
+ BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,oneof"`
+}
+type Value_StructValue struct {
+ StructValue *Struct `protobuf:"bytes,5,opt,name=struct_value,json=structValue,oneof"`
+}
+type Value_ListValue struct {
+ ListValue *ListValue `protobuf:"bytes,6,opt,name=list_value,json=listValue,oneof"`
+}
+
+func (*Value_NullValue) isValue_Kind() {}
+func (*Value_NumberValue) isValue_Kind() {}
+func (*Value_StringValue) isValue_Kind() {}
+func (*Value_BoolValue) isValue_Kind() {}
+func (*Value_StructValue) isValue_Kind() {}
+func (*Value_ListValue) isValue_Kind() {}
+
+func (m *Value) GetKind() isValue_Kind {
+ if m != nil {
+ return m.Kind
+ }
+ return nil
+}
+
+func (m *Value) GetNullValue() NullValue {
+ if x, ok := m.GetKind().(*Value_NullValue); ok {
+ return x.NullValue
+ }
+ return NullValue_NULL_VALUE
+}
+
+func (m *Value) GetNumberValue() float64 {
+ if x, ok := m.GetKind().(*Value_NumberValue); ok {
+ return x.NumberValue
+ }
+ return 0
+}
+
+func (m *Value) GetStringValue() string {
+ if x, ok := m.GetKind().(*Value_StringValue); ok {
+ return x.StringValue
+ }
+ return ""
+}
+
+func (m *Value) GetBoolValue() bool {
+ if x, ok := m.GetKind().(*Value_BoolValue); ok {
+ return x.BoolValue
+ }
+ return false
+}
+
+func (m *Value) GetStructValue() *Struct {
+ if x, ok := m.GetKind().(*Value_StructValue); ok {
+ return x.StructValue
+ }
+ return nil
+}
+
+func (m *Value) GetListValue() *ListValue {
+ if x, ok := m.GetKind().(*Value_ListValue); ok {
+ return x.ListValue
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*Value) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _Value_OneofMarshaler, _Value_OneofUnmarshaler, _Value_OneofSizer, []interface{}{
+ (*Value_NullValue)(nil),
+ (*Value_NumberValue)(nil),
+ (*Value_StringValue)(nil),
+ (*Value_BoolValue)(nil),
+ (*Value_StructValue)(nil),
+ (*Value_ListValue)(nil),
+ }
+}
+
+func _Value_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*Value)
+ // kind
+ switch x := m.Kind.(type) {
+ case *Value_NullValue:
+ b.EncodeVarint(1<<3 | proto.WireVarint)
+ b.EncodeVarint(uint64(x.NullValue))
+ case *Value_NumberValue:
+ b.EncodeVarint(2<<3 | proto.WireFixed64)
+ b.EncodeFixed64(math.Float64bits(x.NumberValue))
+ case *Value_StringValue:
+ b.EncodeVarint(3<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.StringValue)
+ case *Value_BoolValue:
+ t := uint64(0)
+ if x.BoolValue {
+ t = 1
+ }
+ b.EncodeVarint(4<<3 | proto.WireVarint)
+ b.EncodeVarint(t)
+ case *Value_StructValue:
+ b.EncodeVarint(5<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.StructValue); err != nil {
+ return err
+ }
+ case *Value_ListValue:
+ b.EncodeVarint(6<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ListValue); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("Value.Kind has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _Value_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*Value)
+ switch tag {
+ case 1: // kind.null_value
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Kind = &Value_NullValue{NullValue(x)}
+ return true, err
+ case 2: // kind.number_value
+ if wire != proto.WireFixed64 {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeFixed64()
+ m.Kind = &Value_NumberValue{math.Float64frombits(x)}
+ return true, err
+ case 3: // kind.string_value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Kind = &Value_StringValue{x}
+ return true, err
+ case 4: // kind.bool_value
+ if wire != proto.WireVarint {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeVarint()
+ m.Kind = &Value_BoolValue{x != 0}
+ return true, err
+ case 5: // kind.struct_value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(Struct)
+ err := b.DecodeMessage(msg)
+ m.Kind = &Value_StructValue{msg}
+ return true, err
+ case 6: // kind.list_value
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(ListValue)
+ err := b.DecodeMessage(msg)
+ m.Kind = &Value_ListValue{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _Value_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*Value)
+ // kind
+ switch x := m.Kind.(type) {
+ case *Value_NullValue:
+ n += proto.SizeVarint(1<<3 | proto.WireVarint)
+ n += proto.SizeVarint(uint64(x.NullValue))
+ case *Value_NumberValue:
+ n += proto.SizeVarint(2<<3 | proto.WireFixed64)
+ n += 8
+ case *Value_StringValue:
+ n += proto.SizeVarint(3<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(len(x.StringValue)))
+ n += len(x.StringValue)
+ case *Value_BoolValue:
+ n += proto.SizeVarint(4<<3 | proto.WireVarint)
+ n += 1
+ case *Value_StructValue:
+ s := proto.Size(x.StructValue)
+ n += proto.SizeVarint(5<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *Value_ListValue:
+ s := proto.Size(x.ListValue)
+ n += proto.SizeVarint(6<<3 | proto.WireBytes)
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
+type ListValue struct {
+ // Repeated field of dynamically typed values.
+ Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"`
+}
+
+func (m *ListValue) Reset() { *m = ListValue{} }
+func (m *ListValue) String() string { return proto.CompactTextString(m) }
+func (*ListValue) ProtoMessage() {}
+func (*ListValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+func (*ListValue) XXX_WellKnownType() string { return "ListValue" }
+
+func (m *ListValue) GetValues() []*Value {
+ if m != nil {
+ return m.Values
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Struct)(nil), "google.protobuf.Struct")
+ proto.RegisterType((*Value)(nil), "google.protobuf.Value")
+ proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue")
+ proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value)
+}
+
+func init() {
+ proto.RegisterFile("github.com/golang/protobuf/ptypes/struct/struct.proto", fileDescriptor0)
+}
+
+var fileDescriptor0 = []byte{
+ // 417 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x8b, 0xd3, 0x40,
+ 0x14, 0x80, 0x3b, 0xc9, 0x36, 0x98, 0x17, 0x59, 0x97, 0x11, 0xb4, 0xac, 0xa0, 0xa1, 0x7b, 0x09,
+ 0x22, 0x09, 0x56, 0x04, 0x31, 0x5e, 0x0c, 0xac, 0xbb, 0x60, 0x58, 0x62, 0x74, 0x57, 0xf0, 0x52,
+ 0x9a, 0x34, 0x8d, 0xa1, 0xd3, 0x99, 0x90, 0xcc, 0x28, 0x3d, 0xfa, 0x2f, 0x3c, 0x7b, 0xf4, 0xe8,
+ 0xaf, 0xf3, 0x28, 0x33, 0x93, 0x44, 0x69, 0x29, 0x78, 0x9a, 0xbe, 0x37, 0xdf, 0xfb, 0xe6, 0xbd,
+ 0xd7, 0xc0, 0xf3, 0xb2, 0xe2, 0x9f, 0x45, 0xe6, 0xe7, 0x6c, 0x13, 0x94, 0x8c, 0x2c, 0x68, 0x19,
+ 0xd4, 0x0d, 0xe3, 0x2c, 0x13, 0xab, 0xa0, 0xe6, 0xdb, 0xba, 0x68, 0x83, 0x96, 0x37, 0x22, 0xe7,
+ 0xdd, 0xe1, 0xab, 0x5b, 0x7c, 0xa7, 0x64, 0xac, 0x24, 0x85, 0xdf, 0xb3, 0xd3, 0xef, 0x08, 0xac,
+ 0xf7, 0x8a, 0xc0, 0x21, 0x58, 0xab, 0xaa, 0x20, 0xcb, 0x76, 0x82, 0x5c, 0xd3, 0x73, 0x66, 0x67,
+ 0xfe, 0x0e, 0xec, 0x6b, 0xd0, 0x7f, 0xa3, 0xa8, 0x73, 0xca, 0x9b, 0x6d, 0xda, 0x95, 0x9c, 0xbe,
+ 0x03, 0xe7, 0x9f, 0x34, 0x3e, 0x01, 0x73, 0x5d, 0x6c, 0x27, 0xc8, 0x45, 0x9e, 0x9d, 0xca, 0x9f,
+ 0xf8, 0x09, 0x8c, 0xbf, 0x2c, 0x88, 0x28, 0x26, 0x86, 0x8b, 0x3c, 0x67, 0x76, 0x6f, 0x4f, 0x7e,
+ 0x23, 0x6f, 0x53, 0x0d, 0xbd, 0x34, 0x5e, 0xa0, 0xe9, 0x2f, 0x03, 0xc6, 0x2a, 0x89, 0x43, 0x00,
+ 0x2a, 0x08, 0x99, 0x6b, 0x81, 0x94, 0x1e, 0xcf, 0x4e, 0xf7, 0x04, 0x57, 0x82, 0x10, 0xc5, 0x5f,
+ 0x8e, 0x52, 0x9b, 0xf6, 0x01, 0x3e, 0x83, 0xdb, 0x54, 0x6c, 0xb2, 0xa2, 0x99, 0xff, 0x7d, 0x1f,
+ 0x5d, 0x8e, 0x52, 0x47, 0x67, 0x07, 0xa8, 0xe5, 0x4d, 0x45, 0xcb, 0x0e, 0x32, 0x65, 0xe3, 0x12,
+ 0xd2, 0x59, 0x0d, 0x3d, 0x02, 0xc8, 0x18, 0xeb, 0xdb, 0x38, 0x72, 0x91, 0x77, 0x4b, 0x3e, 0x25,
+ 0x73, 0x1a, 0x78, 0xa5, 0x2c, 0x22, 0xe7, 0x1d, 0x32, 0x56, 0xa3, 0xde, 0x3f, 0xb0, 0xc7, 0x4e,
+ 0x2f, 0x72, 0x3e, 0x4c, 0x49, 0xaa, 0xb6, 0xaf, 0xb5, 0x54, 0xed, 0xfe, 0x94, 0x71, 0xd5, 0xf2,
+ 0x61, 0x4a, 0xd2, 0x07, 0x91, 0x05, 0x47, 0xeb, 0x8a, 0x2e, 0xa7, 0x21, 0xd8, 0x03, 0x81, 0x7d,
+ 0xb0, 0x94, 0xac, 0xff, 0x47, 0x0f, 0x2d, 0xbd, 0xa3, 0x1e, 0x3f, 0x00, 0x7b, 0x58, 0x22, 0x3e,
+ 0x06, 0xb8, 0xba, 0x8e, 0xe3, 0xf9, 0xcd, 0xeb, 0xf8, 0xfa, 0xfc, 0x64, 0x14, 0x7d, 0x43, 0x70,
+ 0x37, 0x67, 0x9b, 0x5d, 0x45, 0xe4, 0xe8, 0x69, 0x12, 0x19, 0x27, 0xe8, 0xd3, 0xd3, 0xff, 0xfd,
+ 0x30, 0x43, 0x7d, 0xd4, 0xd9, 0x6f, 0x84, 0x7e, 0x18, 0xe6, 0x45, 0x12, 0xfd, 0x34, 0x1e, 0x5e,
+ 0x68, 0x79, 0xd2, 0xf7, 0xf7, 0xb1, 0x20, 0xe4, 0x2d, 0x65, 0x5f, 0xe9, 0x07, 0x59, 0x99, 0x59,
+ 0x4a, 0xf5, 0xec, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x6e, 0x5d, 0x3c, 0xfe, 0x02, 0x00,
+ 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto b/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto
new file mode 100644
index 000000000..7d7808e7f
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto
@@ -0,0 +1,96 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "StructProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+//
+// The JSON representation for `Struct` is JSON object.
+message Struct {
+ // Unordered map of dynamically typed values.
+ map<string, Value> fields = 1;
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+//
+// The JSON representation for `Value` is JSON value.
+message Value {
+ // The kind of value.
+ oneof kind {
+ // Represents a null value.
+ NullValue null_value = 1;
+ // Represents a double value.
+ double number_value = 2;
+ // Represents a string value.
+ string string_value = 3;
+ // Represents a boolean value.
+ bool bool_value = 4;
+ // Represents a structured value.
+ Struct struct_value = 5;
+ // Represents a repeated `Value`.
+ ListValue list_value = 6;
+ }
+}
+
+// `NullValue` is a singleton enumeration to represent the null value for the
+// `Value` type union.
+//
+// The JSON representation for `NullValue` is JSON `null`.
+enum NullValue {
+ // Null value.
+ NULL_VALUE = 0;
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+//
+// The JSON representation for `ListValue` is JSON array.
+message ListValue {
+ // Repeated field of dynamically typed values.
+ repeated Value values = 1;
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/DOC.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/DOC.md
new file mode 100644
index 000000000..a06d61fdb
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/DOC.md
@@ -0,0 +1,164 @@
+# grpc_middleware
+`import "github.com/grpc-ecosystem/go-grpc-middleware"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+
+## <a name="pkg-overview">Overview</a>
+`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
+
+### Middleware
+gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
+upstream gRPC codebase is relatively bare bones.
+
+This package, and most of its child packages provides commonly needed middleware for gRPC:
+client-side interceptors for retires, server-side interceptors for input validation and auth,
+functions for chaining said interceptors, metadata convenience methods and more.
+
+### Chaining
+By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
+the server side. `grpc_middleware` provides convenient chaining methods
+
+Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
+server chaining:
+
+ myServer := grpc.NewServer(
+ grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
+ grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
+ )
+
+These interceptors will be executed from left to right: logging, monitoring and auth.
+
+Here's an example for client side chaining:
+
+ clientConn, err = grpc.Dial(
+ address,
+ grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
+ grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
+ )
+ client = pb_testproto.NewTestServiceClient(clientConn)
+ resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
+
+These interceptors will be executed from left to right: monitoring and then retry logic.
+
+### Writing Your Own
+Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
+bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
+For example, you may want to pass the identity of the caller from the auth interceptor all the way
+to the handling function.
+
+For example, a client side interceptor example for auth looks like:
+
+ func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ newCtx := context.WithValue(ctx, "user_id", "john@example.com")
+ return handler(newCtx, req)
+ }
+
+Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
+the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
+needed. For example:
+
+ func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ newStream := grpc_middleware.WrapServerStream(stream)
+ newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
+ return handler(srv, stream)
+ }
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+
+## <a name="pkg-index">Index</a>
+* [func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor](#ChainStreamClient)
+* [func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor](#ChainStreamServer)
+* [func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor](#ChainUnaryClient)
+* [func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor](#ChainUnaryServer)
+* [func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption](#WithStreamServerChain)
+* [func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption](#WithUnaryServerChain)
+* [type WrappedServerStream](#WrappedServerStream)
+ * [func WrapServerStream(stream grpc.ServerStream) \*WrappedServerStream](#WrapServerStream)
+ * [func (w \*WrappedServerStream) Context() context.Context](#WrappedServerStream.Context)
+
+#### <a name="pkg-files">Package files</a>
+[chain.go](./chain.go) [doc.go](./doc.go) [wrappers.go](./wrappers.go)
+
+## <a name="ChainStreamClient">func</a> [ChainStreamClient](./chain.go#L106)
+``` go
+func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor
+```
+ChainStreamClient creates a single interceptor out of a chain of many interceptors.
+
+Execution is done in left-to-right order, including passing of context.
+For example ChainStreamClient(one, two, three) will execute one before two before three.
+
+## <a name="ChainStreamServer">func</a> [ChainStreamServer](./chain.go#L48)
+``` go
+func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor
+```
+ChainStreamServer creates a single interceptor out of a chain of many interceptors.
+
+Execution is done in left-to-right order, including passing of context.
+For example ChainUnaryServer(one, two, three) will execute one before two before three.
+If you want to pass context between interceptors, use WrapServerStream.
+
+## <a name="ChainUnaryClient">func</a> [ChainUnaryClient](./chain.go#L77)
+``` go
+func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor
+```
+ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
+
+Execution is done in left-to-right order, including passing of context.
+For example ChainUnaryClient(one, two, three) will execute one before two before three.
+
+## <a name="ChainUnaryServer">func</a> [ChainUnaryServer](./chain.go#L18)
+``` go
+func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor
+```
+ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
+
+Execution is done in left-to-right order, including passing of context.
+For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
+will see context changes of one and two.
+
+## <a name="WithStreamServerChain">func</a> [WithStreamServerChain](./chain.go#L141)
+``` go
+func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption
+```
+WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
+Basically syntactic sugar.
+
+## <a name="WithUnaryServerChain">func</a> [WithUnaryServerChain](./chain.go#L135)
+``` go
+func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption
+```
+Chain creates a single interceptor out of a chain of many interceptors.
+
+WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
+Basically syntactic sugar.
+
+## <a name="WrappedServerStream">type</a> [WrappedServerStream](./wrappers.go#L12-L16)
+``` go
+type WrappedServerStream struct {
+ grpc.ServerStream
+ // WrappedContext is the wrapper's own Context. You can assign it.
+ WrappedContext context.Context
+}
+```
+WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
+
+### <a name="WrapServerStream">func</a> [WrapServerStream](./wrappers.go#L24)
+``` go
+func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream
+```
+WrapServerStream returns a ServerStream that has the ability to overwrite context.
+
+### <a name="WrappedServerStream.Context">func</a> (\*WrappedServerStream) [Context](./wrappers.go#L19)
+``` go
+func (w *WrappedServerStream) Context() context.Context
+```
+Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/mwitkow/go-grpc-middleware/LICENSE b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE
index b2b065037..b2b065037 100644
--- a/vendor/github.com/mwitkow/go-grpc-middleware/LICENSE
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md
new file mode 100644
index 000000000..6842f9d41
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md
@@ -0,0 +1,86 @@
+# Go gRPC Middleware
+
+[![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware.svg?branch=master)](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware)
+[![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-middleware)](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware)
+[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware)
+[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/?badge)
+[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware)
+[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
+[![quality: production](https://img.shields.io/badge/quality-production-orange.svg)](#status)
+
+
+[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.
+
+**Important** The repo recently moved to `github.com/grpc-ecosystem/go-grpc-middleware`, please update your import paths.
+
+## Middleware
+
+[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for
+Interceptors, i.e. [middleware](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs)
+that is executed either on the gRPC Server before the request is passed onto the user's application logic, or on the gRPC client either around the user call. It is a perfect way to implement
+common patters: auth, logging, message, validation, retries or monitoring.
+
+These are generic building blocks that make it easy to build multiple microservices easily.
+The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
+some of them itself, but also will link to useful external repos.
+
+`grpc_middleware` itself provides support for chaining interceptors. See [Documentation](DOC.md), but here's an example:
+
+```go
+import "github.com/grpc-ecosystem/go-grpc-middleware"
+
+myServer := grpc.NewServer(
+ grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
+ grpc_ctxtags.StreamServerInterceptor(),
+ grpc_opentracing.StreamServerInterceptor(),
+ grpc_prometheus.StreamServerInterceptor,
+ grpc_zap.StreamServerInterceptor(zapLogger),
+ grpc_auth.StreamServerInterceptor(myAuthFunction),
+ grpc_recovery.StreamServerInterceptor(),
+ )),
+ grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
+ grpc_ctxtags.UnaryServerInterceptor(),
+ grpc_opentracing.UnaryServerInterceptor(),
+ grpc_prometheus.UnaryServerInterceptor,
+ grpc_zap.UnaryServerInterceptor(zapLogger),
+ grpc_auth.UnaryServerInterceptor(myAuthFunction),
+ grpc_recovery.UnaryServerInterceptor(),
+ )),
+)
+```
+
+## Interceptors
+
+*Please send a PR to add new interceptors or middleware to this list*
+
+#### Auth
+ * [`grpc_auth`](auth) - a customizable (via `AuthFunc) piece of auth middleware
+
+#### Logging
+ * [`grpc_ctxtags`](tags/) - a library that adds a `Tag` map to context, with data populated from request body
+ * [`grpc_zap`](logging/zap/) - integration of [zap](https://github.com/uber-go/zap) logging library into gRPC handlers.
+ * [`grpc_logrus`](logging/logrus/) - integration of [logrus](https://github.com/Sirupsen/logrus) logging library into gRPC handlers.
+
+
+#### Monitoring
+ * [`grpc_prometheus`⚡](https://github.com/grpc-ecosystem/go-grpc-prometheus) - Prometheus client-side and server-side monitoring middleware
+ * [`otgrpc`⚡](https://github.com/grpc-ecosystem/grpc-opentracing/tree/master/go/otgrpc) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors
+ * [`grpc_opentracing`](tracing/opentracing) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors with support for streaming and handler-returned tags
+
+#### Client
+ * [`grpc_retry`](retry/) - a generic gRPC response code retry mechanism, client-side middleware
+
+#### Server
+ * [`grpc_validator`](validator/) - codegen inbound message validation from `.proto` options
+ * [`grpc_recovery`](recovery/) - turn panics into gRPC errors
+
+
+## Status
+
+This code has been running in *production* since May 2016 as the basis of the gRPC micro services stack at [Improbable](https://improbable.io).
+
+Additional tooling will be added, and contributions are welcome.
+
+## License
+
+`go-grpc-middleware` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go
new file mode 100644
index 000000000..df519b982
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go
@@ -0,0 +1,143 @@
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+// gRPC Server Interceptor chaining middleware.
+
+package grpc_middleware
+
+import (
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+)
+
+// ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
+//
+// Execution is done in left-to-right order, including passing of context.
+// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
+// will see context changes of one and two.
+func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
+ switch len(interceptors) {
+ case 0:
+ // do not want to return nil interceptor since this function was never defined to do so/for backwards compatibility
+ return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ return handler(ctx, req)
+ }
+ case 1:
+ return interceptors[0]
+ default:
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ buildChain := func(current grpc.UnaryServerInterceptor, next grpc.UnaryHandler) grpc.UnaryHandler {
+ return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
+ return current(currentCtx, currentReq, info, next)
+ }
+ }
+ chain := handler
+ for i := len(interceptors) - 1; i >= 0; i-- {
+ chain = buildChain(interceptors[i], chain)
+ }
+ return chain(ctx, req)
+ }
+ }
+}
+
+// ChainStreamServer creates a single interceptor out of a chain of many interceptors.
+//
+// Execution is done in left-to-right order, including passing of context.
+// For example ChainUnaryServer(one, two, three) will execute one before two before three.
+// If you want to pass context between interceptors, use WrapServerStream.
+func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
+ switch len(interceptors) {
+ case 0:
+ // do not want to return nil interceptor since this function was never defined to do so/for backwards compatibility
+ return func(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ return handler(srv, stream)
+ }
+ case 1:
+ return interceptors[0]
+ default:
+ return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ buildChain := func(current grpc.StreamServerInterceptor, next grpc.StreamHandler) grpc.StreamHandler {
+ return func(currentSrv interface{}, currentStream grpc.ServerStream) error {
+ return current(currentSrv, currentStream, info, next)
+ }
+ }
+ chain := handler
+ for i := len(interceptors) - 1; i >= 0; i-- {
+ chain = buildChain(interceptors[i], chain)
+ }
+ return chain(srv, stream)
+ }
+ }
+}
+
+// ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
+//
+// Execution is done in left-to-right order, including passing of context.
+// For example ChainUnaryClient(one, two, three) will execute one before two before three.
+func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
+ switch len(interceptors) {
+ case 0:
+ // do not want to return nil interceptor since this function was never defined to do so/for backwards compatibility
+ return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+ return invoker(ctx, method, req, reply, cc, opts...)
+ }
+ case 1:
+ return interceptors[0]
+ default:
+ return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+ buildChain := func(current grpc.UnaryClientInterceptor, next grpc.UnaryInvoker) grpc.UnaryInvoker {
+ return func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
+ return current(currentCtx, currentMethod, currentReq, currentRepl, currentConn, next, currentOpts...)
+ }
+ }
+ chain := invoker
+ for i := len(interceptors) - 1; i >= 0; i-- {
+ chain = buildChain(interceptors[i], chain)
+ }
+ return chain(ctx, method, req, reply, cc, opts...)
+ }
+ }
+}
+
+// ChainStreamClient creates a single interceptor out of a chain of many interceptors.
+//
+// Execution is done in left-to-right order, including passing of context.
+// For example ChainStreamClient(one, two, three) will execute one before two before three.
+func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor {
+ switch len(interceptors) {
+ case 0:
+ // do not want to return nil interceptor since this function was never defined to do so/for backwards compatibility
+ return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ return streamer(ctx, desc, cc, method, opts...)
+ }
+ case 1:
+ return interceptors[0]
+ default:
+ return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ buildChain := func(current grpc.StreamClientInterceptor, next grpc.Streamer) grpc.Streamer {
+ return func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
+ return current(currentCtx, currentDesc, currentConn, currentMethod, next, currentOpts...)
+ }
+ }
+ chain := streamer
+ for i := len(interceptors) - 1; i >= 0; i-- {
+ chain = buildChain(interceptors[i], chain)
+ }
+ return chain(ctx, desc, cc, method, opts...)
+ }
+ }
+}
+
+// Chain creates a single interceptor out of a chain of many interceptors.
+//
+// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
+// Basically syntactic sugar.
+func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption {
+ return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...))
+}
+
+// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
+// Basically syntactic sugar.
+func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption {
+ return grpc.StreamInterceptor(ChainStreamServer(interceptors...))
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/checkup.sh b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/checkup.sh
new file mode 100755
index 000000000..37e9aac6e
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/checkup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Script that checks up code (govet).
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
+
+function print_real_go_files {
+ grep --files-without-match 'DO NOT EDIT!' $(find . -iname '*.go')
+}
+
+function govet_all {
+ ret=0
+ for i in $(print_real_go_files); do
+ output=$(go tool vet -all=true -tests=false ${i})
+ ret=$(($ret | $?))
+ echo -n ${output}
+ done;
+ return ${ret}
+}
+
+govet_all
+echo "returning $?" \ No newline at end of file
diff --git a/vendor/github.com/mwitkow/go-grpc-middleware/doc.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go
index bd6b41477..bd6b41477 100644
--- a/vendor/github.com/mwitkow/go-grpc-middleware/doc.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/fixup.sh b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/fixup.sh
new file mode 100755
index 000000000..850ec557d
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/fixup.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Script that checks the code for errors.
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
+GOBIN=${GOBIN:="$GOPATH/bin"}
+
+function print_real_go_files {
+ grep --files-without-match 'DO NOT EDIT!' $(find . -iname '*.go')
+}
+
+function generate_markdown {
+ echo "Generating Github markdown"
+ oldpwd=$(pwd)
+ for i in $(find . -iname 'doc.go'); do
+ dir=${i%/*}
+ realdir=$(realpath $dir)
+ package=${realdir##${GOPATH}/src/}
+ echo "$package"
+ cd ${dir}
+ ${GOBIN}/godoc2ghmd -ex -file DOC.md ${package}
+ ln -s DOC.md README.md 2> /dev/null # can fail
+ cd ${oldpwd}
+ done;
+}
+
+function goimports_all {
+ echo "Running goimports"
+ goimports -l -w $(print_real_go_files)
+ return $?
+}
+
+go get github.com/davecheney/godoc2md
+
+generate_markdown
+goimports_all
+echo "returning $?"
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/DOC.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/DOC.md
new file mode 100644
index 000000000..3f86b5007
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/DOC.md
@@ -0,0 +1,74 @@
+# grpc_logging
+`import "github.com/grpc-ecosystem/go-grpc-middleware/logging"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+
+## <a name="pkg-overview">Overview</a>
+grpc_logging is a "parent" package for gRPC logging middlewares
+
+### General functionality of all middleware
+All logging middleware have an `Extract(ctx)` function that provides a request-scoped logger with gRPC-related fields
+(service and method names). Moreover, that logger will have fields populated from the `grpc_ctxtags.Tags` of the
+context.
+
+All logging middleware will emit a final log statement. It is based on the error returned by the handler function,
+the gRPC status code, an error (if any) and it will emit at a level controlled via `WithLevels`.
+
+### This parent package
+This particular package is intended for use by other middleware, logging or otherwise. It contains interfaces that other
+logging middlewares *could* share . This allows code to be shared between different implementations.
+
+### Field names
+All field names of loggers follow the OpenTracing semantics definitions, with `grpc.` prefix if needed:
+<a href="https://github.com/opentracing/specification/blob/master/semantic_conventions.md">https://github.com/opentracing/specification/blob/master/semantic_conventions.md</a>
+
+### Implementations
+There are two implementations at the moment: logrus and zap
+
+See relevant packages below.
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+- [google.golang.org/grpc/codes](https://godoc.org/google.golang.org/grpc/codes)
+
+## <a name="pkg-index">Index</a>
+* [func DefaultErrorToCode(err error) codes.Code](#DefaultErrorToCode)
+* [type ClientPayloadLoggingDecider](#ClientPayloadLoggingDecider)
+* [type ErrorToCode](#ErrorToCode)
+* [type ServerPayloadLoggingDecider](#ServerPayloadLoggingDecider)
+
+#### <a name="pkg-files">Package files</a>
+[common.go](./common.go) [doc.go](./doc.go)
+
+## <a name="DefaultErrorToCode">func</a> [DefaultErrorToCode](./common.go#L16)
+``` go
+func DefaultErrorToCode(err error) codes.Code
+```
+
+## <a name="ClientPayloadLoggingDecider">type</a> [ClientPayloadLoggingDecider](./common.go#L26)
+``` go
+type ClientPayloadLoggingDecider func(ctx context.Context, fullMethodName string) bool
+```
+ClientPayloadLoggingDecider is a user-provided function for deciding whether to log the client-side
+request/response payloads
+
+## <a name="ErrorToCode">type</a> [ErrorToCode](./common.go#L14)
+``` go
+type ErrorToCode func(err error) codes.Code
+```
+ErrorToCode function determines the error code of an error
+This makes using custom errors with grpc middleware easier
+
+## <a name="ServerPayloadLoggingDecider">type</a> [ServerPayloadLoggingDecider](./common.go#L22)
+``` go
+type ServerPayloadLoggingDecider func(ctx context.Context, fullMethodName string, servingObject interface{}) bool
+```
+ServerPayloadLoggingDecider is a user-provided function for deciding whether to log the server-side
+request/response payloads
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/README.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/README.md
new file mode 100644
index 000000000..3f86b5007
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/README.md
@@ -0,0 +1,74 @@
+# grpc_logging
+`import "github.com/grpc-ecosystem/go-grpc-middleware/logging"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+
+## <a name="pkg-overview">Overview</a>
+grpc_logging is a "parent" package for gRPC logging middlewares
+
+### General functionality of all middleware
+All logging middleware have an `Extract(ctx)` function that provides a request-scoped logger with gRPC-related fields
+(service and method names). Moreover, that logger will have fields populated from the `grpc_ctxtags.Tags` of the
+context.
+
+All logging middleware will emit a final log statement. It is based on the error returned by the handler function,
+the gRPC status code, an error (if any) and it will emit at a level controlled via `WithLevels`.
+
+### This parent package
+This particular package is intended for use by other middleware, logging or otherwise. It contains interfaces that other
+logging middlewares *could* share . This allows code to be shared between different implementations.
+
+### Field names
+All field names of loggers follow the OpenTracing semantics definitions, with `grpc.` prefix if needed:
+<a href="https://github.com/opentracing/specification/blob/master/semantic_conventions.md">https://github.com/opentracing/specification/blob/master/semantic_conventions.md</a>
+
+### Implementations
+There are two implementations at the moment: logrus and zap
+
+See relevant packages below.
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+- [google.golang.org/grpc/codes](https://godoc.org/google.golang.org/grpc/codes)
+
+## <a name="pkg-index">Index</a>
+* [func DefaultErrorToCode(err error) codes.Code](#DefaultErrorToCode)
+* [type ClientPayloadLoggingDecider](#ClientPayloadLoggingDecider)
+* [type ErrorToCode](#ErrorToCode)
+* [type ServerPayloadLoggingDecider](#ServerPayloadLoggingDecider)
+
+#### <a name="pkg-files">Package files</a>
+[common.go](./common.go) [doc.go](./doc.go)
+
+## <a name="DefaultErrorToCode">func</a> [DefaultErrorToCode](./common.go#L16)
+``` go
+func DefaultErrorToCode(err error) codes.Code
+```
+
+## <a name="ClientPayloadLoggingDecider">type</a> [ClientPayloadLoggingDecider](./common.go#L26)
+``` go
+type ClientPayloadLoggingDecider func(ctx context.Context, fullMethodName string) bool
+```
+ClientPayloadLoggingDecider is a user-provided function for deciding whether to log the client-side
+request/response payloads
+
+## <a name="ErrorToCode">type</a> [ErrorToCode](./common.go#L14)
+``` go
+type ErrorToCode func(err error) codes.Code
+```
+ErrorToCode function determines the error code of an error
+This makes using custom errors with grpc middleware easier
+
+## <a name="ServerPayloadLoggingDecider">type</a> [ServerPayloadLoggingDecider](./common.go#L22)
+``` go
+type ServerPayloadLoggingDecider func(ctx context.Context, fullMethodName string, servingObject interface{}) bool
+```
+ServerPayloadLoggingDecider is a user-provided function for deciding whether to log the server-side
+request/response payloads
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/common.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/common.go
new file mode 100644
index 000000000..a367b72a1
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/common.go
@@ -0,0 +1,26 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logging
+
+import (
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+)
+
+// ErrorToCode function determines the error code of an error
+// This makes using custom errors with grpc middleware easier
+type ErrorToCode func(err error) codes.Code
+
+func DefaultErrorToCode(err error) codes.Code {
+ return grpc.Code(err)
+}
+
+// ServerPayloadLoggingDecider is a user-provided function for deciding whether to log the server-side
+// request/response payloads
+type ServerPayloadLoggingDecider func(ctx context.Context, fullMethodName string, servingObject interface{}) bool
+
+// ClientPayloadLoggingDecider is a user-provided function for deciding whether to log the client-side
+// request/response payloads
+type ClientPayloadLoggingDecider func(ctx context.Context, fullMethodName string) bool
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/doc.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/doc.go
new file mode 100644
index 000000000..02295dfcc
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/doc.go
@@ -0,0 +1,33 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+//
+/*
+grpc_logging is a "parent" package for gRPC logging middlewares
+
+General functionality of all middleware
+
+All logging middleware have an `Extract(ctx)` function that provides a request-scoped logger with gRPC-related fields
+(service and method names). Moreover, that logger will have fields populated from the `grpc_ctxtags.Tags` of the
+context.
+
+All logging middleware will emit a final log statement. It is based on the error returned by the handler function,
+the gRPC status code, an error (if any) and it will emit at a level controlled via `WithLevels`.
+
+This parent package
+
+This particular package is intended for use by other middleware, logging or otherwise. It contains interfaces that other
+logging middlewares *could* share . This allows code to be shared between different implementations.
+
+Field names
+
+All field names of loggers follow the OpenTracing semantics definitions, with `grpc.` prefix if needed:
+https://github.com/opentracing/specification/blob/master/semantic_conventions.md
+
+Implementations
+
+There are two implementations at the moment: logrus and zap
+
+See relevant packages below.
+*/
+package grpc_logging
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/DOC.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/DOC.md
new file mode 100644
index 000000000..e12aaec93
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/DOC.md
@@ -0,0 +1,300 @@
+# grpc_logrus
+`import "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+* [Examples](#pkg-examples)
+
+## <a name="pkg-overview">Overview</a>
+`grpc_logrus` is a gRPC logging middleware backed by Logrus loggers
+
+It accepts a user-configured `logrus.Entry` that will be used for logging completed gRPC calls. The same
+`logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code.
+
+You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. The fields set on the
+logger correspond to the grpc_ctxtags.Tags attached to the context.
+
+This package also implements request and response *payload* logging, both for server-side and client-side. These will be
+logged as structured `jsonbp` fields for every message received/sent (both unary and streaming). For that please use
+`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
+the full request/response payload needs to be written with care, this can significantly slow down gRPC.
+
+Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
+
+Please see examples and tests for examples of use.
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+x := func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) {
+ // Add fields the ctxtags of the request which will be added to all extracted loggers.
+ grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337)
+ // Extract a request-scoped zap.Logger and log a message.
+ grpc_logrus.Extract(ctx).Info("some ping")
+ return &pb_testproto.PingResponse{Value: ping.Value}, nil
+ }
+ return x
+```
+
+</details>
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+// Logrus entry is used, allowing pre-definition of certain fields by the user.
+ logrusEntry := logrus.NewEntry(logrusLogger)
+ // Shared options for the logger, with a custom gRPC code to log level function.
+ opts := []grpc_logrus.Option{
+ grpc_logrus.WithLevels(customFunc),
+ }
+ // Make sure that log statements internal to gRPC library are logged using the zapLogger as well.
+ grpc_logrus.ReplaceGrpcLogger(logrusEntry)
+ // Create a server, make sure we put the grpc_ctxtags context before everything else.
+ server := grpc.NewServer(
+ grpc_middleware.WithUnaryServerChain(
+ grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
+ grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
+ ),
+ grpc_middleware.WithStreamServerChain(
+ grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
+ grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
+ ),
+ )
+ return server
+```
+
+</details>
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+// Logrus entry is used, allowing pre-definition of certain fields by the user.
+ logrusEntry := logrus.NewEntry(logrusLogger)
+ // Shared options for the logger, with a custom duration to log field function.
+ opts := []grpc_logrus.Option{
+ grpc_logrus.WithDurationField(func(duration time.Duration) (key string, value interface{}) {
+ return "grpc.time_ns", duration.Nanoseconds()
+ }),
+ }
+ server := grpc.NewServer(
+ grpc_middleware.WithUnaryServerChain(
+ grpc_ctxtags.UnaryServerInterceptor(),
+ grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
+ ),
+ grpc_middleware.WithStreamServerChain(
+ grpc_ctxtags.StreamServerInterceptor(),
+ grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
+ ),
+ )
+ return server
+```
+
+</details>
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- github.com/Sirupsen/logrus
+- [github.com/golang/protobuf/jsonpb](https://godoc.org/github.com/golang/protobuf/jsonpb)
+- [github.com/golang/protobuf/proto](https://godoc.org/github.com/golang/protobuf/proto)
+- [github.com/grpc-ecosystem/go-grpc-middleware](./../..)
+- [github.com/grpc-ecosystem/go-grpc-middleware/logging](./..)
+- [github.com/grpc-ecosystem/go-grpc-middleware/tags](./../../tags)
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+- [google.golang.org/grpc/codes](https://godoc.org/google.golang.org/grpc/codes)
+- [google.golang.org/grpc/grpclog](https://godoc.org/google.golang.org/grpc/grpclog)
+
+## <a name="pkg-index">Index</a>
+* [Variables](#pkg-variables)
+* [func DefaultClientCodeToLevel(code codes.Code) logrus.Level](#DefaultClientCodeToLevel)
+* [func DefaultCodeToLevel(code codes.Code) logrus.Level](#DefaultCodeToLevel)
+* [func DurationToDurationField(duration time.Duration) (key string, value interface{})](#DurationToDurationField)
+* [func DurationToTimeMillisField(duration time.Duration) (key string, value interface{})](#DurationToTimeMillisField)
+* [func Extract(ctx context.Context) \*logrus.Entry](#Extract)
+* [func PayloadStreamClientInterceptor(entry \*logrus.Entry, decider grpc\_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor](#PayloadStreamClientInterceptor)
+* [func PayloadStreamServerInterceptor(entry \*logrus.Entry, decider grpc\_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor](#PayloadStreamServerInterceptor)
+* [func PayloadUnaryClientInterceptor(entry \*logrus.Entry, decider grpc\_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor](#PayloadUnaryClientInterceptor)
+* [func PayloadUnaryServerInterceptor(entry \*logrus.Entry, decider grpc\_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor](#PayloadUnaryServerInterceptor)
+* [func ReplaceGrpcLogger(logger \*logrus.Entry)](#ReplaceGrpcLogger)
+* [func StreamClientInterceptor(entry \*logrus.Entry, opts ...Option) grpc.StreamClientInterceptor](#StreamClientInterceptor)
+* [func StreamServerInterceptor(entry \*logrus.Entry, opts ...Option) grpc.StreamServerInterceptor](#StreamServerInterceptor)
+* [func UnaryClientInterceptor(entry \*logrus.Entry, opts ...Option) grpc.UnaryClientInterceptor](#UnaryClientInterceptor)
+* [func UnaryServerInterceptor(entry \*logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor](#UnaryServerInterceptor)
+* [type CodeToLevel](#CodeToLevel)
+* [type DurationToField](#DurationToField)
+* [type Option](#Option)
+ * [func WithCodes(f grpc\_logging.ErrorToCode) Option](#WithCodes)
+ * [func WithDurationField(f DurationToField) Option](#WithDurationField)
+ * [func WithLevels(f CodeToLevel) Option](#WithLevels)
+
+#### <a name="pkg-examples">Examples</a>
+* [Package (HandlerUsageUnaryPing)](#example__handlerUsageUnaryPing)
+* [Package (Initialization)](#example__initialization)
+* [Package (InitializationWithDurationFieldOverride)](#example__initializationWithDurationFieldOverride)
+
+#### <a name="pkg-files">Package files</a>
+[client_interceptors.go](./client_interceptors.go) [context.go](./context.go) [doc.go](./doc.go) [grpclogger.go](./grpclogger.go) [noop.go](./noop.go) [options.go](./options.go) [payload_interceptors.go](./payload_interceptors.go) [server_interceptors.go](./server_interceptors.go)
+
+## <a name="pkg-variables">Variables</a>
+``` go
+var (
+ // SystemField is used in every log statement made through grpc_logrus. Can be overwritten before any initialization code.
+ SystemField = "system"
+
+ // KindField describes the log gield used to incicate whether this is a server or a client log statment.
+ KindField = "span.kind"
+)
+```
+``` go
+var DefaultDurationToField = DurationToTimeMillisField
+```
+DefaultDurationToField is the default implementation of converting request duration to a log field (key and value).
+
+``` go
+var (
+ // JsonPBMarshaller is the marshaller used for serializing protobuf messages.
+ JsonPbMarshaller = &jsonpb.Marshaler{}
+)
+```
+
+## <a name="DefaultClientCodeToLevel">func</a> [DefaultClientCodeToLevel](./options.go#L120)
+``` go
+func DefaultClientCodeToLevel(code codes.Code) logrus.Level
+```
+DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.
+
+## <a name="DefaultCodeToLevel">func</a> [DefaultCodeToLevel](./options.go#L78)
+``` go
+func DefaultCodeToLevel(code codes.Code) logrus.Level
+```
+DefaultCodeToLevel is the default implementation of gRPC return codes to log levels for server side.
+
+## <a name="DurationToDurationField">func</a> [DurationToDurationField](./options.go#L170)
+``` go
+func DurationToDurationField(duration time.Duration) (key string, value interface{})
+```
+DurationToDurationField uses the duration value to log the request duration.
+
+## <a name="DurationToTimeMillisField">func</a> [DurationToTimeMillisField](./options.go#L165)
+``` go
+func DurationToTimeMillisField(duration time.Duration) (key string, value interface{})
+```
+DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.
+
+## <a name="Extract">func</a> [Extract](./context.go#L22)
+``` go
+func Extract(ctx context.Context) *logrus.Entry
+```
+Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.
+
+If the grpc_logrus middleware wasn't used, a no-op `logrus.Entry` is returned. This makes it safe to
+use regardless.
+
+## <a name="PayloadStreamClientInterceptor">func</a> [PayloadStreamClientInterceptor](./payload_interceptors.go#L77)
+``` go
+func PayloadStreamClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor
+```
+PayloadStreamServerInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses.
+
+## <a name="PayloadStreamServerInterceptor">func</a> [PayloadStreamServerInterceptor](./payload_interceptors.go#L48)
+``` go
+func PayloadStreamServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor
+```
+PayloadUnaryServerInterceptor returns a new server server interceptors that logs the payloads of requests.
+
+This *only* works when placed *after* the `grpc_logrus.StreamServerInterceptor`. However, the logging can be done to a
+separate instance of the logger.
+
+## <a name="PayloadUnaryClientInterceptor">func</a> [PayloadUnaryClientInterceptor](./payload_interceptors.go#L61)
+``` go
+func PayloadUnaryClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor
+```
+PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses.
+
+## <a name="PayloadUnaryServerInterceptor">func</a> [PayloadUnaryServerInterceptor](./payload_interceptors.go#L28)
+``` go
+func PayloadUnaryServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor
+```
+PayloadUnaryServerInterceptor returns a new unary server interceptors that logs the payloads of requests.
+
+This *only* works when placed *after* the `grpc_logrus.UnaryServerInterceptor`. However, the logging can be done to a
+separate instance of the logger.
+
+## <a name="ReplaceGrpcLogger">func</a> [ReplaceGrpcLogger](./grpclogger.go#L13)
+``` go
+func ReplaceGrpcLogger(logger *logrus.Entry)
+```
+ReplaceGrpcLogger sets the given logrus.Logger as a gRPC-level logger.
+This should be called *before* any other initialization, preferably from init() functions.
+
+## <a name="StreamClientInterceptor">func</a> [StreamClientInterceptor](./client_interceptors.go#L28)
+``` go
+func StreamClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamClientInterceptor
+```
+StreamServerInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.
+
+## <a name="StreamServerInterceptor">func</a> [StreamServerInterceptor](./server_interceptors.go#L50)
+``` go
+func StreamServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamServerInterceptor
+```
+StreamServerInterceptor returns a new streaming server interceptor that adds logrus.Entry to the context.
+
+## <a name="UnaryClientInterceptor">func</a> [UnaryClientInterceptor](./client_interceptors.go#L16)
+``` go
+func UnaryClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryClientInterceptor
+```
+UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.
+
+## <a name="UnaryServerInterceptor">func</a> [UnaryServerInterceptor](./server_interceptors.go#L25)
+``` go
+func UnaryServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor
+```
+PayloadUnaryServerInterceptor returns a new unary server interceptors that adds logrus.Entry to the context.
+
+## <a name="CodeToLevel">type</a> [CodeToLevel](./options.go#L51)
+``` go
+type CodeToLevel func(code codes.Code) logrus.Level
+```
+CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.
+
+## <a name="DurationToField">type</a> [DurationToField](./options.go#L54)
+``` go
+type DurationToField func(duration time.Duration) (key string, value interface{})
+```
+DurationToField function defines how to produce duration fields for logging
+
+## <a name="Option">type</a> [Option](./options.go#L48)
+``` go
+type Option func(*options)
+```
+
+### <a name="WithCodes">func</a> [WithCodes](./options.go#L64)
+``` go
+func WithCodes(f grpc_logging.ErrorToCode) Option
+```
+WithCodes customizes the function for mapping errors to error codes.
+
+### <a name="WithDurationField">func</a> [WithDurationField](./options.go#L71)
+``` go
+func WithDurationField(f DurationToField) Option
+```
+WithDurationField customizes the function for mapping request durations to log fields.
+
+### <a name="WithLevels">func</a> [WithLevels](./options.go#L57)
+``` go
+func WithLevels(f CodeToLevel) Option
+```
+WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/README.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/README.md
new file mode 100644
index 000000000..e12aaec93
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/README.md
@@ -0,0 +1,300 @@
+# grpc_logrus
+`import "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+* [Examples](#pkg-examples)
+
+## <a name="pkg-overview">Overview</a>
+`grpc_logrus` is a gRPC logging middleware backed by Logrus loggers
+
+It accepts a user-configured `logrus.Entry` that will be used for logging completed gRPC calls. The same
+`logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code.
+
+You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. The fields set on the
+logger correspond to the grpc_ctxtags.Tags attached to the context.
+
+This package also implements request and response *payload* logging, both for server-side and client-side. These will be
+logged as structured `jsonbp` fields for every message received/sent (both unary and streaming). For that please use
+`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
+the full request/response payload needs to be written with care, this can significantly slow down gRPC.
+
+Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
+
+Please see examples and tests for examples of use.
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+x := func(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) {
+ // Add fields the ctxtags of the request which will be added to all extracted loggers.
+ grpc_ctxtags.Extract(ctx).Set("custom_tags.string", "something").Set("custom_tags.int", 1337)
+ // Extract a request-scoped zap.Logger and log a message.
+ grpc_logrus.Extract(ctx).Info("some ping")
+ return &pb_testproto.PingResponse{Value: ping.Value}, nil
+ }
+ return x
+```
+
+</details>
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+// Logrus entry is used, allowing pre-definition of certain fields by the user.
+ logrusEntry := logrus.NewEntry(logrusLogger)
+ // Shared options for the logger, with a custom gRPC code to log level function.
+ opts := []grpc_logrus.Option{
+ grpc_logrus.WithLevels(customFunc),
+ }
+ // Make sure that log statements internal to gRPC library are logged using the zapLogger as well.
+ grpc_logrus.ReplaceGrpcLogger(logrusEntry)
+ // Create a server, make sure we put the grpc_ctxtags context before everything else.
+ server := grpc.NewServer(
+ grpc_middleware.WithUnaryServerChain(
+ grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
+ grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
+ ),
+ grpc_middleware.WithStreamServerChain(
+ grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
+ grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
+ ),
+ )
+ return server
+```
+
+</details>
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+// Logrus entry is used, allowing pre-definition of certain fields by the user.
+ logrusEntry := logrus.NewEntry(logrusLogger)
+ // Shared options for the logger, with a custom duration to log field function.
+ opts := []grpc_logrus.Option{
+ grpc_logrus.WithDurationField(func(duration time.Duration) (key string, value interface{}) {
+ return "grpc.time_ns", duration.Nanoseconds()
+ }),
+ }
+ server := grpc.NewServer(
+ grpc_middleware.WithUnaryServerChain(
+ grpc_ctxtags.UnaryServerInterceptor(),
+ grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
+ ),
+ grpc_middleware.WithStreamServerChain(
+ grpc_ctxtags.StreamServerInterceptor(),
+ grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
+ ),
+ )
+ return server
+```
+
+</details>
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- github.com/Sirupsen/logrus
+- [github.com/golang/protobuf/jsonpb](https://godoc.org/github.com/golang/protobuf/jsonpb)
+- [github.com/golang/protobuf/proto](https://godoc.org/github.com/golang/protobuf/proto)
+- [github.com/grpc-ecosystem/go-grpc-middleware](./../..)
+- [github.com/grpc-ecosystem/go-grpc-middleware/logging](./..)
+- [github.com/grpc-ecosystem/go-grpc-middleware/tags](./../../tags)
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+- [google.golang.org/grpc/codes](https://godoc.org/google.golang.org/grpc/codes)
+- [google.golang.org/grpc/grpclog](https://godoc.org/google.golang.org/grpc/grpclog)
+
+## <a name="pkg-index">Index</a>
+* [Variables](#pkg-variables)
+* [func DefaultClientCodeToLevel(code codes.Code) logrus.Level](#DefaultClientCodeToLevel)
+* [func DefaultCodeToLevel(code codes.Code) logrus.Level](#DefaultCodeToLevel)
+* [func DurationToDurationField(duration time.Duration) (key string, value interface{})](#DurationToDurationField)
+* [func DurationToTimeMillisField(duration time.Duration) (key string, value interface{})](#DurationToTimeMillisField)
+* [func Extract(ctx context.Context) \*logrus.Entry](#Extract)
+* [func PayloadStreamClientInterceptor(entry \*logrus.Entry, decider grpc\_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor](#PayloadStreamClientInterceptor)
+* [func PayloadStreamServerInterceptor(entry \*logrus.Entry, decider grpc\_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor](#PayloadStreamServerInterceptor)
+* [func PayloadUnaryClientInterceptor(entry \*logrus.Entry, decider grpc\_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor](#PayloadUnaryClientInterceptor)
+* [func PayloadUnaryServerInterceptor(entry \*logrus.Entry, decider grpc\_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor](#PayloadUnaryServerInterceptor)
+* [func ReplaceGrpcLogger(logger \*logrus.Entry)](#ReplaceGrpcLogger)
+* [func StreamClientInterceptor(entry \*logrus.Entry, opts ...Option) grpc.StreamClientInterceptor](#StreamClientInterceptor)
+* [func StreamServerInterceptor(entry \*logrus.Entry, opts ...Option) grpc.StreamServerInterceptor](#StreamServerInterceptor)
+* [func UnaryClientInterceptor(entry \*logrus.Entry, opts ...Option) grpc.UnaryClientInterceptor](#UnaryClientInterceptor)
+* [func UnaryServerInterceptor(entry \*logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor](#UnaryServerInterceptor)
+* [type CodeToLevel](#CodeToLevel)
+* [type DurationToField](#DurationToField)
+* [type Option](#Option)
+ * [func WithCodes(f grpc\_logging.ErrorToCode) Option](#WithCodes)
+ * [func WithDurationField(f DurationToField) Option](#WithDurationField)
+ * [func WithLevels(f CodeToLevel) Option](#WithLevels)
+
+#### <a name="pkg-examples">Examples</a>
+* [Package (HandlerUsageUnaryPing)](#example__handlerUsageUnaryPing)
+* [Package (Initialization)](#example__initialization)
+* [Package (InitializationWithDurationFieldOverride)](#example__initializationWithDurationFieldOverride)
+
+#### <a name="pkg-files">Package files</a>
+[client_interceptors.go](./client_interceptors.go) [context.go](./context.go) [doc.go](./doc.go) [grpclogger.go](./grpclogger.go) [noop.go](./noop.go) [options.go](./options.go) [payload_interceptors.go](./payload_interceptors.go) [server_interceptors.go](./server_interceptors.go)
+
+## <a name="pkg-variables">Variables</a>
+``` go
+var (
+ // SystemField is used in every log statement made through grpc_logrus. Can be overwritten before any initialization code.
+ SystemField = "system"
+
+ // KindField describes the log gield used to incicate whether this is a server or a client log statment.
+ KindField = "span.kind"
+)
+```
+``` go
+var DefaultDurationToField = DurationToTimeMillisField
+```
+DefaultDurationToField is the default implementation of converting request duration to a log field (key and value).
+
+``` go
+var (
+ // JsonPBMarshaller is the marshaller used for serializing protobuf messages.
+ JsonPbMarshaller = &jsonpb.Marshaler{}
+)
+```
+
+## <a name="DefaultClientCodeToLevel">func</a> [DefaultClientCodeToLevel](./options.go#L120)
+``` go
+func DefaultClientCodeToLevel(code codes.Code) logrus.Level
+```
+DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.
+
+## <a name="DefaultCodeToLevel">func</a> [DefaultCodeToLevel](./options.go#L78)
+``` go
+func DefaultCodeToLevel(code codes.Code) logrus.Level
+```
+DefaultCodeToLevel is the default implementation of gRPC return codes to log levels for server side.
+
+## <a name="DurationToDurationField">func</a> [DurationToDurationField](./options.go#L170)
+``` go
+func DurationToDurationField(duration time.Duration) (key string, value interface{})
+```
+DurationToDurationField uses the duration value to log the request duration.
+
+## <a name="DurationToTimeMillisField">func</a> [DurationToTimeMillisField](./options.go#L165)
+``` go
+func DurationToTimeMillisField(duration time.Duration) (key string, value interface{})
+```
+DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.
+
+## <a name="Extract">func</a> [Extract](./context.go#L22)
+``` go
+func Extract(ctx context.Context) *logrus.Entry
+```
+Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.
+
+If the grpc_logrus middleware wasn't used, a no-op `logrus.Entry` is returned. This makes it safe to
+use regardless.
+
+## <a name="PayloadStreamClientInterceptor">func</a> [PayloadStreamClientInterceptor](./payload_interceptors.go#L77)
+``` go
+func PayloadStreamClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor
+```
+PayloadStreamServerInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses.
+
+## <a name="PayloadStreamServerInterceptor">func</a> [PayloadStreamServerInterceptor](./payload_interceptors.go#L48)
+``` go
+func PayloadStreamServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor
+```
+PayloadUnaryServerInterceptor returns a new server server interceptors that logs the payloads of requests.
+
+This *only* works when placed *after* the `grpc_logrus.StreamServerInterceptor`. However, the logging can be done to a
+separate instance of the logger.
+
+## <a name="PayloadUnaryClientInterceptor">func</a> [PayloadUnaryClientInterceptor](./payload_interceptors.go#L61)
+``` go
+func PayloadUnaryClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor
+```
+PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses.
+
+## <a name="PayloadUnaryServerInterceptor">func</a> [PayloadUnaryServerInterceptor](./payload_interceptors.go#L28)
+``` go
+func PayloadUnaryServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor
+```
+PayloadUnaryServerInterceptor returns a new unary server interceptors that logs the payloads of requests.
+
+This *only* works when placed *after* the `grpc_logrus.UnaryServerInterceptor`. However, the logging can be done to a
+separate instance of the logger.
+
+## <a name="ReplaceGrpcLogger">func</a> [ReplaceGrpcLogger](./grpclogger.go#L13)
+``` go
+func ReplaceGrpcLogger(logger *logrus.Entry)
+```
+ReplaceGrpcLogger sets the given logrus.Logger as a gRPC-level logger.
+This should be called *before* any other initialization, preferably from init() functions.
+
+## <a name="StreamClientInterceptor">func</a> [StreamClientInterceptor](./client_interceptors.go#L28)
+``` go
+func StreamClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamClientInterceptor
+```
+StreamServerInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.
+
+## <a name="StreamServerInterceptor">func</a> [StreamServerInterceptor](./server_interceptors.go#L50)
+``` go
+func StreamServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamServerInterceptor
+```
+StreamServerInterceptor returns a new streaming server interceptor that adds logrus.Entry to the context.
+
+## <a name="UnaryClientInterceptor">func</a> [UnaryClientInterceptor](./client_interceptors.go#L16)
+``` go
+func UnaryClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryClientInterceptor
+```
+UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.
+
+## <a name="UnaryServerInterceptor">func</a> [UnaryServerInterceptor](./server_interceptors.go#L25)
+``` go
+func UnaryServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor
+```
+PayloadUnaryServerInterceptor returns a new unary server interceptors that adds logrus.Entry to the context.
+
+## <a name="CodeToLevel">type</a> [CodeToLevel](./options.go#L51)
+``` go
+type CodeToLevel func(code codes.Code) logrus.Level
+```
+CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.
+
+## <a name="DurationToField">type</a> [DurationToField](./options.go#L54)
+``` go
+type DurationToField func(duration time.Duration) (key string, value interface{})
+```
+DurationToField function defines how to produce duration fields for logging
+
+## <a name="Option">type</a> [Option](./options.go#L48)
+``` go
+type Option func(*options)
+```
+
+### <a name="WithCodes">func</a> [WithCodes](./options.go#L64)
+``` go
+func WithCodes(f grpc_logging.ErrorToCode) Option
+```
+WithCodes customizes the function for mapping errors to error codes.
+
+### <a name="WithDurationField">func</a> [WithDurationField](./options.go#L71)
+``` go
+func WithDurationField(f DurationToField) Option
+```
+WithDurationField customizes the function for mapping request durations to log fields.
+
+### <a name="WithLevels">func</a> [WithLevels](./options.go#L57)
+``` go
+func WithLevels(f CodeToLevel) Option
+```
+WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/client_interceptors.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/client_interceptors.go
new file mode 100644
index 000000000..c11e91514
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/client_interceptors.go
@@ -0,0 +1,65 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logrus
+
+import (
+ "path"
+ "time"
+
+ "github.com/Sirupsen/logrus"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+)
+
+// UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.
+func UnaryClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryClientInterceptor {
+ o := evaluateClientOpt(opts)
+ return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+ fields := newClientLoggerFields(ctx, method)
+ startTime := time.Now()
+ err := invoker(ctx, method, req, reply, cc, opts...)
+ logFinalClientLine(o, entry.WithFields(fields), startTime, err, "finished client unary call")
+ return err
+ }
+}
+
+// StreamServerInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.
+func StreamClientInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamClientInterceptor {
+ o := evaluateClientOpt(opts)
+ return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ fields := newClientLoggerFields(ctx, method)
+ startTime := time.Now()
+ clientStream, err := streamer(ctx, desc, cc, method, opts...)
+ logFinalClientLine(o, entry.WithFields(fields), startTime, err, "finished client streaming call")
+ return clientStream, err
+ }
+}
+
+func logFinalClientLine(o *options, entry *logrus.Entry, startTime time.Time, err error, msg string) {
+ code := o.codeFunc(err)
+ level := o.levelFunc(code)
+ durField, durVal := o.durationFunc(time.Now().Sub(startTime))
+ fields := logrus.Fields{
+ "grpc.code": code.String(),
+ durField: durVal,
+ }
+ if err != nil {
+ fields[logrus.ErrorKey] = err
+ }
+ levelLogf(
+ entry.WithFields(fields),
+ level,
+ msg)
+}
+
+func newClientLoggerFields(ctx context.Context, fullMethodString string) logrus.Fields {
+ service := path.Dir(fullMethodString)[1:]
+ method := path.Base(fullMethodString)
+ return logrus.Fields{
+ SystemField: "grpc",
+ KindField: "client",
+ "grpc.service": service,
+ "grpc.method": method,
+ }
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/context.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/context.go
new file mode 100644
index 000000000..a15ad90b3
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/context.go
@@ -0,0 +1,34 @@
+// Copyright 2016 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logrus
+
+import (
+ "github.com/Sirupsen/logrus"
+ "github.com/grpc-ecosystem/go-grpc-middleware/tags"
+ "golang.org/x/net/context"
+)
+
+type ctxMarker struct{}
+
+var (
+ ctxMarkerKey = &ctxMarker{}
+)
+
+// Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.
+//
+// If the grpc_logrus middleware wasn't used, a no-op `logrus.Entry` is returned. This makes it safe to
+// use regardless.
+func Extract(ctx context.Context) *logrus.Entry {
+ l, ok := ctx.Value(ctxMarkerKey).(*logrus.Entry)
+ if !ok {
+ return logrus.NewEntry(nullLogger)
+ }
+ // Add grpc_ctxtags tags metadata until now.
+ return l.WithFields(logrus.Fields(grpc_ctxtags.Extract(ctx).Values()))
+}
+
+func toContext(ctx context.Context, entry *logrus.Entry) context.Context {
+ return context.WithValue(ctx, ctxMarkerKey, entry)
+
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/doc.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/doc.go
new file mode 100644
index 000000000..0b91720f4
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/doc.go
@@ -0,0 +1,22 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+/*
+`grpc_logrus` is a gRPC logging middleware backed by Logrus loggers
+
+It accepts a user-configured `logrus.Entry` that will be used for logging completed gRPC calls. The same
+`logrus.Entry` will be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code.
+
+You can use `Extract` to log into a request-scoped `logrus.Entry` instance in your handler code. The fields set on the
+logger correspond to the grpc_ctxtags.Tags attached to the context.
+
+This package also implements request and response *payload* logging, both for server-side and client-side. These will be
+logged as structured `jsonbp` fields for every message received/sent (both unary and streaming). For that please use
+`Payload*Interceptor` functions for that. Please note that the user-provided function that determines whetether to log
+the full request/response payload needs to be written with care, this can significantly slow down gRPC.
+
+Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
+
+Please see examples and tests for examples of use.
+*/
+package grpc_logrus
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/grpclogger.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/grpclogger.go
new file mode 100644
index 000000000..8e63d047b
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/grpclogger.go
@@ -0,0 +1,15 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logrus
+
+import (
+ "github.com/Sirupsen/logrus"
+ "google.golang.org/grpc/grpclog"
+)
+
+// ReplaceGrpcLogger sets the given logrus.Logger as a gRPC-level logger.
+// This should be called *before* any other initialization, preferably from init() functions.
+func ReplaceGrpcLogger(logger *logrus.Entry) {
+ grpclog.SetLogger(logger.WithField("system", SystemField))
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/noop.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/noop.go
new file mode 100644
index 000000000..da416b602
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/noop.go
@@ -0,0 +1,16 @@
+package grpc_logrus
+
+import (
+ "io/ioutil"
+
+ "github.com/Sirupsen/logrus"
+)
+
+var (
+ nullLogger = &logrus.Logger{
+ Out: ioutil.Discard,
+ Formatter: new(logrus.TextFormatter),
+ Hooks: make(logrus.LevelHooks),
+ Level: logrus.PanicLevel,
+ }
+)
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/options.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/options.go
new file mode 100644
index 000000000..35eb4f07a
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/options.go
@@ -0,0 +1,176 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logrus
+
+import (
+ "time"
+
+ "github.com/Sirupsen/logrus"
+ "github.com/grpc-ecosystem/go-grpc-middleware/logging"
+ "google.golang.org/grpc/codes"
+)
+
+var (
+ defaultOptions = &options{
+ levelFunc: nil,
+ codeFunc: grpc_logging.DefaultErrorToCode,
+ durationFunc: DefaultDurationToField,
+ }
+)
+
+type options struct {
+ levelFunc CodeToLevel
+ codeFunc grpc_logging.ErrorToCode
+ durationFunc DurationToField
+}
+
+func evaluateServerOpt(opts []Option) *options {
+ optCopy := &options{}
+ *optCopy = *defaultOptions
+ optCopy.levelFunc = DefaultCodeToLevel
+ for _, o := range opts {
+ o(optCopy)
+ }
+ return optCopy
+}
+
+func evaluateClientOpt(opts []Option) *options {
+ optCopy := &options{}
+ *optCopy = *defaultOptions
+ optCopy.levelFunc = DefaultClientCodeToLevel
+ for _, o := range opts {
+ o(optCopy)
+ }
+ return optCopy
+}
+
+type Option func(*options)
+
+// CodeToLevel function defines the mapping between gRPC return codes and interceptor log level.
+type CodeToLevel func(code codes.Code) logrus.Level
+
+// DurationToField function defines how to produce duration fields for logging
+type DurationToField func(duration time.Duration) (key string, value interface{})
+
+// WithLevels customizes the function for mapping gRPC return codes and interceptor log level statements.
+func WithLevels(f CodeToLevel) Option {
+ return func(o *options) {
+ o.levelFunc = f
+ }
+}
+
+// WithCodes customizes the function for mapping errors to error codes.
+func WithCodes(f grpc_logging.ErrorToCode) Option {
+ return func(o *options) {
+ o.codeFunc = f
+ }
+}
+
+// WithDurationField customizes the function for mapping request durations to log fields.
+func WithDurationField(f DurationToField) Option {
+ return func(o *options) {
+ o.durationFunc = f
+ }
+}
+
+// DefaultCodeToLevel is the default implementation of gRPC return codes to log levels for server side.
+func DefaultCodeToLevel(code codes.Code) logrus.Level {
+ switch code {
+ case codes.OK:
+ return logrus.InfoLevel
+ case codes.Canceled:
+ return logrus.InfoLevel
+ case codes.Unknown:
+ return logrus.ErrorLevel
+ case codes.InvalidArgument:
+ return logrus.InfoLevel
+ case codes.DeadlineExceeded:
+ return logrus.WarnLevel
+ case codes.NotFound:
+ return logrus.InfoLevel
+ case codes.AlreadyExists:
+ return logrus.InfoLevel
+ case codes.PermissionDenied:
+ return logrus.WarnLevel
+ case codes.Unauthenticated:
+ return logrus.InfoLevel // unauthenticated requests can happen
+ case codes.ResourceExhausted:
+ return logrus.WarnLevel
+ case codes.FailedPrecondition:
+ return logrus.WarnLevel
+ case codes.Aborted:
+ return logrus.WarnLevel
+ case codes.OutOfRange:
+ return logrus.WarnLevel
+ case codes.Unimplemented:
+ return logrus.ErrorLevel
+ case codes.Internal:
+ return logrus.ErrorLevel
+ case codes.Unavailable:
+ return logrus.WarnLevel
+ case codes.DataLoss:
+ return logrus.ErrorLevel
+ default:
+ return logrus.ErrorLevel
+ }
+}
+
+// DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.
+func DefaultClientCodeToLevel(code codes.Code) logrus.Level {
+ switch code {
+ case codes.OK:
+ return logrus.DebugLevel
+ case codes.Canceled:
+ return logrus.DebugLevel
+ case codes.Unknown:
+ return logrus.InfoLevel
+ case codes.InvalidArgument:
+ return logrus.DebugLevel
+ case codes.DeadlineExceeded:
+ return logrus.InfoLevel
+ case codes.NotFound:
+ return logrus.DebugLevel
+ case codes.AlreadyExists:
+ return logrus.DebugLevel
+ case codes.PermissionDenied:
+ return logrus.InfoLevel
+ case codes.Unauthenticated:
+ return logrus.InfoLevel // unauthenticated requests can happen
+ case codes.ResourceExhausted:
+ return logrus.DebugLevel
+ case codes.FailedPrecondition:
+ return logrus.DebugLevel
+ case codes.Aborted:
+ return logrus.DebugLevel
+ case codes.OutOfRange:
+ return logrus.DebugLevel
+ case codes.Unimplemented:
+ return logrus.WarnLevel
+ case codes.Internal:
+ return logrus.WarnLevel
+ case codes.Unavailable:
+ return logrus.WarnLevel
+ case codes.DataLoss:
+ return logrus.WarnLevel
+ default:
+ return logrus.InfoLevel
+ }
+}
+
+// DefaultDurationToField is the default implementation of converting request duration to a log field (key and value).
+var DefaultDurationToField = DurationToTimeMillisField
+
+// DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.
+func DurationToTimeMillisField(duration time.Duration) (key string, value interface{}) {
+ return "grpc.time_ms", durationToMilliseconds(duration)
+}
+
+// DurationToDurationField uses the duration value to log the request duration.
+func DurationToDurationField(duration time.Duration) (key string, value interface{}) {
+ return "grpc.duration", duration
+}
+
+func durationToMilliseconds(duration time.Duration) float32 {
+ return float32(duration.Nanoseconds() / 1000 / 1000)
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/payload_interceptors.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/payload_interceptors.go
new file mode 100644
index 000000000..964a6f91e
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/payload_interceptors.go
@@ -0,0 +1,147 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logrus
+
+import (
+ "bytes"
+
+ "fmt"
+
+ "github.com/Sirupsen/logrus"
+ "github.com/golang/protobuf/jsonpb"
+ "github.com/golang/protobuf/proto"
+ "github.com/grpc-ecosystem/go-grpc-middleware/logging"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+)
+
+var (
+ // JsonPBMarshaller is the marshaller used for serializing protobuf messages.
+ JsonPbMarshaller = &jsonpb.Marshaler{}
+)
+
+// PayloadUnaryServerInterceptor returns a new unary server interceptors that logs the payloads of requests.
+//
+// This *only* works when placed *after* the `grpc_logrus.UnaryServerInterceptor`. However, the logging can be done to a
+// separate instance of the logger.
+func PayloadUnaryServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.UnaryServerInterceptor {
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ if !decider(ctx, info.FullMethod, info.Server) {
+ return handler(ctx, req)
+ }
+ // Use the provided logrus.Entry for logging but use the fields from context.
+ logEntry := entry.WithFields(Extract(ctx).Data)
+ logProtoMessageAsJson(logEntry, req, "grpc.request.content", "server request payload logged as grpc.request.content field")
+ resp, err := handler(ctx, req)
+ if err == nil {
+ logProtoMessageAsJson(logEntry, resp, "grpc.response.content", "server response payload logged as grpc.request.content field")
+ }
+ return resp, err
+ }
+}
+
+// PayloadUnaryServerInterceptor returns a new server server interceptors that logs the payloads of requests.
+//
+// This *only* works when placed *after* the `grpc_logrus.StreamServerInterceptor`. However, the logging can be done to a
+// separate instance of the logger.
+func PayloadStreamServerInterceptor(entry *logrus.Entry, decider grpc_logging.ServerPayloadLoggingDecider) grpc.StreamServerInterceptor {
+ return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ if !decider(stream.Context(), info.FullMethod, srv) {
+ return handler(srv, stream)
+ }
+ // Use the provided logrus.Entry for logging but use the fields from context.
+ logEntry := entry.WithFields(Extract(stream.Context()).Data)
+ newStream := &loggingServerStream{ServerStream: stream, entry: logEntry}
+ return handler(srv, newStream)
+ }
+}
+
+// PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses.
+func PayloadUnaryClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.UnaryClientInterceptor {
+ return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+ if !decider(ctx, method) {
+ return invoker(ctx, method, req, reply, cc, opts...)
+ }
+ logEntry := entry.WithFields(newClientLoggerFields(ctx, method))
+ logProtoMessageAsJson(logEntry, req, "grpc.request.content", "client request payload logged as grpc.request.content")
+ err := invoker(ctx, method, req, reply, cc, opts...)
+ if err == nil {
+ logProtoMessageAsJson(logEntry, reply, "grpc.response.content", "client response payload logged as grpc.response.content")
+ }
+ return err
+ }
+}
+
+// PayloadStreamServerInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses.
+func PayloadStreamClientInterceptor(entry *logrus.Entry, decider grpc_logging.ClientPayloadLoggingDecider) grpc.StreamClientInterceptor {
+ return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+ if !decider(ctx, method) {
+ return streamer(ctx, desc, cc, method, opts...)
+ }
+ logEntry := entry.WithFields(newClientLoggerFields(ctx, method))
+ clientStream, err := streamer(ctx, desc, cc, method, opts...)
+ newStream := &loggingClientStream{ClientStream: clientStream, entry: logEntry}
+ return newStream, err
+ }
+}
+
+type loggingClientStream struct {
+ grpc.ClientStream
+ entry *logrus.Entry
+}
+
+func (l *loggingClientStream) SendMsg(m interface{}) error {
+ err := l.ClientStream.SendMsg(m)
+ if err == nil {
+ logProtoMessageAsJson(l.entry, m, "grpc.request.content", "server request payload logged as grpc.request.content field")
+ }
+ return err
+}
+
+func (l *loggingClientStream) RecvMsg(m interface{}) error {
+ err := l.ClientStream.RecvMsg(m)
+ if err == nil {
+ logProtoMessageAsJson(l.entry, m, "grpc.response.content", "server response payload logged as grpc.response.content field")
+ }
+ return err
+}
+
+type loggingServerStream struct {
+ grpc.ServerStream
+ entry *logrus.Entry
+}
+
+func (l *loggingServerStream) SendMsg(m interface{}) error {
+ err := l.ServerStream.SendMsg(m)
+ if err == nil {
+ logProtoMessageAsJson(l.entry, m, "grpc.response.content", "server response payload logged as grpc.response.content field")
+ }
+ return err
+}
+
+func (l *loggingServerStream) RecvMsg(m interface{}) error {
+ err := l.ServerStream.RecvMsg(m)
+ if err == nil {
+ logProtoMessageAsJson(l.entry, m, "grpc.request.content", "server request payload logged as grpc.request.content field")
+ }
+ return err
+}
+
+func logProtoMessageAsJson(entry *logrus.Entry, pbMsg interface{}, key string, msg string) {
+ if p, ok := pbMsg.(proto.Message); ok {
+ entry.WithField(key, &jsonpbMarshalleble{p}).Info(msg)
+ }
+}
+
+type jsonpbMarshalleble struct {
+ proto.Message
+}
+
+func (j *jsonpbMarshalleble) MarshalJSON() ([]byte, error) {
+ b := &bytes.Buffer{}
+ if err := JsonPbMarshaller.Marshal(b, j.Message); err != nil {
+ return nil, fmt.Errorf("jsonpb serializer failed: %v", err)
+ }
+ return b.Bytes(), nil
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/server_interceptors.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/server_interceptors.go
new file mode 100644
index 000000000..10c312b1e
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/server_interceptors.go
@@ -0,0 +1,105 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_logrus
+
+import (
+ "path"
+ "time"
+
+ "github.com/Sirupsen/logrus"
+ "github.com/grpc-ecosystem/go-grpc-middleware"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+)
+
+var (
+ // SystemField is used in every log statement made through grpc_logrus. Can be overwritten before any initialization code.
+ SystemField = "system"
+
+ // KindField describes the log gield used to incicate whether this is a server or a client log statment.
+ KindField = "span.kind"
+)
+
+// PayloadUnaryServerInterceptor returns a new unary server interceptors that adds logrus.Entry to the context.
+func UnaryServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.UnaryServerInterceptor {
+ o := evaluateServerOpt(opts)
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ newCtx := newLoggerForCall(ctx, entry, info.FullMethod)
+ startTime := time.Now()
+ resp, err := handler(newCtx, req)
+ code := o.codeFunc(err)
+ level := o.levelFunc(code)
+ durField, durVal := o.durationFunc(time.Now().Sub(startTime))
+ fields := logrus.Fields{
+ "grpc.code": code.String(),
+ durField: durVal,
+ }
+ if err != nil {
+ fields[logrus.ErrorKey] = err
+ }
+ levelLogf(
+ Extract(newCtx).WithFields(fields), // re-extract logger from newCtx, as it may have extra fields that changed in the holder.
+ level,
+ "finished unary call")
+ return resp, err
+ }
+}
+
+// StreamServerInterceptor returns a new streaming server interceptor that adds logrus.Entry to the context.
+func StreamServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamServerInterceptor {
+ o := evaluateServerOpt(opts)
+ return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ newCtx := newLoggerForCall(stream.Context(), entry, info.FullMethod)
+ wrapped := grpc_middleware.WrapServerStream(stream)
+ wrapped.WrappedContext = newCtx
+
+ startTime := time.Now()
+ err := handler(srv, wrapped)
+ code := o.codeFunc(err)
+ level := o.levelFunc(code)
+ durField, durVal := o.durationFunc(time.Now().Sub(startTime))
+ fields := logrus.Fields{
+ "grpc.code": code.String(),
+ durField: durVal,
+ }
+ if err != nil {
+ fields[logrus.ErrorKey] = err
+ }
+ levelLogf(
+ Extract(newCtx).WithFields(fields), // re-extract logger from newCtx, as it may have extra fields that changed in the holder.
+ level,
+ "finished streaming call")
+ return err
+ }
+}
+
+func levelLogf(entry *logrus.Entry, level logrus.Level, format string, args ...interface{}) {
+ switch level {
+ case logrus.DebugLevel:
+ entry.Debugf(format, args...)
+ case logrus.InfoLevel:
+ entry.Infof(format, args...)
+ case logrus.WarnLevel:
+ entry.Warningf(format, args...)
+ case logrus.ErrorLevel:
+ entry.Errorf(format, args...)
+ case logrus.FatalLevel:
+ entry.Fatalf(format, args...)
+ case logrus.PanicLevel:
+ entry.Panicf(format, args...)
+ }
+}
+
+func newLoggerForCall(ctx context.Context, entry *logrus.Entry, fullMethodString string) context.Context {
+ service := path.Dir(fullMethodString)[1:]
+ method := path.Base(fullMethodString)
+ callLog := entry.WithFields(
+ logrus.Fields{
+ SystemField: "grpc",
+ KindField: "server",
+ "grpc.service": service,
+ "grpc.method": method,
+ })
+ return toContext(ctx, callLog)
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/DOC.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/DOC.md
new file mode 100644
index 000000000..62ec88118
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/DOC.md
@@ -0,0 +1,157 @@
+# grpc_ctxtags
+`import "github.com/grpc-ecosystem/go-grpc-middleware/tags"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+* [Examples](#pkg-examples)
+
+## <a name="pkg-overview">Overview</a>
+`grpc_ctxtags` adds a Tag object to the context that can be used by other middleware to add context about a request.
+
+### Request Context Tags
+Tags describe information about the request, and can be set and used by other middleware, or handlers. Tags are used
+for logging and tracing of requests. Tags are populated both upwards, *and* downwards in the interceptor-handler stack.
+
+You can automatically extract tags (in `grpc.request.<field_name>`) from request payloads (in unary and server-streaming)
+by passing in the `WithFieldExtractor` option.
+
+If a user doesn't use the interceptors that initialize the `Tags` object, all operations following from an `Extract(ctx)`
+will be no-ops. This is to ensure that code doesn't panic if the interceptors weren't used.
+
+Tags fields are typed, and shallow and should follow the OpenTracing semantics convention:
+<a href="https://github.com/opentracing/specification/blob/master/semantic_conventions.md">https://github.com/opentracing/specification/blob/master/semantic_conventions.md</a>
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+opts := []grpc_ctxtags.Option{
+ grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.TagBasedRequestFieldExtractor("log_fields")),
+ }
+ server := grpc.NewServer(
+ grpc.StreamInterceptor(grpc_ctxtags.StreamServerInterceptor(opts...)),
+ grpc.UnaryInterceptor(grpc_ctxtags.UnaryServerInterceptor(opts...)),
+ )
+ return server
+```
+
+</details>
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- [github.com/grpc-ecosystem/go-grpc-middleware](./..)
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+- [google.golang.org/grpc/peer](https://godoc.org/google.golang.org/grpc/peer)
+
+## <a name="pkg-index">Index</a>
+* [func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{}](#CodeGenRequestFieldExtractor)
+* [func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor](#StreamServerInterceptor)
+* [func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor](#UnaryServerInterceptor)
+* [type Option](#Option)
+ * [func WithFieldExtractor(f RequestFieldExtractorFunc) Option](#WithFieldExtractor)
+* [type RequestFieldExtractorFunc](#RequestFieldExtractorFunc)
+ * [func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc](#TagBasedRequestFieldExtractor)
+* [type Tags](#Tags)
+ * [func Extract(ctx context.Context) \*Tags](#Extract)
+ * [func (t \*Tags) Has(key string) bool](#Tags.Has)
+ * [func (t \*Tags) Set(key string, value interface{}) \*Tags](#Tags.Set)
+ * [func (t \*Tags) Values() map[string]interface{}](#Tags.Values)
+
+#### <a name="pkg-examples">Examples</a>
+* [Package (Initialization)](#example__initialization)
+
+#### <a name="pkg-files">Package files</a>
+[context.go](./context.go) [doc.go](./doc.go) [fieldextractor.go](./fieldextractor.go) [interceptors.go](./interceptors.go) [options.go](./options.go)
+
+## <a name="CodeGenRequestFieldExtractor">func</a> [CodeGenRequestFieldExtractor](./fieldextractor.go#L23)
+``` go
+func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{}
+```
+CodeGenRequestFieldExtractor is a function that relies on code-generated functions that export log fields from requests.
+These are usually coming from a protoc-plugin that generates additional information based on custom field options.
+
+## <a name="StreamServerInterceptor">func</a> [StreamServerInterceptor](./interceptors.go#L26)
+``` go
+func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor
+```
+StreamServerInterceptor returns a new streaming server interceptor that sets the values for request tags.
+
+## <a name="UnaryServerInterceptor">func</a> [UnaryServerInterceptor](./interceptors.go#L14)
+``` go
+func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor
+```
+UnaryServerInterceptor returns a new unary server interceptors that sets the values for request tags.
+
+## <a name="Option">type</a> [Option](./options.go#L25)
+``` go
+type Option func(*options)
+```
+
+### <a name="WithFieldExtractor">func</a> [WithFieldExtractor](./options.go#L28)
+``` go
+func WithFieldExtractor(f RequestFieldExtractorFunc) Option
+```
+WithFieldExtractor customizes the function for extracting log fields from protobuf messages.
+
+## <a name="RequestFieldExtractorFunc">type</a> [RequestFieldExtractorFunc](./fieldextractor.go#L13)
+``` go
+type RequestFieldExtractorFunc func(fullMethod string, req interface{}) map[string]interface{}
+```
+RequestFieldExtractorFunc is a user-provided function that extracts field information from a gRPC request.
+It is called from tags middleware on arrival of unary request or a server-stream request.
+Keys and values will be added to the context tags of the request. If there are no fields, you should return a nil.
+
+### <a name="TagBasedRequestFieldExtractor">func</a> [TagBasedRequestFieldExtractor](./fieldextractor.go#L43)
+``` go
+func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc
+```
+TagedRequestFiledExtractor is a function that relies on Go struct tags to export log fields from requests.
+These are usualy coming from a protoc-plugin, such as Gogo protobuf.
+
+ message Metadata {
+ repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ];
+ }
+
+The tagName is configurable using the tagName variable. Here it would be "log_field".
+
+## <a name="Tags">type</a> [Tags](./context.go#L15-L17)
+``` go
+type Tags struct {
+ // contains filtered or unexported fields
+}
+```
+Tags is the struct used for storing request tags between Context calls.
+This object is *not* thread safe, and should be handled only in the context of the request.
+
+### <a name="Extract">func</a> [Extract](./context.go#L39)
+``` go
+func Extract(ctx context.Context) *Tags
+```
+Extracts returns a pre-existing Tags object in the Context.
+If the context wasn't set in a tag interceptor, a no-op Tag storage is returned that will *not* be propagated in context.
+
+### <a name="Tags.Has">func</a> (\*Tags) [Has](./context.go#L26)
+``` go
+func (t *Tags) Has(key string) bool
+```
+Has checks if the given key exists.
+
+### <a name="Tags.Set">func</a> (\*Tags) [Set](./context.go#L20)
+``` go
+func (t *Tags) Set(key string, value interface{}) *Tags
+```
+Set sets the given key in the metadata tags.
+
+### <a name="Tags.Values">func</a> (\*Tags) [Values](./context.go#L33)
+``` go
+func (t *Tags) Values() map[string]interface{}
+```
+Values returns a map of key to values.
+Do not modify the underlying map, please use Set instead.
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/README.md b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/README.md
new file mode 100644
index 000000000..62ec88118
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/README.md
@@ -0,0 +1,157 @@
+# grpc_ctxtags
+`import "github.com/grpc-ecosystem/go-grpc-middleware/tags"`
+
+* [Overview](#pkg-overview)
+* [Imported Packages](#pkg-imports)
+* [Index](#pkg-index)
+* [Examples](#pkg-examples)
+
+## <a name="pkg-overview">Overview</a>
+`grpc_ctxtags` adds a Tag object to the context that can be used by other middleware to add context about a request.
+
+### Request Context Tags
+Tags describe information about the request, and can be set and used by other middleware, or handlers. Tags are used
+for logging and tracing of requests. Tags are populated both upwards, *and* downwards in the interceptor-handler stack.
+
+You can automatically extract tags (in `grpc.request.<field_name>`) from request payloads (in unary and server-streaming)
+by passing in the `WithFieldExtractor` option.
+
+If a user doesn't use the interceptors that initialize the `Tags` object, all operations following from an `Extract(ctx)`
+will be no-ops. This is to ensure that code doesn't panic if the interceptors weren't used.
+
+Tags fields are typed, and shallow and should follow the OpenTracing semantics convention:
+<a href="https://github.com/opentracing/specification/blob/master/semantic_conventions.md">https://github.com/opentracing/specification/blob/master/semantic_conventions.md</a>
+
+#### Example:
+
+<details>
+<summary>Click to expand code.</summary>
+
+```go
+opts := []grpc_ctxtags.Option{
+ grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.TagBasedRequestFieldExtractor("log_fields")),
+ }
+ server := grpc.NewServer(
+ grpc.StreamInterceptor(grpc_ctxtags.StreamServerInterceptor(opts...)),
+ grpc.UnaryInterceptor(grpc_ctxtags.UnaryServerInterceptor(opts...)),
+ )
+ return server
+```
+
+</details>
+
+## <a name="pkg-imports">Imported Packages</a>
+
+- [github.com/grpc-ecosystem/go-grpc-middleware](./..)
+- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
+- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
+- [google.golang.org/grpc/peer](https://godoc.org/google.golang.org/grpc/peer)
+
+## <a name="pkg-index">Index</a>
+* [func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{}](#CodeGenRequestFieldExtractor)
+* [func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor](#StreamServerInterceptor)
+* [func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor](#UnaryServerInterceptor)
+* [type Option](#Option)
+ * [func WithFieldExtractor(f RequestFieldExtractorFunc) Option](#WithFieldExtractor)
+* [type RequestFieldExtractorFunc](#RequestFieldExtractorFunc)
+ * [func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc](#TagBasedRequestFieldExtractor)
+* [type Tags](#Tags)
+ * [func Extract(ctx context.Context) \*Tags](#Extract)
+ * [func (t \*Tags) Has(key string) bool](#Tags.Has)
+ * [func (t \*Tags) Set(key string, value interface{}) \*Tags](#Tags.Set)
+ * [func (t \*Tags) Values() map[string]interface{}](#Tags.Values)
+
+#### <a name="pkg-examples">Examples</a>
+* [Package (Initialization)](#example__initialization)
+
+#### <a name="pkg-files">Package files</a>
+[context.go](./context.go) [doc.go](./doc.go) [fieldextractor.go](./fieldextractor.go) [interceptors.go](./interceptors.go) [options.go](./options.go)
+
+## <a name="CodeGenRequestFieldExtractor">func</a> [CodeGenRequestFieldExtractor](./fieldextractor.go#L23)
+``` go
+func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{}
+```
+CodeGenRequestFieldExtractor is a function that relies on code-generated functions that export log fields from requests.
+These are usually coming from a protoc-plugin that generates additional information based on custom field options.
+
+## <a name="StreamServerInterceptor">func</a> [StreamServerInterceptor](./interceptors.go#L26)
+``` go
+func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor
+```
+StreamServerInterceptor returns a new streaming server interceptor that sets the values for request tags.
+
+## <a name="UnaryServerInterceptor">func</a> [UnaryServerInterceptor](./interceptors.go#L14)
+``` go
+func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor
+```
+UnaryServerInterceptor returns a new unary server interceptors that sets the values for request tags.
+
+## <a name="Option">type</a> [Option](./options.go#L25)
+``` go
+type Option func(*options)
+```
+
+### <a name="WithFieldExtractor">func</a> [WithFieldExtractor](./options.go#L28)
+``` go
+func WithFieldExtractor(f RequestFieldExtractorFunc) Option
+```
+WithFieldExtractor customizes the function for extracting log fields from protobuf messages.
+
+## <a name="RequestFieldExtractorFunc">type</a> [RequestFieldExtractorFunc](./fieldextractor.go#L13)
+``` go
+type RequestFieldExtractorFunc func(fullMethod string, req interface{}) map[string]interface{}
+```
+RequestFieldExtractorFunc is a user-provided function that extracts field information from a gRPC request.
+It is called from tags middleware on arrival of unary request or a server-stream request.
+Keys and values will be added to the context tags of the request. If there are no fields, you should return a nil.
+
+### <a name="TagBasedRequestFieldExtractor">func</a> [TagBasedRequestFieldExtractor](./fieldextractor.go#L43)
+``` go
+func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc
+```
+TagedRequestFiledExtractor is a function that relies on Go struct tags to export log fields from requests.
+These are usualy coming from a protoc-plugin, such as Gogo protobuf.
+
+ message Metadata {
+ repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ];
+ }
+
+The tagName is configurable using the tagName variable. Here it would be "log_field".
+
+## <a name="Tags">type</a> [Tags](./context.go#L15-L17)
+``` go
+type Tags struct {
+ // contains filtered or unexported fields
+}
+```
+Tags is the struct used for storing request tags between Context calls.
+This object is *not* thread safe, and should be handled only in the context of the request.
+
+### <a name="Extract">func</a> [Extract](./context.go#L39)
+``` go
+func Extract(ctx context.Context) *Tags
+```
+Extracts returns a pre-existing Tags object in the Context.
+If the context wasn't set in a tag interceptor, a no-op Tag storage is returned that will *not* be propagated in context.
+
+### <a name="Tags.Has">func</a> (\*Tags) [Has](./context.go#L26)
+``` go
+func (t *Tags) Has(key string) bool
+```
+Has checks if the given key exists.
+
+### <a name="Tags.Set">func</a> (\*Tags) [Set](./context.go#L20)
+``` go
+func (t *Tags) Set(key string, value interface{}) *Tags
+```
+Set sets the given key in the metadata tags.
+
+### <a name="Tags.Values">func</a> (\*Tags) [Values](./context.go#L33)
+``` go
+func (t *Tags) Values() map[string]interface{}
+```
+Values returns a map of key to values.
+Do not modify the underlying map, please use Set instead.
+
+- - -
+Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd) \ No newline at end of file
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/context.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/context.go
new file mode 100644
index 000000000..15a1c0b65
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/context.go
@@ -0,0 +1,49 @@
+package grpc_ctxtags
+
+import "context"
+
+type ctxMarker struct{}
+
+var (
+ // ctxMarkerKey is the Context value marker used by *all* logging middleware.
+ // The logging middleware object must interf
+ ctxMarkerKey = &ctxMarker{}
+)
+
+// Tags is the struct used for storing request tags between Context calls.
+// This object is *not* thread safe, and should be handled only in the context of the request.
+type Tags struct {
+ values map[string]interface{}
+}
+
+// Set sets the given key in the metadata tags.
+func (t *Tags) Set(key string, value interface{}) *Tags {
+ t.values[key] = value
+ return t
+}
+
+// Has checks if the given key exists.
+func (t *Tags) Has(key string) bool {
+ _, ok := t.values[key]
+ return ok
+}
+
+// Values returns a map of key to values.
+// Do not modify the underlying map, please use Set instead.
+func (t *Tags) Values() map[string]interface{} {
+ return t.values
+}
+
+// Extracts returns a pre-existing Tags object in the Context.
+// If the context wasn't set in a tag interceptor, a no-op Tag storage is returned that will *not* be propagated in context.
+func Extract(ctx context.Context) *Tags {
+ t, ok := ctx.Value(ctxMarkerKey).(*Tags)
+ if !ok {
+ return &Tags{values: make(map[string]interface{})}
+ }
+ return t
+}
+
+func setInContext(ctx context.Context, tags *Tags) context.Context {
+ return context.WithValue(ctx, ctxMarkerKey, tags)
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/doc.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/doc.go
new file mode 100644
index 000000000..8bfdb0ddc
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/doc.go
@@ -0,0 +1,21 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+/*
+`grpc_ctxtags` adds a Tag object to the context that can be used by other middleware to add context about a request.
+
+Request Context Tags
+
+Tags describe information about the request, and can be set and used by other middleware, or handlers. Tags are used
+for logging and tracing of requests. Tags are populated both upwards, *and* downwards in the interceptor-handler stack.
+
+You can automatically extract tags (in `grpc.request.<field_name>`) from request payloads (in unary and server-streaming)
+by passing in the `WithFieldExtractor` option.
+
+If a user doesn't use the interceptors that initialize the `Tags` object, all operations following from an `Extract(ctx)`
+will be no-ops. This is to ensure that code doesn't panic if the interceptors weren't used.
+
+Tags fields are typed, and shallow and should follow the OpenTracing semantics convention:
+https://github.com/opentracing/specification/blob/master/semantic_conventions.md
+*/
+package grpc_ctxtags
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/fieldextractor.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/fieldextractor.go
new file mode 100644
index 000000000..1d7c1a7fa
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/fieldextractor.go
@@ -0,0 +1,85 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_ctxtags
+
+import (
+ "reflect"
+)
+
+// RequestFieldExtractorFunc is a user-provided function that extracts field information from a gRPC request.
+// It is called from tags middleware on arrival of unary request or a server-stream request.
+// Keys and values will be added to the context tags of the request. If there are no fields, you should return a nil.
+type RequestFieldExtractorFunc func(fullMethod string, req interface{}) map[string]interface{}
+
+type requestFieldsExtractor interface {
+ // ExtractRequestFields is a method declared on a Protobuf message that extracts fields from the interface.
+ // The values from the extracted fields should be set in the appendToMap, in order to avoid allocations.
+ ExtractRequestFields(appendToMap map[string]interface{})
+}
+
+// CodeGenRequestFieldExtractor is a function that relies on code-generated functions that export log fields from requests.
+// These are usually coming from a protoc-plugin that generates additional information based on custom field options.
+func CodeGenRequestFieldExtractor(fullMethod string, req interface{}) map[string]interface{} {
+ if ext, ok := req.(requestFieldsExtractor); ok {
+ retMap := make(map[string]interface{})
+ ext.ExtractRequestFields(retMap)
+ if len(retMap) == 0 {
+ return nil
+ }
+ return retMap
+ }
+ return nil
+}
+
+// TagedRequestFiledExtractor is a function that relies on Go struct tags to export log fields from requests.
+// These are usualy coming from a protoc-plugin, such as Gogo protobuf.
+//
+// message Metadata {
+// repeated string tags = 1 [ (gogoproto.moretags) = "log_field:\"meta_tags\"" ];
+// }
+//
+// The tagName is configurable using the tagName variable. Here it would be "log_field".
+func TagBasedRequestFieldExtractor(tagName string) RequestFieldExtractorFunc {
+ return func(fullMethod string, req interface{}) map[string]interface{} {
+ retMap := make(map[string]interface{})
+ reflectMessageTags(req, retMap, tagName)
+ if len(retMap) == 0 {
+ return nil
+ }
+ return retMap
+ }
+}
+
+func reflectMessageTags(msg interface{}, existingMap map[string]interface{}, tagName string) {
+ v := reflect.ValueOf(msg)
+ // Only deal with pointers to structs.
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
+ return
+ }
+ // Deref the pointer get to the struct.
+ v = v.Elem()
+ t := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ kind := field.Kind()
+ // Only recurse down direct pointers, which should only be to nested structs.
+ if kind == reflect.Ptr {
+ reflectMessageTags(field.Interface(), existingMap, tagName)
+ }
+ // In case of arrays/splices (repeated fields) go down to the concrete type.
+ if kind == reflect.Array || kind == reflect.Slice {
+ if field.Len() == 0 {
+ continue
+ }
+ kind = field.Index(0).Kind()
+ }
+ // Only be interested in
+ if (kind >= reflect.Bool && kind <= reflect.Float64) || kind == reflect.String {
+ if tag := t.Field(i).Tag.Get(tagName); tag != "" {
+ existingMap[tag] = field.Interface()
+ }
+ }
+ }
+ return
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/interceptors.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/interceptors.go
new file mode 100644
index 000000000..2abd4cabc
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/interceptors.go
@@ -0,0 +1,80 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_ctxtags
+
+import (
+ "github.com/grpc-ecosystem/go-grpc-middleware"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/peer"
+)
+
+// UnaryServerInterceptor returns a new unary server interceptors that sets the values for request tags.
+func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
+ o := evaluateOptions(opts)
+ return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+ newCtx := newTagsForCtx(ctx)
+ if o.requestFieldsFunc != nil {
+ setRequestFieldTags(newCtx, o.requestFieldsFunc, info.FullMethod, req)
+ }
+ return handler(newCtx, req)
+ }
+}
+
+// StreamServerInterceptor returns a new streaming server interceptor that sets the values for request tags.
+func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
+ o := evaluateOptions(opts)
+ return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+ newCtx := newTagsForCtx(stream.Context())
+ if o.requestFieldsFunc == nil {
+ // Short-circuit, don't do the expensive bit of allocating a wrappedStream.
+ wrappedStream := grpc_middleware.WrapServerStream(stream)
+ wrappedStream.WrappedContext = newCtx
+ return handler(srv, wrappedStream)
+ }
+ wrapped := &wrappedStream{stream, info, o, newCtx}
+ err := handler(srv, wrapped)
+ return err
+ }
+}
+
+// wrappedStream is a thin wrapper around grpc.ServerStream that allows modifying context and extracts log fields from the initial message.
+type wrappedStream struct {
+ grpc.ServerStream
+ info *grpc.StreamServerInfo
+ opts *options
+ // WrappedContext is the wrapper's own Context. You can assign it.
+ WrappedContext context.Context
+}
+
+// Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
+func (w *wrappedStream) Context() context.Context {
+ return w.WrappedContext
+}
+
+func (w *wrappedStream) RecvMsg(m interface{}) error {
+ err := w.ServerStream.RecvMsg(m)
+ // We only do log fields extraction on the single-reqest of a server-side stream.
+ if !w.info.IsClientStream {
+ setRequestFieldTags(w.Context(), w.opts.requestFieldsFunc, w.info.FullMethod, m)
+ }
+ return err
+}
+
+func newTagsForCtx(ctx context.Context) context.Context {
+ t := Extract(ctx) // will allocate a new one if it didn't exist.
+ if peer, ok := peer.FromContext(ctx); ok {
+ t.Set("peer.address", peer.Addr)
+ }
+ return setInContext(ctx, t)
+}
+
+func setRequestFieldTags(ctx context.Context, f RequestFieldExtractorFunc, fullMethodName string, req interface{}) {
+ if valMap := f(fullMethodName, req); valMap != nil {
+ t := Extract(ctx)
+ for k, v := range valMap {
+ t.Set("grpc.request."+k, v)
+ }
+ }
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/options.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/options.go
new file mode 100644
index 000000000..8b1e04e9b
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/tags/options.go
@@ -0,0 +1,32 @@
+// Copyright 2017 Michal Witkowski. All Rights Reserved.
+// See LICENSE for licensing terms.
+
+package grpc_ctxtags
+
+var (
+ defaultOptions = &options{
+ requestFieldsFunc: nil,
+ }
+)
+
+type options struct {
+ requestFieldsFunc RequestFieldExtractorFunc
+}
+
+func evaluateOptions(opts []Option) *options {
+ optCopy := &options{}
+ *optCopy = *defaultOptions
+ for _, o := range opts {
+ o(optCopy)
+ }
+ return optCopy
+}
+
+type Option func(*options)
+
+// WithFieldExtractor customizes the function for extracting log fields from protobuf messages.
+func WithFieldExtractor(f RequestFieldExtractorFunc) Option {
+ return func(o *options) {
+ o.requestFieldsFunc = f
+ }
+}
diff --git a/vendor/github.com/grpc-ecosystem/go-grpc-middleware/test_all.sh b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/test_all.sh
new file mode 100755
index 000000000..e1e780080
--- /dev/null
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/test_all.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -e
+echo "" > coverage.txt
+
+for d in $(go list ./... | grep -v vendor); do
+ echo -e "TESTS FOR: for \033[0;35m${d}\033[0m"
+ go test -race -v -coverprofile=profile.coverage.out -covermode=atomic $d
+ if [ -f profile.coverage.out ]; then
+ cat profile.coverage.out >> coverage.txt
+ rm profile.coverage.out
+ fi
+ echo ""
+done
diff --git a/vendor/github.com/mwitkow/go-grpc-middleware/wrappers.go b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go
index 597b86244..597b86244 100644
--- a/vendor/github.com/mwitkow/go-grpc-middleware/wrappers.go
+++ b/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go
diff --git a/vendor/github.com/mwitkow/go-grpc-middleware/README.MD b/vendor/github.com/mwitkow/go-grpc-middleware/README.MD
deleted file mode 100644
index 4f41b6241..000000000
--- a/vendor/github.com/mwitkow/go-grpc-middleware/README.MD
+++ /dev/null
@@ -1,63 +0,0 @@
-# Go gRPC Middleware
-
-[![Travis Build](https://travis-ci.org/mwitkow/go-grpc-middleware.svg?branch=master)](https://travis-ci.org/mwitkow/go-grpc-middleware)
-[![Go Report Card](https://goreportcard.com/badge/github.com/mwitkow/go-grpc-middleware)](https://goreportcard.com/report/github.com/mwitkow/go-grpc-middleware)
-[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/mwitkow/go-grpc-middleware)
-[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
-
-[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.
-
-
-## Middleware
-
-[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for
-Interceptors, i.e. [middleware](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs)
-that is executed either on the gRPC Server before the request is passed onto the user's application logic, or on the gRPC client either around the user call. It is a perfect way to implement
-common patters: auth, logging, message, validation, retries or monitoring.
-
-These are generic building blocks that make it easy to build multiple microservices easily.
-The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
-some of them itself, but also will link to useful external repos.
-
-`grpc_middleware` itself provides support for chaining interceptors. Se [Documentation](doc.md), but here's a simple example:
-
-```go
-import "github.com/mwitkow/go-grpc-middleware"
-
-myServer := grpc.NewServer(
- grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
- grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
-)
-```
-
-## Interceptors
-
-*Please send a PR to add new interceptors or middleware to this list*
-
-#### Auth
- * [`grpc_auth`](auth/README.md) - a customizable (via `AuthFunc) piece of auth middleware
-
-#### Logging
-
-#### Monitoring
- * [`grpc_prometheus`⚡](https://github.com/grpc-ecosystem/go-grpc-prometheus) - Prometheus client-side and server-side monitoring middleware
- * [`otgrpc`⚡](https://github.com/grpc-ecosystem/grpc-opentracing/tree/master/go/otgrpc) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors
-
-#### Client
- * [`grpc_retry`](`retry/README.md`) - a generic gRPC response code retry mechanism
-
-#### Server
- * [`grpc_validator`](validator/README.md) - codegen inbound message validation from `.proto` options
-
-
-## Status
-
-This code has been inspired by the gRPC interceptor design discussion, and the [upstream PR](https://github.com/grpc/grpc-go/pull/653).
-
-This code has been running in *production* since May 2016 as the basis of the gRPC micro services stack at [Improbable](https://improbable.io).
-
-Additional tooling will be added, and contributions are welcome.
-
-## License
-
-`go-grpc-middleware` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
diff --git a/vendor/github.com/mwitkow/go-grpc-middleware/chain.go b/vendor/github.com/mwitkow/go-grpc-middleware/chain.go
deleted file mode 100644
index 3252bf8ff..000000000
--- a/vendor/github.com/mwitkow/go-grpc-middleware/chain.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2016 Michal Witkowski. All Rights Reserved.
-// See LICENSE for licensing terms.
-
-// gRPC Server Interceptor chaining middleware.
-
-package grpc_middleware
-
-import (
- "golang.org/x/net/context"
- "google.golang.org/grpc"
-)
-
-// ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
-//
-// Execution is done in left-to-right order, including passing of context.
-// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
-// will see context changes of one and two.
-func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
- return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
- buildChain := func(current grpc.UnaryServerInterceptor, next grpc.UnaryHandler) grpc.UnaryHandler {
- return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
- return current(currentCtx, currentReq, info, next)
- }
- }
- chain := handler
- for i := len(interceptors) - 1; i >= 0; i-- {
- chain = buildChain(interceptors[i], chain)
- }
- return chain(ctx, req)
- }
-}
-
-// ChainStreamServer creates a single interceptor out of a chain of many interceptors.
-//
-// Execution is done in left-to-right order, including passing of context.
-// For example ChainUnaryServer(one, two, three) will execute one before two before three.
-// If you want to pass context between interceptors, use WrapServerStream.
-func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
- return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
- buildChain := func(current grpc.StreamServerInterceptor, next grpc.StreamHandler) grpc.StreamHandler {
- return func(currentSrv interface{}, currentStream grpc.ServerStream) error {
- return current(currentSrv, currentStream, info, next)
- }
- }
- chain := handler
- for i := len(interceptors) - 1; i >= 0; i-- {
- chain = buildChain(interceptors[i], chain)
- }
- return chain(srv, stream)
- }
-}
-
-// ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
-//
-// Execution is done in left-to-right order, including passing of context.
-// For example ChainUnaryClient(one, two, three) will execute one before two before three.
-func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
- return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
- buildChain := func(current grpc.UnaryClientInterceptor, next grpc.UnaryInvoker) grpc.UnaryInvoker {
- return func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
- return current(currentCtx, currentMethod, currentReq, currentRepl, currentConn, next, currentOpts...)
- }
- }
- chain := invoker
- for i := len(interceptors) - 1; i >= 0; i-- {
- chain = buildChain(interceptors[i], chain)
- }
- return chain(ctx, method, req, reply, cc, opts...)
- }
-}
-
-// ChainStreamClient creates a single interceptor out of a chain of many interceptors.
-//
-// Execution is done in left-to-right order, including passing of context.
-// For example ChainStreamClient(one, two, three) will execute one before two before three.
-func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor {
- return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
- buildChain := func(current grpc.StreamClientInterceptor, next grpc.Streamer) grpc.Streamer {
- return func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
- return current(currentCtx, currentDesc, currentConn, currentMethod, next, currentOpts...)
- }
- }
- chain := streamer
- for i := len(interceptors) - 1; i >= 0; i-- {
- chain = buildChain(interceptors[i], chain)
- }
- return chain(ctx, desc, cc, method, opts...)
- }
-}
-
-// Chain creates a single interceptor out of a chain of many interceptors.
-//
-// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
-// Basically syntactic sugar.
-func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption {
- return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...))
-}
-
-// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
-// Basically syntactic sugar.
-func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption {
- return grpc.StreamInterceptor(ChainStreamServer(interceptors...))
-}
diff --git a/vendor/github.com/mwitkow/go-grpc-middleware/doc.md b/vendor/github.com/mwitkow/go-grpc-middleware/doc.md
deleted file mode 100644
index ed63f5380..000000000
--- a/vendor/github.com/mwitkow/go-grpc-middleware/doc.md
+++ /dev/null
@@ -1,171 +0,0 @@
-# grpc_middleware
---
- import "github.com/mwitkow/go-grpc-middleware"
-
-`grpc_middleware` is a collection of gRPC middleware packages: interceptors,
-helpers and tools.
-
-
-### Middleware
-
-gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang
-world. However, the upstream gRPC codebase is relatively bare bones.
-
-This package, and most of its child packages provides commonly needed middleware
-for gRPC: client-side interceptors for retires, server-side interceptors for
-input validation and auth, functions for chaining said interceptors, metadata
-convenience methods and more.
-
-
-### Chaining
-
-By default, gRPC doesn't allow one to have more than one interceptor either on
-the client nor on the server side. `grpc_middleware` provides convenient
-### chaining methods
-
-Simple way of turning a multiple interceptors into a single interceptor. Here's
-an example for server chaining:
-
- myServer := grpc.NewServer(
- grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
- grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
- )
-
-These interceptors will be executed from left to right: logging, monitoring and
-auth.
-
-Here's an example for client side chaining:
-
- clientConn, err = grpc.Dial(
- address,
- grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
- grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
- )
- client = pb_testproto.NewTestServiceClient(clientConn)
- resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
-
-These interceptors will be executed from left to right: monitoring and then
-retry logic.
-
-
-### Writing Your Own
-
-Implementing your own interceptor is pretty trivial: there are interfaces for
-that. But the interesting bit exposing common data to handlers (and other
-middleware), similarly to HTTP Middleware design. For example, you may want to
-### pass the identity of the caller from the auth interceptor all the way to the
-handling function.
-
-For example, a client side interceptor example for auth looks like:
-
- func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
- newCtx := context.WithValue(ctx, "user_id", "john@example.com")
- return handler(newCtx, req)
- }
-
-Unfortunately, it's not as easy for streaming RPCs. These have the
-`context.Context` embedded within the `grpc.ServerStream` object. To pass values
-through context, a wrapper (`WrappedServerStream`) is needed. For example:
-
- func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
- newStream := grpc_middleware.WrapServerStream(stream)
- newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
- return handler(srv, stream)
- }
-
-## Usage
-
-#### func ChainStreamClient
-
-```go
-func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor
-```
-ChainStreamClient creates a single interceptor out of a chain of many
-interceptors.
-
-Execution is done in left-to-right order, including passing of context. For
-example ChainStreamClient(one, two, three) will execute one before two before
-three.
-
-#### func ChainStreamServer
-
-```go
-func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor
-```
-ChainStreamServer creates a single interceptor out of a chain of many
-interceptors.
-
-Execution is done in left-to-right order, including passing of context. For
-example ChainUnaryServer(one, two, three) will execute one before two before
-three. If you want to pass context between interceptors, use WrapServerStream.
-
-#### func ChainUnaryClient
-
-```go
-func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor
-```
-ChainUnaryClient creates a single interceptor out of a chain of many
-interceptors.
-
-Execution is done in left-to-right order, including passing of context. For
-example ChainUnaryClient(one, two, three) will execute one before two before
-three.
-
-#### func ChainUnaryServer
-
-```go
-func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor
-```
-ChainUnaryServer creates a single interceptor out of a chain of many
-interceptors.
-
-Execution is done in left-to-right order, including passing of context. For
-example ChainUnaryServer(one, two, three) will execute one before two before
-three, and three will see context changes of one and two.
-
-#### func WithStreamServerChain
-
-```go
-func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption
-```
-WithStreamServerChain is a grpc.Server config option that accepts multiple
-stream interceptors. Basically syntactic sugar.
-
-#### func WithUnaryServerChain
-
-```go
-func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption
-```
-Chain creates a single interceptor out of a chain of many interceptors.
-
-WithUnaryServerChain is a grpc.Server config option that accepts multiple unary
-interceptors. Basically syntactic sugar.
-
-#### type WrappedServerStream
-
-```go
-type WrappedServerStream struct {
- grpc.ServerStream
- // WrappedContext is the wrapper's own Context. You can assign it.
- WrappedContext context.Context
-}
-```
-
-WrappedServerStream is a thin wrapper around grpc.ServerStream that allows
-modifying context.
-
-#### func WrapServerStream
-
-```go
-func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream
-```
-WrapServerStream returns a ServerStream that has the ability to overwrite
-context.
-
-#### func (*WrappedServerStream) Context
-
-```go
-func (w *WrappedServerStream) Context() context.Context
-```
-Context returns the wrapper's WrappedContext, overwriting the nested
-grpc.ServerStream.Context()
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 3328efb54..3dba82ed6 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -41,6 +41,12 @@
"revisionTime": "2017-01-17T02:28:26Z"
},
{
+ "checksumSHA1": "ITzWX1LucDMHcZh509uUwc920KY=",
+ "path": "github.com/golang/protobuf/jsonpb",
+ "revision": "5a0f697c9ed9d68fef0116532c6e05cfeae00e55",
+ "revisionTime": "2017-06-01T23:02:30Z"
+ },
+ {
"checksumSHA1": "kBeNcaKk56FguvPSUCEaH6AxpRc=",
"path": "github.com/golang/protobuf/proto",
"revision": "8ee79997227bf9b34611aee7946ae64735e6fd93",
@@ -59,12 +65,42 @@
"revisionTime": "2017-05-26T16:57:56Z"
},
{
+ "checksumSHA1": "Z5Cpi8mr3kfpZ/CdmudThTWQ0Mo=",
+ "path": "github.com/golang/protobuf/ptypes/struct",
+ "revision": "5a0f697c9ed9d68fef0116532c6e05cfeae00e55",
+ "revisionTime": "2017-06-01T23:02:30Z"
+ },
+ {
"checksumSHA1": "sfoot+dHmmOgWZS6GJ5X79ClZM0=",
"path": "github.com/golang/protobuf/ptypes/timestamp",
"revision": "c9c7427a2a70d2eb3bafa0ab2dc163e45f143317",
"revisionTime": "2017-03-07T00:15:33Z"
},
{
+ "checksumSHA1": "rr55iSOD7nDMoZLDWjR/A5M8flw=",
+ "path": "github.com/grpc-ecosystem/go-grpc-middleware",
+ "revision": "04e29b049615a854b3a943e372e180c5ec3f7dc3",
+ "revisionTime": "2017-05-24T14:47:55Z"
+ },
+ {
+ "checksumSHA1": "S3ewTxb4DObPxnizenAS0qq1QvE=",
+ "path": "github.com/grpc-ecosystem/go-grpc-middleware/logging",
+ "revision": "04e29b049615a854b3a943e372e180c5ec3f7dc3",
+ "revisionTime": "2017-05-24T14:47:55Z"
+ },
+ {
+ "checksumSHA1": "H+Z0dx+9dNMej51x0EtLU7TA45M=",
+ "path": "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus",
+ "revision": "04e29b049615a854b3a943e372e180c5ec3f7dc3",
+ "revisionTime": "2017-05-24T14:47:55Z"
+ },
+ {
+ "checksumSHA1": "ajCG0vV10Aj13kh6lQaveMyyOdY=",
+ "path": "github.com/grpc-ecosystem/go-grpc-middleware/tags",
+ "revision": "04e29b049615a854b3a943e372e180c5ec3f7dc3",
+ "revisionTime": "2017-05-24T14:47:55Z"
+ },
+ {
"checksumSHA1": "OJPSJ4GBgH/XOFtYu2VM1g7rtjk=",
"path": "github.com/grpc-ecosystem/go-grpc-prometheus",
"revision": "6b7015e65d366bf3f19b2b2a000a831940f0f7e0",
@@ -83,12 +119,6 @@
"revisionTime": "2016-04-24T11:30:07Z"
},
{
- "checksumSHA1": "5h8cJQQ8Vs/Rrk0yZNB9JLhJkaE=",
- "path": "github.com/mwitkow/go-grpc-middleware",
- "revision": "3e23ca7fd796e946de34f19c1a30742057a244b3",
- "revisionTime": "2016-12-19T10:04:13Z"
- },
- {
"checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=",
"path": "github.com/pmezard/go-difflib/difflib",
"revision": "792786c7400a136282c1664665ae0a8db921c6c2",