Recommendation Service

This service is responsible to get a list of recommended products for the user based on existing product IDs the user is browsing.

Recommendation service source

Auto-instrumentation

This Python based service, makes use of the OpenTelemetry auto-instrumentor for Python, accomplished by leveraging the opentelemetry-instrument Python wrapper to run the scripts. This can be done in the ENTRYPOINT command for the service’s Dockerfile.

ENTRYPOINT [ "opentelemetry-instrument", "python", "recommendation_server.py" ]

Traces

Initializing Tracing

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

tracer = trace.get_tracer_provider().get_tracer("recommendationservice")

Add attributes to auto-instrumented spans

Within the execution of auto-instrumented code you can get current span from context.

span = trace.get_current_span()

Adding attributes to a span is accomplished using set_attribute on the span object. In the ListRecommendations function an attribute is added to the span.

span.set_attribute("app.products_recommended.count", len(prod_list))

Create new spans

New spans can be created and placed into active context using start_as_current_span from an OpenTelemetry Tracer object. When used in conjunction with a with block, the span will automatically be ended when the block ends execution. This is done in the get_product_list function.

with tracer.start_as_current_span("get_product_list") as span:

Metrics

Initializing Metrics

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.

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:

  • runtime.cpython.cpu_time
  • runtime.cpython.memory
  • runtime.cpython.gc_count

Logs

Initializing logs

The OpenTelemetry SDK is initialized in the __main__ code block. The following code creates a logger provider with a batch processor, an OTLP log exporter, and a logging handler. Finally, it creates a logger for use throughout the application.

logger_provider = LoggerProvider(
    resource=Resource.create(
        {
            'service.name': service_name,
        }
    ),
)
set_logger_provider(logger_provider)
log_exporter = OTLPLogExporter(insecure=True)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
handler = LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider)

logger = logging.getLogger('main')
logger.addHandler(handler)

Create log records

Create logs using the logger. Examples can be found in ListRecommendations and get_product_list functions.

logger.info(f"Receive ListRecommendations for product ids:{prod_list}")

As you can see, after the initialization, log records can be created in the same way as in standard Python. OpenTelemetry libraries automatically add a trace ID and span ID for each log record and, in this way, enable correlating logs and traces.

Notes

Logs for Python are still experimental, and some changes can be expected. The implementation in this service follows the Python log example.

Last modified October 19, 2023: Support page-relative aliases (#3417) (7f46ec2d)