From 1f772fab70249b0742677050f066006bd4e1a692 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 10 Mar 2020 10:50:49 -0700 Subject: [PATCH 01/59] Add package boilerplate --- ext/opentelemetry-ext-grpc/CHANGELOG.md | 0 ext/opentelemetry-ext-grpc/README.rst | 0 ext/opentelemetry-ext-grpc/setup.cfg | 0 ext/opentelemetry-ext-grpc/setup.py | 0 ext/opentelemetry-ext-grpc/version.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ext/opentelemetry-ext-grpc/CHANGELOG.md create mode 100644 ext/opentelemetry-ext-grpc/README.rst create mode 100644 ext/opentelemetry-ext-grpc/setup.cfg create mode 100644 ext/opentelemetry-ext-grpc/setup.py create mode 100644 ext/opentelemetry-ext-grpc/version.py diff --git a/ext/opentelemetry-ext-grpc/CHANGELOG.md b/ext/opentelemetry-ext-grpc/CHANGELOG.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ext/opentelemetry-ext-grpc/README.rst b/ext/opentelemetry-ext-grpc/README.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ext/opentelemetry-ext-grpc/setup.cfg b/ext/opentelemetry-ext-grpc/setup.cfg new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ext/opentelemetry-ext-grpc/setup.py b/ext/opentelemetry-ext-grpc/setup.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ext/opentelemetry-ext-grpc/version.py b/ext/opentelemetry-ext-grpc/version.py new file mode 100644 index 00000000000..e69de29bb2d From 3377e9e50800e1c01e2fd73a30f85fbf7d25b7ae Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 10 Mar 2020 11:11:19 -0700 Subject: [PATCH 02/59] Copy OC examples --- .../examples/examples/hello_world.proto | 37 +++++ .../examples/examples/hello_world_client.py | 42 ++++++ .../examples/examples/hello_world_pb2.py | 137 ++++++++++++++++++ .../examples/examples/hello_world_pb2_grpc.py | 48 ++++++ .../examples/examples/hello_world_server.py | 54 +++++++ 5 files changed, 318 insertions(+) create mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto create mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py create mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py create mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py create mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto b/ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto new file mode 100644 index 00000000000..a27173a2ee4 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto @@ -0,0 +1,37 @@ +// Copyright 2019, OpenTelemetry 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. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; + +package helloworld; + +// The hello world service definition. +service Greeter { + // Say hello to the request sender (unary-unary) + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the sender's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py new file mode 100644 index 00000000000..5f521d91975 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py @@ -0,0 +1,42 @@ +# Copyright 2019, OpenTelemetry 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. + +from __future__ import print_function + +import grpc + +import hello_world_pb2 +import hello_world_pb2_grpc +from opencensus.ext.grpc import client_interceptor +from opencensus.ext.stackdriver import trace_exporter as stackdriver_exporter +from opencensus.trace.tracer import Tracer + +HOST_PORT = 'localhost:50051' + + +def main(): + exporter = stackdriver_exporter.StackdriverExporter() + tracer = Tracer(exporter=exporter) + tracer_interceptor = client_interceptor.OpenCensusClientInterceptor( + tracer, + host_port=HOST_PORT) + channel = grpc.insecure_channel(HOST_PORT) + channel = grpc.intercept_channel(channel, tracer_interceptor) + stub = hello_world_pb2_grpc.GreeterStub(channel) + response = stub.SayHello(hello_world_pb2.HelloRequest(name='you')) + print("Message received: " + response.message) + + +if __name__ == '__main__': + main() diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py new file mode 100644 index 00000000000..b67e7f718d7 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py @@ -0,0 +1,137 @@ +# flake8: noqa +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: hello_world.proto + +import sys + +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pb2 +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='hello_world.proto', + package='helloworld', + syntax='proto3', + serialized_pb=_b('\n\x11hello_world.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x30\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\x62\x06proto3') +) + + + + +_HELLOREQUEST = _descriptor.Descriptor( + name='HelloRequest', + full_name='helloworld.HelloRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='helloworld.HelloRequest.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=33, + serialized_end=61, +) + + +_HELLOREPLY = _descriptor.Descriptor( + name='HelloReply', + full_name='helloworld.HelloReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message', full_name='helloworld.HelloReply.message', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=63, + serialized_end=92, +) + +DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST +DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( + DESCRIPTOR = _HELLOREQUEST, + __module__ = 'hello_world_pb2' + # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) + )) +_sym_db.RegisterMessage(HelloRequest) + +HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( + DESCRIPTOR = _HELLOREPLY, + __module__ = 'hello_world_pb2' + # @@protoc_insertion_point(class_scope:helloworld.HelloReply) + )) +_sym_db.RegisterMessage(HelloReply) + + +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001')) + +_GREETER = _descriptor.ServiceDescriptor( + name='Greeter', + full_name='helloworld.Greeter', + file=DESCRIPTOR, + index=0, + options=None, + serialized_start=94, + serialized_end=167, + methods=[ + _descriptor.MethodDescriptor( + name='SayHello', + full_name='helloworld.Greeter.SayHello', + index=0, + containing_service=None, + input_type=_HELLOREQUEST, + output_type=_HELLOREPLY, + options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_GREETER) + +DESCRIPTOR.services_by_name['Greeter'] = _GREETER + +# @@protoc_insertion_point(module_scope) diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py new file mode 100644 index 00000000000..66108f48ed0 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py @@ -0,0 +1,48 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import hello_world_pb2 as hello__world__pb2 + + +class GreeterStub(object): + """The hello world service definition. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.SayHello = channel.unary_unary( + '/helloworld.Greeter/SayHello', + request_serializer=hello__world__pb2.HelloRequest. + SerializeToString, + response_deserializer=hello__world__pb2.HelloReply.FromString, + ) + + +class GreeterServicer(object): + """The hello world service definition. + """ + + def SayHello(self, request, context): + """Say hello to the request sender (unary-unary) + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': + grpc.unary_unary_rpc_method_handler( + servicer.SayHello, + request_deserializer=hello__world__pb2.HelloRequest.FromString, + response_serializer=hello__world__pb2.HelloReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'helloworld.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler, )) diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py new file mode 100644 index 00000000000..4a2a957d487 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py @@ -0,0 +1,54 @@ +# Copyright 2019, OpenTelemetry 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. + +import time +from concurrent import futures + +import grpc + +import hello_world_pb2 +import hello_world_pb2_grpc +from opencensus.ext.grpc import server_interceptor +from opencensus.ext.stackdriver import trace_exporter as stackdriver_exporter +from opencensus.trace import samplers + +_ONE_DAY_IN_SECONDS = 60 * 60 * 24 + + +class HelloWorld(hello_world_pb2_grpc.GreeterServicer): + + def SayHello(self, request, context): + return hello_world_pb2.HelloReply(message='Hello, %s!' % request.name) + + +def serve(): + sampler = samplers.AlwaysOnSampler() + exporter = stackdriver_exporter.StackdriverExporter() + tracer_interceptor = server_interceptor.OpenCensusServerInterceptor( + sampler, exporter) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=10), + interceptors=(tracer_interceptor,)) + hello_world_pb2_grpc.add_GreeterServicer_to_server(HelloWorld(), server) + server.add_insecure_port('[::]:50051') + server.start() + try: + while True: + time.sleep(_ONE_DAY_IN_SECONDS) + except KeyboardInterrupt: + server.stop(0) + + +if __name__ == '__main__': + serve() From 38bb4ef6b854495dd9d44d87dec45820a0e7d73b Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 10 Mar 2020 15:13:09 -0700 Subject: [PATCH 03/59] Move examples, add boilerplate --- .../examples/examples/hello_world.proto | 37 ----- .../examples/examples/hello_world_client.py | 42 ------ .../examples/examples/hello_world_pb2.py | 137 ------------------ .../examples/examples/hello_world_pb2_grpc.py | 48 ------ .../examples/examples/hello_world_server.py | 54 ------- ext/opentelemetry-ext-grpc/setup.cfg | 46 ++++++ ext/opentelemetry-ext-grpc/setup.py | 27 ++++ .../src/opentelemetry/ext/grpc/version.py | 15 ++ ext/opentelemetry-ext-grpc/version.py | 0 9 files changed, 88 insertions(+), 318 deletions(-) delete mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto delete mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py delete mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py delete mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py delete mode 100644 ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py delete mode 100644 ext/opentelemetry-ext-grpc/version.py diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto b/ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto deleted file mode 100644 index a27173a2ee4..00000000000 --- a/ext/opentelemetry-ext-grpc/examples/examples/hello_world.proto +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2019, OpenTelemetry 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. - -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "io.grpc.examples.helloworld"; -option java_outer_classname = "HelloWorldProto"; - -package helloworld; - -// The hello world service definition. -service Greeter { - // Say hello to the request sender (unary-unary) - rpc SayHello (HelloRequest) returns (HelloReply) {} -} - -// The request message containing the sender's name. -message HelloRequest { - string name = 1; -} - -// The response message containing the greetings -message HelloReply { - string message = 1; -} diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py deleted file mode 100644 index 5f521d91975..00000000000 --- a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_client.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2019, OpenTelemetry 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. - -from __future__ import print_function - -import grpc - -import hello_world_pb2 -import hello_world_pb2_grpc -from opencensus.ext.grpc import client_interceptor -from opencensus.ext.stackdriver import trace_exporter as stackdriver_exporter -from opencensus.trace.tracer import Tracer - -HOST_PORT = 'localhost:50051' - - -def main(): - exporter = stackdriver_exporter.StackdriverExporter() - tracer = Tracer(exporter=exporter) - tracer_interceptor = client_interceptor.OpenCensusClientInterceptor( - tracer, - host_port=HOST_PORT) - channel = grpc.insecure_channel(HOST_PORT) - channel = grpc.intercept_channel(channel, tracer_interceptor) - stub = hello_world_pb2_grpc.GreeterStub(channel) - response = stub.SayHello(hello_world_pb2.HelloRequest(name='you')) - print("Message received: " + response.message) - - -if __name__ == '__main__': - main() diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py deleted file mode 100644 index b67e7f718d7..00000000000 --- a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2.py +++ /dev/null @@ -1,137 +0,0 @@ -# flake8: noqa -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: hello_world.proto - -import sys - -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pb2 -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='hello_world.proto', - package='helloworld', - syntax='proto3', - serialized_pb=_b('\n\x11hello_world.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x30\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\x62\x06proto3') -) - - - - -_HELLOREQUEST = _descriptor.Descriptor( - name='HelloRequest', - full_name='helloworld.HelloRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='name', full_name='helloworld.HelloRequest.name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=33, - serialized_end=61, -) - - -_HELLOREPLY = _descriptor.Descriptor( - name='HelloReply', - full_name='helloworld.HelloReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='message', full_name='helloworld.HelloReply.message', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=63, - serialized_end=92, -) - -DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST -DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( - DESCRIPTOR = _HELLOREQUEST, - __module__ = 'hello_world_pb2' - # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) - )) -_sym_db.RegisterMessage(HelloRequest) - -HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict( - DESCRIPTOR = _HELLOREPLY, - __module__ = 'hello_world_pb2' - # @@protoc_insertion_point(class_scope:helloworld.HelloReply) - )) -_sym_db.RegisterMessage(HelloReply) - - -DESCRIPTOR.has_options = True -DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001')) - -_GREETER = _descriptor.ServiceDescriptor( - name='Greeter', - full_name='helloworld.Greeter', - file=DESCRIPTOR, - index=0, - options=None, - serialized_start=94, - serialized_end=167, - methods=[ - _descriptor.MethodDescriptor( - name='SayHello', - full_name='helloworld.Greeter.SayHello', - index=0, - containing_service=None, - input_type=_HELLOREQUEST, - output_type=_HELLOREPLY, - options=None, - ), -]) -_sym_db.RegisterServiceDescriptor(_GREETER) - -DESCRIPTOR.services_by_name['Greeter'] = _GREETER - -# @@protoc_insertion_point(module_scope) diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py deleted file mode 100644 index 66108f48ed0..00000000000 --- a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_pb2_grpc.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -import hello_world_pb2 as hello__world__pb2 - - -class GreeterStub(object): - """The hello world service definition. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.SayHello = channel.unary_unary( - '/helloworld.Greeter/SayHello', - request_serializer=hello__world__pb2.HelloRequest. - SerializeToString, - response_deserializer=hello__world__pb2.HelloReply.FromString, - ) - - -class GreeterServicer(object): - """The hello world service definition. - """ - - def SayHello(self, request, context): - """Say hello to the request sender (unary-unary) - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_GreeterServicer_to_server(servicer, server): - rpc_method_handlers = { - 'SayHello': - grpc.unary_unary_rpc_method_handler( - servicer.SayHello, - request_deserializer=hello__world__pb2.HelloRequest.FromString, - response_serializer=hello__world__pb2.HelloReply.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'helloworld.Greeter', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler, )) diff --git a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py b/ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py deleted file mode 100644 index 4a2a957d487..00000000000 --- a/ext/opentelemetry-ext-grpc/examples/examples/hello_world_server.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2019, OpenTelemetry 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. - -import time -from concurrent import futures - -import grpc - -import hello_world_pb2 -import hello_world_pb2_grpc -from opencensus.ext.grpc import server_interceptor -from opencensus.ext.stackdriver import trace_exporter as stackdriver_exporter -from opencensus.trace import samplers - -_ONE_DAY_IN_SECONDS = 60 * 60 * 24 - - -class HelloWorld(hello_world_pb2_grpc.GreeterServicer): - - def SayHello(self, request, context): - return hello_world_pb2.HelloReply(message='Hello, %s!' % request.name) - - -def serve(): - sampler = samplers.AlwaysOnSampler() - exporter = stackdriver_exporter.StackdriverExporter() - tracer_interceptor = server_interceptor.OpenCensusServerInterceptor( - sampler, exporter) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=10), - interceptors=(tracer_interceptor,)) - hello_world_pb2_grpc.add_GreeterServicer_to_server(HelloWorld(), server) - server.add_insecure_port('[::]:50051') - server.start() - try: - while True: - time.sleep(_ONE_DAY_IN_SECONDS) - except KeyboardInterrupt: - server.stop(0) - - -if __name__ == '__main__': - serve() diff --git a/ext/opentelemetry-ext-grpc/setup.cfg b/ext/opentelemetry-ext-grpc/setup.cfg index e69de29bb2d..83d479c8db5 100644 --- a/ext/opentelemetry-ext-grpc/setup.cfg +++ b/ext/opentelemetry-ext-grpc/setup.cfg @@ -0,0 +1,46 @@ +# Copyright 2020, OpenTelemetry 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. + +[metadata] +name = opentelemetry-ext-grpc +description = OpenTelemetry gRPC Integration +long_description = file: README.rst +long_description_content_type = text/x-rst +author = OpenTelemetry Authors +author_email = cncf-opentelemetry-contributors@lists.cncf.io +url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-ext-grpc +platforms = any +license = Apache-2.0 +classifiers = + Development Status :: 3 - Alpha + Intended Audience :: Developers + License :: OSI Approved :: Apache Software License + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + +[options] +python_requires = >=3.4 +package_dir= + =src +packages=find_namespace: +install_requires = + opentelemetry-api + grpcio~=1.27 + +[options.packages.find] +where = src diff --git a/ext/opentelemetry-ext-grpc/setup.py b/ext/opentelemetry-ext-grpc/setup.py index e69de29bb2d..98c35654b77 100644 --- a/ext/opentelemetry-ext-grpc/setup.py +++ b/ext/opentelemetry-ext-grpc/setup.py @@ -0,0 +1,27 @@ +# Copyright 2020, OpenTelemetry 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. + +import os + +import setuptools + +BASE_DIR = os.path.dirname(__file__) +VERSION_FILENAME = os.path.join( + BASE_DIR, "src", "opentelemetry", "ext", "grpc", "version.py" +) +PACKAGE_INFO = {} +with open(VERSION_FILENAME) as f: + exec(f.read(), PACKAGE_INFO) + +setuptools.setup(version=PACKAGE_INFO["__version__"]) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py new file mode 100644 index 00000000000..f48cb5bee5c --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py @@ -0,0 +1,15 @@ +# Copyright 2020, OpenTelemetry 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. + +__version__ = "0.5.dev0" diff --git a/ext/opentelemetry-ext-grpc/version.py b/ext/opentelemetry-ext-grpc/version.py deleted file mode 100644 index e69de29bb2d..00000000000 From 7182f3df5aa25e2398bf5852db5c3c9e1c1f4446 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 10 Mar 2020 15:13:59 -0700 Subject: [PATCH 04/59] Add stub client and server interceptors --- .../ext/grpc/client_interceptor.py | 216 ++++++++++++++++++ .../ext/grpc/server_interceptor.py | 21 ++ 2 files changed, 237 insertions(+) create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py new file mode 100644 index 00000000000..fbb79118f8c --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py @@ -0,0 +1,216 @@ +# Copyright 2020, OpenTelemetry 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. + +from grpc.framework.foundation import future +from grpc.framework.interfaces.face import face +import collections + +import grpc + + +class _ClientCallDetails( + collections.namedtuple( + "_ClientCallDetails", ("method", "timeout", "metadata", "credentials") + ), + grpc.ClientCallDetails, +): + pass + + +# https://github.com/c24t/grpc/blob/50619a562f50ef7ee680ed5ce35de94b5a3b1539/src/python/grpcio/grpc/__init__.py#L561 +# https://github.com/census-instrumentation/opencensus-python/pull/617/files#diff-16ff5c7896222cfa69b7aed98860f7d3R50 +class WrappedResponseIterator(future.Future, face.Call): + """Wraps the rpc response iterator. + + The grpc.StreamStreamClientInterceptor abstract class states stream + interceptor method should return an object that's both a call (implementing + the response iterator) and a future. Thus, this class is a thin wrapper + around the rpc response to provide the opencensus extension. + + :type iterator: (future.Future, face.Call) + :param iterator: rpc response iterator + + :type span: opencensus.trace.Span + :param span: rpc span + """ + def __init__(self, iterator, span): + self._iterator = iterator + self._span = span + + # TODO + # self._messages_received = 0 + + def add_done_callback(self, fn): + self._iterator.add_done_callback(lambda ignored_callback: fn(self)) + + def __iter__(self): + return self + + def __next__(self): + try: + message = next(self._iterator) + except StopIteration: + print("end wrapper iterator") + # execution_context.get_opencensus_tracer().end_span() + raise + + # self._messages_received += 1 + # add_message_event( + # proto_message=message, + # span=self._span, + # message_event_type=time_event.Type.RECEIVED, + # message_id=self._messages_received) + + return message + + def next(self): + return self.__next__() + + def cancel(self): + return self._iterator.cancel() + + def is_active(self): + return self._iterator.is_active() + + def cancelled(self): + raise NotImplementedError() # pragma: NO COVER + + def running(self): + raise NotImplementedError() # pragma: NO COVER + + def done(self): + raise NotImplementedError() # pragma: NO COVER + + def result(self, timeout=None): + raise NotImplementedError() # pragma: NO COVER + + def exception(self, timeout=None): + raise NotImplementedError() # pragma: NO COVER + + def traceback(self, timeout=None): + raise NotImplementedError() # pragma: NO COVER + + def initial_metadata(self): + raise NotImplementedError() # pragma: NO COVER + + def terminal_metadata(self): + raise NotImplementedError() # pragma: NO COVER + + def code(self): + raise NotImplementedError() # pragma: NO COVER + + def details(self): + raise NotImplementedError() # pragma: NO COVER + + def time_remaining(self): + raise NotImplementedError() # pragma: NO COVER + + def add_abortion_callback(self, abortion_callback): + raise NotImplementedError() # pragma: NO COVER + + def protocol_context(self): + raise NotImplementedError() # pragma: NO COVER + + +class OpenTelemetryClientInterceptor( + grpc.UnaryUnaryClientInterceptor, + grpc.UnaryStreamClientInterceptor, + grpc.StreamUnaryClientInterceptor, + grpc.StreamStreamClientInterceptor, +): + def _intercept_call( + self, + client_call_details, + request_iterator, + request_streaming, + response_streaming, + ): + span = "span" + print('intercepted client: start span "{}"'.format(span)) + return client_call_details, request_iterator, "span" + + def _callback(self, span): + def callback(future_response): + print('intercepted client: end span "{}"'.format(span)) + + # TODO + # grpc_utils.add_message_event( + # proto_message=future_response.result(), + # span=current_span, + # message_event_type=time_event.Type.RECEIVED, + # ) + # self._trace_future_exception(future_response) + # self.tracer.end_span() + + return callback + + def intercept_unary_unary( + self, continuation, client_call_details, request + ): + new_details, new_request, current_span = self._intercept_call( + client_call_details=client_call_details, + request_iterator=iter((request,)), + request_streaming=False, + response_streaming=False, + ) + + response = continuation(new_details, next(new_request)) + + response.add_done_callback(self._callback(current_span)) + + return response + + def intercept_unary_stream( + self, continuation, client_call_details, request + ): + new_details, new_request_iterator, current_span = self._intercept_call( + client_call_details=client_call_details, + request_iterator=iter((request,)), + request_streaming=False, + response_streaming=True, + ) + + return WrappedResponseIterator( + continuation(new_details, next(new_request_iterator)), current_span + ) + + def intercept_stream_unary( + self, continuation, client_call_details, request_iterator + ): + new_details, new_request_iterator, current_span = self._intercept_call( + client_call_details=client_call_details, + request_iterator=request_iterator, + request_streaming=True, + response_streaming=False, + ) + + response = continuation(new_details, new_request_iterator) + + response.add_done_callback(self._callback(current_span)) + + return response + + def intercept_stream_stream( + self, continuation, client_call_details, request_iterator + ): + new_details, new_request_iterator, current_span = self._intercept_call( + client_call_details=client_call_details, + request_iterator=request_iterator, + request_streaming=True, + response_streaming=True, + ) + + return WrappedResponseIterator( + continuation(new_details, new_request_iterator), current_span + ) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py new file mode 100644 index 00000000000..e0fe07b0417 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py @@ -0,0 +1,21 @@ +# Copyright 2020, OpenTelemetry 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. + +import grpc + + +class OpenTelemetryServerInterceptor(grpc.ServerInterceptor): + def intercept_service(self, continuation, handler_call_details): + print("intercepted server") + return continuation(handler_call_details) From 9e4cbcae686e60766dc84fdf3772fbcb2c0f8cc2 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 10 Mar 2020 15:14:40 -0700 Subject: [PATCH 05/59] Add gRPC unary examples --- .../examples/codegen.py | 26 ++++ .../examples/hello_world_client.py | 46 ++++++ .../examples/hello_world_server.py | 50 +++++++ .../examples/helloworld.proto | 35 +++++ .../examples/helloworld_pb2.py | 132 ++++++++++++++++++ .../examples/helloworld_pb2_grpc.py | 46 ++++++ 6 files changed, 335 insertions(+) create mode 100755 ext/opentelemetry-ext-grpc/examples/codegen.py create mode 100755 ext/opentelemetry-ext-grpc/examples/hello_world_client.py create mode 100755 ext/opentelemetry-ext-grpc/examples/hello_world_server.py create mode 100644 ext/opentelemetry-ext-grpc/examples/helloworld.proto create mode 100644 ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py create mode 100644 ext/opentelemetry-ext-grpc/examples/helloworld_pb2_grpc.py diff --git a/ext/opentelemetry-ext-grpc/examples/codegen.py b/ext/opentelemetry-ext-grpc/examples/codegen.py new file mode 100755 index 00000000000..6e2afcb347e --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/codegen.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# Copyright 2020, OpenTelemetry 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. + +from grpc_tools import protoc + + +def main(): + return protoc.main( + ["-I.", "--python_out=.", "--grpc_python_out=.", "helloworld.proto"] + ) + + +if __name__ == "__main__": + main() diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_client.py b/ext/opentelemetry-ext-grpc/examples/hello_world_client.py new file mode 100755 index 00000000000..7e446c439a7 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_client.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# Copyright 2020, OpenTelemetry 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. + +# https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_client.py +# https://github.com/grpc/grpc/blob/v1.16.x/examples/python/interceptors/default_value/greeter_client.py +"""The Python implementation of the GRPC helloworld.Greeter client.""" + +import logging + +import grpc + +import helloworld_pb2 +import helloworld_pb2_grpc +from opentelemetry.ext.grpc import client_interceptor + +interceptor = client_interceptor.OpenTelemetryClientInterceptor() + + +def run(): + # NOTE(gRPC Python Team): .close() is possible on a channel and should be + # used in circumstances in which the with statement does not fit the needs + # of the code. + with grpc.insecure_channel("localhost:50051") as channel: + + intercepted_channel = grpc.intercept_channel(channel, interceptor) + stub = helloworld_pb2_grpc.GreeterStub(intercepted_channel) + + response = stub.SayHello(helloworld_pb2.HelloRequest(name="YOU")) + print("Greeter client received: " + response.message) + + +if __name__ == "__main__": + logging.basicConfig() + run() diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py new file mode 100755 index 00000000000..03573fe56e2 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# Copyright 2020, OpenTelemetry 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. + +# https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py +"""The Python implementation of the GRPC helloworld.Greeter server.""" + +import logging +from concurrent import futures + +import grpc + +import helloworld_pb2 +import helloworld_pb2_grpc +from opentelemetry.ext.grpc import server_interceptor + + +class Greeter(helloworld_pb2_grpc.GreeterServicer): + + def SayHello(self, request, context): + return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) + + +def serve(): + + interceptor = server_interceptor.OpenTelemetryServerInterceptor() + # server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), + interceptors=(interceptor,)) + + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) + server.add_insecure_port('[::]:50051') + server.start() + server.wait_for_termination() + + +if __name__ == '__main__': + logging.basicConfig() + serve() diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld.proto b/ext/opentelemetry-ext-grpc/examples/helloworld.proto new file mode 100644 index 00000000000..a2313bd81c6 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/helloworld.proto @@ -0,0 +1,35 @@ +// Copyright 2020, OpenTelemetry 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. + +// https://github.com/grpc/grpc/blob/master/examples/protos/helloworld.proto + +syntax = "proto3"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py b/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py new file mode 100644 index 00000000000..14f6f161da5 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: helloworld.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='helloworld.proto', + package='helloworld', + syntax='proto3', + serialized_options=b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW', + serialized_pb=b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3' +) + + + + +_HELLOREQUEST = _descriptor.Descriptor( + name='HelloRequest', + full_name='helloworld.HelloRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='helloworld.HelloRequest.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=32, + serialized_end=60, +) + + +_HELLOREPLY = _descriptor.Descriptor( + name='HelloReply', + full_name='helloworld.HelloReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message', full_name='helloworld.HelloReply.message', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=62, + serialized_end=91, +) + +DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST +DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), { + 'DESCRIPTOR' : _HELLOREQUEST, + '__module__' : 'helloworld_pb2' + # @@protoc_insertion_point(class_scope:helloworld.HelloRequest) + }) +_sym_db.RegisterMessage(HelloRequest) + +HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), { + 'DESCRIPTOR' : _HELLOREPLY, + '__module__' : 'helloworld_pb2' + # @@protoc_insertion_point(class_scope:helloworld.HelloReply) + }) +_sym_db.RegisterMessage(HelloReply) + + +DESCRIPTOR._options = None + +_GREETER = _descriptor.ServiceDescriptor( + name='Greeter', + full_name='helloworld.Greeter', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=93, + serialized_end=166, + methods=[ + _descriptor.MethodDescriptor( + name='SayHello', + full_name='helloworld.Greeter.SayHello', + index=0, + containing_service=None, + input_type=_HELLOREQUEST, + output_type=_HELLOREPLY, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_GREETER) + +DESCRIPTOR.services_by_name['Greeter'] = _GREETER + +# @@protoc_insertion_point(module_scope) diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld_pb2_grpc.py b/ext/opentelemetry-ext-grpc/examples/helloworld_pb2_grpc.py new file mode 100644 index 00000000000..18e07d16797 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/helloworld_pb2_grpc.py @@ -0,0 +1,46 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import helloworld_pb2 as helloworld__pb2 + + +class GreeterStub(object): + """The greeting service definition. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.SayHello = channel.unary_unary( + '/helloworld.Greeter/SayHello', + request_serializer=helloworld__pb2.HelloRequest.SerializeToString, + response_deserializer=helloworld__pb2.HelloReply.FromString, + ) + + +class GreeterServicer(object): + """The greeting service definition. + """ + + def SayHello(self, request, context): + """Sends a greeting + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler( + servicer.SayHello, + request_deserializer=helloworld__pb2.HelloRequest.FromString, + response_serializer=helloworld__pb2.HelloReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'helloworld.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) From 72a8247f7f7d5ead3df4bb13e6253049647a2e99 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 11 Mar 2020 16:00:22 -0700 Subject: [PATCH 06/59] Add stub docs --- docs/ext/grpc/grpc.client_interceptor.rst | 7 +++++++ docs/ext/grpc/grpc.rst | 17 +++++++++++++++++ docs/ext/grpc/grpc.server_interceptor.rst | 7 +++++++ ext/opentelemetry-ext-grpc/README.rst | 16 ++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 docs/ext/grpc/grpc.client_interceptor.rst create mode 100644 docs/ext/grpc/grpc.rst create mode 100644 docs/ext/grpc/grpc.server_interceptor.rst diff --git a/docs/ext/grpc/grpc.client_interceptor.rst b/docs/ext/grpc/grpc.client_interceptor.rst new file mode 100644 index 00000000000..46de43810ac --- /dev/null +++ b/docs/ext/grpc/grpc.client_interceptor.rst @@ -0,0 +1,7 @@ +grpc.client\_interceptor module +=============================== + +.. automodule:: opentelemetry.ext.grpc.client_interceptor + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/ext/grpc/grpc.rst b/docs/ext/grpc/grpc.rst new file mode 100644 index 00000000000..7e7d5f54264 --- /dev/null +++ b/docs/ext/grpc/grpc.rst @@ -0,0 +1,17 @@ +.. include:: ../../../ext/opentelemetry-ext-grpc/README.rst + +Submodules +---------- + +.. toctree:: + + grpc.client_interceptor + grpc.server_interceptor + +Module contents +--------------- + +.. automodule:: opentelemetry.ext.grpc + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/ext/grpc/grpc.server_interceptor.rst b/docs/ext/grpc/grpc.server_interceptor.rst new file mode 100644 index 00000000000..b51ae1a7cb8 --- /dev/null +++ b/docs/ext/grpc/grpc.server_interceptor.rst @@ -0,0 +1,7 @@ +grpc.server\_interceptor module +=============================== + +.. automodule:: opentelemetry.ext.grpc.server_interceptor + :members: + :undoc-members: + :show-inheritance: diff --git a/ext/opentelemetry-ext-grpc/README.rst b/ext/opentelemetry-ext-grpc/README.rst index e69de29bb2d..c00f2f24f5d 100644 --- a/ext/opentelemetry-ext-grpc/README.rst +++ b/ext/opentelemetry-ext-grpc/README.rst @@ -0,0 +1,16 @@ +OpenTelemetry gRPC Integration +============================== + +|pypi| + +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-ext-grpc.svg + :target: https://pypi.org/project/opentelemetry-ext-grpc/ + +gRPC support! + +Installation +------------ + +:: + + pip install opentelemetry-ext-grpc From d09a0e95dad7c5c5d20102e570f9b970e20a89c0 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 11 Mar 2020 19:06:14 -0700 Subject: [PATCH 07/59] Add unary server interceptor logic --- .../ext/grpc/server_interceptor.py | 79 ++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py index e0fe07b0417..7ba3c7ba746 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py @@ -14,8 +14,83 @@ import grpc +from opentelemetry import trace + class OpenTelemetryServerInterceptor(grpc.ServerInterceptor): + """gRPC service interceptor that wraps each incoming request in a span. + + Usage:: + + from opentelemetry.ext.grpc.server_interceptor import ( + OpenTelemetryServerInterceptor + ) + + ot_interceptor = OpenTelemetryServerInterceptor(tracer) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=10), + interceptors=(interceptor,) + ) + ... + server.start() + + + Args: + tracer: The tracer to use to create spans. + """ + + def __init__(self, tracer: trace.Tracer): + self._tracer = tracer + def intercept_service(self, continuation, handler_call_details): - print("intercepted server") - return continuation(handler_call_details) + def trace_wrapper(behavior, request_streaming, response_streaming): + """A grpc.RpcMethodHandler that wraps behavoir.""" + + def new_behavior(request_or_iterator, servicer_context): + """Wrap behavoir in a span.""" + with self._tracer.start_as_current_span( + _get_span_name(servicer_context), + kind=trace.SpanKind.SERVER, + ): + + response_or_iterator = behavior( + request_or_iterator, servicer_context + ) + + return response_or_iterator + + return new_behavior + + handler = continuation(handler_call_details) + + if handler.request_streaming and handler.response_streaming: + behavior_fn = handler.stream_stream + handler_factory = grpc.stream_stream_rpc_method_handler + elif handler.request_streaming and not handler.response_streaming: + behavior_fn = handler.stream_unary + handler_factory = grpc.stream_unary_rpc_method_handler + elif not handler.request_streaming and handler.response_streaming: + behavior_fn = handler.unary_stream + handler_factory = grpc.unary_stream_rpc_method_handler + else: + behavior_fn = handler.unary_unary + handler_factory = grpc.unary_unary_rpc_method_handler + + new_handler = handler_factory( + trace_wrapper( + behavior_fn, + handler.request_streaming, + handler.response_streaming, + ), + request_deserializer=handler.request_deserializer, + response_serializer=handler.response_serializer, + ) + return new_handler + + +def _get_span_name(servicer_context): + """Get the gRPC servicer method name to use as the span name.""" + method_name = servicer_context._rpc_event.call_details.method[1:] + if isinstance(method_name, bytes): + method_name = method_name.decode("utf-8") + return method_name From d11b855a738c0a8d8ed2724276b2e460c59e5368 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 11 Mar 2020 19:11:00 -0700 Subject: [PATCH 08/59] Extend server example --- .../examples/hello_world_server.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py index 03573fe56e2..13bbf8bd08c 100755 --- a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py @@ -23,28 +23,39 @@ import helloworld_pb2 import helloworld_pb2_grpc +from opentelemetry import trace from opentelemetry.ext.grpc import server_interceptor +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, +) +trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) +trace.tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) +) +tracer = trace.get_tracer(__name__) -class Greeter(helloworld_pb2_grpc.GreeterServicer): +class Greeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): - return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) + return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name) def serve(): - interceptor = server_interceptor.OpenTelemetryServerInterceptor() - # server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), - interceptors=(interceptor,)) + interceptor = server_interceptor.OpenTelemetryServerInterceptor(tracer) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=10), interceptors=(interceptor,) + ) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) - server.add_insecure_port('[::]:50051') + server.add_insecure_port("[::]:50051") server.start() server.wait_for_termination() -if __name__ == '__main__': +if __name__ == "__main__": logging.basicConfig() serve() From 0c33c800ba65b0efb416319148f09b0297e79fa2 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 11 Mar 2020 19:50:41 -0700 Subject: [PATCH 09/59] Add server interceptor tests --- .../tests/test_server_interceptor.py | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py new file mode 100644 index 00000000000..6a89f10ea7d --- /dev/null +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -0,0 +1,190 @@ +# Copyright 2020, OpenTelemetry 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. + +import threading +import unittest +from concurrent import futures +from contextlib import contextmanager +from unittest import mock + +import grpc + +from opentelemetry import trace +from opentelemetry.ext.grpc import server_interceptor +from opentelemetry.sdk import trace as trace_sdk + + +class UnaryUnaryMethodHandler(grpc.RpcMethodHandler): + def __init__(self, handler): + self.request_streaming = False + self.response_streaming = False + self.request_deserializer = None + self.response_serializer = None + self.unary_unary = handler + self.unary_stream = None + self.stream_unary = None + self.stream_stream = None + + +class UnaryUnaryRpcHandler(grpc.GenericRpcHandler): + def __init__(self, handler): + self._unary_unary_handler = handler + + def service(self, handler_call_details): + return UnaryUnaryMethodHandler(self._unary_unary_handler) + + +class TestOpenTelemetryServerInterceptor(unittest.TestCase): + def test_create_span(self): + """Check that the interceptor wraps calls with spans server-side.""" + + @contextmanager + def mock_start_as_current_span(*args, **kwargs): + yield mock.Mock(spec=trace.Span) + + # Intercept gRPC calls... + tracer = mock.Mock(spec=trace.Tracer) + tracer.start_as_current_span.side_effect = mock_start_as_current_span + interceptor = server_interceptor.OpenTelemetryServerInterceptor( + tracer=tracer + ) + + # No-op RPC handler + def handler(request, context): + return b"" + + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=1), + handlers=(UnaryUnaryRpcHandler(handler),), + interceptors=(interceptor,), + options=(("grpc.so_reuseport", 0),), + ) + port = server.add_insecure_port("[::]:0") + channel = grpc.insecure_channel("localhost:{:d}".format(port)) + + try: + server.start() + channel.unary_unary("")(b"") + finally: + server.stop(None) + + tracer.start_as_current_span.assert_called_once_with( + "", kind=trace.SpanKind.SERVER + ) + + def test_span_lifetime(self): + """Check that the span is active for the duration of the call.""" + + tracer_provider = trace_sdk.TracerProvider() + tracer = tracer_provider.get_tracer(__name__) + interceptor = server_interceptor.OpenTelemetryServerInterceptor( + tracer=tracer + ) + + # To capture the current span at the time the handler is called + active_span_in_handler = None + + def handler(request, context): + nonlocal active_span_in_handler + active_span_in_handler = tracer.get_current_span() + return b"" + + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=1), + handlers=(UnaryUnaryRpcHandler(handler),), + interceptors=(interceptor,), + options=(("grpc.so_reuseport", 0),), + ) + port = server.add_insecure_port("[::]:0") + channel = grpc.insecure_channel("localhost:{:d}".format(port)) + + active_span_before_call = tracer.get_current_span() + try: + server.start() + channel.unary_unary("")(b"") + finally: + server.stop(None) + active_span_after_call = tracer.get_current_span() + + self.assertIsNone(active_span_before_call) + self.assertIsNone(active_span_after_call) + self.assertIsInstance(active_span_in_handler, trace_sdk.Span) + self.assertIsNone(active_span_in_handler.parent) + + def test_concurrent_server_spans(self): + """Check that each call gets its own span.""" + + tracer_provider = trace_sdk.TracerProvider() + tracer = tracer_provider.get_tracer(__name__) + interceptor = server_interceptor.OpenTelemetryServerInterceptor( + tracer=tracer + ) + + # Capture the currently active span in each thread + active_spans_in_handler = [] + latch = get_latch(2) + + def handler(request, context): + latch() + active_spans_in_handler.append(tracer.get_current_span()) + return b"" + + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=2), + handlers=(UnaryUnaryRpcHandler(handler),), + interceptors=(interceptor,), + options=(("grpc.so_reuseport", 0),), + ) + port = server.add_insecure_port("[::]:0") + channel = grpc.insecure_channel("localhost:{:d}".format(port)) + + try: + server.start() + # Interleave calls so spans are active on each thread at the same + # time + with futures.ThreadPoolExecutor(max_workers=2) as tpe: + f1 = tpe.submit(channel.unary_unary(""), b"") + f2 = tpe.submit(channel.unary_unary(""), b"") + futures.wait((f1, f2)) + finally: + server.stop(None) + + self.assertEqual(len(active_spans_in_handler), 2) + span1, span2 = active_spans_in_handler + # Spans should belong to separate traces, and each should be a root + # span + self.assertNotEqual(span1.context.span_id, span2.context.span_id) + self.assertNotEqual(span1.context.trace_id, span2.context.trace_id) + self.assertIsNone(span1.parent) + self.assertIsNone(span1.parent) + + +def get_latch(n): + """Get a countdown latch function for use in n threads.""" + cv = threading.Condition() + count = 0 + + def countdown_latch(): + """Block until n-1 other threads have called.""" + nonlocal count + cv.acquire() + count += 1 + cv.notify() + cv.release() + cv.acquire() + while count < n: + cv.wait() + cv.release() + + return countdown_latch From f0b0ba57c65fee7c776f4953b084d5a011a9b9a7 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 11 Mar 2020 19:58:22 -0700 Subject: [PATCH 10/59] TODOs --- .../opentelemetry/ext/grpc/client_interceptor.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py index fbb79118f8c..cfbacffc078 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py @@ -12,11 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -from grpc.framework.foundation import future -from grpc.framework.interfaces.face import face import collections import grpc +from grpc.framework.foundation import future +from grpc.framework.interfaces.face import face class _ClientCallDetails( @@ -28,6 +28,7 @@ class _ClientCallDetails( pass +# TODO # https://github.com/c24t/grpc/blob/50619a562f50ef7ee680ed5ce35de94b5a3b1539/src/python/grpcio/grpc/__init__.py#L561 # https://github.com/census-instrumentation/opencensus-python/pull/617/files#diff-16ff5c7896222cfa69b7aed98860f7d3R50 class WrappedResponseIterator(future.Future, face.Call): @@ -44,6 +45,7 @@ class WrappedResponseIterator(future.Future, face.Call): :type span: opencensus.trace.Span :param span: rpc span """ + def __init__(self, iterator, span): self._iterator = iterator self._span = span @@ -136,13 +138,12 @@ def _intercept_call( request_streaming, response_streaming, ): - span = "span" - print('intercepted client: start span "{}"'.format(span)) - return client_call_details, request_iterator, "span" + # TODO + return client_call_details, request_iterator, None def _callback(self, span): def callback(future_response): - print('intercepted client: end span "{}"'.format(span)) + pass # TODO # grpc_utils.add_message_event( From 483c32f953a13c27e2f10077e797743fda9b5045 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 12 Mar 2020 21:58:46 -0700 Subject: [PATCH 11/59] Missing init --- .../src/opentelemetry/ext/grpc/__init__.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py new file mode 100644 index 00000000000..6ab2e961ec4 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020, OpenTelemetry 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. From 88e946724c20fbcf36d74757aa0a1eecddcb986b Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Fri, 13 Mar 2020 13:14:31 -0700 Subject: [PATCH 12/59] Copy grpc_opentracing --- .../src/opentelemetry/ext/grpc/__init__.py | 109 ++++- .../src/opentelemetry/ext/grpc/_client.py | 209 ++++++++++ .../src/opentelemetry/ext/grpc/_server.py | 237 +++++++++++ .../src/opentelemetry/ext/grpc/_utilities.py | 65 +++ .../ext/grpc/grpcext/__init__.py | 185 +++++++++ .../ext/grpc/grpcext/_interceptor.py | 378 ++++++++++++++++++ 6 files changed, 1170 insertions(+), 13 deletions(-) create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py create mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 6ab2e961ec4..f35e79e86c2 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -1,13 +1,96 @@ -# Copyright 2020, OpenTelemetry 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. +import abc +import enum + +import six + +import grpc + + +class ActiveSpanSource(six.with_metaclass(abc.ABCMeta)): + """Provides a way to access an the active span.""" + + @abc.abstractmethod + def get_active_span(self): + """Identifies the active span. + + Returns: + An object that implements the opentracing.Span interface. + """ + raise NotImplementedError() + + +class RpcInfo(six.with_metaclass(abc.ABCMeta)): + """Provides information for an RPC call. + + Attributes: + full_method: A string of the full RPC method, i.e., /package.service/method. + metadata: The initial :term:`metadata`. + timeout: The length of time in seconds to wait for the computation to + terminate or be cancelled. + request: The RPC request or None for request-streaming RPCs. + response: The RPC response or None for response-streaming or erroring RPCs. + error: The RPC error or None for successful RPCs. + """ + + +class SpanDecorator(six.with_metaclass(abc.ABCMeta)): + """Provides a mechanism to add arbitrary tags/logs/etc to the + opentracing.Span associated with client and/or server RPCs.""" + + @abc.abstractmethod + def __call__(self, span, rpc_info): + """Customizes an RPC span. + + Args: + span: The client-side or server-side opentracing.Span for the RPC. + rpc_info: An RpcInfo describing the RPC. + """ + raise NotImplementedError() + + +def open_tracing_client_interceptor(tracer, + active_span_source=None, + log_payloads=False, + span_decorator=None): + """Creates an invocation-side interceptor that can be use with gRPC to add + OpenTracing information. + + Args: + tracer: An object implmenting the opentracing.Tracer interface. + active_span_source: An optional ActiveSpanSource to customize how the + active span is determined. + log_payloads: Indicates whether requests should be logged. + span_decorator: An optional SpanDecorator. + + Returns: + An invocation-side interceptor object. + """ + from grpc_opentracing import _client + return _client.OpenTracingClientInterceptor(tracer, active_span_source, + log_payloads, span_decorator) + + +def open_tracing_server_interceptor(tracer, + log_payloads=False, + span_decorator=None): + """Creates a service-side interceptor that can be use with gRPC to add + OpenTracing information. + + Args: + tracer: An object implmenting the opentracing.Tracer interface. + log_payloads: Indicates whether requests should be logged. + span_decorator: An optional SpanDecorator. + + Returns: + A service-side interceptor object. + """ + from grpc_opentracing import _server + return _server.OpenTracingServerInterceptor(tracer, log_payloads, + span_decorator) + + +################################### __all__ ################################# + +__all__ = ('ActiveSpanSource', 'RpcInfo', 'SpanDecorator', + 'open_tracing_client_interceptor', + 'open_tracing_server_interceptor',) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py new file mode 100644 index 00000000000..01afb3ed9b5 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -0,0 +1,209 @@ +"""Implementation of the invocation-side open-tracing interceptor.""" + +import sys +import logging +import time + +from six import iteritems + +import grpc +from grpc_opentracing import grpcext +from grpc_opentracing._utilities import get_method_type, get_deadline_millis,\ + log_or_wrap_request_or_iterator, RpcInfo +import opentracing +from opentracing.ext import tags as ot_tags + + +class _GuardedSpan(object): + + def __init__(self, span): + self.span = span + self._engaged = True + + def __enter__(self): + self.span.__enter__() + return self + + def __exit__(self, *args, **kwargs): + if self._engaged: + return self.span.__exit__(*args, **kwargs) + else: + return False + + def release(self): + self._engaged = False + return self.span + + +def _inject_span_context(tracer, span, metadata): + headers = {} + try: + tracer.inject(span.context, opentracing.Format.HTTP_HEADERS, headers) + except (opentracing.UnsupportedFormatException, + opentracing.InvalidCarrierException, + opentracing.SpanContextCorruptedException) as e: + logging.exception('tracer.inject() failed') + span.log_kv({'event': 'error', 'error.object': e}) + return metadata + metadata = () if metadata is None else tuple(metadata) + return metadata + tuple((k.lower(), v) for (k, v) in iteritems(headers)) + + +def _make_future_done_callback(span, rpc_info, log_payloads, span_decorator): + + def callback(response_future): + with span: + code = response_future.code() + if code != grpc.StatusCode.OK: + span.set_tag('error', True) + error_log = {'event': 'error', 'error.kind': str(code)} + details = response_future.details() + if details is not None: + error_log['message'] = details + span.log_kv(error_log) + rpc_info.error = code + if span_decorator is not None: + span_decorator(span, rpc_info) + return + response = response_future.result() + rpc_info.response = response + if log_payloads: + span.log_kv({'response': response}) + if span_decorator is not None: + span_decorator(span, rpc_info) + + return callback + + +class OpenTracingClientInterceptor(grpcext.UnaryClientInterceptor, + grpcext.StreamClientInterceptor): + + def __init__(self, tracer, active_span_source, log_payloads, + span_decorator): + self._tracer = tracer + self._active_span_source = active_span_source + self._log_payloads = log_payloads + self._span_decorator = span_decorator + + def _start_span(self, method): + active_span_context = None + if self._active_span_source is not None: + active_span = self._active_span_source.get_active_span() + if active_span is not None: + active_span_context = active_span.context + tags = { + ot_tags.COMPONENT: 'grpc', + ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_CLIENT + } + return self._tracer.start_span( + operation_name=method, child_of=active_span_context, tags=tags) + + def _trace_result(self, guarded_span, rpc_info, result): + # If the RPC is called asynchronously, release the guard and add a callback + # so that the span can be finished once the future is done. + if isinstance(result, grpc.Future): + result.add_done_callback( + _make_future_done_callback(guarded_span.release( + ), rpc_info, self._log_payloads, self._span_decorator)) + return result + response = result + # Handle the case when the RPC is initiated via the with_call + # method and the result is a tuple with the first element as the + # response. + # http://www.grpc.io/grpc/python/grpc.html#grpc.UnaryUnaryMultiCallable.with_call + if isinstance(result, tuple): + response = result[0] + rpc_info.response = response + if self._log_payloads: + guarded_span.span.log_kv({'response': response}) + if self._span_decorator is not None: + self._span_decorator(guarded_span.span, rpc_info) + return result + + def _start_guarded_span(self, *args, **kwargs): + return _GuardedSpan(self._start_span(*args, **kwargs)) + + def intercept_unary(self, request, metadata, client_info, invoker): + with self._start_guarded_span(client_info.full_method) as guarded_span: + metadata = _inject_span_context(self._tracer, guarded_span.span, + metadata) + rpc_info = RpcInfo( + full_method=client_info.full_method, + metadata=metadata, + timeout=client_info.timeout, + request=request) + if self._log_payloads: + guarded_span.span.log_kv({'request': request}) + try: + result = invoker(request, metadata) + except: + e = sys.exc_info()[0] + guarded_span.span.set_tag('error', True) + guarded_span.span.log_kv({'event': 'error', 'error.object': e}) + rpc_info.error = e + if self._span_decorator is not None: + self._span_decorator(guarded_span.span, rpc_info) + raise + return self._trace_result(guarded_span, rpc_info, result) + + # For RPCs that stream responses, the result can be a generator. To record + # the span across the generated responses and detect any errors, we wrap the + # result in a new generator that yields the response values. + def _intercept_server_stream(self, request_or_iterator, metadata, + client_info, invoker): + with self._start_span(client_info.full_method) as span: + metadata = _inject_span_context(self._tracer, span, metadata) + rpc_info = RpcInfo( + full_method=client_info.full_method, + metadata=metadata, + timeout=client_info.timeout) + if client_info.is_client_stream: + rpc_info.request = request_or_iterator + if self._log_payloads: + request_or_iterator = log_or_wrap_request_or_iterator( + span, client_info.is_client_stream, request_or_iterator) + try: + result = invoker(request_or_iterator, metadata) + for response in result: + if self._log_payloads: + span.log_kv({'response': response}) + yield response + except: + e = sys.exc_info()[0] + span.set_tag('error', True) + span.log_kv({'event': 'error', 'error.object': e}) + rpc_info.error = e + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + raise + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + + def intercept_stream(self, request_or_iterator, metadata, client_info, + invoker): + if client_info.is_server_stream: + return self._intercept_server_stream(request_or_iterator, metadata, + client_info, invoker) + with self._start_guarded_span(client_info.full_method) as guarded_span: + metadata = _inject_span_context(self._tracer, guarded_span.span, + metadata) + rpc_info = RpcInfo( + full_method=client_info.full_method, + metadata=metadata, + timeout=client_info.timeout, + request=request_or_iterator) + if self._log_payloads: + request_or_iterator = log_or_wrap_request_or_iterator( + guarded_span.span, client_info.is_client_stream, + request_or_iterator) + try: + result = invoker(request_or_iterator, metadata) + except: + e = sys.exc_info()[0] + guarded_span.span.set_tag('error', True) + guarded_span.span.log_kv({'event': 'error', 'error.object': e}) + rpc_info.error = e + if self._span_decorator is not None: + self._span_decorator(guarded_span.span, rpc_info) + raise + return self._trace_result(guarded_span, rpc_info, result) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py new file mode 100644 index 00000000000..937a4e83fd1 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -0,0 +1,237 @@ +"""Implementation of the service-side open-tracing interceptor.""" + +import sys +import logging +import re + +import grpc +from grpc_opentracing import grpcext, ActiveSpanSource +from grpc_opentracing._utilities import get_method_type, get_deadline_millis,\ + log_or_wrap_request_or_iterator, RpcInfo +import opentracing +from opentracing.ext import tags as ot_tags + + +class _OpenTracingServicerContext(grpc.ServicerContext, ActiveSpanSource): + + def __init__(self, servicer_context, active_span): + self._servicer_context = servicer_context + self._active_span = active_span + self.code = grpc.StatusCode.OK + self.details = None + + def is_active(self, *args, **kwargs): + return self._servicer_context.is_active(*args, **kwargs) + + def time_remaining(self, *args, **kwargs): + return self._servicer_context.time_remaining(*args, **kwargs) + + def cancel(self, *args, **kwargs): + return self._servicer_context.cancel(*args, **kwargs) + + def add_callback(self, *args, **kwargs): + return self._servicer_context.add_callback(*args, **kwargs) + + def invocation_metadata(self, *args, **kwargs): + return self._servicer_context.invocation_metadata(*args, **kwargs) + + def peer(self, *args, **kwargs): + return self._servicer_context.peer(*args, **kwargs) + + def peer_identities(self, *args, **kwargs): + return self._servicer_context.peer_identities(*args, **kwargs) + + def peer_identity_key(self, *args, **kwargs): + return self._servicer_context.peer_identity_key(*args, **kwargs) + + def auth_context(self, *args, **kwargs): + return self._servicer_context.auth_context(*args, **kwargs) + + def send_initial_metadata(self, *args, **kwargs): + return self._servicer_context.send_initial_metadata(*args, **kwargs) + + def set_trailing_metadata(self, *args, **kwargs): + return self._servicer_context.set_trailing_metadata(*args, **kwargs) + + def abort(self, *args, **kwargs): + if not hasattr(self._servicer_context, 'abort'): + raise RuntimeError('abort() is not supported with the installed version of grpcio') + return self._servicer_context.abort(*args, **kwargs) + + def abort_with_status(self, *args, **kwargs): + if not hasattr(self._servicer_context, 'abort_with_status'): + raise RuntimeError('abort_with_status() is not supported with the installed version of grpcio') + return self._servicer_context.abort_with_status(*args, **kwargs) + + def set_code(self, code): + self.code = code + return self._servicer_context.set_code(code) + + def set_details(self, details): + self.details = details + return self._servicer_context.set_details(details) + + def get_active_span(self): + return self._active_span + + +def _add_peer_tags(peer_str, tags): + ipv4_re = r"ipv4:(?P
.+):(?P\d+)" + match = re.match(ipv4_re, peer_str) + if match: + tags[ot_tags.PEER_HOST_IPV4] = match.group('address') + tags[ot_tags.PEER_PORT] = match.group('port') + return + ipv6_re = r"ipv6:\[(?P
.+)\]:(?P\d+)" + match = re.match(ipv6_re, peer_str) + if match: + tags[ot_tags.PEER_HOST_IPV6] = match.group('address') + tags[ot_tags.PEER_PORT] = match.group('port') + return + logging.warning('Unrecognized peer: \"%s\"', peer_str) + + +# On the service-side, errors can be signaled either by exceptions or by calling +# `set_code` on the `servicer_context`. This function checks for the latter and +# updates the span accordingly. +def _check_error_code(span, servicer_context, rpc_info): + if servicer_context.code != grpc.StatusCode.OK: + span.set_tag('error', True) + error_log = {'event': 'error', 'error.kind': str(servicer_context.code)} + if servicer_context.details is not None: + error_log['message'] = servicer_context.details + span.log_kv(error_log) + rpc_info.error = servicer_context.code + + +class OpenTracingServerInterceptor(grpcext.UnaryServerInterceptor, + grpcext.StreamServerInterceptor): + + def __init__(self, tracer, log_payloads, span_decorator): + self._tracer = tracer + self._log_payloads = log_payloads + self._span_decorator = span_decorator + + def _start_span(self, servicer_context, method): + span_context = None + error = None + metadata = servicer_context.invocation_metadata() + try: + if metadata: + span_context = self._tracer.extract( + opentracing.Format.HTTP_HEADERS, dict(metadata)) + except (opentracing.UnsupportedFormatException, + opentracing.InvalidCarrierException, + opentracing.SpanContextCorruptedException) as e: + logging.exception('tracer.extract() failed') + error = e + tags = { + ot_tags.COMPONENT: 'grpc', + ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_SERVER + } + _add_peer_tags(servicer_context.peer(), tags) + span = self._tracer.start_span( + operation_name=method, child_of=span_context, tags=tags) + if error is not None: + span.log_kv({'event': 'error', 'error.object': error}) + return span + + def intercept_unary(self, request, servicer_context, server_info, handler): + with self._start_span(servicer_context, + server_info.full_method) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining(), + request=request) + if self._log_payloads: + span.log_kv({'request': request}) + servicer_context = _OpenTracingServicerContext( + servicer_context, span) + try: + response = handler(request, servicer_context) + except: + e = sys.exc_info()[0] + span.set_tag('error', True) + span.log_kv({'event': 'error', 'error.object': e}) + rpc_info.error = e + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + raise + if self._log_payloads: + span.log_kv({'response': response}) + _check_error_code(span, servicer_context, rpc_info) + rpc_info.response = response + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + return response + + # For RPCs that stream responses, the result can be a generator. To record + # the span across the generated responses and detect any errors, we wrap the + # result in a new generator that yields the response values. + def _intercept_server_stream(self, request_or_iterator, servicer_context, + server_info, handler): + with self._start_span(servicer_context, + server_info.full_method) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining()) + if not server_info.is_client_stream: + rpc_info.request = request_or_iterator + if self._log_payloads: + request_or_iterator = log_or_wrap_request_or_iterator( + span, server_info.is_client_stream, request_or_iterator) + servicer_context = _OpenTracingServicerContext( + servicer_context, span) + try: + result = handler(request_or_iterator, servicer_context) + for response in result: + if self._log_payloads: + span.log_kv({'response': response}) + yield response + except: + e = sys.exc_info()[0] + span.set_tag('error', True) + span.log_kv({'event': 'error', 'error.object': e}) + rpc_info.error = e + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + raise + _check_error_code(span, servicer_context, rpc_info) + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + + def intercept_stream(self, request_or_iterator, servicer_context, + server_info, handler): + if server_info.is_server_stream: + return self._intercept_server_stream( + request_or_iterator, servicer_context, server_info, handler) + with self._start_span(servicer_context, + server_info.full_method) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining()) + if self._log_payloads: + request_or_iterator = log_or_wrap_request_or_iterator( + span, server_info.is_client_stream, request_or_iterator) + servicer_context = _OpenTracingServicerContext( + servicer_context, span) + try: + response = handler(request_or_iterator, servicer_context) + except: + e = sys.exc_info()[0] + span.set_tag('error', True) + span.log_kv({'event': 'error', 'error.object': e}) + rpc_info.error = e + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + raise + if self._log_payloads: + span.log_kv({'response': response}) + _check_error_code(span, servicer_context, rpc_info) + rpc_info.response = response + if self._span_decorator is not None: + self._span_decorator(span, rpc_info) + return response diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py new file mode 100644 index 00000000000..8b826147556 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py @@ -0,0 +1,65 @@ +"""Internal utilities for gRPC OpenTracing.""" + +import collections +import grpc_opentracing + + +class RpcInfo(grpc_opentracing.RpcInfo): + + def __init__(self, + full_method=None, + metadata=None, + timeout=None, + request=None, + response=None, + error=None): + self.full_method = full_method + self.metadata = metadata + self.timeout = timeout + self.request = request + self.response = response + self.error = error + + +def get_method_type(is_client_stream, is_server_stream): + if is_client_stream and is_server_stream: + return 'BIDI_STREAMING' + elif is_client_stream: + return 'CLIENT_STREAMING' + elif is_server_stream: + return 'SERVER_STREAMING' + else: + return 'UNARY' + + +def get_deadline_millis(timeout): + if timeout is None: + return 'None' + return str(int(round(timeout * 1000))) + + +class _RequestLoggingIterator(object): + + def __init__(self, request_iterator, span): + self._request_iterator = request_iterator + self._span = span + + def __iter__(self): + return self + + def next(self): + request = next(self._request_iterator) + self._span.log_kv({'request': request}) + return request + + def __next__(self): + return self.next() + + +def log_or_wrap_request_or_iterator(span, is_client_stream, + request_or_iterator): + if is_client_stream: + return _RequestLoggingIterator(request_or_iterator, span) + else: + span.log_kv({'request': request_or_iterator}) + return request_or_iterator diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py new file mode 100644 index 00000000000..c8d7e06171f --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -0,0 +1,185 @@ +import abc + +import six + + +class UnaryClientInfo(six.with_metaclass(abc.ABCMeta)): + """Consists of various information about a unary RPC on the invocation-side. + + Attributes: + full_method: A string of the full RPC method, i.e., /package.service/method. + timeout: The length of time in seconds to wait for the computation to + terminate or be cancelled, or None if this method should block until + the computation is terminated or is cancelled no matter how long that + takes. + """ + + +class StreamClientInfo(six.with_metaclass(abc.ABCMeta)): + """Consists of various information about a stream RPC on the invocation-side. + + Attributes: + full_method: A string of the full RPC method, i.e., /package.service/method. + is_client_stream: Indicates whether the RPC is client-streaming. + is_server_stream: Indicates whether the RPC is server-streaming. + timeout: The length of time in seconds to wait for the computation to + terminate or be cancelled, or None if this method should block until + the computation is terminated or is cancelled no matter how long that + takes. + """ + + +class UnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)): + """Affords intercepting unary-unary RPCs on the invocation-side.""" + + @abc.abstractmethod + def intercept_unary(self, request, metadata, client_info, invoker): + """Intercepts unary-unary RPCs on the invocation-side. + + Args: + request: The request value for the RPC. + metadata: Optional :term:`metadata` to be transmitted to the + service-side of the RPC. + client_info: A UnaryClientInfo containing various information about + the RPC. + invoker: The handler to complete the RPC on the client. It is the + interceptor's responsibility to call it. + + Returns: + The result from calling invoker(request, metadata). + """ + raise NotImplementedError() + + +class StreamClientInterceptor(six.with_metaclass(abc.ABCMeta)): + """Affords intercepting stream RPCs on the invocation-side.""" + + @abc.abstractmethod + def intercept_stream(self, request_or_iterator, metadata, client_info, + invoker): + """Intercepts stream RPCs on the invocation-side. + + Args: + request_or_iterator: The request value for the RPC if + `client_info.is_client_stream` is `false`; otherwise, an iterator of + request values. + metadata: Optional :term:`metadata` to be transmitted to the service-side + of the RPC. + client_info: A StreamClientInfo containing various information about + the RPC. + invoker: The handler to complete the RPC on the client. It is the + interceptor's responsibility to call it. + + Returns: + The result from calling invoker(metadata). + """ + raise NotImplementedError() + + +def intercept_channel(channel, *interceptors): + """Creates an intercepted channel. + + Args: + channel: A Channel. + interceptors: Zero or more UnaryClientInterceptors or + StreamClientInterceptors + + Returns: + A Channel. + + Raises: + TypeError: If an interceptor derives from neither UnaryClientInterceptor + nor StreamClientInterceptor. + """ + from grpc_opentracing.grpcext import _interceptor + return _interceptor.intercept_channel(channel, *interceptors) + + +class UnaryServerInfo(six.with_metaclass(abc.ABCMeta)): + """Consists of various information about a unary RPC on the service-side. + + Attributes: + full_method: A string of the full RPC method, i.e., /package.service/method. + """ + + +class StreamServerInfo(six.with_metaclass(abc.ABCMeta)): + """Consists of various information about a stream RPC on the service-side. + + Attributes: + full_method: A string of the full RPC method, i.e., /package.service/method. + is_client_stream: Indicates whether the RPC is client-streaming. + is_server_stream: Indicates whether the RPC is server-streaming. + """ + + +class UnaryServerInterceptor(six.with_metaclass(abc.ABCMeta)): + """Affords intercepting unary-unary RPCs on the service-side.""" + + @abc.abstractmethod + def intercept_unary(self, request, servicer_context, server_info, handler): + """Intercepts unary-unary RPCs on the service-side. + + Args: + request: The request value for the RPC. + servicer_context: A ServicerContext. + server_info: A UnaryServerInfo containing various information about + the RPC. + handler: The handler to complete the RPC on the server. It is the + interceptor's responsibility to call it. + + Returns: + The result from calling handler(request, servicer_context). + """ + raise NotImplementedError() + + +class StreamServerInterceptor(six.with_metaclass(abc.ABCMeta)): + """Affords intercepting stream RPCs on the service-side.""" + + @abc.abstractmethod + def intercept_stream(self, request_or_iterator, servicer_context, + server_info, handler): + """Intercepts stream RPCs on the service-side. + + Args: + request_or_iterator: The request value for the RPC if + `server_info.is_client_stream` is `False`; otherwise, an iterator of + request values. + servicer_context: A ServicerContext. + server_info: A StreamServerInfo containing various information about + the RPC. + handler: The handler to complete the RPC on the server. It is the + interceptor's responsibility to call it. + + Returns: + The result from calling handler(servicer_context). + """ + raise NotImplementedError() + + +def intercept_server(server, *interceptors): + """Creates an intercepted server. + + Args: + server: A Server. + interceptors: Zero or more UnaryServerInterceptors or + StreamServerInterceptors + + Returns: + A Server. + + Raises: + TypeError: If an interceptor derives from neither UnaryServerInterceptor + nor StreamServerInterceptor. + """ + from grpc_opentracing.grpcext import _interceptor + return _interceptor.intercept_server(server, *interceptors) + + +################################### __all__ ################################# + +__all__ = ('UnaryClientInterceptor', 'StreamClientInfo', + 'StreamClientInterceptor', 'UnaryServerInfo', 'StreamServerInfo', + 'UnaryServerInterceptor', 'StreamServerInterceptor', + 'intercept_channel', 'intercept_server',) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py new file mode 100644 index 00000000000..a6bd328ac68 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -0,0 +1,378 @@ +"""Implementation of gRPC Python interceptors.""" + +import collections + +import grpc +from grpc_opentracing import grpcext + + +class _UnaryClientInfo( + collections.namedtuple('_UnaryClientInfo', + ('full_method', 'timeout',))): + pass + + +class _StreamClientInfo( + collections.namedtuple('_StreamClientInfo', ( + 'full_method', 'is_client_stream', 'is_server_stream', 'timeout'))): + pass + + +class _InterceptorUnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): + + def __init__(self, method, base_callable, interceptor): + self._method = method + self._base_callable = base_callable + self._interceptor = interceptor + + def __call__(self, request, timeout=None, metadata=None, credentials=None): + + def invoker(request, metadata): + return self._base_callable(request, timeout, metadata, credentials) + + client_info = _UnaryClientInfo(self._method, timeout) + return self._interceptor.intercept_unary(request, metadata, client_info, + invoker) + + def with_call(self, request, timeout=None, metadata=None, credentials=None): + + def invoker(request, metadata): + return self._base_callable.with_call(request, timeout, metadata, + credentials) + + client_info = _UnaryClientInfo(self._method, timeout) + return self._interceptor.intercept_unary(request, metadata, client_info, + invoker) + + def future(self, request, timeout=None, metadata=None, credentials=None): + + def invoker(request, metadata): + return self._base_callable.future(request, timeout, metadata, + credentials) + + client_info = _UnaryClientInfo(self._method, timeout) + return self._interceptor.intercept_unary(request, metadata, client_info, + invoker) + + +class _InterceptorUnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): + + def __init__(self, method, base_callable, interceptor): + self._method = method + self._base_callable = base_callable + self._interceptor = interceptor + + def __call__(self, request, timeout=None, metadata=None, credentials=None): + + def invoker(request, metadata): + return self._base_callable(request, timeout, metadata, credentials) + + client_info = _StreamClientInfo(self._method, False, True, timeout) + return self._interceptor.intercept_stream(request, metadata, + client_info, invoker) + + +class _InterceptorStreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): + + def __init__(self, method, base_callable, interceptor): + self._method = method + self._base_callable = base_callable + self._interceptor = interceptor + + def __call__(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + + def invoker(request_iterator, metadata): + return self._base_callable(request_iterator, timeout, metadata, + credentials) + + client_info = _StreamClientInfo(self._method, True, False, timeout) + return self._interceptor.intercept_stream(request_iterator, metadata, + client_info, invoker) + + def with_call(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + + def invoker(request_iterator, metadata): + return self._base_callable.with_call(request_iterator, timeout, + metadata, credentials) + + client_info = _StreamClientInfo(self._method, True, False, timeout) + return self._interceptor.intercept_stream(request_iterator, metadata, + client_info, invoker) + + def future(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + + def invoker(request_iterator, metadata): + return self._base_callable.future(request_iterator, timeout, + metadata, credentials) + + client_info = _StreamClientInfo(self._method, True, False, timeout) + return self._interceptor.intercept_stream(request_iterator, metadata, + client_info, invoker) + + +class _InterceptorStreamStreamMultiCallable(grpc.StreamStreamMultiCallable): + + def __init__(self, method, base_callable, interceptor): + self._method = method + self._base_callable = base_callable + self._interceptor = interceptor + + def __call__(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + + def invoker(request_iterator, metadata): + return self._base_callable(request_iterator, timeout, metadata, + credentials) + + client_info = _StreamClientInfo(self._method, True, True, timeout) + return self._interceptor.intercept_stream(request_iterator, metadata, + client_info, invoker) + + +class _InterceptorChannel(grpc.Channel): + + def __init__(self, channel, interceptor): + self._channel = channel + self._interceptor = interceptor + + def subscribe(self, *args, **kwargs): + self._channel.subscribe(*args, **kwargs) + + def unsubscribe(self, *args, **kwargs): + self._channel.unsubscribe(*args, **kwargs) + + def unary_unary(self, + method, + request_serializer=None, + response_deserializer=None): + base_callable = self._channel.unary_unary(method, request_serializer, + response_deserializer) + if isinstance(self._interceptor, grpcext.UnaryClientInterceptor): + return _InterceptorUnaryUnaryMultiCallable(method, base_callable, + self._interceptor) + else: + return base_callable + + def unary_stream(self, + method, + request_serializer=None, + response_deserializer=None): + base_callable = self._channel.unary_stream(method, request_serializer, + response_deserializer) + if isinstance(self._interceptor, grpcext.StreamClientInterceptor): + return _InterceptorUnaryStreamMultiCallable(method, base_callable, + self._interceptor) + else: + return base_callable + + def stream_unary(self, + method, + request_serializer=None, + response_deserializer=None): + base_callable = self._channel.stream_unary(method, request_serializer, + response_deserializer) + if isinstance(self._interceptor, grpcext.StreamClientInterceptor): + return _InterceptorStreamUnaryMultiCallable(method, base_callable, + self._interceptor) + else: + return base_callable + + def stream_stream(self, + method, + request_serializer=None, + response_deserializer=None): + base_callable = self._channel.stream_stream(method, request_serializer, + response_deserializer) + if isinstance(self._interceptor, grpcext.StreamClientInterceptor): + return _InterceptorStreamStreamMultiCallable(method, base_callable, + self._interceptor) + else: + return base_callable + + def close(self): + if not hasattr(self._channel, 'close'): + raise RuntimeError('close() is not supported with the installed version of grpcio') + self._channel.close() + + +def intercept_channel(channel, *interceptors): + result = channel + for interceptor in interceptors: + if not isinstance(interceptor, grpcext.UnaryClientInterceptor) and \ + not isinstance(interceptor, grpcext.StreamClientInterceptor): + raise TypeError('interceptor must be either a ' + 'grpcext.UnaryClientInterceptor or a ' + 'grpcext.StreamClientInterceptor') + result = _InterceptorChannel(result, interceptor) + return result + + +class _UnaryServerInfo( + collections.namedtuple('_UnaryServerInfo', ('full_method',))): + pass + + +class _StreamServerInfo( + collections.namedtuple('_StreamServerInfo', ( + 'full_method', 'is_client_stream', 'is_server_stream'))): + pass + + +class _InterceptorRpcMethodHandler(grpc.RpcMethodHandler): + + def __init__(self, rpc_method_handler, method, interceptor): + self._rpc_method_handler = rpc_method_handler + self._method = method + self._interceptor = interceptor + + @property + def request_streaming(self): + return self._rpc_method_handler.request_streaming + + @property + def response_streaming(self): + return self._rpc_method_handler.response_streaming + + @property + def request_deserializer(self): + return self._rpc_method_handler.request_deserializer + + @property + def response_serializer(self): + return self._rpc_method_handler.response_serializer + + @property + def unary_unary(self): + if not isinstance(self._interceptor, grpcext.UnaryServerInterceptor): + return self._rpc_method_handler.unary_unary + + def adaptation(request, servicer_context): + + def handler(request, servicer_context): + return self._rpc_method_handler.unary_unary(request, + servicer_context) + + return self._interceptor.intercept_unary( + request, servicer_context, + _UnaryServerInfo(self._method), handler) + + return adaptation + + @property + def unary_stream(self): + if not isinstance(self._interceptor, grpcext.StreamServerInterceptor): + return self._rpc_method_handler.unary_stream + + def adaptation(request, servicer_context): + + def handler(request, servicer_context): + return self._rpc_method_handler.unary_stream(request, + servicer_context) + + return self._interceptor.intercept_stream( + request, servicer_context, + _StreamServerInfo(self._method, False, True), handler) + + return adaptation + + @property + def stream_unary(self): + if not isinstance(self._interceptor, grpcext.StreamServerInterceptor): + return self._rpc_method_handler.stream_unary + + def adaptation(request_iterator, servicer_context): + + def handler(request_iterator, servicer_context): + return self._rpc_method_handler.stream_unary(request_iterator, + servicer_context) + + return self._interceptor.intercept_stream( + request_iterator, servicer_context, + _StreamServerInfo(self._method, True, False), handler) + + return adaptation + + @property + def stream_stream(self): + if not isinstance(self._interceptor, grpcext.StreamServerInterceptor): + return self._rpc_method_handler.stream_stream + + def adaptation(request_iterator, servicer_context): + + def handler(request_iterator, servicer_context): + return self._rpc_method_handler.stream_stream(request_iterator, + servicer_context) + + return self._interceptor.intercept_stream( + request_iterator, servicer_context, + _StreamServerInfo(self._method, True, True), handler) + + return adaptation + + +class _InterceptorGenericRpcHandler(grpc.GenericRpcHandler): + + def __init__(self, generic_rpc_handler, interceptor): + self.generic_rpc_handler = generic_rpc_handler + self._interceptor = interceptor + + def service(self, handler_call_details): + result = self.generic_rpc_handler.service(handler_call_details) + if result: + result = _InterceptorRpcMethodHandler( + result, handler_call_details.method, self._interceptor) + return result + + +class _InterceptorServer(grpc.Server): + + def __init__(self, server, interceptor): + self._server = server + self._interceptor = interceptor + + def add_generic_rpc_handlers(self, generic_rpc_handlers): + generic_rpc_handlers = [ + _InterceptorGenericRpcHandler(generic_rpc_handler, + self._interceptor) + for generic_rpc_handler in generic_rpc_handlers + ] + return self._server.add_generic_rpc_handlers(generic_rpc_handlers) + + def add_insecure_port(self, *args, **kwargs): + return self._server.add_insecure_port(*args, **kwargs) + + def add_secure_port(self, *args, **kwargs): + return self._server.add_secure_port(*args, **kwargs) + + def start(self, *args, **kwargs): + return self._server.start(*args, **kwargs) + + def stop(self, *args, **kwargs): + return self._server.stop(*args, **kwargs) + + +def intercept_server(server, *interceptors): + result = server + for interceptor in interceptors: + if not isinstance(interceptor, grpcext.UnaryServerInterceptor) and \ + not isinstance(interceptor, grpcext.StreamServerInterceptor): + raise TypeError('interceptor must be either a ' + 'grpcext.UnaryServerInterceptor or a ' + 'grpcext.StreamServerInterceptor') + result = _InterceptorServer(result, interceptor) + return result From 987d6d415c10cc736963f917bd23094ee02f6432 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Fri, 13 Mar 2020 13:18:26 -0700 Subject: [PATCH 13/59] Cleanup --- .../src/opentelemetry/ext/grpc/__init__.py | 50 +++--- .../src/opentelemetry/ext/grpc/_client.py | 153 +++++++++------- .../src/opentelemetry/ext/grpc/_server.py | 170 +++++++++++------- .../src/opentelemetry/ext/grpc/_utilities.py | 15 +- 4 files changed, 242 insertions(+), 146 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index f35e79e86c2..45970a00736 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -1,10 +1,21 @@ +# Copyright 2020, OpenTelemetry 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. + import abc -import enum import six -import grpc - class ActiveSpanSource(six.with_metaclass(abc.ABCMeta)): """Provides a way to access an the active span.""" @@ -23,7 +34,8 @@ class RpcInfo(six.with_metaclass(abc.ABCMeta)): """Provides information for an RPC call. Attributes: - full_method: A string of the full RPC method, i.e., /package.service/method. + full_method: A string of the full RPC method, i.e., + /package.service/method. metadata: The initial :term:`metadata`. timeout: The length of time in seconds to wait for the computation to terminate or be cancelled. @@ -48,10 +60,9 @@ def __call__(self, span, rpc_info): raise NotImplementedError() -def open_tracing_client_interceptor(tracer, - active_span_source=None, - log_payloads=False, - span_decorator=None): +def open_tracing_client_interceptor( + tracer, active_span_source=None, log_payloads=False, span_decorator=None +): """Creates an invocation-side interceptor that can be use with gRPC to add OpenTracing information. @@ -66,13 +77,15 @@ def open_tracing_client_interceptor(tracer, An invocation-side interceptor object. """ from grpc_opentracing import _client - return _client.OpenTracingClientInterceptor(tracer, active_span_source, - log_payloads, span_decorator) + + return _client.OpenTracingClientInterceptor( + tracer, active_span_source, log_payloads, span_decorator + ) -def open_tracing_server_interceptor(tracer, - log_payloads=False, - span_decorator=None): +def open_tracing_server_interceptor( + tracer, log_payloads=False, span_decorator=None +): """Creates a service-side interceptor that can be use with gRPC to add OpenTracing information. @@ -85,12 +98,7 @@ def open_tracing_server_interceptor(tracer, A service-side interceptor object. """ from grpc_opentracing import _server - return _server.OpenTracingServerInterceptor(tracer, log_payloads, - span_decorator) - - -################################### __all__ ################################# -__all__ = ('ActiveSpanSource', 'RpcInfo', 'SpanDecorator', - 'open_tracing_client_interceptor', - 'open_tracing_server_interceptor',) + return _server.OpenTracingServerInterceptor( + tracer, log_payloads, span_decorator + ) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index 01afb3ed9b5..b61fb6a25db 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -1,21 +1,35 @@ +# Copyright 2020, OpenTelemetry 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. + """Implementation of the invocation-side open-tracing interceptor.""" -import sys import logging -import time - -from six import iteritems +import sys import grpc -from grpc_opentracing import grpcext -from grpc_opentracing._utilities import get_method_type, get_deadline_millis,\ - log_or_wrap_request_or_iterator, RpcInfo import opentracing from opentracing.ext import tags as ot_tags +from six import iteritems +from grpc_opentracing import grpcext +from grpc_opentracing._utilities import ( + RpcInfo, + log_or_wrap_request_or_iterator, +) -class _GuardedSpan(object): +class _GuardedSpan(object): def __init__(self, span): self.span = span self._engaged = True @@ -39,27 +53,28 @@ def _inject_span_context(tracer, span, metadata): headers = {} try: tracer.inject(span.context, opentracing.Format.HTTP_HEADERS, headers) - except (opentracing.UnsupportedFormatException, - opentracing.InvalidCarrierException, - opentracing.SpanContextCorruptedException) as e: - logging.exception('tracer.inject() failed') - span.log_kv({'event': 'error', 'error.object': e}) + except ( + opentracing.UnsupportedFormatException, + opentracing.InvalidCarrierException, + opentracing.SpanContextCorruptedException, + ) as e: + logging.exception("tracer.inject() failed") + span.log_kv({"event": "error", "error.object": e}) return metadata metadata = () if metadata is None else tuple(metadata) return metadata + tuple((k.lower(), v) for (k, v) in iteritems(headers)) def _make_future_done_callback(span, rpc_info, log_payloads, span_decorator): - def callback(response_future): with span: code = response_future.code() if code != grpc.StatusCode.OK: - span.set_tag('error', True) - error_log = {'event': 'error', 'error.kind': str(code)} + span.set_tag("error", True) + error_log = {"event": "error", "error.kind": str(code)} details = response_future.details() if details is not None: - error_log['message'] = details + error_log["message"] = details span.log_kv(error_log) rpc_info.error = code if span_decorator is not None: @@ -68,18 +83,19 @@ def callback(response_future): response = response_future.result() rpc_info.response = response if log_payloads: - span.log_kv({'response': response}) + span.log_kv({"response": response}) if span_decorator is not None: span_decorator(span, rpc_info) return callback -class OpenTracingClientInterceptor(grpcext.UnaryClientInterceptor, - grpcext.StreamClientInterceptor): - - def __init__(self, tracer, active_span_source, log_payloads, - span_decorator): +class OpenTracingClientInterceptor( + grpcext.UnaryClientInterceptor, grpcext.StreamClientInterceptor +): + def __init__( + self, tracer, active_span_source, log_payloads, span_decorator + ): self._tracer = tracer self._active_span_source = active_span_source self._log_payloads = log_payloads @@ -92,19 +108,25 @@ def _start_span(self, method): if active_span is not None: active_span_context = active_span.context tags = { - ot_tags.COMPONENT: 'grpc', - ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_CLIENT + ot_tags.COMPONENT: "grpc", + ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_CLIENT, } return self._tracer.start_span( - operation_name=method, child_of=active_span_context, tags=tags) + operation_name=method, child_of=active_span_context, tags=tags + ) def _trace_result(self, guarded_span, rpc_info, result): - # If the RPC is called asynchronously, release the guard and add a callback - # so that the span can be finished once the future is done. + # If the RPC is called asynchronously, release the guard and add a + # callback so that the span can be finished once the future is done. if isinstance(result, grpc.Future): result.add_done_callback( - _make_future_done_callback(guarded_span.release( - ), rpc_info, self._log_payloads, self._span_decorator)) + _make_future_done_callback( + guarded_span.release(), + rpc_info, + self._log_payloads, + self._span_decorator, + ) + ) return result response = result # Handle the case when the RPC is initiated via the with_call @@ -115,7 +137,7 @@ def _trace_result(self, guarded_span, rpc_info, result): response = result[0] rpc_info.response = response if self._log_payloads: - guarded_span.span.log_kv({'response': response}) + guarded_span.span.log_kv({"response": response}) if self._span_decorator is not None: self._span_decorator(guarded_span.span, rpc_info) return result @@ -125,21 +147,23 @@ def _start_guarded_span(self, *args, **kwargs): def intercept_unary(self, request, metadata, client_info, invoker): with self._start_guarded_span(client_info.full_method) as guarded_span: - metadata = _inject_span_context(self._tracer, guarded_span.span, - metadata) + metadata = _inject_span_context( + self._tracer, guarded_span.span, metadata + ) rpc_info = RpcInfo( full_method=client_info.full_method, metadata=metadata, timeout=client_info.timeout, - request=request) + request=request, + ) if self._log_payloads: - guarded_span.span.log_kv({'request': request}) + guarded_span.span.log_kv({"request": request}) try: result = invoker(request, metadata) - except: + except Exception: e = sys.exc_info()[0] - guarded_span.span.set_tag('error', True) - guarded_span.span.log_kv({'event': 'error', 'error.object': e}) + guarded_span.span.set_tag("error", True) + guarded_span.span.log_kv({"event": "error", "error.object": e}) rpc_info.error = e if self._span_decorator is not None: self._span_decorator(guarded_span.span, rpc_info) @@ -147,31 +171,34 @@ def intercept_unary(self, request, metadata, client_info, invoker): return self._trace_result(guarded_span, rpc_info, result) # For RPCs that stream responses, the result can be a generator. To record - # the span across the generated responses and detect any errors, we wrap the - # result in a new generator that yields the response values. - def _intercept_server_stream(self, request_or_iterator, metadata, - client_info, invoker): + # the span across the generated responses and detect any errors, we wrap + # the result in a new generator that yields the response values. + def _intercept_server_stream( + self, request_or_iterator, metadata, client_info, invoker + ): with self._start_span(client_info.full_method) as span: metadata = _inject_span_context(self._tracer, span, metadata) rpc_info = RpcInfo( full_method=client_info.full_method, metadata=metadata, - timeout=client_info.timeout) + timeout=client_info.timeout, + ) if client_info.is_client_stream: rpc_info.request = request_or_iterator if self._log_payloads: request_or_iterator = log_or_wrap_request_or_iterator( - span, client_info.is_client_stream, request_or_iterator) + span, client_info.is_client_stream, request_or_iterator + ) try: result = invoker(request_or_iterator, metadata) for response in result: if self._log_payloads: - span.log_kv({'response': response}) + span.log_kv({"response": response}) yield response - except: + except Exception: e = sys.exc_info()[0] - span.set_tag('error', True) - span.log_kv({'event': 'error', 'error.object': e}) + span.set_tag("error", True) + span.log_kv({"event": "error", "error.object": e}) rpc_info.error = e if self._span_decorator is not None: self._span_decorator(span, rpc_info) @@ -179,29 +206,35 @@ def _intercept_server_stream(self, request_or_iterator, metadata, if self._span_decorator is not None: self._span_decorator(span, rpc_info) - def intercept_stream(self, request_or_iterator, metadata, client_info, - invoker): + def intercept_stream( + self, request_or_iterator, metadata, client_info, invoker + ): if client_info.is_server_stream: - return self._intercept_server_stream(request_or_iterator, metadata, - client_info, invoker) + return self._intercept_server_stream( + request_or_iterator, metadata, client_info, invoker + ) with self._start_guarded_span(client_info.full_method) as guarded_span: - metadata = _inject_span_context(self._tracer, guarded_span.span, - metadata) + metadata = _inject_span_context( + self._tracer, guarded_span.span, metadata + ) rpc_info = RpcInfo( full_method=client_info.full_method, metadata=metadata, timeout=client_info.timeout, - request=request_or_iterator) + request=request_or_iterator, + ) if self._log_payloads: request_or_iterator = log_or_wrap_request_or_iterator( - guarded_span.span, client_info.is_client_stream, - request_or_iterator) + guarded_span.span, + client_info.is_client_stream, + request_or_iterator, + ) try: result = invoker(request_or_iterator, metadata) - except: + except Exception: e = sys.exc_info()[0] - guarded_span.span.set_tag('error', True) - guarded_span.span.log_kv({'event': 'error', 'error.object': e}) + guarded_span.span.set_tag("error", True) + guarded_span.span.log_kv({"event": "error", "error.object": e}) rpc_info.error = e if self._span_decorator is not None: self._span_decorator(guarded_span.span, rpc_info) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index 937a4e83fd1..16e3d571979 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -1,19 +1,35 @@ +# Copyright 2020, OpenTelemetry 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. + """Implementation of the service-side open-tracing interceptor.""" -import sys import logging import re +import sys import grpc -from grpc_opentracing import grpcext, ActiveSpanSource -from grpc_opentracing._utilities import get_method_type, get_deadline_millis,\ - log_or_wrap_request_or_iterator, RpcInfo import opentracing from opentracing.ext import tags as ot_tags +from grpc_opentracing import ActiveSpanSource, grpcext +from grpc_opentracing._utilities import ( + RpcInfo, + log_or_wrap_request_or_iterator, +) -class _OpenTracingServicerContext(grpc.ServicerContext, ActiveSpanSource): +class _OpenTracingServicerContext(grpc.ServicerContext, ActiveSpanSource): def __init__(self, servicer_context, active_span): self._servicer_context = servicer_context self._active_span = active_span @@ -54,13 +70,18 @@ def set_trailing_metadata(self, *args, **kwargs): return self._servicer_context.set_trailing_metadata(*args, **kwargs) def abort(self, *args, **kwargs): - if not hasattr(self._servicer_context, 'abort'): - raise RuntimeError('abort() is not supported with the installed version of grpcio') + if not hasattr(self._servicer_context, "abort"): + raise RuntimeError( + "abort() is not supported with the installed version of grpcio" + ) return self._servicer_context.abort(*args, **kwargs) def abort_with_status(self, *args, **kwargs): - if not hasattr(self._servicer_context, 'abort_with_status'): - raise RuntimeError('abort_with_status() is not supported with the installed version of grpcio') + if not hasattr(self._servicer_context, "abort_with_status"): + raise RuntimeError( + "abort_with_status() is not supported with the installed " + "version of grpcio" + ) return self._servicer_context.abort_with_status(*args, **kwargs) def set_code(self, code): @@ -79,34 +100,37 @@ def _add_peer_tags(peer_str, tags): ipv4_re = r"ipv4:(?P
.+):(?P\d+)" match = re.match(ipv4_re, peer_str) if match: - tags[ot_tags.PEER_HOST_IPV4] = match.group('address') - tags[ot_tags.PEER_PORT] = match.group('port') + tags[ot_tags.PEER_HOST_IPV4] = match.group("address") + tags[ot_tags.PEER_PORT] = match.group("port") return ipv6_re = r"ipv6:\[(?P
.+)\]:(?P\d+)" match = re.match(ipv6_re, peer_str) if match: - tags[ot_tags.PEER_HOST_IPV6] = match.group('address') - tags[ot_tags.PEER_PORT] = match.group('port') + tags[ot_tags.PEER_HOST_IPV6] = match.group("address") + tags[ot_tags.PEER_PORT] = match.group("port") return - logging.warning('Unrecognized peer: \"%s\"', peer_str) + logging.warning('Unrecognized peer: "%s"', peer_str) -# On the service-side, errors can be signaled either by exceptions or by calling -# `set_code` on the `servicer_context`. This function checks for the latter and -# updates the span accordingly. +# On the service-side, errors can be signaled either by exceptions or by +# calling `set_code` on the `servicer_context`. This function checks for the +# latter and updates the span accordingly. def _check_error_code(span, servicer_context, rpc_info): if servicer_context.code != grpc.StatusCode.OK: - span.set_tag('error', True) - error_log = {'event': 'error', 'error.kind': str(servicer_context.code)} + span.set_tag("error", True) + error_log = { + "event": "error", + "error.kind": str(servicer_context.code), + } if servicer_context.details is not None: - error_log['message'] = servicer_context.details + error_log["message"] = servicer_context.details span.log_kv(error_log) rpc_info.error = servicer_context.code -class OpenTracingServerInterceptor(grpcext.UnaryServerInterceptor, - grpcext.StreamServerInterceptor): - +class OpenTracingServerInterceptor( + grpcext.UnaryServerInterceptor, grpcext.StreamServerInterceptor +): def __init__(self, tracer, log_payloads, span_decorator): self._tracer = tracer self._log_payloads = log_payloads @@ -119,47 +143,54 @@ def _start_span(self, servicer_context, method): try: if metadata: span_context = self._tracer.extract( - opentracing.Format.HTTP_HEADERS, dict(metadata)) - except (opentracing.UnsupportedFormatException, - opentracing.InvalidCarrierException, - opentracing.SpanContextCorruptedException) as e: - logging.exception('tracer.extract() failed') + opentracing.Format.HTTP_HEADERS, dict(metadata) + ) + except ( + opentracing.UnsupportedFormatException, + opentracing.InvalidCarrierException, + opentracing.SpanContextCorruptedException, + ) as e: + logging.exception("tracer.extract() failed") error = e tags = { - ot_tags.COMPONENT: 'grpc', - ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_SERVER + ot_tags.COMPONENT: "grpc", + ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_SERVER, } _add_peer_tags(servicer_context.peer(), tags) span = self._tracer.start_span( - operation_name=method, child_of=span_context, tags=tags) + operation_name=method, child_of=span_context, tags=tags + ) if error is not None: - span.log_kv({'event': 'error', 'error.object': error}) + span.log_kv({"event": "error", "error.object": error}) return span def intercept_unary(self, request, servicer_context, server_info, handler): - with self._start_span(servicer_context, - server_info.full_method) as span: + with self._start_span( + servicer_context, server_info.full_method + ) as span: rpc_info = RpcInfo( full_method=server_info.full_method, metadata=servicer_context.invocation_metadata(), timeout=servicer_context.time_remaining(), - request=request) + request=request, + ) if self._log_payloads: - span.log_kv({'request': request}) + span.log_kv({"request": request}) servicer_context = _OpenTracingServicerContext( - servicer_context, span) + servicer_context, span + ) try: response = handler(request, servicer_context) - except: + except Exception: e = sys.exc_info()[0] - span.set_tag('error', True) - span.log_kv({'event': 'error', 'error.object': e}) + span.set_tag("error", True) + span.log_kv({"event": "error", "error.object": e}) rpc_info.error = e if self._span_decorator is not None: self._span_decorator(span, rpc_info) raise if self._log_payloads: - span.log_kv({'response': response}) + span.log_kv({"response": response}) _check_error_code(span, servicer_context, rpc_info) rpc_info.response = response if self._span_decorator is not None: @@ -169,31 +200,36 @@ def intercept_unary(self, request, servicer_context, server_info, handler): # For RPCs that stream responses, the result can be a generator. To record # the span across the generated responses and detect any errors, we wrap the # result in a new generator that yields the response values. - def _intercept_server_stream(self, request_or_iterator, servicer_context, - server_info, handler): - with self._start_span(servicer_context, - server_info.full_method) as span: + def _intercept_server_stream( + self, request_or_iterator, servicer_context, server_info, handler + ): + with self._start_span( + servicer_context, server_info.full_method + ) as span: rpc_info = RpcInfo( full_method=server_info.full_method, metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining()) + timeout=servicer_context.time_remaining(), + ) if not server_info.is_client_stream: rpc_info.request = request_or_iterator if self._log_payloads: request_or_iterator = log_or_wrap_request_or_iterator( - span, server_info.is_client_stream, request_or_iterator) + span, server_info.is_client_stream, request_or_iterator + ) servicer_context = _OpenTracingServicerContext( - servicer_context, span) + servicer_context, span + ) try: result = handler(request_or_iterator, servicer_context) for response in result: if self._log_payloads: - span.log_kv({'response': response}) + span.log_kv({"response": response}) yield response - except: + except Exception: e = sys.exc_info()[0] - span.set_tag('error', True) - span.log_kv({'event': 'error', 'error.object': e}) + span.set_tag("error", True) + span.log_kv({"event": "error", "error.object": e}) rpc_info.error = e if self._span_decorator is not None: self._span_decorator(span, rpc_info) @@ -202,34 +238,40 @@ def _intercept_server_stream(self, request_or_iterator, servicer_context, if self._span_decorator is not None: self._span_decorator(span, rpc_info) - def intercept_stream(self, request_or_iterator, servicer_context, - server_info, handler): + def intercept_stream( + self, request_or_iterator, servicer_context, server_info, handler + ): if server_info.is_server_stream: return self._intercept_server_stream( - request_or_iterator, servicer_context, server_info, handler) - with self._start_span(servicer_context, - server_info.full_method) as span: + request_or_iterator, servicer_context, server_info, handler + ) + with self._start_span( + servicer_context, server_info.full_method + ) as span: rpc_info = RpcInfo( full_method=server_info.full_method, metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining()) + timeout=servicer_context.time_remaining(), + ) if self._log_payloads: request_or_iterator = log_or_wrap_request_or_iterator( - span, server_info.is_client_stream, request_or_iterator) + span, server_info.is_client_stream, request_or_iterator + ) servicer_context = _OpenTracingServicerContext( - servicer_context, span) + servicer_context, span + ) try: response = handler(request_or_iterator, servicer_context) - except: + except Exception: e = sys.exc_info()[0] - span.set_tag('error', True) - span.log_kv({'event': 'error', 'error.object': e}) + span.set_tag("error", True) + span.log_kv({"event": "error", "error.object": e}) rpc_info.error = e if self._span_decorator is not None: self._span_decorator(span, rpc_info) raise if self._log_payloads: - span.log_kv({'response': response}) + span.log_kv({"response": response}) _check_error_code(span, servicer_context, rpc_info) rpc_info.response = response if self._span_decorator is not None: diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py index 8b826147556..0584be768f9 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py @@ -1,6 +1,19 @@ +# Copyright 2020, OpenTelemetry 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. + """Internal utilities for gRPC OpenTracing.""" -import collections import grpc_opentracing From 3c80b314c004ceef20c24b222cc9683d10a7ecd4 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 23 Mar 2020 22:20:47 -0700 Subject: [PATCH 14/59] Scrub more OpenTracing references, unused code --- .../src/opentelemetry/ext/grpc/__init__.py | 93 +++---------------- .../src/opentelemetry/ext/grpc/_utilities.py | 50 +--------- .../ext/grpc/grpcext/__init__.py | 4 +- .../ext/grpc/grpcext/_interceptor.py | 2 +- 4 files changed, 20 insertions(+), 129 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 45970a00736..3ca2c1e2f32 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -12,93 +12,30 @@ # See the License for the specific language governing permissions and # limitations under the License. -import abc -import six +def client_interceptor(tracer): + """Create a gRPC client channel interceptor. - -class ActiveSpanSource(six.with_metaclass(abc.ABCMeta)): - """Provides a way to access an the active span.""" - - @abc.abstractmethod - def get_active_span(self): - """Identifies the active span. + Args: + tracer: The tracer to use to create client-side spans. Returns: - An object that implements the opentracing.Span interface. + An invocation-side interceptor object. """ - raise NotImplementedError() - - -class RpcInfo(six.with_metaclass(abc.ABCMeta)): - """Provides information for an RPC call. + from . import _client - Attributes: - full_method: A string of the full RPC method, i.e., - /package.service/method. - metadata: The initial :term:`metadata`. - timeout: The length of time in seconds to wait for the computation to - terminate or be cancelled. - request: The RPC request or None for request-streaming RPCs. - response: The RPC response or None for response-streaming or erroring RPCs. - error: The RPC error or None for successful RPCs. - """ + return _client.OpenTelemetryClientInterceptor(tracer) -class SpanDecorator(six.with_metaclass(abc.ABCMeta)): - """Provides a mechanism to add arbitrary tags/logs/etc to the - opentracing.Span associated with client and/or server RPCs.""" - - @abc.abstractmethod - def __call__(self, span, rpc_info): - """Customizes an RPC span. +def server_interceptor(tracer): + """Create a gRPC server interceptor. Args: - span: The client-side or server-side opentracing.Span for the RPC. - rpc_info: An RpcInfo describing the RPC. - """ - raise NotImplementedError() - - -def open_tracing_client_interceptor( - tracer, active_span_source=None, log_payloads=False, span_decorator=None -): - """Creates an invocation-side interceptor that can be use with gRPC to add - OpenTracing information. + tracer: The tracer to use to create server-side spans. - Args: - tracer: An object implmenting the opentracing.Tracer interface. - active_span_source: An optional ActiveSpanSource to customize how the - active span is determined. - log_payloads: Indicates whether requests should be logged. - span_decorator: An optional SpanDecorator. - - Returns: - An invocation-side interceptor object. - """ - from grpc_opentracing import _client - - return _client.OpenTracingClientInterceptor( - tracer, active_span_source, log_payloads, span_decorator - ) - - -def open_tracing_server_interceptor( - tracer, log_payloads=False, span_decorator=None -): - """Creates a service-side interceptor that can be use with gRPC to add - OpenTracing information. - - Args: - tracer: An object implmenting the opentracing.Tracer interface. - log_payloads: Indicates whether requests should be logged. - span_decorator: An optional SpanDecorator. - - Returns: - A service-side interceptor object. - """ - from grpc_opentracing import _server + Returns: + A service-side interceptor object. + """ + from . import _server - return _server.OpenTracingServerInterceptor( - tracer, log_payloads, span_decorator - ) + return _server.OpenTelemetryServerInterceptor(tracer) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py index 0584be768f9..b3159440e08 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py @@ -12,12 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Internal utilities for gRPC OpenTracing.""" +"""Internal utilities.""" -import grpc_opentracing - -class RpcInfo(grpc_opentracing.RpcInfo): +class RpcInfo: def __init__(self, full_method=None, @@ -32,47 +30,3 @@ def __init__(self, self.request = request self.response = response self.error = error - - -def get_method_type(is_client_stream, is_server_stream): - if is_client_stream and is_server_stream: - return 'BIDI_STREAMING' - elif is_client_stream: - return 'CLIENT_STREAMING' - elif is_server_stream: - return 'SERVER_STREAMING' - else: - return 'UNARY' - - -def get_deadline_millis(timeout): - if timeout is None: - return 'None' - return str(int(round(timeout * 1000))) - - -class _RequestLoggingIterator(object): - - def __init__(self, request_iterator, span): - self._request_iterator = request_iterator - self._span = span - - def __iter__(self): - return self - - def next(self): - request = next(self._request_iterator) - self._span.log_kv({'request': request}) - return request - - def __next__(self): - return self.next() - - -def log_or_wrap_request_or_iterator(span, is_client_stream, - request_or_iterator): - if is_client_stream: - return _RequestLoggingIterator(request_or_iterator, span) - else: - span.log_kv({'request': request_or_iterator}) - return request_or_iterator diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py index c8d7e06171f..2864fd6d395 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -91,7 +91,7 @@ def intercept_channel(channel, *interceptors): TypeError: If an interceptor derives from neither UnaryClientInterceptor nor StreamClientInterceptor. """ - from grpc_opentracing.grpcext import _interceptor + from . import _interceptor return _interceptor.intercept_channel(channel, *interceptors) @@ -173,7 +173,7 @@ def intercept_server(server, *interceptors): TypeError: If an interceptor derives from neither UnaryServerInterceptor nor StreamServerInterceptor. """ - from grpc_opentracing.grpcext import _interceptor + from . import _interceptor return _interceptor.intercept_server(server, *interceptors) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py index a6bd328ac68..a1c48d12695 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -3,7 +3,7 @@ import collections import grpc -from grpc_opentracing import grpcext +from .. import grpcext class _UnaryClientInfo( From 19d91ec6cae6e7156fa35bf453fb6f8f2bc4857d Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 23 Mar 2020 22:21:27 -0700 Subject: [PATCH 15/59] Add wait_for_termination --- .../src/opentelemetry/ext/grpc/grpcext/_interceptor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py index a1c48d12695..dfebce90e11 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -365,6 +365,9 @@ def start(self, *args, **kwargs): def stop(self, *args, **kwargs): return self._server.stop(*args, **kwargs) + def wait_for_termination(self, *args, **kwargs): + return self._server.wait_for_termination(*args, **kwargs) + def intercept_server(server, *interceptors): result = server From 5a747103c275af58880cd44eaa74a8455fd354b4 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 11:55:23 -0700 Subject: [PATCH 16/59] Update interceptors, unary examples --- .../examples/hello_world_client.py | 20 +- .../examples/hello_world_server.py | 7 +- .../src/opentelemetry/ext/grpc/_client.py | 154 +++------- .../src/opentelemetry/ext/grpc/_server.py | 290 +++++++++--------- 4 files changed, 195 insertions(+), 276 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_client.py b/ext/opentelemetry-ext-grpc/examples/hello_world_client.py index 7e446c439a7..b0353a61ca6 100755 --- a/ext/opentelemetry-ext-grpc/examples/hello_world_client.py +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_client.py @@ -23,9 +23,20 @@ import helloworld_pb2 import helloworld_pb2_grpc +from opentelemetry import trace from opentelemetry.ext.grpc import client_interceptor +from opentelemetry.ext.grpc.grpcext import intercept_channel +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, +) -interceptor = client_interceptor.OpenTelemetryClientInterceptor() +trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) +trace.tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) +) +tracer = trace.get_tracer(__name__) def run(): @@ -34,10 +45,13 @@ def run(): # of the code. with grpc.insecure_channel("localhost:50051") as channel: - intercepted_channel = grpc.intercept_channel(channel, interceptor) - stub = helloworld_pb2_grpc.GreeterStub(intercepted_channel) + channel = intercept_channel(channel, client_interceptor(tracer)) + stub = helloworld_pb2_grpc.GreeterStub(channel) + + # stub.SayHello is a _InterceptorUnaryUnaryMultiCallable response = stub.SayHello(helloworld_pb2.HelloRequest(name="YOU")) + print("Greeter client received: " + response.message) diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py index 13bbf8bd08c..c702a8d1134 100755 --- a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py @@ -25,6 +25,7 @@ import helloworld_pb2_grpc from opentelemetry import trace from opentelemetry.ext.grpc import server_interceptor +from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( ConsoleSpanExporter, @@ -45,10 +46,8 @@ def SayHello(self, request, context): def serve(): - interceptor = server_interceptor.OpenTelemetryServerInterceptor(tracer) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=10), interceptors=(interceptor,) - ) + server = grpc.server(futures.ThreadPoolExecutor()) + server = intercept_server(server, server_interceptor(tracer)) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) server.add_insecure_port("[::]:50051") diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index b61fb6a25db..512e4b23c70 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -12,21 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Implementation of the invocation-side open-tracing interceptor.""" +"""Implementation of the invocation-side open-telemetry interceptor.""" -import logging -import sys +from collections import OrderedDict +from typing import MutableMapping import grpc -import opentracing -from opentracing.ext import tags as ot_tags -from six import iteritems -from grpc_opentracing import grpcext -from grpc_opentracing._utilities import ( - RpcInfo, - log_or_wrap_request_or_iterator, -) +from opentelemetry import propagators, trace + +from . import grpcext +from ._utilities import RpcInfo class _GuardedSpan(object): @@ -49,70 +45,38 @@ def release(self): return self.span -def _inject_span_context(tracer, span, metadata): - headers = {} - try: - tracer.inject(span.context, opentracing.Format.HTTP_HEADERS, headers) - except ( - opentracing.UnsupportedFormatException, - opentracing.InvalidCarrierException, - opentracing.SpanContextCorruptedException, - ) as e: - logging.exception("tracer.inject() failed") - span.log_kv({"event": "error", "error.object": e}) - return metadata - metadata = () if metadata is None else tuple(metadata) - return metadata + tuple((k.lower(), v) for (k, v) in iteritems(headers)) +def _inject_span_context(metadata: MutableMapping[str, str]) -> None: + def append_metadata( + carrier: MutableMapping[str, str], key: str, value: str + ): + metadata[key] = value + + # Inject current active span from the context + propagators.inject(append_metadata, metadata) -def _make_future_done_callback(span, rpc_info, log_payloads, span_decorator): +def _make_future_done_callback(span, rpc_info): def callback(response_future): with span: code = response_future.code() if code != grpc.StatusCode.OK: - span.set_tag("error", True) - error_log = {"event": "error", "error.kind": str(code)} - details = response_future.details() - if details is not None: - error_log["message"] = details - span.log_kv(error_log) rpc_info.error = code - if span_decorator is not None: - span_decorator(span, rpc_info) return response = response_future.result() rpc_info.response = response - if log_payloads: - span.log_kv({"response": response}) - if span_decorator is not None: - span_decorator(span, rpc_info) return callback -class OpenTracingClientInterceptor( +class OpenTelemetryClientInterceptor( grpcext.UnaryClientInterceptor, grpcext.StreamClientInterceptor ): - def __init__( - self, tracer, active_span_source, log_payloads, span_decorator - ): + def __init__(self, tracer): self._tracer = tracer - self._active_span_source = active_span_source - self._log_payloads = log_payloads - self._span_decorator = span_decorator def _start_span(self, method): - active_span_context = None - if self._active_span_source is not None: - active_span = self._active_span_source.get_active_span() - if active_span is not None: - active_span_context = active_span.context - tags = { - ot_tags.COMPONENT: "grpc", - ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_CLIENT, - } - return self._tracer.start_span( - operation_name=method, child_of=active_span_context, tags=tags + return self._tracer.start_as_current_span( + name=method, kind=trace.SpanKind.CLIENT ) def _trace_result(self, guarded_span, rpc_info, result): @@ -120,12 +84,7 @@ def _trace_result(self, guarded_span, rpc_info, result): # callback so that the span can be finished once the future is done. if isinstance(result, grpc.Future): result.add_done_callback( - _make_future_done_callback( - guarded_span.release(), - rpc_info, - self._log_payloads, - self._span_decorator, - ) + _make_future_done_callback(guarded_span.release(), rpc_info) ) return result response = result @@ -136,10 +95,6 @@ def _trace_result(self, guarded_span, rpc_info, result): if isinstance(result, tuple): response = result[0] rpc_info.response = response - if self._log_payloads: - guarded_span.span.log_kv({"response": response}) - if self._span_decorator is not None: - self._span_decorator(guarded_span.span, rpc_info) return result def _start_guarded_span(self, *args, **kwargs): @@ -147,27 +102,22 @@ def _start_guarded_span(self, *args, **kwargs): def intercept_unary(self, request, metadata, client_info, invoker): with self._start_guarded_span(client_info.full_method) as guarded_span: - metadata = _inject_span_context( - self._tracer, guarded_span.span, metadata - ) + + if not metadata: + mutable_metadata = OrderedDict() + else: + mutable_metadata = OrderedDict(metadata) + + _inject_span_context(mutable_metadata) + metadata = tuple(mutable_metadata.items()) + rpc_info = RpcInfo( full_method=client_info.full_method, metadata=metadata, timeout=client_info.timeout, request=request, ) - if self._log_payloads: - guarded_span.span.log_kv({"request": request}) - try: - result = invoker(request, metadata) - except Exception: - e = sys.exc_info()[0] - guarded_span.span.set_tag("error", True) - guarded_span.span.log_kv({"event": "error", "error.object": e}) - rpc_info.error = e - if self._span_decorator is not None: - self._span_decorator(guarded_span.span, rpc_info) - raise + result = invoker(request, metadata) return self._trace_result(guarded_span, rpc_info, result) # For RPCs that stream responses, the result can be a generator. To record @@ -185,26 +135,11 @@ def _intercept_server_stream( ) if client_info.is_client_stream: rpc_info.request = request_or_iterator - if self._log_payloads: - request_or_iterator = log_or_wrap_request_or_iterator( - span, client_info.is_client_stream, request_or_iterator - ) - try: - result = invoker(request_or_iterator, metadata) - for response in result: - if self._log_payloads: - span.log_kv({"response": response}) - yield response - except Exception: - e = sys.exc_info()[0] - span.set_tag("error", True) - span.log_kv({"event": "error", "error.object": e}) - rpc_info.error = e - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) - raise - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) + result = invoker(request_or_iterator, metadata) + for response in result: + if self._log_payloads: + span.log_kv({"response": response}) + yield response def intercept_stream( self, request_or_iterator, metadata, client_info, invoker @@ -223,20 +158,5 @@ def intercept_stream( timeout=client_info.timeout, request=request_or_iterator, ) - if self._log_payloads: - request_or_iterator = log_or_wrap_request_or_iterator( - guarded_span.span, - client_info.is_client_stream, - request_or_iterator, - ) - try: - result = invoker(request_or_iterator, metadata) - except Exception: - e = sys.exc_info()[0] - guarded_span.span.set_tag("error", True) - guarded_span.span.log_kv({"event": "error", "error.object": e}) - rpc_info.error = e - if self._span_decorator is not None: - self._span_decorator(guarded_span.span, rpc_info) - raise + result = invoker(request_or_iterator, metadata) return self._trace_result(guarded_span, rpc_info, result) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index 16e3d571979..c9d46cd1048 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -12,24 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Implementation of the service-side open-tracing interceptor.""" +"""Implementation of the service-side open-telemetry interceptor. + +This library borrows heavily from the OpenTelemetry gRPC integration: +https://github.com/opentracing-contrib/python-grpc +""" import logging -import re -import sys +from typing import List import grpc -import opentracing -from opentracing.ext import tags as ot_tags -from grpc_opentracing import ActiveSpanSource, grpcext -from grpc_opentracing._utilities import ( - RpcInfo, - log_or_wrap_request_or_iterator, -) +from opentelemetry import propagators, trace +from opentelemetry.context import attach + +from . import grpcext +from ._utilities import RpcInfo -class _OpenTracingServicerContext(grpc.ServicerContext, ActiveSpanSource): +class _OpenTelemetryServicerContext(grpc.ServicerContext): def __init__(self, servicer_context, active_span): self._servicer_context = servicer_context self._active_span = active_span @@ -92,24 +93,21 @@ def set_details(self, details): self.details = details return self._servicer_context.set_details(details) - def get_active_span(self): - return self._active_span - -def _add_peer_tags(peer_str, tags): - ipv4_re = r"ipv4:(?P
.+):(?P\d+)" - match = re.match(ipv4_re, peer_str) - if match: - tags[ot_tags.PEER_HOST_IPV4] = match.group("address") - tags[ot_tags.PEER_PORT] = match.group("port") - return - ipv6_re = r"ipv6:\[(?P
.+)\]:(?P\d+)" - match = re.match(ipv6_re, peer_str) - if match: - tags[ot_tags.PEER_HOST_IPV6] = match.group("address") - tags[ot_tags.PEER_PORT] = match.group("port") - return - logging.warning('Unrecognized peer: "%s"', peer_str) +# def _add_peer_tags(peer_str, tags): +# ipv4_re = r"ipv4:(?P
.+):(?P\d+)" +# match = re.match(ipv4_re, peer_str) +# if match: +# tags[ot_tags.PEER_HOST_IPV4] = match.group("address") +# tags[ot_tags.PEER_PORT] = match.group("port") +# return +# ipv6_re = r"ipv6:\[(?P
.+)\]:(?P\d+)" +# match = re.match(ipv6_re, peer_str) +# if match: +# tags[ot_tags.PEER_HOST_IPV6] = match.group("address") +# tags[ot_tags.PEER_PORT] = match.group("port") +# return +# logging.warning('Unrecognized peer: "%s"', peer_str) # On the service-side, errors can be signaled either by exceptions or by @@ -117,54 +115,68 @@ def _add_peer_tags(peer_str, tags): # latter and updates the span accordingly. def _check_error_code(span, servicer_context, rpc_info): if servicer_context.code != grpc.StatusCode.OK: - span.set_tag("error", True) - error_log = { - "event": "error", - "error.kind": str(servicer_context.code), - } - if servicer_context.details is not None: - error_log["message"] = servicer_context.details - span.log_kv(error_log) + # span.set_tag("error", True) + # error_log = { + # "event": "error", + # "error.kind": str(servicer_context.code), + # } + # if servicer_context.details is not None: + # error_log["message"] = servicer_context.details + # span.log_kv(error_log) rpc_info.error = servicer_context.code -class OpenTracingServerInterceptor( +class OpenTelemetryServerInterceptor( grpcext.UnaryServerInterceptor, grpcext.StreamServerInterceptor ): - def __init__(self, tracer, log_payloads, span_decorator): + def __init__(self, tracer): self._tracer = tracer - self._log_payloads = log_payloads - self._span_decorator = span_decorator def _start_span(self, servicer_context, method): - span_context = None - error = None metadata = servicer_context.invocation_metadata() + error = None + try: if metadata: - span_context = self._tracer.extract( - opentracing.Format.HTTP_HEADERS, dict(metadata) - ) - except ( - opentracing.UnsupportedFormatException, - opentracing.InvalidCarrierException, - opentracing.SpanContextCorruptedException, - ) as e: + md_dict = {md.key: md.value for md in metadata} + + def get_from_grpc_metadata(metadata, key) -> List[str]: + return [md_dict[key]] if key in md_dict else [] + + # set the request-global context! + ctx = propagators.extract(get_from_grpc_metadata, metadata) + attach(ctx) + + except Exception as ex: logging.exception("tracer.extract() failed") - error = e - tags = { - ot_tags.COMPONENT: "grpc", - ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_SERVER, - } - _add_peer_tags(servicer_context.peer(), tags) - span = self._tracer.start_span( - operation_name=method, child_of=span_context, tags=tags + error = ex + + # TODO: set gRPC attributes + # tags = { + # ot_tags.COMPONENT: "grpc", + # ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_SERVER, + # } + + # TODO: set IP attributes + # _add_peer_tags(servicer_context.peer(), tags) + + # span = self._tracer.start_span( + # operation_name=method, child_of=span_context, tags=tags + # ) + + span = self._tracer.start_as_current_span( + name=method, kind=trace.SpanKind.SERVER ) + + # TODO: add error/stacktrace attribute if error is not None: - span.log_kv({"event": "error", "error.object": error}) + pass + # span.log_kv({"event": "error", "error.object": error}) + return span def intercept_unary(self, request, servicer_context, server_info, handler): + with self._start_span( servicer_context, server_info.full_method ) as span: @@ -174,106 +186,80 @@ def intercept_unary(self, request, servicer_context, server_info, handler): timeout=servicer_context.time_remaining(), request=request, ) - if self._log_payloads: - span.log_kv({"request": request}) - servicer_context = _OpenTracingServicerContext( + servicer_context = _OpenTelemetryServicerContext( servicer_context, span ) - try: - response = handler(request, servicer_context) - except Exception: - e = sys.exc_info()[0] - span.set_tag("error", True) - span.log_kv({"event": "error", "error.object": e}) - rpc_info.error = e - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) - raise - if self._log_payloads: - span.log_kv({"response": response}) + response = handler(request, servicer_context) + _check_error_code(span, servicer_context, rpc_info) + rpc_info.response = response - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) + return response - # For RPCs that stream responses, the result can be a generator. To record - # the span across the generated responses and detect any errors, we wrap the - # result in a new generator that yields the response values. - def _intercept_server_stream( - self, request_or_iterator, servicer_context, server_info, handler - ): - with self._start_span( - servicer_context, server_info.full_method - ) as span: - rpc_info = RpcInfo( - full_method=server_info.full_method, - metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining(), - ) - if not server_info.is_client_stream: - rpc_info.request = request_or_iterator - if self._log_payloads: - request_or_iterator = log_or_wrap_request_or_iterator( - span, server_info.is_client_stream, request_or_iterator - ) - servicer_context = _OpenTracingServicerContext( - servicer_context, span - ) - try: - result = handler(request_or_iterator, servicer_context) - for response in result: - if self._log_payloads: - span.log_kv({"response": response}) - yield response - except Exception: - e = sys.exc_info()[0] - span.set_tag("error", True) - span.log_kv({"event": "error", "error.object": e}) - rpc_info.error = e - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) - raise - _check_error_code(span, servicer_context, rpc_info) - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) + # # For RPCs that stream responses, the result can be a generator. To record + # # the span across the generated responses and detect any errors, we wrap the + # # result in a new generator that yields the response values. + # def _intercept_server_stream( + # self, request_or_iterator, servicer_context, server_info, handler + # ): + # with self._start_span( + # servicer_context, server_info.full_method + # ) as span: + # rpc_info = RpcInfo( + # full_method=server_info.full_method, + # metadata=servicer_context.invocation_metadata(), + # timeout=servicer_context.time_remaining(), + # ) + # if not server_info.is_client_stream: + # rpc_info.request = request_or_iterator + # servicer_context = _OpenTelemetryServicerContext( + # servicer_context, span + # ) + # try: + # result = handler(request_or_iterator, servicer_context) + # for response in result: + # yield response + # except Exception: + # e = sys.exc_info()[0] + # span.set_tag("error", True) + # span.log_kv({"event": "error", "error.object": e}) + # rpc_info.error = e + # raise + # _check_error_code(span, servicer_context, rpc_info) def intercept_stream( self, request_or_iterator, servicer_context, server_info, handler ): - if server_info.is_server_stream: - return self._intercept_server_stream( - request_or_iterator, servicer_context, server_info, handler - ) - with self._start_span( - servicer_context, server_info.full_method - ) as span: - rpc_info = RpcInfo( - full_method=server_info.full_method, - metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining(), - ) - if self._log_payloads: - request_or_iterator = log_or_wrap_request_or_iterator( - span, server_info.is_client_stream, request_or_iterator - ) - servicer_context = _OpenTracingServicerContext( - servicer_context, span - ) - try: - response = handler(request_or_iterator, servicer_context) - except Exception: - e = sys.exc_info()[0] - span.set_tag("error", True) - span.log_kv({"event": "error", "error.object": e}) - rpc_info.error = e - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) - raise - if self._log_payloads: - span.log_kv({"response": response}) - _check_error_code(span, servicer_context, rpc_info) - rpc_info.response = response - if self._span_decorator is not None: - self._span_decorator(span, rpc_info) - return response + pass + + # def intercept_stream( + # self, request_or_iterator, servicer_context, server_info, handler + # ): + # """TODO doc and types""" + # if server_info.is_server_stream: + # return self._intercept_server_stream( + # request_or_iterator, servicer_context, server_info, handler + # ) + # with self._start_span( + # servicer_context, server_info.full_method + # ) as span: + # rpc_info = RpcInfo( + # full_method=server_info.full_method, + # metadata=servicer_context.invocation_metadata(), + # timeout=servicer_context.time_remaining(), + # ) + # servicer_context = _OpenTelemetryServicerContext( + # servicer_context, span + # ) + # try: + # response = handler(request_or_iterator, servicer_context) + # except Exception: + # e = sys.exc_info()[0] + # span.set_tag("error", True) + # span.log_kv({"event": "error", "error.object": e}) + # rpc_info.error = e + # raise + # _check_error_code(span, servicer_context, rpc_info) + # rpc_info.response = response + # return response From b597a803df728da5f58e82a21ba91c3c13974e3a Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 12:24:17 -0700 Subject: [PATCH 17/59] Use get/set_tracer_provider --- ext/opentelemetry-ext-grpc/examples/hello_world_client.py | 4 ++-- ext/opentelemetry-ext-grpc/examples/hello_world_server.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_client.py b/ext/opentelemetry-ext-grpc/examples/hello_world_client.py index b0353a61ca6..7c7625057bc 100755 --- a/ext/opentelemetry-ext-grpc/examples/hello_world_client.py +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_client.py @@ -32,8 +32,8 @@ SimpleExportSpanProcessor, ) -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) -trace.tracer_provider().add_span_processor( +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) ) tracer = trace.get_tracer(__name__) diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py index c702a8d1134..46938f5226d 100755 --- a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py +++ b/ext/opentelemetry-ext-grpc/examples/hello_world_server.py @@ -32,8 +32,8 @@ SimpleExportSpanProcessor, ) -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) -trace.tracer_provider().add_span_processor( +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) ) tracer = trace.get_tracer(__name__) From f24f8267a76378d1deb8040d76dc73e59edfe17c Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 12:29:48 -0700 Subject: [PATCH 18/59] Add gRPC route guide streaming examples --- .../examples/route_guide.proto | 108 ++++ .../examples/route_guide_client.py | 142 +++++ .../examples/route_guide_db.json | 601 ++++++++++++++++++ .../examples/route_guide_resources.py | 40 ++ .../examples/route_guide_server.py | 135 ++++ 5 files changed, 1026 insertions(+) create mode 100644 ext/opentelemetry-ext-grpc/examples/route_guide.proto create mode 100755 ext/opentelemetry-ext-grpc/examples/route_guide_client.py create mode 100644 ext/opentelemetry-ext-grpc/examples/route_guide_db.json create mode 100644 ext/opentelemetry-ext-grpc/examples/route_guide_resources.py create mode 100755 ext/opentelemetry-ext-grpc/examples/route_guide_server.py diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide.proto b/ext/opentelemetry-ext-grpc/examples/route_guide.proto new file mode 100644 index 00000000000..777f48325a6 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide.proto @@ -0,0 +1,108 @@ +// Copyright 2020, OpenTelemetry 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. + +// https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto + +syntax = "proto3"; + +package routeguide; + +// Interface exported by the server. +service RouteGuide { + // A simple RPC. + // + // Obtains the feature at a given position. + // + // A feature with an empty name is returned if there's no feature at the given + // position. + rpc GetFeature(Point) returns (Feature) {} + + // A server-to-client streaming RPC. + // + // Obtains the Features available within the given Rectangle. Results are + // streamed rather than returned at once (e.g. in a response message with a + // repeated field), as the rectangle may cover a large area and contain a + // huge number of features. + rpc ListFeatures(Rectangle) returns (stream Feature) {} + + // A client-to-server streaming RPC. + // + // Accepts a stream of Points on a route being traversed, returning a + // RouteSummary when traversal is completed. + rpc RecordRoute(stream Point) returns (RouteSummary) {} + + // A Bidirectional streaming RPC. + // + // Accepts a stream of RouteNotes sent while a route is being traversed, + // while receiving other RouteNotes (e.g. from other users). + rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} +} + +// Points are represented as latitude-longitude pairs in the E7 representation +// (degrees multiplied by 10**7 and rounded to the nearest integer). +// Latitudes should be in the range +/- 90 degrees and longitude should be in +// the range +/- 180 degrees (inclusive). +message Point { + int32 latitude = 1; + int32 longitude = 2; +} + +// A latitude-longitude rectangle, represented as two diagonally opposite +// points "lo" and "hi". +message Rectangle { + // One corner of the rectangle. + Point lo = 1; + + // The other corner of the rectangle. + Point hi = 2; +} + +// A feature names something at a given point. +// +// If a feature could not be named, the name is empty. +message Feature { + // The name of the feature. + string name = 1; + + // The point where the feature is detected. + Point location = 2; +} + +// A RouteNote is a message sent while at a given point. +message RouteNote { + // The location from which the message is sent. + Point location = 1; + + // The message to be sent. + string message = 2; +} + +// A RouteSummary is received in response to a RecordRoute rpc. +// +// It contains the number of individual points received, the number of +// detected features, and the total distance covered as the cumulative sum of +// the distance between each point. +message RouteSummary { + // The number of points received. + int32 point_count = 1; + + // The number of known features passed while traversing the route. + int32 feature_count = 2; + + // The distance covered in metres. + int32 distance = 3; + + // The duration of the traversal in seconds. + int32 elapsed_time = 4; +} diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_client.py b/ext/opentelemetry-ext-grpc/examples/route_guide_client.py new file mode 100755 index 00000000000..ee3087feac5 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_client.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# Copyright 2020, OpenTelemetry 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. + +# https://github.com/grpc/grpc/tree/master/examples/python/route_guide + +"""The Python implementation of the gRPC route guide client.""" + +import random + +import grpc + +import route_guide_pb2 +import route_guide_pb2_grpc +import route_guide_resources +from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, +) + +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) +) +tracer = trace.get_tracer(__name__) + + +def make_route_note(message, latitude, longitude): + return route_guide_pb2.RouteNote( + message=message, + location=route_guide_pb2.Point(latitude=latitude, longitude=longitude), + ) + + +def guide_get_one_feature(stub, point): + feature = stub.GetFeature(point) + if not feature.location: + print("Server returned incomplete feature") + return + + if feature.name: + print("Feature called %s at %s" % (feature.name, feature.location)) + else: + print("Found no feature at %s" % feature.location) + + +def guide_get_feature(stub): + guide_get_one_feature( + stub, route_guide_pb2.Point(latitude=409146138, longitude=-746188906) + ) + guide_get_one_feature(stub, route_guide_pb2.Point(latitude=0, longitude=0)) + + +def guide_list_features(stub): + rectangle = route_guide_pb2.Rectangle( + lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000), + hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000), + ) + print("Looking for features between 40, -75 and 42, -73") + + features = stub.ListFeatures(rectangle) + + for feature in features: + print("Feature called %s at %s" % (feature.name, feature.location)) + + +def generate_route(feature_list): + for _ in range(0, 10): + random_feature = feature_list[random.randint(0, len(feature_list) - 1)] + print("Visiting point %s" % random_feature.location) + yield random_feature.location + + +def guide_record_route(stub): + feature_list = route_guide_resources.read_route_guide_database() + + route_iterator = generate_route(feature_list) + route_summary = stub.RecordRoute(route_iterator) + print("Finished trip with %s points " % route_summary.point_count) + print("Passed %s features " % route_summary.feature_count) + print("Travelled %s meters " % route_summary.distance) + print("It took %s seconds " % route_summary.elapsed_time) + + +def generate_messages(): + messages = [ + make_route_note("First message", 0, 0), + make_route_note("Second message", 0, 1), + make_route_note("Third message", 1, 0), + make_route_note("Fourth message", 0, 0), + make_route_note("Fifth message", 1, 0), + ] + for msg in messages: + print("Sending %s at %s" % (msg.message, msg.location)) + yield msg + + +def guide_route_chat(stub): + responses = stub.RouteChat(generate_messages()) + for response in responses: + print( + "Received message %s at %s" % (response.message, response.location) + ) + + +def run(): + + from opentelemetry.ext.grpc.grpcext import intercept_channel + from opentelemetry.ext.grpc import client_interceptor + + # NOTE(gRPC Python Team): .close() is possible on a channel and should be + # used in circumstances in which the with statement does not fit the needs + # of the code. + with grpc.insecure_channel("localhost:50051") as channel: + channel = intercept_channel(channel, client_interceptor(tracer)) + + stub = route_guide_pb2_grpc.RouteGuideStub(channel) + print("-------------- GetFeature --------------") + guide_get_feature(stub) + print("-------------- ListFeatures --------------") + guide_list_features(stub) + print("-------------- RecordRoute --------------") + guide_record_route(stub) + print("-------------- RouteChat --------------") + guide_route_chat(stub) + + +if __name__ == "__main__": + run() diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_db.json b/ext/opentelemetry-ext-grpc/examples/route_guide_db.json new file mode 100644 index 00000000000..9d6a980ab7d --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_db.json @@ -0,0 +1,601 @@ +[{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" +}, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" +}, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" +}, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" +}, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" +}, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" +}, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" +}, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" +}, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" +}, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" +}, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" +}, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" +}, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" +}, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" +}, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" +}, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" +}, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" +}, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" +}, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" +}, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" +}, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" +}, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" +}, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" +}, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" +}, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" +}, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" +}, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" +}, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" +}, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" +}, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" +}, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" +}, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" +}, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" +}, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" +}, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" +}, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" +}, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" +}, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" +}, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" +}, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" +}, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" +}, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" +}, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" +}, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" +}, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" +}, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" +}, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" +}, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" +}, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" +}, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" +}, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" +}, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" +}, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" +}, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" +}, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" +}, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" +}, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" +}, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" +}, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" +}, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" +}, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" +}, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" +}, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" +}, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" +}, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" +}, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" +}, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" +}, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" +}, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" +}, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" +}, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" +}, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" +}, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" +}, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" +}, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" +}, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" +}, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" +}, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" +}, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" +}, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" +}, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" +}, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" +}, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" +}, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" +}, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" +}, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" +}, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" +}, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" +}, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" +}, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" +}, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" +}, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" +}, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" +}, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" +}, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" +}, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" +}] diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_resources.py b/ext/opentelemetry-ext-grpc/examples/route_guide_resources.py new file mode 100644 index 00000000000..495f7dcc7a5 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_resources.py @@ -0,0 +1,40 @@ +# Copyright 2020, OpenTelemetry 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. + +# https://github.com/grpc/grpc/tree/master/examples/python/route_guide + +"""Common resources used in the gRPC route guide example.""" + +import json + +import route_guide_pb2 + + +def read_route_guide_database(): + """Reads the route guide database. + + Returns: + The full contents of the route guide database as a sequence of + route_guide_pb2.Features. + """ + feature_list = [] + with open("route_guide_db.json") as route_guide_db_file: + for item in json.load(route_guide_db_file): + feature = route_guide_pb2.Feature( + name=item["name"], + location=route_guide_pb2.Point( + latitude=item["location"]["latitude"], + longitude=item["location"]["longitude"])) + feature_list.append(feature) + return feature_list diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_server.py b/ext/opentelemetry-ext-grpc/examples/route_guide_server.py new file mode 100755 index 00000000000..5c81adb1fc3 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_server.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# Copyright 2020, OpenTelemetry 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. + +# https://github.com/grpc/grpc/tree/master/examples/python/route_guide + +"""The Python implementation of the gRPC route guide server.""" + +import logging +import math +import time +from concurrent import futures + +import grpc + +import route_guide_pb2 +import route_guide_pb2_grpc +import route_guide_resources + + +def get_feature(feature_db, point): + """Returns Feature at given location or None.""" + for feature in feature_db: + if feature.location == point: + return feature + return None + + +def get_distance(start, end): + """Distance between two points.""" + coord_factor = 10000000.0 + lat_1 = start.latitude / coord_factor + lat_2 = end.latitude / coord_factor + lon_1 = start.longitude / coord_factor + lon_2 = end.longitude / coord_factor + lat_rad_1 = math.radians(lat_1) + lat_rad_2 = math.radians(lat_2) + delta_lat_rad = math.radians(lat_2 - lat_1) + delta_lon_rad = math.radians(lon_2 - lon_1) + + # Formula is based on http://mathforum.org/library/drmath/view/51879.html + a = pow(math.sin(delta_lat_rad / 2), 2) + ( + math.cos(lat_rad_1) + * math.cos(lat_rad_2) + * pow(math.sin(delta_lon_rad / 2), 2) + ) + c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) + R = 6371000 + # metres + return R * c + + +class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer): + """Provides methods that implement functionality of route guide server.""" + + def __init__(self): + self.db = route_guide_resources.read_route_guide_database() + + def GetFeature(self, request, context): + feature = get_feature(self.db, request) + if feature is None: + return route_guide_pb2.Feature(name="", location=request) + else: + return feature + + def ListFeatures(self, request, context): + left = min(request.lo.longitude, request.hi.longitude) + right = max(request.lo.longitude, request.hi.longitude) + top = max(request.lo.latitude, request.hi.latitude) + bottom = min(request.lo.latitude, request.hi.latitude) + for feature in self.db: + if ( + feature.location.longitude >= left + and feature.location.longitude <= right + and feature.location.latitude >= bottom + and feature.location.latitude <= top + ): + yield feature + + def RecordRoute(self, request_iterator, context): + point_count = 0 + feature_count = 0 + distance = 0.0 + prev_point = None + + start_time = time.time() + for point in request_iterator: + point_count += 1 + if get_feature(self.db, point): + feature_count += 1 + if prev_point: + distance += get_distance(prev_point, point) + prev_point = point + + elapsed_time = time.time() - start_time + return route_guide_pb2.RouteSummary( + point_count=point_count, + feature_count=feature_count, + distance=int(distance), + elapsed_time=int(elapsed_time), + ) + + def RouteChat(self, request_iterator, context): + prev_notes = [] + for new_note in request_iterator: + for prev_note in prev_notes: + if prev_note.location == new_note.location: + yield prev_note + prev_notes.append(new_note) + + +def serve(): + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + route_guide_pb2_grpc.add_RouteGuideServicer_to_server( + RouteGuideServicer(), server + ) + server.add_insecure_port("[::]:50051") + server.start() + server.wait_for_termination() + + +if __name__ == "__main__": + logging.basicConfig() + serve() From 6a104ccd2510c3cdf9ccb2357964373d5eeade85 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 12:30:39 -0700 Subject: [PATCH 19/59] Update generated gRPC files --- .../examples/codegen.py | 8 +- .../examples/helloworld_pb2.py | 5 +- .../examples/route_guide_pb2.py | 328 ++++++++++++++++++ .../examples/route_guide_pb2_grpc.py | 113 ++++++ 4 files changed, 450 insertions(+), 4 deletions(-) create mode 100644 ext/opentelemetry-ext-grpc/examples/route_guide_pb2.py create mode 100644 ext/opentelemetry-ext-grpc/examples/route_guide_pb2_grpc.py diff --git a/ext/opentelemetry-ext-grpc/examples/codegen.py b/ext/opentelemetry-ext-grpc/examples/codegen.py index 6e2afcb347e..5a7cc13d64f 100755 --- a/ext/opentelemetry-ext-grpc/examples/codegen.py +++ b/ext/opentelemetry-ext-grpc/examples/codegen.py @@ -18,7 +18,13 @@ def main(): return protoc.main( - ["-I.", "--python_out=.", "--grpc_python_out=.", "helloworld.proto"] + [ + "-I.", + "--python_out=.", + "--grpc_python_out=.", + "helloworld.proto", + "route_guide.proto", + ] ) diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py b/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py index 14f6f161da5..0e37874ebc2 100644 --- a/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py +++ b/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py @@ -17,8 +17,8 @@ name='helloworld.proto', package='helloworld', syntax='proto3', - serialized_options=b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW', - serialized_pb=b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3' + serialized_options=None, + serialized_pb=b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x62\x06proto3' ) @@ -104,7 +104,6 @@ _sym_db.RegisterMessage(HelloReply) -DESCRIPTOR._options = None _GREETER = _descriptor.ServiceDescriptor( name='Greeter', diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_pb2.py b/ext/opentelemetry-ext-grpc/examples/route_guide_pb2.py new file mode 100644 index 00000000000..4a4006a2c77 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_pb2.py @@ -0,0 +1,328 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: route_guide.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='route_guide.proto', + package='routeguide', + syntax='proto3', + serialized_options=None, + serialized_pb=b'\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x62\x06proto3' +) + + + + +_POINT = _descriptor.Descriptor( + name='Point', + full_name='routeguide.Point', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='latitude', full_name='routeguide.Point.latitude', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='longitude', full_name='routeguide.Point.longitude', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=33, + serialized_end=77, +) + + +_RECTANGLE = _descriptor.Descriptor( + name='Rectangle', + full_name='routeguide.Rectangle', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='lo', full_name='routeguide.Rectangle.lo', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='hi', full_name='routeguide.Rectangle.hi', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=79, + serialized_end=152, +) + + +_FEATURE = _descriptor.Descriptor( + name='Feature', + full_name='routeguide.Feature', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='routeguide.Feature.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='location', full_name='routeguide.Feature.location', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=154, + serialized_end=214, +) + + +_ROUTENOTE = _descriptor.Descriptor( + name='RouteNote', + full_name='routeguide.RouteNote', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='location', full_name='routeguide.RouteNote.location', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message', full_name='routeguide.RouteNote.message', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=216, + serialized_end=281, +) + + +_ROUTESUMMARY = _descriptor.Descriptor( + name='RouteSummary', + full_name='routeguide.RouteSummary', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='point_count', full_name='routeguide.RouteSummary.point_count', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='feature_count', full_name='routeguide.RouteSummary.feature_count', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='distance', full_name='routeguide.RouteSummary.distance', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='elapsed_time', full_name='routeguide.RouteSummary.elapsed_time', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=283, + serialized_end=381, +) + +_RECTANGLE.fields_by_name['lo'].message_type = _POINT +_RECTANGLE.fields_by_name['hi'].message_type = _POINT +_FEATURE.fields_by_name['location'].message_type = _POINT +_ROUTENOTE.fields_by_name['location'].message_type = _POINT +DESCRIPTOR.message_types_by_name['Point'] = _POINT +DESCRIPTOR.message_types_by_name['Rectangle'] = _RECTANGLE +DESCRIPTOR.message_types_by_name['Feature'] = _FEATURE +DESCRIPTOR.message_types_by_name['RouteNote'] = _ROUTENOTE +DESCRIPTOR.message_types_by_name['RouteSummary'] = _ROUTESUMMARY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), { + 'DESCRIPTOR' : _POINT, + '__module__' : 'route_guide_pb2' + # @@protoc_insertion_point(class_scope:routeguide.Point) + }) +_sym_db.RegisterMessage(Point) + +Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), { + 'DESCRIPTOR' : _RECTANGLE, + '__module__' : 'route_guide_pb2' + # @@protoc_insertion_point(class_scope:routeguide.Rectangle) + }) +_sym_db.RegisterMessage(Rectangle) + +Feature = _reflection.GeneratedProtocolMessageType('Feature', (_message.Message,), { + 'DESCRIPTOR' : _FEATURE, + '__module__' : 'route_guide_pb2' + # @@protoc_insertion_point(class_scope:routeguide.Feature) + }) +_sym_db.RegisterMessage(Feature) + +RouteNote = _reflection.GeneratedProtocolMessageType('RouteNote', (_message.Message,), { + 'DESCRIPTOR' : _ROUTENOTE, + '__module__' : 'route_guide_pb2' + # @@protoc_insertion_point(class_scope:routeguide.RouteNote) + }) +_sym_db.RegisterMessage(RouteNote) + +RouteSummary = _reflection.GeneratedProtocolMessageType('RouteSummary', (_message.Message,), { + 'DESCRIPTOR' : _ROUTESUMMARY, + '__module__' : 'route_guide_pb2' + # @@protoc_insertion_point(class_scope:routeguide.RouteSummary) + }) +_sym_db.RegisterMessage(RouteSummary) + + + +_ROUTEGUIDE = _descriptor.ServiceDescriptor( + name='RouteGuide', + full_name='routeguide.RouteGuide', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=384, + serialized_end=645, + methods=[ + _descriptor.MethodDescriptor( + name='GetFeature', + full_name='routeguide.RouteGuide.GetFeature', + index=0, + containing_service=None, + input_type=_POINT, + output_type=_FEATURE, + serialized_options=None, + ), + _descriptor.MethodDescriptor( + name='ListFeatures', + full_name='routeguide.RouteGuide.ListFeatures', + index=1, + containing_service=None, + input_type=_RECTANGLE, + output_type=_FEATURE, + serialized_options=None, + ), + _descriptor.MethodDescriptor( + name='RecordRoute', + full_name='routeguide.RouteGuide.RecordRoute', + index=2, + containing_service=None, + input_type=_POINT, + output_type=_ROUTESUMMARY, + serialized_options=None, + ), + _descriptor.MethodDescriptor( + name='RouteChat', + full_name='routeguide.RouteGuide.RouteChat', + index=3, + containing_service=None, + input_type=_ROUTENOTE, + output_type=_ROUTENOTE, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_ROUTEGUIDE) + +DESCRIPTOR.services_by_name['RouteGuide'] = _ROUTEGUIDE + +# @@protoc_insertion_point(module_scope) diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_pb2_grpc.py b/ext/opentelemetry-ext-grpc/examples/route_guide_pb2_grpc.py new file mode 100644 index 00000000000..05c1b793128 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_pb2_grpc.py @@ -0,0 +1,113 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import route_guide_pb2 as route__guide__pb2 + + +class RouteGuideStub(object): + """Interface exported by the server. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GetFeature = channel.unary_unary( + '/routeguide.RouteGuide/GetFeature', + request_serializer=route__guide__pb2.Point.SerializeToString, + response_deserializer=route__guide__pb2.Feature.FromString, + ) + self.ListFeatures = channel.unary_stream( + '/routeguide.RouteGuide/ListFeatures', + request_serializer=route__guide__pb2.Rectangle.SerializeToString, + response_deserializer=route__guide__pb2.Feature.FromString, + ) + self.RecordRoute = channel.stream_unary( + '/routeguide.RouteGuide/RecordRoute', + request_serializer=route__guide__pb2.Point.SerializeToString, + response_deserializer=route__guide__pb2.RouteSummary.FromString, + ) + self.RouteChat = channel.stream_stream( + '/routeguide.RouteGuide/RouteChat', + request_serializer=route__guide__pb2.RouteNote.SerializeToString, + response_deserializer=route__guide__pb2.RouteNote.FromString, + ) + + +class RouteGuideServicer(object): + """Interface exported by the server. + """ + + def GetFeature(self, request, context): + """A simple RPC. + + Obtains the feature at a given position. + + A feature with an empty name is returned if there's no feature at the given + position. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def ListFeatures(self, request, context): + """A server-to-client streaming RPC. + + Obtains the Features available within the given Rectangle. Results are + streamed rather than returned at once (e.g. in a response message with a + repeated field), as the rectangle may cover a large area and contain a + huge number of features. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def RecordRoute(self, request_iterator, context): + """A client-to-server streaming RPC. + + Accepts a stream of Points on a route being traversed, returning a + RouteSummary when traversal is completed. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def RouteChat(self, request_iterator, context): + """A Bidirectional streaming RPC. + + Accepts a stream of RouteNotes sent while a route is being traversed, + while receiving other RouteNotes (e.g. from other users). + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_RouteGuideServicer_to_server(servicer, server): + rpc_method_handlers = { + 'GetFeature': grpc.unary_unary_rpc_method_handler( + servicer.GetFeature, + request_deserializer=route__guide__pb2.Point.FromString, + response_serializer=route__guide__pb2.Feature.SerializeToString, + ), + 'ListFeatures': grpc.unary_stream_rpc_method_handler( + servicer.ListFeatures, + request_deserializer=route__guide__pb2.Rectangle.FromString, + response_serializer=route__guide__pb2.Feature.SerializeToString, + ), + 'RecordRoute': grpc.stream_unary_rpc_method_handler( + servicer.RecordRoute, + request_deserializer=route__guide__pb2.Point.FromString, + response_serializer=route__guide__pb2.RouteSummary.SerializeToString, + ), + 'RouteChat': grpc.stream_stream_rpc_method_handler( + servicer.RouteChat, + request_deserializer=route__guide__pb2.RouteNote.FromString, + response_serializer=route__guide__pb2.RouteNote.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'routeguide.RouteGuide', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) From 58469385fab0bacd7577993c04a8168abd0d72e2 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 13:04:50 -0700 Subject: [PATCH 20/59] Instrument gRPC examples --- .../examples/route_guide_client.py | 15 ++++++++++++--- .../examples/route_guide_server.py | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_client.py b/ext/opentelemetry-ext-grpc/examples/route_guide_client.py index ee3087feac5..857c792c0bc 100755 --- a/ext/opentelemetry-ext-grpc/examples/route_guide_client.py +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_client.py @@ -17,6 +17,7 @@ """The Python implementation of the gRPC route guide client.""" +import logging import random import grpc @@ -25,6 +26,8 @@ import route_guide_pb2_grpc import route_guide_resources from opentelemetry import trace +from opentelemetry.ext.grpc import client_interceptor +from opentelemetry.ext.grpc.grpcext import intercept_channel from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( ConsoleSpanExporter, @@ -118,9 +121,6 @@ def guide_route_chat(stub): def run(): - from opentelemetry.ext.grpc.grpcext import intercept_channel - from opentelemetry.ext.grpc import client_interceptor - # NOTE(gRPC Python Team): .close() is possible on a channel and should be # used in circumstances in which the with statement does not fit the needs # of the code. @@ -128,15 +128,24 @@ def run(): channel = intercept_channel(channel, client_interceptor(tracer)) stub = route_guide_pb2_grpc.RouteGuideStub(channel) + + # Unary print("-------------- GetFeature --------------") guide_get_feature(stub) + + # Server streaming print("-------------- ListFeatures --------------") guide_list_features(stub) + + # Client streaming print("-------------- RecordRoute --------------") guide_record_route(stub) + + # Bidirectional streaming print("-------------- RouteChat --------------") guide_route_chat(stub) if __name__ == "__main__": + logging.basicConfig() run() diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_server.py b/ext/opentelemetry-ext-grpc/examples/route_guide_server.py index 5c81adb1fc3..3b73f5da068 100755 --- a/ext/opentelemetry-ext-grpc/examples/route_guide_server.py +++ b/ext/opentelemetry-ext-grpc/examples/route_guide_server.py @@ -27,6 +27,20 @@ import route_guide_pb2 import route_guide_pb2_grpc import route_guide_resources +from opentelemetry import trace +from opentelemetry.ext.grpc import server_interceptor +from opentelemetry.ext.grpc.grpcext import intercept_server +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, +) + +trace.set_tracer_provider(TracerProvider()) +trace.get_tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) +) +tracer = trace.get_tracer(__name__) def get_feature(feature_db, point): @@ -122,6 +136,8 @@ def RouteChat(self, request_iterator, context): def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + server = intercept_server(server, server_interceptor(tracer)) + route_guide_pb2_grpc.add_RouteGuideServicer_to_server( RouteGuideServicer(), server ) From 82a78de3a0216f9627a314ad932adaa5cee51b61 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 13:05:16 -0700 Subject: [PATCH 21/59] Handle streaming requests/responses in client --- .../src/opentelemetry/ext/grpc/_client.py | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index 512e4b23c70..81a7a0ef96e 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -101,13 +101,12 @@ def _start_guarded_span(self, *args, **kwargs): return _GuardedSpan(self._start_span(*args, **kwargs)) def intercept_unary(self, request, metadata, client_info, invoker): - with self._start_guarded_span(client_info.full_method) as guarded_span: - - if not metadata: - mutable_metadata = OrderedDict() - else: - mutable_metadata = OrderedDict(metadata) + if not metadata: + mutable_metadata = OrderedDict() + else: + mutable_metadata = OrderedDict(metadata) + with self._start_guarded_span(client_info.full_method) as guarded_span: _inject_span_context(mutable_metadata) metadata = tuple(mutable_metadata.items()) @@ -126,8 +125,14 @@ def intercept_unary(self, request, metadata, client_info, invoker): def _intercept_server_stream( self, request_or_iterator, metadata, client_info, invoker ): - with self._start_span(client_info.full_method) as span: - metadata = _inject_span_context(self._tracer, span, metadata) + if not metadata: + mutable_metadata = OrderedDict() + else: + mutable_metadata = OrderedDict(metadata) + + with self._start_span(client_info.full_method): + _inject_span_context(mutable_metadata) + metadata = tuple(mutable_metadata.items()) rpc_info = RpcInfo( full_method=client_info.full_method, metadata=metadata, @@ -137,8 +142,6 @@ def _intercept_server_stream( rpc_info.request = request_or_iterator result = invoker(request_or_iterator, metadata) for response in result: - if self._log_payloads: - span.log_kv({"response": response}) yield response def intercept_stream( @@ -148,10 +151,15 @@ def intercept_stream( return self._intercept_server_stream( request_or_iterator, metadata, client_info, invoker ) + + if not metadata: + mutable_metadata = OrderedDict() + else: + mutable_metadata = OrderedDict(metadata) + with self._start_guarded_span(client_info.full_method) as guarded_span: - metadata = _inject_span_context( - self._tracer, guarded_span.span, metadata - ) + _inject_span_context(mutable_metadata) + metadata = tuple(mutable_metadata.items()) rpc_info = RpcInfo( full_method=client_info.full_method, metadata=metadata, From aa79c70c0dc324ccb73af0ca9ce74aec513cc94b Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 13:12:12 -0700 Subject: [PATCH 22/59] Handle streaming requests/responses in server --- .../src/opentelemetry/ext/grpc/_server.py | 104 +++++++----------- 1 file changed, 42 insertions(+), 62 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index c9d46cd1048..eea8569479a 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -197,69 +197,49 @@ def intercept_unary(self, request, servicer_context, server_info, handler): return response - # # For RPCs that stream responses, the result can be a generator. To record - # # the span across the generated responses and detect any errors, we wrap the - # # result in a new generator that yields the response values. - # def _intercept_server_stream( - # self, request_or_iterator, servicer_context, server_info, handler - # ): - # with self._start_span( - # servicer_context, server_info.full_method - # ) as span: - # rpc_info = RpcInfo( - # full_method=server_info.full_method, - # metadata=servicer_context.invocation_metadata(), - # timeout=servicer_context.time_remaining(), - # ) - # if not server_info.is_client_stream: - # rpc_info.request = request_or_iterator - # servicer_context = _OpenTelemetryServicerContext( - # servicer_context, span - # ) - # try: - # result = handler(request_or_iterator, servicer_context) - # for response in result: - # yield response - # except Exception: - # e = sys.exc_info()[0] - # span.set_tag("error", True) - # span.log_kv({"event": "error", "error.object": e}) - # rpc_info.error = e - # raise - # _check_error_code(span, servicer_context, rpc_info) + # For RPCs that stream responses, the result can be a generator. To record + # the span across the generated responses and detect any errors, we wrap + # the result in a new generator that yields the response values. + def _intercept_server_stream( + self, request_or_iterator, servicer_context, server_info, handler + ): + with self._start_span( + servicer_context, server_info.full_method + ) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining(), + ) + if not server_info.is_client_stream: + rpc_info.request = request_or_iterator + servicer_context = _OpenTelemetryServicerContext( + servicer_context, span + ) + result = handler(request_or_iterator, servicer_context) + for response in result: + yield response + _check_error_code(span, servicer_context, rpc_info) def intercept_stream( self, request_or_iterator, servicer_context, server_info, handler ): - pass - - # def intercept_stream( - # self, request_or_iterator, servicer_context, server_info, handler - # ): - # """TODO doc and types""" - # if server_info.is_server_stream: - # return self._intercept_server_stream( - # request_or_iterator, servicer_context, server_info, handler - # ) - # with self._start_span( - # servicer_context, server_info.full_method - # ) as span: - # rpc_info = RpcInfo( - # full_method=server_info.full_method, - # metadata=servicer_context.invocation_metadata(), - # timeout=servicer_context.time_remaining(), - # ) - # servicer_context = _OpenTelemetryServicerContext( - # servicer_context, span - # ) - # try: - # response = handler(request_or_iterator, servicer_context) - # except Exception: - # e = sys.exc_info()[0] - # span.set_tag("error", True) - # span.log_kv({"event": "error", "error.object": e}) - # rpc_info.error = e - # raise - # _check_error_code(span, servicer_context, rpc_info) - # rpc_info.response = response - # return response + if server_info.is_server_stream: + return self._intercept_server_stream( + request_or_iterator, servicer_context, server_info, handler + ) + with self._start_span( + servicer_context, server_info.full_method + ) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining(), + ) + servicer_context = _OpenTelemetryServicerContext( + servicer_context, span + ) + response = handler(request_or_iterator, servicer_context) + _check_error_code(span, servicer_context, rpc_info) + rpc_info.response = response + return response From 38456040dd8e79a86e7c7d635d3bca412acbb4fd Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 17:10:38 -0700 Subject: [PATCH 23/59] Update server tests --- .../tests/test_server_interceptor.py | 244 ++++++++++++++++-- 1 file changed, 222 insertions(+), 22 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 6a89f10ea7d..fbaae5dee7d 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -17,11 +17,14 @@ from concurrent import futures from contextlib import contextmanager from unittest import mock +from unittest.mock import patch import grpc -from opentelemetry import trace +from opentelemetry import context, trace +from opentelemetry.context.threadlocal_context import ThreadLocalRuntimeContext from opentelemetry.ext.grpc import server_interceptor +from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk import trace as trace_sdk @@ -37,6 +40,22 @@ def __init__(self, handler): self.stream_stream = None +# lifted from +# https://github.com/grpc/grpc/blob/694f491e06b3503952ca5053c98493cf48af43c1/src/python/grpcio_tests/tests/unit/_interceptor_test.py + + +_SERIALIZE_REQUEST = lambda bytestring: bytestring * 2 +_DESERIALIZE_REQUEST = lambda bytestring: bytestring[len(bytestring) // 2 :] +_SERIALIZE_RESPONSE = lambda bytestring: bytestring * 3 +_DESERIALIZE_RESPONSE = lambda bytestring: bytestring[: len(bytestring) // 3] + + +_UNARY_UNARY = "/test/UnaryUnary" +_UNARY_STREAM = "/test/UnaryStream" +_STREAM_UNARY = "/test/StreamUnary" +_STREAM_STREAM = "/test/StreamStream" + + class UnaryUnaryRpcHandler(grpc.GenericRpcHandler): def __init__(self, handler): self._unary_unary_handler = handler @@ -45,7 +64,144 @@ def service(self, handler_call_details): return UnaryUnaryMethodHandler(self._unary_unary_handler) +class _Handler(object): + def __init__(self, control): + self._control = control + + def handle_unary_unary(self, request, servicer_context): + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) + if request == _EXCEPTION_REQUEST: + raise _ApplicationErrorStandin() + return request + + def handle_unary_stream(self, request, servicer_context): + if request == _EXCEPTION_REQUEST: + raise _ApplicationErrorStandin() + for _ in range(test_constants.STREAM_LENGTH): + self._control.control() + yield request + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) + + def handle_stream_unary(self, request_iterator, servicer_context): + if servicer_context is not None: + servicer_context.invocation_metadata() + self._control.control() + response_elements = [] + for request in request_iterator: + self._control.control() + response_elements.append(request) + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) + if _EXCEPTION_REQUEST in response_elements: + raise _ApplicationErrorStandin() + return b"".join(response_elements) + + def handle_stream_stream(self, request_iterator, servicer_context): + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) + for request in request_iterator: + if request == _EXCEPTION_REQUEST: + raise _ApplicationErrorStandin() + self._control.control() + yield request + self._control.control() + + +class _MethodHandler(grpc.RpcMethodHandler): + def __init__( + self, + request_streaming, + response_streaming, + request_deserializer, + response_serializer, + unary_unary, + unary_stream, + stream_unary, + stream_stream, + ): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = request_deserializer + self.response_serializer = response_serializer + self.unary_unary = unary_unary + self.unary_stream = unary_stream + self.stream_unary = stream_unary + self.stream_stream = stream_stream + + +class _GenericHandler(grpc.GenericRpcHandler): + def __init__(self, handler): + self._handler = handler + + def service(self, handler_call_details): + if handler_call_details.method == _UNARY_UNARY: + return _MethodHandler( + False, + False, + None, + None, + self._handler.handle_unary_unary, + None, + None, + None, + ) + elif handler_call_details.method == _UNARY_STREAM: + return _MethodHandler( + False, + True, + _DESERIALIZE_REQUEST, + _SERIALIZE_RESPONSE, + None, + self._handler.handle_unary_stream, + None, + None, + ) + elif handler_call_details.method == _STREAM_UNARY: + return _MethodHandler( + True, + False, + _DESERIALIZE_REQUEST, + _SERIALIZE_RESPONSE, + None, + None, + self._handler.handle_stream_unary, + None, + ) + elif handler_call_details.method == _STREAM_STREAM: + return _MethodHandler( + True, + True, + None, + None, + None, + None, + None, + self._handler.handle_stream_stream, + ) + else: + return None + + class TestOpenTelemetryServerInterceptor(unittest.TestCase): + + # FIXME: test_concurrent_server_spans fails with contextvars context. + def setUp(self) -> None: + super(TestOpenTelemetryServerInterceptor, self).setUp() + self.mock_runtime = patch.object( + context, "_RUNTIME_CONTEXT", ThreadLocalRuntimeContext() + ) + self.mock_runtime.start() + + def tearDown(self) -> None: + super(TestOpenTelemetryServerInterceptor, self).tearDown() + self.mock_runtime.stop() + def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" @@ -56,20 +212,20 @@ def mock_start_as_current_span(*args, **kwargs): # Intercept gRPC calls... tracer = mock.Mock(spec=trace.Tracer) tracer.start_as_current_span.side_effect = mock_start_as_current_span - interceptor = server_interceptor.OpenTelemetryServerInterceptor( - tracer=tracer - ) + interceptor = server_interceptor(tracer) # No-op RPC handler def handler(request, context): return b"" server = grpc.server( - futures.ThreadPoolExecutor(max_workers=1), - handlers=(UnaryUnaryRpcHandler(handler),), - interceptors=(interceptor,), - options=(("grpc.so_reuseport", 0),), + futures.ThreadPoolExecutor(), options=(("grpc.so_reuseport", 0),) ) + # FIXME: grpcext interceptor doesn't apply to handlers passed to server + # init, should use intercept_service API instead. + server = intercept_server(server, interceptor) + server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) + port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) @@ -80,7 +236,7 @@ def handler(request, context): server.stop(None) tracer.start_as_current_span.assert_called_once_with( - "", kind=trace.SpanKind.SERVER + name="", kind=trace.SpanKind.SERVER ) def test_span_lifetime(self): @@ -88,9 +244,7 @@ def test_span_lifetime(self): tracer_provider = trace_sdk.TracerProvider() tracer = tracer_provider.get_tracer(__name__) - interceptor = server_interceptor.OpenTelemetryServerInterceptor( - tracer=tracer - ) + interceptor = server_interceptor(tracer) # To capture the current span at the time the handler is called active_span_in_handler = None @@ -101,11 +255,11 @@ def handler(request, context): return b"" server = grpc.server( - futures.ThreadPoolExecutor(max_workers=1), - handlers=(UnaryUnaryRpcHandler(handler),), - interceptors=(interceptor,), - options=(("grpc.so_reuseport", 0),), + futures.ThreadPoolExecutor(), options=(("grpc.so_reuseport", 0),) ) + server = intercept_server(server, interceptor) + server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) + port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) @@ -122,14 +276,59 @@ def handler(request, context): self.assertIsInstance(active_span_in_handler, trace_sdk.Span) self.assertIsNone(active_span_in_handler.parent) - def test_concurrent_server_spans(self): - """Check that each call gets its own span.""" + def test_sequential_server_spans(self): + """Check that sequential RPCs get separate server spans.""" tracer_provider = trace_sdk.TracerProvider() tracer = tracer_provider.get_tracer(__name__) - interceptor = server_interceptor.OpenTelemetryServerInterceptor( - tracer=tracer + + interceptor = server_interceptor(tracer) + + # Capture the currently active span in each thread + active_spans_in_handler = [] + + def handler(request, context): + active_spans_in_handler.append(tracer.get_current_span()) + return b"" + + server = grpc.server( + futures.ThreadPoolExecutor(), options=(("grpc.so_reuseport", 0),) ) + server = intercept_server(server, interceptor) + server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) + + port = server.add_insecure_port("[::]:0") + channel = grpc.insecure_channel("localhost:{:d}".format(port)) + + try: + server.start() + channel.unary_unary("")(b"") + channel.unary_unary("")(b"") + finally: + server.stop(None) + + self.assertEqual(len(active_spans_in_handler), 2) + span1, span2 = active_spans_in_handler + # Spans should belong to separate traces, and each should be a root + # span + self.assertNotEqual(span1.context.span_id, span2.context.span_id) + self.assertNotEqual(span1.context.trace_id, span2.context.trace_id) + self.assertIsNone(span1.parent) + self.assertIsNone(span1.parent) + + def test_concurrent_server_spans(self): + """Check that concurrent RPC calls don't interfere with each other. + + This is the same check as test_sequential_server_spans except that the + RPCs are concurrent. Two handlers are invoked at the same time on two + separate threads. Each one should see a different active span and + context. + """ + + tracer_provider = trace_sdk.TracerProvider() + tracer = tracer_provider.get_tracer(__name__) + + interceptor = server_interceptor(tracer) # Capture the currently active span in each thread active_spans_in_handler = [] @@ -142,10 +341,11 @@ def handler(request, context): server = grpc.server( futures.ThreadPoolExecutor(max_workers=2), - handlers=(UnaryUnaryRpcHandler(handler),), - interceptors=(interceptor,), options=(("grpc.so_reuseport", 0),), ) + server = intercept_server(server, interceptor) + server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) + port = server.add_insecure_port("[::]:0") channel = grpc.insecure_channel("localhost:{:d}".format(port)) From 9cf65ab14e99ab84e0cb6c924bbad8cae8fa8bfd Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 17:15:16 -0700 Subject: [PATCH 24/59] Set server context explicitly --- .../src/opentelemetry/ext/grpc/_server.py | 91 ++++++++----------- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index eea8569479a..2370e5ab745 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -18,13 +18,13 @@ https://github.com/opentracing-contrib/python-grpc """ -import logging +from contextlib import contextmanager from typing import List import grpc from opentelemetry import propagators, trace -from opentelemetry.context import attach +from opentelemetry.context import attach, detach from . import grpcext from ._utilities import RpcInfo @@ -132,70 +132,51 @@ class OpenTelemetryServerInterceptor( def __init__(self, tracer): self._tracer = tracer - def _start_span(self, servicer_context, method): + @contextmanager + def _set_remote_context(self, servicer_context): metadata = servicer_context.invocation_metadata() - error = None - - try: - if metadata: - md_dict = {md.key: md.value for md in metadata} - - def get_from_grpc_metadata(metadata, key) -> List[str]: - return [md_dict[key]] if key in md_dict else [] - - # set the request-global context! - ctx = propagators.extract(get_from_grpc_metadata, metadata) - attach(ctx) - - except Exception as ex: - logging.exception("tracer.extract() failed") - error = ex - - # TODO: set gRPC attributes - # tags = { - # ot_tags.COMPONENT: "grpc", - # ot_tags.SPAN_KIND: ot_tags.SPAN_KIND_RPC_SERVER, - # } - - # TODO: set IP attributes - # _add_peer_tags(servicer_context.peer(), tags) - - # span = self._tracer.start_span( - # operation_name=method, child_of=span_context, tags=tags - # ) - + if metadata: + md_dict = {md.key: md.value for md in metadata} + + def get_from_grpc_metadata(metadata, key) -> List[str]: + return [md_dict[key]] if key in md_dict else [] + + # Update the context with the traceparent from the RPC metadata. + ctx = propagators.extract(get_from_grpc_metadata, metadata) + token = attach(ctx) + try: + yield + finally: + detach(token) + else: + yield + + def _start_span(self, method): span = self._tracer.start_as_current_span( name=method, kind=trace.SpanKind.SERVER ) - - # TODO: add error/stacktrace attribute - if error is not None: - pass - # span.log_kv({"event": "error", "error.object": error}) - return span def intercept_unary(self, request, servicer_context, server_info, handler): - with self._start_span( - servicer_context, server_info.full_method - ) as span: - rpc_info = RpcInfo( - full_method=server_info.full_method, - metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining(), - request=request, - ) - servicer_context = _OpenTelemetryServicerContext( - servicer_context, span - ) - response = handler(request, servicer_context) + with self._set_remote_context(servicer_context): + with self._start_span(server_info.full_method) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining(), + request=request, + ) + servicer_context = _OpenTelemetryServicerContext( + servicer_context, span + ) + response = handler(request, servicer_context) - _check_error_code(span, servicer_context, rpc_info) + _check_error_code(span, servicer_context, rpc_info) - rpc_info.response = response + rpc_info.response = response - return response + return response # For RPCs that stream responses, the result can be a generator. To record # the span across the generated responses and detect any errors, we wrap From 55efac2c2bd4e028f3d09419f6c0e7cb89add4a4 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 17:22:05 -0700 Subject: [PATCH 25/59] Remove unused server test classes --- .../tests/test_server_interceptor.py | 140 ------------------ 1 file changed, 140 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index fbaae5dee7d..68c1ef84303 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -40,22 +40,6 @@ def __init__(self, handler): self.stream_stream = None -# lifted from -# https://github.com/grpc/grpc/blob/694f491e06b3503952ca5053c98493cf48af43c1/src/python/grpcio_tests/tests/unit/_interceptor_test.py - - -_SERIALIZE_REQUEST = lambda bytestring: bytestring * 2 -_DESERIALIZE_REQUEST = lambda bytestring: bytestring[len(bytestring) // 2 :] -_SERIALIZE_RESPONSE = lambda bytestring: bytestring * 3 -_DESERIALIZE_RESPONSE = lambda bytestring: bytestring[: len(bytestring) // 3] - - -_UNARY_UNARY = "/test/UnaryUnary" -_UNARY_STREAM = "/test/UnaryStream" -_STREAM_UNARY = "/test/StreamUnary" -_STREAM_STREAM = "/test/StreamStream" - - class UnaryUnaryRpcHandler(grpc.GenericRpcHandler): def __init__(self, handler): self._unary_unary_handler = handler @@ -64,130 +48,6 @@ def service(self, handler_call_details): return UnaryUnaryMethodHandler(self._unary_unary_handler) -class _Handler(object): - def __init__(self, control): - self._control = control - - def handle_unary_unary(self, request, servicer_context): - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) - if request == _EXCEPTION_REQUEST: - raise _ApplicationErrorStandin() - return request - - def handle_unary_stream(self, request, servicer_context): - if request == _EXCEPTION_REQUEST: - raise _ApplicationErrorStandin() - for _ in range(test_constants.STREAM_LENGTH): - self._control.control() - yield request - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) - - def handle_stream_unary(self, request_iterator, servicer_context): - if servicer_context is not None: - servicer_context.invocation_metadata() - self._control.control() - response_elements = [] - for request in request_iterator: - self._control.control() - response_elements.append(request) - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) - if _EXCEPTION_REQUEST in response_elements: - raise _ApplicationErrorStandin() - return b"".join(response_elements) - - def handle_stream_stream(self, request_iterator, servicer_context): - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((("testkey", "testvalue"),)) - for request in request_iterator: - if request == _EXCEPTION_REQUEST: - raise _ApplicationErrorStandin() - self._control.control() - yield request - self._control.control() - - -class _MethodHandler(grpc.RpcMethodHandler): - def __init__( - self, - request_streaming, - response_streaming, - request_deserializer, - response_serializer, - unary_unary, - unary_stream, - stream_unary, - stream_stream, - ): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = request_deserializer - self.response_serializer = response_serializer - self.unary_unary = unary_unary - self.unary_stream = unary_stream - self.stream_unary = stream_unary - self.stream_stream = stream_stream - - -class _GenericHandler(grpc.GenericRpcHandler): - def __init__(self, handler): - self._handler = handler - - def service(self, handler_call_details): - if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler( - False, - False, - None, - None, - self._handler.handle_unary_unary, - None, - None, - None, - ) - elif handler_call_details.method == _UNARY_STREAM: - return _MethodHandler( - False, - True, - _DESERIALIZE_REQUEST, - _SERIALIZE_RESPONSE, - None, - self._handler.handle_unary_stream, - None, - None, - ) - elif handler_call_details.method == _STREAM_UNARY: - return _MethodHandler( - True, - False, - _DESERIALIZE_REQUEST, - _SERIALIZE_RESPONSE, - None, - None, - self._handler.handle_stream_unary, - None, - ) - elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler( - True, - True, - None, - None, - None, - None, - None, - self._handler.handle_stream_stream, - ) - else: - return None - - class TestOpenTelemetryServerInterceptor(unittest.TestCase): # FIXME: test_concurrent_server_spans fails with contextvars context. From 82530ae5babd608270273360d447858b64ac832d Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 18:26:00 -0700 Subject: [PATCH 26/59] Exclude gRPC examples from lint --- .flake8 | 1 + 1 file changed, 1 insertion(+) diff --git a/.flake8 b/.flake8 index 6d1c2bc1752..139ec0d31f9 100644 --- a/.flake8 +++ b/.flake8 @@ -17,3 +17,4 @@ exclude = __pycache__ ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/ ext/opentelemetry-ext-jaeger/build/* + ext/opentelemetry-ext-grpc/examples/ From 8ea858fe258cf89041c05ffebead0aef668659ca Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 18:28:30 -0700 Subject: [PATCH 27/59] Remove OC interceptors --- .../ext/grpc/client_interceptor.py | 217 ------------------ .../ext/grpc/server_interceptor.py | 96 -------- 2 files changed, 313 deletions(-) delete mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py delete mode 100644 ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py deleted file mode 100644 index cfbacffc078..00000000000 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/client_interceptor.py +++ /dev/null @@ -1,217 +0,0 @@ -# Copyright 2020, OpenTelemetry 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. - -import collections - -import grpc -from grpc.framework.foundation import future -from grpc.framework.interfaces.face import face - - -class _ClientCallDetails( - collections.namedtuple( - "_ClientCallDetails", ("method", "timeout", "metadata", "credentials") - ), - grpc.ClientCallDetails, -): - pass - - -# TODO -# https://github.com/c24t/grpc/blob/50619a562f50ef7ee680ed5ce35de94b5a3b1539/src/python/grpcio/grpc/__init__.py#L561 -# https://github.com/census-instrumentation/opencensus-python/pull/617/files#diff-16ff5c7896222cfa69b7aed98860f7d3R50 -class WrappedResponseIterator(future.Future, face.Call): - """Wraps the rpc response iterator. - - The grpc.StreamStreamClientInterceptor abstract class states stream - interceptor method should return an object that's both a call (implementing - the response iterator) and a future. Thus, this class is a thin wrapper - around the rpc response to provide the opencensus extension. - - :type iterator: (future.Future, face.Call) - :param iterator: rpc response iterator - - :type span: opencensus.trace.Span - :param span: rpc span - """ - - def __init__(self, iterator, span): - self._iterator = iterator - self._span = span - - # TODO - # self._messages_received = 0 - - def add_done_callback(self, fn): - self._iterator.add_done_callback(lambda ignored_callback: fn(self)) - - def __iter__(self): - return self - - def __next__(self): - try: - message = next(self._iterator) - except StopIteration: - print("end wrapper iterator") - # execution_context.get_opencensus_tracer().end_span() - raise - - # self._messages_received += 1 - # add_message_event( - # proto_message=message, - # span=self._span, - # message_event_type=time_event.Type.RECEIVED, - # message_id=self._messages_received) - - return message - - def next(self): - return self.__next__() - - def cancel(self): - return self._iterator.cancel() - - def is_active(self): - return self._iterator.is_active() - - def cancelled(self): - raise NotImplementedError() # pragma: NO COVER - - def running(self): - raise NotImplementedError() # pragma: NO COVER - - def done(self): - raise NotImplementedError() # pragma: NO COVER - - def result(self, timeout=None): - raise NotImplementedError() # pragma: NO COVER - - def exception(self, timeout=None): - raise NotImplementedError() # pragma: NO COVER - - def traceback(self, timeout=None): - raise NotImplementedError() # pragma: NO COVER - - def initial_metadata(self): - raise NotImplementedError() # pragma: NO COVER - - def terminal_metadata(self): - raise NotImplementedError() # pragma: NO COVER - - def code(self): - raise NotImplementedError() # pragma: NO COVER - - def details(self): - raise NotImplementedError() # pragma: NO COVER - - def time_remaining(self): - raise NotImplementedError() # pragma: NO COVER - - def add_abortion_callback(self, abortion_callback): - raise NotImplementedError() # pragma: NO COVER - - def protocol_context(self): - raise NotImplementedError() # pragma: NO COVER - - -class OpenTelemetryClientInterceptor( - grpc.UnaryUnaryClientInterceptor, - grpc.UnaryStreamClientInterceptor, - grpc.StreamUnaryClientInterceptor, - grpc.StreamStreamClientInterceptor, -): - def _intercept_call( - self, - client_call_details, - request_iterator, - request_streaming, - response_streaming, - ): - # TODO - return client_call_details, request_iterator, None - - def _callback(self, span): - def callback(future_response): - pass - - # TODO - # grpc_utils.add_message_event( - # proto_message=future_response.result(), - # span=current_span, - # message_event_type=time_event.Type.RECEIVED, - # ) - # self._trace_future_exception(future_response) - # self.tracer.end_span() - - return callback - - def intercept_unary_unary( - self, continuation, client_call_details, request - ): - new_details, new_request, current_span = self._intercept_call( - client_call_details=client_call_details, - request_iterator=iter((request,)), - request_streaming=False, - response_streaming=False, - ) - - response = continuation(new_details, next(new_request)) - - response.add_done_callback(self._callback(current_span)) - - return response - - def intercept_unary_stream( - self, continuation, client_call_details, request - ): - new_details, new_request_iterator, current_span = self._intercept_call( - client_call_details=client_call_details, - request_iterator=iter((request,)), - request_streaming=False, - response_streaming=True, - ) - - return WrappedResponseIterator( - continuation(new_details, next(new_request_iterator)), current_span - ) - - def intercept_stream_unary( - self, continuation, client_call_details, request_iterator - ): - new_details, new_request_iterator, current_span = self._intercept_call( - client_call_details=client_call_details, - request_iterator=request_iterator, - request_streaming=True, - response_streaming=False, - ) - - response = continuation(new_details, new_request_iterator) - - response.add_done_callback(self._callback(current_span)) - - return response - - def intercept_stream_stream( - self, continuation, client_call_details, request_iterator - ): - new_details, new_request_iterator, current_span = self._intercept_call( - client_call_details=client_call_details, - request_iterator=request_iterator, - request_streaming=True, - response_streaming=True, - ) - - return WrappedResponseIterator( - continuation(new_details, new_request_iterator), current_span - ) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py deleted file mode 100644 index 7ba3c7ba746..00000000000 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/server_interceptor.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright 2020, OpenTelemetry 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. - -import grpc - -from opentelemetry import trace - - -class OpenTelemetryServerInterceptor(grpc.ServerInterceptor): - """gRPC service interceptor that wraps each incoming request in a span. - - Usage:: - - from opentelemetry.ext.grpc.server_interceptor import ( - OpenTelemetryServerInterceptor - ) - - ot_interceptor = OpenTelemetryServerInterceptor(tracer) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=10), - interceptors=(interceptor,) - ) - ... - server.start() - - - Args: - tracer: The tracer to use to create spans. - """ - - def __init__(self, tracer: trace.Tracer): - self._tracer = tracer - - def intercept_service(self, continuation, handler_call_details): - def trace_wrapper(behavior, request_streaming, response_streaming): - """A grpc.RpcMethodHandler that wraps behavoir.""" - - def new_behavior(request_or_iterator, servicer_context): - """Wrap behavoir in a span.""" - with self._tracer.start_as_current_span( - _get_span_name(servicer_context), - kind=trace.SpanKind.SERVER, - ): - - response_or_iterator = behavior( - request_or_iterator, servicer_context - ) - - return response_or_iterator - - return new_behavior - - handler = continuation(handler_call_details) - - if handler.request_streaming and handler.response_streaming: - behavior_fn = handler.stream_stream - handler_factory = grpc.stream_stream_rpc_method_handler - elif handler.request_streaming and not handler.response_streaming: - behavior_fn = handler.stream_unary - handler_factory = grpc.stream_unary_rpc_method_handler - elif not handler.request_streaming and handler.response_streaming: - behavior_fn = handler.unary_stream - handler_factory = grpc.unary_stream_rpc_method_handler - else: - behavior_fn = handler.unary_unary - handler_factory = grpc.unary_unary_rpc_method_handler - - new_handler = handler_factory( - trace_wrapper( - behavior_fn, - handler.request_streaming, - handler.response_streaming, - ), - request_deserializer=handler.request_deserializer, - response_serializer=handler.response_serializer, - ) - return new_handler - - -def _get_span_name(servicer_context): - """Get the gRPC servicer method name to use as the span name.""" - method_name = servicer_context._rpc_event.call_details.method[1:] - if isinstance(method_name, bytes): - method_name = method_name.decode("utf-8") - return method_name From ac10d52172547f1c445cdb9e94d95973acd3030a Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 18:30:48 -0700 Subject: [PATCH 28/59] Update server context managers --- .../src/opentelemetry/ext/grpc/_server.py | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index 2370e5ab745..c482c1c193a 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -184,23 +184,22 @@ def intercept_unary(self, request, servicer_context, server_info, handler): def _intercept_server_stream( self, request_or_iterator, servicer_context, server_info, handler ): - with self._start_span( - servicer_context, server_info.full_method - ) as span: - rpc_info = RpcInfo( - full_method=server_info.full_method, - metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining(), - ) - if not server_info.is_client_stream: - rpc_info.request = request_or_iterator - servicer_context = _OpenTelemetryServicerContext( - servicer_context, span - ) - result = handler(request_or_iterator, servicer_context) - for response in result: - yield response - _check_error_code(span, servicer_context, rpc_info) + with self._set_remote_context(servicer_context): + with self._start_span(server_info.full_method) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining(), + ) + if not server_info.is_client_stream: + rpc_info.request = request_or_iterator + servicer_context = _OpenTelemetryServicerContext( + servicer_context, span + ) + result = handler(request_or_iterator, servicer_context) + for response in result: + yield response + _check_error_code(span, servicer_context, rpc_info) def intercept_stream( self, request_or_iterator, servicer_context, server_info, handler @@ -209,18 +208,17 @@ def intercept_stream( return self._intercept_server_stream( request_or_iterator, servicer_context, server_info, handler ) - with self._start_span( - servicer_context, server_info.full_method - ) as span: - rpc_info = RpcInfo( - full_method=server_info.full_method, - metadata=servicer_context.invocation_metadata(), - timeout=servicer_context.time_remaining(), - ) - servicer_context = _OpenTelemetryServicerContext( - servicer_context, span - ) - response = handler(request_or_iterator, servicer_context) - _check_error_code(span, servicer_context, rpc_info) - rpc_info.response = response - return response + with self._set_remote_context(servicer_context): + with self._start_span(server_info.full_method) as span: + rpc_info = RpcInfo( + full_method=server_info.full_method, + metadata=servicer_context.invocation_metadata(), + timeout=servicer_context.time_remaining(), + ) + servicer_context = _OpenTelemetryServicerContext( + servicer_context, span + ) + response = handler(request_or_iterator, servicer_context) + _check_error_code(span, servicer_context, rpc_info) + rpc_info.response = response + return response From 60afdb83d362a80fc3f3c8b9b6d552222b901d69 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Tue, 24 Mar 2020 18:31:05 -0700 Subject: [PATCH 29/59] s/OpenTelemetry/OpenTracing/ --- .../src/opentelemetry/ext/grpc/_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index c482c1c193a..f81c9d72f59 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -14,7 +14,7 @@ """Implementation of the service-side open-telemetry interceptor. -This library borrows heavily from the OpenTelemetry gRPC integration: +This library borrows heavily from the OpenTracing gRPC integration: https://github.com/opentracing-contrib/python-grpc """ From fa18357287063d36adfb5ac6d91bfd8bce7e3a1e Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 25 Mar 2020 12:40:20 -0700 Subject: [PATCH 30/59] Move grpc examples, generated code --- .../examples/grpc}/examples/codegen.py | 0 docs/examples/grpc/examples/gen/__init__.py | 0 .../examples/grpc/examples/gen}/helloworld_pb2.py | 0 .../examples/grpc/examples/gen}/helloworld_pb2_grpc.py | 0 .../examples/grpc/examples/gen}/route_guide_pb2.py | 0 .../examples/grpc/examples/gen}/route_guide_pb2_grpc.py | 0 .../examples/grpc}/examples/hello_world_client.py | 0 .../examples/grpc}/examples/hello_world_server.py | 0 .../examples/grpc}/examples/helloworld.proto | 0 .../examples/grpc}/examples/route_guide.proto | 0 .../examples/grpc}/examples/route_guide_client.py | 0 .../examples/grpc}/examples/route_guide_db.json | 0 .../examples/grpc}/examples/route_guide_resources.py | 0 .../examples/grpc}/examples/route_guide_server.py | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/codegen.py (100%) create mode 100644 docs/examples/grpc/examples/gen/__init__.py rename {ext/opentelemetry-ext-grpc/examples => docs/examples/grpc/examples/gen}/helloworld_pb2.py (100%) rename {ext/opentelemetry-ext-grpc/examples => docs/examples/grpc/examples/gen}/helloworld_pb2_grpc.py (100%) rename {ext/opentelemetry-ext-grpc/examples => docs/examples/grpc/examples/gen}/route_guide_pb2.py (100%) rename {ext/opentelemetry-ext-grpc/examples => docs/examples/grpc/examples/gen}/route_guide_pb2_grpc.py (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/hello_world_client.py (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/hello_world_server.py (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/helloworld.proto (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/route_guide.proto (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/route_guide_client.py (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/route_guide_db.json (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/route_guide_resources.py (100%) rename {ext/opentelemetry-ext-grpc => docs/examples/grpc}/examples/route_guide_server.py (100%) diff --git a/ext/opentelemetry-ext-grpc/examples/codegen.py b/docs/examples/grpc/examples/codegen.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/codegen.py rename to docs/examples/grpc/examples/codegen.py diff --git a/docs/examples/grpc/examples/gen/__init__.py b/docs/examples/grpc/examples/gen/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py b/docs/examples/grpc/examples/gen/helloworld_pb2.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/helloworld_pb2.py rename to docs/examples/grpc/examples/gen/helloworld_pb2.py diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld_pb2_grpc.py b/docs/examples/grpc/examples/gen/helloworld_pb2_grpc.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/helloworld_pb2_grpc.py rename to docs/examples/grpc/examples/gen/helloworld_pb2_grpc.py diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_pb2.py b/docs/examples/grpc/examples/gen/route_guide_pb2.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide_pb2.py rename to docs/examples/grpc/examples/gen/route_guide_pb2.py diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_pb2_grpc.py b/docs/examples/grpc/examples/gen/route_guide_pb2_grpc.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide_pb2_grpc.py rename to docs/examples/grpc/examples/gen/route_guide_pb2_grpc.py diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_client.py b/docs/examples/grpc/examples/hello_world_client.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/hello_world_client.py rename to docs/examples/grpc/examples/hello_world_client.py diff --git a/ext/opentelemetry-ext-grpc/examples/hello_world_server.py b/docs/examples/grpc/examples/hello_world_server.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/hello_world_server.py rename to docs/examples/grpc/examples/hello_world_server.py diff --git a/ext/opentelemetry-ext-grpc/examples/helloworld.proto b/docs/examples/grpc/examples/helloworld.proto similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/helloworld.proto rename to docs/examples/grpc/examples/helloworld.proto diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide.proto b/docs/examples/grpc/examples/route_guide.proto similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide.proto rename to docs/examples/grpc/examples/route_guide.proto diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_client.py b/docs/examples/grpc/examples/route_guide_client.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide_client.py rename to docs/examples/grpc/examples/route_guide_client.py diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_db.json b/docs/examples/grpc/examples/route_guide_db.json similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide_db.json rename to docs/examples/grpc/examples/route_guide_db.json diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_resources.py b/docs/examples/grpc/examples/route_guide_resources.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide_resources.py rename to docs/examples/grpc/examples/route_guide_resources.py diff --git a/ext/opentelemetry-ext-grpc/examples/route_guide_server.py b/docs/examples/grpc/examples/route_guide_server.py similarity index 100% rename from ext/opentelemetry-ext-grpc/examples/route_guide_server.py rename to docs/examples/grpc/examples/route_guide_server.py From bc585d47e775b524725e9e7bfe9515ddcd7a0899 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 25 Mar 2020 14:10:42 -0700 Subject: [PATCH 31/59] Make examples portable --- .../grpc}/__init__.py | 0 .../grpc/gen/__init__.py | 19 ++++++ .../grpc/gen}/codegen.py | 0 .../grpc/gen}/helloworld.proto | 0 .../grpc}/gen/helloworld_pb2.py | 0 .../grpc}/gen/helloworld_pb2_grpc.py | 0 .../grpc/gen}/route_guide.proto | 0 .../grpc}/gen/route_guide_pb2.py | 0 .../grpc}/gen/route_guide_pb2_grpc.py | 0 .../grpc}/hello_world_client.py | 12 +++- .../grpc}/hello_world_server.py | 12 +++- .../grpc/hello_world_server_two.py | 61 +++++++++++++++++++ .../grpc}/route_guide_client.py | 15 ++++- .../grpc}/route_guide_db.json | 0 .../grpc}/route_guide_resources.py | 8 ++- .../grpc}/route_guide_server.py | 16 ++++- 16 files changed, 131 insertions(+), 12 deletions(-) rename docs/examples/{grpc/examples/gen => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/__init__.py (100%) create mode 100644 docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen}/codegen.py (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen}/helloworld.proto (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/gen/helloworld_pb2.py (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/gen/helloworld_pb2_grpc.py (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen}/route_guide.proto (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/gen/route_guide_pb2.py (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/gen/route_guide_pb2_grpc.py (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/hello_world_client.py (82%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/hello_world_server.py (80%) create mode 100755 docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/route_guide_client.py (90%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/route_guide_db.json (100%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/route_guide_resources.py (84%) rename docs/examples/{grpc/examples => opentelemetry-example-app/src/opentelemetry_example_app/grpc}/route_guide_server.py (90%) diff --git a/docs/examples/grpc/examples/gen/__init__.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/__init__.py similarity index 100% rename from docs/examples/grpc/examples/gen/__init__.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/__init__.py diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py new file mode 100644 index 00000000000..0dca3063466 --- /dev/null +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2020, OpenTelemetry 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. + +import importlib +import sys + +# gRPC-generated modules expect other generated modules to be on the path. +sys.path.extend(importlib.util.find_spec(__name__).submodule_search_locations) diff --git a/docs/examples/grpc/examples/codegen.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/codegen.py similarity index 100% rename from docs/examples/grpc/examples/codegen.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/codegen.py diff --git a/docs/examples/grpc/examples/helloworld.proto b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld.proto similarity index 100% rename from docs/examples/grpc/examples/helloworld.proto rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld.proto diff --git a/docs/examples/grpc/examples/gen/helloworld_pb2.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld_pb2.py similarity index 100% rename from docs/examples/grpc/examples/gen/helloworld_pb2.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld_pb2.py diff --git a/docs/examples/grpc/examples/gen/helloworld_pb2_grpc.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld_pb2_grpc.py similarity index 100% rename from docs/examples/grpc/examples/gen/helloworld_pb2_grpc.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld_pb2_grpc.py diff --git a/docs/examples/grpc/examples/route_guide.proto b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide.proto similarity index 100% rename from docs/examples/grpc/examples/route_guide.proto rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide.proto diff --git a/docs/examples/grpc/examples/gen/route_guide_pb2.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide_pb2.py similarity index 100% rename from docs/examples/grpc/examples/gen/route_guide_pb2.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide_pb2.py diff --git a/docs/examples/grpc/examples/gen/route_guide_pb2_grpc.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide_pb2_grpc.py similarity index 100% rename from docs/examples/grpc/examples/gen/route_guide_pb2_grpc.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide_pb2_grpc.py diff --git a/docs/examples/grpc/examples/hello_world_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py similarity index 82% rename from docs/examples/grpc/examples/hello_world_client.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py index 7c7625057bc..c653fe49615 100755 --- a/docs/examples/grpc/examples/hello_world_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py @@ -21,8 +21,6 @@ import grpc -import helloworld_pb2 -import helloworld_pb2_grpc from opentelemetry import trace from opentelemetry.ext.grpc import client_interceptor from opentelemetry.ext.grpc.grpcext import intercept_channel @@ -32,6 +30,16 @@ SimpleExportSpanProcessor, ) +try: + # Relative imports should work in the context of the package, e.g.: + # `python -m opentelemetry_example_app.grpc.hello_world_client`. + from .gen import helloworld_pb2, helloworld_pb2_grpc +except ImportError: + # This will fail when running the file as a script, e.g.: + # `./hello_world_client.py` + # fall back to importing from the same directory in this case. + from gen import helloworld_pb2, helloworld_pb2_grpc + trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) diff --git a/docs/examples/grpc/examples/hello_world_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py similarity index 80% rename from docs/examples/grpc/examples/hello_world_server.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py index 46938f5226d..c8c8ce27542 100755 --- a/docs/examples/grpc/examples/hello_world_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py @@ -21,8 +21,6 @@ import grpc -import helloworld_pb2 -import helloworld_pb2_grpc from opentelemetry import trace from opentelemetry.ext.grpc import server_interceptor from opentelemetry.ext.grpc.grpcext import intercept_server @@ -32,6 +30,16 @@ SimpleExportSpanProcessor, ) +try: + # Relative imports should work in the context of the package, e.g.: + # `python -m opentelemetry_example_app.grpc.hello_world_server`. + from .gen import helloworld_pb2, helloworld_pb2_grpc +except ImportError: + # This will fail when running the file as a script, e.g.: + # `./hello_world_server.py` + # fall back to importing from the same directory in this case. + from gen import helloworld_pb2, helloworld_pb2_grpc + trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py new file mode 100755 index 00000000000..525000214a8 --- /dev/null +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# Copyright 2020, OpenTelemetry 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. + +# https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py +"""The Python implementation of the GRPC helloworld.Greeter server.""" + +import logging +from concurrent import futures + +import grpc + +import helloworld_pb2 +import helloworld_pb2_grpc +from opentelemetry import trace +from opentelemetry.ext.grpc import _server +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import ( + ConsoleSpanExporter, + SimpleExportSpanProcessor, +) + +trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) +trace.tracer_provider().add_span_processor( + SimpleExportSpanProcessor(ConsoleSpanExporter()) +) +tracer = trace.get_tracer(__name__) + + +class Greeter(helloworld_pb2_grpc.GreeterServicer): + def SayHello(self, request, context): + return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name) + + +def serve(): + + interceptor = _server.OpenTelemetryServerInterceptor(tracer) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=10), interceptors=(interceptor,) + ) + + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) + server.add_insecure_port("[::]:50051") + server.start() + server.wait_for_termination() + + +if __name__ == "__main__": + logging.basicConfig() + serve() diff --git a/docs/examples/grpc/examples/route_guide_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py similarity index 90% rename from docs/examples/grpc/examples/route_guide_client.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py index 857c792c0bc..5e29492fcdf 100755 --- a/docs/examples/grpc/examples/route_guide_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py @@ -22,9 +22,6 @@ import grpc -import route_guide_pb2 -import route_guide_pb2_grpc -import route_guide_resources from opentelemetry import trace from opentelemetry.ext.grpc import client_interceptor from opentelemetry.ext.grpc.grpcext import intercept_channel @@ -34,6 +31,18 @@ SimpleExportSpanProcessor, ) +try: + # Relative imports should work in the context of the package, e.g.: + # `python -m opentelemetry_example_app.grpc.route_guide_client`. + from .gen import route_guide_pb2, route_guide_pb2_grpc + from . import route_guide_resources +except ImportError: + # This will fail when running the file as a script, e.g.: + # `./route_guide_client.py` + # fall back to importing from the same directory in this case. + from gen import route_guide_pb2, route_guide_pb2_grpc + import route_guide_resources + trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) diff --git a/docs/examples/grpc/examples/route_guide_db.json b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_db.json similarity index 100% rename from docs/examples/grpc/examples/route_guide_db.json rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_db.json diff --git a/docs/examples/grpc/examples/route_guide_resources.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py similarity index 84% rename from docs/examples/grpc/examples/route_guide_resources.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py index 495f7dcc7a5..1fc4a90e105 100644 --- a/docs/examples/grpc/examples/route_guide_resources.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py @@ -17,6 +17,7 @@ """Common resources used in the gRPC route guide example.""" import json +import os import route_guide_pb2 @@ -29,12 +30,15 @@ def read_route_guide_database(): route_guide_pb2.Features. """ feature_list = [] - with open("route_guide_db.json") as route_guide_db_file: + db_file = os.path.join(os.path.dirname(__file__), "route_guide_db.json") + with open(db_file) as route_guide_db_file: for item in json.load(route_guide_db_file): feature = route_guide_pb2.Feature( name=item["name"], location=route_guide_pb2.Point( latitude=item["location"]["latitude"], - longitude=item["location"]["longitude"])) + longitude=item["location"]["longitude"], + ), + ) feature_list.append(feature) return feature_list diff --git a/docs/examples/grpc/examples/route_guide_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py similarity index 90% rename from docs/examples/grpc/examples/route_guide_server.py rename to docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py index 3b73f5da068..fd94eaa25ce 100755 --- a/docs/examples/grpc/examples/route_guide_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py @@ -24,9 +24,7 @@ import grpc -import route_guide_pb2 -import route_guide_pb2_grpc -import route_guide_resources + from opentelemetry import trace from opentelemetry.ext.grpc import server_interceptor from opentelemetry.ext.grpc.grpcext import intercept_server @@ -36,6 +34,18 @@ SimpleExportSpanProcessor, ) +try: + # Relative imports should work in the context of the package, e.g.: + # `python -m opentelemetry_example_app.grpc.route_guide_server`. + from .gen import route_guide_pb2, route_guide_pb2_grpc + from . import route_guide_resources +except ImportError: + # This will fail when running the file as a script, e.g.: + # `./route_guide_server.py` + # fall back to importing from the same directory in this case. + from gen import route_guide_pb2, route_guide_pb2_grpc + import route_guide_resources + trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) From a3e0c86655113420d0b75ed6c9f075f35398a0a0 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 25 Mar 2020 14:18:22 -0700 Subject: [PATCH 32/59] Lint, blacken --- .../grpc/route_guide_server.py | 1 - .../src/opentelemetry/ext/grpc/_utilities.py | 17 +- .../ext/grpc/grpcext/__init__.py | 29 +- .../ext/grpc/grpcext/_interceptor.py | 304 ++++++++++-------- 4 files changed, 193 insertions(+), 158 deletions(-) diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py index fd94eaa25ce..afae77afda0 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py @@ -24,7 +24,6 @@ import grpc - from opentelemetry import trace from opentelemetry.ext.grpc import server_interceptor from opentelemetry.ext.grpc.grpcext import intercept_server diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py index b3159440e08..ec1e5fe1f98 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py @@ -16,14 +16,15 @@ class RpcInfo: - - def __init__(self, - full_method=None, - metadata=None, - timeout=None, - request=None, - response=None, - error=None): + def __init__( + self, + full_method=None, + metadata=None, + timeout=None, + request=None, + response=None, + error=None, + ): self.full_method = full_method self.metadata = metadata self.timeout = timeout diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py index 2864fd6d395..abafa009bf6 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -55,8 +55,9 @@ class StreamClientInterceptor(six.with_metaclass(abc.ABCMeta)): """Affords intercepting stream RPCs on the invocation-side.""" @abc.abstractmethod - def intercept_stream(self, request_or_iterator, metadata, client_info, - invoker): + def intercept_stream( + self, request_or_iterator, metadata, client_info, invoker + ): """Intercepts stream RPCs on the invocation-side. Args: @@ -92,6 +93,7 @@ def intercept_channel(channel, *interceptors): nor StreamClientInterceptor. """ from . import _interceptor + return _interceptor.intercept_channel(channel, *interceptors) @@ -138,8 +140,9 @@ class StreamServerInterceptor(six.with_metaclass(abc.ABCMeta)): """Affords intercepting stream RPCs on the service-side.""" @abc.abstractmethod - def intercept_stream(self, request_or_iterator, servicer_context, - server_info, handler): + def intercept_stream( + self, request_or_iterator, servicer_context, server_info, handler + ): """Intercepts stream RPCs on the service-side. Args: @@ -174,12 +177,18 @@ def intercept_server(server, *interceptors): nor StreamServerInterceptor. """ from . import _interceptor - return _interceptor.intercept_server(server, *interceptors) + return _interceptor.intercept_server(server, *interceptors) -################################### __all__ ################################# -__all__ = ('UnaryClientInterceptor', 'StreamClientInfo', - 'StreamClientInterceptor', 'UnaryServerInfo', 'StreamServerInfo', - 'UnaryServerInterceptor', 'StreamServerInterceptor', - 'intercept_channel', 'intercept_server',) +__all__ = ( + "UnaryClientInterceptor", + "StreamClientInfo", + "StreamClientInterceptor", + "UnaryServerInfo", + "StreamServerInfo", + "UnaryServerInterceptor", + "StreamServerInterceptor", + "intercept_channel", + "intercept_server", +) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py index dfebce90e11..2c936cbcd87 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -3,149 +3,148 @@ import collections import grpc + from .. import grpcext class _UnaryClientInfo( - collections.namedtuple('_UnaryClientInfo', - ('full_method', 'timeout',))): + collections.namedtuple("_UnaryClientInfo", ("full_method", "timeout",)) +): pass class _StreamClientInfo( - collections.namedtuple('_StreamClientInfo', ( - 'full_method', 'is_client_stream', 'is_server_stream', 'timeout'))): + collections.namedtuple( + "_StreamClientInfo", + ("full_method", "is_client_stream", "is_server_stream", "timeout"), + ) +): pass class _InterceptorUnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): - def __init__(self, method, base_callable, interceptor): self._method = method self._base_callable = base_callable self._interceptor = interceptor def __call__(self, request, timeout=None, metadata=None, credentials=None): - def invoker(request, metadata): return self._base_callable(request, timeout, metadata, credentials) client_info = _UnaryClientInfo(self._method, timeout) - return self._interceptor.intercept_unary(request, metadata, client_info, - invoker) - - def with_call(self, request, timeout=None, metadata=None, credentials=None): + return self._interceptor.intercept_unary( + request, metadata, client_info, invoker + ) + def with_call( + self, request, timeout=None, metadata=None, credentials=None + ): def invoker(request, metadata): - return self._base_callable.with_call(request, timeout, metadata, - credentials) + return self._base_callable.with_call( + request, timeout, metadata, credentials + ) client_info = _UnaryClientInfo(self._method, timeout) - return self._interceptor.intercept_unary(request, metadata, client_info, - invoker) + return self._interceptor.intercept_unary( + request, metadata, client_info, invoker + ) def future(self, request, timeout=None, metadata=None, credentials=None): - def invoker(request, metadata): - return self._base_callable.future(request, timeout, metadata, - credentials) + return self._base_callable.future( + request, timeout, metadata, credentials + ) client_info = _UnaryClientInfo(self._method, timeout) - return self._interceptor.intercept_unary(request, metadata, client_info, - invoker) + return self._interceptor.intercept_unary( + request, metadata, client_info, invoker + ) class _InterceptorUnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): - def __init__(self, method, base_callable, interceptor): self._method = method self._base_callable = base_callable self._interceptor = interceptor def __call__(self, request, timeout=None, metadata=None, credentials=None): - def invoker(request, metadata): return self._base_callable(request, timeout, metadata, credentials) client_info = _StreamClientInfo(self._method, False, True, timeout) - return self._interceptor.intercept_stream(request, metadata, - client_info, invoker) + return self._interceptor.intercept_stream( + request, metadata, client_info, invoker + ) class _InterceptorStreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): - def __init__(self, method, base_callable, interceptor): self._method = method self._base_callable = base_callable self._interceptor = interceptor - def __call__(self, - request_iterator, - timeout=None, - metadata=None, - credentials=None): - + def __call__( + self, request_iterator, timeout=None, metadata=None, credentials=None + ): def invoker(request_iterator, metadata): - return self._base_callable(request_iterator, timeout, metadata, - credentials) + return self._base_callable( + request_iterator, timeout, metadata, credentials + ) client_info = _StreamClientInfo(self._method, True, False, timeout) - return self._interceptor.intercept_stream(request_iterator, metadata, - client_info, invoker) - - def with_call(self, - request_iterator, - timeout=None, - metadata=None, - credentials=None): + return self._interceptor.intercept_stream( + request_iterator, metadata, client_info, invoker + ) + def with_call( + self, request_iterator, timeout=None, metadata=None, credentials=None + ): def invoker(request_iterator, metadata): - return self._base_callable.with_call(request_iterator, timeout, - metadata, credentials) + return self._base_callable.with_call( + request_iterator, timeout, metadata, credentials + ) client_info = _StreamClientInfo(self._method, True, False, timeout) - return self._interceptor.intercept_stream(request_iterator, metadata, - client_info, invoker) - - def future(self, - request_iterator, - timeout=None, - metadata=None, - credentials=None): + return self._interceptor.intercept_stream( + request_iterator, metadata, client_info, invoker + ) + def future( + self, request_iterator, timeout=None, metadata=None, credentials=None + ): def invoker(request_iterator, metadata): - return self._base_callable.future(request_iterator, timeout, - metadata, credentials) + return self._base_callable.future( + request_iterator, timeout, metadata, credentials + ) client_info = _StreamClientInfo(self._method, True, False, timeout) - return self._interceptor.intercept_stream(request_iterator, metadata, - client_info, invoker) + return self._interceptor.intercept_stream( + request_iterator, metadata, client_info, invoker + ) class _InterceptorStreamStreamMultiCallable(grpc.StreamStreamMultiCallable): - def __init__(self, method, base_callable, interceptor): self._method = method self._base_callable = base_callable self._interceptor = interceptor - def __call__(self, - request_iterator, - timeout=None, - metadata=None, - credentials=None): - + def __call__( + self, request_iterator, timeout=None, metadata=None, credentials=None + ): def invoker(request_iterator, metadata): - return self._base_callable(request_iterator, timeout, metadata, - credentials) + return self._base_callable( + request_iterator, timeout, metadata, credentials + ) client_info = _StreamClientInfo(self._method, True, True, timeout) - return self._interceptor.intercept_stream(request_iterator, metadata, - client_info, invoker) + return self._interceptor.intercept_stream( + request_iterator, metadata, client_info, invoker + ) class _InterceptorChannel(grpc.Channel): - def __init__(self, channel, interceptor): self._channel = channel self._interceptor = interceptor @@ -156,85 +155,97 @@ def subscribe(self, *args, **kwargs): def unsubscribe(self, *args, **kwargs): self._channel.unsubscribe(*args, **kwargs) - def unary_unary(self, - method, - request_serializer=None, - response_deserializer=None): - base_callable = self._channel.unary_unary(method, request_serializer, - response_deserializer) + def unary_unary( + self, method, request_serializer=None, response_deserializer=None + ): + base_callable = self._channel.unary_unary( + method, request_serializer, response_deserializer + ) if isinstance(self._interceptor, grpcext.UnaryClientInterceptor): - return _InterceptorUnaryUnaryMultiCallable(method, base_callable, - self._interceptor) + return _InterceptorUnaryUnaryMultiCallable( + method, base_callable, self._interceptor + ) else: return base_callable - def unary_stream(self, - method, - request_serializer=None, - response_deserializer=None): - base_callable = self._channel.unary_stream(method, request_serializer, - response_deserializer) + def unary_stream( + self, method, request_serializer=None, response_deserializer=None + ): + base_callable = self._channel.unary_stream( + method, request_serializer, response_deserializer + ) if isinstance(self._interceptor, grpcext.StreamClientInterceptor): - return _InterceptorUnaryStreamMultiCallable(method, base_callable, - self._interceptor) + return _InterceptorUnaryStreamMultiCallable( + method, base_callable, self._interceptor + ) else: return base_callable - def stream_unary(self, - method, - request_serializer=None, - response_deserializer=None): - base_callable = self._channel.stream_unary(method, request_serializer, - response_deserializer) + def stream_unary( + self, method, request_serializer=None, response_deserializer=None + ): + base_callable = self._channel.stream_unary( + method, request_serializer, response_deserializer + ) if isinstance(self._interceptor, grpcext.StreamClientInterceptor): - return _InterceptorStreamUnaryMultiCallable(method, base_callable, - self._interceptor) + return _InterceptorStreamUnaryMultiCallable( + method, base_callable, self._interceptor + ) else: return base_callable - def stream_stream(self, - method, - request_serializer=None, - response_deserializer=None): - base_callable = self._channel.stream_stream(method, request_serializer, - response_deserializer) + def stream_stream( + self, method, request_serializer=None, response_deserializer=None + ): + base_callable = self._channel.stream_stream( + method, request_serializer, response_deserializer + ) if isinstance(self._interceptor, grpcext.StreamClientInterceptor): - return _InterceptorStreamStreamMultiCallable(method, base_callable, - self._interceptor) + return _InterceptorStreamStreamMultiCallable( + method, base_callable, self._interceptor + ) else: return base_callable def close(self): - if not hasattr(self._channel, 'close'): - raise RuntimeError('close() is not supported with the installed version of grpcio') + if not hasattr(self._channel, "close"): + raise RuntimeError( + "close() is not supported with the installed version of grpcio" + ) self._channel.close() def intercept_channel(channel, *interceptors): result = channel for interceptor in interceptors: - if not isinstance(interceptor, grpcext.UnaryClientInterceptor) and \ - not isinstance(interceptor, grpcext.StreamClientInterceptor): - raise TypeError('interceptor must be either a ' - 'grpcext.UnaryClientInterceptor or a ' - 'grpcext.StreamClientInterceptor') + if not isinstance( + interceptor, grpcext.UnaryClientInterceptor + ) and not isinstance(interceptor, grpcext.StreamClientInterceptor): + raise TypeError( + "interceptor must be either a " + "grpcext.UnaryClientInterceptor or a " + "grpcext.StreamClientInterceptor" + ) result = _InterceptorChannel(result, interceptor) return result class _UnaryServerInfo( - collections.namedtuple('_UnaryServerInfo', ('full_method',))): + collections.namedtuple("_UnaryServerInfo", ("full_method",)) +): pass class _StreamServerInfo( - collections.namedtuple('_StreamServerInfo', ( - 'full_method', 'is_client_stream', 'is_server_stream'))): + collections.namedtuple( + "_StreamServerInfo", + ("full_method", "is_client_stream", "is_server_stream"), + ) +): pass class _InterceptorRpcMethodHandler(grpc.RpcMethodHandler): - def __init__(self, rpc_method_handler, method, interceptor): self._rpc_method_handler = rpc_method_handler self._method = method @@ -262,14 +273,17 @@ def unary_unary(self): return self._rpc_method_handler.unary_unary def adaptation(request, servicer_context): - def handler(request, servicer_context): - return self._rpc_method_handler.unary_unary(request, - servicer_context) + return self._rpc_method_handler.unary_unary( + request, servicer_context + ) return self._interceptor.intercept_unary( - request, servicer_context, - _UnaryServerInfo(self._method), handler) + request, + servicer_context, + _UnaryServerInfo(self._method), + handler, + ) return adaptation @@ -279,14 +293,17 @@ def unary_stream(self): return self._rpc_method_handler.unary_stream def adaptation(request, servicer_context): - def handler(request, servicer_context): - return self._rpc_method_handler.unary_stream(request, - servicer_context) + return self._rpc_method_handler.unary_stream( + request, servicer_context + ) return self._interceptor.intercept_stream( - request, servicer_context, - _StreamServerInfo(self._method, False, True), handler) + request, + servicer_context, + _StreamServerInfo(self._method, False, True), + handler, + ) return adaptation @@ -296,14 +313,17 @@ def stream_unary(self): return self._rpc_method_handler.stream_unary def adaptation(request_iterator, servicer_context): - def handler(request_iterator, servicer_context): - return self._rpc_method_handler.stream_unary(request_iterator, - servicer_context) + return self._rpc_method_handler.stream_unary( + request_iterator, servicer_context + ) return self._interceptor.intercept_stream( - request_iterator, servicer_context, - _StreamServerInfo(self._method, True, False), handler) + request_iterator, + servicer_context, + _StreamServerInfo(self._method, True, False), + handler, + ) return adaptation @@ -313,20 +333,22 @@ def stream_stream(self): return self._rpc_method_handler.stream_stream def adaptation(request_iterator, servicer_context): - def handler(request_iterator, servicer_context): - return self._rpc_method_handler.stream_stream(request_iterator, - servicer_context) + return self._rpc_method_handler.stream_stream( + request_iterator, servicer_context + ) return self._interceptor.intercept_stream( - request_iterator, servicer_context, - _StreamServerInfo(self._method, True, True), handler) + request_iterator, + servicer_context, + _StreamServerInfo(self._method, True, True), + handler, + ) return adaptation class _InterceptorGenericRpcHandler(grpc.GenericRpcHandler): - def __init__(self, generic_rpc_handler, interceptor): self.generic_rpc_handler = generic_rpc_handler self._interceptor = interceptor @@ -335,20 +357,21 @@ def service(self, handler_call_details): result = self.generic_rpc_handler.service(handler_call_details) if result: result = _InterceptorRpcMethodHandler( - result, handler_call_details.method, self._interceptor) + result, handler_call_details.method, self._interceptor + ) return result class _InterceptorServer(grpc.Server): - def __init__(self, server, interceptor): self._server = server self._interceptor = interceptor def add_generic_rpc_handlers(self, generic_rpc_handlers): generic_rpc_handlers = [ - _InterceptorGenericRpcHandler(generic_rpc_handler, - self._interceptor) + _InterceptorGenericRpcHandler( + generic_rpc_handler, self._interceptor + ) for generic_rpc_handler in generic_rpc_handlers ] return self._server.add_generic_rpc_handlers(generic_rpc_handlers) @@ -372,10 +395,13 @@ def wait_for_termination(self, *args, **kwargs): def intercept_server(server, *interceptors): result = server for interceptor in interceptors: - if not isinstance(interceptor, grpcext.UnaryServerInterceptor) and \ - not isinstance(interceptor, grpcext.StreamServerInterceptor): - raise TypeError('interceptor must be either a ' - 'grpcext.UnaryServerInterceptor or a ' - 'grpcext.StreamServerInterceptor') + if not isinstance( + interceptor, grpcext.UnaryServerInterceptor + ) and not isinstance(interceptor, grpcext.StreamServerInterceptor): + raise TypeError( + "interceptor must be either a " + "grpcext.UnaryServerInterceptor or a " + "grpcext.StreamServerInterceptor" + ) result = _InterceptorServer(result, interceptor) return result From 401b48800f7220e9e9a865c1884964089763baac Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Wed, 25 Mar 2020 14:23:06 -0700 Subject: [PATCH 33/59] Don't lint generated files --- .flake8 | 1 + 1 file changed, 1 insertion(+) diff --git a/.flake8 b/.flake8 index 139ec0d31f9..c1918f16ebf 100644 --- a/.flake8 +++ b/.flake8 @@ -18,3 +18,4 @@ exclude = ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/ ext/opentelemetry-ext-jaeger/build/* ext/opentelemetry-ext-grpc/examples/ + docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/ From 47e4eedc949a8881e5f31b7b4c5e7c85f54192bd Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 26 Mar 2020 09:35:23 -0700 Subject: [PATCH 34/59] Remove extra test file --- .../grpc/hello_world_server_two.py | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100755 docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py deleted file mode 100755 index 525000214a8..00000000000 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server_two.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# Copyright 2020, OpenTelemetry 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. - -# https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py -"""The Python implementation of the GRPC helloworld.Greeter server.""" - -import logging -from concurrent import futures - -import grpc - -import helloworld_pb2 -import helloworld_pb2_grpc -from opentelemetry import trace -from opentelemetry.ext.grpc import _server -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import ( - ConsoleSpanExporter, - SimpleExportSpanProcessor, -) - -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) -trace.tracer_provider().add_span_processor( - SimpleExportSpanProcessor(ConsoleSpanExporter()) -) -tracer = trace.get_tracer(__name__) - - -class Greeter(helloworld_pb2_grpc.GreeterServicer): - def SayHello(self, request, context): - return helloworld_pb2.HelloReply(message="Hello, %s!" % request.name) - - -def serve(): - - interceptor = _server.OpenTelemetryServerInterceptor(tracer) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=10), interceptors=(interceptor,) - ) - - helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) - server.add_insecure_port("[::]:50051") - server.start() - server.wait_for_termination() - - -if __name__ == "__main__": - logging.basicConfig() - serve() From bb33a9d16fe38e2112243cec4d3a2abe8a6cd303 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 26 Mar 2020 15:49:44 -0700 Subject: [PATCH 35/59] Update ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py Co-Authored-By: alrex --- .../src/opentelemetry/ext/grpc/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py index f48cb5bee5c..373ae92cb85 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.5.dev0" +__version__ = "0.6.dev0" From 3d49b86533d104364daea432d99e656467dfc37f Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 26 Mar 2020 15:48:09 -0700 Subject: [PATCH 36/59] Remove old example dir --- .flake8 | 1 - 1 file changed, 1 deletion(-) diff --git a/.flake8 b/.flake8 index c1918f16ebf..0c2204782fc 100644 --- a/.flake8 +++ b/.flake8 @@ -17,5 +17,4 @@ exclude = __pycache__ ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/ ext/opentelemetry-ext-jaeger/build/* - ext/opentelemetry-ext-grpc/examples/ docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/ From df9f74536ee382420ac3795cd4fb964574d856a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauricio=20V=C3=A1squez?= Date: Wed, 25 Mar 2020 14:00:54 -0500 Subject: [PATCH 37/59] Remove copyright year (#523) It is not needed and becomes a burden of maintaince work. --- docs/examples/basic_meter/basic_metrics.py | 2 +- docs/examples/basic_meter/calling_conventions.py | 2 +- docs/examples/basic_meter/observer.py | 2 +- docs/examples/basic_tracer/__init__.py | 2 +- docs/examples/basic_tracer/tests/__init__.py | 2 +- docs/examples/basic_tracer/tests/test_tracer.py | 2 +- docs/examples/basic_tracer/tracer.py | 2 +- docs/examples/http/__init__.py | 2 +- docs/examples/http/client.py | 2 +- docs/examples/http/server.py | 2 +- docs/examples/http/tests/__init__.py | 2 +- docs/examples/http/tests/test_http.py | 2 +- docs/examples/opentelemetry-example-app/setup.py | 2 +- .../src/opentelemetry_example_app/flask_example.py | 2 +- docs/examples/opentelemetry-example-app/tests/__init__.py | 2 +- .../opentelemetry-example-app/tests/test_flask_example.py | 2 +- docs/examples/otcollector-metrics/collector.py | 2 +- docs/examples/prometheus/prometheus.py | 2 +- ext/opentelemetry-ext-dbapi/setup.cfg | 2 +- ext/opentelemetry-ext-dbapi/setup.py | 2 +- .../src/opentelemetry/ext/dbapi/__init__.py | 2 +- .../src/opentelemetry/ext/dbapi/version.py | 2 +- ext/opentelemetry-ext-dbapi/tests/test_dbapi_integration.py | 2 +- .../tests/pymongo/test_pymongo_functional.py | 2 +- ext/opentelemetry-ext-flask/setup.cfg | 2 +- ext/opentelemetry-ext-flask/setup.py | 2 +- .../src/opentelemetry/ext/flask/version.py | 2 +- ext/opentelemetry-ext-flask/tests/test_flask_integration.py | 2 +- ext/opentelemetry-ext-http-requests/setup.cfg | 2 +- ext/opentelemetry-ext-http-requests/setup.py | 2 +- .../src/opentelemetry/ext/http_requests/__init__.py | 2 +- .../src/opentelemetry/ext/http_requests/version.py | 2 +- .../tests/test_requests_integration.py | 2 +- ext/opentelemetry-ext-jaeger/setup.cfg | 2 +- ext/opentelemetry-ext-jaeger/setup.py | 2 +- .../src/opentelemetry/ext/jaeger/__init__.py | 2 +- .../src/opentelemetry/ext/jaeger/version.py | 2 +- ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py | 2 +- ext/opentelemetry-ext-mysql/setup.cfg | 2 +- ext/opentelemetry-ext-mysql/setup.py | 2 +- .../src/opentelemetry/ext/mysql/__init__.py | 2 +- .../src/opentelemetry/ext/mysql/version.py | 2 +- ext/opentelemetry-ext-mysql/tests/test_mysql_integration.py | 2 +- ext/opentelemetry-ext-opentracing-shim/setup.cfg | 2 +- ext/opentelemetry-ext-opentracing-shim/setup.py | 2 +- .../src/opentelemetry/ext/opentracing_shim/__init__.py | 2 +- .../src/opentelemetry/ext/opentracing_shim/util.py | 2 +- .../src/opentelemetry/ext/opentracing_shim/version.py | 2 +- ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py | 2 +- ext/opentelemetry-ext-opentracing-shim/tests/test_util.py | 2 +- ext/opentelemetry-ext-otcollector/setup.cfg | 2 +- ext/opentelemetry-ext-otcollector/setup.py | 2 +- .../src/opentelemetry/ext/otcollector/__init__.py | 2 +- .../opentelemetry/ext/otcollector/metrics_exporter/__init__.py | 2 +- .../opentelemetry/ext/otcollector/trace_exporter/__init__.py | 2 +- .../src/opentelemetry/ext/otcollector/util.py | 2 +- .../src/opentelemetry/ext/otcollector/version.py | 2 +- .../tests/test_otcollector_metrics_exporter.py | 2 +- .../tests/test_otcollector_trace_exporter.py | 2 +- ext/opentelemetry-ext-prometheus/setup.cfg | 2 +- ext/opentelemetry-ext-prometheus/setup.py | 2 +- .../src/opentelemetry/ext/prometheus/__init__.py | 2 +- .../src/opentelemetry/ext/prometheus/version.py | 2 +- ext/opentelemetry-ext-prometheus/tests/__init__.py | 2 +- .../tests/test_prometheus_exporter.py | 2 +- ext/opentelemetry-ext-psycopg2/setup.cfg | 2 +- ext/opentelemetry-ext-psycopg2/setup.py | 2 +- .../src/opentelemetry/ext/psycopg2/__init__.py | 2 +- .../src/opentelemetry/ext/psycopg2/version.py | 2 +- .../tests/test_psycopg2_integration.py | 2 +- ext/opentelemetry-ext-pymongo/setup.cfg | 2 +- ext/opentelemetry-ext-pymongo/setup.py | 2 +- .../src/opentelemetry/ext/pymongo/__init__.py | 2 +- .../src/opentelemetry/ext/pymongo/version.py | 2 +- ext/opentelemetry-ext-pymongo/tests/test_pymongo.py | 2 +- ext/opentelemetry-ext-testutil/setup.cfg | 2 +- ext/opentelemetry-ext-testutil/setup.py | 2 +- ext/opentelemetry-ext-wsgi/setup.cfg | 2 +- ext/opentelemetry-ext-wsgi/setup.py | 2 +- .../src/opentelemetry/ext/wsgi/__init__.py | 2 +- .../src/opentelemetry/ext/wsgi/version.py | 2 +- ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py | 2 +- ext/opentelemetry-ext-zipkin/setup.cfg | 2 +- ext/opentelemetry-ext-zipkin/setup.py | 2 +- .../src/opentelemetry/ext/zipkin/__init__.py | 2 +- .../src/opentelemetry/ext/zipkin/version.py | 2 +- ext/opentelemetry-ext-zipkin/tests/__init__.py | 2 +- ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py | 2 +- opentelemetry-api/setup.py | 2 +- opentelemetry-api/src/opentelemetry/configuration/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/context/__init__.py | 2 +- .../src/opentelemetry/context/aiocontextvarsfix.py | 2 +- opentelemetry-api/src/opentelemetry/context/context.py | 2 +- .../src/opentelemetry/context/contextvars_context.py | 2 +- .../src/opentelemetry/context/threadlocal_context.py | 2 +- .../src/opentelemetry/correlationcontext/__init__.py | 2 +- .../opentelemetry/correlationcontext/propagation/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/logs/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/propagators/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/propagators/composite.py | 2 +- opentelemetry-api/src/opentelemetry/trace/__init__.py | 2 +- .../src/opentelemetry/trace/propagation/__init__.py | 2 +- .../src/opentelemetry/trace/propagation/httptextformat.py | 2 +- .../trace/propagation/tracecontexthttptextformat.py | 2 +- opentelemetry-api/src/opentelemetry/trace/sampling.py | 2 +- opentelemetry-api/src/opentelemetry/trace/status.py | 2 +- opentelemetry-api/src/opentelemetry/util/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/util/types.py | 2 +- opentelemetry-api/src/opentelemetry/util/version.py | 2 +- opentelemetry-api/tests/__init__.py | 2 +- opentelemetry-api/tests/configuration/test_configuration.py | 2 +- opentelemetry-api/tests/context/base_context.py | 2 +- opentelemetry-api/tests/context/test_context.py | 2 +- opentelemetry-api/tests/context/test_contextvars_context.py | 2 +- opentelemetry-api/tests/context/test_threadlocal_context.py | 2 +- .../tests/correlationcontext/test_correlation_context.py | 2 +- .../correlationcontext/test_correlation_context_propagation.py | 2 +- opentelemetry-api/tests/distributedcontext/__init__.py | 2 +- opentelemetry-api/tests/metrics/__init__.py | 2 +- opentelemetry-api/tests/metrics/test_metrics.py | 2 +- opentelemetry-api/tests/mypysmoke.py | 2 +- opentelemetry-api/tests/propagators/test_composite.py | 2 +- .../tests/propagators/test_global_httptextformat.py | 2 +- opentelemetry-api/tests/test_implementation.py | 2 +- opentelemetry-api/tests/trace/__init__.py | 2 +- .../tests/trace/propagation/test_tracecontexthttptextformat.py | 2 +- opentelemetry-api/tests/trace/test_defaultspan.py | 2 +- opentelemetry-api/tests/trace/test_sampling.py | 2 +- opentelemetry-api/tests/trace/test_tracer.py | 2 +- opentelemetry-sdk/setup.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/__init__.py | 2 +- .../src/opentelemetry/sdk/context/propagation/b3_format.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py | 2 +- .../src/opentelemetry/sdk/metrics/export/__init__.py | 2 +- .../src/opentelemetry/sdk/metrics/export/aggregate.py | 2 +- .../src/opentelemetry/sdk/metrics/export/batcher.py | 2 +- .../src/opentelemetry/sdk/metrics/export/controller.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py | 2 +- .../src/opentelemetry/sdk/trace/export/__init__.py | 2 +- .../opentelemetry/sdk/trace/export/in_memory_span_exporter.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py | 2 +- opentelemetry-sdk/src/opentelemetry/sdk/version.py | 2 +- opentelemetry-sdk/tests/__init__.py | 2 +- opentelemetry-sdk/tests/conftest.py | 2 +- opentelemetry-sdk/tests/context/propagation/test_b3_format.py | 2 +- opentelemetry-sdk/tests/context/test_asyncio.py | 2 +- opentelemetry-sdk/tests/correlationcontext/__init__.py | 2 +- opentelemetry-sdk/tests/metrics/__init__.py | 2 +- opentelemetry-sdk/tests/metrics/export/__init__.py | 2 +- opentelemetry-sdk/tests/metrics/export/test_export.py | 2 +- opentelemetry-sdk/tests/metrics/test_implementation.py | 2 +- opentelemetry-sdk/tests/metrics/test_metrics.py | 2 +- opentelemetry-sdk/tests/resources/test_resources.py | 2 +- opentelemetry-sdk/tests/test_util.py | 2 +- opentelemetry-sdk/tests/trace/__init__.py | 2 +- opentelemetry-sdk/tests/trace/export/__init__.py | 2 +- opentelemetry-sdk/tests/trace/export/test_export.py | 2 +- .../tests/trace/export/test_in_memory_span_exporter.py | 2 +- opentelemetry-sdk/tests/trace/test_implementation.py | 2 +- opentelemetry-sdk/tests/trace/test_trace.py | 2 +- tests/w3c_tracecontext_validation_server.py | 2 +- 164 files changed, 164 insertions(+), 164 deletions(-) diff --git a/docs/examples/basic_meter/basic_metrics.py b/docs/examples/basic_meter/basic_metrics.py index ac06284c328..e702be42e22 100644 --- a/docs/examples/basic_meter/basic_metrics.py +++ b/docs/examples/basic_meter/basic_metrics.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/basic_meter/calling_conventions.py b/docs/examples/basic_meter/calling_conventions.py index 946dccda628..6efa737e63c 100644 --- a/docs/examples/basic_meter/calling_conventions.py +++ b/docs/examples/basic_meter/calling_conventions.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/basic_meter/observer.py b/docs/examples/basic_meter/observer.py index 2b459f25bed..716968b4aef 100644 --- a/docs/examples/basic_meter/observer.py +++ b/docs/examples/basic_meter/observer.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/basic_tracer/__init__.py b/docs/examples/basic_tracer/__init__.py index 88051cd8bb0..c9670f80413 100644 --- a/docs/examples/basic_tracer/__init__.py +++ b/docs/examples/basic_tracer/__init__.py @@ -1,5 +1,5 @@ # pylint: disable=C0103 -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/basic_tracer/tests/__init__.py b/docs/examples/basic_tracer/tests/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/docs/examples/basic_tracer/tests/__init__.py +++ b/docs/examples/basic_tracer/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/basic_tracer/tests/test_tracer.py b/docs/examples/basic_tracer/tests/test_tracer.py index 4bd1a25c0ea..8f73c2bbb06 100644 --- a/docs/examples/basic_tracer/tests/test_tracer.py +++ b/docs/examples/basic_tracer/tests/test_tracer.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/basic_tracer/tracer.py b/docs/examples/basic_tracer/tracer.py index 51b2e69b129..20c520b88a8 100755 --- a/docs/examples/basic_tracer/tracer.py +++ b/docs/examples/basic_tracer/tracer.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/http/__init__.py b/docs/examples/http/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/docs/examples/http/__init__.py +++ b/docs/examples/http/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/http/client.py b/docs/examples/http/client.py index 7c5aaa41300..2b37d89597f 100755 --- a/docs/examples/http/client.py +++ b/docs/examples/http/client.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/http/server.py b/docs/examples/http/server.py index ab066e99bf4..67476c25db5 100755 --- a/docs/examples/http/server.py +++ b/docs/examples/http/server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/http/tests/__init__.py b/docs/examples/http/tests/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/docs/examples/http/tests/__init__.py +++ b/docs/examples/http/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/http/tests/test_http.py b/docs/examples/http/tests/test_http.py index dec0ce5f381..fe2a38cec0d 100644 --- a/docs/examples/http/tests/test_http.py +++ b/docs/examples/http/tests/test_http.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/setup.py b/docs/examples/opentelemetry-example-app/setup.py index aa40b5b26bd..220bcbf6ca4 100644 --- a/docs/examples/opentelemetry-example-app/setup.py +++ b/docs/examples/opentelemetry-example-app/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py index d523224d13a..a37048b7d49 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/tests/__init__.py b/docs/examples/opentelemetry-example-app/tests/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/docs/examples/opentelemetry-example-app/tests/__init__.py +++ b/docs/examples/opentelemetry-example-app/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/tests/test_flask_example.py b/docs/examples/opentelemetry-example-app/tests/test_flask_example.py index cbefadc5328..bc903a9c60c 100644 --- a/docs/examples/opentelemetry-example-app/tests/test_flask_example.py +++ b/docs/examples/opentelemetry-example-app/tests/test_flask_example.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/otcollector-metrics/collector.py b/docs/examples/otcollector-metrics/collector.py index 5e1f401e38b..9bef12603a1 100644 --- a/docs/examples/otcollector-metrics/collector.py +++ b/docs/examples/otcollector-metrics/collector.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/prometheus/prometheus.py b/docs/examples/prometheus/prometheus.py index 8806d007804..2561138fb11 100644 --- a/docs/examples/prometheus/prometheus.py +++ b/docs/examples/prometheus/prometheus.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-dbapi/setup.cfg b/ext/opentelemetry-ext-dbapi/setup.cfg index 451a994f92d..146e7ee2164 100644 --- a/ext/opentelemetry-ext-dbapi/setup.cfg +++ b/ext/opentelemetry-ext-dbapi/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-dbapi/setup.py b/ext/opentelemetry-ext-dbapi/setup.py index 5e1a68ac51b..f5c1b3fa814 100644 --- a/ext/opentelemetry-ext-dbapi/setup.py +++ b/ext/opentelemetry-ext-dbapi/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/__init__.py b/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/__init__.py index 7b015dd2fb5..0c18c672242 100644 --- a/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/__init__.py +++ b/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/version.py b/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/version.py +++ b/ext/opentelemetry-ext-dbapi/src/opentelemetry/ext/dbapi/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-dbapi/tests/test_dbapi_integration.py b/ext/opentelemetry-ext-dbapi/tests/test_dbapi_integration.py index afe5a49a02f..f0773788bce 100644 --- a/ext/opentelemetry-ext-dbapi/tests/test_dbapi_integration.py +++ b/ext/opentelemetry-ext-dbapi/tests/test_dbapi_integration.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-docker-tests/tests/pymongo/test_pymongo_functional.py b/ext/opentelemetry-ext-docker-tests/tests/pymongo/test_pymongo_functional.py index c728aebf380..7b018dab253 100644 --- a/ext/opentelemetry-ext-docker-tests/tests/pymongo/test_pymongo_functional.py +++ b/ext/opentelemetry-ext-docker-tests/tests/pymongo/test_pymongo_functional.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-flask/setup.cfg b/ext/opentelemetry-ext-flask/setup.cfg index 1d4956a82f7..61545bba1be 100644 --- a/ext/opentelemetry-ext-flask/setup.cfg +++ b/ext/opentelemetry-ext-flask/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-flask/setup.py b/ext/opentelemetry-ext-flask/setup.py index 34b27c60342..df9742c9006 100644 --- a/ext/opentelemetry-ext-flask/setup.py +++ b/ext/opentelemetry-ext-flask/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/version.py b/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/version.py +++ b/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-flask/tests/test_flask_integration.py b/ext/opentelemetry-ext-flask/tests/test_flask_integration.py index 9d2f2560118..9f61920ce94 100644 --- a/ext/opentelemetry-ext-flask/tests/test_flask_integration.py +++ b/ext/opentelemetry-ext-flask/tests/test_flask_integration.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-http-requests/setup.cfg b/ext/opentelemetry-ext-http-requests/setup.cfg index 7537aa340f8..36a81d7fc5a 100644 --- a/ext/opentelemetry-ext-http-requests/setup.cfg +++ b/ext/opentelemetry-ext-http-requests/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-http-requests/setup.py b/ext/opentelemetry-ext-http-requests/setup.py index 2f757e6cde4..d7917ed893d 100644 --- a/ext/opentelemetry-ext-http-requests/setup.py +++ b/ext/opentelemetry-ext-http-requests/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/__init__.py b/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/__init__.py index 517069ad0d3..418bdee2e6d 100644 --- a/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/__init__.py +++ b/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/version.py b/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/version.py +++ b/ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py b/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py index ea37cbbf1b6..5a007f5a25f 100644 --- a/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py +++ b/ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-jaeger/setup.cfg b/ext/opentelemetry-ext-jaeger/setup.cfg index a5f04f1e9b3..f28cb843328 100644 --- a/ext/opentelemetry-ext-jaeger/setup.cfg +++ b/ext/opentelemetry-ext-jaeger/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-jaeger/setup.py b/ext/opentelemetry-ext-jaeger/setup.py index 44f6eb32b1d..842a6f6416b 100644 --- a/ext/opentelemetry-ext-jaeger/setup.py +++ b/ext/opentelemetry-ext-jaeger/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/__init__.py b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/__init__.py index cee1596711f..77435aa261b 100644 --- a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/__init__.py +++ b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/__init__.py @@ -1,5 +1,5 @@ # Copyright 2018, OpenCensus Authors -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/version.py b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/version.py index aadc5afd63f..cebb24db32a 100644 --- a/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/version.py +++ b/ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/version.py @@ -1,5 +1,5 @@ # Copyright 2019, OpenCensus Authors -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py b/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py index 08c5a4adeda..e8ad734e0e0 100644 --- a/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py +++ b/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py @@ -1,5 +1,5 @@ # Copyright 2018, OpenCensus Authors -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-mysql/setup.cfg b/ext/opentelemetry-ext-mysql/setup.cfg index 2d69dadd0c0..916deb99c24 100644 --- a/ext/opentelemetry-ext-mysql/setup.cfg +++ b/ext/opentelemetry-ext-mysql/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-mysql/setup.py b/ext/opentelemetry-ext-mysql/setup.py index b2c62679e1f..4ba48fb4040 100644 --- a/ext/opentelemetry-ext-mysql/setup.py +++ b/ext/opentelemetry-ext-mysql/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/__init__.py b/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/__init__.py index 34151431ad8..9c146c66381 100644 --- a/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/__init__.py +++ b/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/version.py b/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/version.py +++ b/ext/opentelemetry-ext-mysql/src/opentelemetry/ext/mysql/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-mysql/tests/test_mysql_integration.py b/ext/opentelemetry-ext-mysql/tests/test_mysql_integration.py index 3b6eaa0c642..b4f1a006a19 100644 --- a/ext/opentelemetry-ext-mysql/tests/test_mysql_integration.py +++ b/ext/opentelemetry-ext-mysql/tests/test_mysql_integration.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/setup.cfg b/ext/opentelemetry-ext-opentracing-shim/setup.cfg index a9daabee0b2..aa89f10a49e 100644 --- a/ext/opentelemetry-ext-opentracing-shim/setup.cfg +++ b/ext/opentelemetry-ext-opentracing-shim/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/setup.py b/ext/opentelemetry-ext-opentracing-shim/setup.py index bbec88b5004..5924121c431 100644 --- a/ext/opentelemetry-ext-opentracing-shim/setup.py +++ b/ext/opentelemetry-ext-opentracing-shim/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py index 6e77ac5bc72..a547bca22e6 100644 --- a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py +++ b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/util.py b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/util.py index 97e2415e44f..eb7d3d9acaa 100644 --- a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/util.py +++ b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/util.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/version.py b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/version.py +++ b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py index 1d619ab2770..12c792d4e65 100644 --- a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py +++ b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/test_util.py b/ext/opentelemetry-ext-opentracing-shim/tests/test_util.py index 84bdc73a6a1..cbbd4b075aa 100644 --- a/ext/opentelemetry-ext-opentracing-shim/tests/test_util.py +++ b/ext/opentelemetry-ext-opentracing-shim/tests/test_util.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/setup.cfg b/ext/opentelemetry-ext-otcollector/setup.cfg index 203f2a6c823..069331815e9 100644 --- a/ext/opentelemetry-ext-otcollector/setup.cfg +++ b/ext/opentelemetry-ext-otcollector/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/setup.py b/ext/opentelemetry-ext-otcollector/setup.py index ecd84195115..d5c2886ac5f 100644 --- a/ext/opentelemetry-ext-otcollector/setup.py +++ b/ext/opentelemetry-ext-otcollector/setup.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/__init__.py b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/__init__.py index 0b2c26cb1d6..e3e5e43cdc3 100644 --- a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/__init__.py +++ b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/metrics_exporter/__init__.py b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/metrics_exporter/__init__.py index 12715035c25..8fcfd813734 100644 --- a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/metrics_exporter/__init__.py +++ b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/metrics_exporter/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/trace_exporter/__init__.py b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/trace_exporter/__init__.py index 8712682ecfd..495579574cb 100644 --- a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/trace_exporter/__init__.py +++ b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/trace_exporter/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/util.py b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/util.py index 7d605ab8f90..16c5af7e735 100644 --- a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/util.py +++ b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/util.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/version.py b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/version.py index 373ae92cb85..0941210ca3f 100644 --- a/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/version.py +++ b/ext/opentelemetry-ext-otcollector/src/opentelemetry/ext/otcollector/version.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py index ab6f4c8ccd5..716dac493cf 100644 --- a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py +++ b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py index 9a17ea6c94d..a731626b08a 100644 --- a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py +++ b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-prometheus/setup.cfg b/ext/opentelemetry-ext-prometheus/setup.cfg index f6bfd7c38b2..f060b7c7975 100644 --- a/ext/opentelemetry-ext-prometheus/setup.cfg +++ b/ext/opentelemetry-ext-prometheus/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-prometheus/setup.py b/ext/opentelemetry-ext-prometheus/setup.py index aa968af60db..0276cd66554 100644 --- a/ext/opentelemetry-ext-prometheus/setup.py +++ b/ext/opentelemetry-ext-prometheus/setup.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/__init__.py b/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/__init__.py index 533355aaf86..05d16b552d9 100644 --- a/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/__init__.py +++ b/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/version.py b/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/version.py index 373ae92cb85..0941210ca3f 100644 --- a/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/version.py +++ b/ext/opentelemetry-ext-prometheus/src/opentelemetry/ext/prometheus/version.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-prometheus/tests/__init__.py b/ext/opentelemetry-ext-prometheus/tests/__init__.py index 6ab2e961ec4..b0a6f428417 100644 --- a/ext/opentelemetry-ext-prometheus/tests/__init__.py +++ b/ext/opentelemetry-ext-prometheus/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index 512a3170adb..6c2d900c774 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-psycopg2/setup.cfg b/ext/opentelemetry-ext-psycopg2/setup.cfg index c7ddb5c25c4..bb9bff1f444 100644 --- a/ext/opentelemetry-ext-psycopg2/setup.cfg +++ b/ext/opentelemetry-ext-psycopg2/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-psycopg2/setup.py b/ext/opentelemetry-ext-psycopg2/setup.py index a84391e6dd4..df7f7c21288 100644 --- a/ext/opentelemetry-ext-psycopg2/setup.py +++ b/ext/opentelemetry-ext-psycopg2/setup.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/__init__.py b/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/__init__.py index f2fb4c40989..13c990dfbc2 100644 --- a/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/__init__.py +++ b/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/version.py b/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/version.py index 373ae92cb85..0941210ca3f 100644 --- a/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/version.py +++ b/ext/opentelemetry-ext-psycopg2/src/opentelemetry/ext/psycopg2/version.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-psycopg2/tests/test_psycopg2_integration.py b/ext/opentelemetry-ext-psycopg2/tests/test_psycopg2_integration.py index 56ab3a8aae7..a512ba4fa5c 100644 --- a/ext/opentelemetry-ext-psycopg2/tests/test_psycopg2_integration.py +++ b/ext/opentelemetry-ext-psycopg2/tests/test_psycopg2_integration.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-pymongo/setup.cfg b/ext/opentelemetry-ext-pymongo/setup.cfg index 927b2db3355..418986cbcd9 100644 --- a/ext/opentelemetry-ext-pymongo/setup.cfg +++ b/ext/opentelemetry-ext-pymongo/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-pymongo/setup.py b/ext/opentelemetry-ext-pymongo/setup.py index ed63ddf42da..301aded3383 100644 --- a/ext/opentelemetry-ext-pymongo/setup.py +++ b/ext/opentelemetry-ext-pymongo/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/__init__.py b/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/__init__.py index b27101e5907..f44bf4925ee 100644 --- a/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/__init__.py +++ b/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/version.py b/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/version.py +++ b/ext/opentelemetry-ext-pymongo/src/opentelemetry/ext/pymongo/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-pymongo/tests/test_pymongo.py b/ext/opentelemetry-ext-pymongo/tests/test_pymongo.py index 0889d9d994b..8c82e016792 100644 --- a/ext/opentelemetry-ext-pymongo/tests/test_pymongo.py +++ b/ext/opentelemetry-ext-pymongo/tests/test_pymongo.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-testutil/setup.cfg b/ext/opentelemetry-ext-testutil/setup.cfg index 520df8bf974..d7fbf21c59c 100644 --- a/ext/opentelemetry-ext-testutil/setup.cfg +++ b/ext/opentelemetry-ext-testutil/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-testutil/setup.py b/ext/opentelemetry-ext-testutil/setup.py index 9de576d3567..33b875ed06d 100644 --- a/ext/opentelemetry-ext-testutil/setup.py +++ b/ext/opentelemetry-ext-testutil/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-wsgi/setup.cfg b/ext/opentelemetry-ext-wsgi/setup.cfg index 1db49209bec..deffea3df90 100644 --- a/ext/opentelemetry-ext-wsgi/setup.cfg +++ b/ext/opentelemetry-ext-wsgi/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-wsgi/setup.py b/ext/opentelemetry-ext-wsgi/setup.py index 3f8ef9cc5fc..886800eacf9 100644 --- a/ext/opentelemetry-ext-wsgi/setup.py +++ b/ext/opentelemetry-ext-wsgi/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py index aa015fab2be..8ac9ec4a831 100644 --- a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py +++ b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/version.py b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/version.py +++ b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py b/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py index 1912dd0079f..2e009696c54 100644 --- a/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py +++ b/ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-zipkin/setup.cfg b/ext/opentelemetry-ext-zipkin/setup.cfg index 89d60d149a7..d4957f24a6a 100644 --- a/ext/opentelemetry-ext-zipkin/setup.cfg +++ b/ext/opentelemetry-ext-zipkin/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-zipkin/setup.py b/ext/opentelemetry-ext-zipkin/setup.py index f93bbad4490..a01df70c9d0 100644 --- a/ext/opentelemetry-ext-zipkin/setup.py +++ b/ext/opentelemetry-ext-zipkin/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/__init__.py b/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/__init__.py index 01e455a8316..ab2a6d1d947 100644 --- a/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/__init__.py +++ b/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/version.py b/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/version.py index ef946f58722..0941210ca3f 100644 --- a/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/version.py +++ b/ext/opentelemetry-ext-zipkin/src/opentelemetry/ext/zipkin/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-zipkin/tests/__init__.py b/ext/opentelemetry-ext-zipkin/tests/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/ext/opentelemetry-ext-zipkin/tests/__init__.py +++ b/ext/opentelemetry-ext-zipkin/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py b/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py index c779c7388f6..34183e923b4 100644 --- a/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py +++ b/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/setup.py b/opentelemetry-api/setup.py index 5eb91d1f1b6..2ba3602bf3b 100644 --- a/opentelemetry-api/setup.py +++ b/opentelemetry-api/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index f038e570168..850f0d4fe0f 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/context/__init__.py b/opentelemetry-api/src/opentelemetry/context/__init__.py index 1ac837f51c5..779bdc488c1 100644 --- a/opentelemetry-api/src/opentelemetry/context/__init__.py +++ b/opentelemetry-api/src/opentelemetry/context/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/context/aiocontextvarsfix.py b/opentelemetry-api/src/opentelemetry/context/aiocontextvarsfix.py index f0d4ce56ffa..bd8100041c8 100644 --- a/opentelemetry-api/src/opentelemetry/context/aiocontextvarsfix.py +++ b/opentelemetry-api/src/opentelemetry/context/aiocontextvarsfix.py @@ -1,5 +1,5 @@ # type: ignore -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/context/context.py b/opentelemetry-api/src/opentelemetry/context/context.py index 1c7cfba9634..c7508603a56 100644 --- a/opentelemetry-api/src/opentelemetry/context/context.py +++ b/opentelemetry-api/src/opentelemetry/context/context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/context/contextvars_context.py b/opentelemetry-api/src/opentelemetry/context/contextvars_context.py index 0d075e0776a..429fd10c2c5 100644 --- a/opentelemetry-api/src/opentelemetry/context/contextvars_context.py +++ b/opentelemetry-api/src/opentelemetry/context/contextvars_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py b/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py index 6a0e76bb693..43e9fb7ce9e 100644 --- a/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py +++ b/opentelemetry-api/src/opentelemetry/context/threadlocal_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py b/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py index 543c175dfe1..c16d75162ad 100644 --- a/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py +++ b/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/correlationcontext/propagation/__init__.py b/opentelemetry-api/src/opentelemetry/correlationcontext/propagation/__init__.py index c336f4476b6..fca9465fbb3 100644 --- a/opentelemetry-api/src/opentelemetry/correlationcontext/propagation/__init__.py +++ b/opentelemetry-api/src/opentelemetry/correlationcontext/propagation/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/logs/__init__.py b/opentelemetry-api/src/opentelemetry/logs/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-api/src/opentelemetry/logs/__init__.py +++ b/opentelemetry-api/src/opentelemetry/logs/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 0db7f125c84..64b47e3a12f 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/propagators/__init__.py b/opentelemetry-api/src/opentelemetry/propagators/__init__.py index 264fe06b5c3..5aa53e25dce 100644 --- a/opentelemetry-api/src/opentelemetry/propagators/__init__.py +++ b/opentelemetry-api/src/opentelemetry/propagators/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/propagators/composite.py b/opentelemetry-api/src/opentelemetry/propagators/composite.py index 4ec953c8395..50fba01423b 100644 --- a/opentelemetry-api/src/opentelemetry/propagators/composite.py +++ b/opentelemetry-api/src/opentelemetry/propagators/composite.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 69cca344b6a..4ea2ebd745f 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/__init__.py b/opentelemetry-api/src/opentelemetry/trace/propagation/__init__.py index 90e7f9dcb3c..f17350c7455 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/httptextformat.py b/opentelemetry-api/src/opentelemetry/trace/propagation/httptextformat.py index 500014d7384..e15e2a0e6d6 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/httptextformat.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/httptextformat.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py index 07d3ee05abc..46765011318 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/trace/sampling.py b/opentelemetry-api/src/opentelemetry/trace/sampling.py index c398efbf86c..892689783df 100644 --- a/opentelemetry-api/src/opentelemetry/trace/sampling.py +++ b/opentelemetry-api/src/opentelemetry/trace/sampling.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/trace/status.py b/opentelemetry-api/src/opentelemetry/trace/status.py index 0abe9747ada..4ae2ad96d08 100644 --- a/opentelemetry-api/src/opentelemetry/trace/status.py +++ b/opentelemetry-api/src/opentelemetry/trace/status.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/util/__init__.py b/opentelemetry-api/src/opentelemetry/util/__init__.py index 9bfc79df21c..9f68ef2d393 100644 --- a/opentelemetry-api/src/opentelemetry/util/__init__.py +++ b/opentelemetry-api/src/opentelemetry/util/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/util/types.py b/opentelemetry-api/src/opentelemetry/util/types.py index 5ce93d84b25..98836805533 100644 --- a/opentelemetry-api/src/opentelemetry/util/types.py +++ b/opentelemetry-api/src/opentelemetry/util/types.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/src/opentelemetry/util/version.py b/opentelemetry-api/src/opentelemetry/util/version.py index ef946f58722..0941210ca3f 100644 --- a/opentelemetry-api/src/opentelemetry/util/version.py +++ b/opentelemetry-api/src/opentelemetry/util/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/__init__.py b/opentelemetry-api/tests/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-api/tests/__init__.py +++ b/opentelemetry-api/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index 754f9c48942..a9387017f96 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/context/base_context.py b/opentelemetry-api/tests/context/base_context.py index 66e6df97a2d..05acc95d89a 100644 --- a/opentelemetry-api/tests/context/base_context.py +++ b/opentelemetry-api/tests/context/base_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/context/test_context.py b/opentelemetry-api/tests/context/test_context.py index 8942a333ed6..7dad1191c6c 100644 --- a/opentelemetry-api/tests/context/test_context.py +++ b/opentelemetry-api/tests/context/test_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/context/test_contextvars_context.py b/opentelemetry-api/tests/context/test_contextvars_context.py index d19ac5ca126..7a384f16782 100644 --- a/opentelemetry-api/tests/context/test_contextvars_context.py +++ b/opentelemetry-api/tests/context/test_contextvars_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/context/test_threadlocal_context.py b/opentelemetry-api/tests/context/test_threadlocal_context.py index 342163020ed..02c62ba1803 100644 --- a/opentelemetry-api/tests/context/test_threadlocal_context.py +++ b/opentelemetry-api/tests/context/test_threadlocal_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/correlationcontext/test_correlation_context.py b/opentelemetry-api/tests/correlationcontext/test_correlation_context.py index 3bddb951e26..31996c6913a 100644 --- a/opentelemetry-api/tests/correlationcontext/test_correlation_context.py +++ b/opentelemetry-api/tests/correlationcontext/test_correlation_context.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/correlationcontext/test_correlation_context_propagation.py b/opentelemetry-api/tests/correlationcontext/test_correlation_context_propagation.py index d0ecbdb17fd..c33326b173c 100644 --- a/opentelemetry-api/tests/correlationcontext/test_correlation_context_propagation.py +++ b/opentelemetry-api/tests/correlationcontext/test_correlation_context_propagation.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/distributedcontext/__init__.py b/opentelemetry-api/tests/distributedcontext/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-api/tests/distributedcontext/__init__.py +++ b/opentelemetry-api/tests/distributedcontext/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/metrics/__init__.py b/opentelemetry-api/tests/metrics/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-api/tests/metrics/__init__.py +++ b/opentelemetry-api/tests/metrics/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/metrics/test_metrics.py b/opentelemetry-api/tests/metrics/test_metrics.py index a2552d9f576..f0f6976eb06 100644 --- a/opentelemetry-api/tests/metrics/test_metrics.py +++ b/opentelemetry-api/tests/metrics/test_metrics.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/mypysmoke.py b/opentelemetry-api/tests/mypysmoke.py index 2891f3ee624..ede4af74e01 100644 --- a/opentelemetry-api/tests/mypysmoke.py +++ b/opentelemetry-api/tests/mypysmoke.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/propagators/test_composite.py b/opentelemetry-api/tests/propagators/test_composite.py index 09ac0ecf689..8c61b6dc1fa 100644 --- a/opentelemetry-api/tests/propagators/test_composite.py +++ b/opentelemetry-api/tests/propagators/test_composite.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/propagators/test_global_httptextformat.py b/opentelemetry-api/tests/propagators/test_global_httptextformat.py index 6045feb6754..cac24f30a08 100644 --- a/opentelemetry-api/tests/propagators/test_global_httptextformat.py +++ b/opentelemetry-api/tests/propagators/test_global_httptextformat.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/test_implementation.py b/opentelemetry-api/tests/test_implementation.py index 6d2aa215f5a..ea1e929eefb 100644 --- a/opentelemetry-api/tests/test_implementation.py +++ b/opentelemetry-api/tests/test_implementation.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/trace/__init__.py b/opentelemetry-api/tests/trace/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-api/tests/trace/__init__.py +++ b/opentelemetry-api/tests/trace/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py index a13d9630aec..f3c97aae015 100644 --- a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py +++ b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/trace/test_defaultspan.py b/opentelemetry-api/tests/trace/test_defaultspan.py index a20b55cc4e6..b6595579f9b 100644 --- a/opentelemetry-api/tests/trace/test_defaultspan.py +++ b/opentelemetry-api/tests/trace/test_defaultspan.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/trace/test_sampling.py b/opentelemetry-api/tests/trace/test_sampling.py index 0a3d8195285..3b5f1dc6fc1 100644 --- a/opentelemetry-api/tests/trace/test_sampling.py +++ b/opentelemetry-api/tests/trace/test_sampling.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-api/tests/trace/test_tracer.py b/opentelemetry-api/tests/trace/test_tracer.py index 20c218ad8f1..4fe3d20f78c 100644 --- a/opentelemetry-api/tests/trace/test_tracer.py +++ b/opentelemetry-api/tests/trace/test_tracer.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/setup.py b/opentelemetry-sdk/setup.py index 02bfc0a9e81..4e7ff2c99b8 100644 --- a/opentelemetry-sdk/setup.py +++ b/opentelemetry-sdk/setup.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/__init__.py index 7b87f0d8f6a..ca21f8b8609 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py b/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py index 3e03c9aa020..6b8d16bf563 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py index 55552ace7b1..05d88fc7648 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py index 6901a4efe46..a2513b1bfba 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/aggregate.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/aggregate.py index 5b730cc8040..20e5e5c2097 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/aggregate.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/aggregate.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/batcher.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/batcher.py index f4418c61399..a2a3ec48d38 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/batcher.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/batcher.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/controller.py b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/controller.py index 03c857f04d9..3b7db0e8863 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/controller.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/metrics/export/controller.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py index 05c015de68b..193f2831752 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 0c98cc33af6..94efa160116 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index e5d96eff9e9..d67f7b9f814 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py index 0818805f39c..e50ca614d68 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py index 009a0bcdd73..b8ebd22fc82 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py index 893a6066d9f..ee8111fdb11 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/util/instrumentation.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/version.py b/opentelemetry-sdk/src/opentelemetry/sdk/version.py index ef946f58722..0941210ca3f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/version.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/version.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/__init__.py b/opentelemetry-sdk/tests/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-sdk/tests/__init__.py +++ b/opentelemetry-sdk/tests/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/conftest.py b/opentelemetry-sdk/tests/conftest.py index 59e306f1303..80a79222a1f 100644 --- a/opentelemetry-sdk/tests/conftest.py +++ b/opentelemetry-sdk/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/context/propagation/test_b3_format.py b/opentelemetry-sdk/tests/context/propagation/test_b3_format.py index 0cdda1bcd0b..75b3f562b53 100644 --- a/opentelemetry-sdk/tests/context/propagation/test_b3_format.py +++ b/opentelemetry-sdk/tests/context/propagation/test_b3_format.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/context/test_asyncio.py b/opentelemetry-sdk/tests/context/test_asyncio.py index ea7ebbddbf8..f213753c59f 100644 --- a/opentelemetry-sdk/tests/context/test_asyncio.py +++ b/opentelemetry-sdk/tests/context/test_asyncio.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/correlationcontext/__init__.py b/opentelemetry-sdk/tests/correlationcontext/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-sdk/tests/correlationcontext/__init__.py +++ b/opentelemetry-sdk/tests/correlationcontext/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/__init__.py b/opentelemetry-sdk/tests/metrics/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-sdk/tests/metrics/__init__.py +++ b/opentelemetry-sdk/tests/metrics/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/export/__init__.py b/opentelemetry-sdk/tests/metrics/export/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-sdk/tests/metrics/export/__init__.py +++ b/opentelemetry-sdk/tests/metrics/export/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/export/test_export.py b/opentelemetry-sdk/tests/metrics/export/test_export.py index 33d8d07c299..5e0a8e46fb8 100644 --- a/opentelemetry-sdk/tests/metrics/export/test_export.py +++ b/opentelemetry-sdk/tests/metrics/export/test_export.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/test_implementation.py b/opentelemetry-sdk/tests/metrics/test_implementation.py index 1fedc9ae571..29b3b987f9a 100644 --- a/opentelemetry-sdk/tests/metrics/test_implementation.py +++ b/opentelemetry-sdk/tests/metrics/test_implementation.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/metrics/test_metrics.py b/opentelemetry-sdk/tests/metrics/test_metrics.py index dc09091c356..9212a9967c5 100644 --- a/opentelemetry-sdk/tests/metrics/test_metrics.py +++ b/opentelemetry-sdk/tests/metrics/test_metrics.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/resources/test_resources.py b/opentelemetry-sdk/tests/resources/test_resources.py index 16cf29057c8..959e23f0def 100644 --- a/opentelemetry-sdk/tests/resources/test_resources.py +++ b/opentelemetry-sdk/tests/resources/test_resources.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/test_util.py b/opentelemetry-sdk/tests/test_util.py index ead310bd8d4..cacc77dbd98 100644 --- a/opentelemetry-sdk/tests/test_util.py +++ b/opentelemetry-sdk/tests/test_util.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/trace/__init__.py b/opentelemetry-sdk/tests/trace/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-sdk/tests/trace/__init__.py +++ b/opentelemetry-sdk/tests/trace/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/trace/export/__init__.py b/opentelemetry-sdk/tests/trace/export/__init__.py index d853a7bcf65..b0a6f428417 100644 --- a/opentelemetry-sdk/tests/trace/export/__init__.py +++ b/opentelemetry-sdk/tests/trace/export/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/trace/export/test_export.py b/opentelemetry-sdk/tests/trace/export/test_export.py index cedb5967666..7a63963648c 100644 --- a/opentelemetry-sdk/tests/trace/export/test_export.py +++ b/opentelemetry-sdk/tests/trace/export/test_export.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py b/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py index 45b65fb3726..1054cc413d7 100644 --- a/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py +++ b/opentelemetry-sdk/tests/trace/export/test_in_memory_span_exporter.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/trace/test_implementation.py b/opentelemetry-sdk/tests/trace/test_implementation.py index 74d3d5a9232..cd53a643951 100644 --- a/opentelemetry-sdk/tests/trace/test_implementation.py +++ b/opentelemetry-sdk/tests/trace/test_implementation.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index a0e22f93113..3c5d1f1a581 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -1,4 +1,4 @@ -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/w3c_tracecontext_validation_server.py b/tests/w3c_tracecontext_validation_server.py index c2119f95873..7790fac12d9 100644 --- a/tests/w3c_tracecontext_validation_server.py +++ b/tests/w3c_tracecontext_validation_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright 2019, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From 656d3a49391602738972d5ac3684a1ae8aa75d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauricio=20V=C3=A1squez?= Date: Wed, 25 Mar 2020 14:03:19 -0500 Subject: [PATCH 38/59] Update PyPI classifiers (#525) - Update development status to beta - Add Python 3.8 to list of languages --- docs/examples/opentelemetry-example-app/setup.py | 2 +- ext/opentelemetry-ext-dbapi/setup.cfg | 3 ++- ext/opentelemetry-ext-flask/setup.cfg | 3 ++- ext/opentelemetry-ext-http-requests/setup.cfg | 3 ++- ext/opentelemetry-ext-jaeger/setup.cfg | 3 ++- ext/opentelemetry-ext-mysql/setup.cfg | 3 ++- ext/opentelemetry-ext-opentracing-shim/setup.cfg | 3 ++- ext/opentelemetry-ext-otcollector/setup.cfg | 3 ++- ext/opentelemetry-ext-prometheus/setup.cfg | 3 ++- ext/opentelemetry-ext-psycopg2/setup.cfg | 3 ++- ext/opentelemetry-ext-pymongo/setup.cfg | 3 ++- ext/opentelemetry-ext-testutil/setup.cfg | 3 ++- ext/opentelemetry-ext-wsgi/setup.cfg | 3 ++- ext/opentelemetry-ext-zipkin/setup.cfg | 3 ++- opentelemetry-api/setup.py | 3 ++- opentelemetry-sdk/setup.py | 3 ++- 16 files changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/examples/opentelemetry-example-app/setup.py b/docs/examples/opentelemetry-example-app/setup.py index 220bcbf6ca4..c90da05047a 100644 --- a/docs/examples/opentelemetry-example-app/setup.py +++ b/docs/examples/opentelemetry-example-app/setup.py @@ -20,7 +20,7 @@ author="OpenTelemetry Authors", author_email="cncf-opentelemetry-contributors@lists.cncf.io", classifiers=[ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", diff --git a/ext/opentelemetry-ext-dbapi/setup.cfg b/ext/opentelemetry-ext-dbapi/setup.cfg index 146e7ee2164..84d3ed4a208 100644 --- a/ext/opentelemetry-ext-dbapi/setup.cfg +++ b/ext/opentelemetry-ext-dbapi/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-flask/setup.cfg b/ext/opentelemetry-ext-flask/setup.cfg index 61545bba1be..3e5f722ed90 100644 --- a/ext/opentelemetry-ext-flask/setup.cfg +++ b/ext/opentelemetry-ext-flask/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-http-requests/setup.cfg b/ext/opentelemetry-ext-http-requests/setup.cfg index 36a81d7fc5a..ced12c71eba 100644 --- a/ext/opentelemetry-ext-http-requests/setup.cfg +++ b/ext/opentelemetry-ext-http-requests/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-jaeger/setup.cfg b/ext/opentelemetry-ext-jaeger/setup.cfg index f28cb843328..941c20d537d 100644 --- a/ext/opentelemetry-ext-jaeger/setup.cfg +++ b/ext/opentelemetry-ext-jaeger/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-mysql/setup.cfg b/ext/opentelemetry-ext-mysql/setup.cfg index 916deb99c24..d43bfd06455 100644 --- a/ext/opentelemetry-ext-mysql/setup.cfg +++ b/ext/opentelemetry-ext-mysql/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-opentracing-shim/setup.cfg b/ext/opentelemetry-ext-opentracing-shim/setup.cfg index aa89f10a49e..7b2278c78e9 100644 --- a/ext/opentelemetry-ext-opentracing-shim/setup.cfg +++ b/ext/opentelemetry-ext-opentracing-shim/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-otcollector/setup.cfg b/ext/opentelemetry-ext-otcollector/setup.cfg index 069331815e9..804e596d060 100644 --- a/ext/opentelemetry-ext-otcollector/setup.cfg +++ b/ext/opentelemetry-ext-otcollector/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-prometheus/setup.cfg b/ext/opentelemetry-ext-prometheus/setup.cfg index f060b7c7975..ed0b5e43c18 100644 --- a/ext/opentelemetry-ext-prometheus/setup.cfg +++ b/ext/opentelemetry-ext-prometheus/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-psycopg2/setup.cfg b/ext/opentelemetry-ext-psycopg2/setup.cfg index bb9bff1f444..25ee7012a62 100644 --- a/ext/opentelemetry-ext-psycopg2/setup.cfg +++ b/ext/opentelemetry-ext-psycopg2/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-pymongo/setup.cfg b/ext/opentelemetry-ext-pymongo/setup.cfg index 418986cbcd9..2dad6e62cb0 100644 --- a/ext/opentelemetry-ext-pymongo/setup.cfg +++ b/ext/opentelemetry-ext-pymongo/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-testutil/setup.cfg b/ext/opentelemetry-ext-testutil/setup.cfg index d7fbf21c59c..833a61b767f 100644 --- a/ext/opentelemetry-ext-testutil/setup.cfg +++ b/ext/opentelemetry-ext-testutil/setup.cfg @@ -22,7 +22,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -31,6 +31,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-wsgi/setup.cfg b/ext/opentelemetry-ext-wsgi/setup.cfg index deffea3df90..885e9c2dfb9 100644 --- a/ext/opentelemetry-ext-wsgi/setup.cfg +++ b/ext/opentelemetry-ext-wsgi/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/ext/opentelemetry-ext-zipkin/setup.cfg b/ext/opentelemetry-ext-zipkin/setup.cfg index d4957f24a6a..66326cbd58e 100644 --- a/ext/opentelemetry-ext-zipkin/setup.cfg +++ b/ext/opentelemetry-ext-zipkin/setup.cfg @@ -23,7 +23,7 @@ url = https://github.com/open-telemetry/opentelemetry-python/ext/opentelemetry-e platforms = any license = Apache-2.0 classifiers = - Development Status :: 3 - Alpha + Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License Programming Language :: Python @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [options] python_requires = >=3.4 diff --git a/opentelemetry-api/setup.py b/opentelemetry-api/setup.py index 2ba3602bf3b..61ad9ab3200 100644 --- a/opentelemetry-api/setup.py +++ b/opentelemetry-api/setup.py @@ -28,7 +28,7 @@ author="OpenTelemetry Authors", author_email="cncf-opentelemetry-contributors@lists.cncf.io", classifiers=[ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", @@ -37,6 +37,7 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", ], description="OpenTelemetry Python API", include_package_data=True, diff --git a/opentelemetry-sdk/setup.py b/opentelemetry-sdk/setup.py index 4e7ff2c99b8..ce17cb4577f 100644 --- a/opentelemetry-sdk/setup.py +++ b/opentelemetry-sdk/setup.py @@ -30,7 +30,7 @@ author="OpenTelemetry Authors", author_email="cncf-opentelemetry-contributors@lists.cncf.io", classifiers=[ - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", @@ -39,6 +39,7 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", ], description="OpenTelemetry Python SDK", include_package_data=True, From 8c495e14438252596b6667e5af4340ade3e12aa9 Mon Sep 17 00:00:00 2001 From: Mario Jonke Date: Thu, 26 Mar 2020 16:42:10 +0100 Subject: [PATCH 39/59] Add indicator if SpanContext was propagated from remote parent (#516) According to the spec a SpanContext should have an indicator if it was propagated from a remote parent. Introduces an is_remote flag on the SpanContext which gets set when the SpanContext is extracted in a propagaton. --- .../tests/test_jaeger_exporter.py | 13 ++++-- .../tests/test_shim.py | 15 +++++-- .../tests/test_otcollector_trace_exporter.py | 14 +++++-- .../tests/test_zipkin_exporter.py | 14 +++++-- .../src/opentelemetry/trace/__init__.py | 17 +++++--- .../propagation/tracecontexthttptextformat.py | 1 + .../test_tracecontexthttptextformat.py | 3 +- .../tests/trace/test_defaultspan.py | 6 ++- .../tests/trace/test_sampling.py | 42 ++++++++++++++----- .../sdk/context/propagation/b3_format.py | 1 + .../src/opentelemetry/sdk/trace/__init__.py | 6 ++- .../context/propagation/test_b3_format.py | 4 ++ opentelemetry-sdk/tests/trace/test_trace.py | 11 +++++ 13 files changed, 116 insertions(+), 31 deletions(-) diff --git a/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py b/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py index e8ad734e0e0..eac90455ade 100644 --- a/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py +++ b/ext/opentelemetry-ext-jaeger/tests/test_jaeger_exporter.py @@ -31,6 +31,7 @@ def setUp(self): context = trace_api.SpanContext( trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, + is_remote=False, ) self._test_span = trace.Span("test_span", context=context) @@ -133,9 +134,15 @@ def test_translate_to_jaeger(self): start_times[2] + durations[2], ) - span_context = trace_api.SpanContext(trace_id, span_id) - parent_context = trace_api.SpanContext(trace_id, parent_id) - other_context = trace_api.SpanContext(trace_id, other_id) + span_context = trace_api.SpanContext( + trace_id, span_id, is_remote=False + ) + parent_context = trace_api.SpanContext( + trace_id, parent_id, is_remote=False + ) + other_context = trace_api.SpanContext( + trace_id, other_id, is_remote=False + ) event_attributes = { "annotation_bool": True, diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py index 12c792d4e65..9f62b90ddf1 100644 --- a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py +++ b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py @@ -450,7 +450,7 @@ def test_log_event(self): def test_span_context(self): """Test construction of `SpanContextShim` objects.""" - otel_context = trace.SpanContext(1234, 5678) + otel_context = trace.SpanContext(1234, 5678, is_remote=False) context = opentracingshim.SpanContextShim(otel_context) self.assertIsInstance(context, opentracing.SpanContext) @@ -476,7 +476,9 @@ def test_span_on_error(self): def test_inject_http_headers(self): """Test `inject()` method for Format.HTTP_HEADERS.""" - otel_context = trace.SpanContext(trace_id=1220, span_id=7478) + otel_context = trace.SpanContext( + trace_id=1220, span_id=7478, is_remote=False + ) context = opentracingshim.SpanContextShim(otel_context) headers = {} @@ -487,7 +489,9 @@ def test_inject_http_headers(self): def test_inject_text_map(self): """Test `inject()` method for Format.TEXT_MAP.""" - otel_context = trace.SpanContext(trace_id=1220, span_id=7478) + otel_context = trace.SpanContext( + trace_id=1220, span_id=7478, is_remote=False + ) context = opentracingshim.SpanContextShim(otel_context) # Verify Format.TEXT_MAP @@ -499,7 +503,9 @@ def test_inject_text_map(self): def test_inject_binary(self): """Test `inject()` method for Format.BINARY.""" - otel_context = trace.SpanContext(trace_id=1220, span_id=7478) + otel_context = trace.SpanContext( + trace_id=1220, span_id=7478, is_remote=False + ) context = opentracingshim.SpanContextShim(otel_context) # Verify exception for non supported binary format. @@ -561,6 +567,7 @@ def extract( trace.SpanContext( trace_id=int(trace_id_list[0]), span_id=int(span_id_list[0]), + is_remote=True, ) ) ) diff --git a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py index a731626b08a..636639bb1a3 100644 --- a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py +++ b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_trace_exporter.py @@ -92,11 +92,16 @@ def test_translate_to_collector(self): span_context = trace_api.SpanContext( trace_id, span_id, + is_remote=False, trace_flags=TraceFlags(TraceFlags.SAMPLED), trace_state=trace_api.TraceState({"testKey": "testValue"}), ) - parent_context = trace_api.SpanContext(trace_id, parent_id) - other_context = trace_api.SpanContext(trace_id, span_id) + parent_context = trace_api.SpanContext( + trace_id, parent_id, is_remote=False + ) + other_context = trace_api.SpanContext( + trace_id, span_id, is_remote=False + ) event_attributes = { "annotation_bool": True, "annotation_string": "annotation_test", @@ -279,7 +284,10 @@ def test_export(self): trace_id = 0x6E0C63257DE34C926F9EFCD03927272E span_id = 0x34BF92DEEFC58C92 span_context = trace_api.SpanContext( - trace_id, span_id, trace_flags=TraceFlags(TraceFlags.SAMPLED) + trace_id, + span_id, + is_remote=False, + trace_flags=TraceFlags(TraceFlags.SAMPLED), ) otel_spans = [ trace.Span( diff --git a/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py b/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py index 34183e923b4..22c64b80152 100644 --- a/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py +++ b/ext/opentelemetry-ext-zipkin/tests/test_zipkin_exporter.py @@ -35,6 +35,7 @@ def setUp(self): context = trace_api.SpanContext( trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, + is_remote=False, ) self._test_span = trace.Span("test_span", context=context) @@ -114,10 +115,17 @@ def test_export(self): ) span_context = trace_api.SpanContext( - trace_id, span_id, trace_flags=TraceFlags(TraceFlags.SAMPLED) + trace_id, + span_id, + is_remote=False, + trace_flags=TraceFlags(TraceFlags.SAMPLED), + ) + parent_context = trace_api.SpanContext( + trace_id, parent_id, is_remote=False + ) + other_context = trace_api.SpanContext( + trace_id, other_id, is_remote=False ) - parent_context = trace_api.SpanContext(trace_id, parent_id) - other_context = trace_api.SpanContext(trace_id, other_id) event_attributes = { "annotation_bool": True, diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 4ea2ebd745f..69cfb157d67 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -319,12 +319,14 @@ class SpanContext: span_id: This span's ID. trace_flags: Trace options to propagate. trace_state: Tracing-system-specific info to propagate. + is_remote: True if propagated from a remote parent. """ def __init__( self, trace_id: int, span_id: int, + is_remote: bool, trace_flags: "TraceFlags" = DEFAULT_TRACE_OPTIONS, trace_state: "TraceState" = DEFAULT_TRACE_STATE, ) -> None: @@ -336,13 +338,17 @@ def __init__( self.span_id = span_id self.trace_flags = trace_flags self.trace_state = trace_state + self.is_remote = is_remote def __repr__(self) -> str: - return "{}(trace_id={}, span_id={}, trace_state={!r})".format( + return ( + "{}(trace_id={}, span_id={}, trace_state={!r}, is_remote={})" + ).format( type(self).__name__, format_trace_id(self.trace_id), format_span_id(self.span_id), self.trace_state, + self.is_remote, ) def is_valid(self) -> bool: @@ -402,10 +408,11 @@ def set_status(self, status: Status) -> None: INVALID_SPAN_ID = 0x0000000000000000 INVALID_TRACE_ID = 0x00000000000000000000000000000000 INVALID_SPAN_CONTEXT = SpanContext( - INVALID_TRACE_ID, - INVALID_SPAN_ID, - DEFAULT_TRACE_OPTIONS, - DEFAULT_TRACE_STATE, + trace_id=INVALID_TRACE_ID, + span_id=INVALID_SPAN_ID, + is_remote=False, + trace_flags=DEFAULT_TRACE_OPTIONS, + trace_state=DEFAULT_TRACE_STATE, ) INVALID_SPAN = DefaultSpan(INVALID_SPAN_CONTEXT) diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py index 46765011318..732ce96c665 100644 --- a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py +++ b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontexthttptextformat.py @@ -105,6 +105,7 @@ def extract( span_context = trace.SpanContext( trace_id=int(trace_id, 16), span_id=int(span_id, 16), + is_remote=True, trace_flags=trace.TraceFlags(trace_flags), trace_state=tracestate, ) diff --git a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py index f3c97aae015..11a8ecd56e9 100644 --- a/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py +++ b/opentelemetry-api/tests/trace/propagation/test_tracecontexthttptextformat.py @@ -72,6 +72,7 @@ def test_headers_with_tracestate(self): self.assertEqual( span_context.trace_state, {"foo": "1", "bar": "2", "baz": "3"} ) + self.assertTrue(span_context.is_remote) output = {} # type:typing.Dict[str, str] span = trace.DefaultSpan(span_context) @@ -155,7 +156,7 @@ def test_no_send_empty_tracestate(self): """ output = {} # type:typing.Dict[str, str] span = trace.DefaultSpan( - trace.SpanContext(self.TRACE_ID, self.SPAN_ID) + trace.SpanContext(self.TRACE_ID, self.SPAN_ID, is_remote=False) ) ctx = set_span_in_context(span) FORMAT.inject(dict.__setitem__, output, ctx) diff --git a/opentelemetry-api/tests/trace/test_defaultspan.py b/opentelemetry-api/tests/trace/test_defaultspan.py index b6595579f9b..d27f2b1bbcd 100644 --- a/opentelemetry-api/tests/trace/test_defaultspan.py +++ b/opentelemetry-api/tests/trace/test_defaultspan.py @@ -20,7 +20,11 @@ class TestDefaultSpan(unittest.TestCase): def test_ctor(self): context = trace.SpanContext( - 1, 1, trace.DEFAULT_TRACE_OPTIONS, trace.DEFAULT_TRACE_STATE + 1, + 1, + is_remote=False, + trace_flags=trace.DEFAULT_TRACE_OPTIONS, + trace_state=trace.DEFAULT_TRACE_STATE, ) span = trace.DefaultSpan(context) self.assertEqual(context, span.get_context()) diff --git a/opentelemetry-api/tests/trace/test_sampling.py b/opentelemetry-api/tests/trace/test_sampling.py index 3b5f1dc6fc1..0be222f3dc0 100644 --- a/opentelemetry-api/tests/trace/test_sampling.py +++ b/opentelemetry-api/tests/trace/test_sampling.py @@ -25,7 +25,9 @@ class TestSampler(unittest.TestCase): def test_always_on(self): no_record_always_on = sampling.ALWAYS_ON.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT + ), 0xDEADBEF1, 0xDEADBEF2, "unsampled parent, sampling on", @@ -34,7 +36,9 @@ def test_always_on(self): self.assertEqual(no_record_always_on.attributes, {}) sampled_always_on = sampling.ALWAYS_ON.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED + ), 0xDEADBEF1, 0xDEADBEF2, "sampled parent, sampling on", @@ -44,7 +48,9 @@ def test_always_on(self): def test_always_off(self): no_record_always_off = sampling.ALWAYS_OFF.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT + ), 0xDEADBEF1, 0xDEADBEF2, "unsampled parent, sampling off", @@ -53,7 +59,9 @@ def test_always_off(self): self.assertEqual(no_record_always_off.attributes, {}) sampled_always_on = sampling.ALWAYS_OFF.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED + ), 0xDEADBEF1, 0xDEADBEF2, "sampled parent, sampling off", @@ -63,7 +71,9 @@ def test_always_off(self): def test_default_on(self): no_record_default_on = sampling.DEFAULT_ON.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT + ), 0xDEADBEF1, 0xDEADBEF2, "unsampled parent, sampling on", @@ -72,7 +82,9 @@ def test_default_on(self): self.assertEqual(no_record_default_on.attributes, {}) sampled_default_on = sampling.DEFAULT_ON.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED + ), 0xDEADBEF1, 0xDEADBEF2, "sampled parent, sampling on", @@ -82,7 +94,9 @@ def test_default_on(self): def test_default_off(self): no_record_default_off = sampling.DEFAULT_OFF.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_DEFAULT), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_DEFAULT + ), 0xDEADBEF1, 0xDEADBEF2, "unsampled parent, sampling off", @@ -91,7 +105,9 @@ def test_default_off(self): self.assertEqual(no_record_default_off.attributes, {}) sampled_default_off = sampling.DEFAULT_OFF.should_sample( - trace.SpanContext(0xDEADBEEF, 0xDEADBEF0, trace_flags=TO_SAMPLED), + trace.SpanContext( + 0xDEADBEEF, 0xDEADBEF0, is_remote=False, trace_flags=TO_SAMPLED + ), 0xDEADBEF1, 0xDEADBEF2, "sampled parent, sampling off", @@ -120,7 +136,10 @@ def test_probability_sampler(self): self.assertFalse( sampler.should_sample( trace.SpanContext( - 0xDEADBEF0, 0xDEADBEF1, trace_flags=TO_DEFAULT + 0xDEADBEF0, + 0xDEADBEF1, + is_remote=False, + trace_flags=TO_DEFAULT, ), 0x7FFFFFFFFFFFFFFF, 0xDEADBEEF, @@ -130,7 +149,10 @@ def test_probability_sampler(self): self.assertTrue( sampler.should_sample( trace.SpanContext( - 0xDEADBEF0, 0xDEADBEF1, trace_flags=TO_SAMPLED + 0xDEADBEF0, + 0xDEADBEF1, + is_remote=False, + trace_flags=TO_SAMPLED, ), 0x8000000000000000, 0xDEADBEEF, diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py b/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py index 6b8d16bf563..e082ed03e4e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/context/propagation/b3_format.py @@ -112,6 +112,7 @@ def extract( # trace an span ids are encoded in hex, so must be converted trace_id=int(trace_id, 16), span_id=int(span_id, 16), + is_remote=True, trace_flags=trace.TraceFlags(options), trace_state=trace.TraceState(), ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 94efa160116..6211d1878ff 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -453,7 +453,11 @@ def start_span( # pylint: disable=too-many-locals trace_state = parent_context.trace_state context = trace_api.SpanContext( - trace_id, generate_span_id(), trace_flags, trace_state + trace_id, + generate_span_id(), + is_remote=False, + trace_flags=trace_flags, + trace_state=trace_state, ) # The sampler decides whether to create a real or no-op span at the diff --git a/opentelemetry-sdk/tests/context/propagation/test_b3_format.py b/opentelemetry-sdk/tests/context/propagation/test_b3_format.py index 75b3f562b53..8f06912b9ec 100644 --- a/opentelemetry-sdk/tests/context/propagation/test_b3_format.py +++ b/opentelemetry-sdk/tests/context/propagation/test_b3_format.py @@ -41,6 +41,7 @@ def get_child_parent_new_carrier(old_carrier): trace_api.SpanContext( parent_context.trace_id, trace.generate_span_id(), + is_remote=False, trace_flags=parent_context.trace_flags, trace_state=parent_context.trace_state, ), @@ -90,6 +91,7 @@ def test_extract_multi_header(self): new_carrier[FORMAT.PARENT_SPAN_ID_KEY], b3_format.format_span_id(parent.context.span_id), ) + self.assertTrue(parent.context.is_remote) self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1") def test_extract_single_header(self): @@ -111,6 +113,7 @@ def test_extract_single_header(self): b3_format.format_span_id(child.context.span_id), ) self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1") + self.assertTrue(parent.context.is_remote) child, parent, new_carrier = get_child_parent_new_carrier( { @@ -134,6 +137,7 @@ def test_extract_single_header(self): new_carrier[FORMAT.PARENT_SPAN_ID_KEY], b3_format.format_span_id(parent.context.span_id), ) + self.assertTrue(parent.context.is_remote) self.assertEqual(new_carrier[FORMAT.SAMPLED_KEY], "1") def test_extract_header_precedence(self): diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index 3c5d1f1a581..acf7e66b44f 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -268,6 +268,7 @@ def test_start_span_explicit(self): other_parent = trace_api.SpanContext( trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, + is_remote=False, trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), ) @@ -337,6 +338,7 @@ def test_start_as_current_span_explicit(self): other_parent = trace_api.SpanContext( trace_id=0x000000000000000000000000DEADBEEF, span_id=0x00000000DEADBEF0, + is_remote=False, ) self.assertIsNone(tracer.get_current_span()) @@ -378,6 +380,12 @@ def test_default_span_resource(self): # pylint: disable=protected-access self.assertIs(span.resource, resources._EMPTY_RESOURCE) + def test_span_context_remote_flag(self): + tracer = new_tracer() + + span = tracer.start_span("foo") + self.assertFalse(span.context.is_remote) + class TestSpan(unittest.TestCase): def setUp(self): @@ -564,14 +572,17 @@ def test_links(self): other_context1 = trace_api.SpanContext( trace_id=trace.generate_trace_id(), span_id=trace.generate_span_id(), + is_remote=False, ) other_context2 = trace_api.SpanContext( trace_id=trace.generate_trace_id(), span_id=trace.generate_span_id(), + is_remote=False, ) other_context3 = trace_api.SpanContext( trace_id=trace.generate_trace_id(), span_id=trace.generate_span_id(), + is_remote=False, ) links = [ trace_api.Link(other_context1), From ae08b19b85afead98311524fdc8d76cbcc47f7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gonz=C3=A1lez?= Date: Thu, 26 Mar 2020 20:50:06 +0100 Subject: [PATCH 40/59] docs: Remove authors from releases (#531) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A git shortlog provides the same functionality. Signed-off-by: Daniel González Lopes --- README.md | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/README.md b/README.md index 2bb9188b55c..abd77f006fb 100644 --- a/README.md +++ b/README.md @@ -136,21 +136,6 @@ release](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0. - Prometheus Metrics Exporter - New Examples and Improvements to Existing Examples -Thank you to the following individuals for contributing to this release: - -* Alex Boten -* Chris Kleinknecht -* Christian Neumüller -* Daniel González -* Diego Hurtado -* Golovin Pavel -* Hector Hernandez -* Jake Malachowski -* Joshua H Lang -* Leighton Chen -* Mauricio Vásquez -* Yusuke Tsutsumi - The [v0.5 beta release](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0.5.0) release includes: @@ -160,18 +145,6 @@ release](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0. - Global configuration module - Documentation improvements -Thank you to the following individuals for contributing to this release: - -* Alex Boten -* Chris Kleinknecht -* Dave Grochowski -* Diego Hurtado -* Hector Hernandez -* Leighton Chen -* Liz Fong-Jones -* Mauricio Vásquez -* Yusuke Tsutsumi - See the [project milestones](https://github.com/open-telemetry/opentelemetry-python/milestones) for details on upcoming releases. The dates and features described here are From 8100ab670c529dcac69ac2e4989872bf9c0e5359 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 26 Mar 2020 15:54:04 -0700 Subject: [PATCH 41/59] Update license boilerplate for #523 --- .../src/opentelemetry_example_app/grpc/gen/__init__.py | 2 +- .../src/opentelemetry_example_app/grpc/gen/codegen.py | 2 +- .../src/opentelemetry_example_app/grpc/gen/helloworld.proto | 2 +- .../src/opentelemetry_example_app/grpc/gen/route_guide.proto | 2 +- .../src/opentelemetry_example_app/grpc/hello_world_client.py | 2 +- .../src/opentelemetry_example_app/grpc/hello_world_server.py | 2 +- .../src/opentelemetry_example_app/grpc/route_guide_client.py | 2 +- .../src/opentelemetry_example_app/grpc/route_guide_resources.py | 2 +- .../src/opentelemetry_example_app/grpc/route_guide_server.py | 2 +- ext/opentelemetry-ext-grpc/setup.cfg | 2 +- ext/opentelemetry-ext-grpc/setup.py | 2 +- .../src/opentelemetry/ext/grpc/__init__.py | 2 +- .../src/opentelemetry/ext/grpc/_client.py | 2 +- .../src/opentelemetry/ext/grpc/_server.py | 2 +- .../src/opentelemetry/ext/grpc/_utilities.py | 2 +- .../src/opentelemetry/ext/grpc/version.py | 2 +- ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py index 0dca3063466..bcedda2270e 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/codegen.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/codegen.py index 5a7cc13d64f..72c24bad39e 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/codegen.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/codegen.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld.proto b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld.proto index a2313bd81c6..446102166db 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld.proto +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/helloworld.proto @@ -1,4 +1,4 @@ -// Copyright 2020, OpenTelemetry Authors +// Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide.proto b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide.proto index 777f48325a6..7017e93498d 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide.proto +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen/route_guide.proto @@ -1,4 +1,4 @@ -// Copyright 2020, OpenTelemetry Authors +// Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py index c653fe49615..62521bf0399 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py index c8c8ce27542..ed83dd77598 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py index 5e29492fcdf..27fd92aed5d 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py index 1fc4a90e105..24c24479782 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py index afae77afda0..76d27260d02 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/setup.cfg b/ext/opentelemetry-ext-grpc/setup.cfg index 83d479c8db5..df7074078b8 100644 --- a/ext/opentelemetry-ext-grpc/setup.cfg +++ b/ext/opentelemetry-ext-grpc/setup.cfg @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/setup.py b/ext/opentelemetry-ext-grpc/setup.py index 98c35654b77..9a0a4b5d1e3 100644 --- a/ext/opentelemetry-ext-grpc/setup.py +++ b/ext/opentelemetry-ext-grpc/setup.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 3ca2c1e2f32..81e08971027 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index 81a7a0ef96e..ae98a852646 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index f81c9d72f59..2d382dc2239 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py index ec1e5fe1f98..b6ff7d311a4 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_utilities.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py index 373ae92cb85..0941210ca3f 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/version.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 68c1ef84303..2e9f3c28904 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright The OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From d4b9ca08d4a6d02b3b7808ba3cc360557417f011 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 26 Mar 2020 16:30:44 -0700 Subject: [PATCH 42/59] Add example app protobuf req, add docs --- .../opentelemetry-example-app/setup.py | 2 ++ .../grpc/hello_world_client.py | 24 ++++++++++++++++--- .../grpc/hello_world_server.py | 22 +++++++++++++++-- .../grpc/route_guide_client.py | 21 +++++++++++++++- .../grpc/route_guide_server.py | 21 ++++++++++++++-- 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/docs/examples/opentelemetry-example-app/setup.py b/docs/examples/opentelemetry-example-app/setup.py index c90da05047a..9e641873cfe 100644 --- a/docs/examples/opentelemetry-example-app/setup.py +++ b/docs/examples/opentelemetry-example-app/setup.py @@ -41,6 +41,8 @@ "opentelemetry-ext-flask", "flask", "requests", + "opentelemetry-ext-grpc", + "protobuf~=3.11", ], license="Apache-2.0", package_dir={"": "src"}, diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py index 62521bf0399..40e0481833c 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py @@ -13,9 +13,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -# https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_client.py -# https://github.com/grpc/grpc/blob/v1.16.x/examples/python/interceptors/default_value/greeter_client.py -"""The Python implementation of the GRPC helloworld.Greeter client.""" +"""The Python implementation of the GRPC helloworld.Greeter client. + +Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed +to run these examples. To run this script in the context of the example app, +install ``opentelemetry-example-app``:: + + pip install -e ext/opentelemetry-ext-grpc/ + pip install -e docs/examples/opentelemetry-example-app + +Then run the server in one shell:: + + python -m opentelemetry_example_app.grpc.hello_world_server + +and the client in another:: + + python -m opentelemetry_example_app.grpc.hello_world_client + +See also: +https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_client.py +https://github.com/grpc/grpc/blob/v1.16.x/examples/python/interceptors/default_value/greeter_client.py +""" import logging diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py index ed83dd77598..f0ff2c7283b 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py @@ -13,8 +13,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -# https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py -"""The Python implementation of the GRPC helloworld.Greeter server.""" +"""The Python implementation of the GRPC helloworld.Greeter server. + +Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed +to run these examples. To run this script in the context of the example app, +install ``opentelemetry-example-app``:: + + pip install -e ext/opentelemetry-ext-grpc/ + pip install -e docs/examples/opentelemetry-example-app + +Then run the server in one shell:: + + python -m opentelemetry_example_app.grpc.hello_world_client + +and the client in another:: + + python -m opentelemetry_example_app.grpc.hello_world_server + +See also: +https://github.com/grpc/grpc/blob/master/examples/python/helloworld/greeter_server.py +""" import logging from concurrent import futures diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py index 27fd92aed5d..1f08de1cc6e 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py @@ -13,9 +13,28 @@ # See the License for the specific language governing permissions and # limitations under the License. + +"""The Python implementation of the gRPC route guide client. + +Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed +to run these examples. To run this script in the context of the example app, +install ``opentelemetry-example-app``:: + + pip install -e ext/opentelemetry-ext-grpc/ + pip install -e docs/examples/opentelemetry-example-app + +Then run the server in one shell:: + + python -m opentelemetry_example_app.grpc.route_guide_server + +and the client in another:: + + python -m opentelemetry_example_app.grpc.route_guide_client + +See also: # https://github.com/grpc/grpc/tree/master/examples/python/route_guide +""" -"""The Python implementation of the gRPC route guide client.""" import logging import random diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py index 76d27260d02..1926d7cd5cd 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py @@ -13,9 +13,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -# https://github.com/grpc/grpc/tree/master/examples/python/route_guide +"""The Python implementation of the gRPC route guide server. -"""The Python implementation of the gRPC route guide server.""" +Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed +to run these examples. To run this script in the context of the example app, +install ``opentelemetry-example-app``:: + + pip install -e ext/opentelemetry-ext-grpc/ + pip install -e docs/examples/opentelemetry-example-app + +Then run the server in one shell:: + + python -m opentelemetry_example_app.grpc.route_guide_server + +and the client in another:: + + python -m opentelemetry_example_app.grpc.route_guide_client + +See also: +https://github.com/grpc/grpc/tree/master/examples/python/route_guide +""" import logging import math From b484813f4c0c7ec17ef85ae62fd346cad7856303 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Thu, 26 Mar 2020 16:32:51 -0700 Subject: [PATCH 43/59] Formatting fix --- .../src/opentelemetry_example_app/grpc/route_guide_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py index 1f08de1cc6e..488cf050465 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py @@ -32,7 +32,7 @@ python -m opentelemetry_example_app.grpc.route_guide_client See also: -# https://github.com/grpc/grpc/tree/master/examples/python/route_guide +https://github.com/grpc/grpc/tree/master/examples/python/route_guide """ From f5ae6252844ecaf1842ca700ac9cb578d01cb0a9 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Fri, 27 Mar 2020 12:36:19 -0700 Subject: [PATCH 44/59] Remove grpc example app requirement for now --- docs/examples/opentelemetry-example-app/setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/examples/opentelemetry-example-app/setup.py b/docs/examples/opentelemetry-example-app/setup.py index 9e641873cfe..1466fd94635 100644 --- a/docs/examples/opentelemetry-example-app/setup.py +++ b/docs/examples/opentelemetry-example-app/setup.py @@ -41,7 +41,6 @@ "opentelemetry-ext-flask", "flask", "requests", - "opentelemetry-ext-grpc", "protobuf~=3.11", ], license="Apache-2.0", From 2ae99f91d87d3d862b2fd6178a3e14fe81b0f692 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Sun, 29 Mar 2020 21:16:09 -0700 Subject: [PATCH 45/59] Remove commented code --- .../src/opentelemetry/ext/grpc/_server.py | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index 2d382dc2239..dedb6602101 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -94,35 +94,11 @@ def set_details(self, details): return self._servicer_context.set_details(details) -# def _add_peer_tags(peer_str, tags): -# ipv4_re = r"ipv4:(?P
.+):(?P\d+)" -# match = re.match(ipv4_re, peer_str) -# if match: -# tags[ot_tags.PEER_HOST_IPV4] = match.group("address") -# tags[ot_tags.PEER_PORT] = match.group("port") -# return -# ipv6_re = r"ipv6:\[(?P
.+)\]:(?P\d+)" -# match = re.match(ipv6_re, peer_str) -# if match: -# tags[ot_tags.PEER_HOST_IPV6] = match.group("address") -# tags[ot_tags.PEER_PORT] = match.group("port") -# return -# logging.warning('Unrecognized peer: "%s"', peer_str) - - # On the service-side, errors can be signaled either by exceptions or by # calling `set_code` on the `servicer_context`. This function checks for the # latter and updates the span accordingly. def _check_error_code(span, servicer_context, rpc_info): if servicer_context.code != grpc.StatusCode.OK: - # span.set_tag("error", True) - # error_log = { - # "event": "error", - # "error.kind": str(servicer_context.code), - # } - # if servicer_context.details is not None: - # error_log["message"] = servicer_context.details - # span.log_kv(error_log) rpc_info.error = servicer_context.code From 9392b675c3f6fde3dc542f48648bf5db1c330efa Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 30 Mar 2020 08:58:28 -0700 Subject: [PATCH 46/59] need a lock when initializing the context --- .../tests/test_server_interceptor.py | 15 ------- .../src/opentelemetry/context/__init__.py | 45 ++++++++++--------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 2e9f3c28904..ae45702bea8 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -17,12 +17,10 @@ from concurrent import futures from contextlib import contextmanager from unittest import mock -from unittest.mock import patch import grpc from opentelemetry import context, trace -from opentelemetry.context.threadlocal_context import ThreadLocalRuntimeContext from opentelemetry.ext.grpc import server_interceptor from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk import trace as trace_sdk @@ -49,19 +47,6 @@ def service(self, handler_call_details): class TestOpenTelemetryServerInterceptor(unittest.TestCase): - - # FIXME: test_concurrent_server_spans fails with contextvars context. - def setUp(self) -> None: - super(TestOpenTelemetryServerInterceptor, self).setUp() - self.mock_runtime = patch.object( - context, "_RUNTIME_CONTEXT", ThreadLocalRuntimeContext() - ) - self.mock_runtime.start() - - def tearDown(self) -> None: - super(TestOpenTelemetryServerInterceptor, self).tearDown() - self.mock_runtime.stop() - def test_create_span(self): """Check that the interceptor wraps calls with spans server-side.""" diff --git a/opentelemetry-api/src/opentelemetry/context/__init__.py b/opentelemetry-api/src/opentelemetry/context/__init__.py index 779bdc488c1..adf1bc0869f 100644 --- a/opentelemetry-api/src/opentelemetry/context/__init__.py +++ b/opentelemetry-api/src/opentelemetry/context/__init__.py @@ -13,6 +13,7 @@ # limitations under the License. import logging +import threading import typing from functools import wraps from os import environ @@ -24,7 +25,7 @@ logger = logging.getLogger(__name__) _RUNTIME_CONTEXT = None # type: typing.Optional[RuntimeContext] - +_RUNTIME_CONTEXT_LOCK = threading.Lock() _F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any]) @@ -42,26 +43,30 @@ def wrapper( **kwargs: typing.Dict[typing.Any, typing.Any] ) -> typing.Optional[typing.Any]: global _RUNTIME_CONTEXT # pylint: disable=global-statement - if _RUNTIME_CONTEXT is None: - # FIXME use a better implementation of a configuration manager to avoid having - # to get configuration values straight from environment variables - if version_info < (3, 5): - # contextvars are not supported in 3.4, use thread-local storage - default_context = "threadlocal_context" - else: - default_context = "contextvars_context" - - configured_context = environ.get( - "OPENTELEMETRY_CONTEXT", default_context - ) # type: str - try: - _RUNTIME_CONTEXT = next( - iter_entry_points( - "opentelemetry_context", configured_context + + with _RUNTIME_CONTEXT_LOCK: + if _RUNTIME_CONTEXT is None: + # FIXME use a better implementation of a configuration manager to avoid having + # to get configuration values straight from environment variables + if version_info < (3, 5): + # contextvars are not supported in 3.4, use thread-local storage + default_context = "threadlocal_context" + else: + default_context = "contextvars_context" + + configured_context = environ.get( + "OPENTELEMETRY_CONTEXT", default_context + ) # type: str + try: + _RUNTIME_CONTEXT = next( + iter_entry_points( + "opentelemetry_context", configured_context + ) + ).load()() + except Exception: # pylint: disable=broad-except + logger.error( + "Failed to load context: %s", configured_context ) - ).load()() - except Exception: # pylint: disable=broad-except - logger.error("Failed to load context: %s", configured_context) return func(*args, **kwargs) # type: ignore return wrapper # type:ignore From ac3e6171cdd0bd83e8a3e8ff768dde7140957e32 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 13:29:01 -0700 Subject: [PATCH 47/59] Don't lint generated files --- .isort.cfg | 4 ++-- pyproject.toml | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.isort.cfg b/.isort.cfg index 4e7bff8bb45..3eda40d140a 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -13,5 +13,5 @@ line_length=79 ; docs: https://github.com/timothycrosley/isort#multi-line-output-modes multi_line_output=3 skip=target -skip_glob=ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen/*,.venv*/*,venv*/* -known_first_party=opentelemetry +skip_glob=**/gen/*,.venv*/*,venv*/* +known_first_party=opentelemetry,opentelemetry_example_app diff --git a/pyproject.toml b/pyproject.toml index 5d19c298827..961304074c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,8 +2,9 @@ line-length = 79 exclude = ''' ( - /( - ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen # generated files + /( # generated files + docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/gen| + ext/opentelemetry-ext-jaeger/src/opentelemetry/ext/jaeger/gen )/ ) ''' From 88a21fff1330524a1687d27f95f76069838bf454 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 13:29:24 -0700 Subject: [PATCH 48/59] Fix now-unused import --- ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index ae45702bea8..33aabd859ee 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -20,7 +20,7 @@ import grpc -from opentelemetry import context, trace +from opentelemetry import trace from opentelemetry.ext.grpc import server_interceptor from opentelemetry.ext.grpc.grpcext import intercept_server from opentelemetry.sdk import trace as trace_sdk From ef080be092e4efb41618ef339a421e5a8d86224c Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 13:30:25 -0700 Subject: [PATCH 49/59] Pylint grpcext fixes --- .../ext/grpc/grpcext/__init__.py | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py index abafa009bf6..463c532d29e 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -1,13 +1,13 @@ import abc -import six - -class UnaryClientInfo(six.with_metaclass(abc.ABCMeta)): - """Consists of various information about a unary RPC on the invocation-side. +class UnaryClientInfo(abc.ABC): + """Consists of various information about a unary RPC on the + invocation-side. Attributes: - full_method: A string of the full RPC method, i.e., /package.service/method. + full_method: A string of the full RPC method, i.e., + /package.service/method. timeout: The length of time in seconds to wait for the computation to terminate or be cancelled, or None if this method should block until the computation is terminated or is cancelled no matter how long that @@ -15,11 +15,13 @@ class UnaryClientInfo(six.with_metaclass(abc.ABCMeta)): """ -class StreamClientInfo(six.with_metaclass(abc.ABCMeta)): - """Consists of various information about a stream RPC on the invocation-side. +class StreamClientInfo(abc.ABC): + """Consists of various information about a stream RPC on the + invocation-side. Attributes: - full_method: A string of the full RPC method, i.e., /package.service/method. + full_method: A string of the full RPC method, i.e., + /package.service/method. is_client_stream: Indicates whether the RPC is client-streaming. is_server_stream: Indicates whether the RPC is server-streaming. timeout: The length of time in seconds to wait for the computation to @@ -29,7 +31,7 @@ class StreamClientInfo(six.with_metaclass(abc.ABCMeta)): """ -class UnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)): +class UnaryClientInterceptor(abc.ABC): """Affords intercepting unary-unary RPCs on the invocation-side.""" @abc.abstractmethod @@ -51,7 +53,7 @@ def intercept_unary(self, request, metadata, client_info, invoker): raise NotImplementedError() -class StreamClientInterceptor(six.with_metaclass(abc.ABCMeta)): +class StreamClientInterceptor(abc.ABC): """Affords intercepting stream RPCs on the invocation-side.""" @abc.abstractmethod @@ -92,30 +94,33 @@ def intercept_channel(channel, *interceptors): TypeError: If an interceptor derives from neither UnaryClientInterceptor nor StreamClientInterceptor. """ + # pylint: disable=import-outside-toplevel from . import _interceptor return _interceptor.intercept_channel(channel, *interceptors) -class UnaryServerInfo(six.with_metaclass(abc.ABCMeta)): +class UnaryServerInfo(abc.ABC): """Consists of various information about a unary RPC on the service-side. Attributes: - full_method: A string of the full RPC method, i.e., /package.service/method. + full_method: A string of the full RPC method, i.e., + /package.service/method. """ -class StreamServerInfo(six.with_metaclass(abc.ABCMeta)): +class StreamServerInfo(abc.ABC): """Consists of various information about a stream RPC on the service-side. Attributes: - full_method: A string of the full RPC method, i.e., /package.service/method. + full_method: A string of the full RPC method, i.e., + /package.service/method. is_client_stream: Indicates whether the RPC is client-streaming. is_server_stream: Indicates whether the RPC is server-streaming. """ -class UnaryServerInterceptor(six.with_metaclass(abc.ABCMeta)): +class UnaryServerInterceptor(abc.ABC): """Affords intercepting unary-unary RPCs on the service-side.""" @abc.abstractmethod @@ -136,7 +141,7 @@ def intercept_unary(self, request, servicer_context, server_info, handler): raise NotImplementedError() -class StreamServerInterceptor(six.with_metaclass(abc.ABCMeta)): +class StreamServerInterceptor(abc.ABC): """Affords intercepting stream RPCs on the service-side.""" @abc.abstractmethod @@ -176,6 +181,7 @@ def intercept_server(server, *interceptors): TypeError: If an interceptor derives from neither UnaryServerInterceptor nor StreamServerInterceptor. """ + # pylint: disable=import-outside-toplevel from . import _interceptor return _interceptor.intercept_server(server, *interceptors) From a6eb598748fe5538ef1e6dee672e09fb388650b9 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 13:54:11 -0700 Subject: [PATCH 50/59] Pylint fixes --- .../src/opentelemetry/ext/grpc/__init__.py | 4 ++-- .../src/opentelemetry/ext/grpc/_client.py | 10 +++++++--- .../src/opentelemetry/ext/grpc/_server.py | 7 +++++++ .../opentelemetry/ext/grpc/grpcext/__init__.py | 6 ++---- .../ext/grpc/grpcext/_interceptor.py | 17 ++++++++--------- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index 81e08971027..fa030bc84b2 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -22,7 +22,7 @@ def client_interceptor(tracer): Returns: An invocation-side interceptor object. """ - from . import _client + from . import _client # pylint: disable=import-outside-toplevel return _client.OpenTelemetryClientInterceptor(tracer) @@ -36,6 +36,6 @@ def server_interceptor(tracer): Returns: A service-side interceptor object. """ - from . import _server + from . import _server # pylint: disable=import-outside-toplevel return _server.OpenTelemetryServerInterceptor(tracer) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index ae98a852646..13135eba69b 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -13,6 +13,9 @@ # limitations under the License. """Implementation of the invocation-side open-telemetry interceptor.""" +# pylint:disable=no-member +# pylint:disable=arguments-differ +# pylint:disable=signature-differs from collections import OrderedDict from typing import MutableMapping @@ -25,7 +28,7 @@ from ._utilities import RpcInfo -class _GuardedSpan(object): +class _GuardedSpan: def __init__(self, span): self.span = span self._engaged = True @@ -37,8 +40,7 @@ def __enter__(self): def __exit__(self, *args, **kwargs): if self._engaged: return self.span.__exit__(*args, **kwargs) - else: - return False + return False def release(self): self._engaged = False @@ -46,6 +48,7 @@ def release(self): def _inject_span_context(metadata: MutableMapping[str, str]) -> None: + # pylint:disable=unused-argument def append_metadata( carrier: MutableMapping[str, str], key: str, value: str ): @@ -79,6 +82,7 @@ def _start_span(self, method): name=method, kind=trace.SpanKind.CLIENT ) + # pylint:disable=no-self-use def _trace_result(self, guarded_span, rpc_info, result): # If the RPC is called asynchronously, release the guard and add a # callback so that the span can be finished once the future is done. diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index dedb6602101..6df7581f35a 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -17,6 +17,9 @@ This library borrows heavily from the OpenTracing gRPC integration: https://github.com/opentracing-contrib/python-grpc """ +# pylint:disable=no-member +# pylint:disable=arguments-differ +# pylint:disable=signature-differs from contextlib import contextmanager from typing import List @@ -30,12 +33,14 @@ from ._utilities import RpcInfo +# pylint:disable=abstract-method class _OpenTelemetryServicerContext(grpc.ServicerContext): def __init__(self, servicer_context, active_span): self._servicer_context = servicer_context self._active_span = active_span self.code = grpc.StatusCode.OK self.details = None + super(_OpenTelemetryServicerContext, self).__init__() def is_active(self, *args, **kwargs): return self._servicer_context.is_active(*args, **kwargs) @@ -97,6 +102,7 @@ def set_details(self, details): # On the service-side, errors can be signaled either by exceptions or by # calling `set_code` on the `servicer_context`. This function checks for the # latter and updates the span accordingly. +# pylint:disable=unused-argument def _check_error_code(span, servicer_context, rpc_info): if servicer_context.code != grpc.StatusCode.OK: rpc_info.error = servicer_context.code @@ -109,6 +115,7 @@ def __init__(self, tracer): self._tracer = tracer @contextmanager + # pylint:disable=no-self-use def _set_remote_context(self, servicer_context): metadata = servicer_context.invocation_metadata() if metadata: diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py index 463c532d29e..fb519204b56 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -94,8 +94,7 @@ def intercept_channel(channel, *interceptors): TypeError: If an interceptor derives from neither UnaryClientInterceptor nor StreamClientInterceptor. """ - # pylint: disable=import-outside-toplevel - from . import _interceptor + from . import _interceptor # pylint: disable=import-outside-toplevel return _interceptor.intercept_channel(channel, *interceptors) @@ -181,8 +180,7 @@ def intercept_server(server, *interceptors): TypeError: If an interceptor derives from neither UnaryServerInterceptor nor StreamServerInterceptor. """ - # pylint: disable=import-outside-toplevel - from . import _interceptor + from . import _interceptor # pylint: disable=import-outside-toplevel return _interceptor.intercept_server(server, *interceptors) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py index 2c936cbcd87..a4cde0974cd 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -1,4 +1,7 @@ """Implementation of gRPC Python interceptors.""" +# pylint:disable=no-member +# pylint:disable=arguments-differ +# pylint:disable=signature-differs import collections @@ -8,7 +11,7 @@ class _UnaryClientInfo( - collections.namedtuple("_UnaryClientInfo", ("full_method", "timeout",)) + collections.namedtuple("_UnaryClientInfo", ("full_method", "timeout")) ): pass @@ -165,8 +168,7 @@ def unary_unary( return _InterceptorUnaryUnaryMultiCallable( method, base_callable, self._interceptor ) - else: - return base_callable + return base_callable def unary_stream( self, method, request_serializer=None, response_deserializer=None @@ -178,8 +180,7 @@ def unary_stream( return _InterceptorUnaryStreamMultiCallable( method, base_callable, self._interceptor ) - else: - return base_callable + return base_callable def stream_unary( self, method, request_serializer=None, response_deserializer=None @@ -191,8 +192,7 @@ def stream_unary( return _InterceptorStreamUnaryMultiCallable( method, base_callable, self._interceptor ) - else: - return base_callable + return base_callable def stream_stream( self, method, request_serializer=None, response_deserializer=None @@ -204,8 +204,7 @@ def stream_stream( return _InterceptorStreamStreamMultiCallable( method, base_callable, self._interceptor ) - else: - return base_callable + return base_callable def close(self): if not hasattr(self._channel, "close"): From 08e6687da51a5b5f304ffe523fc30130bfbec205 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 15:06:03 -0700 Subject: [PATCH 51/59] Pylint fixes, ignores --- docs/examples/basic_meter/observer.py | 1 - .../grpc/hello_world_client.py | 2 ++ .../grpc/hello_world_server.py | 2 ++ .../grpc/route_guide_client.py | 1 + .../grpc/route_guide_resources.py | 2 ++ .../grpc/route_guide_server.py | 6 +++-- .../src/opentelemetry/ext/grpc/__init__.py | 9 ++++++-- .../src/opentelemetry/ext/grpc/_client.py | 6 +++-- .../src/opentelemetry/ext/grpc/_server.py | 8 ++++--- .../ext/grpc/grpcext/__init__.py | 22 +++++++++++++++++-- .../ext/grpc/grpcext/_interceptor.py | 21 ++++++++++++++++-- 11 files changed, 66 insertions(+), 14 deletions(-) diff --git a/docs/examples/basic_meter/observer.py b/docs/examples/basic_meter/observer.py index 0490fbe8efb..1d40e1c0756 100644 --- a/docs/examples/basic_meter/observer.py +++ b/docs/examples/basic_meter/observer.py @@ -17,7 +17,6 @@ asynchronous metrics data. """ import psutil - from opentelemetry import metrics from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py index 40e0481833c..2f2351b9afc 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_client.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=import-error + """The Python implementation of the GRPC helloworld.Greeter client. Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py index f0ff2c7283b..86dcd66527c 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/hello_world_server.py @@ -13,6 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=import-error + """The Python implementation of the GRPC helloworld.Greeter server. Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py index 488cf050465..18391b4228c 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_client.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=import-error """The Python implementation of the gRPC route guide client. diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py index 24c24479782..c7977698ba7 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_resources.py @@ -14,6 +14,8 @@ # https://github.com/grpc/grpc/tree/master/examples/python/route_guide +# pylint: disable=import-error + """Common resources used in the gRPC route guide example.""" import json diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py index 1926d7cd5cd..9cd9db666e3 100755 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/grpc/route_guide_server.py @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=import-error +# pylint: disable=invalid-name + """The Python implementation of the gRPC route guide server. Note that you need ``opentelemetry-ext-grpc`` and ``protobuf`` to be installed @@ -111,8 +114,7 @@ def GetFeature(self, request, context): feature = get_feature(self.db, request) if feature is None: return route_guide_pb2.Feature(name="", location=request) - else: - return feature + return feature def ListFeatures(self, request, context): left = min(request.lo.longitude, request.hi.longitude) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index fa030bc84b2..e8312e7eff1 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -12,6 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=import-outside-toplevel +# pylint: disable=import-self +# pylint: disable=no-name-in-module +# pylint: disable=relative-beyond-top-level + def client_interceptor(tracer): """Create a gRPC client channel interceptor. @@ -22,7 +27,7 @@ def client_interceptor(tracer): Returns: An invocation-side interceptor object. """ - from . import _client # pylint: disable=import-outside-toplevel + from . import _client return _client.OpenTelemetryClientInterceptor(tracer) @@ -36,6 +41,6 @@ def server_interceptor(tracer): Returns: A service-side interceptor object. """ - from . import _server # pylint: disable=import-outside-toplevel + from . import _server return _server.OpenTelemetryServerInterceptor(tracer) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index 13135eba69b..3ea8dcc14e6 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -12,11 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Implementation of the invocation-side open-telemetry interceptor.""" -# pylint:disable=no-member +# pylint: disable=relative-beyond-top-level # pylint:disable=arguments-differ +# pylint:disable=no-member # pylint:disable=signature-differs +"""Implementation of the invocation-side open-telemetry interceptor.""" + from collections import OrderedDict from typing import MutableMapping diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index 6df7581f35a..aa1fa3a357c 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -12,14 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=relative-beyond-top-level +# pylint:disable=arguments-differ +# pylint:disable=no-member +# pylint:disable=signature-differs + """Implementation of the service-side open-telemetry interceptor. This library borrows heavily from the OpenTracing gRPC integration: https://github.com/opentracing-contrib/python-grpc """ -# pylint:disable=no-member -# pylint:disable=arguments-differ -# pylint:disable=signature-differs from contextlib import contextmanager from typing import List diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py index fb519204b56..934eb57348a 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -1,3 +1,21 @@ +# Copyright The OpenTelemetry 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. + +# pylint: disable=import-outside-toplevel +# pylint: disable=import-self +# pylint: disable=no-name-in-module + import abc @@ -94,7 +112,7 @@ def intercept_channel(channel, *interceptors): TypeError: If an interceptor derives from neither UnaryClientInterceptor nor StreamClientInterceptor. """ - from . import _interceptor # pylint: disable=import-outside-toplevel + from . import _interceptor return _interceptor.intercept_channel(channel, *interceptors) @@ -180,7 +198,7 @@ def intercept_server(server, *interceptors): TypeError: If an interceptor derives from neither UnaryServerInterceptor nor StreamServerInterceptor. """ - from . import _interceptor # pylint: disable=import-outside-toplevel + from . import _interceptor return _interceptor.intercept_server(server, *interceptors) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py index a4cde0974cd..01b58f47c53 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -1,8 +1,25 @@ -"""Implementation of gRPC Python interceptors.""" -# pylint:disable=no-member +# Copyright The OpenTelemetry 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. + +# pylint: disable=relative-beyond-top-level # pylint:disable=arguments-differ +# pylint:disable=no-member # pylint:disable=signature-differs +"""Implementation of gRPC Python interceptors.""" + + import collections import grpc From 59858d42887f1794c4ca7302531cfc788ae51927 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 15:11:51 -0700 Subject: [PATCH 52/59] More pylint fixes --- .../src/opentelemetry/ext/grpc/__init__.py | 8 ++++---- .../src/opentelemetry/ext/grpc/_client.py | 2 +- .../src/opentelemetry/ext/grpc/_server.py | 2 +- .../src/opentelemetry/ext/grpc/grpcext/__init__.py | 6 +++--- .../src/opentelemetry/ext/grpc/grpcext/_interceptor.py | 2 +- .../tests/test_server_interceptor.py | 9 +++++++-- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py index e8312e7eff1..8807abcb1f2 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/__init__.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=import-outside-toplevel -# pylint: disable=import-self -# pylint: disable=no-name-in-module -# pylint: disable=relative-beyond-top-level +# pylint:disable=import-outside-toplevel +# pylint:disable=import-self +# pylint:disable=no-name-in-module +# pylint:disable=relative-beyond-top-level def client_interceptor(tracer): diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py index 3ea8dcc14e6..ebf455910c7 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_client.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=relative-beyond-top-level +# pylint:disable=relative-beyond-top-level # pylint:disable=arguments-differ # pylint:disable=no-member # pylint:disable=signature-differs diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py index aa1fa3a357c..cb0e997d367 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/_server.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=relative-beyond-top-level +# pylint:disable=relative-beyond-top-level # pylint:disable=arguments-differ # pylint:disable=no-member # pylint:disable=signature-differs diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py index 934eb57348a..fe83467a70a 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/__init__.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=import-outside-toplevel -# pylint: disable=import-self -# pylint: disable=no-name-in-module +# pylint:disable=import-outside-toplevel +# pylint:disable=import-self +# pylint:disable=no-name-in-module import abc diff --git a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py index 01b58f47c53..0cae2cf9fde 100644 --- a/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py +++ b/ext/opentelemetry-ext-grpc/src/opentelemetry/ext/grpc/grpcext/_interceptor.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=relative-beyond-top-level +# pylint:disable=relative-beyond-top-level # pylint:disable=arguments-differ # pylint:disable=no-member # pylint:disable=signature-differs diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index 33aabd859ee..e575a610a9e 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint:disable=unused-argument +# pylint:disable=no-self-use + import threading import unittest from concurrent import futures @@ -153,6 +156,7 @@ def handler(request, context): server.stop(None) self.assertEqual(len(active_spans_in_handler), 2) + # pylint:disable=unbalanced-tuple-unpacking span1, span2 = active_spans_in_handler # Spans should belong to separate traces, and each should be a root # span @@ -206,6 +210,7 @@ def handler(request, context): server.stop(None) self.assertEqual(len(active_spans_in_handler), 2) + # pylint:disable=unbalanced-tuple-unpacking span1, span2 = active_spans_in_handler # Spans should belong to separate traces, and each should be a root # span @@ -215,7 +220,7 @@ def handler(request, context): self.assertIsNone(span1.parent) -def get_latch(n): +def get_latch(num): """Get a countdown latch function for use in n threads.""" cv = threading.Condition() count = 0 @@ -228,7 +233,7 @@ def countdown_latch(): cv.notify() cv.release() cv.acquire() - while count < n: + while count < num: cv.wait() cv.release() From 9f5c85a4a44ba91fc5745db7dae132d151b5e7da Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 16:00:19 -0700 Subject: [PATCH 53/59] Misc isort fixes (#535) --- .isort.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/.isort.cfg b/.isort.cfg index 3eda40d140a..c5723b06a20 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -15,3 +15,4 @@ multi_line_output=3 skip=target skip_glob=**/gen/*,.venv*/*,venv*/* known_first_party=opentelemetry,opentelemetry_example_app +known_third_party=psutil,pytest From 4e048e0a90297fcb3994dc0859d662f1dd95d1d7 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Mon, 30 Mar 2020 16:32:36 -0700 Subject: [PATCH 54/59] adding a tox environment for grpc --- tox.ini | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 6e64bdbd441..6b2f94b9913 100644 --- a/tox.ini +++ b/tox.ini @@ -76,8 +76,13 @@ envlist = py3{4,5,6,7,8}-test-opentracing-shim pypy3-test-opentracing-shim + ; opentelemetry-opentracing-shim + py3{4,5,6,7,8}-test-opentracing-shim + pypy3-test-opentracing-shim - py3{4,5,6,7,8}-coverage + ; opentelemetry-opentracing-shim + py3{4,5,6,7,8}-test-ext-grpc + pypy3-test-ext-grpc ; Coverage is temporarily disabled for pypy3 due to the pytest bug. ; pypy3-coverage @@ -107,6 +112,7 @@ changedir = test-api: opentelemetry-api/tests test-sdk: opentelemetry-sdk/tests test-auto-instrumentation: opentelemetry-auto-instrumentation/tests + test-ext-grpc: ext/opentelemetry-ext-grpc/tests test-ext-http-requests: ext/opentelemetry-ext-http-requests/tests test-ext-jaeger: ext/opentelemetry-ext-jaeger/tests test-ext-dbapi: ext/opentelemetry-ext-dbapi/tests @@ -144,6 +150,8 @@ commands_pre = example-http: pip install -r {toxinidir}/docs/examples/http/requirements.txt ext: pip install {toxinidir}/opentelemetry-api + grpc: pip install {toxinidir}/ext/opentelemetry-ext-grpc + grpc: pip install {toxinidir}/opentelemetry-sdk wsgi,flask: pip install {toxinidir}/ext/opentelemetry-ext-testutil wsgi,flask: pip install {toxinidir}/ext/opentelemetry-ext-wsgi wsgi,flask: pip install {toxinidir}/opentelemetry-sdk From 7b950a893a3047cc870fbf704b695e874d3a7e47 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Mon, 30 Mar 2020 16:50:28 -0700 Subject: [PATCH 55/59] fixing lint --- docs/examples/basic_meter/observer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/examples/basic_meter/observer.py b/docs/examples/basic_meter/observer.py index 1d40e1c0756..0490fbe8efb 100644 --- a/docs/examples/basic_meter/observer.py +++ b/docs/examples/basic_meter/observer.py @@ -17,6 +17,7 @@ asynchronous metrics data. """ import psutil + from opentelemetry import metrics from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter From 06b4c193437e83f526efa21a7db8f00b3bc614df Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 16:20:11 -0700 Subject: [PATCH 56/59] Less silly documentation --- ext/opentelemetry-ext-grpc/README.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/opentelemetry-ext-grpc/README.rst b/ext/opentelemetry-ext-grpc/README.rst index c00f2f24f5d..335c03614b9 100644 --- a/ext/opentelemetry-ext-grpc/README.rst +++ b/ext/opentelemetry-ext-grpc/README.rst @@ -6,7 +6,9 @@ OpenTelemetry gRPC Integration .. |pypi| image:: https://badge.fury.io/py/opentelemetry-ext-grpc.svg :target: https://pypi.org/project/opentelemetry-ext-grpc/ -gRPC support! +Client and server interceptors for `gRPC Python`_. + +.. _gRPC Python: https://grpc.github.io/grpc/python/grpc.html Installation ------------ From 8956bfba8f528191d1a785804929382b73ba8d95 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 17:15:28 -0700 Subject: [PATCH 57/59] Py3.4 threadpools need max_workers --- .../tests/test_server_interceptor.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py index e575a610a9e..8dabd11fdf0 100644 --- a/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py +++ b/ext/opentelemetry-ext-grpc/tests/test_server_interceptor.py @@ -67,7 +67,8 @@ def handler(request, context): return b"" server = grpc.server( - futures.ThreadPoolExecutor(), options=(("grpc.so_reuseport", 0),) + futures.ThreadPoolExecutor(max_workers=1), + options=(("grpc.so_reuseport", 0),), ) # FIXME: grpcext interceptor doesn't apply to handlers passed to server # init, should use intercept_service API instead. @@ -103,7 +104,8 @@ def handler(request, context): return b"" server = grpc.server( - futures.ThreadPoolExecutor(), options=(("grpc.so_reuseport", 0),) + futures.ThreadPoolExecutor(max_workers=1), + options=(("grpc.so_reuseport", 0),), ) server = intercept_server(server, interceptor) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) @@ -140,7 +142,8 @@ def handler(request, context): return b"" server = grpc.server( - futures.ThreadPoolExecutor(), options=(("grpc.so_reuseport", 0),) + futures.ThreadPoolExecutor(max_workers=1), + options=(("grpc.so_reuseport", 0),), ) server = intercept_server(server, interceptor) server.add_generic_rpc_handlers((UnaryUnaryRpcHandler(handler),)) From a8d07cf1ebbfa7619301c643d219c68e4b55fbc7 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 17:28:07 -0700 Subject: [PATCH 58/59] Add missing test init --- ext/opentelemetry-ext-grpc/tests/__init__.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 ext/opentelemetry-ext-grpc/tests/__init__.py diff --git a/ext/opentelemetry-ext-grpc/tests/__init__.py b/ext/opentelemetry-ext-grpc/tests/__init__.py new file mode 100644 index 00000000000..b0a6f428417 --- /dev/null +++ b/ext/opentelemetry-ext-grpc/tests/__init__.py @@ -0,0 +1,13 @@ +# Copyright The OpenTelemetry 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. From 12db93b404e75e4e00469fe94bf315c68cac833d Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Mon, 30 Mar 2020 17:48:47 -0700 Subject: [PATCH 59/59] Remove pypy3-test-ext-grpc tox target --- tox.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 6b2f94b9913..06a54bc83d7 100644 --- a/tox.ini +++ b/tox.ini @@ -80,9 +80,8 @@ envlist = py3{4,5,6,7,8}-test-opentracing-shim pypy3-test-opentracing-shim - ; opentelemetry-opentracing-shim + ; opentelemetry-ext-grpc py3{4,5,6,7,8}-test-ext-grpc - pypy3-test-ext-grpc ; Coverage is temporarily disabled for pypy3 due to the pytest bug. ; pypy3-coverage