mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-28 09:41:57 +00:00
Update weaveworks/common to latest version
``` $ gvt delete github.com/weaveworks/common $ gvt fetch --revision 4d96fd8dcf2c7b417912c6219b310112cb4a4626 github.com/weaveworks/common 2018/07/23 15:31:11 Fetching: github.com/weaveworks/common 2018/07/23 15:31:14 · Skipping (existing): github.com/golang/protobuf/ptypes/any 2018/07/23 15:31:14 · Fetching recursive dependency: github.com/pkg/errors 2018/07/23 15:31:16 · Skipping (existing): github.com/aws/aws-sdk-go/aws 2018/07/23 15:31:16 · Fetching recursive dependency: github.com/sirupsen/logrus 2018/07/23 15:31:18 ·· Skipping (existing): golang.org/x/sys/unix 2018/07/23 15:31:18 ·· Skipping (existing): golang.org/x/crypto/ssh/terminal 2018/07/23 15:31:18 · Skipping (existing): google.golang.org/grpc/status 2018/07/23 15:31:18 · Skipping (existing): github.com/gorilla/mux 2018/07/23 15:31:18 · Fetching recursive dependency: github.com/opentracing-contrib/go-stdlib/nethttp 2018/07/23 15:31:20 ·· Skipping (existing): github.com/opentracing/opentracing-go/ext 2018/07/23 15:31:20 ·· Skipping (existing): github.com/opentracing/opentracing-go/log 2018/07/23 15:31:20 ·· Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:31:20 · Skipping (existing): github.com/prometheus/client_golang/prometheus 2018/07/23 15:31:20 · Skipping (existing): google.golang.org/grpc 2018/07/23 15:31:20 · Skipping (existing): github.com/pmezard/go-difflib/difflib 2018/07/23 15:31:20 · Fetching recursive dependency: github.com/go-kit/kit/log 2018/07/23 15:31:23 ·· Fetching recursive dependency: github.com/go-logfmt/logfmt 2018/07/23 15:31:25 ··· Fetching recursive dependency: github.com/kr/logfmt 2018/07/23 15:31:27 ·· Fetching recursive dependency: github.com/go-stack/stack 2018/07/23 15:31:29 · Fetching recursive dependency: google.golang.org/genproto/googleapis/rpc/status 2018/07/23 15:31:37 ·· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:31:37 ·· Skipping (existing): github.com/golang/protobuf/ptypes/any 2018/07/23 15:31:37 · Skipping (existing): github.com/opentracing/opentracing-go/log 2018/07/23 15:31:37 · Fetching recursive dependency: github.com/sercand/kuberesolver 2018/07/23 15:31:39 ·· Skipping (existing): google.golang.org/grpc/grpclog 2018/07/23 15:31:39 ·· Skipping (existing): google.golang.org/grpc/resolver 2018/07/23 15:31:39 ·· Skipping (existing): golang.org/x/net/context 2018/07/23 15:31:39 · Skipping (existing): google.golang.org/grpc/metadata 2018/07/23 15:31:39 · Skipping (existing): github.com/opentracing/opentracing-go/ext 2018/07/23 15:31:39 · Skipping (existing): github.com/armon/go-socks5 2018/07/23 15:31:39 · Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:31:39 · Skipping (existing): github.com/davecgh/go-spew/spew 2018/07/23 15:31:39 · Skipping (existing): github.com/golang/protobuf/ptypes 2018/07/23 15:31:39 · Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:31:39 · Fetching recursive dependency: github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc 2018/07/23 15:31:41 ·· Skipping (existing): github.com/opentracing/opentracing-go/log 2018/07/23 15:31:41 ·· Skipping (existing): golang.org/x/net/context 2018/07/23 15:31:41 ·· Skipping (existing): google.golang.org/grpc/codes 2018/07/23 15:31:41 ·· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:31:41 ·· Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:31:41 ·· Skipping (existing): github.com/opentracing/opentracing-go/ext 2018/07/23 15:31:41 ·· Skipping (existing): google.golang.org/grpc 2018/07/23 15:31:41 ·· Skipping (existing): google.golang.org/grpc/metadata 2018/07/23 15:31:41 ·· Skipping (existing): google.golang.org/grpc/status 2018/07/23 15:31:41 · Fetching recursive dependency: github.com/uber/jaeger-client-go/config 2018/07/23 15:31:44 ·· Fetching recursive dependency: github.com/uber/jaeger-client-go/internal/throttler/remote 2018/07/23 15:31:44 ··· Fetching recursive dependency: github.com/uber/jaeger-client-go/utils 2018/07/23 15:31:44 ···· Fetching recursive dependency: github.com/uber/jaeger-client-go/thrift 2018/07/23 15:31:44 ···· Fetching recursive dependency: github.com/uber/jaeger-client-go/thrift-gen/agent 2018/07/23 15:31:44 ····· Fetching recursive dependency: github.com/uber/jaeger-client-go/thrift-gen/jaeger 2018/07/23 15:31:44 ····· Fetching recursive dependency: github.com/uber/jaeger-client-go/thrift-gen/zipkincore 2018/07/23 15:31:44 ··· Fetching recursive dependency: github.com/uber/jaeger-client-go 2018/07/23 15:31:44 ···· Fetching recursive dependency: github.com/crossdock/crossdock-go 2018/07/23 15:31:46 ····· Skipping (existing): github.com/davecgh/go-spew/spew 2018/07/23 15:31:46 ····· Skipping (existing): golang.org/x/net/context/ctxhttp 2018/07/23 15:31:46 ····· Skipping (existing): golang.org/x/net/context 2018/07/23 15:31:46 ····· Skipping (existing): github.com/pmezard/go-difflib/difflib 2018/07/23 15:31:46 ···· Skipping (existing): github.com/opentracing/opentracing-go/log 2018/07/23 15:31:46 ···· Fetching recursive dependency: go.uber.org/zap/zapcore 2018/07/23 15:31:49 ····· Fetching recursive dependency: go.uber.org/atomic 2018/07/23 15:31:51 ····· Fetching recursive dependency: go.uber.org/zap/internal/bufferpool 2018/07/23 15:31:51 ······ Fetching recursive dependency: go.uber.org/zap/buffer 2018/07/23 15:31:51 ····· Fetching recursive dependency: go.uber.org/multierr 2018/07/23 15:31:54 ····· Fetching recursive dependency: go.uber.org/zap/internal/exit 2018/07/23 15:31:54 ····· Fetching recursive dependency: go.uber.org/zap/internal/color 2018/07/23 15:31:54 ···· Fetching recursive dependency: go.uber.org/zap 2018/07/23 15:31:54 ···· Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:31:54 ···· Skipping (existing): github.com/opentracing/opentracing-go/ext 2018/07/23 15:31:54 ···· Fetching recursive dependency: github.com/uber/jaeger-lib/metrics 2018/07/23 15:31:56 ····· Fetching recursive dependency: github.com/uber-go/tally 2018/07/23 15:31:58 ······ Fetching recursive dependency: github.com/m3db/prometheus_client_golang/prometheus/promhttp 2018/07/23 15:32:00 ······· Skipping (existing): github.com/prometheus/client_golang/prometheus 2018/07/23 15:32:00 ······· Skipping (existing): github.com/prometheus/common/expfmt 2018/07/23 15:32:00 ······· Skipping (existing): github.com/prometheus/client_model/go 2018/07/23 15:32:00 ······ Fetching recursive dependency: gopkg.in/validator.v2 2018/07/23 15:32:06 ······ Fetching recursive dependency: github.com/cactus/go-statsd-client/statsd 2018/07/23 15:32:08 ······ Skipping (existing): gopkg.in/yaml.v2 2018/07/23 15:32:08 ······ Fetching recursive dependency: github.com/m3db/prometheus_client_golang/prometheus 2018/07/23 15:32:08 ······· Skipping (existing): github.com/prometheus/procfs 2018/07/23 15:32:08 ······· Skipping (existing): github.com/prometheus/client_model/go 2018/07/23 15:32:08 ······· Skipping (existing): github.com/prometheus/common/expfmt 2018/07/23 15:32:08 ······· Skipping (existing): golang.org/x/net/context 2018/07/23 15:32:08 ······· Skipping (existing): github.com/beorn7/perks/quantile 2018/07/23 15:32:08 ······· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:32:08 ······· Skipping (existing): github.com/prometheus/common/model 2018/07/23 15:32:08 ······· Skipping (existing): github.com/prometheus/client_golang/prometheus 2018/07/23 15:32:08 ······ Fetching recursive dependency: github.com/apache/thrift/lib/go/thrift 2018/07/23 15:32:13 ····· Skipping (existing): github.com/stretchr/testify/assert 2018/07/23 15:32:13 ····· Fetching recursive dependency: github.com/go-kit/kit/metrics/influx 2018/07/23 15:32:13 ······ Fetching recursive dependency: github.com/influxdata/influxdb/client/v2 2018/07/23 15:32:17 ······· Fetching recursive dependency: github.com/influxdata/influxdb/models 2018/07/23 15:32:17 ········ Fetching recursive dependency: github.com/influxdata/influxdb/pkg/escape 2018/07/23 15:32:17 ······ Fetching recursive dependency: github.com/go-kit/kit/metrics 2018/07/23 15:32:17 ······· Fetching recursive dependency: github.com/performancecopilot/speed 2018/07/23 15:32:19 ······· Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/aws 2018/07/23 15:32:28 ········ Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/internal/sdk 2018/07/23 15:32:28 ········ Skipping (existing): github.com/go-ini/ini 2018/07/23 15:32:28 ········ Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/service/sts 2018/07/23 15:32:28 ········· Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/private/protocol/query 2018/07/23 15:32:28 ·········· Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/private/protocol 2018/07/23 15:32:28 ········· Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/internal/awsutil 2018/07/23 15:32:28 ·········· Skipping (existing): github.com/jmespath/go-jmespath 2018/07/23 15:32:28 ······· Fetching recursive dependency: github.com/aws/aws-sdk-go-v2/service/cloudwatch 2018/07/23 15:32:29 ······· Skipping (existing): github.com/aws/aws-sdk-go/aws 2018/07/23 15:32:29 ······· Skipping (existing): github.com/prometheus/client_golang/prometheus 2018/07/23 15:32:29 ······· Skipping (existing): github.com/aws/aws-sdk-go/service/cloudwatch 2018/07/23 15:32:29 ······· Skipping (existing): github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface 2018/07/23 15:32:29 ······· Fetching recursive dependency: golang.org/x/sync/errgroup 2018/07/23 15:32:31 ········ Skipping (existing): golang.org/x/net/context 2018/07/23 15:32:31 ······· Fetching recursive dependency: github.com/go-kit/kit/util/conn 2018/07/23 15:32:31 ······· Fetching recursive dependency: github.com/VividCortex/gohistogram 2018/07/23 15:32:33 ····· Skipping (existing): github.com/prometheus/client_golang/prometheus 2018/07/23 15:32:33 ····· Fetching recursive dependency: github.com/codahale/hdrhistogram 2018/07/23 15:32:35 ·· Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:32:35 · Fetching recursive dependency: github.com/mwitkow/go-grpc-middleware 2018/07/23 15:32:37 ·· Fetching recursive dependency: github.com/grpc-ecosystem/go-grpc-middleware/logging 2018/07/23 15:32:39 ··· Fetching recursive dependency: github.com/grpc-ecosystem/go-grpc-middleware 2018/07/23 15:32:39 ···· Fetching recursive dependency: github.com/golang/protobuf/jsonpb 2018/07/23 15:32:42 ····· Skipping (existing): github.com/golang/protobuf/ptypes/timestamp 2018/07/23 15:32:42 ····· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:32:42 ····· Skipping (existing): github.com/golang/protobuf/ptypes/duration 2018/07/23 15:32:42 ····· Skipping (existing): github.com/golang/protobuf/ptypes/any 2018/07/23 15:32:42 ····· Skipping (existing): github.com/golang/protobuf/ptypes/struct 2018/07/23 15:32:42 ····· Skipping (existing): github.com/golang/protobuf/ptypes/wrappers 2018/07/23 15:32:42 ···· Skipping (existing): google.golang.org/grpc/metadata 2018/07/23 15:32:42 ···· Fetching recursive dependency: github.com/stretchr/testify/suite 2018/07/23 15:32:45 ····· Skipping (existing): github.com/stretchr/testify/assert 2018/07/23 15:32:45 ····· Fetching recursive dependency: github.com/stretchr/testify/require 2018/07/23 15:32:45 ······ Skipping (existing): github.com/stretchr/testify/assert 2018/07/23 15:32:45 ···· Skipping (existing): google.golang.org/grpc/peer 2018/07/23 15:32:45 ···· Skipping (existing): golang.org/x/net/context 2018/07/23 15:32:45 ···· Skipping (existing): golang.org/x/net/trace 2018/07/23 15:32:45 ···· Fetching recursive dependency: github.com/gogo/protobuf/gogoproto 2018/07/23 15:32:48 ····· Fetching recursive dependency: github.com/gogo/protobuf/protoc-gen-gogo/descriptor 2018/07/23 15:32:48 ······ Skipping (existing): github.com/gogo/protobuf/proto 2018/07/23 15:32:48 ····· Skipping (existing): github.com/gogo/protobuf/proto 2018/07/23 15:32:48 ···· Skipping (existing): google.golang.org/grpc/credentials 2018/07/23 15:32:48 ···· Skipping (existing): google.golang.org/grpc 2018/07/23 15:32:48 ···· Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:32:48 ···· Skipping (existing): google.golang.org/grpc/codes 2018/07/23 15:32:48 ···· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:32:48 ···· Skipping (existing): google.golang.org/grpc/grpclog 2018/07/23 15:32:48 ···· Skipping (existing): github.com/opentracing/opentracing-go/ext 2018/07/23 15:32:48 ···· Skipping (existing): github.com/opentracing/opentracing-go/log 2018/07/23 15:32:48 ··· Skipping (existing): golang.org/x/net/context 2018/07/23 15:32:48 ··· Skipping (existing): google.golang.org/grpc 2018/07/23 15:32:48 ··· Skipping (existing): google.golang.org/grpc/grpclog 2018/07/23 15:32:48 ··· Skipping (existing): google.golang.org/grpc/codes 2018/07/23 15:32:48 ··· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:32:48 ·· Skipping (existing): github.com/opentracing/opentracing-go 2018/07/23 15:32:48 ·· Skipping (existing): google.golang.org/grpc 2018/07/23 15:32:48 ·· Skipping (existing): golang.org/x/net/context 2018/07/23 15:32:48 ·· Skipping (existing): google.golang.org/grpc/codes 2018/07/23 15:32:48 ·· Skipping (existing): google.golang.org/grpc/grpclog 2018/07/23 15:32:48 ·· Skipping (existing): github.com/opentracing/opentracing-go/log 2018/07/23 15:32:48 ·· Skipping (existing): google.golang.org/grpc/metadata 2018/07/23 15:32:48 ·· Skipping (existing): google.golang.org/grpc/peer 2018/07/23 15:32:48 ·· Skipping (existing): google.golang.org/grpc/credentials 2018/07/23 15:32:48 ·· Skipping (existing): github.com/golang/protobuf/proto 2018/07/23 15:32:48 ·· Skipping (existing): golang.org/x/net/trace 2018/07/23 15:32:48 ·· Skipping (existing): github.com/opentracing/opentracing-go/ext 2018/07/23 15:32:48 · Fetching recursive dependency: github.com/weaveworks/promrus 2018/07/23 15:32:53 ·· Skipping (existing): gopkg.in/yaml.v2 2018/07/23 15:32:53 ·· Skipping (existing): golang.org/x/net/context/ctxhttp 2018/07/23 15:32:53 ·· Fetching recursive dependency: github.com/stretchr/objx 2018/07/23 15:32:55 ·· Fetching recursive dependency: gopkg.in/alecthomas/kingpin.v2 2018/07/23 15:32:58 ··· Fetching recursive dependency: github.com/alecthomas/units 2018/07/23 15:33:00 ··· Fetching recursive dependency: github.com/alecthomas/template 2018/07/23 15:33:02 ·· Fetching recursive dependency: github.com/julienschmidt/httprouter 2018/07/23 15:33:05 ·· Skipping (existing): golang.org/x/net/context 2018/07/23 15:33:05 · Skipping (existing): github.com/aws/aws-sdk-go/aws/credentials 2018/07/23 15:33:05 · Skipping (existing): github.com/golang/protobuf/ptypes/empty 2018/07/23 15:33:05 · Skipping (existing): golang.org/x/net/context 2018/07/23 15:33:05 · Skipping (existing): golang.org/x/tools/cover 2018/07/23 15:33:05 · Skipping (existing): github.com/mgutz/ansi ```
This commit is contained in:
201
vendor/github.com/mwitkow/go-grpc-middleware/LICENSE
generated
vendored
Normal file
201
vendor/github.com/mwitkow/go-grpc-middleware/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
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.
|
||||
67
vendor/github.com/mwitkow/go-grpc-middleware/auth/auth.go
generated
vendored
Normal file
67
vendor/github.com/mwitkow/go-grpc-middleware/auth/auth.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_auth
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// AuthFunc is the pluggable function that performs authentication.
|
||||
//
|
||||
// The passed in `Context` will contain the gRPC metadata.MD object (for header-based authentication) and
|
||||
// the peer.Peer information that can contain transport-based credentials (e.g. `credentials.AuthInfo`).
|
||||
//
|
||||
// The returned context will be propagated to handlers, allowing user changes to `Context`. However,
|
||||
// please make sure that the `Context` returned is a child `Context` of the one passed in.
|
||||
//
|
||||
// If error is returned, its `grpc.Code()` will be returned to the user as well as the verbatim message.
|
||||
// Please make sure you use `codes.Unauthenticated` (lacking auth) and `codes.PermissionDenied`
|
||||
// (authed, but lacking perms) appropriately.
|
||||
type AuthFunc func(ctx context.Context) (context.Context, error)
|
||||
|
||||
// ServiceAuthFuncOverride allows a given gRPC service implementation to override the global `AuthFunc`.
|
||||
//
|
||||
// If a service implements the AuthFuncOverride method, it takes precedence over the `AuthFunc` method,
|
||||
// and will be called instead of AuthFunc for all method invocations within that service.
|
||||
type ServiceAuthFuncOverride interface {
|
||||
AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error)
|
||||
}
|
||||
|
||||
// UnaryServerInterceptor returns a new unary server interceptors that performs per-request auth.
|
||||
func UnaryServerInterceptor(authFunc AuthFunc) grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
var newCtx context.Context
|
||||
var err error
|
||||
if overrideSrv, ok := info.Server.(ServiceAuthFuncOverride); ok {
|
||||
newCtx, err = overrideSrv.AuthFuncOverride(ctx, info.FullMethod)
|
||||
} else {
|
||||
newCtx, err = authFunc(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler(newCtx, req)
|
||||
}
|
||||
}
|
||||
|
||||
// StreamServerInterceptor returns a new unary server interceptors that performs per-request auth.
|
||||
func StreamServerInterceptor(authFunc AuthFunc) grpc.StreamServerInterceptor {
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
var newCtx context.Context
|
||||
var err error
|
||||
if overrideSrv, ok := srv.(ServiceAuthFuncOverride); ok {
|
||||
newCtx, err = overrideSrv.AuthFuncOverride(stream.Context(), info.FullMethod)
|
||||
} else {
|
||||
newCtx, err = authFunc(stream.Context())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wrapped := grpc_middleware.WrapServerStream(stream)
|
||||
wrapped.WrappedContext = newCtx
|
||||
return handler(srv, wrapped)
|
||||
}
|
||||
}
|
||||
20
vendor/github.com/mwitkow/go-grpc-middleware/auth/doc.go
generated
vendored
Normal file
20
vendor/github.com/mwitkow/go-grpc-middleware/auth/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`grpc_auth` a generic server-side auth middleware for gRPC.
|
||||
|
||||
Server Side Auth Middleware
|
||||
|
||||
It allows for easy assertion of `:authorization` headers in gRPC calls, be it HTTP Basic auth, or
|
||||
OAuth2 Bearer tokens.
|
||||
|
||||
The middleware takes a user-customizable `AuthFunc`, which can be customized to verify and extract
|
||||
auth information from the request. The extracted information can be put in the `context.Context` of
|
||||
handlers downstream for retrieval.
|
||||
|
||||
It also allows for per-service implementation overrides of `AuthFunc`. See `ServiceAuthFuncOverride`.
|
||||
|
||||
Please see examples for simple examples of use.
|
||||
*/
|
||||
package grpc_auth
|
||||
38
vendor/github.com/mwitkow/go-grpc-middleware/auth/metadata.go
generated
vendored
Normal file
38
vendor/github.com/mwitkow/go-grpc-middleware/auth/metadata.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_auth
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
var (
|
||||
headerAuthorize = "authorization"
|
||||
)
|
||||
|
||||
// AuthFromMD is a helper function for extracting the :authorization header from the gRPC metadata of the request.
|
||||
//
|
||||
// It expects the `:authorization` header to be of a certain scheme (e.g. `basic`, `bearer`), in a
|
||||
// case-insensitive format (see rfc2617, sec 1.2). If no such authorization is found, or the token
|
||||
// is of wrong scheme, an error with gRPC status `Unauthenticated` is returned.
|
||||
func AuthFromMD(ctx context.Context, expectedScheme string) (string, error) {
|
||||
val := metautils.ExtractIncoming(ctx).Get(headerAuthorize)
|
||||
if val == "" {
|
||||
return "", grpc.Errorf(codes.Unauthenticated, "Request unauthenticated with "+expectedScheme)
|
||||
|
||||
}
|
||||
splits := strings.SplitN(val, " ", 2)
|
||||
if len(splits) < 2 {
|
||||
return "", grpc.Errorf(codes.Unauthenticated, "Bad authorization string")
|
||||
}
|
||||
if strings.ToLower(splits[0]) != strings.ToLower(expectedScheme) {
|
||||
return "", grpc.Errorf(codes.Unauthenticated, "Request unauthenticated with "+expectedScheme)
|
||||
}
|
||||
return splits[1], nil
|
||||
}
|
||||
183
vendor/github.com/mwitkow/go-grpc-middleware/chain.go
generated
vendored
Normal file
183
vendor/github.com/mwitkow/go-grpc-middleware/chain.go
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// 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 {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
var (
|
||||
chainHandler grpc.UnaryHandler
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
|
||||
if curI == lastI {
|
||||
return handler(currentCtx, currentReq)
|
||||
}
|
||||
curI++
|
||||
resp, err := interceptors[curI](currentCtx, currentReq, info, chainHandler)
|
||||
curI--
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return interceptors[0](ctx, req, info, chainHandler)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
return handler(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 {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
var (
|
||||
chainHandler grpc.StreamHandler
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentSrv interface{}, currentStream grpc.ServerStream) error {
|
||||
if curI == lastI {
|
||||
return handler(currentSrv, currentStream)
|
||||
}
|
||||
curI++
|
||||
err := interceptors[curI](currentSrv, currentStream, info, chainHandler)
|
||||
curI--
|
||||
return err
|
||||
}
|
||||
|
||||
return interceptors[0](srv, stream, info, chainHandler)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
return func(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
return handler(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 {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
var (
|
||||
chainHandler grpc.UnaryInvoker
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
|
||||
if curI == lastI {
|
||||
return invoker(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentOpts...)
|
||||
}
|
||||
curI++
|
||||
err := interceptors[curI](currentCtx, currentMethod, currentReq, currentRepl, currentConn, chainHandler, currentOpts...)
|
||||
curI--
|
||||
return err
|
||||
}
|
||||
|
||||
return interceptors[0](ctx, method, req, reply, cc, chainHandler, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
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...)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
n := len(interceptors)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
var (
|
||||
chainHandler grpc.Streamer
|
||||
curI int
|
||||
)
|
||||
|
||||
chainHandler = func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
if curI == lastI {
|
||||
return streamer(currentCtx, currentDesc, currentConn, currentMethod, currentOpts...)
|
||||
}
|
||||
curI++
|
||||
stream, err := interceptors[curI](currentCtx, currentDesc, currentConn, currentMethod, chainHandler, currentOpts...)
|
||||
curI--
|
||||
return stream, err
|
||||
}
|
||||
|
||||
return interceptors[0](ctx, desc, cc, method, chainHandler, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return interceptors[0]
|
||||
}
|
||||
|
||||
// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
|
||||
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...)
|
||||
}
|
||||
}
|
||||
|
||||
// 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...))
|
||||
}
|
||||
69
vendor/github.com/mwitkow/go-grpc-middleware/doc.go
generated
vendored
Normal file
69
vendor/github.com/mwitkow/go-grpc-middleware/doc.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`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.
|
||||
|
||||
The retry interceptor will call every interceptor that follows it whenever when a retry happens.
|
||||
|
||||
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)
|
||||
}
|
||||
*/
|
||||
package grpc_middleware
|
||||
35
vendor/github.com/mwitkow/go-grpc-middleware/logging/common.go
generated
vendored
Normal file
35
vendor/github.com/mwitkow/go-grpc-middleware/logging/common.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Decider function defines rules for suppressing any interceptor logs
|
||||
type Decider func(fullMethodName string, err error) bool
|
||||
|
||||
// DefaultDeciderMethod is the default implementation of decider to see if you should log the call
|
||||
// by default this if always true so all calls are logged
|
||||
func DefaultDeciderMethod(fullMethodName string, err error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// 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
|
||||
35
vendor/github.com/mwitkow/go-grpc-middleware/logging/doc.go
generated
vendored
Normal file
35
vendor/github.com/mwitkow/go-grpc-middleware/logging/doc.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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
|
||||
|
||||
The gRPC logging middleware populates request-scoped data to `grpc_ctxtags.Tags` that relate to the current gRPC call
|
||||
(e.g. service and method names).
|
||||
|
||||
Once the gRPC logging middleware has added the gRPC specific Tags to the ctx they will then be written with the logs
|
||||
that are made using the `ctx_logrus` or `ctx_zap` loggers.
|
||||
|
||||
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
|
||||
65
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/client_interceptors.go
generated
vendored
Normal file
65
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/client_interceptors.go
generated
vendored
Normal file
@@ -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,
|
||||
}
|
||||
}
|
||||
19
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/context.go
generated
vendored
Normal file
19
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/context.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package grpc_logrus
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// AddFields adds logrus fields to the logger.
|
||||
// Deprecated: should use the ctxlogrus.Extract instead
|
||||
func AddFields(ctx context.Context, fields logrus.Fields) {
|
||||
ctxlogrus.AddFields(ctx, fields)
|
||||
}
|
||||
|
||||
// Extract takes the call-scoped logrus.Entry from grpc_logrus middleware.
|
||||
// Deprecated: should use the ctxlogrus.Extract instead
|
||||
func Extract(ctx context.Context) *logrus.Entry {
|
||||
return ctxlogrus.Extract(ctx)
|
||||
}
|
||||
65
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/ctxlogrus/context.go
generated
vendored
Normal file
65
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/ctxlogrus/context.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package ctxlogrus
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type ctxLoggerMarker struct{}
|
||||
|
||||
type ctxLogger struct {
|
||||
logger *logrus.Entry
|
||||
fields logrus.Fields
|
||||
}
|
||||
|
||||
var (
|
||||
ctxLoggerKey = &ctxLoggerMarker{}
|
||||
)
|
||||
|
||||
// AddFields adds logrus fields to the logger.
|
||||
func AddFields(ctx context.Context, fields logrus.Fields) {
|
||||
l, ok := ctx.Value(ctxLoggerKey).(*ctxLogger)
|
||||
if !ok || l == nil {
|
||||
return
|
||||
}
|
||||
for k, v := range fields {
|
||||
l.fields[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Extract takes the call-scoped logrus.Entry from ctx_logrus middleware.
|
||||
//
|
||||
// If the ctx_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(ctxLoggerKey).(*ctxLogger)
|
||||
if !ok || l == nil {
|
||||
return logrus.NewEntry(nullLogger)
|
||||
}
|
||||
|
||||
fields := logrus.Fields{}
|
||||
|
||||
// Add grpc_ctxtags tags metadata until now.
|
||||
tags := grpc_ctxtags.Extract(ctx)
|
||||
for k, v := range tags.Values() {
|
||||
fields[k] = v
|
||||
}
|
||||
|
||||
// Add logrus fields added until now.
|
||||
for k, v := range l.fields {
|
||||
fields[k] = v
|
||||
}
|
||||
|
||||
return l.logger.WithFields(fields)
|
||||
}
|
||||
|
||||
// ToContext adds the logrus.Entry to the context for extraction later.
|
||||
// Returning the new context that has been created.
|
||||
func ToContext(ctx context.Context, entry *logrus.Entry) context.Context {
|
||||
l := &ctxLogger{
|
||||
logger: entry,
|
||||
fields: logrus.Fields{},
|
||||
}
|
||||
return context.WithValue(ctx, ctxLoggerKey, l)
|
||||
}
|
||||
14
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/ctxlogrus/doc.go
generated
vendored
Normal file
14
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/ctxlogrus/doc.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
`ctxlogrus` is a ctxlogger that is backed by logrus
|
||||
|
||||
It accepts a user-configured `logrus.Logger` that will be used for logging. The same `logrus.Logger` will
|
||||
be populated into the `context.Context` passed into gRPC handler code.
|
||||
|
||||
You can use `ctx_logrus.Extract` to log into a request-scoped `logrus.Logger` instance in your handler code.
|
||||
|
||||
As `ctx_logrus.Extract` will iterate all tags on from `grpc_ctxtags` it is therefore expensive so it is advised that you
|
||||
extract once at the start of the function from the context and reuse it for the remainder of the function (see examples).
|
||||
|
||||
Please see examples and tests for examples of use.
|
||||
*/
|
||||
package ctxlogrus
|
||||
16
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/ctxlogrus/noop.go
generated
vendored
Normal file
16
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/ctxlogrus/noop.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package ctxlogrus
|
||||
|
||||
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,
|
||||
}
|
||||
)
|
||||
67
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/doc.go
generated
vendored
Normal file
67
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/doc.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
`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.
|
||||
|
||||
On calling `StreamServerInterceptor` or `UnaryServerInterceptor` this logging middleware will add gRPC call information
|
||||
to the ctx so that it will be present on subsequent use of the `ctxlogrus` logger.
|
||||
|
||||
This package also implements request and response *payload* logging, both for server-side and client-side. These will be
|
||||
logged as structured `jsonpb` 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.
|
||||
|
||||
If a deadline is present on the gRPC request the grpc.request.deadline tag is populated when the request begins. grpc.request.deadline
|
||||
is a string representing the time (RFC3339) when the current call will expire.
|
||||
|
||||
Logrus can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
|
||||
|
||||
*Server Interceptor*
|
||||
Below is a JSON formatted example of a log that would be logged by the server interceptor:
|
||||
|
||||
{
|
||||
"level": "info", // string logrus log levels
|
||||
"msg": "finished unary call", // string log message
|
||||
"grpc.code": "OK", // string grpc status code
|
||||
"grpc.method": "Ping", // string method name
|
||||
"grpc.service": "mwitkow.testproto.TestService", // string full name of the called service
|
||||
"grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time
|
||||
"grpc.request.deadline": "2006-01-02T15:04:05Z07:00", // string RFC3339 deadline of the current request if supplied
|
||||
"grpc.request.value": "something", // string value on the request
|
||||
"grpc.time_ms": 1.234, // float32 run time of the call in ms
|
||||
"peer.address": {
|
||||
"IP": "127.0.0.1", // string IP address of calling party
|
||||
"Port": 60216, // int port call is coming in on
|
||||
"Zone": "" // string peer zone for caller
|
||||
},
|
||||
"span.kind": "server", // string client | server
|
||||
"system": "grpc" // string
|
||||
|
||||
"custom_field": "custom_value", // string user defined field
|
||||
"custom_tags.int": 1337, // int user defined tag on the ctx
|
||||
"custom_tags.string": "something", // string user defined tag on the ctx
|
||||
}
|
||||
|
||||
*Payload Interceptor*
|
||||
Below is a JSON formatted example of a log that would be logged by the payload interceptor:
|
||||
|
||||
{
|
||||
"level": "info", // string logrus log levels
|
||||
"msg": "client request payload logged as grpc.request.content", // string log message
|
||||
|
||||
"grpc.request.content": { // object content of RPC request
|
||||
"value": "something", // string defined by caller
|
||||
"sleepTimeMs": 9999 // int defined by caller
|
||||
},
|
||||
"grpc.method": "Ping", // string method being called
|
||||
"grpc.service": "mwitkow.testproto.TestService", // string service being called
|
||||
"span.kind": "client", // string client | server
|
||||
"system": "grpc" // string
|
||||
}
|
||||
|
||||
Note - due to implementation ZAP differs from Logrus in the "grpc.request.content" object by having an inner "msg" object.
|
||||
|
||||
Please see examples and tests for examples of use.
|
||||
*/
|
||||
package grpc_logrus
|
||||
15
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/grpclogger.go
generated
vendored
Normal file
15
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/grpclogger.go
generated
vendored
Normal file
@@ -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))
|
||||
}
|
||||
185
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/options.go
generated
vendored
Normal file
185
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/options.go
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_logrus
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultOptions = &options{
|
||||
levelFunc: nil,
|
||||
shouldLog: grpc_logging.DefaultDeciderMethod,
|
||||
codeFunc: grpc_logging.DefaultErrorToCode,
|
||||
durationFunc: DefaultDurationToField,
|
||||
}
|
||||
)
|
||||
|
||||
type options struct {
|
||||
levelFunc CodeToLevel
|
||||
shouldLog grpc_logging.Decider
|
||||
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{})
|
||||
|
||||
// WithDecider customizes the function for deciding if the gRPC interceptor logs should log.
|
||||
func WithDecider(f grpc_logging.Decider) Option {
|
||||
return func(o *options) {
|
||||
o.shouldLog = f
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
144
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/payload_interceptors.go
generated
vendored
Normal file
144
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/payload_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
package grpc_logrus
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"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(ctx_logrus.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
|
||||
}
|
||||
}
|
||||
|
||||
// PayloadStreamServerInterceptor 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
|
||||
}
|
||||
}
|
||||
|
||||
// PayloadStreamClientInterceptor 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
|
||||
}
|
||||
129
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/server_interceptors.go
generated
vendored
Normal file
129
vendor/github.com/mwitkow/go-grpc-middleware/logging/logrus/server_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright (c) Improbable Worlds Ltd, All Rights Reserved
|
||||
|
||||
package grpc_logrus
|
||||
|
||||
import (
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags/logrus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"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"
|
||||
)
|
||||
|
||||
// UnaryServerInterceptor 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) {
|
||||
startTime := time.Now()
|
||||
newCtx := newLoggerForCall(ctx, entry, info.FullMethod, startTime)
|
||||
|
||||
resp, err := handler(newCtx, req)
|
||||
|
||||
if !o.shouldLog(info.FullMethod, err) {
|
||||
return resp, err
|
||||
}
|
||||
code := o.codeFunc(err)
|
||||
level := o.levelFunc(code)
|
||||
durField, durVal := o.durationFunc(time.Since(startTime))
|
||||
fields := logrus.Fields{
|
||||
"grpc.code": code.String(),
|
||||
durField: durVal,
|
||||
}
|
||||
if err != nil {
|
||||
fields[logrus.ErrorKey] = err
|
||||
}
|
||||
|
||||
levelLogf(
|
||||
ctx_logrus.Extract(newCtx).WithFields(fields), // re-extract logger from newCtx, as it may have extra fields that changed in the holder.
|
||||
level,
|
||||
"finished unary call with code "+code.String())
|
||||
|
||||
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 {
|
||||
startTime := time.Now()
|
||||
newCtx := newLoggerForCall(stream.Context(), entry, info.FullMethod, startTime)
|
||||
wrapped := grpc_middleware.WrapServerStream(stream)
|
||||
wrapped.WrappedContext = newCtx
|
||||
|
||||
err := handler(srv, wrapped)
|
||||
|
||||
if !o.shouldLog(info.FullMethod, err) {
|
||||
return err
|
||||
}
|
||||
code := o.codeFunc(err)
|
||||
level := o.levelFunc(code)
|
||||
durField, durVal := o.durationFunc(time.Since(startTime))
|
||||
fields := logrus.Fields{
|
||||
"grpc.code": code.String(),
|
||||
durField: durVal,
|
||||
}
|
||||
if err != nil {
|
||||
fields[logrus.ErrorKey] = err
|
||||
}
|
||||
|
||||
levelLogf(
|
||||
ctx_logrus.Extract(newCtx).WithFields(fields), // re-extract logger from newCtx, as it may have extra fields that changed in the holder.
|
||||
level,
|
||||
"finished streaming call with code "+code.String())
|
||||
|
||||
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, start time.Time) 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,
|
||||
"grpc.start_time": start.Format(time.RFC3339),
|
||||
})
|
||||
|
||||
if d, ok := ctx.Deadline(); ok {
|
||||
callLog = callLog.WithFields(
|
||||
logrus.Fields{
|
||||
"grpc.request.deadline": d.Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
|
||||
callLog = callLog.WithFields(ctx_logrus.Extract(ctx).Data)
|
||||
return ctxlogrus.ToContext(ctx, callLog)
|
||||
}
|
||||
64
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/client_interceptors.go
generated
vendored
Normal file
64
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/client_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_zap
|
||||
|
||||
import (
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
// ClientField is used in every client-side log statement made through grpc_zap. Can be overwritten before initialization.
|
||||
ClientField = zap.String("span.kind", "client")
|
||||
)
|
||||
|
||||
// UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.
|
||||
func UnaryClientInterceptor(logger *zap.Logger, 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, logger.With(fields...), startTime, err, "finished client unary call")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// StreamClientInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.
|
||||
func StreamClientInterceptor(logger *zap.Logger, 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, logger.With(fields...), startTime, err, "finished client streaming call")
|
||||
return clientStream, err
|
||||
}
|
||||
}
|
||||
|
||||
func logFinalClientLine(o *options, logger *zap.Logger, startTime time.Time, err error, msg string) {
|
||||
code := o.codeFunc(err)
|
||||
level := o.levelFunc(code)
|
||||
logger.Check(level, msg).Write(
|
||||
zap.Error(err),
|
||||
zap.String("grpc.code", code.String()),
|
||||
o.durationFunc(time.Now().Sub(startTime)),
|
||||
)
|
||||
}
|
||||
|
||||
func newClientLoggerFields(ctx context.Context, fullMethodString string) []zapcore.Field {
|
||||
service := path.Dir(fullMethodString)[1:]
|
||||
method := path.Base(fullMethodString)
|
||||
return []zapcore.Field{
|
||||
SystemField,
|
||||
ClientField,
|
||||
zap.String("grpc.service", service),
|
||||
zap.String("grpc.method", method),
|
||||
}
|
||||
}
|
||||
20
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/context.go
generated
vendored
Normal file
20
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/context.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package grpc_zap
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// AddFields adds zap fields to the logger.
|
||||
// Deprecated: should use the ctxzap.AddFields instead
|
||||
func AddFields(ctx context.Context, fields ...zapcore.Field) {
|
||||
ctxzap.AddFields(ctx, fields...)
|
||||
}
|
||||
|
||||
// Extract takes the call-scoped Logger from grpc_zap middleware.
|
||||
// Deprecated: should use the ctxzap.Extract instead
|
||||
func Extract(ctx context.Context) *zap.Logger {
|
||||
return ctxzap.Extract(ctx)
|
||||
}
|
||||
64
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/ctxzap/context.go
generated
vendored
Normal file
64
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/ctxzap/context.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package ctxzap
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type ctxMarker struct{}
|
||||
|
||||
type ctxLogger struct {
|
||||
logger *zap.Logger
|
||||
fields []zapcore.Field
|
||||
}
|
||||
|
||||
var (
|
||||
ctxMarkerKey = &ctxMarker{}
|
||||
nullLogger = zap.NewNop()
|
||||
)
|
||||
|
||||
// AddFields adds zap fields to the logger.
|
||||
func AddFields(ctx context.Context, fields ...zapcore.Field) {
|
||||
l, ok := ctx.Value(ctxMarkerKey).(*ctxLogger)
|
||||
if !ok || l == nil {
|
||||
return
|
||||
}
|
||||
l.fields = append(l.fields, fields...)
|
||||
|
||||
}
|
||||
|
||||
// Extract takes the call-scoped Logger from grpc_zap middleware.
|
||||
//
|
||||
// It always returns a Logger that has all the grpc_ctxtags updated.
|
||||
func Extract(ctx context.Context) *zap.Logger {
|
||||
l, ok := ctx.Value(ctxMarkerKey).(*ctxLogger)
|
||||
if !ok || l == nil {
|
||||
return nullLogger
|
||||
}
|
||||
// Add grpc_ctxtags tags metadata until now.
|
||||
fields := TagsToFields(ctx)
|
||||
// Add zap fields added until now.
|
||||
fields = append(fields, l.fields...)
|
||||
return l.logger.With(fields...)
|
||||
}
|
||||
|
||||
// TagsToFields transforms the Tags on the supplied context into zap fields.
|
||||
func TagsToFields(ctx context.Context) []zapcore.Field {
|
||||
fields := []zapcore.Field{}
|
||||
tags := grpc_ctxtags.Extract(ctx)
|
||||
for k, v := range tags.Values() {
|
||||
fields = append(fields, zap.Any(k, v))
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// ToContext adds the zap.Logger to the context for extraction later.
|
||||
// Returning the new context that has been created.
|
||||
func ToContext(ctx context.Context, logger *zap.Logger) context.Context {
|
||||
l := &ctxLogger{
|
||||
logger: logger,
|
||||
}
|
||||
return context.WithValue(ctx, ctxMarkerKey, l)
|
||||
}
|
||||
14
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/ctxzap/doc.go
generated
vendored
Normal file
14
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/ctxzap/doc.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
`ctxzap` is a ctxlogger that is backed by Zap
|
||||
|
||||
It accepts a user-configured `zap.Logger` that will be used for logging. The same `zap.Logger` will
|
||||
be populated into the `context.Context` passed into gRPC handler code.
|
||||
|
||||
You can use `ctxzap.Extract` to log into a request-scoped `zap.Logger` instance in your handler code.
|
||||
|
||||
As `ctxzap.Extract` will iterate all tags on from `grpc_ctxtags` it is therefore expensive so it is advised that you
|
||||
extract once at the start of the function from the context and reuse it for the remainder of the function (see examples).
|
||||
|
||||
Please see examples and tests for examples of use.
|
||||
*/
|
||||
package ctxzap
|
||||
74
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/doc.go
generated
vendored
Normal file
74
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/doc.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
`grpc_zap` is a gRPC logging middleware backed by ZAP loggers
|
||||
|
||||
It accepts a user-configured `zap.Logger` that will be used for logging completed gRPC calls. The same `zap.Logger` will
|
||||
be used for logging completed gRPC calls, and be populated into the `context.Context` passed into gRPC handler code.
|
||||
|
||||
On calling `StreamServerInterceptor` or `UnaryServerInterceptor` this logging middleware will add gRPC call information
|
||||
to the ctx so that it will be present on subsequent use of the `ctx_zap` logger.
|
||||
|
||||
If a deadline is present on the gRPC request the grpc.request.deadline tag is populated when the request begins. grpc.request.deadline
|
||||
is a string representing the time (RFC3339) when the current call will expire.
|
||||
|
||||
This package also implements request and response *payload* logging, both for server-side and client-side. These will be
|
||||
logged as structured `jsonpb` 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.
|
||||
|
||||
ZAP can also be made as a backend for gRPC library internals. For that use `ReplaceGrpcLogger`.
|
||||
|
||||
|
||||
*Server Interceptor*
|
||||
Below is a JSON formatted example of a log that would be logged by the server interceptor:
|
||||
|
||||
{
|
||||
"level": "info", // string zap log levels
|
||||
"msg": "finished unary call", // string log message
|
||||
|
||||
"grpc.code": "OK", // string grpc status code
|
||||
"grpc.method": "Ping", // string method name
|
||||
"grpc.service": "mwitkow.testproto.TestService", // string full name of the called service
|
||||
"grpc.start_time": "2006-01-02T15:04:05Z07:00", // string RFC3339 representation of the start time
|
||||
"grpc.request.deadline": "2006-01-02T15:04:05Z07:00", // string RFC3339 deadline of the current request if supplied
|
||||
"grpc.request.value": "something", // string value on the request
|
||||
"grpc.time_ms": 1.345, // float32 run time of the call in ms
|
||||
|
||||
"peer.address": {
|
||||
"IP": "127.0.0.1", // string IP address of calling party
|
||||
"Port": 60216, // int port call is coming in on
|
||||
"Zone": "" // string peer zone for caller
|
||||
},
|
||||
"span.kind": "server", // string client | server
|
||||
"system": "grpc" // string
|
||||
|
||||
"custom_field": "custom_value", // string user defined field
|
||||
"custom_tags.int": 1337, // int user defined tag on the ctx
|
||||
"custom_tags.string": "something", // string user defined tag on the ctx
|
||||
}
|
||||
|
||||
*Payload Interceptor*
|
||||
Below is a JSON formatted example of a log that would be logged by the payload interceptor:
|
||||
|
||||
{
|
||||
"level": "info", // string zap log levels
|
||||
"msg": "client request payload logged as grpc.request.content", // string log message
|
||||
|
||||
"grpc.request.content": { // object content of RPC request
|
||||
"msg" : { // object ZAP specific inner object
|
||||
"value": "something", // string defined by caller
|
||||
"sleepTimeMs": 9999 // int defined by caller
|
||||
}
|
||||
},
|
||||
"grpc.method": "Ping", // string method being called
|
||||
"grpc.service": "mwitkow.testproto.TestService", // string service being called
|
||||
|
||||
"span.kind": "client", // string client | server
|
||||
"system": "grpc" // string
|
||||
}
|
||||
|
||||
Note - due to implementation ZAP differs from Logrus in the "grpc.request.content" object by having an inner "msg" object.
|
||||
|
||||
|
||||
Please see examples and tests for examples of use.
|
||||
*/
|
||||
package grpc_zap
|
||||
46
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/grpclogger.go
generated
vendored
Normal file
46
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/grpclogger.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_zap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
// ReplaceGrpcLogger sets the given zap.Logger as a gRPC-level logger.
|
||||
// This should be called *before* any other initialization, preferably from init() functions.
|
||||
func ReplaceGrpcLogger(logger *zap.Logger) {
|
||||
zgl := &zapGrpcLogger{logger.With(SystemField, zap.Bool("grpc_log", true))}
|
||||
grpclog.SetLogger(zgl)
|
||||
}
|
||||
|
||||
type zapGrpcLogger struct {
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (l *zapGrpcLogger) Fatal(args ...interface{}) {
|
||||
l.logger.Fatal(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (l *zapGrpcLogger) Fatalf(format string, args ...interface{}) {
|
||||
l.logger.Fatal(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (l *zapGrpcLogger) Fatalln(args ...interface{}) {
|
||||
l.logger.Fatal(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (l *zapGrpcLogger) Print(args ...interface{}) {
|
||||
l.logger.Info(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
func (l *zapGrpcLogger) Printf(format string, args ...interface{}) {
|
||||
l.logger.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (l *zapGrpcLogger) Println(args ...interface{}) {
|
||||
l.logger.Info(fmt.Sprint(args...))
|
||||
}
|
||||
184
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/options.go
generated
vendored
Normal file
184
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/options.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
package grpc_zap
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultOptions = &options{
|
||||
levelFunc: DefaultCodeToLevel,
|
||||
shouldLog: grpc_logging.DefaultDeciderMethod,
|
||||
codeFunc: grpc_logging.DefaultErrorToCode,
|
||||
durationFunc: DefaultDurationToField,
|
||||
}
|
||||
)
|
||||
|
||||
type options struct {
|
||||
levelFunc CodeToLevel
|
||||
shouldLog grpc_logging.Decider
|
||||
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) zapcore.Level
|
||||
|
||||
// DurationToField function defines how to produce duration fields for logging
|
||||
type DurationToField func(duration time.Duration) zapcore.Field
|
||||
|
||||
// WithDecider customizes the function for deciding if the gRPC interceptor logs should log.
|
||||
func WithDecider(f grpc_logging.Decider) Option {
|
||||
return func(o *options) {
|
||||
o.shouldLog = f
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Zap fields.
|
||||
func WithDurationField(f DurationToField) Option {
|
||||
return func(o *options) {
|
||||
o.durationFunc = f
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultCodeToLevel is the default implementation of gRPC return codes and interceptor log level for server side.
|
||||
func DefaultCodeToLevel(code codes.Code) zapcore.Level {
|
||||
switch code {
|
||||
case codes.OK:
|
||||
return zap.InfoLevel
|
||||
case codes.Canceled:
|
||||
return zap.InfoLevel
|
||||
case codes.Unknown:
|
||||
return zap.ErrorLevel
|
||||
case codes.InvalidArgument:
|
||||
return zap.InfoLevel
|
||||
case codes.DeadlineExceeded:
|
||||
return zap.WarnLevel
|
||||
case codes.NotFound:
|
||||
return zap.InfoLevel
|
||||
case codes.AlreadyExists:
|
||||
return zap.InfoLevel
|
||||
case codes.PermissionDenied:
|
||||
return zap.WarnLevel
|
||||
case codes.Unauthenticated:
|
||||
return zap.InfoLevel // unauthenticated requests can happen
|
||||
case codes.ResourceExhausted:
|
||||
return zap.WarnLevel
|
||||
case codes.FailedPrecondition:
|
||||
return zap.WarnLevel
|
||||
case codes.Aborted:
|
||||
return zap.WarnLevel
|
||||
case codes.OutOfRange:
|
||||
return zap.WarnLevel
|
||||
case codes.Unimplemented:
|
||||
return zap.ErrorLevel
|
||||
case codes.Internal:
|
||||
return zap.ErrorLevel
|
||||
case codes.Unavailable:
|
||||
return zap.WarnLevel
|
||||
case codes.DataLoss:
|
||||
return zap.ErrorLevel
|
||||
default:
|
||||
return zap.ErrorLevel
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultClientCodeToLevel is the default implementation of gRPC return codes to log levels for client side.
|
||||
func DefaultClientCodeToLevel(code codes.Code) zapcore.Level {
|
||||
switch code {
|
||||
case codes.OK:
|
||||
return zap.DebugLevel
|
||||
case codes.Canceled:
|
||||
return zap.DebugLevel
|
||||
case codes.Unknown:
|
||||
return zap.InfoLevel
|
||||
case codes.InvalidArgument:
|
||||
return zap.DebugLevel
|
||||
case codes.DeadlineExceeded:
|
||||
return zap.InfoLevel
|
||||
case codes.NotFound:
|
||||
return zap.DebugLevel
|
||||
case codes.AlreadyExists:
|
||||
return zap.DebugLevel
|
||||
case codes.PermissionDenied:
|
||||
return zap.InfoLevel
|
||||
case codes.Unauthenticated:
|
||||
return zap.InfoLevel // unauthenticated requests can happen
|
||||
case codes.ResourceExhausted:
|
||||
return zap.DebugLevel
|
||||
case codes.FailedPrecondition:
|
||||
return zap.DebugLevel
|
||||
case codes.Aborted:
|
||||
return zap.DebugLevel
|
||||
case codes.OutOfRange:
|
||||
return zap.DebugLevel
|
||||
case codes.Unimplemented:
|
||||
return zap.WarnLevel
|
||||
case codes.Internal:
|
||||
return zap.WarnLevel
|
||||
case codes.Unavailable:
|
||||
return zap.WarnLevel
|
||||
case codes.DataLoss:
|
||||
return zap.WarnLevel
|
||||
default:
|
||||
return zap.InfoLevel
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultDurationToField is the default implementation of converting request duration to a Zap field.
|
||||
var DefaultDurationToField = DurationToTimeMillisField
|
||||
|
||||
// DurationToTimeMillisField converts the duration to milliseconds and uses the key `grpc.time_ms`.
|
||||
func DurationToTimeMillisField(duration time.Duration) zapcore.Field {
|
||||
return zap.Float32("grpc.time_ms", durationToMilliseconds(duration))
|
||||
}
|
||||
|
||||
// DurationToDurationField uses a Duration field to log the request duration
|
||||
// and leaves it up to Zap's encoder settings to determine how that is output.
|
||||
func DurationToDurationField(duration time.Duration) zapcore.Field {
|
||||
return zap.Duration("grpc.duration", duration)
|
||||
}
|
||||
|
||||
func durationToMilliseconds(duration time.Duration) float32 {
|
||||
return float32(duration.Nanoseconds()/1000) / 1000
|
||||
}
|
||||
149
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/payload_interceptors.go
generated
vendored
Normal file
149
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/payload_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
package grpc_zap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"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_zap.UnaryServerInterceptor`. However, the logging can be done to a
|
||||
// separate instance of the logger.
|
||||
func PayloadUnaryServerInterceptor(logger *zap.Logger, 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 zap.Logger for logging but use the fields from context.
|
||||
logEntry := logger.With(append(serverCallFields(info.FullMethod), ctxzap.TagsToFields(ctx)...)...)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// PayloadStreamServerInterceptor returns a new server server interceptors that logs the payloads of requests.
|
||||
//
|
||||
// This *only* works when placed *after* the `grpc_zap.StreamServerInterceptor`. However, the logging can be done to a
|
||||
// separate instance of the logger.
|
||||
func PayloadStreamServerInterceptor(logger *zap.Logger, 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)
|
||||
}
|
||||
logEntry := logger.With(append(serverCallFields(info.FullMethod), ctxzap.TagsToFields(stream.Context())...)...)
|
||||
newStream := &loggingServerStream{ServerStream: stream, logger: logEntry}
|
||||
return handler(srv, newStream)
|
||||
}
|
||||
}
|
||||
|
||||
// PayloadUnaryClientInterceptor returns a new unary client interceptor that logs the paylods of requests and responses.
|
||||
func PayloadUnaryClientInterceptor(logger *zap.Logger, 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 := logger.With(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
|
||||
}
|
||||
}
|
||||
|
||||
// PayloadStreamClientInterceptor returns a new streaming client interceptor that logs the paylods of requests and responses.
|
||||
func PayloadStreamClientInterceptor(logger *zap.Logger, 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 := logger.With(newClientLoggerFields(ctx, method)...)
|
||||
clientStream, err := streamer(ctx, desc, cc, method, opts...)
|
||||
newStream := &loggingClientStream{ClientStream: clientStream, logger: logEntry}
|
||||
return newStream, err
|
||||
}
|
||||
}
|
||||
|
||||
type loggingClientStream struct {
|
||||
grpc.ClientStream
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (l *loggingClientStream) SendMsg(m interface{}) error {
|
||||
err := l.ClientStream.SendMsg(m)
|
||||
if err == nil {
|
||||
logProtoMessageAsJson(l.logger, 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.logger, m, "grpc.response.content", "server response payload logged as grpc.response.content field")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type loggingServerStream struct {
|
||||
grpc.ServerStream
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (l *loggingServerStream) SendMsg(m interface{}) error {
|
||||
err := l.ServerStream.SendMsg(m)
|
||||
if err == nil {
|
||||
logProtoMessageAsJson(l.logger, 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.logger, m, "grpc.request.content", "server request payload logged as grpc.request.content field")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func logProtoMessageAsJson(logger *zap.Logger, pbMsg interface{}, key string, msg string) {
|
||||
if p, ok := pbMsg.(proto.Message); ok {
|
||||
logger.Check(zapcore.InfoLevel, msg).Write(zap.Object(key, &jsonpbObjectMarshaler{pb: p}))
|
||||
}
|
||||
}
|
||||
|
||||
type jsonpbObjectMarshaler struct {
|
||||
pb proto.Message
|
||||
}
|
||||
|
||||
func (j *jsonpbObjectMarshaler) MarshalLogObject(e zapcore.ObjectEncoder) error {
|
||||
// ZAP jsonEncoder deals with AddReflect by using json.MarshalObject. The same thing applies for consoleEncoder.
|
||||
return e.AddReflected("msg", j)
|
||||
}
|
||||
|
||||
func (j *jsonpbObjectMarshaler) MarshalJSON() ([]byte, error) {
|
||||
b := &bytes.Buffer{}
|
||||
if err := JsonPbMarshaller.Marshal(b, j.pb); err != nil {
|
||||
return nil, fmt.Errorf("jsonpb serializer failed: %v", err)
|
||||
}
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
96
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/server_interceptors.go
generated
vendored
Normal file
96
vendor/github.com/mwitkow/go-grpc-middleware/logging/zap/server_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package grpc_zap
|
||||
|
||||
import (
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags/zap"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
// SystemField is used in every log statement made through grpc_zap. Can be overwritten before any initialization code.
|
||||
SystemField = zap.String("system", "grpc")
|
||||
|
||||
// ServerField is used in every server-side log statement made through grpc_zap.Can be overwritten before initialization.
|
||||
ServerField = zap.String("span.kind", "server")
|
||||
)
|
||||
|
||||
// UnaryServerInterceptor returns a new unary server interceptors that adds zap.Logger to the context.
|
||||
func UnaryServerInterceptor(logger *zap.Logger, opts ...Option) grpc.UnaryServerInterceptor {
|
||||
o := evaluateServerOpt(opts)
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
startTime := time.Now()
|
||||
|
||||
newCtx := newLoggerForCall(ctx, logger, info.FullMethod, startTime)
|
||||
|
||||
resp, err := handler(newCtx, req)
|
||||
if !o.shouldLog(info.FullMethod, err) {
|
||||
return resp, err
|
||||
}
|
||||
code := o.codeFunc(err)
|
||||
level := o.levelFunc(code)
|
||||
|
||||
// re-extract logger from newCtx, as it may have extra fields that changed in the holder.
|
||||
ctx_zap.Extract(newCtx).Check(level, "finished unary call with code "+code.String()).Write(
|
||||
zap.Error(err),
|
||||
zap.String("grpc.code", code.String()),
|
||||
o.durationFunc(time.Since(startTime)),
|
||||
)
|
||||
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
// StreamServerInterceptor returns a new streaming server interceptor that adds zap.Logger to the context.
|
||||
func StreamServerInterceptor(logger *zap.Logger, opts ...Option) grpc.StreamServerInterceptor {
|
||||
o := evaluateServerOpt(opts)
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
startTime := time.Now()
|
||||
newCtx := newLoggerForCall(stream.Context(), logger, info.FullMethod, startTime)
|
||||
wrapped := grpc_middleware.WrapServerStream(stream)
|
||||
wrapped.WrappedContext = newCtx
|
||||
|
||||
err := handler(srv, wrapped)
|
||||
if !o.shouldLog(info.FullMethod, err) {
|
||||
return err
|
||||
}
|
||||
code := o.codeFunc(err)
|
||||
level := o.levelFunc(code)
|
||||
|
||||
// re-extract logger from newCtx, as it may have extra fields that changed in the holder.
|
||||
ctx_zap.Extract(newCtx).Check(level, "finished streaming call with code "+code.String()).Write(
|
||||
zap.Error(err),
|
||||
zap.String("grpc.code", code.String()),
|
||||
o.durationFunc(time.Since(startTime)),
|
||||
)
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func serverCallFields(fullMethodString string) []zapcore.Field {
|
||||
service := path.Dir(fullMethodString)[1:]
|
||||
method := path.Base(fullMethodString)
|
||||
return []zapcore.Field{
|
||||
SystemField,
|
||||
ServerField,
|
||||
zap.String("grpc.service", service),
|
||||
zap.String("grpc.method", method),
|
||||
}
|
||||
}
|
||||
|
||||
func newLoggerForCall(ctx context.Context, logger *zap.Logger, fullMethodString string, start time.Time) context.Context {
|
||||
f := ctxzap.TagsToFields(ctx)
|
||||
f = append(f, zap.String("grpc.start_time", start.Format(time.RFC3339)))
|
||||
if d, ok := ctx.Deadline(); ok {
|
||||
f = append(f, zap.String("grpc.request.deadline", d.Format(time.RFC3339)))
|
||||
}
|
||||
callLog := logger.With(append(f, serverCallFields(fullMethodString)...)...)
|
||||
return ctxzap.ToContext(ctx, callLog)
|
||||
}
|
||||
15
vendor/github.com/mwitkow/go-grpc-middleware/recovery/doc.go
generated
vendored
Normal file
15
vendor/github.com/mwitkow/go-grpc-middleware/recovery/doc.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2017 David Ackroyd. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`grpc_recovery` are intereceptors that recover from gRPC handler panics.
|
||||
|
||||
Server Side Recovery Middleware
|
||||
|
||||
By default a panic will be converted into a gRPC error with `code.Internal`.
|
||||
|
||||
Handling can be customised by providing an alternate recovery function.
|
||||
|
||||
Please see examples for simple examples of use.
|
||||
*/
|
||||
package grpc_recovery
|
||||
48
vendor/github.com/mwitkow/go-grpc-middleware/recovery/interceptors.go
generated
vendored
Normal file
48
vendor/github.com/mwitkow/go-grpc-middleware/recovery/interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2017 David Ackroyd. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_recovery
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
// RecoveryHandlerFunc is a function that recovers from the panic `p` by returning an `error`.
|
||||
type RecoveryHandlerFunc func(p interface{}) (err error)
|
||||
|
||||
// UnaryServerInterceptor returns a new unary server interceptor for panic recovery.
|
||||
func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
|
||||
o := evaluateOptions(opts)
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (_ interface{}, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = recoverFrom(r, o.recoveryHandlerFunc)
|
||||
}
|
||||
}()
|
||||
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
|
||||
// StreamServerInterceptor returns a new streaming server interceptor for panic recovery.
|
||||
func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
|
||||
o := evaluateOptions(opts)
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = recoverFrom(r, o.recoveryHandlerFunc)
|
||||
}
|
||||
}()
|
||||
|
||||
return handler(srv, stream)
|
||||
}
|
||||
}
|
||||
|
||||
func recoverFrom(p interface{}, r RecoveryHandlerFunc) error {
|
||||
if r == nil {
|
||||
return grpc.Errorf(codes.Internal, "%s", p)
|
||||
}
|
||||
return r(p)
|
||||
}
|
||||
32
vendor/github.com/mwitkow/go-grpc-middleware/recovery/options.go
generated
vendored
Normal file
32
vendor/github.com/mwitkow/go-grpc-middleware/recovery/options.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2017 David Ackroyd. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_recovery
|
||||
|
||||
var (
|
||||
defaultOptions = &options{
|
||||
recoveryHandlerFunc: nil,
|
||||
}
|
||||
)
|
||||
|
||||
type options struct {
|
||||
recoveryHandlerFunc RecoveryHandlerFunc
|
||||
}
|
||||
|
||||
func evaluateOptions(opts []Option) *options {
|
||||
optCopy := &options{}
|
||||
*optCopy = *defaultOptions
|
||||
for _, o := range opts {
|
||||
o(optCopy)
|
||||
}
|
||||
return optCopy
|
||||
}
|
||||
|
||||
type Option func(*options)
|
||||
|
||||
// WithRecoveryHandler customizes the function for recovering from a panic.
|
||||
func WithRecoveryHandler(f RecoveryHandlerFunc) Option {
|
||||
return func(o *options) {
|
||||
o.recoveryHandlerFunc = f
|
||||
}
|
||||
}
|
||||
26
vendor/github.com/mwitkow/go-grpc-middleware/retry/backoff.go
generated
vendored
Normal file
26
vendor/github.com/mwitkow/go-grpc-middleware/retry/backoff.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_retry
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/backoffutils"
|
||||
)
|
||||
|
||||
// BackoffLinear is very simple: it waits for a fixed period of time between calls.
|
||||
func BackoffLinear(waitBetween time.Duration) BackoffFunc {
|
||||
return func(attempt uint) time.Duration {
|
||||
return waitBetween
|
||||
}
|
||||
}
|
||||
|
||||
// BackoffLinearWithJitter waits a set period of time, allowing for jitter (fractional adjustment).
|
||||
//
|
||||
// For example waitBetween=1s and jitter=0.10 can generate waits between 900ms and 1100ms.
|
||||
func BackoffLinearWithJitter(waitBetween time.Duration, jitterFraction float64) BackoffFunc {
|
||||
return func(attempt uint) time.Duration {
|
||||
return backoffutils.JitterUp(waitBetween, jitterFraction)
|
||||
}
|
||||
}
|
||||
25
vendor/github.com/mwitkow/go-grpc-middleware/retry/doc.go
generated
vendored
Normal file
25
vendor/github.com/mwitkow/go-grpc-middleware/retry/doc.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`grpc_retry` provides client-side request retry logic for gRPC.
|
||||
|
||||
Client-Side Request Retry Interceptor
|
||||
|
||||
It allows for automatic retry, inside the generated gRPC code of requests based on the gRPC status
|
||||
of the reply. It supports unary (1:1), and server stream (1:n) requests.
|
||||
|
||||
By default the interceptors *are disabled*, preventing accidental use of retries. You can easily
|
||||
override the number of retries (setting them to more than 0) with a `grpc.ClientOption`, e.g.:
|
||||
|
||||
myclient.Ping(ctx, goodPing, grpc_retry.WithMax(5))
|
||||
|
||||
Other default options are: retry on `ResourceExhausted` and `Unavailable` gRPC codes, use a 50ms
|
||||
linear backoff with 10% jitter.
|
||||
|
||||
For chained interceptors, the retry interceptor will call every interceptor that follows it
|
||||
whenever when a retry happens.
|
||||
|
||||
Please see examples for more advanced use.
|
||||
*/
|
||||
package grpc_retry
|
||||
120
vendor/github.com/mwitkow/go-grpc-middleware/retry/options.go
generated
vendored
Normal file
120
vendor/github.com/mwitkow/go-grpc-middleware/retry/options.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_retry
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultRetriableCodes is a set of well known types gRPC codes that should be retri-able.
|
||||
//
|
||||
// `ResourceExhausted` means that the user quota, e.g. per-RPC limits, have been reached.
|
||||
// `Unavailable` means that system is currently unavailable and the client should retry again.
|
||||
DefaultRetriableCodes = []codes.Code{codes.ResourceExhausted, codes.Unavailable}
|
||||
|
||||
defaultOptions = &options{
|
||||
max: 0, // disabed
|
||||
perCallTimeout: 0, // disabled
|
||||
includeHeader: true,
|
||||
codes: DefaultRetriableCodes,
|
||||
backoffFunc: BackoffLinearWithJitter(50*time.Millisecond /*jitter*/, 0.10),
|
||||
}
|
||||
)
|
||||
|
||||
// BackoffFunc denotes a family of functions that control the backoff duration between call retries.
|
||||
//
|
||||
// They are called with an identifier of the attempt, and should return a time the system client should
|
||||
// hold off for. If the time returned is longer than the `context.Context.Deadline` of the request
|
||||
// the deadline of the request takes precedence and the wait will be interrupted before proceeding
|
||||
// with the next iteration.
|
||||
type BackoffFunc func(attempt uint) time.Duration
|
||||
|
||||
// Disable disables the retry behaviour on this call, or this interceptor.
|
||||
//
|
||||
// Its semantically the same to `WithMax`
|
||||
func Disable() CallOption {
|
||||
return WithMax(0)
|
||||
}
|
||||
|
||||
// WithMax sets the maximum number of retries on this call, or this interceptor.
|
||||
func WithMax(maxRetries uint) CallOption {
|
||||
return CallOption{applyFunc: func(o *options) {
|
||||
o.max = maxRetries
|
||||
}}
|
||||
}
|
||||
|
||||
// WithBackoff sets the `BackoffFunc `used to control time between retries.
|
||||
func WithBackoff(bf BackoffFunc) CallOption {
|
||||
return CallOption{applyFunc: func(o *options) {
|
||||
o.backoffFunc = bf
|
||||
}}
|
||||
}
|
||||
|
||||
// WithCodes sets which codes should be retried.
|
||||
//
|
||||
// Please *use with care*, as you may be retrying non-idempotend calls.
|
||||
//
|
||||
// You cannot automatically retry on Cancelled and Deadline, please use `WithPerRetryTimeout` for these.
|
||||
func WithCodes(retryCodes ...codes.Code) CallOption {
|
||||
return CallOption{applyFunc: func(o *options) {
|
||||
o.codes = retryCodes
|
||||
}}
|
||||
}
|
||||
|
||||
// WithPerRetryTimeout sets the RPC timeout per call (including initial call) on this call, or this interceptor.
|
||||
//
|
||||
// The context.Deadline of the call takes precedence and sets the maximum time the whole invocation
|
||||
// will take, but WithPerRetryTimeout can be used to limit the RPC time per each call.
|
||||
//
|
||||
// For example, with context.Deadline = now + 10s, and WithPerRetryTimeout(3 * time.Seconds), each
|
||||
// of the retry calls (including the initial one) will have a deadline of now + 3s.
|
||||
//
|
||||
// A value of 0 disables the timeout overrides completely and returns to each retry call using the
|
||||
// parent `context.Deadline`.
|
||||
func WithPerRetryTimeout(timeout time.Duration) CallOption {
|
||||
return CallOption{applyFunc: func(o *options) {
|
||||
o.perCallTimeout = timeout
|
||||
}}
|
||||
}
|
||||
|
||||
type options struct {
|
||||
max uint
|
||||
perCallTimeout time.Duration
|
||||
includeHeader bool
|
||||
codes []codes.Code
|
||||
backoffFunc BackoffFunc
|
||||
}
|
||||
|
||||
// CallOption is a grpc.CallOption that is local to grpc_retry.
|
||||
type CallOption struct {
|
||||
grpc.EmptyCallOption // make sure we implement private after() and before() fields so we don't panic.
|
||||
applyFunc func(opt *options)
|
||||
}
|
||||
|
||||
func reuseOrNewWithCallOptions(opt *options, callOptions []CallOption) *options {
|
||||
if len(callOptions) == 0 {
|
||||
return opt
|
||||
}
|
||||
optCopy := &options{}
|
||||
*optCopy = *opt
|
||||
for _, f := range callOptions {
|
||||
f.applyFunc(optCopy)
|
||||
}
|
||||
return optCopy
|
||||
}
|
||||
|
||||
func filterCallOptions(callOptions []grpc.CallOption) (grpcOptions []grpc.CallOption, retryOptions []CallOption) {
|
||||
for _, opt := range callOptions {
|
||||
if co, ok := opt.(CallOption); ok {
|
||||
retryOptions = append(retryOptions, co)
|
||||
} else {
|
||||
grpcOptions = append(grpcOptions, opt)
|
||||
}
|
||||
}
|
||||
return grpcOptions, retryOptions
|
||||
}
|
||||
296
vendor/github.com/mwitkow/go-grpc-middleware/retry/retry.go
generated
vendored
Normal file
296
vendor/github.com/mwitkow/go-grpc-middleware/retry/retry.go
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_retry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/trace"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
AttemptMetadataKey = "x-retry-attempty"
|
||||
)
|
||||
|
||||
// UnaryClientInterceptor returns a new retrying unary client interceptor.
|
||||
//
|
||||
// The default configuration of the interceptor is to not retry *at all*. This behaviour can be
|
||||
// changed through options (e.g. WithMax) on creation of the interceptor or on call (through grpc.CallOptions).
|
||||
func UnaryClientInterceptor(optFuncs ...CallOption) grpc.UnaryClientInterceptor {
|
||||
intOpts := reuseOrNewWithCallOptions(defaultOptions, optFuncs)
|
||||
return func(parentCtx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
grpcOpts, retryOpts := filterCallOptions(opts)
|
||||
callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts)
|
||||
// short circuit for simplicity, and avoiding allocations.
|
||||
if callOpts.max == 0 {
|
||||
return invoker(parentCtx, method, req, reply, cc, grpcOpts...)
|
||||
}
|
||||
var lastErr error
|
||||
for attempt := uint(0); attempt < callOpts.max; attempt++ {
|
||||
if err := waitRetryBackoff(attempt, parentCtx, callOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
callCtx := perCallContext(parentCtx, callOpts, attempt)
|
||||
lastErr = invoker(callCtx, method, req, reply, cc, grpcOpts...)
|
||||
// TODO(mwitkow): Maybe dial and transport errors should be retriable?
|
||||
if lastErr == nil {
|
||||
return nil
|
||||
}
|
||||
logTrace(parentCtx, "grpc_retry attempt: %d, got err: %v", attempt, lastErr)
|
||||
if isContextError(lastErr) {
|
||||
if parentCtx.Err() != nil {
|
||||
logTrace(parentCtx, "grpc_retry attempt: %d, parent context error: %v", attempt, parentCtx.Err())
|
||||
// its the parent context deadline or cancellation.
|
||||
return lastErr
|
||||
} else {
|
||||
logTrace(parentCtx, "grpc_retry attempt: %d, context error from retry call", attempt)
|
||||
// its the callCtx deadline or cancellation, in which case try again.
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !isRetriable(lastErr, callOpts) {
|
||||
return lastErr
|
||||
}
|
||||
}
|
||||
return lastErr
|
||||
}
|
||||
}
|
||||
|
||||
// StreamClientInterceptor returns a new retrying stream client interceptor for server side streaming calls.
|
||||
//
|
||||
// The default configuration of the interceptor is to not retry *at all*. This behaviour can be
|
||||
// changed through options (e.g. WithMax) on creation of the interceptor or on call (through grpc.CallOptions).
|
||||
//
|
||||
// Retry logic is available *only for ServerStreams*, i.e. 1:n streams, as the internal logic needs
|
||||
// to buffer the messages sent by the client. If retry is enabled on any other streams (ClientStreams,
|
||||
// BidiStreams), the retry interceptor will fail the call.
|
||||
func StreamClientInterceptor(optFuncs ...CallOption) grpc.StreamClientInterceptor {
|
||||
intOpts := reuseOrNewWithCallOptions(defaultOptions, optFuncs)
|
||||
return func(parentCtx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
grpcOpts, retryOpts := filterCallOptions(opts)
|
||||
callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts)
|
||||
// short circuit for simplicity, and avoiding allocations.
|
||||
if callOpts.max == 0 {
|
||||
return streamer(parentCtx, desc, cc, method, grpcOpts...)
|
||||
}
|
||||
if desc.ClientStreams {
|
||||
return nil, grpc.Errorf(codes.Unimplemented, "grpc_retry: cannot retry on ClientStreams, set grpc_retry.Disable()")
|
||||
}
|
||||
logTrace(parentCtx, "grpc_retry attempt: %d, no backoff for this call", 0)
|
||||
callCtx := perCallContext(parentCtx, callOpts, 0)
|
||||
newStreamer, err := streamer(callCtx, desc, cc, method, grpcOpts...)
|
||||
if err != nil {
|
||||
// TODO(mwitkow): Maybe dial and transport errors should be retriable?
|
||||
return nil, err
|
||||
}
|
||||
retryingStreamer := &serverStreamingRetryingStream{
|
||||
ClientStream: newStreamer,
|
||||
callOpts: callOpts,
|
||||
parentCtx: parentCtx,
|
||||
streamerCall: func(ctx context.Context) (grpc.ClientStream, error) {
|
||||
return streamer(ctx, desc, cc, method, grpcOpts...)
|
||||
},
|
||||
}
|
||||
return retryingStreamer, nil
|
||||
}
|
||||
}
|
||||
|
||||
// type serverStreamingRetryingStream is the implementation of grpc.ClientStream that acts as a
|
||||
// proxy to the underlying call. If any of the RecvMsg() calls fail, it will try to reestablish
|
||||
// a new ClientStream according to the retry policy.
|
||||
type serverStreamingRetryingStream struct {
|
||||
grpc.ClientStream
|
||||
bufferedSends []interface{} // single messsage that the client can sen
|
||||
receivedGood bool // indicates whether any prior receives were successful
|
||||
wasClosedSend bool // indicates that CloseSend was closed
|
||||
parentCtx context.Context
|
||||
callOpts *options
|
||||
streamerCall func(ctx context.Context) (grpc.ClientStream, error)
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) setStream(clientStream grpc.ClientStream) {
|
||||
s.mu.Lock()
|
||||
s.ClientStream = clientStream
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) getStream() grpc.ClientStream {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.ClientStream
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) SendMsg(m interface{}) error {
|
||||
s.mu.Lock()
|
||||
s.bufferedSends = append(s.bufferedSends, m)
|
||||
s.mu.Unlock()
|
||||
return s.getStream().SendMsg(m)
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) CloseSend() error {
|
||||
s.mu.Lock()
|
||||
s.wasClosedSend = true
|
||||
s.mu.Unlock()
|
||||
return s.getStream().CloseSend()
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) Header() (metadata.MD, error) {
|
||||
return s.getStream().Header()
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) Trailer() metadata.MD {
|
||||
return s.getStream().Trailer()
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) RecvMsg(m interface{}) error {
|
||||
attemptRetry, lastErr := s.receiveMsgAndIndicateRetry(m)
|
||||
if !attemptRetry {
|
||||
return lastErr // success or hard failure
|
||||
}
|
||||
// We start off from attempt 1, because zeroth was already made on normal SendMsg().
|
||||
for attempt := uint(1); attempt < s.callOpts.max; attempt++ {
|
||||
if err := waitRetryBackoff(attempt, s.parentCtx, s.callOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
callCtx := perCallContext(s.parentCtx, s.callOpts, attempt)
|
||||
newStream, err := s.reestablishStreamAndResendBuffer(callCtx)
|
||||
if err != nil {
|
||||
// TODO(mwitkow): Maybe dial and transport errors should be retriable?
|
||||
return err
|
||||
}
|
||||
s.setStream(newStream)
|
||||
attemptRetry, lastErr = s.receiveMsgAndIndicateRetry(m)
|
||||
//fmt.Printf("Received message and indicate: %v %v\n", attemptRetry, lastErr)
|
||||
if !attemptRetry {
|
||||
return lastErr
|
||||
}
|
||||
}
|
||||
return lastErr
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) receiveMsgAndIndicateRetry(m interface{}) (bool, error) {
|
||||
s.mu.RLock()
|
||||
wasGood := s.receivedGood
|
||||
s.mu.RUnlock()
|
||||
err := s.getStream().RecvMsg(m)
|
||||
if err == nil || err == io.EOF {
|
||||
s.mu.Lock()
|
||||
s.receivedGood = true
|
||||
s.mu.Unlock()
|
||||
return false, err
|
||||
} else if wasGood {
|
||||
// previous RecvMsg in the stream succeeded, no retry logic should interfere
|
||||
return false, err
|
||||
}
|
||||
if isContextError(err) {
|
||||
if s.parentCtx.Err() != nil {
|
||||
logTrace(s.parentCtx, "grpc_retry parent context error: %v", s.parentCtx.Err())
|
||||
return false, err
|
||||
} else {
|
||||
logTrace(s.parentCtx, "grpc_retry context error from retry call")
|
||||
// its the callCtx deadline or cancellation, in which case try again.
|
||||
return true, err
|
||||
}
|
||||
}
|
||||
return isRetriable(err, s.callOpts), err
|
||||
|
||||
}
|
||||
|
||||
func (s *serverStreamingRetryingStream) reestablishStreamAndResendBuffer(callCtx context.Context) (grpc.ClientStream, error) {
|
||||
s.mu.RLock()
|
||||
bufferedSends := s.bufferedSends
|
||||
s.mu.RUnlock()
|
||||
newStream, err := s.streamerCall(callCtx)
|
||||
if err != nil {
|
||||
logTrace(callCtx, "grpc_retry failed redialing new stream: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
for _, msg := range bufferedSends {
|
||||
if err := newStream.SendMsg(msg); err != nil {
|
||||
logTrace(callCtx, "grpc_retry failed resending message: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := newStream.CloseSend(); err != nil {
|
||||
logTrace(callCtx, "grpc_retry failed CloseSend on new stream %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return newStream, nil
|
||||
}
|
||||
|
||||
func waitRetryBackoff(attempt uint, parentCtx context.Context, callOpts *options) error {
|
||||
var waitTime time.Duration = 0
|
||||
if attempt > 0 {
|
||||
waitTime = callOpts.backoffFunc(attempt)
|
||||
}
|
||||
if waitTime > 0 {
|
||||
logTrace(parentCtx, "grpc_retry attempt: %d, backoff for %v", attempt, waitTime)
|
||||
timer := time.NewTimer(waitTime)
|
||||
select {
|
||||
case <-parentCtx.Done():
|
||||
timer.Stop()
|
||||
return contextErrToGrpcErr(parentCtx.Err())
|
||||
case <-timer.C:
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isRetriable(err error, callOpts *options) bool {
|
||||
errCode := grpc.Code(err)
|
||||
if isContextError(err) {
|
||||
// context errors are not retriable based on user settings.
|
||||
return false
|
||||
}
|
||||
for _, code := range callOpts.codes {
|
||||
if code == errCode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isContextError(err error) bool {
|
||||
return grpc.Code(err) == codes.DeadlineExceeded || grpc.Code(err) == codes.Canceled
|
||||
}
|
||||
|
||||
func perCallContext(parentCtx context.Context, callOpts *options, attempt uint) context.Context {
|
||||
ctx := parentCtx
|
||||
if callOpts.perCallTimeout != 0 {
|
||||
ctx, _ = context.WithTimeout(ctx, callOpts.perCallTimeout)
|
||||
}
|
||||
if attempt > 0 && callOpts.includeHeader {
|
||||
mdClone := metautils.ExtractOutgoing(ctx).Clone().Set(AttemptMetadataKey, fmt.Sprintf("%d", attempt))
|
||||
ctx = mdClone.ToOutgoing(ctx)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func contextErrToGrpcErr(err error) error {
|
||||
switch err {
|
||||
case context.DeadlineExceeded:
|
||||
return grpc.Errorf(codes.DeadlineExceeded, err.Error())
|
||||
case context.Canceled:
|
||||
return grpc.Errorf(codes.Canceled, err.Error())
|
||||
default:
|
||||
return grpc.Errorf(codes.Unknown, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func logTrace(ctx context.Context, format string, a ...interface{}) {
|
||||
tr, ok := trace.FromContext(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
tr.LazyPrintf(format, a...)
|
||||
}
|
||||
163
vendor/github.com/mwitkow/go-grpc-middleware/testing/gogotestproto/fields.pb.go
generated
vendored
Normal file
163
vendor/github.com/mwitkow/go-grpc-middleware/testing/gogotestproto/fields.pb.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// Code generated by protoc-gen-gogo.
|
||||
// source: fields.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package mwitkow_testproto is a generated protocol buffer package.
|
||||
|
||||
This file is used for testing discovery of log fields from requests using reflection and gogo proto more tags.
|
||||
|
||||
It is generated from these files:
|
||||
fields.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Metadata
|
||||
PingId
|
||||
Ping
|
||||
PingRequest
|
||||
Pong
|
||||
PongRequest
|
||||
*/
|
||||
package mwitkow_testproto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
// 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
|
||||
|
||||
type Metadata struct {
|
||||
Tags []string `protobuf:"bytes,1,rep,name=tags" json:"tags,omitempty" log_field:"meta_tags"`
|
||||
}
|
||||
|
||||
func (m *Metadata) Reset() { *m = Metadata{} }
|
||||
func (m *Metadata) String() string { return proto.CompactTextString(m) }
|
||||
func (*Metadata) ProtoMessage() {}
|
||||
func (*Metadata) Descriptor() ([]byte, []int) { return fileDescriptorFields, []int{0} }
|
||||
|
||||
type PingId struct {
|
||||
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty" log_field:"ping_id"`
|
||||
}
|
||||
|
||||
func (m *PingId) Reset() { *m = PingId{} }
|
||||
func (m *PingId) String() string { return proto.CompactTextString(m) }
|
||||
func (*PingId) ProtoMessage() {}
|
||||
func (*PingId) Descriptor() ([]byte, []int) { return fileDescriptorFields, []int{1} }
|
||||
|
||||
type Ping struct {
|
||||
Id *PingId `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Ping) Reset() { *m = Ping{} }
|
||||
func (m *Ping) String() string { return proto.CompactTextString(m) }
|
||||
func (*Ping) ProtoMessage() {}
|
||||
func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptorFields, []int{2} }
|
||||
|
||||
func (m *Ping) GetId() *PingId {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PingRequest struct {
|
||||
Ping *Ping `protobuf:"bytes,1,opt,name=ping" json:"ping,omitempty"`
|
||||
Meta *Metadata `protobuf:"bytes,2,opt,name=meta" json:"meta,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PingRequest) Reset() { *m = PingRequest{} }
|
||||
func (m *PingRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PingRequest) ProtoMessage() {}
|
||||
func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptorFields, []int{3} }
|
||||
|
||||
func (m *PingRequest) GetPing() *Ping {
|
||||
if m != nil {
|
||||
return m.Ping
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PingRequest) GetMeta() *Metadata {
|
||||
if m != nil {
|
||||
return m.Meta
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Pong struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" log_field:"pong_id"`
|
||||
}
|
||||
|
||||
func (m *Pong) Reset() { *m = Pong{} }
|
||||
func (m *Pong) String() string { return proto.CompactTextString(m) }
|
||||
func (*Pong) ProtoMessage() {}
|
||||
func (*Pong) Descriptor() ([]byte, []int) { return fileDescriptorFields, []int{4} }
|
||||
|
||||
type PongRequest struct {
|
||||
Pong *Pong `protobuf:"bytes,1,opt,name=pong" json:"pong,omitempty"`
|
||||
Meta *Metadata `protobuf:"bytes,2,opt,name=meta" json:"meta,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PongRequest) Reset() { *m = PongRequest{} }
|
||||
func (m *PongRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PongRequest) ProtoMessage() {}
|
||||
func (*PongRequest) Descriptor() ([]byte, []int) { return fileDescriptorFields, []int{5} }
|
||||
|
||||
func (m *PongRequest) GetPong() *Pong {
|
||||
if m != nil {
|
||||
return m.Pong
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PongRequest) GetMeta() *Metadata {
|
||||
if m != nil {
|
||||
return m.Meta
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Metadata)(nil), "mwitkow.testproto.Metadata")
|
||||
proto.RegisterType((*PingId)(nil), "mwitkow.testproto.PingId")
|
||||
proto.RegisterType((*Ping)(nil), "mwitkow.testproto.Ping")
|
||||
proto.RegisterType((*PingRequest)(nil), "mwitkow.testproto.PingRequest")
|
||||
proto.RegisterType((*Pong)(nil), "mwitkow.testproto.Pong")
|
||||
proto.RegisterType((*PongRequest)(nil), "mwitkow.testproto.PongRequest")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("fields.proto", fileDescriptorFields) }
|
||||
|
||||
var fileDescriptorFields = []byte{
|
||||
// 304 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x50, 0x41, 0x4e, 0xeb, 0x30,
|
||||
0x14, 0xfc, 0xe9, 0x77, 0x2b, 0xea, 0xb2, 0xc1, 0x80, 0xda, 0x82, 0x44, 0x2b, 0x6f, 0x28, 0x42,
|
||||
0x4d, 0x44, 0x59, 0xc1, 0xb2, 0x1b, 0xc4, 0x02, 0xa9, 0xf2, 0x05, 0x22, 0x07, 0xbb, 0xc6, 0x6a,
|
||||
0x92, 0x57, 0x88, 0x43, 0xaf, 0xc2, 0xe9, 0xba, 0xe1, 0x06, 0x3d, 0x01, 0xf2, 0x0b, 0xa0, 0xa0,
|
||||
0x02, 0x0b, 0x76, 0x9e, 0xf7, 0x66, 0xe6, 0xcd, 0x98, 0xee, 0xce, 0xad, 0x4e, 0x55, 0x11, 0x2e,
|
||||
0x9f, 0xc0, 0x01, 0xdb, 0xcb, 0x56, 0xd6, 0x2d, 0x60, 0x15, 0x3a, 0x5d, 0x38, 0x1c, 0x1d, 0x8d,
|
||||
0x8d, 0x75, 0x0f, 0x65, 0x12, 0xde, 0x43, 0x16, 0x19, 0x30, 0x10, 0xe1, 0x38, 0x29, 0xe7, 0x88,
|
||||
0x10, 0xe0, 0xab, 0x72, 0xe0, 0x57, 0x74, 0xe7, 0x4e, 0x3b, 0xa9, 0xa4, 0x93, 0x6c, 0x4c, 0x89,
|
||||
0x93, 0xa6, 0xe8, 0x05, 0xc3, 0xff, 0xa3, 0xf6, 0xb4, 0xbf, 0x59, 0x0f, 0x0e, 0x53, 0x30, 0x31,
|
||||
0x5e, 0xbc, 0xe6, 0x99, 0x76, 0x32, 0xf6, 0x7b, 0x2e, 0x90, 0xc6, 0x2f, 0x68, 0x6b, 0x66, 0x73,
|
||||
0x73, 0xab, 0xd8, 0x29, 0x6d, 0x58, 0xd5, 0x0b, 0x86, 0xc1, 0xa8, 0x39, 0xed, 0x6e, 0xd6, 0x83,
|
||||
0xfd, 0x9a, 0x6c, 0x69, 0x73, 0x13, 0x5b, 0xc5, 0x45, 0xc3, 0x2a, 0x7e, 0x43, 0x89, 0x97, 0xb0,
|
||||
0xb3, 0x4f, 0x41, 0x67, 0xd2, 0x0f, 0xb7, 0x4a, 0x84, 0x95, 0xaf, 0x97, 0xb0, 0x03, 0xda, 0x7c,
|
||||
0x96, 0x69, 0xa9, 0x7b, 0x8d, 0x61, 0x30, 0x6a, 0x8b, 0x0a, 0xf0, 0x05, 0xed, 0x78, 0x8e, 0xd0,
|
||||
0x8f, 0xa5, 0x2e, 0x1c, 0x3b, 0xa7, 0xc4, 0xdf, 0x79, 0x77, 0xec, 0xfe, 0xe0, 0x28, 0x90, 0xc4,
|
||||
0x22, 0x4a, 0x7c, 0x17, 0x34, 0xec, 0x4c, 0x8e, 0xbf, 0x21, 0x7f, 0xfc, 0x88, 0x40, 0x22, 0x8f,
|
||||
0x28, 0x99, 0x41, 0x6e, 0x6a, 0x35, 0xdb, 0xdb, 0x35, 0xa1, 0x56, 0xd3, 0xa7, 0x83, 0xaf, 0xe9,
|
||||
0xe0, 0xf7, 0x74, 0x80, 0xe9, 0xe0, 0x0f, 0xe9, 0xa6, 0xe4, 0xe5, 0xf5, 0xe4, 0x5f, 0xd2, 0xc2,
|
||||
0xdd, 0xe5, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x67, 0x44, 0x3b, 0x20, 0x02, 0x00, 0x00,
|
||||
}
|
||||
111
vendor/github.com/mwitkow/go-grpc-middleware/testing/interceptor_suite.go
generated
vendored
Normal file
111
vendor/github.com/mwitkow/go-grpc-middleware/testing/interceptor_suite.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_testing
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"flag"
|
||||
"path"
|
||||
"runtime"
|
||||
|
||||
pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
var (
|
||||
flagTls = flag.Bool("use_tls", true, "whether all gRPC middleware tests should use tls")
|
||||
)
|
||||
|
||||
func getTestingCertsPath() string {
|
||||
_, callerPath, _, _ := runtime.Caller(0)
|
||||
return path.Join(path.Dir(callerPath), "certs")
|
||||
}
|
||||
|
||||
// InterceptorTestSuite is a testify/Suite that starts a gRPC PingService server and a client.
|
||||
type InterceptorTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
TestService pb_testproto.TestServiceServer
|
||||
ServerOpts []grpc.ServerOption
|
||||
ClientOpts []grpc.DialOption
|
||||
|
||||
ServerListener net.Listener
|
||||
Server *grpc.Server
|
||||
clientConn *grpc.ClientConn
|
||||
Client pb_testproto.TestServiceClient
|
||||
}
|
||||
|
||||
func (s *InterceptorTestSuite) SetupSuite() {
|
||||
var err error
|
||||
s.ServerListener, err = net.Listen("tcp", "127.0.0.1:0")
|
||||
require.NoError(s.T(), err, "must be able to allocate a port for serverListener")
|
||||
if *flagTls {
|
||||
creds, err := credentials.NewServerTLSFromFile(
|
||||
path.Join(getTestingCertsPath(), "localhost.crt"),
|
||||
path.Join(getTestingCertsPath(), "localhost.key"),
|
||||
)
|
||||
require.NoError(s.T(), err, "failed reading server credentials for localhost.crt")
|
||||
s.ServerOpts = append(s.ServerOpts, grpc.Creds(creds))
|
||||
}
|
||||
// This is the point where we hook up the interceptor
|
||||
s.Server = grpc.NewServer(s.ServerOpts...)
|
||||
// Crete a service of the instantiator hasn't provided one.
|
||||
if s.TestService == nil {
|
||||
s.TestService = &TestPingService{T: s.T()}
|
||||
}
|
||||
pb_testproto.RegisterTestServiceServer(s.Server, s.TestService)
|
||||
|
||||
go func() {
|
||||
s.Server.Serve(s.ServerListener)
|
||||
}()
|
||||
s.Client = s.NewClient(s.ClientOpts...)
|
||||
}
|
||||
|
||||
func (s *InterceptorTestSuite) NewClient(dialOpts ...grpc.DialOption) pb_testproto.TestServiceClient {
|
||||
newDialOpts := append(dialOpts, grpc.WithBlock(), grpc.WithTimeout(2*time.Second))
|
||||
if *flagTls {
|
||||
creds, err := credentials.NewClientTLSFromFile(
|
||||
path.Join(getTestingCertsPath(), "localhost.crt"), "localhost")
|
||||
require.NoError(s.T(), err, "failed reading client credentials for localhost.crt")
|
||||
newDialOpts = append(newDialOpts, grpc.WithTransportCredentials(creds))
|
||||
} else {
|
||||
newDialOpts = append(newDialOpts, grpc.WithInsecure())
|
||||
}
|
||||
clientConn, err := grpc.Dial(s.ServerAddr(), newDialOpts...)
|
||||
require.NoError(s.T(), err, "must not error on client Dial")
|
||||
return pb_testproto.NewTestServiceClient(clientConn)
|
||||
}
|
||||
|
||||
func (s *InterceptorTestSuite) ServerAddr() string {
|
||||
return s.ServerListener.Addr().String()
|
||||
}
|
||||
|
||||
func (s *InterceptorTestSuite) SimpleCtx() context.Context {
|
||||
ctx, _ := context.WithTimeout(context.TODO(), 2*time.Second)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (s *InterceptorTestSuite) DeadlineCtx(deadline time.Time) context.Context {
|
||||
ctx, _ := context.WithDeadline(context.TODO(), deadline)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (s *InterceptorTestSuite) TearDownSuite() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
if s.ServerListener != nil {
|
||||
s.Server.GracefulStop()
|
||||
s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr())
|
||||
s.ServerListener.Close()
|
||||
|
||||
}
|
||||
if s.clientConn != nil {
|
||||
s.clientConn.Close()
|
||||
}
|
||||
}
|
||||
31
vendor/github.com/mwitkow/go-grpc-middleware/testing/mutex_readerwriter.go
generated
vendored
Normal file
31
vendor/github.com/mwitkow/go-grpc-middleware/testing/mutex_readerwriter.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package grpc_testing
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// MutexReadWriter is a io.ReadWriter that can be read and worked on from multiple go routines.
|
||||
type MutexReadWriter struct {
|
||||
sync.Mutex
|
||||
rw io.ReadWriter
|
||||
}
|
||||
|
||||
// NewMutexReadWriter creates a new thread-safe io.ReadWriter.
|
||||
func NewMutexReadWriter(rw io.ReadWriter) *MutexReadWriter {
|
||||
return &MutexReadWriter{rw: rw}
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (m *MutexReadWriter) Write(p []byte) (int, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.rw.Write(p)
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface.
|
||||
func (m *MutexReadWriter) Read(p []byte) (int, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.rw.Read(p)
|
||||
}
|
||||
71
vendor/github.com/mwitkow/go-grpc-middleware/testing/pingservice.go
generated
vendored
Normal file
71
vendor/github.com/mwitkow/go-grpc-middleware/testing/pingservice.go
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
Package `grpc_testing` provides helper functions for testing validators in this package.
|
||||
*/
|
||||
|
||||
package grpc_testing
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultPongValue is the default value used.
|
||||
DefaultResponseValue = "default_response_value"
|
||||
// ListResponseCount is the expeted number of responses to PingList
|
||||
ListResponseCount = 100
|
||||
)
|
||||
|
||||
type TestPingService struct {
|
||||
T *testing.T
|
||||
}
|
||||
|
||||
func (s *TestPingService) PingEmpty(ctx context.Context, _ *pb_testproto.Empty) (*pb_testproto.PingResponse, error) {
|
||||
return &pb_testproto.PingResponse{Value: DefaultResponseValue, Counter: 42}, nil
|
||||
}
|
||||
|
||||
func (s *TestPingService) Ping(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.PingResponse, error) {
|
||||
// Send user trailers and headers.
|
||||
return &pb_testproto.PingResponse{Value: ping.Value, Counter: 42}, nil
|
||||
}
|
||||
|
||||
func (s *TestPingService) PingError(ctx context.Context, ping *pb_testproto.PingRequest) (*pb_testproto.Empty, error) {
|
||||
code := codes.Code(ping.ErrorCodeReturned)
|
||||
return nil, grpc.Errorf(code, "Userspace error.")
|
||||
}
|
||||
|
||||
func (s *TestPingService) PingList(ping *pb_testproto.PingRequest, stream pb_testproto.TestService_PingListServer) error {
|
||||
if ping.ErrorCodeReturned != 0 {
|
||||
return grpc.Errorf(codes.Code(ping.ErrorCodeReturned), "foobar")
|
||||
}
|
||||
// Send user trailers and headers.
|
||||
for i := 0; i < ListResponseCount; i++ {
|
||||
stream.Send(&pb_testproto.PingResponse{Value: ping.Value, Counter: int32(i)})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TestPingService) PingStream(stream pb_testproto.TestService_PingStreamServer) error {
|
||||
count := 0
|
||||
for true {
|
||||
ping, err := stream.Recv()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream.Send(&pb_testproto.PingResponse{Value: ping.Value, Counter: int32(count)})
|
||||
count += 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
8
vendor/github.com/mwitkow/go-grpc-middleware/testing/testproto/test.manual_extractfields.pb.go
generated
vendored
Normal file
8
vendor/github.com/mwitkow/go-grpc-middleware/testing/testproto/test.manual_extractfields.pb.go
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Manual code for logging field extraction tests.
|
||||
|
||||
package mwitkow_testproto
|
||||
|
||||
// This is implementing grpc_logging.requestLogFieldsExtractor
|
||||
func (m *PingRequest) ExtractRequestFields(appendToMap map[string]interface{}) {
|
||||
appendToMap["value"] = m.Value
|
||||
}
|
||||
12
vendor/github.com/mwitkow/go-grpc-middleware/testing/testproto/test.manual_validator.pb.go
generated
vendored
Normal file
12
vendor/github.com/mwitkow/go-grpc-middleware/testing/testproto/test.manual_validator.pb.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// Manual code for validation tests.
|
||||
|
||||
package mwitkow_testproto
|
||||
|
||||
import "errors"
|
||||
|
||||
func (p *PingRequest) Validate() error {
|
||||
if p.SleepTimeMs > 10000 {
|
||||
return errors.New("cannot sleep for more than 10s")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
394
vendor/github.com/mwitkow/go-grpc-middleware/testing/testproto/test.pb.go
generated
vendored
Normal file
394
vendor/github.com/mwitkow/go-grpc-middleware/testing/testproto/test.pb.go
generated
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: test.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package mwitkow_testproto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
test.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Empty
|
||||
PingRequest
|
||||
PingResponse
|
||||
*/
|
||||
package mwitkow_testproto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
type Empty struct {
|
||||
}
|
||||
|
||||
func (m *Empty) Reset() { *m = Empty{} }
|
||||
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
||||
func (*Empty) ProtoMessage() {}
|
||||
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
type PingRequest struct {
|
||||
Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
|
||||
SleepTimeMs int32 `protobuf:"varint,2,opt,name=sleep_time_ms,json=sleepTimeMs" json:"sleep_time_ms,omitempty"`
|
||||
ErrorCodeReturned uint32 `protobuf:"varint,3,opt,name=error_code_returned,json=errorCodeReturned" json:"error_code_returned,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PingRequest) Reset() { *m = PingRequest{} }
|
||||
func (m *PingRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PingRequest) ProtoMessage() {}
|
||||
func (*PingRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *PingRequest) GetValue() string {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PingRequest) GetSleepTimeMs() int32 {
|
||||
if m != nil {
|
||||
return m.SleepTimeMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *PingRequest) GetErrorCodeReturned() uint32 {
|
||||
if m != nil {
|
||||
return m.ErrorCodeReturned
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type PingResponse struct {
|
||||
Value string `protobuf:"bytes,1,opt,name=Value,json=value" json:"Value,omitempty"`
|
||||
Counter int32 `protobuf:"varint,2,opt,name=counter" json:"counter,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PingResponse) Reset() { *m = PingResponse{} }
|
||||
func (m *PingResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*PingResponse) ProtoMessage() {}
|
||||
func (*PingResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *PingResponse) GetValue() string {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PingResponse) GetCounter() int32 {
|
||||
if m != nil {
|
||||
return m.Counter
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Empty)(nil), "mwitkow.testproto.Empty")
|
||||
proto.RegisterType((*PingRequest)(nil), "mwitkow.testproto.PingRequest")
|
||||
proto.RegisterType((*PingResponse)(nil), "mwitkow.testproto.PingResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for TestService service
|
||||
|
||||
type TestServiceClient interface {
|
||||
PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error)
|
||||
Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error)
|
||||
PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error)
|
||||
PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error)
|
||||
PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error)
|
||||
}
|
||||
|
||||
type testServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient {
|
||||
return &testServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *testServiceClient) PingEmpty(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*PingResponse, error) {
|
||||
out := new(PingResponse)
|
||||
err := grpc.Invoke(ctx, "/mwitkow.testproto.TestService/PingEmpty", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) {
|
||||
out := new(PingResponse)
|
||||
err := grpc.Invoke(ctx, "/mwitkow.testproto.TestService/Ping", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) PingError(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*Empty, error) {
|
||||
out := new(Empty)
|
||||
err := grpc.Invoke(ctx, "/mwitkow.testproto.TestService/PingError", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) PingList(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (TestService_PingListClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[0], c.cc, "/mwitkow.testproto.TestService/PingList", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServicePingListClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_PingListClient interface {
|
||||
Recv() (*PingResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServicePingListClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServicePingListClient) Recv() (*PingResponse, error) {
|
||||
m := new(PingResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *testServiceClient) PingStream(ctx context.Context, opts ...grpc.CallOption) (TestService_PingStreamClient, error) {
|
||||
stream, err := grpc.NewClientStream(ctx, &_TestService_serviceDesc.Streams[1], c.cc, "/mwitkow.testproto.TestService/PingStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &testServicePingStreamClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type TestService_PingStreamClient interface {
|
||||
Send(*PingRequest) error
|
||||
Recv() (*PingResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type testServicePingStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *testServicePingStreamClient) Send(m *PingRequest) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServicePingStreamClient) Recv() (*PingResponse, error) {
|
||||
m := new(PingResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Server API for TestService service
|
||||
|
||||
type TestServiceServer interface {
|
||||
PingEmpty(context.Context, *Empty) (*PingResponse, error)
|
||||
Ping(context.Context, *PingRequest) (*PingResponse, error)
|
||||
PingError(context.Context, *PingRequest) (*Empty, error)
|
||||
PingList(*PingRequest, TestService_PingListServer) error
|
||||
PingStream(TestService_PingStreamServer) error
|
||||
}
|
||||
|
||||
func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
|
||||
s.RegisterService(&_TestService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _TestService_PingEmpty_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).PingEmpty(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/mwitkow.testproto.TestService/PingEmpty",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).PingEmpty(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(PingRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).Ping(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/mwitkow.testproto.TestService/Ping",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).Ping(ctx, req.(*PingRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_PingError_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(PingRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TestServiceServer).PingError(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/mwitkow.testproto.TestService/PingError",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TestServiceServer).PingError(ctx, req.(*PingRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TestService_PingList_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(PingRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(TestServiceServer).PingList(m, &testServicePingListServer{stream})
|
||||
}
|
||||
|
||||
type TestService_PingListServer interface {
|
||||
Send(*PingResponse) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServicePingListServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServicePingListServer) Send(m *PingResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _TestService_PingStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(TestServiceServer).PingStream(&testServicePingStreamServer{stream})
|
||||
}
|
||||
|
||||
type TestService_PingStreamServer interface {
|
||||
Send(*PingResponse) error
|
||||
Recv() (*PingRequest, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type testServicePingStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *testServicePingStreamServer) Send(m *PingResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *testServicePingStreamServer) Recv() (*PingRequest, error) {
|
||||
m := new(PingRequest)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _TestService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "mwitkow.testproto.TestService",
|
||||
HandlerType: (*TestServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "PingEmpty",
|
||||
Handler: _TestService_PingEmpty_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Ping",
|
||||
Handler: _TestService_Ping_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PingError",
|
||||
Handler: _TestService_PingError_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "PingList",
|
||||
Handler: _TestService_PingList_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "PingStream",
|
||||
Handler: _TestService_PingStream_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "test.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("test.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 288 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x90, 0x4f, 0x4b, 0xfb, 0x30,
|
||||
0x18, 0xc7, 0x97, 0xdf, 0x7e, 0x75, 0xee, 0xa9, 0x3b, 0x2c, 0x7a, 0x28, 0x1e, 0xb4, 0xe4, 0xd4,
|
||||
0x53, 0x19, 0x7a, 0xf7, 0x22, 0xa2, 0x82, 0xa2, 0xb4, 0xc3, 0x6b, 0x99, 0xed, 0x83, 0x04, 0x97,
|
||||
0xa6, 0x26, 0x4f, 0x57, 0x7c, 0x19, 0xbe, 0x63, 0x49, 0x56, 0x41, 0x98, 0x43, 0x0f, 0x3b, 0xe6,
|
||||
0xfb, 0x79, 0xf8, 0xfe, 0x09, 0x00, 0xa1, 0xa5, 0xb4, 0x31, 0x9a, 0x34, 0x9f, 0xaa, 0x4e, 0xd2,
|
||||
0xab, 0xee, 0x52, 0xa7, 0x79, 0x49, 0x8c, 0x20, 0xb8, 0x52, 0x0d, 0xbd, 0x8b, 0x0e, 0xc2, 0x47,
|
||||
0x59, 0xbf, 0x64, 0xf8, 0xd6, 0xa2, 0x25, 0x7e, 0x04, 0xc1, 0x6a, 0xb1, 0x6c, 0x31, 0x62, 0x31,
|
||||
0x4b, 0xc6, 0xd9, 0xfa, 0xc1, 0x05, 0x4c, 0xec, 0x12, 0xb1, 0x29, 0x48, 0x2a, 0x2c, 0x94, 0x8d,
|
||||
0xfe, 0xc5, 0x2c, 0x09, 0xb2, 0xd0, 0x8b, 0x73, 0xa9, 0xf0, 0xde, 0xf2, 0x14, 0x0e, 0xd1, 0x18,
|
||||
0x6d, 0x8a, 0x52, 0x57, 0x58, 0x18, 0xa4, 0xd6, 0xd4, 0x58, 0x45, 0xc3, 0x98, 0x25, 0x93, 0x6c,
|
||||
0xea, 0xd1, 0xa5, 0xae, 0x30, 0xeb, 0x81, 0xb8, 0x80, 0x83, 0x75, 0xb0, 0x6d, 0x74, 0x6d, 0xd1,
|
||||
0x25, 0x3f, 0x6d, 0x26, 0x47, 0x30, 0x2a, 0x75, 0x5b, 0x13, 0x9a, 0x3e, 0xf3, 0xeb, 0x79, 0xf6,
|
||||
0x31, 0x84, 0x70, 0x8e, 0x96, 0x72, 0x34, 0x2b, 0x59, 0x22, 0xbf, 0x81, 0xb1, 0xf3, 0xf3, 0xab,
|
||||
0x78, 0x94, 0x6e, 0x4c, 0x4e, 0x3d, 0x39, 0x3e, 0xfd, 0x81, 0x7c, 0xef, 0x21, 0x06, 0xfc, 0x16,
|
||||
0xfe, 0x3b, 0x85, 0x9f, 0x6c, 0x3d, 0xf5, 0x7f, 0xf5, 0x17, 0xab, 0xeb, 0xbe, 0x94, 0x5b, 0xff,
|
||||
0xab, 0xdf, 0xd6, 0xd2, 0x62, 0xc0, 0x1f, 0x60, 0xdf, 0x9d, 0xde, 0x49, 0x4b, 0x3b, 0xe8, 0x35,
|
||||
0x63, 0x3c, 0x07, 0x70, 0x5a, 0x4e, 0x06, 0x17, 0x6a, 0x07, 0x96, 0x09, 0x9b, 0xb1, 0xe7, 0x3d,
|
||||
0x4f, 0xce, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x2a, 0x8a, 0x7b, 0x7d, 0x02, 0x00, 0x00,
|
||||
}
|
||||
142
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/client_interceptors.go
generated
vendored
Normal file
142
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/client_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_opentracing
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"github.com/opentracing/opentracing-go/log"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
// UnaryClientInterceptor returns a new unary client interceptor for OpenTracing.
|
||||
func UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor {
|
||||
o := evaluateOptions(opts)
|
||||
return func(parentCtx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
if o.filterOutFunc != nil && !o.filterOutFunc(parentCtx, method) {
|
||||
return invoker(parentCtx, method, req, reply, cc, opts...)
|
||||
}
|
||||
newCtx, clientSpan := newClientSpanFromContext(parentCtx, o.tracer, method)
|
||||
err := invoker(newCtx, method, req, reply, cc, opts...)
|
||||
finishClientSpan(clientSpan, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// StreamClientInterceptor returns a new streaming client interceptor for OpenTracing.
|
||||
func StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor {
|
||||
o := evaluateOptions(opts)
|
||||
return func(parentCtx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
if o.filterOutFunc != nil && !o.filterOutFunc(parentCtx, method) {
|
||||
return streamer(parentCtx, desc, cc, method, opts...)
|
||||
}
|
||||
newCtx, clientSpan := newClientSpanFromContext(parentCtx, o.tracer, method)
|
||||
clientStream, err := streamer(newCtx, desc, cc, method, opts...)
|
||||
if err != nil {
|
||||
finishClientSpan(clientSpan, err)
|
||||
return nil, err
|
||||
}
|
||||
return &tracedClientStream{ClientStream: clientStream, clientSpan: clientSpan}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// type serverStreamingRetryingStream is the implementation of grpc.ClientStream that acts as a
|
||||
// proxy to the underlying call. If any of the RecvMsg() calls fail, it will try to reestablish
|
||||
// a new ClientStream according to the retry policy.
|
||||
type tracedClientStream struct {
|
||||
grpc.ClientStream
|
||||
mu sync.Mutex
|
||||
alreadyFinished bool
|
||||
clientSpan opentracing.Span
|
||||
}
|
||||
|
||||
func (s *tracedClientStream) Header() (metadata.MD, error) {
|
||||
h, err := s.ClientStream.Header()
|
||||
if err != nil {
|
||||
s.finishClientSpan(err)
|
||||
}
|
||||
return h, err
|
||||
}
|
||||
|
||||
func (s *tracedClientStream) SendMsg(m interface{}) error {
|
||||
err := s.ClientStream.SendMsg(m)
|
||||
if err != nil {
|
||||
s.finishClientSpan(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *tracedClientStream) CloseSend() error {
|
||||
err := s.ClientStream.CloseSend()
|
||||
if err != nil {
|
||||
s.finishClientSpan(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *tracedClientStream) RecvMsg(m interface{}) error {
|
||||
err := s.ClientStream.RecvMsg(m)
|
||||
if err != nil {
|
||||
s.finishClientSpan(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *tracedClientStream) finishClientSpan(err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if !s.alreadyFinished {
|
||||
finishClientSpan(s.clientSpan, err)
|
||||
s.alreadyFinished = true
|
||||
}
|
||||
}
|
||||
|
||||
// ClientAddContextTags returns a context with specified opentracing tags, which
|
||||
// are used by UnaryClientInterceptor/StreamClientInterceptor when creating a
|
||||
// new span.
|
||||
func ClientAddContextTags(ctx context.Context, tags opentracing.Tags) context.Context {
|
||||
return context.WithValue(ctx, clientSpanTagKey{}, tags)
|
||||
}
|
||||
|
||||
type clientSpanTagKey struct{}
|
||||
|
||||
func newClientSpanFromContext(ctx context.Context, tracer opentracing.Tracer, fullMethodName string) (context.Context, opentracing.Span) {
|
||||
var parentSpanCtx opentracing.SpanContext
|
||||
if parent := opentracing.SpanFromContext(ctx); parent != nil {
|
||||
parentSpanCtx = parent.Context()
|
||||
}
|
||||
opts := []opentracing.StartSpanOption{
|
||||
opentracing.ChildOf(parentSpanCtx),
|
||||
ext.SpanKindRPCClient,
|
||||
grpcTag,
|
||||
}
|
||||
if tagx := ctx.Value(clientSpanTagKey{}); tagx != nil {
|
||||
if opt, ok := tagx.(opentracing.StartSpanOption); ok {
|
||||
opts = append(opts, opt)
|
||||
}
|
||||
}
|
||||
clientSpan := tracer.StartSpan(fullMethodName, opts...)
|
||||
// Make sure we add this to the metadata of the call, so it gets propagated:
|
||||
md := metautils.ExtractOutgoing(ctx).Clone()
|
||||
if err := tracer.Inject(clientSpan.Context(), opentracing.HTTPHeaders, metadataTextMap(md)); err != nil {
|
||||
grpclog.Printf("grpc_opentracing: failed serializing trace information: %v", err)
|
||||
}
|
||||
ctxWithMetadata := md.ToOutgoing(ctx)
|
||||
return opentracing.ContextWithSpan(ctxWithMetadata, clientSpan), clientSpan
|
||||
}
|
||||
|
||||
func finishClientSpan(clientSpan opentracing.Span, err error) {
|
||||
if err != nil && err != io.EOF {
|
||||
ext.Error.Set(clientSpan, true)
|
||||
clientSpan.LogFields(log.String("event", "error"), log.String("message", err.Error()))
|
||||
}
|
||||
clientSpan.Finish()
|
||||
}
|
||||
22
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/doc.go
generated
vendored
Normal file
22
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/doc.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`grpc_opentracing` adds OpenTracing
|
||||
|
||||
OpenTracing Interceptors
|
||||
|
||||
These are both client-side and server-side interceptors for OpenTracing. They are a provider-agnostic, with backends
|
||||
such as Zipkin, or Google Stackdriver Trace.
|
||||
|
||||
For a service that sends out requests and receives requests, you *need* to use both, otherwise downstream requests will
|
||||
not have the appropriate requests propagated.
|
||||
|
||||
All server-side spans are tagged with grpc_ctxtags information.
|
||||
|
||||
For more information see:
|
||||
http://opentracing.io/documentation/
|
||||
https://github.com/opentracing/specification/blob/master/semantic_conventions.md
|
||||
|
||||
*/
|
||||
package grpc_opentracing
|
||||
50
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/id_extract.go
generated
vendored
Normal file
50
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/id_extract.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_opentracing
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
const (
|
||||
TagTraceId = "trace.traceid"
|
||||
TagSpanId = "trace.spanid"
|
||||
)
|
||||
|
||||
// hackyInjectOpentracingIdsToTags writes the given context to the ctxtags.
|
||||
// This is done in an incredibly hacky way, because the public-facing interface of opentracing doesn't give access to
|
||||
// the TraceId and SpanId of the SpanContext. Only the Tracer's Inject/Extract methods know what these are.
|
||||
// Most tracers have them encoded as keys with 'traceid' and 'spanid':
|
||||
// https://github.com/openzipkin/zipkin-go-opentracing/blob/594640b9ef7e5c994e8d9499359d693c032d738c/propagation_ot.go#L29
|
||||
// https://github.com/opentracing/basictracer-go/blob/1b32af207119a14b1b231d451df3ed04a72efebf/propagation_ot.go#L26
|
||||
// Jaeger from Uber use one-key schema with next format '{trace-id}:{span-id}:{parent-span-id}:{flags}'
|
||||
// https://www.jaegertracing.io/docs/client-libraries/#trace-span-identity
|
||||
func hackyInjectOpentracingIdsToTags(span opentracing.Span, tags grpc_ctxtags.Tags) {
|
||||
if err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, &hackyTagsCarrier{tags}); err != nil {
|
||||
grpclog.Printf("grpc_opentracing: failed extracting trace info into ctx %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// hackyTagsCarrier is a really hacky way of
|
||||
type hackyTagsCarrier struct {
|
||||
grpc_ctxtags.Tags
|
||||
}
|
||||
|
||||
func (t *hackyTagsCarrier) Set(key, val string) {
|
||||
if strings.Contains(key, "traceid") || strings.Contains(strings.ToLower(key), "traceid") {
|
||||
t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded
|
||||
} else if (strings.Contains(key, "spanid") && !strings.Contains(key, "parent")) || (strings.Contains(strings.ToLower(key), "spanid") && !strings.Contains(strings.ToLower(key), "parent")) {
|
||||
t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded
|
||||
} else if key == "uber-trace-id" {
|
||||
parts := strings.Split(val, ":")
|
||||
if len(parts) >= 2 {
|
||||
t.Tags.Set(TagTraceId, parts[0])
|
||||
t.Tags.Set(TagSpanId, parts[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
56
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/metadata.go
generated
vendored
Normal file
56
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/metadata.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_opentracing
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
binHdrSuffix = "-bin"
|
||||
)
|
||||
|
||||
// metadataTextMap extends a metadata.MD to be an opentracing textmap
|
||||
type metadataTextMap metadata.MD
|
||||
|
||||
// Set is a opentracing.TextMapReader interface that extracts values.
|
||||
func (m metadataTextMap) Set(key, val string) {
|
||||
// gRPC allows for complex binary values to be written.
|
||||
encodedKey, encodedVal := encodeKeyValue(key, val)
|
||||
// The metadata object is a multimap, and previous values may exist, but for opentracing headers, we do not append
|
||||
// we just override.
|
||||
m[encodedKey] = []string{encodedVal}
|
||||
}
|
||||
|
||||
// ForeachKey is a opentracing.TextMapReader interface that extracts values.
|
||||
func (m metadataTextMap) ForeachKey(callback func(key, val string) error) error {
|
||||
for k, vv := range m {
|
||||
for _, v := range vv {
|
||||
if decodedKey, decodedVal, err := metadata.DecodeKeyValue(k, v); err == nil {
|
||||
if err = callback(decodedKey, decodedVal); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("failed decoding opentracing from gRPC metadata: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// encodeKeyValue encodes key and value qualified for transmission via gRPC.
|
||||
// note: copy pasted from private values of grpc.metadata
|
||||
func encodeKeyValue(k, v string) (string, string) {
|
||||
k = strings.ToLower(k)
|
||||
if strings.HasSuffix(k, binHdrSuffix) {
|
||||
val := base64.StdEncoding.EncodeToString([]byte(v))
|
||||
v = string(val)
|
||||
}
|
||||
return k, v
|
||||
}
|
||||
55
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/options.go
generated
vendored
Normal file
55
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/options.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_opentracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultOptions = &options{
|
||||
filterOutFunc: nil,
|
||||
tracer: nil,
|
||||
}
|
||||
)
|
||||
|
||||
// FilterFunc allows users to provide a function that filters out certain methods from being traced.
|
||||
//
|
||||
// If it returns false, the given request will not be traced.
|
||||
type FilterFunc func(ctx context.Context, fullMethodName string) bool
|
||||
|
||||
type options struct {
|
||||
filterOutFunc FilterFunc
|
||||
tracer opentracing.Tracer
|
||||
}
|
||||
|
||||
func evaluateOptions(opts []Option) *options {
|
||||
optCopy := &options{}
|
||||
*optCopy = *defaultOptions
|
||||
for _, o := range opts {
|
||||
o(optCopy)
|
||||
}
|
||||
if optCopy.tracer == nil {
|
||||
optCopy.tracer = opentracing.GlobalTracer()
|
||||
}
|
||||
return optCopy
|
||||
}
|
||||
|
||||
type Option func(*options)
|
||||
|
||||
// WithFilterFunc customizes the function used for deciding whether a given call is traced or not.
|
||||
func WithFilterFunc(f FilterFunc) Option {
|
||||
return func(o *options) {
|
||||
o.filterOutFunc = f
|
||||
}
|
||||
}
|
||||
|
||||
// WithTracer sets a custom tracer to be used for this middleware, otherwise the opentracing.GlobalTracer is used.
|
||||
func WithTracer(tracer opentracing.Tracer) Option {
|
||||
return func(o *options) {
|
||||
o.tracer = tracer
|
||||
}
|
||||
}
|
||||
86
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/server_interceptors.go
generated
vendored
Normal file
86
vendor/github.com/mwitkow/go-grpc-middleware/tracing/opentracing/server_interceptors.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright 2017 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_opentracing
|
||||
|
||||
import (
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"github.com/opentracing/opentracing-go/log"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
var (
|
||||
grpcTag = opentracing.Tag{Key: string(ext.Component), Value: "gRPC"}
|
||||
)
|
||||
|
||||
// UnaryServerInterceptor returns a new unary server interceptor for OpenTracing.
|
||||
func UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor {
|
||||
o := evaluateOptions(opts)
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if o.filterOutFunc != nil && !o.filterOutFunc(ctx, info.FullMethod) {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
newCtx, serverSpan := newServerSpanFromInbound(ctx, o.tracer, info.FullMethod)
|
||||
resp, err := handler(newCtx, req)
|
||||
finishServerSpan(ctx, serverSpan, err)
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
// StreamServerInterceptor returns a new streaming server interceptor for OpenTracing.
|
||||
func StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor {
|
||||
o := evaluateOptions(opts)
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
if o.filterOutFunc != nil && !o.filterOutFunc(stream.Context(), info.FullMethod) {
|
||||
return handler(srv, stream)
|
||||
}
|
||||
newCtx, serverSpan := newServerSpanFromInbound(stream.Context(), o.tracer, info.FullMethod)
|
||||
wrappedStream := grpc_middleware.WrapServerStream(stream)
|
||||
wrappedStream.WrappedContext = newCtx
|
||||
err := handler(srv, wrappedStream)
|
||||
finishServerSpan(newCtx, serverSpan, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func newServerSpanFromInbound(ctx context.Context, tracer opentracing.Tracer, fullMethodName string) (context.Context, opentracing.Span) {
|
||||
md := metautils.ExtractIncoming(ctx)
|
||||
parentSpanContext, err := tracer.Extract(opentracing.HTTPHeaders, metadataTextMap(md))
|
||||
if err != nil && err != opentracing.ErrSpanContextNotFound {
|
||||
grpclog.Printf("grpc_opentracing: failed parsing trace information: %v", err)
|
||||
}
|
||||
|
||||
serverSpan := tracer.StartSpan(
|
||||
fullMethodName,
|
||||
// this is magical, it attaches the new span to the parent parentSpanContext, and creates an unparented one if empty.
|
||||
ext.RPCServerOption(parentSpanContext),
|
||||
grpcTag,
|
||||
)
|
||||
hackyInjectOpentracingIdsToTags(serverSpan, grpc_ctxtags.Extract(ctx))
|
||||
return opentracing.ContextWithSpan(ctx, serverSpan), serverSpan
|
||||
}
|
||||
|
||||
func finishServerSpan(ctx context.Context, serverSpan opentracing.Span, err error) {
|
||||
// Log context information
|
||||
tags := grpc_ctxtags.Extract(ctx)
|
||||
for k, v := range tags.Values() {
|
||||
// Don't tag errors, log them instead.
|
||||
if vErr, ok := v.(error); ok {
|
||||
serverSpan.LogKV(k, vErr.Error())
|
||||
|
||||
} else {
|
||||
serverSpan.SetTag(k, v)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
ext.Error.Set(serverSpan, true)
|
||||
serverSpan.LogFields(log.String("event", "error"), log.String("message", err.Error()))
|
||||
}
|
||||
serverSpan.Finish()
|
||||
}
|
||||
23
vendor/github.com/mwitkow/go-grpc-middleware/util/backoffutils/backoff.go
generated
vendored
Normal file
23
vendor/github.com/mwitkow/go-grpc-middleware/util/backoffutils/backoff.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
Backoff Helper Utilities
|
||||
|
||||
Implements common backoff features.
|
||||
*/
|
||||
package backoffutils
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// JitterUp adds random jitter to the duration.
|
||||
//
|
||||
// This adds or substracts time from the duration within a given jitter fraction.
|
||||
// For example for 10s and jitter 0.1, it will returna time within [9s, 11s])
|
||||
func JitterUp(duration time.Duration, jitter float64) time.Duration {
|
||||
multiplier := jitter * (rand.Float64()*2 - 1)
|
||||
return time.Duration(float64(duration) * (1 + multiplier))
|
||||
}
|
||||
19
vendor/github.com/mwitkow/go-grpc-middleware/util/metautils/doc.go
generated
vendored
Normal file
19
vendor/github.com/mwitkow/go-grpc-middleware/util/metautils/doc.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
Package `metautils` provides convenience functions for dealing with gRPC metadata.MD objects inside
|
||||
Context handlers.
|
||||
|
||||
While the upstream grpc-go package contains decent functionality (see https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md)
|
||||
they are hard to use.
|
||||
|
||||
The majority of functions center around the NiceMD, which is a convenience wrapper around metadata.MD. For example
|
||||
the following code allows you to easily extract incoming metadata (server handler) and put it into a new client context
|
||||
metadata.
|
||||
|
||||
nmd := metautils.ExtractIncoming(serverCtx).Clone(":authorization", ":custom")
|
||||
clientCtx := nmd.Set("x-client-header", "2").Set("x-another", "3").ToOutgoing(ctx)
|
||||
*/
|
||||
|
||||
package metautils
|
||||
126
vendor/github.com/mwitkow/go-grpc-middleware/util/metautils/nicemd.go
generated
vendored
Normal file
126
vendor/github.com/mwitkow/go-grpc-middleware/util/metautils/nicemd.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package metautils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
// NiceMD is a convenience wrapper definiting extra functions on the metadata.
|
||||
type NiceMD metadata.MD
|
||||
|
||||
// ExtractIncoming extracts an inbound metadata from the server-side context.
|
||||
//
|
||||
// This function always returns a NiceMD wrapper of the metadata.MD, in case the context doesn't have metadata it returns
|
||||
// a new empty NiceMD.
|
||||
func ExtractIncoming(ctx context.Context) NiceMD {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return NiceMD(metadata.Pairs())
|
||||
}
|
||||
return NiceMD(md)
|
||||
}
|
||||
|
||||
// ExtractOutgoing extracts an outbound metadata from the client-side context.
|
||||
//
|
||||
// This function always returns a NiceMD wrapper of the metadata.MD, in case the context doesn't have metadata it returns
|
||||
// a new empty NiceMD.
|
||||
func ExtractOutgoing(ctx context.Context) NiceMD {
|
||||
md, ok := metadata.FromOutgoingContext(ctx)
|
||||
if !ok {
|
||||
return NiceMD(metadata.Pairs())
|
||||
}
|
||||
return NiceMD(md)
|
||||
}
|
||||
|
||||
// Clone performs a *deep* copy of the metadata.MD.
|
||||
//
|
||||
// You can specify the lower-case copiedKeys to only copy certain whitelisted keys. If no keys are explicitly whitelisted
|
||||
// all keys get copied.
|
||||
func (m NiceMD) Clone(copiedKeys ...string) NiceMD {
|
||||
newMd := NiceMD(metadata.Pairs())
|
||||
for k, vv := range m {
|
||||
found := false
|
||||
if len(copiedKeys) == 0 {
|
||||
found = true
|
||||
} else {
|
||||
for _, allowedKey := range copiedKeys {
|
||||
if strings.ToLower(allowedKey) == strings.ToLower(k) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
newMd[k] = make([]string, len(vv))
|
||||
copy(newMd[k], vv)
|
||||
}
|
||||
return NiceMD(newMd)
|
||||
}
|
||||
|
||||
// ToOutgoing sets the given NiceMD as a client-side context for dispatching.
|
||||
func (m NiceMD) ToOutgoing(ctx context.Context) context.Context {
|
||||
return metadata.NewOutgoingContext(ctx, metadata.MD(m))
|
||||
}
|
||||
|
||||
// ToIncoming sets the given NiceMD as a server-side context for dispatching.
|
||||
//
|
||||
// This is mostly useful in ServerInterceptors..
|
||||
func (m NiceMD) ToIncoming(ctx context.Context) context.Context {
|
||||
return metadata.NewIncomingContext(ctx, metadata.MD(m))
|
||||
}
|
||||
|
||||
// Get retrieves a single value from the metadata.
|
||||
//
|
||||
// It works analogously to http.Header.Get, returning the first value if there are many set. If the value is not set,
|
||||
// an empty string is returned.
|
||||
//
|
||||
// The function is binary-key safe.
|
||||
func (m NiceMD) Get(key string) string {
|
||||
k, _ := encodeKeyValue(key, "")
|
||||
vv, ok := m[k]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return vv[0]
|
||||
}
|
||||
|
||||
// Del retrieves a single value from the metadata.
|
||||
//
|
||||
// It works analogously to http.Header.Del, deleting all values if they exist.
|
||||
//
|
||||
// The function is binary-key safe.
|
||||
|
||||
func (m NiceMD) Del(key string) NiceMD {
|
||||
k, _ := encodeKeyValue(key, "")
|
||||
delete(m, k)
|
||||
return m
|
||||
}
|
||||
|
||||
// Set sets the given value in a metadata.
|
||||
//
|
||||
// It works analogously to http.Header.Set, overwriting all previous metadata values.
|
||||
//
|
||||
// The function is binary-key safe.
|
||||
func (m NiceMD) Set(key string, value string) NiceMD {
|
||||
k, v := encodeKeyValue(key, value)
|
||||
m[k] = []string{v}
|
||||
return m
|
||||
}
|
||||
|
||||
// Add retrieves a single value from the metadata.
|
||||
//
|
||||
// It works analogously to http.Header.Add, as it appends to any existing values associated with key.
|
||||
//
|
||||
// The function is binary-key safe.
|
||||
func (m NiceMD) Add(key string, value string) NiceMD {
|
||||
k, v := encodeKeyValue(key, value)
|
||||
m[k] = append(m[k], v)
|
||||
return m
|
||||
}
|
||||
22
vendor/github.com/mwitkow/go-grpc-middleware/util/metautils/single_key.go
generated
vendored
Normal file
22
vendor/github.com/mwitkow/go-grpc-middleware/util/metautils/single_key.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package metautils
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
binHdrSuffix = "-bin"
|
||||
)
|
||||
|
||||
func encodeKeyValue(k, v string) (string, string) {
|
||||
k = strings.ToLower(k)
|
||||
if strings.HasSuffix(k, binHdrSuffix) {
|
||||
val := base64.StdEncoding.EncodeToString([]byte(v))
|
||||
v = string(val)
|
||||
}
|
||||
return k, v
|
||||
}
|
||||
45
vendor/github.com/mwitkow/go-grpc-middleware/validator/doc.go
generated
vendored
Normal file
45
vendor/github.com/mwitkow/go-grpc-middleware/validator/doc.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
/*
|
||||
`grpc_validator` is a generic request contents validator server-side middleware for gRPC.
|
||||
|
||||
Request Validator Middleware
|
||||
|
||||
Validating input is important, and hard. It also causes a lot of boilerplate code. This middleware
|
||||
checks for the existence of a `Validate` method on each of the messages of a gRPC request. This
|
||||
includes the single request of the `Unary` calls, as well as each message of the inbound Stream calls.
|
||||
In case of a validation failure, an `InvalidArgument` gRPC status is returned, along with a
|
||||
description of the validation failure.
|
||||
|
||||
While it is generic, it was intended to be used with https://github.com/mwitkow/go-proto-validators,
|
||||
a Go protocol buffers codegen plugin that creates the `Validate` methods (including nested messages)
|
||||
based on declarative options in the `.proto` files themselves. For example:
|
||||
|
||||
|
||||
syntax = "proto3";
|
||||
package validator.examples;
|
||||
import "github.com/mwitkow/go-proto-validators/validator.proto";
|
||||
|
||||
message InnerMessage {
|
||||
// some_integer can only be in range (1, 100).
|
||||
int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];
|
||||
// some_float can only be in range (0;1).
|
||||
double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];
|
||||
}
|
||||
|
||||
message OuterMessage {
|
||||
// important_string must be a lowercase alpha-numeric of 5 to 30 characters (RE2 syntax).
|
||||
string important_string = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}];
|
||||
// proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage.
|
||||
InnerMessage inner = 2 [(validator.field) = {msg_exists : true}];
|
||||
}
|
||||
|
||||
The `OuterMessage.Validate` would include validation of regexes, existence of the InnerMessage and
|
||||
the range values within it. The `grpc_validator` middleware would then automatically use that to
|
||||
check all messages processed by the server.
|
||||
|
||||
Please consult https://github.com/mwitkow/go-proto-validators for details on `protoc` invocation and
|
||||
other parameters of customization.
|
||||
*/
|
||||
package grpc_validator
|
||||
57
vendor/github.com/mwitkow/go-grpc-middleware/validator/validator.go
generated
vendored
Normal file
57
vendor/github.com/mwitkow/go-grpc-middleware/validator/validator.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_validator
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
type validator interface {
|
||||
Validate() error
|
||||
}
|
||||
|
||||
// UnaryServerInterceptor returns a new unary server interceptor that validates incoming messages.
|
||||
//
|
||||
// Invalid messages will be rejected with `InvalidArgument` before reaching any userspace handlers.
|
||||
func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if v, ok := req.(validator); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return nil, grpc.Errorf(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
}
|
||||
return handler(ctx, req)
|
||||
}
|
||||
}
|
||||
|
||||
// StreamServerInterceptor returns a new streaming server interceptor that validates incoming messages.
|
||||
//
|
||||
// The stage at which invalid messages will be rejected with `InvalidArgument` varies based on the
|
||||
// type of the RPC. For `ServerStream` (1:m) requests, it will happen before reaching any userspace
|
||||
// handlers. For `ClientStream` (n:1) or `BidiStream` (n:m) RPCs, the messages will be rejected on
|
||||
// calls to `stream.Recv()`.
|
||||
func StreamServerInterceptor() grpc.StreamServerInterceptor {
|
||||
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
wrapper := &recvWrapper{stream}
|
||||
return handler(srv, wrapper)
|
||||
}
|
||||
}
|
||||
|
||||
type recvWrapper struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (s *recvWrapper) RecvMsg(m interface{}) error {
|
||||
if err := s.ServerStream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
if v, ok := m.(validator); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return grpc.Errorf(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
29
vendor/github.com/mwitkow/go-grpc-middleware/wrappers.go
generated
vendored
Normal file
29
vendor/github.com/mwitkow/go-grpc-middleware/wrappers.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
|
||||
package grpc_middleware
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
|
||||
type WrappedServerStream struct {
|
||||
grpc.ServerStream
|
||||
// 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 *WrappedServerStream) Context() context.Context {
|
||||
return w.WrappedContext
|
||||
}
|
||||
|
||||
// WrapServerStream returns a ServerStream that has the ability to overwrite context.
|
||||
func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream {
|
||||
if existing, ok := stream.(*WrappedServerStream); ok {
|
||||
return existing
|
||||
}
|
||||
return &WrappedServerStream{ServerStream: stream, WrappedContext: stream.Context()}
|
||||
}
|
||||
Reference in New Issue
Block a user