|
21 | 21 | import io |
22 | 22 | import json |
23 | 23 | import logging |
| 24 | +from timeit import default_timer |
24 | 25 | from typing import Any |
25 | 26 |
|
26 | 27 | from botocore.eventstream import EventStream |
@@ -326,14 +327,15 @@ def before_service_call( |
326 | 327 | for event in message_to_event(message, capture_content): |
327 | 328 | event_logger.emit(event) |
328 | 329 |
|
329 | | - if not span.is_recording(): |
330 | | - return |
| 330 | + if span.is_recording(): |
| 331 | + operation_name = span.attributes.get(GEN_AI_OPERATION_NAME, "") |
| 332 | + request_model = span.attributes.get(GEN_AI_REQUEST_MODEL, "") |
| 333 | + # avoid setting to an empty string if are not available |
| 334 | + if operation_name and request_model: |
| 335 | + span.update_name(f"{operation_name} {request_model}") |
331 | 336 |
|
332 | | - operation_name = span.attributes.get(GEN_AI_OPERATION_NAME, "") |
333 | | - request_model = span.attributes.get(GEN_AI_REQUEST_MODEL, "") |
334 | | - # avoid setting to an empty string if are not available |
335 | | - if operation_name and request_model: |
336 | | - span.update_name(f"{operation_name} {request_model}") |
| 337 | + # this is used to calculate the operation duration metric, duration may be skewed by request_hook |
| 338 | + self._operation_start = default_timer() |
337 | 339 |
|
338 | 340 | # pylint: disable=no-self-use |
339 | 341 | def _converse_on_success( |
@@ -376,9 +378,18 @@ def _converse_on_success( |
376 | 378 | ) |
377 | 379 |
|
378 | 380 | metrics = instrumentor_context.metrics |
| 381 | + metrics_attributes = self._extract_metrics_attributes() |
| 382 | + if operation_duration_histogram := metrics.get( |
| 383 | + GEN_AI_CLIENT_OPERATION_DURATION |
| 384 | + ): |
| 385 | + duration = max((default_timer() - self._operation_start), 0) |
| 386 | + operation_duration_histogram.record( |
| 387 | + duration, |
| 388 | + attributes=metrics_attributes, |
| 389 | + ) |
| 390 | + |
379 | 391 | if token_usage_histogram := metrics.get(GEN_AI_CLIENT_TOKEN_USAGE): |
380 | 392 | if usage := result.get("usage"): |
381 | | - metrics_attributes = self._extract_metrics_attributes() |
382 | 393 | if input_tokens := usage.get("inputTokens"): |
383 | 394 | input_attributes = { |
384 | 395 | **metrics_attributes, |
@@ -543,8 +554,17 @@ def _handle_amazon_titan_response( |
543 | 554 | event_logger.emit(choice.to_choice_event()) |
544 | 555 |
|
545 | 556 | metrics = instrumentor_context.metrics |
| 557 | + metrics_attributes = self._extract_metrics_attributes() |
| 558 | + if operation_duration_histogram := metrics.get( |
| 559 | + GEN_AI_CLIENT_OPERATION_DURATION |
| 560 | + ): |
| 561 | + duration = max((default_timer() - self._operation_start), 0) |
| 562 | + operation_duration_histogram.record( |
| 563 | + duration, |
| 564 | + attributes=metrics_attributes, |
| 565 | + ) |
| 566 | + |
546 | 567 | if token_usage_histogram := metrics.get(GEN_AI_CLIENT_TOKEN_USAGE): |
547 | | - metrics_attributes = self._extract_metrics_attributes() |
548 | 568 | if input_tokens := response_body.get("inputTextTokenCount"): |
549 | 569 | input_attributes = { |
550 | 570 | **metrics_attributes, |
@@ -592,9 +612,18 @@ def _handle_amazon_nova_response( |
592 | 612 | event_logger.emit(choice.to_choice_event()) |
593 | 613 |
|
594 | 614 | metrics = instrumentor_context.metrics |
| 615 | + metrics_attributes = self._extract_metrics_attributes() |
| 616 | + if operation_duration_histogram := metrics.get( |
| 617 | + GEN_AI_CLIENT_OPERATION_DURATION |
| 618 | + ): |
| 619 | + duration = max((default_timer() - self._operation_start), 0) |
| 620 | + operation_duration_histogram.record( |
| 621 | + duration, |
| 622 | + attributes=metrics_attributes, |
| 623 | + ) |
| 624 | + |
595 | 625 | if token_usage_histogram := metrics.get(GEN_AI_CLIENT_TOKEN_USAGE): |
596 | 626 | if usage := response_body.get("usage"): |
597 | | - metrics_attributes = self._extract_metrics_attributes() |
598 | 627 | if input_tokens := usage.get("inputTokens"): |
599 | 628 | input_attributes = { |
600 | 629 | **metrics_attributes, |
@@ -642,9 +671,18 @@ def _handle_anthropic_claude_response( |
642 | 671 | event_logger.emit(choice.to_choice_event()) |
643 | 672 |
|
644 | 673 | metrics = instrumentor_context.metrics |
| 674 | + metrics_attributes = self._extract_metrics_attributes() |
| 675 | + if operation_duration_histogram := metrics.get( |
| 676 | + GEN_AI_CLIENT_OPERATION_DURATION |
| 677 | + ): |
| 678 | + duration = max((default_timer() - self._operation_start), 0) |
| 679 | + operation_duration_histogram.record( |
| 680 | + duration, |
| 681 | + attributes=metrics_attributes, |
| 682 | + ) |
| 683 | + |
645 | 684 | if token_usage_histogram := metrics.get(GEN_AI_CLIENT_TOKEN_USAGE): |
646 | 685 | if usage := response_body.get("usage"): |
647 | | - metrics_attributes = self._extract_metrics_attributes() |
648 | 686 | if input_tokens := usage.get("input_tokens"): |
649 | 687 | input_attributes = { |
650 | 688 | **metrics_attributes, |
|
0 commit comments