Skip to content

Commit c1c859d

Browse files
committed
Add server address and port to Bedrock metric attributes
1 parent f7ecf32 commit c1c859d

File tree

4 files changed

+44
-17
lines changed

4 files changed

+44
-17
lines changed

instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py

+2-13
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ def response_hook(span, service_name, operation_name, result):
8282

8383
import logging
8484
from typing import Any, Callable, Collection, Dict, Optional, Tuple
85-
from urllib.parse import urlparse
8685

8786
from botocore.client import BaseClient
8887
from botocore.endpoint import Endpoint
@@ -100,6 +99,7 @@ def response_hook(span, service_name, operation_name, result):
10099
_BotocoreInstrumentorContext,
101100
)
102101
from opentelemetry.instrumentation.botocore.package import _instruments
102+
from opentelemetry.instrumentation.botocore.utils import get_server_attributes
103103
from opentelemetry.instrumentation.botocore.version import __version__
104104
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
105105
from opentelemetry.instrumentation.utils import (
@@ -112,7 +112,6 @@ def response_hook(span, service_name, operation_name, result):
112112
from opentelemetry.semconv.trace import SpanAttributes
113113
from opentelemetry.trace import get_tracer
114114
from opentelemetry.trace.span import Span
115-
from opentelemetry.util.types import AttributeValue
116115

117116
logger = logging.getLogger(__name__)
118117

@@ -279,7 +278,7 @@ def _patched_api_call(self, original_func, instance, args, kwargs):
279278
SpanAttributes.RPC_METHOD: call_context.operation,
280279
# TODO: update when semantic conventions exist
281280
"aws.region": call_context.region,
282-
**_get_server_attributes(call_context.endpoint_url),
281+
**get_server_attributes(call_context.endpoint_url),
283282
}
284283

285284
_safe_invoke(extension.extract_attributes, attributes)
@@ -406,13 +405,3 @@ def _safe_invoke(function: Callable, *args):
406405
logger.error(
407406
"Error when invoking function '%s'", function_name, exc_info=ex
408407
)
409-
410-
411-
def _get_server_attributes(endpoint_url: str) -> Dict[str, AttributeValue]:
412-
"""Extract server.* attributes from AWS endpoint URL."""
413-
parsed = urlparse(endpoint_url)
414-
attributes = {}
415-
if parsed.hostname:
416-
attributes[SpanAttributes.SERVER_ADDRESS] = parsed.hostname
417-
attributes[SpanAttributes.SERVER_PORT] = parsed.port or 443
418-
return attributes

instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/bedrock.py

+6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
_BotoClientErrorT,
4242
_BotocoreInstrumentorContext,
4343
)
44+
from opentelemetry.instrumentation.botocore.utils import get_server_attributes
4445
from opentelemetry.metrics import Instrument, Meter
4546
from opentelemetry.semconv._incubating.attributes.error_attributes import (
4647
ERROR_TYPE,
@@ -163,6 +164,11 @@ def _extract_metrics_attributes(self) -> _AttributeMapT:
163164
attributes[GEN_AI_OPERATION_NAME] = (
164165
GenAiOperationNameValues.CHAT.value
165166
)
167+
168+
server_attributes = get_server_attributes(
169+
self._call_context.endpoint_url
170+
)
171+
attributes.update(server_attributes)
166172
return attributes
167173

168174
def extract_attributes(self, attributes: _AttributeMapT):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from typing import Dict
2+
from urllib.parse import urlparse
3+
4+
from opentelemetry.semconv._incubating.attributes import (
5+
server_attributes as ServerAttributes,
6+
)
7+
from opentelemetry.util.types import AttributeValue
8+
9+
10+
def get_server_attributes(endpoint_url: str) -> Dict[str, AttributeValue]:
11+
"""Extract server.* attributes from AWS endpoint URL."""
12+
parsed = urlparse(endpoint_url)
13+
attributes = {}
14+
if parsed.hostname:
15+
attributes[ServerAttributes.SERVER_ADDRESS] = parsed.hostname
16+
attributes[ServerAttributes.SERVER_PORT] = parsed.port or 443
17+
return attributes

instrumentation/opentelemetry-instrumentation-botocore/tests/bedrock_utils.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@
3232
from opentelemetry.semconv._incubating.attributes import (
3333
gen_ai_attributes as GenAIAttributes,
3434
)
35+
from opentelemetry.semconv._incubating.attributes import (
36+
server_attributes as ServerAttributes,
37+
)
3538
from opentelemetry.semconv._incubating.attributes.error_attributes import (
3639
ERROR_TYPE,
3740
)
3841
from opentelemetry.semconv._incubating.metrics.gen_ai_metrics import (
3942
GEN_AI_CLIENT_OPERATION_DURATION,
4043
GEN_AI_CLIENT_TOKEN_USAGE,
4144
)
42-
from opentelemetry.semconv.trace import SpanAttributes
4345

4446

4547
# pylint: disable=too-many-branches, too-many-locals, too-many-statements
@@ -238,8 +240,8 @@ def assert_all_attributes(
238240
request_model == span.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL]
239241
)
240242

241-
assert server_address == span.attributes[SpanAttributes.SERVER_ADDRESS]
242-
assert server_port == span.attributes[SpanAttributes.SERVER_PORT]
243+
assert server_address == span.attributes[ServerAttributes.SERVER_ADDRESS]
244+
assert server_port == span.attributes[ServerAttributes.SERVER_PORT]
243245

244246
assert_equal_or_not_present(
245247
input_tokens, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, span
@@ -309,7 +311,12 @@ def assert_message_in_logs(log, event_name, expected_content, parent_span):
309311

310312

311313
def assert_all_metric_attributes(
312-
data_point, operation_name: str, model: str, error_type: str | None = None
314+
data_point,
315+
operation_name: str,
316+
model: str,
317+
error_type: str | None = None,
318+
server_address: str = "bedrock-runtime.us-east-1.amazonaws.com",
319+
server_port: int = 443,
313320
):
314321
assert GenAIAttributes.GEN_AI_OPERATION_NAME in data_point.attributes
315322
assert (
@@ -324,6 +331,14 @@ def assert_all_metric_attributes(
324331
assert GenAIAttributes.GEN_AI_REQUEST_MODEL in data_point.attributes
325332
assert data_point.attributes[GenAIAttributes.GEN_AI_REQUEST_MODEL] == model
326333

334+
assert ServerAttributes.SERVER_ADDRESS in data_point.attributes
335+
assert (
336+
data_point.attributes[ServerAttributes.SERVER_ADDRESS]
337+
== server_address
338+
)
339+
assert ServerAttributes.SERVER_PORT in data_point.attributes
340+
assert data_point.attributes[ServerAttributes.SERVER_PORT] == server_port
341+
327342
if error_type is not None:
328343
assert ERROR_TYPE in data_point.attributes
329344
assert data_point.attributes[ERROR_TYPE] == error_type

0 commit comments

Comments
 (0)