mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 20:52:57 +08:00
Add server attributes to Vertex AI spans (#3208)
This commit is contained in:
@ -11,3 +11,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
([#3192](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3192))
|
([#3192](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3192))
|
||||||
- Initial VertexAI instrumentation
|
- Initial VertexAI instrumentation
|
||||||
([#3123](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3123))
|
([#3123](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3123))
|
||||||
|
- Add server attributes to Vertex AI spans
|
||||||
|
([#3208](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3208))
|
||||||
|
@ -25,6 +25,7 @@ from opentelemetry._events import EventLogger
|
|||||||
from opentelemetry.instrumentation.vertexai.utils import (
|
from opentelemetry.instrumentation.vertexai.utils import (
|
||||||
GenerateContentParams,
|
GenerateContentParams,
|
||||||
get_genai_request_attributes,
|
get_genai_request_attributes,
|
||||||
|
get_server_attributes,
|
||||||
get_span_name,
|
get_span_name,
|
||||||
)
|
)
|
||||||
from opentelemetry.trace import SpanKind, Tracer
|
from opentelemetry.trace import SpanKind, Tracer
|
||||||
@ -100,7 +101,11 @@ def generate_content_create(
|
|||||||
kwargs: Any,
|
kwargs: Any,
|
||||||
):
|
):
|
||||||
params = _extract_params(*args, **kwargs)
|
params = _extract_params(*args, **kwargs)
|
||||||
span_attributes = get_genai_request_attributes(params)
|
api_endpoint: str = instance.api_endpoint # type: ignore[reportUnknownMemberType]
|
||||||
|
span_attributes = {
|
||||||
|
**get_genai_request_attributes(params),
|
||||||
|
**get_server_attributes(api_endpoint),
|
||||||
|
}
|
||||||
|
|
||||||
span_name = get_span_name(span_attributes)
|
span_name = get_span_name(span_attributes)
|
||||||
with tracer.start_as_current_span(
|
with tracer.start_as_current_span(
|
||||||
|
@ -22,10 +22,12 @@ from typing import (
|
|||||||
Mapping,
|
Mapping,
|
||||||
Sequence,
|
Sequence,
|
||||||
)
|
)
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from opentelemetry.semconv._incubating.attributes import (
|
from opentelemetry.semconv._incubating.attributes import (
|
||||||
gen_ai_attributes as GenAIAttributes,
|
gen_ai_attributes as GenAIAttributes,
|
||||||
)
|
)
|
||||||
|
from opentelemetry.semconv.attributes import server_attributes
|
||||||
from opentelemetry.util.types import AttributeValue
|
from opentelemetry.util.types import AttributeValue
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -58,6 +60,24 @@ class GenerateContentParams:
|
|||||||
) = None
|
) = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_server_attributes(
|
||||||
|
endpoint: str,
|
||||||
|
) -> dict[str, AttributeValue]:
|
||||||
|
"""Get server.* attributes from the endpoint, which is a hostname with optional port e.g.
|
||||||
|
- ``us-central1-aiplatform.googleapis.com``
|
||||||
|
- ``us-central1-aiplatform.googleapis.com:5431``
|
||||||
|
"""
|
||||||
|
parsed = urlparse(f"scheme://{endpoint}")
|
||||||
|
|
||||||
|
if not parsed.hostname:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
server_attributes.SERVER_ADDRESS: parsed.hostname,
|
||||||
|
server_attributes.SERVER_PORT: parsed.port or 443,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_genai_request_attributes(
|
def get_genai_request_attributes(
|
||||||
params: GenerateContentParams,
|
params: GenerateContentParams,
|
||||||
operation_name: GenAIAttributes.GenAiOperationNameValues = GenAIAttributes.GenAiOperationNameValues.CHAT,
|
operation_name: GenAIAttributes.GenAiOperationNameValues = GenAIAttributes.GenAiOperationNameValues.CHAT,
|
||||||
|
@ -34,6 +34,8 @@ def test_generate_content(
|
|||||||
"gen_ai.operation.name": "chat",
|
"gen_ai.operation.name": "chat",
|
||||||
"gen_ai.request.model": "gemini-1.5-flash-002",
|
"gen_ai.request.model": "gemini-1.5-flash-002",
|
||||||
"gen_ai.system": "vertex_ai",
|
"gen_ai.system": "vertex_ai",
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 443,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -62,6 +64,8 @@ def test_generate_content_empty_model(
|
|||||||
"gen_ai.operation.name": "chat",
|
"gen_ai.operation.name": "chat",
|
||||||
"gen_ai.request.model": "",
|
"gen_ai.request.model": "",
|
||||||
"gen_ai.system": "vertex_ai",
|
"gen_ai.system": "vertex_ai",
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 443,
|
||||||
}
|
}
|
||||||
assert_span_error(spans[0])
|
assert_span_error(spans[0])
|
||||||
|
|
||||||
@ -91,6 +95,8 @@ def test_generate_content_missing_model(
|
|||||||
"gen_ai.operation.name": "chat",
|
"gen_ai.operation.name": "chat",
|
||||||
"gen_ai.request.model": "gemini-does-not-exist",
|
"gen_ai.request.model": "gemini-does-not-exist",
|
||||||
"gen_ai.system": "vertex_ai",
|
"gen_ai.system": "vertex_ai",
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 443,
|
||||||
}
|
}
|
||||||
assert_span_error(spans[0])
|
assert_span_error(spans[0])
|
||||||
|
|
||||||
@ -122,6 +128,8 @@ def test_generate_content_invalid_temperature(
|
|||||||
"gen_ai.request.model": "gemini-1.5-flash-002",
|
"gen_ai.request.model": "gemini-1.5-flash-002",
|
||||||
"gen_ai.request.temperature": 1000.0,
|
"gen_ai.request.temperature": 1000.0,
|
||||||
"gen_ai.system": "vertex_ai",
|
"gen_ai.system": "vertex_ai",
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 443,
|
||||||
}
|
}
|
||||||
assert_span_error(spans[0])
|
assert_span_error(spans[0])
|
||||||
|
|
||||||
@ -158,6 +166,8 @@ def test_generate_content_extra_params(span_exporter, instrument_no_content):
|
|||||||
"gen_ai.request.temperature": 0.20000000298023224,
|
"gen_ai.request.temperature": 0.20000000298023224,
|
||||||
"gen_ai.request.top_p": 0.949999988079071,
|
"gen_ai.request.top_p": 0.949999988079071,
|
||||||
"gen_ai.system": "vertex_ai",
|
"gen_ai.system": "vertex_ai",
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 443,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright The OpenTelemetry Authors
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
from opentelemetry.instrumentation.vertexai.utils import get_server_attributes
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_server_attributes() -> None:
|
||||||
|
# without port
|
||||||
|
assert get_server_attributes("us-central1-aiplatform.googleapis.com") == {
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 443,
|
||||||
|
}
|
||||||
|
|
||||||
|
# with port
|
||||||
|
assert get_server_attributes(
|
||||||
|
"us-central1-aiplatform.googleapis.com:5432"
|
||||||
|
) == {
|
||||||
|
"server.address": "us-central1-aiplatform.googleapis.com",
|
||||||
|
"server.port": 5432,
|
||||||
|
}
|
Reference in New Issue
Block a user