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 all 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,5 +113,8 @@ significant modifications will be credited to OpenTelemetry Authors.
([#339](https:/open-telemetry/opentelemetry-demo/pull/339))
* Added basic metrics support for recommendation service (Python)
([#416](https:/open-telemetry/opentelemetry-demo/pull/416))
* Added metrics auto-instrumentation + minor metrics refactor for recommendation
service (Python)
[#432](https:/open-telemetry/opentelemetry-demo/pull/432)
* Replaced the Jaeger exporter to the OTLP exporter in the OTel Collector
([#435](https:/open-telemetry/opentelemetry-demo/pull/435))
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ 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_TRACES_EXPORTER=otlp
- 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
2 changes: 1 addition & 1 deletion docs/metric_service_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: | :100: | :construction: | :construction: | :construction: | :construction: |
| Recommendation | Python | :100: | :100: | :construction: | :construction: | :construction: | :construction: |
| Shipping | Rust | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
33 changes: 28 additions & 5 deletions docs/services/recommendationservice.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ endpoints, resource attributes, and service name are automatically set by the
OpenTelemetry auto instrumentor based on environment variables.

```python
tracer_provider = TracerProvider()
trace.set_tracer_provider(tracer_provider)
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
tracer = trace.get_tracer("recommendationservice")
tracer = trace.get_tracer_provider().get_tracer("recommendationservice")
```

### Add attributes to auto-instrumented spans
Expand Down Expand Up @@ -61,7 +58,33 @@ block ends execution. This is done in the `get_product_list` function.

## Metrics

TBD
### Initialize meter provider

The OpenTelemetry SDK is initialized in the `__main__` code block. This code
will create a meter provider. Export
endpoints, resource attributes, and service name are automatically set by the
OpenTelemetry auto instrumentor based on environment variables.

```python
meter = metrics.get_meter_provider().get_meter("recommendationservice")
```

### Custom metrics

The following custom metrics are currently available:

* `app_recommendations_counter`: Cumulative count of # recommended
products per service call

### Auto-instrumented metrics

The following metrics are available through auto-instrumentation, courtesy of
the `opentelemetry-instrumentation-system-metrics`, which is installed as part
of `opentelemetry-bootstrap` on building the recommendationservice Docker image:

avillela marked this conversation as resolved.
Show resolved Hide resolved
avillela marked this conversation as resolved.
Show resolved Hide resolved
* `runtime.cpython.cpu_time`
* `runtime.cpython.memory`
* `runtime.cpython.gc_count`

## Logs

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
14 changes: 14 additions & 0 deletions src/recommendationservice/metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/python

def init_metrics(meter):

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

rec_svc_metrics = {
"app_recommendations_counter": app_recommendations_counter,
}

return rec_svc_metrics
51 changes: 18 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,23 @@
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 for this service
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 +82,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 +95,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 +116,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