Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate with existing metrics code #432

Merged
merged 22 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,6 @@ significant modifications will be credited to OpenTelemetry Authors.
([#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))
* Added metrics auto-instrumentation + minor metrics refactor for recommendation
service (Python)
[#432](https://github.com/open-telemetry/opentelemetry-demo/pull/432)
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,7 @@ services:
- RECOMMENDATION_SERVICE_PORT
- 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_METRICS_EXPORTER=otlp
- OTEL_EXPORTER_OTLP_ENDPOINT
- OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
avillela marked this conversation as resolved.
Show resolved Hide resolved
avillela marked this conversation as resolved.
Show resolved Hide resolved
- OTEL_SERVICE_NAME=recommendationservice
Expand Down
4 changes: 3 additions & 1 deletion src/recommendationservice/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ COPY ./pb/ ./proto/
RUN pip install --upgrade pip
RUN pip install -r ./requirements.txt

RUN opentelemetry-bootstrap -a install

# add files into working directory
RUN python -m pip install grpcio-tools
RUN python -m pip install grpcio-tools==1.48.2
RUN python -m grpc_tools.protoc -I=./proto/ --python_out=./ --grpc_python_out=./ ./proto/demo.proto

EXPOSE ${RECOMMENDATION_SERVICE_PORT}
Expand Down
30 changes: 30 additions & 0 deletions src/recommendationservice/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/python

# from gc import callbacks
# from typing import Iterable
# import psutil


def init_metrics(meter):

# Requests counter
list_recommendations_request_counter = meter.create_counter(
avillela marked this conversation as resolved.
Show resolved Hide resolved
name="app_recommendations_request_counter",
avillela marked this conversation as resolved.
Show resolved Hide resolved
description="number of requests to RecommendationService.ListRecommendations",
unit="requests"
)

# Recommendations counter
app_recommendations_counter = meter.create_counter(
'app_recommendations_counter', unit='recommendations', description="Counts the total number of given recommendations"
)

attributes = {"application.name": "otel-demo"}

rec_svc_metrics = {
"list_recommendations_request_counter": list_recommendations_request_counter,
"attributes": attributes,
"app_recommendations_counter": app_recommendations_counter,
}

return rec_svc_metrics
52 changes: 19 additions & 33 deletions src/recommendationservice/recommendation_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,12 @@
# Python
import os
import random
import time
from concurrent import futures

# Pip
import grpc
from opentelemetry import trace, metrics

# 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
Expand All @@ -42,18 +31,24 @@
from grpc_health.v1 import health_pb2_grpc
from logger import getJSONLogger

from metrics import (
init_metrics
)

class RecommendationService(demo_pb2_grpc.RecommendationServiceServicer):
def ListRecommendations(self, request, context):
prod_list = get_product_list(request.product_ids)
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'})

logger.info(f"[Recv ListRecommendations] product_ids={prod_list}")
# build and return response
response = demo_pb2.ListRecommendationsResponse()
response.product_ids.extend(prod_list)

# Collect metrics on # requests to this service
rec_svc_metrics["list_recommendations_request_counter"].add(1, rec_svc_metrics["attributes"])
rec_svc_metrics["app_recommendations_counter"].add(len(prod_list), {'recommendation.type': 'catalog'})

return response

def Check(self, request, context):
Expand Down Expand Up @@ -88,6 +83,9 @@ def get_product_list(request_product_ids):
indices = random.sample(range(num_products), num_return)
# Fetch product ids from indices
prod_list = [filtered_products[i] for i in indices]

span.set_attribute("app.filtered_products.list", prod_list)
fatsheep9146 marked this conversation as resolved.
Show resolved Hide resolved

return prod_list


Expand All @@ -98,22 +96,10 @@ def must_map_env(key: str):
return value

if __name__ == "__main__":
# 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"
)
# Initialize Traces and Metrics
tracer = trace.get_tracer_provider().get_tracer("recommendationservice")
meter = metrics.get_meter_provider().get_meter("recommendationservice")
rec_svc_metrics = init_metrics(meter)

port = must_map_env('RECOMMENDATION_SERVICE_PORT')
catalog_addr = must_map_env('PRODUCT_CATALOG_SERVICE_ADDR')
Expand All @@ -131,9 +117,9 @@ def must_map_env(key: str):

# Start logger
logger = getJSONLogger('recommendationservice-server')
logger.info("RecommendationService listening on port: " + port)
logger.info(f"RecommendationService listening on port: {port}")

# Start server
server.add_insecure_port('[::]:' + port)
server.add_insecure_port(f'[::]:{port}')
server.start()
server.wait_for_termination()
13 changes: 4 additions & 9 deletions src/recommendationservice/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
google-api-core==2.4.0
grpcio-health-checking==1.43.0
grpcio==1.43.0
opentelemetry-api==1.13.0
opentelemetry-distro==0.34b0
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
urllib3==1.26.8
python-dotenv==0.21.0
python-json-logger==2.0.4
psutil==5.9.2 # Importing this will also import opentelemetry-instrumentation-system-metrics when running opentelemetry-bootstrap