Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def _convert_any_value_to_string(value: Any) -> str:

# Be careful not to mutate original body. Make copies of anything that needs to change.
def _sanitized_body(
body: Mapping[str, AnyValue]
body: Mapping[str, AnyValue],
) -> MutableMapping[str, AnyValue]:
new_body: MutableMapping[str, AnyValue] = {}
for key, value in body.items():
Expand Down Expand Up @@ -212,6 +212,45 @@ def is_log_id_valid(log_id: str) -> bool:
)


def _get_monitored_resource(
resource: Optional[Resource],
) -> MonitoredResource | None:
if not resource:
return None

# TODO: Remove temporary special case for Vertex Agent Engine
# https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/issues/444
cloud_resource_id = resource.attributes.get("cloud.resource_id")
if isinstance(cloud_resource_id, str) and (
match := re.match(
r"//aiplatform\.googleapis\.com/projects/(?P<project_id>[^/]+)"
r"/locations/(?P<location>[^/]+)"
r"/reasoningEngines/(?P<agent_engine_id>[^/]+)",
cloud_resource_id,
)
):
location = match.group("location")
agent_engine_id = match.group("agent_engine_id")
# https://cloud.google.com/monitoring/api/resources#tag_aiplatform.googleapis.com/ReasoningEngine
return MonitoredResource(
type="aiplatform.googleapis.com/ReasoningEngine",
labels={
# Intentionally omit the project ID
"location": location,
"reasoning_engine_id": agent_engine_id,
},
)

monitored_resource_data = get_monitored_resource(resource)
if not monitored_resource_data:
return None

return MonitoredResource(
type=monitored_resource_data.type,
labels=monitored_resource_data.labels,
)


class CloudLoggingExporter(LogExporter):
def __init__(
self,
Expand Down Expand Up @@ -302,14 +341,10 @@ def export(self, batch: Sequence[LogData]):
else:
ts.FromDatetime(now)
log_entry.timestamp = ts
monitored_resource_data = get_monitored_resource(
log_record.resource or Resource({})
)
if monitored_resource_data:
log_entry.resource = MonitoredResource(
type=monitored_resource_data.type,
labels=monitored_resource_data.labels,
)
if monitored_resource := _get_monitored_resource(
log_record.resource
):
log_entry.resource = monitored_resource
log_entry.trace_sampled = (
log_record.trace_flags is not None
and log_record.trace_flags.sampled
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"entries": [
{
"logName": "projects/fakeproject/logs/test",
"resource": {
"labels": {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the logging API accepts this

Image

"location": "europe-west3",
"reasoning_engine_id": "8477639270431981568"
},
"type": "aiplatform.googleapis.com/ReasoningEngine"
},
"textPayload": "valid agent engine",
"timestamp": "2025-01-15T21:25:10.997977393Z"
},
{
"logName": "projects/fakeproject/logs/test",
"resource": {
"labels": {
"location": "global",
"namespace": "",
"node_id": ""
},
"type": "generic_node"
},
"textPayload": "invalid 1",
"timestamp": "2025-01-15T21:25:10.997977393Z"
},
{
"logName": "projects/fakeproject/logs/test",
"resource": {
"labels": {
"location": "global",
"namespace": "",
"node_id": ""
},
"type": "generic_node"
},
"textPayload": "invalid 2",
"timestamp": "2025-01-15T21:25:10.997977393Z"
},
{
"logName": "projects/fakeproject/logs/test",
"resource": {
"labels": {
"location": "global",
"namespace": "",
"node_id": ""
},
"type": "generic_node"
},
"textPayload": "invalid 3",
"timestamp": "2025-01-15T21:25:10.997977393Z"
}
],
"partialSuccess": true
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"logging.googleapis.com/labels": {},
"logging.googleapis.com/spanId": "",
"logging.googleapis.com/trace": "",
"logging.googleapis.com/trace_sampled": false,
"message": "valid agent engine",
"severity": "DEFAULT",
"time": "2025-01-15T21:25:10.997977393Z"
},
{
"logging.googleapis.com/labels": {},
"logging.googleapis.com/spanId": "",
"logging.googleapis.com/trace": "",
"logging.googleapis.com/trace_sampled": false,
"message": "invalid 1",
"severity": "DEFAULT",
"time": "2025-01-15T21:25:10.997977393Z"
},
{
"logging.googleapis.com/labels": {},
"logging.googleapis.com/spanId": "",
"logging.googleapis.com/trace": "",
"logging.googleapis.com/trace_sampled": false,
"message": "invalid 2",
"severity": "DEFAULT",
"time": "2025-01-15T21:25:10.997977393Z"
},
{
"logging.googleapis.com/labels": {},
"logging.googleapis.com/spanId": "",
"logging.googleapis.com/trace": "",
"logging.googleapis.com/trace_sampled": false,
"message": "invalid 3",
"severity": "DEFAULT",
"time": "2025-01-15T21:25:10.997977393Z"
}
]
56 changes: 56 additions & 0 deletions opentelemetry-exporter-gcp-logging/tests/test_cloud_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,62 @@ def test_user_agent(cloudloggingfake: CloudLoggingFake) -> None:
)


def test_agent_engine_monitored_resources(
export_and_assert_snapshot: ExportAndAssertSnapshot,
) -> None:
log_data = [
LogData(
log_record=LogRecord(
body="valid agent engine",
timestamp=1736976310997977393,
resource=Resource(
{
"cloud.resource_id": "//aiplatform.googleapis.com/projects/some-project123-321/locations/europe-west3/reasoningEngines/8477639270431981568"
}
),
),
instrumentation_scope=InstrumentationScope("test"),
),
LogData(
log_record=LogRecord(
body="invalid 1",
timestamp=1736976310997977393,
resource=Resource(
{
"cloud.resource_id": "//aiplatform.googleapis.com/locations/europe-west3/reasoningEngines/8477639270431981568"
}
),
),
instrumentation_scope=InstrumentationScope("test"),
),
LogData(
log_record=LogRecord(
body="invalid 2",
timestamp=1736976310997977393,
resource=Resource(
{
"cloud.resource_id": "//aiplatform.googleapis.com/projects/some-project123-321/locations/europe-west3/reasoningEngines//8477639270431981568"
}
),
),
instrumentation_scope=InstrumentationScope("test"),
),
LogData(
log_record=LogRecord(
body="invalid 3",
timestamp=1736976310997977393,
resource=Resource(
{
"cloud.resource_id": "aiplatform.googleapis.com/projects/some-project123-321/locations/europe-west3/reasoningEngines//8477639270431981568"
}
),
),
instrumentation_scope=InstrumentationScope("test"),
),
]
export_and_assert_snapshot(log_data)


def test_convert_otlp_dict_body(
export_and_assert_snapshot: ExportAndAssertSnapshot,
) -> None:
Expand Down