diff --git a/CHANGELOG.md b/CHANGELOG.md index 44ecb6bb4a..9a15bd76b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,3 +111,5 @@ significant modifications will be credited to OpenTelemetry Authors. ([#409](https://github.com/open-telemetry/opentelemetry-demo/pull/409)) * Added hero scenario metric to Checkout Service on cache leak ([#339](https://github.com/open-telemetry/opentelemetry-demo/pull/339)) +* Added basic metrics support for recommendation service (Python) +([#416](https://github.com/open-telemetry/opentelemetry-demo/pull/416)) diff --git a/docker-compose.yml b/docker-compose.yml index 3f233f2256..141cf1883e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -329,6 +329,9 @@ services: - PRODUCT_CATALOG_SERVICE_ADDR - OTEL_PYTHON_LOG_CORRELATION=true - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT + # OTEL_EXPORTER_OTLP_METRICS_ENDPOINT # Not working for Python OTLP exporter + - OTEL_EXPORTER_OTLP_ENDPOINT + - OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE - OTEL_SERVICE_NAME=recommendationservice - PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python logging: *logging diff --git a/docs/metric_service_features.md b/docs/metric_service_features.md index c5666fb506..a2ea79b8db 100644 --- a/docs/metric_service_features.md +++ b/docs/metric_service_features.md @@ -17,5 +17,5 @@ Emoji Legend | Frontend | JavaScript | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | | Payment | JavaScript | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | | Product Catalog | Go | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | -| Recommendation | Python | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | +| Recommendation | Python | :construction: | :100: | :construction: | :construction: | :construction: | :construction: | | Shipping | Rust | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | diff --git a/src/recommendationservice/recommendation_server.py b/src/recommendationservice/recommendation_server.py index 6b8473be2e..ad17b30a88 100644 --- a/src/recommendationservice/recommendation_server.py +++ b/src/recommendationservice/recommendation_server.py @@ -22,11 +22,19 @@ # Pip import grpc + +# Traces from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import (BatchSpanProcessor) from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter +# Metrics +from opentelemetry import metrics +from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.metrics.export import (PeriodicExportingMetricReader) +from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter + # Local import demo_pb2 import demo_pb2_grpc @@ -41,6 +49,8 @@ def ListRecommendations(self, request, context): span = trace.get_current_span() span.set_attribute("app.products_recommended.count", len(prod_list)) logger.info("[Recv ListRecommendations] product_ids={}".format(prod_list)) + app_recommendations_counter.add(len(prod_list), {'recommendation.type': 'catalog'}) + # build and return response response = demo_pb2.ListRecommendationsResponse() response.product_ids.extend(prod_list) @@ -88,28 +98,42 @@ def must_map_env(key: str): return value if __name__ == "__main__": - logger = getJSONLogger('recommendationservice-server') + # Initialize tracer provider tracer_provider = TracerProvider() trace.set_tracer_provider(tracer_provider) tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) tracer = trace.get_tracer("recommendationservice") + # Initialize meter provider + metric_reader = PeriodicExportingMetricReader(OTLPMetricExporter()) + provider = MeterProvider(metric_readers=[metric_reader]) + metrics.set_meter_provider(provider) + meter = metrics.get_meter(__name__) + + # Create counters + app_recommendations_counter = meter.create_counter( + 'app.recommendations.counter', unit='recommendations', description="Counts the total number of given recommendations" + ) + port = must_map_env('RECOMMENDATION_SERVICE_PORT') catalog_addr = must_map_env('PRODUCT_CATALOG_SERVICE_ADDR') channel = grpc.insecure_channel(catalog_addr) product_catalog_stub = demo_pb2_grpc.ProductCatalogServiceStub(channel) - # create gRPC server + # Create gRPC server server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - # add class to gRPC server + # Add class to gRPC server service = RecommendationService() demo_pb2_grpc.add_RecommendationServiceServicer_to_server(service, server) health_pb2_grpc.add_HealthServicer_to_server(service, server) - # start server + # Start logger + logger = getJSONLogger('recommendationservice-server') logger.info("RecommendationService listening on port: " + port) + + # Start server server.add_insecure_port('[::]:' + port) server.start() server.wait_for_termination() diff --git a/src/recommendationservice/requirements.txt b/src/recommendationservice/requirements.txt index 0bd544764d..1065829c37 100644 --- a/src/recommendationservice/requirements.txt +++ b/src/recommendationservice/requirements.txt @@ -1,12 +1,12 @@ google-api-core==2.4.0 grpcio-health-checking==1.43.0 grpcio==1.43.0 -opentelemetry-api==1.9.1 -opentelemetry-exporter-otlp-proto-grpc==1.9.1 -opentelemetry-instrumentation==0.28b1 -opentelemetry-instrumentation-grpc==0.28b1 -opentelemetry-instrumentation-urllib3==0.28b1 -opentelemetry-sdk==1.9.1 +opentelemetry-api==1.13.0 +opentelemetry-exporter-otlp-proto-grpc==1.13.0 +opentelemetry-instrumentation==0.34b0 +opentelemetry-instrumentation-grpc==0.34b0 +opentelemetry-instrumentation-urllib3==0.34b0 +opentelemetry-sdk==1.13.0 python-dotenv==0.20.0 python-json-logger==2.0.2 requests==2.27.1