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