Skip to content
This repository was archived by the owner on Feb 26, 2026. It is now read-only.

Commit b4b777b

Browse files
authored
Merge branch 'main' into owl-bot-update-lock-04c35dc5f49f0f503a306397d6d043685f8d2bb822ab515818c4208d7fb2db3a
2 parents 98d5594 + c47946f commit b4b777b

File tree

8 files changed

+77
-8
lines changed

8 files changed

+77
-8
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "3.11.3"
2+
".": "3.11.4"
33
}

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44

55
[1]: https://pypi.org/project/google-cloud-logging/#history
66

7+
## [3.11.4](https://github.com/googleapis/python-logging/compare/v3.11.3...v3.11.4) (2025-01-22)
8+
9+
10+
### Bug Fixes
11+
12+
* Made `write_entries` raise `ValueError` on `ParseError`s ([#958](https://github.com/googleapis/python-logging/issues/958)) ([5309478](https://github.com/googleapis/python-logging/commit/5309478c054d0f2b9301817fd835f2098f51dc3a))
13+
* Require proto-plus >= 1.25 for Python 3.13 ([#955](https://github.com/googleapis/python-logging/issues/955)) ([7baed8e](https://github.com/googleapis/python-logging/commit/7baed8e968f0bfa6abdbf0715dc43822f2fba8ba))
14+
* Require proto-plus >= 1.25 for Python 3.13 ([#955](https://github.com/googleapis/python-logging/issues/955)) ([002b1fc](https://github.com/googleapis/python-logging/commit/002b1fcb395d77d94d7216560c30015b9aefca81))
15+
716
## [3.11.3](https://github.com/googleapis/python-logging/compare/v3.11.2...v3.11.3) (2024-10-15)
817

918

google/cloud/logging/gapic_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16-
__version__ = "3.11.3" # {x-release-please-version}
16+
__version__ = "3.11.4" # {x-release-please-version}

google/cloud/logging_v2/_gapic.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from google.protobuf.json_format import MessageToDict
3232
from google.protobuf.json_format import ParseDict
33+
from google.protobuf.json_format import ParseError
3334

3435
from google.cloud.logging_v2._helpers import entry_from_resource
3536
from google.cloud.logging_v2.sink import Sink
@@ -151,7 +152,10 @@ def write_entries(
151152
Useful for checking whether the logging API endpoints are working
152153
properly before sending valuable data.
153154
"""
154-
log_entry_pbs = [_log_entry_mapping_to_pb(entry) for entry in entries]
155+
try:
156+
log_entry_pbs = [_log_entry_mapping_to_pb(entry) for entry in entries]
157+
except ParseError as e:
158+
raise ValueError(f"Invalid log entry: {str(e)}") from e
155159

156160
request = WriteLogEntriesRequest(
157161
log_name=logger_name,

google/cloud/logging_v2/gapic_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16-
__version__ = "3.11.3" # {x-release-please-version}
16+
__version__ = "3.11.4" # {x-release-please-version}

google/cloud/logging_v2/logger.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ def _do_log(self, client, _entry_class, payload=None, **kw):
162162

163163
api_repr = entry.to_api_repr()
164164
entries = [api_repr]
165+
165166
if google.cloud.logging_v2._instrumentation_emitted is False:
166167
entries = _add_instrumentation(entries, **kw)
167168
google.cloud.logging_v2._instrumentation_emitted = True
@@ -200,18 +201,38 @@ def log_text(self, text, *, client=None, **kw):
200201
self._do_log(client, TextEntry, text, **kw)
201202

202203
def log_struct(self, info, *, client=None, **kw):
203-
"""Log a dictionary message
204+
"""Logs a dictionary message.
204205
205206
See
206207
https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write
207208
209+
The message must be able to be serializable to a Protobuf Struct.
210+
It must be a dictionary of strings to one of the following:
211+
212+
- :class:`str`
213+
- :class:`int`
214+
- :class:`float`
215+
- :class:`bool`
216+
- :class:`list[str|float|int|bool|list|dict|None]`
217+
- :class:`dict[str, str|float|int|bool|list|dict|None]`
218+
219+
For more details on Protobuf structs, see https://protobuf.dev/reference/protobuf/google.protobuf/#value.
220+
If the provided dictionary cannot be serialized into a Protobuf struct,
221+
it will not be logged, and a :class:`ValueError` will be raised.
222+
208223
Args:
209-
info (dict): the log entry information
224+
info (dict[str, str|float|int|bool|list|dict|None]):
225+
the log entry information.
210226
client (Optional[~logging_v2.client.Client]):
211227
The client to use. If not passed, falls back to the
212228
``client`` stored on the current sink.
213229
kw (Optional[dict]): additional keyword arguments for the entry.
214230
See :class:`~logging_v2.entries.LogEntry`.
231+
232+
Raises:
233+
ValueError:
234+
if the dictionary message provided cannot be serialized into a Protobuf
235+
struct.
215236
"""
216237
for field in _STRUCT_EXTRACTABLE_FIELDS:
217238
# attempt to copy relevant fields from the payload into the LogEntry body
@@ -405,8 +426,22 @@ def log_text(self, text, **kw):
405426
def log_struct(self, info, **kw):
406427
"""Add a struct entry to be logged during :meth:`commit`.
407428
429+
The message must be able to be serializable to a Protobuf Struct.
430+
It must be a dictionary of strings to one of the following:
431+
432+
- :class:`str`
433+
- :class:`int`
434+
- :class:`float`
435+
- :class:`bool`
436+
- :class:`list[str|float|int|bool|list|dict|None]`
437+
- :class:`dict[str, str|float|int|bool|list|dict|None]`
438+
439+
For more details on Protobuf structs, see https://protobuf.dev/reference/protobuf/google.protobuf/#value.
440+
If the provided dictionary cannot be serialized into a Protobuf struct,
441+
it will not be logged, and a :class:`ValueError` will be raised during :meth:`commit`.
442+
408443
Args:
409-
info (dict): The struct entry,
444+
info (dict[str, str|float|int|bool|list|dict|None]): The struct entry,
410445
kw (Optional[dict]): Additional keyword arguments for the entry.
411446
See :class:`~logging_v2.entries.LogEntry`.
412447
"""
@@ -451,6 +486,10 @@ def commit(self, *, client=None, partial_success=True):
451486
Whether a batch's valid entries should be written even
452487
if some other entry failed due to a permanent error such
453488
as INVALID_ARGUMENT or PERMISSION_DENIED.
489+
490+
Raises:
491+
ValueError:
492+
if one of the messages in the batch cannot be successfully parsed.
454493
"""
455494
if client is None:
456495
client = self.client

samples/generated_samples/snippet_metadata_google.logging.v2.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
],
99
"language": "PYTHON",
1010
"name": "google-cloud-logging",
11-
"version": "3.11.3"
11+
"version": "3.11.4"
1212
},
1313
"snippets": [
1414
{

tests/unit/test__gapic.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import google.auth.credentials
1818
import mock
1919

20+
from datetime import datetime
21+
2022
import google.cloud.logging
2123
from google.cloud import logging_v2
2224
from google.cloud.logging_v2 import _gapic
@@ -173,6 +175,21 @@ def test_write_entries_single(self):
173175
assert request.entries[0].resource.type == entry["resource"]["type"]
174176
assert request.entries[0].text_payload == "text"
175177

178+
def test_write_entries_parse_error(self):
179+
client = self.make_logging_api()
180+
with self.assertRaises(ValueError):
181+
with mock.patch.object(
182+
type(client._gapic_api.transport.write_log_entries), "__call__"
183+
) as call:
184+
entry = {
185+
"logName": self.LOG_PATH,
186+
"resource": {"type": "global"},
187+
"jsonPayload": {"time": datetime.now()},
188+
}
189+
client.write_entries([entry])
190+
191+
call.assert_not_called()
192+
176193
def test_logger_delete(self):
177194
client = self.make_logging_api()
178195

0 commit comments

Comments
 (0)