aboutsummaryrefslogtreecommitdiff
path: root/vendor/go.opencensus.io/plugin/ocgrpc
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.opencensus.io/plugin/ocgrpc')
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/client.go56
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/client_metrics.go116
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go49
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/doc.go19
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/server.go80
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/server_metrics.go97
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go63
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/stats_common.go205
-rw-r--r--vendor/go.opencensus.io/plugin/ocgrpc/trace_common.go107
9 files changed, 792 insertions, 0 deletions
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/client.go b/vendor/go.opencensus.io/plugin/ocgrpc/client.go
new file mode 100644
index 0000000..a6c466a
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/client.go
@@ -0,0 +1,56 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ocgrpc
+
+import (
+ "go.opencensus.io/trace"
+ "golang.org/x/net/context"
+
+ "google.golang.org/grpc/stats"
+)
+
+// ClientHandler implements a gRPC stats.Handler for recording OpenCensus stats and
+// traces. Use with gRPC clients only.
+type ClientHandler struct {
+ // StartOptions allows configuring the StartOptions used to create new spans.
+ //
+ // StartOptions.SpanKind will always be set to trace.SpanKindClient
+ // for spans started by this handler.
+ StartOptions trace.StartOptions
+}
+
+// HandleConn exists to satisfy gRPC stats.Handler.
+func (c *ClientHandler) HandleConn(ctx context.Context, cs stats.ConnStats) {
+ // no-op
+}
+
+// TagConn exists to satisfy gRPC stats.Handler.
+func (c *ClientHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
+ // no-op
+ return ctx
+}
+
+// HandleRPC implements per-RPC tracing and stats instrumentation.
+func (c *ClientHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
+ traceHandleRPC(ctx, rs)
+ statsHandleRPC(ctx, rs)
+}
+
+// TagRPC implements per-RPC context management.
+func (c *ClientHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
+ ctx = c.traceTagRPC(ctx, rti)
+ ctx = c.statsTagRPC(ctx, rti)
+ return ctx
+}
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/client_metrics.go b/vendor/go.opencensus.io/plugin/ocgrpc/client_metrics.go
new file mode 100644
index 0000000..b8efacf
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/client_metrics.go
@@ -0,0 +1,116 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package ocgrpc
+
+import (
+ "go.opencensus.io/stats"
+ "go.opencensus.io/stats/view"
+ "go.opencensus.io/tag"
+)
+
+// The following variables are measures are recorded by ClientHandler:
+var (
+ ClientSentMessagesPerRPC = stats.Int64("grpc.io/client/sent_messages_per_rpc", "Number of messages sent in the RPC (always 1 for non-streaming RPCs).", stats.UnitDimensionless)
+ ClientSentBytesPerRPC = stats.Int64("grpc.io/client/sent_bytes_per_rpc", "Total bytes sent across all request messages per RPC.", stats.UnitBytes)
+ ClientReceivedMessagesPerRPC = stats.Int64("grpc.io/client/received_messages_per_rpc", "Number of response messages received per RPC (always 1 for non-streaming RPCs).", stats.UnitDimensionless)
+ ClientReceivedBytesPerRPC = stats.Int64("grpc.io/client/received_bytes_per_rpc", "Total bytes received across all response messages per RPC.", stats.UnitBytes)
+ ClientRoundtripLatency = stats.Float64("grpc.io/client/roundtrip_latency", "Time between first byte of request sent to last byte of response received, or terminal error.", stats.UnitMilliseconds)
+ ClientServerLatency = stats.Float64("grpc.io/client/server_latency", `Propagated from the server and should have the same value as "grpc.io/server/latency".`, stats.UnitMilliseconds)
+)
+
+// Predefined views may be subscribed to collect data for the above measures.
+// As always, you may also define your own custom views over measures collected by this
+// package. These are declared as a convenience only; none are subscribed by
+// default.
+var (
+ ClientSentBytesPerRPCView = &view.View{
+ Measure: ClientSentBytesPerRPC,
+ Name: "grpc.io/client/sent_bytes_per_rpc",
+ Description: "Distribution of bytes sent per RPC, by method.",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Aggregation: DefaultBytesDistribution,
+ }
+
+ ClientReceivedBytesPerRPCView = &view.View{
+ Measure: ClientReceivedBytesPerRPC,
+ Name: "grpc.io/client/received_bytes_per_rpc",
+ Description: "Distribution of bytes received per RPC, by method.",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Aggregation: DefaultBytesDistribution,
+ }
+
+ ClientRoundtripLatencyView = &view.View{
+ Measure: ClientRoundtripLatency,
+ Name: "grpc.io/client/roundtrip_latency",
+ Description: "Distribution of round-trip latency, by method.",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Aggregation: DefaultMillisecondsDistribution,
+ }
+
+ ClientCompletedRPCsView = &view.View{
+ Measure: ClientRoundtripLatency,
+ Name: "grpc.io/client/completed_rpcs",
+ Description: "Count of RPCs by method and status.",
+ TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus},
+ Aggregation: view.Count(),
+ }
+
+ ClientSentMessagesPerRPCView = &view.View{
+ Measure: ClientSentMessagesPerRPC,
+ Name: "grpc.io/client/sent_messages_per_rpc",
+ Description: "Distribution of sent messages count per RPC, by method.",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Aggregation: DefaultMessageCountDistribution,
+ }
+
+ ClientReceivedMessagesPerRPCView = &view.View{
+ Measure: ClientReceivedMessagesPerRPC,
+ Name: "grpc.io/client/received_messages_per_rpc",
+ Description: "Distribution of received messages count per RPC, by method.",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Aggregation: DefaultMessageCountDistribution,
+ }
+
+ ClientServerLatencyView = &view.View{
+ Measure: ClientServerLatency,
+ Name: "grpc.io/client/server_latency",
+ Description: "Distribution of server latency as viewed by client, by method.",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Aggregation: DefaultMillisecondsDistribution,
+ }
+
+ // Deprecated: This view is going to be removed, if you need it please define it
+ // yourself.
+ ClientRequestCountView = &view.View{
+ Name: "Count of request messages per client RPC",
+ TagKeys: []tag.Key{KeyClientMethod},
+ Measure: ClientRoundtripLatency,
+ Aggregation: view.Count(),
+ }
+)
+
+// DefaultClientViews are the default client views provided by this package.
+var DefaultClientViews = []*view.View{
+ ClientSentBytesPerRPCView,
+ ClientReceivedBytesPerRPCView,
+ ClientRoundtripLatencyView,
+ ClientCompletedRPCsView,
+}
+
+// TODO(jbd): Add roundtrip_latency, uncompressed_request_bytes, uncompressed_response_bytes, request_count, response_count.
+// TODO(acetechnologist): This is temporary and will need to be replaced by a
+// mechanism to load these defaults from a common repository/config shared by
+// all supported languages. Likely a serialized protobuf of these defaults.
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go b/vendor/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go
new file mode 100644
index 0000000..303c607
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/client_stats_handler.go
@@ -0,0 +1,49 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package ocgrpc
+
+import (
+ "time"
+
+ "go.opencensus.io/tag"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/stats"
+)
+
+// statsTagRPC gets the tag.Map populated by the application code, serializes
+// its tags into the GRPC metadata in order to be sent to the server.
+func (h *ClientHandler) statsTagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
+ startTime := time.Now()
+ if info == nil {
+ if grpclog.V(2) {
+ grpclog.Infof("clientHandler.TagRPC called with nil info.", info.FullMethodName)
+ }
+ return ctx
+ }
+
+ d := &rpcData{
+ startTime: startTime,
+ method: info.FullMethodName,
+ }
+ ts := tag.FromContext(ctx)
+ if ts != nil {
+ encoded := tag.Encode(ts)
+ ctx = stats.SetTags(ctx, encoded)
+ }
+
+ return context.WithValue(ctx, rpcDataKey, d)
+}
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/doc.go b/vendor/go.opencensus.io/plugin/ocgrpc/doc.go
new file mode 100644
index 0000000..1370323
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/doc.go
@@ -0,0 +1,19 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package ocgrpc contains OpenCensus stats and trace
+// integrations for gRPC.
+//
+// Use ServerHandler for servers and ClientHandler for clients.
+package ocgrpc // import "go.opencensus.io/plugin/ocgrpc"
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/server.go b/vendor/go.opencensus.io/plugin/ocgrpc/server.go
new file mode 100644
index 0000000..b67b3e2
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/server.go
@@ -0,0 +1,80 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ocgrpc
+
+import (
+ "go.opencensus.io/trace"
+ "golang.org/x/net/context"
+
+ "google.golang.org/grpc/stats"
+)
+
+// ServerHandler implements gRPC stats.Handler recording OpenCensus stats and
+// traces. Use with gRPC servers.
+//
+// When installed (see Example), tracing metadata is read from inbound RPCs
+// by default. If no tracing metadata is present, or if the tracing metadata is
+// present but the SpanContext isn't sampled, then a new trace may be started
+// (as determined by Sampler).
+type ServerHandler struct {
+ // IsPublicEndpoint may be set to true to always start a new trace around
+ // each RPC. Any SpanContext in the RPC metadata will be added as a linked
+ // span instead of making it the parent of the span created around the
+ // server RPC.
+ //
+ // Be aware that if you leave this false (the default) on a public-facing
+ // server, callers will be able to send tracing metadata in gRPC headers
+ // and trigger traces in your backend.
+ IsPublicEndpoint bool
+
+ // StartOptions to use for to spans started around RPCs handled by this server.
+ //
+ // These will apply even if there is tracing metadata already
+ // present on the inbound RPC but the SpanContext is not sampled. This
+ // ensures that each service has some opportunity to be traced. If you would
+ // like to not add any additional traces for this gRPC service, set:
+ //
+ // StartOptions.Sampler = trace.ProbabilitySampler(0.0)
+ //
+ // StartOptions.SpanKind will always be set to trace.SpanKindServer
+ // for spans started by this handler.
+ StartOptions trace.StartOptions
+}
+
+var _ stats.Handler = (*ServerHandler)(nil)
+
+// HandleConn exists to satisfy gRPC stats.Handler.
+func (s *ServerHandler) HandleConn(ctx context.Context, cs stats.ConnStats) {
+ // no-op
+}
+
+// TagConn exists to satisfy gRPC stats.Handler.
+func (s *ServerHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
+ // no-op
+ return ctx
+}
+
+// HandleRPC implements per-RPC tracing and stats instrumentation.
+func (s *ServerHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
+ traceHandleRPC(ctx, rs)
+ statsHandleRPC(ctx, rs)
+}
+
+// TagRPC implements per-RPC context management.
+func (s *ServerHandler) TagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
+ ctx = s.traceTagRPC(ctx, rti)
+ ctx = s.statsTagRPC(ctx, rti)
+ return ctx
+}
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/server_metrics.go b/vendor/go.opencensus.io/plugin/ocgrpc/server_metrics.go
new file mode 100644
index 0000000..02323f8
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/server_metrics.go
@@ -0,0 +1,97 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package ocgrpc
+
+import (
+ "go.opencensus.io/stats"
+ "go.opencensus.io/stats/view"
+ "go.opencensus.io/tag"
+)
+
+// The following variables are measures are recorded by ServerHandler:
+var (
+ ServerReceivedMessagesPerRPC = stats.Int64("grpc.io/server/received_messages_per_rpc", "Number of messages received in each RPC. Has value 1 for non-streaming RPCs.", stats.UnitDimensionless)
+ ServerReceivedBytesPerRPC = stats.Int64("grpc.io/server/received_bytes_per_rpc", "Total bytes received across all messages per RPC.", stats.UnitBytes)
+ ServerSentMessagesPerRPC = stats.Int64("grpc.io/server/sent_messages_per_rpc", "Number of messages sent in each RPC. Has value 1 for non-streaming RPCs.", stats.UnitDimensionless)
+ ServerSentBytesPerRPC = stats.Int64("grpc.io/server/sent_bytes_per_rpc", "Total bytes sent in across all response messages per RPC.", stats.UnitBytes)
+ ServerLatency = stats.Float64("grpc.io/server/server_latency", "Time between first byte of request received to last byte of response sent, or terminal error.", stats.UnitMilliseconds)
+)
+
+// TODO(acetechnologist): This is temporary and will need to be replaced by a
+// mechanism to load these defaults from a common repository/config shared by
+// all supported languages. Likely a serialized protobuf of these defaults.
+
+// Predefined views may be subscribed to collect data for the above measures.
+// As always, you may also define your own custom views over measures collected by this
+// package. These are declared as a convenience only; none are subscribed by
+// default.
+var (
+ ServerReceivedBytesPerRPCView = &view.View{
+ Name: "grpc.io/server/received_bytes_per_rpc",
+ Description: "Distribution of received bytes per RPC, by method.",
+ Measure: ServerReceivedBytesPerRPC,
+ TagKeys: []tag.Key{KeyServerMethod},
+ Aggregation: DefaultBytesDistribution,
+ }
+
+ ServerSentBytesPerRPCView = &view.View{
+ Name: "grpc.io/server/sent_bytes_per_rpc",
+ Description: "Distribution of total sent bytes per RPC, by method.",
+ Measure: ServerSentBytesPerRPC,
+ TagKeys: []tag.Key{KeyServerMethod},
+ Aggregation: DefaultBytesDistribution,
+ }
+
+ ServerLatencyView = &view.View{
+ Name: "grpc.io/server/server_latency",
+ Description: "Distribution of server latency in milliseconds, by method.",
+ TagKeys: []tag.Key{KeyServerMethod},
+ Measure: ServerLatency,
+ Aggregation: DefaultMillisecondsDistribution,
+ }
+
+ ServerCompletedRPCsView = &view.View{
+ Name: "grpc.io/server/completed_rpcs",
+ Description: "Count of RPCs by method and status.",
+ TagKeys: []tag.Key{KeyServerMethod, KeyServerStatus},
+ Measure: ServerLatency,
+ Aggregation: view.Count(),
+ }
+
+ ServerReceivedMessagesPerRPCView = &view.View{
+ Name: "grpc.io/server/received_messages_per_rpc",
+ Description: "Distribution of messages received count per RPC, by method.",
+ TagKeys: []tag.Key{KeyServerMethod},
+ Measure: ServerReceivedMessagesPerRPC,
+ Aggregation: DefaultMessageCountDistribution,
+ }
+
+ ServerSentMessagesPerRPCView = &view.View{
+ Name: "grpc.io/server/sent_messages_per_rpc",
+ Description: "Distribution of messages sent count per RPC, by method.",
+ TagKeys: []tag.Key{KeyServerMethod},
+ Measure: ServerSentMessagesPerRPC,
+ Aggregation: DefaultMessageCountDistribution,
+ }
+)
+
+// DefaultServerViews are the default server views provided by this package.
+var DefaultServerViews = []*view.View{
+ ServerReceivedBytesPerRPCView,
+ ServerSentBytesPerRPCView,
+ ServerLatencyView,
+ ServerCompletedRPCsView,
+}
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go b/vendor/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go
new file mode 100644
index 0000000..7847c1a
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/server_stats_handler.go
@@ -0,0 +1,63 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package ocgrpc
+
+import (
+ "time"
+
+ "golang.org/x/net/context"
+
+ "go.opencensus.io/tag"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/stats"
+)
+
+// statsTagRPC gets the metadata from gRPC context, extracts the encoded tags from
+// it and creates a new tag.Map and puts them into the returned context.
+func (h *ServerHandler) statsTagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
+ startTime := time.Now()
+ if info == nil {
+ if grpclog.V(2) {
+ grpclog.Infof("opencensus: TagRPC called with nil info.")
+ }
+ return ctx
+ }
+ d := &rpcData{
+ startTime: startTime,
+ method: info.FullMethodName,
+ }
+ propagated := h.extractPropagatedTags(ctx)
+ ctx = tag.NewContext(ctx, propagated)
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyServerMethod, methodName(info.FullMethodName)))
+ return context.WithValue(ctx, rpcDataKey, d)
+}
+
+// extractPropagatedTags creates a new tag map containing the tags extracted from the
+// gRPC metadata.
+func (h *ServerHandler) extractPropagatedTags(ctx context.Context) *tag.Map {
+ buf := stats.Tags(ctx)
+ if buf == nil {
+ return nil
+ }
+ propagated, err := tag.Decode(buf)
+ if err != nil {
+ if grpclog.V(2) {
+ grpclog.Warningf("opencensus: Failed to decode tags from gRPC metadata failed to decode: %v", err)
+ }
+ return nil
+ }
+ return propagated
+}
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/stats_common.go b/vendor/go.opencensus.io/plugin/ocgrpc/stats_common.go
new file mode 100644
index 0000000..119bbda
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/stats_common.go
@@ -0,0 +1,205 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package ocgrpc
+
+import (
+ "context"
+ "strconv"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ ocstats "go.opencensus.io/stats"
+ "go.opencensus.io/stats/view"
+ "go.opencensus.io/tag"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+)
+
+type grpcInstrumentationKey string
+
+// rpcData holds the instrumentation RPC data that is needed between the start
+// and end of an call. It holds the info that this package needs to keep track
+// of between the various GRPC events.
+type rpcData struct {
+ // reqCount and respCount has to be the first words
+ // in order to be 64-aligned on 32-bit architectures.
+ sentCount, sentBytes, recvCount, recvBytes int64 // access atomically
+
+ // startTime represents the time at which TagRPC was invoked at the
+ // beginning of an RPC. It is an appoximation of the time when the
+ // application code invoked GRPC code.
+ startTime time.Time
+ method string
+}
+
+// The following variables define the default hard-coded auxiliary data used by
+// both the default GRPC client and GRPC server metrics.
+var (
+ DefaultBytesDistribution = view.Distribution(0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824, 4294967296)
+ DefaultMillisecondsDistribution = view.Distribution(0, 0.01, 0.05, 0.1, 0.3, 0.6, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000)
+ DefaultMessageCountDistribution = view.Distribution(0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536)
+)
+
+// Server tags are applied to the context used to process each RPC, as well as
+// the measures at the end of each RPC.
+var (
+ KeyServerMethod, _ = tag.NewKey("grpc_server_method")
+ KeyServerStatus, _ = tag.NewKey("grpc_server_status")
+)
+
+// Client tags are applied to measures at the end of each RPC.
+var (
+ KeyClientMethod, _ = tag.NewKey("grpc_client_method")
+ KeyClientStatus, _ = tag.NewKey("grpc_client_status")
+)
+
+var (
+ rpcDataKey = grpcInstrumentationKey("opencensus-rpcData")
+)
+
+func methodName(fullname string) string {
+ return strings.TrimLeft(fullname, "/")
+}
+
+// statsHandleRPC processes the RPC events.
+func statsHandleRPC(ctx context.Context, s stats.RPCStats) {
+ switch st := s.(type) {
+ case *stats.Begin, *stats.OutHeader, *stats.InHeader, *stats.InTrailer, *stats.OutTrailer:
+ // do nothing for client
+ case *stats.OutPayload:
+ handleRPCOutPayload(ctx, st)
+ case *stats.InPayload:
+ handleRPCInPayload(ctx, st)
+ case *stats.End:
+ handleRPCEnd(ctx, st)
+ default:
+ grpclog.Infof("unexpected stats: %T", st)
+ }
+}
+
+func handleRPCOutPayload(ctx context.Context, s *stats.OutPayload) {
+ d, ok := ctx.Value(rpcDataKey).(*rpcData)
+ if !ok {
+ if grpclog.V(2) {
+ grpclog.Infoln("Failed to retrieve *rpcData from context.")
+ }
+ return
+ }
+
+ atomic.AddInt64(&d.sentBytes, int64(s.Length))
+ atomic.AddInt64(&d.sentCount, 1)
+}
+
+func handleRPCInPayload(ctx context.Context, s *stats.InPayload) {
+ d, ok := ctx.Value(rpcDataKey).(*rpcData)
+ if !ok {
+ if grpclog.V(2) {
+ grpclog.Infoln("Failed to retrieve *rpcData from context.")
+ }
+ return
+ }
+
+ atomic.AddInt64(&d.recvBytes, int64(s.Length))
+ atomic.AddInt64(&d.recvCount, 1)
+}
+
+func handleRPCEnd(ctx context.Context, s *stats.End) {
+ d, ok := ctx.Value(rpcDataKey).(*rpcData)
+ if !ok {
+ if grpclog.V(2) {
+ grpclog.Infoln("Failed to retrieve *rpcData from context.")
+ }
+ return
+ }
+
+ elapsedTime := time.Since(d.startTime)
+
+ var st string
+ if s.Error != nil {
+ s, ok := status.FromError(s.Error)
+ if ok {
+ st = statusCodeToString(s)
+ }
+ } else {
+ st = "OK"
+ }
+
+ latencyMillis := float64(elapsedTime) / float64(time.Millisecond)
+ if s.Client {
+ ctx, _ = tag.New(ctx,
+ tag.Upsert(KeyClientMethod, methodName(d.method)),
+ tag.Upsert(KeyClientStatus, st))
+ ocstats.Record(ctx,
+ ClientSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
+ ClientSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
+ ClientReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
+ ClientReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
+ ClientRoundtripLatency.M(latencyMillis))
+ } else {
+ ctx, _ = tag.New(ctx, tag.Upsert(KeyServerStatus, st))
+ ocstats.Record(ctx,
+ ServerSentBytesPerRPC.M(atomic.LoadInt64(&d.sentBytes)),
+ ServerSentMessagesPerRPC.M(atomic.LoadInt64(&d.sentCount)),
+ ServerReceivedMessagesPerRPC.M(atomic.LoadInt64(&d.recvCount)),
+ ServerReceivedBytesPerRPC.M(atomic.LoadInt64(&d.recvBytes)),
+ ServerLatency.M(latencyMillis))
+ }
+}
+
+func statusCodeToString(s *status.Status) string {
+ // see https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
+ switch c := s.Code(); c {
+ case codes.OK:
+ return "OK"
+ case codes.Canceled:
+ return "CANCELLED"
+ case codes.Unknown:
+ return "UNKNOWN"
+ case codes.InvalidArgument:
+ return "INVALID_ARGUMENT"
+ case codes.DeadlineExceeded:
+ return "DEADLINE_EXCEEDED"
+ case codes.NotFound:
+ return "NOT_FOUND"
+ case codes.AlreadyExists:
+ return "ALREADY_EXISTS"
+ case codes.PermissionDenied:
+ return "PERMISSION_DENIED"
+ case codes.ResourceExhausted:
+ return "RESOURCE_EXHAUSTED"
+ case codes.FailedPrecondition:
+ return "FAILED_PRECONDITION"
+ case codes.Aborted:
+ return "ABORTED"
+ case codes.OutOfRange:
+ return "OUT_OF_RANGE"
+ case codes.Unimplemented:
+ return "UNIMPLEMENTED"
+ case codes.Internal:
+ return "INTERNAL"
+ case codes.Unavailable:
+ return "UNAVAILABLE"
+ case codes.DataLoss:
+ return "DATA_LOSS"
+ case codes.Unauthenticated:
+ return "UNAUTHENTICATED"
+ default:
+ return "CODE_" + strconv.FormatInt(int64(c), 10)
+ }
+}
diff --git a/vendor/go.opencensus.io/plugin/ocgrpc/trace_common.go b/vendor/go.opencensus.io/plugin/ocgrpc/trace_common.go
new file mode 100644
index 0000000..720f381
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ocgrpc/trace_common.go
@@ -0,0 +1,107 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ocgrpc
+
+import (
+ "strings"
+
+ "google.golang.org/grpc/codes"
+
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+)
+
+const traceContextKey = "grpc-trace-bin"
+
+// TagRPC creates a new trace span for the client side of the RPC.
+//
+// It returns ctx with the new trace span added and a serialization of the
+// SpanContext added to the outgoing gRPC metadata.
+func (c *ClientHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
+ name := strings.TrimPrefix(rti.FullMethodName, "/")
+ name = strings.Replace(name, "/", ".", -1)
+ ctx, span := trace.StartSpan(ctx, name,
+ trace.WithSampler(c.StartOptions.Sampler),
+ trace.WithSpanKind(trace.SpanKindClient)) // span is ended by traceHandleRPC
+ traceContextBinary := propagation.Binary(span.SpanContext())
+ return metadata.AppendToOutgoingContext(ctx, traceContextKey, string(traceContextBinary))
+}
+
+// TagRPC creates a new trace span for the server side of the RPC.
+//
+// It checks the incoming gRPC metadata in ctx for a SpanContext, and if
+// it finds one, uses that SpanContext as the parent context of the new span.
+//
+// It returns ctx, with the new trace span added.
+func (s *ServerHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) context.Context {
+ md, _ := metadata.FromIncomingContext(ctx)
+ name := strings.TrimPrefix(rti.FullMethodName, "/")
+ name = strings.Replace(name, "/", ".", -1)
+ traceContext := md[traceContextKey]
+ var (
+ parent trace.SpanContext
+ haveParent bool
+ )
+ if len(traceContext) > 0 {
+ // Metadata with keys ending in -bin are actually binary. They are base64
+ // encoded before being put on the wire, see:
+ // https://github.com/grpc/grpc-go/blob/08d6261/Documentation/grpc-metadata.md#storing-binary-data-in-metadata
+ traceContextBinary := []byte(traceContext[0])
+ parent, haveParent = propagation.FromBinary(traceContextBinary)
+ if haveParent && !s.IsPublicEndpoint {
+ ctx, _ := trace.StartSpanWithRemoteParent(ctx, name, parent,
+ trace.WithSpanKind(trace.SpanKindServer),
+ trace.WithSampler(s.StartOptions.Sampler),
+ )
+ return ctx
+ }
+ }
+ ctx, span := trace.StartSpan(ctx, name,
+ trace.WithSpanKind(trace.SpanKindServer),
+ trace.WithSampler(s.StartOptions.Sampler))
+ if haveParent {
+ span.AddLink(trace.Link{TraceID: parent.TraceID, SpanID: parent.SpanID, Type: trace.LinkTypeChild})
+ }
+ return ctx
+}
+
+func traceHandleRPC(ctx context.Context, rs stats.RPCStats) {
+ span := trace.FromContext(ctx)
+ // TODO: compressed and uncompressed sizes are not populated in every message.
+ switch rs := rs.(type) {
+ case *stats.Begin:
+ span.AddAttributes(
+ trace.BoolAttribute("Client", rs.Client),
+ trace.BoolAttribute("FailFast", rs.FailFast))
+ case *stats.InPayload:
+ span.AddMessageReceiveEvent(0 /* TODO: messageID */, int64(rs.Length), int64(rs.WireLength))
+ case *stats.OutPayload:
+ span.AddMessageSendEvent(0, int64(rs.Length), int64(rs.WireLength))
+ case *stats.End:
+ if rs.Error != nil {
+ s, ok := status.FromError(rs.Error)
+ if ok {
+ span.SetStatus(trace.Status{Code: int32(s.Code()), Message: s.Message()})
+ } else {
+ span.SetStatus(trace.Status{Code: int32(codes.Internal), Message: rs.Error.Error()})
+ }
+ }
+ span.End()
+ }
+}