Skip to content
Closed
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
@@ -0,0 +1,71 @@
# Copyright 2026 Google LLC
#
# 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.

import sys

from google.api import monitored_resource_pb2
from google.cloud.logging_v2.services.logging_service_v2 import LoggingServiceV2Client
from google.cloud.logging_v2.types import LogEntry
from google.cloud.logging_v2.types import WriteLogEntriesRequest
Comment on lines +18 to +20
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Avoid importing from deep internal paths like services.logging_service_v2 or types. It is more idiomatic and robust to import from the public surface of the library, which is less likely to change in future versions.

Suggested change
from google.cloud.logging_v2.services.logging_service_v2 import LoggingServiceV2Client
from google.cloud.logging_v2.types import LogEntry
from google.cloud.logging_v2.types import WriteLogEntriesRequest
from google.cloud.logging_v2 import LoggingServiceV2Client
from google.cloud.logging_v2 import LogEntry
from google.cloud.logging_v2 import WriteLogEntriesRequest

from google.logging.type import log_severity_pb2


# [START logging_write_log_entry]
def write_log_entry(project_id: str) -> None:
"""Writes text and structured log entries to Cloud Logging."""

client = LoggingServiceV2Client()
log_name = f"projects/{project_id}/logs/python-example-log"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Instead of manually constructing the log resource name string, use the log_path helper method provided by the client. This ensures the name is correctly formatted and follows the library's best practices.

Suggested change
log_name = f"projects/{project_id}/logs/python-example-log"
log_name = client.log_path(project_id, "python-example-log")

resource = monitored_resource_pb2.MonitoredResource(type="global")
labels = {"sample": "write-log-entry"}

text_entry = LogEntry(
log_name=log_name,
resource=resource,
severity=log_severity_pb2.INFO,
labels=labels,
text_payload="Text log entry written from Python.",
)

struct_entry = LogEntry(
log_name=log_name,
resource=resource,
severity=log_severity_pb2.WARNING,
labels=labels,
json_payload={
"message": "Structured log entry written from Python.",
"component": "sample",
},
)

client.write_log_entries(
request=WriteLogEntriesRequest(
entries=[text_entry],
)
)
print("Wrote one text log entry.")

client.write_log_entries(
request=WriteLogEntriesRequest(
entries=[text_entry, struct_entry],
)
)
print("Wrote a batch of text and structured log entries.")


# [END logging_write_log_entry]


if __name__ == "__main__":
write_log_entry(project_id=sys.argv[1])
Comment on lines +70 to +71
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The script will raise an IndexError if no command-line argument is provided. Adding a simple check for sys.argv improves the usability of this sample by providing a clear usage message.

Suggested change
if __name__ == "__main__":
write_log_entry(project_id=sys.argv[1])
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python write_log_entry.py <PROJECT_ID>")
sys.exit(1)
write_log_entry(project_id=sys.argv[1])

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2026 Google LLC
#
# 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 unittest import mock

from google.logging.type import log_severity_pb2

import write_log_entry


def test_write_log_entry(capsys):
project_id = "my-project"

with mock.patch.object(write_log_entry, "LoggingServiceV2Client") as client:
write_log_entry.write_log_entry(project_id)

logging_client = client.return_value
assert logging_client.write_log_entries.call_count == 2

single_request = logging_client.write_log_entries.call_args_list[0].kwargs["request"]
assert len(single_request.entries) == 1

text_entry = single_request.entries[0]
assert text_entry.log_name == f"projects/{project_id}/logs/python-example-log"
assert text_entry.resource.type == "global"
assert text_entry.severity == log_severity_pb2.INFO
assert text_entry.labels["sample"] == "write-log-entry"
assert text_entry.text_payload == "Text log entry written from Python."

batch_request = logging_client.write_log_entries.call_args_list[1].kwargs["request"]
assert len(batch_request.entries) == 2
assert batch_request.entries[0].text_payload == text_entry.text_payload

struct_entry = batch_request.entries[1]
assert struct_entry.resource.type == "global"
assert struct_entry.severity == log_severity_pb2.WARNING
assert struct_entry.labels["sample"] == "write-log-entry"
assert (
struct_entry.json_payload["message"]
== "Structured log entry written from Python."
)
assert struct_entry.json_payload["component"] == "sample"

out, _ = capsys.readouterr()
assert "Wrote one text log entry." in out
assert "Wrote a batch of text and structured log entries." in out
Loading