mirror of https://github.com/grpc/grpc.git
commit
24c232009c
14 changed files with 469 additions and 34 deletions
@ -0,0 +1,59 @@ |
|||||||
|
# Copyright 2019 The gRPC 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. |
||||||
|
|
||||||
|
load("@grpc_python_dependencies//:requirements.bzl", "requirement") |
||||||
|
|
||||||
|
py_binary( |
||||||
|
name = "debug_server", |
||||||
|
testonly = 1, |
||||||
|
srcs = ["debug_server.py"], |
||||||
|
deps = [ |
||||||
|
"//src/python/grpcio/grpc:grpcio", |
||||||
|
"//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", |
||||||
|
"//examples:py_helloworld", |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
py_binary( |
||||||
|
name = "send_message", |
||||||
|
testonly = 1, |
||||||
|
srcs = ["send_message.py"], |
||||||
|
deps = [ |
||||||
|
"//src/python/grpcio/grpc:grpcio", |
||||||
|
"//examples:py_helloworld", |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
py_binary( |
||||||
|
name = "get_stats", |
||||||
|
testonly = 1, |
||||||
|
srcs = ["get_stats.py"], |
||||||
|
deps = [ |
||||||
|
"//src/python/grpcio/grpc:grpcio", |
||||||
|
"//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", |
||||||
|
], |
||||||
|
) |
||||||
|
|
||||||
|
py_test( |
||||||
|
name = "_debug_example_test", |
||||||
|
srcs = ["test/_debug_example_test.py"], |
||||||
|
deps = [ |
||||||
|
"//src/python/grpcio/grpc:grpcio", |
||||||
|
"//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", |
||||||
|
"//examples:py_helloworld", |
||||||
|
":debug_server", |
||||||
|
":send_message", |
||||||
|
":get_stats", |
||||||
|
], |
||||||
|
) |
@ -0,0 +1,68 @@ |
|||||||
|
# gRPC Python Debug Example |
||||||
|
|
||||||
|
This example demonstrate the usage of Channelz. For a better looking website, |
||||||
|
the [gdebug](https://github.com/grpc/grpc-experiments/tree/master/gdebug) uses |
||||||
|
gRPC-Web protocol and will serve all useful information in web pages. |
||||||
|
|
||||||
|
## Channelz: Live Channel Tracing |
||||||
|
|
||||||
|
Channelz is a channel tracing feature. It will track statistics like how many |
||||||
|
messages have been sent, how many of them failed, what are the connected |
||||||
|
sockets. Since it is implemented in C-Core and has low-overhead, it is |
||||||
|
recommended to turn on for production services. See [Channelz design |
||||||
|
doc](https://github.com/grpc/proposal/blob/master/A14-channelz.md). |
||||||
|
|
||||||
|
## How to enable tracing log |
||||||
|
The tracing log generation might have larger overhead, especially when you try |
||||||
|
to trace transport. It would result in replicating the traffic loads. However, |
||||||
|
it is still the most powerful tool when you need to dive in. |
||||||
|
|
||||||
|
### The Most Verbose Tracing Log |
||||||
|
|
||||||
|
Specify environment variables, then run your application: |
||||||
|
|
||||||
|
``` |
||||||
|
GRPC_VERBOSITY=debug |
||||||
|
GRPC_TRACE=all |
||||||
|
``` |
||||||
|
|
||||||
|
For more granularity, please see |
||||||
|
[environment_variables](https://github.com/grpc/grpc/blob/master/doc/environment_variables.md). |
||||||
|
|
||||||
|
### Debug Transport Protocol |
||||||
|
|
||||||
|
``` |
||||||
|
GRPC_VERBOSITY=debug |
||||||
|
GRPC_TRACE=tcp,http,secure_endpoint,transport_security |
||||||
|
``` |
||||||
|
|
||||||
|
### Debug Connection Behavior |
||||||
|
|
||||||
|
``` |
||||||
|
GRPC_VERBOSITY=debug |
||||||
|
GRPC_TRACE=call_error,connectivity_state,pick_first,round_robin,glb |
||||||
|
``` |
||||||
|
|
||||||
|
## How to debug your application? |
||||||
|
|
||||||
|
`pdb` is a debugging tool that is available for Python interpreters natively. |
||||||
|
You can set breakpoint, and execute commands while the application is stopped. |
||||||
|
|
||||||
|
The simplest usage is add a single line in the place you want to inspect: |
||||||
|
`import pdb; pdb.set_trace()`. When interpreter see this line, it would pop out |
||||||
|
a interactive command line interface for you to inspect the application state. |
||||||
|
|
||||||
|
For more detailed usage, see https://docs.python.org/3/library/pdb.html. |
||||||
|
|
||||||
|
**Caveat**: gRPC Python uses C-Extension under-the-hood, so `pdb` may not be |
||||||
|
able to trace through the whole stack. |
||||||
|
|
||||||
|
## gRPC Command Line Tool |
||||||
|
|
||||||
|
`grpc_cli` is a handy tool to interact with gRPC backend easily. Imageine you can |
||||||
|
inspect what service does a server provide without writing any code, and make |
||||||
|
gRPC calls just like `curl`. |
||||||
|
|
||||||
|
The installation guide: https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md#code-location |
||||||
|
The usage guide: https://github.com/grpc/grpc/blob/master/doc/command_line_tool.md#usage |
||||||
|
The source code: https://github.com/grpc/grpc/blob/master/test/cpp/util/grpc_cli.cc |
@ -0,0 +1,90 @@ |
|||||||
|
# Copyright 2019 The gRPC 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. |
||||||
|
"""The Python example of utilizing Channelz feature.""" |
||||||
|
|
||||||
|
from __future__ import absolute_import |
||||||
|
from __future__ import division |
||||||
|
from __future__ import print_function |
||||||
|
|
||||||
|
import argparse |
||||||
|
import logging |
||||||
|
import time |
||||||
|
from concurrent import futures |
||||||
|
import random |
||||||
|
|
||||||
|
import grpc |
||||||
|
from grpc_channelz.v1 import channelz |
||||||
|
|
||||||
|
from examples import helloworld_pb2 |
||||||
|
from examples import helloworld_pb2_grpc |
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__) |
||||||
|
_LOGGER.setLevel(logging.INFO) |
||||||
|
|
||||||
|
_ONE_DAY_IN_SECONDS = 60 * 60 * 24 |
||||||
|
_RANDOM_FAILURE_RATE = 0.3 |
||||||
|
|
||||||
|
|
||||||
|
class FaultInjectGreeter(helloworld_pb2_grpc.GreeterServicer): |
||||||
|
|
||||||
|
def __init__(self, failure_rate): |
||||||
|
self._failure_rate = failure_rate |
||||||
|
|
||||||
|
def SayHello(self, request, context): |
||||||
|
if random.random() < self._failure_rate: |
||||||
|
context.abort(grpc.StatusCode.UNAVAILABLE, |
||||||
|
'Randomly injected failure.') |
||||||
|
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) |
||||||
|
|
||||||
|
|
||||||
|
def create_server(addr, failure_rate): |
||||||
|
server = grpc.server(futures.ThreadPoolExecutor()) |
||||||
|
helloworld_pb2_grpc.add_GreeterServicer_to_server( |
||||||
|
FaultInjectGreeter(failure_rate), server) |
||||||
|
|
||||||
|
# Add Channelz Servicer to the gRPC server |
||||||
|
channelz.add_channelz_servicer(server) |
||||||
|
|
||||||
|
server.add_insecure_port(addr) |
||||||
|
return server |
||||||
|
|
||||||
|
|
||||||
|
def main(): |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument( |
||||||
|
'--addr', |
||||||
|
nargs=1, |
||||||
|
type=str, |
||||||
|
default='[::]:50051', |
||||||
|
help='the address to listen on') |
||||||
|
parser.add_argument( |
||||||
|
'--failure_rate', |
||||||
|
nargs=1, |
||||||
|
type=float, |
||||||
|
default=0.3, |
||||||
|
help='a float indicates the percentage of failed message injections') |
||||||
|
args = parser.parse_args() |
||||||
|
|
||||||
|
server = create_server(addr=args.addr, failure_rate=args.failure_rate) |
||||||
|
server.start() |
||||||
|
try: |
||||||
|
while True: |
||||||
|
time.sleep(_ONE_DAY_IN_SECONDS) |
||||||
|
except KeyboardInterrupt: |
||||||
|
server.stop(0) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
logging.basicConfig(level=logging.INFO) |
||||||
|
main() |
@ -0,0 +1,49 @@ |
|||||||
|
# Copyright 2019 The gRPC 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. |
||||||
|
"""Poll statistics from the server.""" |
||||||
|
|
||||||
|
from __future__ import absolute_import |
||||||
|
from __future__ import division |
||||||
|
from __future__ import print_function |
||||||
|
|
||||||
|
import logging |
||||||
|
import argparse |
||||||
|
import grpc |
||||||
|
from grpc_channelz.v1 import channelz_pb2 |
||||||
|
from grpc_channelz.v1 import channelz_pb2_grpc |
||||||
|
|
||||||
|
|
||||||
|
def run(addr): |
||||||
|
with grpc.insecure_channel(addr) as channel: |
||||||
|
channelz_stub = channelz_pb2_grpc.ChannelzStub(channel) |
||||||
|
response = channelz_stub.GetServers( |
||||||
|
channelz_pb2.GetServersRequest(start_server_id=0)) |
||||||
|
print('Info for all servers: %s' % response) |
||||||
|
|
||||||
|
|
||||||
|
def main(): |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument( |
||||||
|
'--addr', |
||||||
|
nargs=1, |
||||||
|
type=str, |
||||||
|
default='[::]:50051', |
||||||
|
help='the address to request') |
||||||
|
args = parser.parse_args() |
||||||
|
run(addr=args.addr) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
logging.basicConfig() |
||||||
|
main() |
@ -0,0 +1,64 @@ |
|||||||
|
# Copyright 2019 The gRPC 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. |
||||||
|
"""Send multiple greeting messages to the backend.""" |
||||||
|
|
||||||
|
from __future__ import absolute_import |
||||||
|
from __future__ import division |
||||||
|
from __future__ import print_function |
||||||
|
|
||||||
|
import logging |
||||||
|
import argparse |
||||||
|
import grpc |
||||||
|
from examples import helloworld_pb2 |
||||||
|
from examples import helloworld_pb2_grpc |
||||||
|
|
||||||
|
|
||||||
|
def process(stub, request): |
||||||
|
try: |
||||||
|
response = stub.SayHello(request) |
||||||
|
except grpc.RpcError as rpc_error: |
||||||
|
print('Received error: %s' % rpc_error) |
||||||
|
else: |
||||||
|
print('Received message: %s' % response) |
||||||
|
|
||||||
|
|
||||||
|
def run(addr, n): |
||||||
|
with grpc.insecure_channel(addr) as channel: |
||||||
|
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||||
|
request = helloworld_pb2.HelloRequest(name='you') |
||||||
|
for _ in range(n): |
||||||
|
process(stub, request) |
||||||
|
|
||||||
|
|
||||||
|
def main(): |
||||||
|
parser = argparse.ArgumentParser() |
||||||
|
parser.add_argument( |
||||||
|
'--addr', |
||||||
|
nargs=1, |
||||||
|
type=str, |
||||||
|
default='[::]:50051', |
||||||
|
help='the address to request') |
||||||
|
parser.add_argument( |
||||||
|
'-n', |
||||||
|
nargs=1, |
||||||
|
type=int, |
||||||
|
default=10, |
||||||
|
help='an integer for number of messages to sent') |
||||||
|
args = parser.parse_args() |
||||||
|
run(addr=args.addr, n=args.n) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
logging.basicConfig() |
||||||
|
main() |
@ -0,0 +1,53 @@ |
|||||||
|
# Copyright 2019 The gRPC 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. |
||||||
|
"""Test for gRPC Python debug example.""" |
||||||
|
|
||||||
|
from __future__ import absolute_import |
||||||
|
from __future__ import division |
||||||
|
from __future__ import print_function |
||||||
|
|
||||||
|
import logging |
||||||
|
import unittest |
||||||
|
|
||||||
|
from examples.python.debug import debug_server |
||||||
|
from examples.python.debug import send_message |
||||||
|
from examples.python.debug import get_stats |
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__) |
||||||
|
_LOGGER.setLevel(logging.INFO) |
||||||
|
|
||||||
|
_FAILURE_RATE = 0.5 |
||||||
|
_NUMBER_OF_MESSAGES = 100 |
||||||
|
|
||||||
|
_ADDR_TEMPLATE = 'localhost:%d' |
||||||
|
|
||||||
|
|
||||||
|
class DebugExampleTest(unittest.TestCase): |
||||||
|
|
||||||
|
def test_channelz_example(self): |
||||||
|
server = debug_server.create_server( |
||||||
|
addr='[::]:0', failure_rate=_FAILURE_RATE) |
||||||
|
port = server.add_insecure_port('[::]:0') |
||||||
|
server.start() |
||||||
|
address = _ADDR_TEMPLATE % port |
||||||
|
|
||||||
|
send_message.run(addr=address, n=_NUMBER_OF_MESSAGES) |
||||||
|
get_stats.run(addr=address) |
||||||
|
server.stop(None) |
||||||
|
# No unhandled exception raised, test passed! |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
logging.basicConfig() |
||||||
|
unittest.main(verbosity=2) |
@ -0,0 +1,22 @@ |
|||||||
|
#!/bin/bash |
||||||
|
# Copyright 2019 gRPC 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. |
||||||
|
|
||||||
|
# This script is used after a release to verify the released pods are working appropriately |
||||||
|
|
||||||
|
set -ex |
||||||
|
|
||||||
|
SCHEME=HelloWorld EXAMPLE_PATH=examples/objective-c/helloworld ./build_one_example.sh |
||||||
|
SCHEME=RouteGuideClient EXAMPLE_PATH=examples/objective-c/route_guide ./build_one_example.sh |
||||||
|
SCHEME=AuthSample EXAMPLE_PATH=examples/objective-c/auth_sample ./build_one_example.sh |
Loading…
Reference in new issue