From 3a7c5942828df5b4cbe2b9bb3758097e8c3c4843 Mon Sep 17 00:00:00 2001 From: David del Real Sifuentes Date: Mon, 29 Jun 2026 22:56:15 +0000 Subject: [PATCH 1/5] feat(logging): update write_entry snippet to use Python logging framework - Update `write_entry` in `snippets.py` to use `google.cloud.logging.setup_logging()` instead of calling the client logger methods directly. - Demonstrate writing a structured JSON log using the standard `logging` library's `extra` parameter. - Update `test_write` in `snippets_test.py` to verify logs written via the default python logging handler. - Remove python version constraint for pytest in `requirements-test.txt`. --- .../samples/snippets/requirements-test.txt | 2 +- logging/samples/snippets/snippets.py | 41 ++++++++++--------- logging/samples/snippets/snippets_test.py | 24 ++++++++--- 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/logging/samples/snippets/requirements-test.txt b/logging/samples/snippets/requirements-test.txt index 79932f8353..a5a3777fcb 100644 --- a/logging/samples/snippets/requirements-test.txt +++ b/logging/samples/snippets/requirements-test.txt @@ -1,2 +1,2 @@ backoff==2.2.1 -pytest==9.0.3; python_version >= "3.10" +pytest==9.0.3 diff --git a/logging/samples/snippets/snippets.py b/logging/samples/snippets/snippets.py index f6c16d17e3..786745f2e4 100644 --- a/logging/samples/snippets/snippets.py +++ b/logging/samples/snippets/snippets.py @@ -22,35 +22,38 @@ """ import argparse +import logging +import time -from google.cloud import logging +import google.cloud.logging # [START logging_write_log_entry] -def write_entry(logger_name): +def write_entry(): """Writes log entries to the given logger.""" - logging_client = logging.Client() + logging_client = google.cloud.logging.Client() - # This log can be found in the Cloud Logging console under 'Custom Logs'. - logger = logging_client.logger(logger_name) + # By default, all logs sent through setup_logging() + # appear under the log name projects/[PROJECT_ID]/logs/python + logging_client.setup_logging(log_level=logging.INFO) # Make a simple text log - logger.log_text("Hello, world!") + logging.info("Hello, world!") # Simple text log with severity. - logger.log_text("Goodbye, world!", severity="WARNING") - - # Struct log. The struct can be any JSON-serializable dictionary. - logger.log_struct( - { - "name": "King Arthur", - "quest": "Find the Holy Grail", - "favorite_color": "Blue", - }, - severity="INFO", - ) + logging.warning("Goodbye, world!") + + # Prepare your structured data as a dictionary. + json_log = { + "name": "King Arthur", + "quest": "Find the Holy Grail", + "favorite_color": "Blue", + } + + logging.info("This is a JSON log.", extra={"json_fields": json_log}) - print("Wrote logs to {}.".format(logger.name)) + # wait for threads + time.sleep(5) # [END logging_write_log_entry] @@ -105,6 +108,6 @@ def delete_logger(logger_name): if args.command == "list": list_entries(args.logger_name) elif args.command == "write": - write_entry(args.logger_name) + write_entry() elif args.command == "delete": delete_logger(args.logger_name) diff --git a/logging/samples/snippets/snippets_test.py b/logging/samples/snippets/snippets_test.py index 5cddc92d31..b75e43f853 100644 --- a/logging/samples/snippets/snippets_test.py +++ b/logging/samples/snippets/snippets_test.py @@ -13,6 +13,7 @@ # limitations under the License. import uuid +import os import backoff from google.api_core.exceptions import NotFound @@ -21,9 +22,10 @@ import snippets - TEST_LOGGER_NAME = "example_log_{}".format(uuid.uuid4().hex) TEST_TEXT = "Hello, world." +GOOGLE_CLOUD_PROJECT = os.getenv("GOOGLE_CLOUD_PROJECT") +DEFAULT_LOG_ID = f"projects/{GOOGLE_CLOUD_PROJECT}/logs/python" @pytest.fixture @@ -47,13 +49,25 @@ def eventually_consistent_test(): def test_write(capsys): - snippets.write_entry(TEST_LOGGER_NAME) + snippets.write_entry() @backoff.on_exception(backoff.expo, AssertionError, max_time=120) def eventually_consistent_test(): - snippets.list_entries(TEST_LOGGER_NAME) - out, _ = capsys.readouterr() - assert TEST_TEXT in out + # retrieve logs + client = logging.Client() + + log_filter = DEFAULT_LOG_ID + + entries = client.list_entries( + filter_=log_filter, order_by=logging.DESCENDING, max_results=3 + ) + + entry_1 = next(entries) + assert entry_1.payload["message"] == "This is a JSON log." + entry_2 = next(entries) + assert entry_2.payload == "Goodbye, world!" + entry_3 = next(entries) + assert entry_3.payload == "Hello, world!" eventually_consistent_test() From 757f87724bcd70decd7a2f59a60a9bbea1b53929 Mon Sep 17 00:00:00 2001 From: David del Real Sifuentes Date: Mon, 29 Jun 2026 23:00:34 +0000 Subject: [PATCH 2/5] linting import orders --- logging/samples/snippets/snippets.py | 3 ++- logging/samples/snippets/snippets_test.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/logging/samples/snippets/snippets.py b/logging/samples/snippets/snippets.py index 786745f2e4..4c139b3186 100644 --- a/logging/samples/snippets/snippets.py +++ b/logging/samples/snippets/snippets.py @@ -22,9 +22,10 @@ """ import argparse -import logging import time +import logging + import google.cloud.logging diff --git a/logging/samples/snippets/snippets_test.py b/logging/samples/snippets/snippets_test.py index b75e43f853..91e5e71bff 100644 --- a/logging/samples/snippets/snippets_test.py +++ b/logging/samples/snippets/snippets_test.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import uuid import os +import uuid import backoff from google.api_core.exceptions import NotFound From e88bbc4e9863639cd580c9bab90f5fc6c69ec4b2 Mon Sep 17 00:00:00 2001 From: David del Real Sifuentes Date: Mon, 29 Jun 2026 23:07:28 +0000 Subject: [PATCH 3/5] Fix gemini suggestions and lint more import order. --- logging/samples/snippets/snippets.py | 6 +++--- logging/samples/snippets/snippets_test.py | 15 +++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/logging/samples/snippets/snippets.py b/logging/samples/snippets/snippets.py index 4c139b3186..c617f5185b 100644 --- a/logging/samples/snippets/snippets.py +++ b/logging/samples/snippets/snippets.py @@ -24,14 +24,14 @@ import argparse import time -import logging - import google.cloud.logging +import logging + # [START logging_write_log_entry] def write_entry(): - """Writes log entries to the given logger.""" + """Writes log entries to the default logger.""" logging_client = google.cloud.logging.Client() # By default, all logs sent through setup_logging() diff --git a/logging/samples/snippets/snippets_test.py b/logging/samples/snippets/snippets_test.py index 91e5e71bff..616ce424d4 100644 --- a/logging/samples/snippets/snippets_test.py +++ b/logging/samples/snippets/snippets_test.py @@ -25,7 +25,7 @@ TEST_LOGGER_NAME = "example_log_{}".format(uuid.uuid4().hex) TEST_TEXT = "Hello, world." GOOGLE_CLOUD_PROJECT = os.getenv("GOOGLE_CLOUD_PROJECT") -DEFAULT_LOG_ID = f"projects/{GOOGLE_CLOUD_PROJECT}/logs/python" +DEFAULT_LOGGER = f"projects/{GOOGLE_CLOUD_PROJECT}/logs/python" @pytest.fixture @@ -56,18 +56,17 @@ def eventually_consistent_test(): # retrieve logs client = logging.Client() - log_filter = DEFAULT_LOG_ID + log_filter = DEFAULT_LOGGER entries = client.list_entries( filter_=log_filter, order_by=logging.DESCENDING, max_results=3 ) - entry_1 = next(entries) - assert entry_1.payload["message"] == "This is a JSON log." - entry_2 = next(entries) - assert entry_2.payload == "Goodbye, world!" - entry_3 = next(entries) - assert entry_3.payload == "Hello, world!" + retrieved_entries = list(entries) + + assert retrieved_entries[0].payload["message"] == "This is a JSON log." + assert retrieved_entries[1].payload == "Goodbye, world!" + assert retrieved_entries[2].payload == "Hello, world!" eventually_consistent_test() From dc0ba3b3e9cd99a6cf270bc2a622c145a963edd8 Mon Sep 17 00:00:00 2001 From: David del Real Sifuentes Date: Tue, 30 Jun 2026 19:27:53 +0000 Subject: [PATCH 4/5] Overhaul comments by request. --- logging/samples/snippets/snippets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/logging/samples/snippets/snippets.py b/logging/samples/snippets/snippets.py index c617f5185b..cb27bde517 100644 --- a/logging/samples/snippets/snippets.py +++ b/logging/samples/snippets/snippets.py @@ -31,11 +31,11 @@ # [START logging_write_log_entry] def write_entry(): - """Writes log entries to the default logger.""" + """Demonstrates how to write log entries to Google Cloud using Python's standard logging library.""" logging_client = google.cloud.logging.Client() - # By default, all logs sent through setup_logging() - # appear under the log name projects/[PROJECT_ID]/logs/python + # Logs default to projects/[PROJECT_ID]/logs/python unless routed + # differently by a custom handler or managed GCP infrastructure. logging_client.setup_logging(log_level=logging.INFO) # Make a simple text log @@ -53,7 +53,7 @@ def write_entry(): logging.info("This is a JSON log.", extra={"json_fields": json_log}) - # wait for threads + # wait for threads to finish working on the background. time.sleep(5) From b2fad50611bf8e5ae3928152c5e2f1deaeebf323 Mon Sep 17 00:00:00 2001 From: David del Real Sifuentes Date: Tue, 30 Jun 2026 20:20:10 +0000 Subject: [PATCH 5/5] more comment overhaul --- logging/samples/snippets/snippets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/logging/samples/snippets/snippets.py b/logging/samples/snippets/snippets.py index cb27bde517..71a1e385e5 100644 --- a/logging/samples/snippets/snippets.py +++ b/logging/samples/snippets/snippets.py @@ -34,8 +34,8 @@ def write_entry(): """Demonstrates how to write log entries to Google Cloud using Python's standard logging library.""" logging_client = google.cloud.logging.Client() - # Logs default to projects/[PROJECT_ID]/logs/python unless routed - # differently by a custom handler or managed GCP infrastructure. + # By default, logs route to projects/[PROJECT_ID]/logs/python + # unless overridden by GCP or custom handlers. logging_client.setup_logging(log_level=logging.INFO) # Make a simple text log