mirror of https://github.com/grpc/grpc.git
The client binary can be built with 'bazel build //tools/grpcz:grpcz_client' and can be invoked with bazel-bin/tools/grpcz/grpcz_client --server SERVER_ADDR:PORT You can see the stats page at http://localhost:8000/grpczpull/9810/head
parent
1096672527
commit
003092a202
8 changed files with 910 additions and 5 deletions
@ -0,0 +1,73 @@ |
|||||||
|
# Copyright 2017, Google Inc. |
||||||
|
# All rights reserved. |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are |
||||||
|
# met: |
||||||
|
# |
||||||
|
# * Redistributions of source code must retain the above copyright |
||||||
|
# notice, this list of conditions and the following disclaimer. |
||||||
|
# * Redistributions in binary form must reproduce the above |
||||||
|
# copyright notice, this list of conditions and the following disclaimer |
||||||
|
# in the documentation and/or other materials provided with the |
||||||
|
# distribution. |
||||||
|
# * Neither the name of Google Inc. nor the names of its |
||||||
|
# contributors may be used to endorse or promote products derived from |
||||||
|
# this software without specific prior written permission. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
licenses(["notice"]) # 3-clause BSD |
||||||
|
|
||||||
|
package(default_visibility = ["//visibility:public"]) |
||||||
|
|
||||||
|
load("//:bazel/generate_cc.bzl", "generate_cc") |
||||||
|
|
||||||
|
proto_library ( |
||||||
|
name = "monitoring_proto_local_copy", |
||||||
|
srcs = [ |
||||||
|
# TODO (erikgribkoff) : remove the local copies of these protos |
||||||
|
"monitoring.proto", |
||||||
|
"empty.proto", |
||||||
|
"any.proto", |
||||||
|
"census.proto", |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
generate_cc( |
||||||
|
name = "monitoring_codegen", |
||||||
|
srcs = [":monitoring_proto_local_copy"], |
||||||
|
) |
||||||
|
|
||||||
|
generate_cc( |
||||||
|
name = "monitoring_grpc_codegen", |
||||||
|
srcs = [":monitoring_proto_local_copy"], |
||||||
|
plugin = "//:grpc_cpp_plugin", |
||||||
|
) |
||||||
|
|
||||||
|
cc_library( |
||||||
|
name = "proto_lib", |
||||||
|
srcs = [":monitoring_codegen", ":monitoring_grpc_codegen"], |
||||||
|
hdrs = [":monitoring_codegen", ":monitoring_grpc_codegen"], |
||||||
|
deps = ["//:grpc++", "//:grpc++_codegen_proto", "//external:protobuf"], |
||||||
|
) |
||||||
|
|
||||||
|
cc_binary( |
||||||
|
name = "grpcz_client", |
||||||
|
srcs = ["grpcz_client.cc",], |
||||||
|
deps = [ |
||||||
|
"proto_lib", |
||||||
|
"//external:gflags", |
||||||
|
"@mongoose_repo//:mongoose_lib", |
||||||
|
], |
||||||
|
) |
@ -0,0 +1,139 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
//package google.protobuf; |
||||||
|
|
||||||
|
option csharp_namespace = "Google.Protobuf.WellKnownTypes"; |
||||||
|
option go_package = "github.com/golang/protobuf/ptypes/any"; |
||||||
|
option java_package = "com.google.protobuf"; |
||||||
|
option java_outer_classname = "AnyProto"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option objc_class_prefix = "GPB"; |
||||||
|
|
||||||
|
// `Any` contains an arbitrary serialized protocol buffer message along with a |
||||||
|
// URL that describes the type of the serialized message. |
||||||
|
// |
||||||
|
// Protobuf library provides support to pack/unpack Any values in the form |
||||||
|
// of utility functions or additional generated methods of the Any type. |
||||||
|
// |
||||||
|
// Example 1: Pack and unpack a message in C++. |
||||||
|
// |
||||||
|
// Foo foo = ...; |
||||||
|
// Any any; |
||||||
|
// any.PackFrom(foo); |
||||||
|
// ... |
||||||
|
// if (any.UnpackTo(&foo)) { |
||||||
|
// ... |
||||||
|
// } |
||||||
|
// |
||||||
|
// Example 2: Pack and unpack a message in Java. |
||||||
|
// |
||||||
|
// Foo foo = ...; |
||||||
|
// Any any = Any.pack(foo); |
||||||
|
// ... |
||||||
|
// if (any.is(Foo.class)) { |
||||||
|
// foo = any.unpack(Foo.class); |
||||||
|
// } |
||||||
|
// |
||||||
|
// Example 3: Pack and unpack a message in Python. |
||||||
|
// |
||||||
|
// foo = Foo(...) |
||||||
|
// any = Any() |
||||||
|
// any.Pack(foo) |
||||||
|
// ... |
||||||
|
// if any.Is(Foo.DESCRIPTOR): |
||||||
|
// any.Unpack(foo) |
||||||
|
// ... |
||||||
|
// |
||||||
|
// The pack methods provided by protobuf library will by default use |
||||||
|
// 'type.googleapis.com/full.type.name' as the type URL and the unpack |
||||||
|
// methods only use the fully qualified type name after the last '/' |
||||||
|
// in the type URL, for example "foo.bar.com/x/y.z" will yield type |
||||||
|
// name "y.z". |
||||||
|
// |
||||||
|
// |
||||||
|
// JSON |
||||||
|
// ==== |
||||||
|
// The JSON representation of an `Any` value uses the regular |
||||||
|
// representation of the deserialized, embedded message, with an |
||||||
|
// additional field `@type` which contains the type URL. Example: |
||||||
|
// |
||||||
|
// package google.profile; |
||||||
|
// message Person { |
||||||
|
// string first_name = 1; |
||||||
|
// string last_name = 2; |
||||||
|
// } |
||||||
|
// |
||||||
|
// { |
||||||
|
// "@type": "type.googleapis.com/google.profile.Person", |
||||||
|
// "firstName": <string>, |
||||||
|
// "lastName": <string> |
||||||
|
// } |
||||||
|
// |
||||||
|
// If the embedded message type is well-known and has a custom JSON |
||||||
|
// representation, that representation will be embedded adding a field |
||||||
|
// `value` which holds the custom JSON in addition to the `@type` |
||||||
|
// field. Example (for message [google.protobuf.Duration][]): |
||||||
|
// |
||||||
|
// { |
||||||
|
// "@type": "type.googleapis.com/google.protobuf.Duration", |
||||||
|
// "value": "1.212s" |
||||||
|
// } |
||||||
|
// |
||||||
|
message Any { |
||||||
|
// A URL/resource name whose content describes the type of the |
||||||
|
// serialized protocol buffer message. |
||||||
|
// |
||||||
|
// For URLs which use the scheme `http`, `https`, or no scheme, the |
||||||
|
// following restrictions and interpretations apply: |
||||||
|
// |
||||||
|
// * If no scheme is provided, `https` is assumed. |
||||||
|
// * The last segment of the URL's path must represent the fully |
||||||
|
// qualified name of the type (as in `path/google.protobuf.Duration`). |
||||||
|
// The name should be in a canonical form (e.g., leading "." is |
||||||
|
// not accepted). |
||||||
|
// * An HTTP GET on the URL must yield a [google.protobuf.Type][] |
||||||
|
// value in binary format, or produce an error. |
||||||
|
// * Applications are allowed to cache lookup results based on the |
||||||
|
// URL, or have them precompiled into a binary to avoid any |
||||||
|
// lookup. Therefore, binary compatibility needs to be preserved |
||||||
|
// on changes to types. (Use versioned type names to manage |
||||||
|
// breaking changes.) |
||||||
|
// |
||||||
|
// Schemes other than `http`, `https` (or the empty scheme) might be |
||||||
|
// used with implementation specific semantics. |
||||||
|
// |
||||||
|
string type_url = 1; |
||||||
|
|
||||||
|
// Must be a valid serialized protocol buffer of the above specified type. |
||||||
|
bytes value = 2; |
||||||
|
} |
@ -0,0 +1,318 @@ |
|||||||
|
// Copyright 2017, Google Inc. |
||||||
|
// 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. |
||||||
|
|
||||||
|
//TODO(ericgribkoff) Depend on this directly from the instrumentation-proto |
||||||
|
//repository. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package google.instrumentation; |
||||||
|
|
||||||
|
option java_package = "com.google.instrumentation.stats.proto"; |
||||||
|
option java_outer_classname = "CensusProto"; |
||||||
|
|
||||||
|
// All the census protos. |
||||||
|
// |
||||||
|
// Nomenclature notes: |
||||||
|
// * Capitalized names below (like View) are protos. |
||||||
|
// * Protos which describe types are named with a Descriptor suffix (e.g. |
||||||
|
// MesurementDescriptor). |
||||||
|
// |
||||||
|
// Census lets you define the type and description of the data being measured |
||||||
|
// (e.g. the latency of an RPC or the number of CPU cycles spent on an |
||||||
|
// operation using MeasurementDescriptor. As individual measurements (a double |
||||||
|
// value) for are recorded, they are aggregated together into an |
||||||
|
// Aggregation. There are two Aggregation types available: Distribution |
||||||
|
// (describes the distribution of all measurements, possibly with a histogram) |
||||||
|
// and IntervalStats (the count and mean of measurements across specified time |
||||||
|
// periods). An Aggregation is described by an AggregationDescriptor. |
||||||
|
// |
||||||
|
// You can define how your measurements (described by a MeasurementDescriptor) |
||||||
|
// are broken down by Tag values and which Aggregations to use through a |
||||||
|
// ViewDescriptor. The output (all measurements broken down by tag values into |
||||||
|
// specific Aggregations) is called a View. |
||||||
|
|
||||||
|
|
||||||
|
// The following two types are copied from |
||||||
|
// google/protobuf/{duration,timestamp}.proto. Ideally, we would be able to |
||||||
|
// import them, but this causes compilation issues on C-based systems |
||||||
|
// (e.g. https://koti.kapsi.fi/jpa/nanopb/), which cannot process the C++ |
||||||
|
// headers generated from the standard protobuf distribution. See the relevant |
||||||
|
// proto files for full documentation of these types. |
||||||
|
|
||||||
|
message Duration { |
||||||
|
// Signed seconds of the span of time. Must be from -315,576,000,000 |
||||||
|
// to +315,576,000,000 inclusive. |
||||||
|
int64 seconds = 1; |
||||||
|
|
||||||
|
// Signed fractions of a second at nanosecond resolution of the span |
||||||
|
// of time. Durations less than one second are represented with a 0 |
||||||
|
// `seconds` field and a positive or negative `nanos` field. For durations |
||||||
|
// of one second or more, a non-zero value for the `nanos` field must be |
||||||
|
// of the same sign as the `seconds` field. Must be from -999,999,999 |
||||||
|
// to +999,999,999 inclusive. |
||||||
|
int32 nanos = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message Timestamp { |
||||||
|
// Represents seconds of UTC time since Unix epoch |
||||||
|
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to |
||||||
|
// 9999-12-31T23:59:59Z inclusive. |
||||||
|
int64 seconds = 1; |
||||||
|
|
||||||
|
// Non-negative fractions of a second at nanosecond resolution. Negative |
||||||
|
// second values with fractions must still have non-negative nanos values |
||||||
|
// that count forward in time. Must be from 0 to 999,999,999 |
||||||
|
// inclusive. |
||||||
|
int32 nanos = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// MeasurementDescriptor describes a data point (measurement) type. |
||||||
|
message MeasurementDescriptor { |
||||||
|
// A descriptive name, e.g. rpc_latency, cpu. Must be unique. |
||||||
|
string name = 1; |
||||||
|
|
||||||
|
// More detailed description of the resource, used in documentation. |
||||||
|
string description = 2; |
||||||
|
|
||||||
|
// Fundamental units of measurement supported by Census |
||||||
|
// TODO(aveitch): expand this to include other S.I. units? |
||||||
|
enum BasicUnit { |
||||||
|
UNKNOWN = 0; // Implementations should not use this |
||||||
|
SCALAR = 1; // Dimensionless |
||||||
|
BITS = 2; // A single bit |
||||||
|
BYTES = 3; // An 8-bit byte |
||||||
|
SECONDS = 4; // S.I. unit |
||||||
|
CORES = 5; // CPU core usage |
||||||
|
MAX_UNITS = 6; // Last defined value; implementations should only use |
||||||
|
// this for validation. |
||||||
|
} |
||||||
|
|
||||||
|
// MeasurementUnit lets you build compound units of the form |
||||||
|
// 10^n * (A * B * ...) / (X * Y * ...), |
||||||
|
// where the elements in the numerator and denominator are all BasicUnits. A |
||||||
|
// MeasurementUnit must have at least one BasicUnit in its numerator. |
||||||
|
// |
||||||
|
// To specify multiplication in the numerator or denominator, simply specify |
||||||
|
// multiple numerator or denominator fields. For example: |
||||||
|
// |
||||||
|
// - byte-seconds (i.e. bytes * seconds): |
||||||
|
// numerator: BYTES |
||||||
|
// numerator: SECS |
||||||
|
// |
||||||
|
// - events/sec^2 (i.e. rate of change of events/sec): |
||||||
|
// numerator: SCALAR |
||||||
|
// denominator: SECS |
||||||
|
// denominator: SECS |
||||||
|
// |
||||||
|
// To specify multiples (in power of 10) of units, specify a non-zero |
||||||
|
// 'power10' value, for example: |
||||||
|
// |
||||||
|
// - MB/s (i.e. megabytes / s): |
||||||
|
// power10: 6 |
||||||
|
// numerator: BYTES |
||||||
|
// denominator: SECS |
||||||
|
// |
||||||
|
// - nanoseconds |
||||||
|
// power10: -9 |
||||||
|
// numerator: SECS |
||||||
|
message MeasurementUnit { |
||||||
|
int32 power10 = 1; |
||||||
|
repeated BasicUnit numerators = 2; |
||||||
|
repeated BasicUnit denominators = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// The units used by this type of measurement. |
||||||
|
MeasurementUnit unit = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// An aggregation summarizes a series of individual measurements. There are |
||||||
|
// two types of aggregation (IntervalAggregation and DistributionAggregation), |
||||||
|
// unique types of each can be set using descriptors for each. |
||||||
|
|
||||||
|
// DistributionAggregation contains summary statistics for a population of |
||||||
|
// values and, optionally, a histogram representing the distribution of those |
||||||
|
// values across a specified set of histogram buckets, as defined in |
||||||
|
// DistributionAggregationDescriptor.bucket_bounds. |
||||||
|
// |
||||||
|
// The summary statistics are the count, mean, minimum, and the maximum of the |
||||||
|
// set of population of values. |
||||||
|
// |
||||||
|
// Although it is not forbidden, it is generally a bad idea to include |
||||||
|
// non-finite values (infinities or NaNs) in the population of values, as this |
||||||
|
// will render the `mean` field meaningless. |
||||||
|
message DistributionAggregation { |
||||||
|
// The number of values in the population. Must be non-negative. |
||||||
|
int64 count = 1; |
||||||
|
|
||||||
|
// The arithmetic mean of the values in the population. If `count` is zero |
||||||
|
// then this field must be zero. |
||||||
|
double mean = 2; |
||||||
|
|
||||||
|
// The sum of the values in the population. If `count` is zero then this |
||||||
|
// field must be zero. |
||||||
|
double sum = 3; |
||||||
|
|
||||||
|
// Describes a range of population values. |
||||||
|
message Range { |
||||||
|
// The minimum of the population values. |
||||||
|
double min = 1; |
||||||
|
// The maximum of the population values. |
||||||
|
double max = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// The range of the population values. If `count` is zero, this field will not |
||||||
|
// be defined. |
||||||
|
Range range = 4; |
||||||
|
|
||||||
|
// A Distribution may optionally contain a histogram of the values in the |
||||||
|
// population. The histogram is given in `bucket_count` as counts of values |
||||||
|
// that fall into one of a sequence of non-overlapping buckets, as described |
||||||
|
// by `DistributionAggregationDescriptor.bucket_boundaries`. The sum of the |
||||||
|
// values in `bucket_counts` must equal the value in `count`. |
||||||
|
// |
||||||
|
// Bucket counts are given in order under the numbering scheme described |
||||||
|
// above (the underflow bucket has number 0; the finite buckets, if any, |
||||||
|
// have numbers 1 through N-2; the overflow bucket has number N-1). |
||||||
|
// |
||||||
|
// The size of `bucket_count` must be no greater than N as defined in |
||||||
|
// `bucket_boundaries`. |
||||||
|
// |
||||||
|
// Any suffix of trailing zero bucket_count fields may be omitted. |
||||||
|
repeated int64 bucket_counts = 5; |
||||||
|
|
||||||
|
// Tags associated with this DistributionAggregation. These will be filled |
||||||
|
// in based on the View specification. |
||||||
|
repeated Tag tags = 6; |
||||||
|
} |
||||||
|
|
||||||
|
message DistributionAggregationDescriptor { |
||||||
|
// A Distribution may optionally contain a histogram of the values in the |
||||||
|
// population. The bucket boundaries for that histogram are described by |
||||||
|
// `bucket_bounds`. This defines `size(bucket_bounds) + 1` (= N) |
||||||
|
// buckets. The boundaries for bucket index i are: |
||||||
|
// |
||||||
|
// [-infinity, bucket_bounds[i]) for i == 0 |
||||||
|
// [bucket_bounds[i-1], bucket_bounds[i]) for 0 < i < N-2 |
||||||
|
// [bucket_bounds[i-1], +infinity) for i == N-1 |
||||||
|
// |
||||||
|
// i.e. an underflow bucket (number 0), zero or more finite buckets (1 |
||||||
|
// through N - 2, and an overflow bucket (N - 1), with inclusive lower |
||||||
|
// bounds and exclusive upper bounds. |
||||||
|
// |
||||||
|
// If `bucket_bounds` has no elements (zero size), then there is no |
||||||
|
// histogram associated with the Distribution. If `bucket_bounds` has only |
||||||
|
// one element, there are no finite buckets, and that single element is the |
||||||
|
// common boundary of the overflow and underflow buckets. The values must |
||||||
|
// be monotonically increasing. |
||||||
|
repeated double bucket_bounds = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// An IntervalAggreation records summary stats over various time |
||||||
|
// windows. These stats are approximate, with the degree of accuracy |
||||||
|
// controlled by setting the n_sub_intervals parameter in the |
||||||
|
// IntervalAggregationDescriptor. |
||||||
|
message IntervalAggregation { |
||||||
|
// Summary statistic over a single time interval. |
||||||
|
message Interval { |
||||||
|
// The interval duration. Must be positive. |
||||||
|
Duration interval_size = 1; |
||||||
|
// Approximate number of measurements recorded in this interval. |
||||||
|
double count = 2; |
||||||
|
// The cumulative sum of measurements in this interval. |
||||||
|
double sum = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// Full set of intervals for this aggregation. |
||||||
|
repeated Interval intervals = 1; |
||||||
|
|
||||||
|
// Tags associated with this IntervalAggregation. These will be filled in |
||||||
|
// based on the View specification. |
||||||
|
repeated Tag tags = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// An IntervalAggreationDescriptor specifies time intervals for an |
||||||
|
// IntervalAggregation. |
||||||
|
message IntervalAggregationDescriptor { |
||||||
|
// Number of internal sub-intervals to use when collecting stats for each |
||||||
|
// interval. The max error in interval measurements will be approximately |
||||||
|
// 1/n_sub_intervals (although in practice, this will only be approached in |
||||||
|
// the presence of very large and bursty workload changes), and underlying |
||||||
|
// memory usage will be roughly proportional to the value of this |
||||||
|
// field. Must be in the range [2, 20]. A value of 5 will be used if this is |
||||||
|
// unspecified. |
||||||
|
int32 n_sub_intervals = 1; |
||||||
|
|
||||||
|
// The size of each interval, as a time duration. Must have at least one |
||||||
|
// element. |
||||||
|
repeated Duration interval_sizes = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// A Tag: key-value pair. |
||||||
|
message Tag { |
||||||
|
string key = 1; |
||||||
|
string value = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// A ViewDescriptor specifies an AggregationDescriptor and a set of tag |
||||||
|
// keys. Views instantiated from this descriptor will contain Aggregations |
||||||
|
// broken down by the unique set of matching tag values for each measurement. |
||||||
|
message ViewDescriptor { |
||||||
|
// Name of view. Must be unique. |
||||||
|
string name = 1; |
||||||
|
|
||||||
|
// More detailed description, for documentation purposes. |
||||||
|
string description = 2; |
||||||
|
|
||||||
|
// Name of a MeasurementDescriptor to be used for this view. |
||||||
|
string measurement_descriptor_name = 3; |
||||||
|
|
||||||
|
// Aggregation type to associate with View. |
||||||
|
oneof aggregation { |
||||||
|
IntervalAggregationDescriptor interval_aggregation = 4; |
||||||
|
DistributionAggregationDescriptor distribution_aggregation = 5; |
||||||
|
} |
||||||
|
|
||||||
|
// Tag keys to match with a given measurement. If no keys are specified, |
||||||
|
// then all stats are recorded. Keys must be unique. |
||||||
|
repeated string tag_keys = 6; |
||||||
|
} |
||||||
|
|
||||||
|
// DistributionView contains all aggregations for a view specified using a |
||||||
|
// DistributionAggregationDescriptor. |
||||||
|
message DistributionView { |
||||||
|
// Aggregations - each will have a unique set of tag values for the tag_keys |
||||||
|
// associated with the corresponding View. |
||||||
|
repeated DistributionAggregation aggregations = 1; |
||||||
|
|
||||||
|
// Start and end timestamps over which aggregations was accumulated. |
||||||
|
Timestamp start = 2; |
||||||
|
Timestamp end = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// IntervalView contains all aggregations for a view specified using a |
||||||
|
// IntervalAggregationDescriptor. |
||||||
|
message IntervalView { |
||||||
|
// Aggregations - each will have a unique set of tag values for the tag_keys |
||||||
|
// associated with the corresponding View. |
||||||
|
repeated IntervalAggregation aggregations = 1; |
||||||
|
} |
||||||
|
|
||||||
|
// A View contains the aggregations based on a ViewDescriptor. |
||||||
|
message View { |
||||||
|
// ViewDescriptor name associated with this set of View. |
||||||
|
string view_name = 1; |
||||||
|
|
||||||
|
oneof view { |
||||||
|
DistributionView distribution_view = 2; |
||||||
|
IntervalView interval_view = 3; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
// Protocol Buffers - Google's data interchange format |
||||||
|
// Copyright 2008 Google Inc. All rights reserved. |
||||||
|
// https://developers.google.com/protocol-buffers/ |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package google.protobuf; |
||||||
|
|
||||||
|
option csharp_namespace = "Google.Protobuf.WellKnownTypes"; |
||||||
|
option go_package = "github.com/golang/protobuf/ptypes/empty"; |
||||||
|
option java_package = "com.google.protobuf"; |
||||||
|
option java_outer_classname = "EmptyProto"; |
||||||
|
option java_multiple_files = true; |
||||||
|
option objc_class_prefix = "GPB"; |
||||||
|
option cc_enable_arenas = true; |
||||||
|
|
||||||
|
// A generic empty message that you can re-use to avoid defining duplicated |
||||||
|
// empty messages in your APIs. A typical example is to use it as the request |
||||||
|
// or the response type of an API method. For instance: |
||||||
|
// |
||||||
|
// service Foo { |
||||||
|
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); |
||||||
|
// } |
||||||
|
// |
||||||
|
// The JSON representation for `Empty` is empty JSON object `{}`. |
||||||
|
message Empty {} |
@ -0,0 +1,174 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2017, Google Inc. |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above |
||||||
|
* copyright notice, this list of conditions and the following disclaimer |
||||||
|
* in the documentation and/or other materials provided with the |
||||||
|
* distribution. |
||||||
|
* * Neither the name of Google Inc. nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <iostream> |
||||||
|
#include <memory> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include <google/protobuf/util/json_util.h> |
||||||
|
#include <grpc++/grpc++.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
|
||||||
|
#include "gflags/gflags.h" |
||||||
|
#include "mongoose.h" |
||||||
|
|
||||||
|
// TODO (makdharma): remove local copies of these protos
|
||||||
|
#include "tools/grpcz/census.grpc.pb.h" |
||||||
|
#include "tools/grpcz/monitoring.grpc.pb.h" |
||||||
|
|
||||||
|
DEFINE_string(server, "127.0.0.1:50052", |
||||||
|
"file path (or host:port) where grpcz server is running"); |
||||||
|
DEFINE_string(http_port, "8000", |
||||||
|
"Port id for accessing the HTTP server that renders /grpcz page"); |
||||||
|
DEFINE_bool(print, false, "only print the output and quit"); |
||||||
|
|
||||||
|
using grpc::Channel; |
||||||
|
using grpc::ClientContext; |
||||||
|
using grpc::Status; |
||||||
|
|
||||||
|
using ::grpc::instrumentation::v1alpha::CanonicalRpcStats; |
||||||
|
using ::grpc::instrumentation::v1alpha::Monitoring; |
||||||
|
|
||||||
|
static const std::string static_html_header = |
||||||
|
"<!DOCTYPE html> <html> <head> <style> \
|
||||||
|
table { border-collapse: collapse; width: 100%; } \
|
||||||
|
table, td, th { border: 1px solid black; } \
|
||||||
|
</style> </head> <body>\
|
||||||
|
<div id='stats' stats='"; |
||||||
|
|
||||||
|
static const std::string static_html_footer = |
||||||
|
"' class='hidden'></div>\
|
||||||
|
<h1> GRPCZ FTW </h1> <div id='table'> </div> \
|
||||||
|
<script> \
|
||||||
|
var canonical_stats = JSON.parse(\
|
||||||
|
document.getElementById('stats').getAttribute('stats')); \
|
||||||
|
var table = document.createElement('table'); \
|
||||||
|
for (var key in canonical_stats) { \
|
||||||
|
name = canonical_stats[key]['view']['viewName']; \
|
||||||
|
distribution = canonical_stats[key]['view']['distributionView']; \
|
||||||
|
interval = canonical_stats[key]['view']['intervalView']; \
|
||||||
|
value = (interval == undefined) ? \
|
||||||
|
JSON.stringify(distribution, null, ' ') : \
|
||||||
|
JSON.stringify(interval, null, ' '); \
|
||||||
|
var row = table.insertRow(-1); \
|
||||||
|
var col1 = row.insertCell(0); \
|
||||||
|
var col2 = row.insertCell(1); \
|
||||||
|
col1.innerHTML = name; \
|
||||||
|
col2.innerHTML = '<pre>' + value + '</pre>'; \
|
||||||
|
} \
|
||||||
|
document.getElementById('table').appendChild(table); \
|
||||||
|
</script> </body> </html>"; |
||||||
|
|
||||||
|
class GrpczClient { |
||||||
|
public: |
||||||
|
GrpczClient(std::shared_ptr<Channel> channel) |
||||||
|
: stub_(Monitoring::NewStub(channel)) {} |
||||||
|
|
||||||
|
std::string GetStatsAsJson() { |
||||||
|
const ::google::protobuf::Empty request; |
||||||
|
CanonicalRpcStats reply; |
||||||
|
ClientContext context; |
||||||
|
Status status = stub_->GetCanonicalRpcStats(&context, request, &reply); |
||||||
|
|
||||||
|
if (status.ok()) { |
||||||
|
std::string json_str; |
||||||
|
::google::protobuf::util::MessageToJsonString(reply, &json_str); |
||||||
|
return json_str; |
||||||
|
} else { |
||||||
|
static const std::string error_message_json = |
||||||
|
"{\"grpcz Access Error\"\
|
||||||
|
:{\"view\":{\"viewName\":\"grpcz Access Error\",\
|
||||||
|
\"intervalView\":\"Server not running?\"}}}"; |
||||||
|
std::cout << status.error_code() << ":= " << status.error_message() |
||||||
|
<< std::endl; |
||||||
|
return error_message_json; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
std::unique_ptr<Monitoring::Stub> stub_; |
||||||
|
}; |
||||||
|
|
||||||
|
static struct mg_serve_http_opts s_http_server_opts; |
||||||
|
std::unique_ptr<GrpczClient> g_grpcz_client; |
||||||
|
|
||||||
|
static void ev_handler(struct mg_connection *nc, int ev, void *p) { |
||||||
|
if (ev == MG_EV_HTTP_REQUEST) { |
||||||
|
mg_serve_http(nc, (struct http_message *)p, s_http_server_opts); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void grpcz_handler(struct mg_connection *nc, int ev, void *ev_data) { |
||||||
|
(void)ev; |
||||||
|
(void)ev_data; |
||||||
|
gpr_log(GPR_INFO, "fetching grpcz stats from %s", FLAGS_server.c_str()); |
||||||
|
std::string json_str = g_grpcz_client->GetStatsAsJson(); |
||||||
|
std::string rendered_html = |
||||||
|
static_html_header + json_str + static_html_footer; |
||||||
|
mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n%s", rendered_html.c_str()); |
||||||
|
nc->flags |= MG_F_SEND_AND_CLOSE; |
||||||
|
} |
||||||
|
|
||||||
|
int main(int argc, char **argv) { |
||||||
|
gflags::ParseCommandLineFlags(&argc, &argv, true); |
||||||
|
|
||||||
|
// Create a client
|
||||||
|
g_grpcz_client.reset(new GrpczClient( |
||||||
|
grpc::CreateChannel(FLAGS_server, grpc::InsecureChannelCredentials()))); |
||||||
|
if (FLAGS_print) { |
||||||
|
g_grpcz_client->GetStatsAsJson(); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
// Set up a mongoose webserver handler
|
||||||
|
struct mg_mgr mgr; |
||||||
|
mg_mgr_init(&mgr, NULL); |
||||||
|
gpr_log(GPR_INFO, "Starting grpcz web server on port %s\n", |
||||||
|
FLAGS_http_port.c_str()); |
||||||
|
|
||||||
|
struct mg_connection *nc = mg_bind(&mgr, FLAGS_http_port.c_str(), ev_handler); |
||||||
|
if (nc == NULL) { |
||||||
|
gpr_log(GPR_ERROR, "Failed to create listener on port %s\n", |
||||||
|
FLAGS_http_port.c_str()); |
||||||
|
return -11; |
||||||
|
} |
||||||
|
mg_register_http_endpoint(nc, "/grpcz", grpcz_handler); |
||||||
|
mg_set_protocol_http_websocket(nc); |
||||||
|
|
||||||
|
// Poll in a loop and serve /grpcz pages
|
||||||
|
for (;;) { |
||||||
|
mg_mgr_poll(&mgr, 100); |
||||||
|
} |
||||||
|
mg_mgr_free(&mgr); |
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,131 @@ |
|||||||
|
// Copyright 2017, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// This file defines an interface for exporting monitoring information |
||||||
|
// out of gRPC servers. |
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
// TODO(ericgribkoff) Figure out how to manage the external Census proto |
||||||
|
// dependency. |
||||||
|
import "tools/grpcz/census.proto"; |
||||||
|
import "tools/grpcz/empty.proto"; |
||||||
|
import "tools/grpcz/any.proto"; |
||||||
|
|
||||||
|
package grpc.instrumentation.v1alpha; |
||||||
|
|
||||||
|
option java_multiple_files = true; |
||||||
|
option java_package = "io.grpc.instrumentation.v1alpha"; |
||||||
|
option java_outer_classname = "MonitoringProto"; |
||||||
|
|
||||||
|
service Monitoring { |
||||||
|
// Return canonical RPC stats |
||||||
|
rpc GetCanonicalRpcStats(google.protobuf.Empty) returns (CanonicalRpcStats) { |
||||||
|
} |
||||||
|
|
||||||
|
// Query the server for specific stats |
||||||
|
rpc GetStats(StatsRequest) returns (StatsResponse) { |
||||||
|
// TODO(aveitch, ericgribkoff): Pease define the stats response message |
||||||
|
// StatsRequest would specifically identify the stats to be returned. |
||||||
|
} |
||||||
|
|
||||||
|
// Request the server to stream back snapshots of the requested stats |
||||||
|
rpc WatchStats(StatsRequest) returns (stream StatsResponse) { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Return request traces. |
||||||
|
rpc GetRequestTraces(TraceRequest) returns(TraceResponse) { |
||||||
|
// TODO(aveitch): Please define the messages here |
||||||
|
} |
||||||
|
|
||||||
|
// Return application-defined groups of monitoring data. |
||||||
|
// This is a low level facility to allow extension of the monitoring API to |
||||||
|
// application-specific monitoring data. Frameworks may use this to define |
||||||
|
// additional groups of monitoring data made available by servers. |
||||||
|
rpc GetCustomMonitoringData(MonitoringDataGroup) |
||||||
|
returns (CustomMonitoringData) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
// Canonical RPC stats exported by gRPC. |
||||||
|
message CanonicalRpcStats { |
||||||
|
// Wrapper combining View and ViewDescriptor. |
||||||
|
message View { |
||||||
|
google.instrumentation.MeasurementDescriptor measurement_descriptor = 1; |
||||||
|
google.instrumentation.ViewDescriptor view_descriptor = 2; |
||||||
|
google.instrumentation.View view = 3; |
||||||
|
} |
||||||
|
|
||||||
|
View rpc_client_errors = 1; |
||||||
|
View rpc_client_completed_rpcs = 2; |
||||||
|
View rpc_client_started_rpcs = 3; |
||||||
|
View rpc_client_elapsed_time = 4; |
||||||
|
View rpc_client_server_elapsed_time = 5; |
||||||
|
View rpc_client_request_bytes = 6; |
||||||
|
View rpc_client_response_bytes = 7; |
||||||
|
View rpc_client_request_count = 8; |
||||||
|
View rpc_client_response_count = 9; |
||||||
|
View rpc_server_errors = 10; |
||||||
|
View rpc_server_completed_rpcs = 11; |
||||||
|
View rpc_server_server_elapsed_time = 12; |
||||||
|
View rpc_server_request_bytes = 13; |
||||||
|
View rpc_server_response_bytes = 14; |
||||||
|
View rpc_server_request_count = 15; |
||||||
|
View rpc_server_response_count = 16; |
||||||
|
View rpc_server_elapsed_time = 17; |
||||||
|
//TODO(ericgribkoff) Add minute-hour interval stats. |
||||||
|
} |
||||||
|
|
||||||
|
message StatsRequest { |
||||||
|
// TODO(aveitch): Complete definition of this type |
||||||
|
} |
||||||
|
|
||||||
|
message StatsResponse { |
||||||
|
// TODO(aveitch): Complete definition of this type |
||||||
|
} |
||||||
|
|
||||||
|
message TraceRequest { |
||||||
|
// TODO(aveitch): Complete definition of this type |
||||||
|
} |
||||||
|
|
||||||
|
message TraceResponse { |
||||||
|
// TODO(aveitch): Complete definition of this type |
||||||
|
} |
||||||
|
|
||||||
|
message MonitoringDataGroup { |
||||||
|
string name = 1; // name of a group of monitoring data |
||||||
|
} |
||||||
|
|
||||||
|
// The wrapper for custom monitoring data. |
||||||
|
message CustomMonitoringData { |
||||||
|
// can be any application specific monitoring data |
||||||
|
Any contents = 1; |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue