From 20e8cdddde276f110ea254b12f88aa4f27cc0d34 Mon Sep 17 00:00:00 2001 From: Xuan Wang Date: Fri, 19 Jan 2024 17:47:15 +0000 Subject: [PATCH] Remove example from this PR --- examples/python/observability/README.md | 55 ------------- .../python/observability/helloworld_pb2.py | 30 ------- .../python/observability/helloworld_pb2.pyi | 17 ---- .../observability/helloworld_pb2_grpc.py | 70 ---------------- .../observability_greeter_client.py | 71 ----------------- .../observability_greeter_server.py | 79 ------------------- .../observability/open_telemetry_exporter.py | 75 ------------------ 7 files changed, 397 deletions(-) delete mode 100644 examples/python/observability/README.md delete mode 100644 examples/python/observability/helloworld_pb2.py delete mode 100644 examples/python/observability/helloworld_pb2.pyi delete mode 100644 examples/python/observability/helloworld_pb2_grpc.py delete mode 100644 examples/python/observability/observability_greeter_client.py delete mode 100644 examples/python/observability/observability_greeter_server.py delete mode 100644 examples/python/observability/open_telemetry_exporter.py diff --git a/examples/python/observability/README.md b/examples/python/observability/README.md deleted file mode 100644 index 4e4a83197244d..0000000000000 --- a/examples/python/observability/README.md +++ /dev/null @@ -1,55 +0,0 @@ -gRPC Observability Example -===================== - -The examples here demonstrate how to setup gRPC Python Observability with Opentelemetry. - -More details about how to use gRPC Python Observability APIs can be found in [OpenTelemetry Metrics gRFC](https://github.com/grpc/proposal/blob/master/A66-otel-stats.md#opentelemetry-metrics). - -### Requirements - -The examples here depends on grpcio and grpcio-observability version of 1.62.0 or newer. - -### Run the Server - -1. Navigate to this directory: - -```sh -cd grpc/examples/python/observability -``` - -2. Run the server: - -```sh -python -m observability_greeter_server -``` - -### Run the Client - -Note that client should start within 10 seconds of the server becoming active. - -``` -python -m observability_greeter_client -``` - -### Verifying Metrics - -On server side, it should print a list of metric names collected: -``` -Server started, listening on 50051 -Metrics exported on Server side: -grpc.server.call.started -grpc.server.call.sent_total_compressed_message_size -grpc.server.call.rcvd_total_compressed_message_size -grpc.server.call.duration -``` - -On client side, it should print a list of metric names collected: -``` -Greeter client received: Hello You -Metrics exported on client side: -grpc.client.call.duration -grpc.client.attempt.started -grpc.client.attempt.sent_total_compressed_message_size -grpc.client.attempt.rcvd_total_compressed_message_size -grpc.client.attempt.duration -``` diff --git a/examples/python/observability/helloworld_pb2.py b/examples/python/observability/helloworld_pb2.py deleted file mode 100644 index f5b4f2d27dce7..0000000000000 --- a/examples/python/observability/helloworld_pb2.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: helloworld.proto -"""Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder -from google.protobuf import descriptor as _descriptor -from google.protobuf import descriptor_pool as _descriptor_pool -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(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') - -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals()) -if _descriptor._USE_C_DESCRIPTORS == False: - - DESCRIPTOR._options = None - DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW' - _HELLOREQUEST._serialized_start=32 - _HELLOREQUEST._serialized_end=60 - _HELLOREPLY._serialized_start=62 - _HELLOREPLY._serialized_end=91 - _GREETER._serialized_start=93 - _GREETER._serialized_end=166 -# @@protoc_insertion_point(module_scope) diff --git a/examples/python/observability/helloworld_pb2.pyi b/examples/python/observability/helloworld_pb2.pyi deleted file mode 100644 index 8c4b5b22805d9..0000000000000 --- a/examples/python/observability/helloworld_pb2.pyi +++ /dev/null @@ -1,17 +0,0 @@ -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from typing import ClassVar as _ClassVar, Optional as _Optional - -DESCRIPTOR: _descriptor.FileDescriptor - -class HelloReply(_message.Message): - __slots__ = ["message"] - MESSAGE_FIELD_NUMBER: _ClassVar[int] - message: str - def __init__(self, message: _Optional[str] = ...) -> None: ... - -class HelloRequest(_message.Message): - __slots__ = ["name"] - NAME_FIELD_NUMBER: _ClassVar[int] - name: str - def __init__(self, name: _Optional[str] = ...) -> None: ... diff --git a/examples/python/observability/helloworld_pb2_grpc.py b/examples/python/observability/helloworld_pb2_grpc.py deleted file mode 100644 index 47c186976e1c6..0000000000000 --- a/examples/python/observability/helloworld_pb2_grpc.py +++ /dev/null @@ -1,70 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -"""Client and server classes corresponding to protobuf-defined services.""" -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,)) - - - # This class is part of an EXPERIMENTAL API. -class Greeter(object): - """The greeting service definition. - """ - - @staticmethod - def SayHello(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello', - helloworld__pb2.HelloRequest.SerializeToString, - helloworld__pb2.HelloReply.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/examples/python/observability/observability_greeter_client.py b/examples/python/observability/observability_greeter_client.py deleted file mode 100644 index 25f7d68a4c8cf..0000000000000 --- a/examples/python/observability/observability_greeter_client.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2024 gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""gRPC Python helloworld.Greeter client with observability enabled.""" - -from collections import defaultdict -import logging -import time -from typing import Optional - -import grpc -import grpc_observability -import helloworld_pb2 -import helloworld_pb2_grpc -import open_telemetry_exporter -from opentelemetry.sdk.metrics import MeterProvider -from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader - -OTEL_EXPORT_INTERVAL_S = 0.5 - - -class BaseOpenTelemetryPlugin(grpc_observability.OpenTelemetryPlugin): - def __init__(self, provider: MeterProvider): - self.provider = provider - - def get_meter_provider(self) -> Optional[MeterProvider]: - return self.provider - - -def run(): - all_metrics = defaultdict(list) - otel_exporter = open_telemetry_exporter.OTelMetricExporter(all_metrics) - reader = PeriodicExportingMetricReader( - exporter=otel_exporter, - export_interval_millis=OTEL_EXPORT_INTERVAL_S * 1000, - ) - provider = MeterProvider(metric_readers=[reader]) - otel_plugin = BaseOpenTelemetryPlugin(provider) - - with grpc_observability.OpenTelemetryObservability(plugins=[otel_plugin]): - with grpc.insecure_channel(target="localhost:50051") as channel: - stub = helloworld_pb2_grpc.GreeterStub(channel) - try: - response = stub.SayHello( - helloworld_pb2.HelloRequest(name="You") - ) - print(f"Greeter client received: {response.message}") - except grpc.RpcError as rpc_error: - print("Call failed with code: ", rpc_error.code()) - - # Sleep to make sure all metrics are exported. - time.sleep(5) - - print("Metrics exported on client side:") - for metric in all_metrics: - print(metric) - - -if __name__ == "__main__": - logging.basicConfig() - run() diff --git a/examples/python/observability/observability_greeter_server.py b/examples/python/observability/observability_greeter_server.py deleted file mode 100644 index b57bca9e54eed..0000000000000 --- a/examples/python/observability/observability_greeter_server.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2024 gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""The Python implementation of the GRPC helloworld.Greeter server with observability enabled.""" - -from collections import defaultdict -from concurrent import futures -import logging -import time -from typing import Optional - -import grpc -import grpc_observability -import helloworld_pb2 -import helloworld_pb2_grpc -import open_telemetry_exporter -from opentelemetry.sdk.metrics import MeterProvider -from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader - -OTEL_EXPORT_INTERVAL_S = 0.5 - - -class BaseOpenTelemetryPlugin(grpc_observability.OpenTelemetryPlugin): - def __init__(self, provider: MeterProvider): - self.provider = provider - - def get_meter_provider(self) -> Optional[MeterProvider]: - return self.provider - - -class Greeter(helloworld_pb2_grpc.GreeterServicer): - def SayHello(self, request, context): - message = request.name - return helloworld_pb2.HelloReply(message=f"Hello {message}") - - -def serve(): - all_metrics = defaultdict(list) - otel_exporter = open_telemetry_exporter.OTelMetricExporter( - all_metrics, print_live=False - ) - reader = PeriodicExportingMetricReader( - exporter=otel_exporter, - export_interval_millis=OTEL_EXPORT_INTERVAL_S * 1000, - ) - provider = MeterProvider(metric_readers=[reader]) - otel_plugin = BaseOpenTelemetryPlugin(provider) - port = "50051" - - with grpc_observability.OpenTelemetryObservability(plugins=[otel_plugin]): - server = grpc.server( - thread_pool=futures.ThreadPoolExecutor(max_workers=10), - ) - helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) - server.add_insecure_port("[::]:" + port) - server.start() - print("Server started, listening on " + port) - - time.sleep(10) - print("Metrics exported on Server side:") - for metric in all_metrics: - print(metric) - - server.stop(0) - - -if __name__ == "__main__": - logging.basicConfig() - serve() diff --git a/examples/python/observability/open_telemetry_exporter.py b/examples/python/observability/open_telemetry_exporter.py deleted file mode 100644 index af70bdb05a9d3..0000000000000 --- a/examples/python/observability/open_telemetry_exporter.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2024 gRPC authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import Dict, List - -from opentelemetry.sdk.metrics.export import AggregationTemporality -from opentelemetry.sdk.metrics.export import MetricExportResult -from opentelemetry.sdk.metrics.export import MetricExporter -from opentelemetry.sdk.metrics.export import MetricsData - - -class OTelMetricExporter(MetricExporter): - """Implementation of :class:`MetricExporter` that export metrics to the - provided metric_list. - - all_metrics: A dict which key is grpc_observability._opentelemetry_measures.Metric.name, - value is a list of labels recorded for that metric. - An example item of this dict: - {"grpc.client.attempt.started": - [{'grpc.method': 'test/UnaryUnary', 'grpc.target': 'localhost:42517'}, - {'grpc.method': 'other', 'grpc.target': 'localhost:42517'}]} - """ - - def __init__( - self, - all_metrics: Dict[str, List], - preferred_temporality: Dict[type, AggregationTemporality] = None, - preferred_aggregation: Dict[ - type, "opentelemetry.sdk.metrics.view.Aggregation" - ] = None, - print_live: bool = False, - ): - super().__init__( - preferred_temporality=preferred_temporality, - preferred_aggregation=preferred_aggregation, - ) - self._all_metrics = all_metrics - self._print_live = print_live - - def export( - self, - metrics_data: MetricsData, - timeout_millis: float = 10_000, - **kwargs, - ) -> MetricExportResult: - self.record_metric(metrics_data) - return MetricExportResult.SUCCESS - - def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None: - pass - - def force_flush(self, timeout_millis: float = 10_000) -> bool: - return True - - def record_metric(self, metrics_data: MetricsData) -> None: - for resource_metric in metrics_data.resource_metrics: - for scope_metric in resource_metric.scope_metrics: - for metric in scope_metric.metrics: - for data_point in metric.data.data_points: - self._all_metrics[metric.name].append( - data_point.attributes - ) - if self._print_live: - print(f"Metric exporter received: {metric.name}")