-
Notifications
You must be signed in to change notification settings - Fork 1.7k
docs(logging): add write log entry sample #16906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||||||||||||||||
| 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" | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of manually constructing the log resource name string, use the
Suggested change
|
||||||||||||||||
| 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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The script will raise an
Suggested change
|
||||||||||||||||
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid importing from deep internal paths like
services.logging_service_v2ortypes. It is more idiomatic and robust to import from the public surface of the library, which is less likely to change in future versions.