Skip to content

Commit 00bd01e

Browse files
committed
Merge branch 'main' into logname_change
2 parents 408d1a3 + f4a864a commit 00bd01e

File tree

30 files changed

+3637
-1045
lines changed

30 files changed

+3637
-1045
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,6 @@ cython_debug/
146146
# Sphinx
147147
_build/
148148
_autosummary/
149+
150+
# Ephemeral Databases
151+
*.db

e2e-test-server/e2e_test_server/scenarios.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@
2222
from opentelemetry.propagators.cloud_trace_propagator import (
2323
CloudTraceFormatPropagator,
2424
)
25-
from opentelemetry.resourcedetector.gcp_resource_detector._detector import (
26-
GoogleCloudResourceDetector,
27-
)
25+
from opentelemetry.resourcedetector.gcp_resource_detector import GoogleCloudResourceDetector
2826
from opentelemetry.sdk.trace import TracerProvider
2927
from opentelemetry.sdk.trace.export import BatchSpanProcessor
3028
from opentelemetry.sdk.trace.sampling import ALWAYS_ON

opentelemetry-exporter-gcp-logging/CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
## Unreleased
44

5-
Added support for when `bytes` or `list['bytes']` is in `LogRecord.body` and
6-
body is of type Mapping. Update opentelemetry-api/sdk dependencies to 1.3.
5+
- Added support for when a `Mapping[str, bytes]` or `Mapping[str, List[bytes]]` is in `LogRecord.body`.
6+
- Added support for when a `Mapping[str, List[Mapping]]` is in `LogRecord.body`.
7+
- Do not call `logging.warning` when `LogRecord.body` is of None type, instead leave `LogEntry.payload` empty.
8+
- Update opentelemetry-api/sdk dependencies to 1.3.
79

810
The suffix part of `LogEntry.log_name` will be the `LogRecord.event_name` when
911
that is present and the `gcp.log_name` attribute is not.

opentelemetry-exporter-gcp-logging/src/opentelemetry/exporter/cloud_logging/__init__.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,6 @@ def _convert_any_value_to_string(value: Any) -> str:
112112
return str(value)
113113
if isinstance(value, (list, tuple)):
114114
return json.dumps(value)
115-
logging.warning(
116-
"Unknown value %s found, cannot convert to string.", type(value)
117-
)
118115
return ""
119116

120117

@@ -132,9 +129,19 @@ def _sanitized_body(
132129
# Should not be possible for a non-bytes value to be present. AnyValue requires Sequence be of one type, and above
133130
# we verified the first value is type bytes.
134131
new_body[key] = [
135-
base64.b64encode(v).decode()
132+
base64.b64encode(v).decode() if isinstance(v, bytes) else v
136133
for v in value
137-
if isinstance(v, bytes)
134+
]
135+
elif (
136+
isinstance(value, Sequence)
137+
and len(value) > 0
138+
and isinstance(value[0], Mapping)
139+
):
140+
# Should not be possible for a non-mapping value to be present. AnyValue requires Sequence be of one type, and above
141+
# we verified the first value is type mapping.
142+
new_body[key] = [
143+
_sanitized_body(x) if isinstance(x, Mapping) else x
144+
for x in value
138145
]
139146
elif isinstance(value, bytes):
140147
new_body[key] = base64.b64encode(value).decode()
@@ -148,8 +155,15 @@ def _sanitized_body(
148155
def _set_payload_in_log_entry(log_entry: LogEntry, body: AnyValue):
149156
struct = Struct()
150157
if isinstance(body, Mapping):
151-
struct.update(_sanitized_body(body))
152-
log_entry.json_payload = struct
158+
sanitized = _sanitized_body(body)
159+
try:
160+
struct.update(sanitized)
161+
log_entry.json_payload = struct
162+
except Exception as exc: # pylint: disable=broad-except
163+
logging.exception(
164+
"Error mapping LogRecord.body to Struct, will write log with empty body: %s",
165+
exc,
166+
)
153167
elif isinstance(body, bytes):
154168
json_str = body.decode("utf-8", errors="replace")
155169
json_dict = json.loads(json_str)
@@ -158,7 +172,7 @@ def _set_payload_in_log_entry(log_entry: LogEntry, body: AnyValue):
158172
log_entry.json_payload = struct
159173
else:
160174
log_entry.text_payload = base64.b64encode(body).decode()
161-
else:
175+
elif body is not None:
162176
log_entry.text_payload = _convert_any_value_to_string(body)
163177

164178

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[
2+
{
3+
"entries": [
4+
{
5+
"logName": "projects/fakeproject/logs/test",
6+
"resource": {
7+
"labels": {
8+
"location": "global",
9+
"namespace": "",
10+
"node_id": ""
11+
},
12+
"type": "generic_node"
13+
},
14+
"timestamp": "2025-01-15T21:25:10.997977393Z"
15+
}
16+
],
17+
"partialSuccess": true
18+
}
19+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[
2+
{
3+
"entries": [
4+
{
5+
"jsonPayload": {
6+
"my_dict": [
7+
true,
8+
false,
9+
false,
10+
true
11+
]
12+
},
13+
"logName": "projects/fakeproject/logs/test",
14+
"resource": {
15+
"labels": {
16+
"location": "global",
17+
"namespace": "",
18+
"node_id": ""
19+
},
20+
"type": "generic_node"
21+
},
22+
"timestamp": "2025-01-15T21:25:10.997977393Z"
23+
}
24+
],
25+
"partialSuccess": true
26+
}
27+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"entries": [
4+
{
5+
"jsonPayload": {
6+
"my_dict": [
7+
{
8+
"key": "Ynl0ZXM="
9+
}
10+
]
11+
},
12+
"logName": "projects/fakeproject/logs/test",
13+
"resource": {
14+
"labels": {
15+
"location": "global",
16+
"namespace": "",
17+
"node_id": ""
18+
},
19+
"type": "generic_node"
20+
},
21+
"timestamp": "2025-01-15T21:25:10.997977393Z"
22+
}
23+
],
24+
"partialSuccess": true
25+
}
26+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[
2+
{
3+
"entries": [
4+
{
5+
"jsonPayload": {
6+
"my_dict": [
7+
true,
8+
"str",
9+
1.0,
10+
0.234
11+
]
12+
},
13+
"logName": "projects/fakeproject/logs/test",
14+
"resource": {
15+
"labels": {
16+
"location": "global",
17+
"namespace": "",
18+
"node_id": ""
19+
},
20+
"type": "generic_node"
21+
},
22+
"timestamp": "2025-01-15T21:25:10.997977393Z"
23+
}
24+
],
25+
"partialSuccess": true
26+
}
27+
]

opentelemetry-exporter-gcp-logging/tests/test_cloud_logging.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
Be sure to review the changes.
2727
"""
2828
import re
29-
from typing import List, Union
29+
from typing import List, Mapping, Union
3030

3131
import pytest
3232
from fixtures.cloud_logging_fake import CloudLoggingFake, WriteLogEntriesCall
@@ -156,12 +156,25 @@ def test_convert_non_json_dict_bytes(
156156

157157
@pytest.mark.parametrize(
158158
"body",
159-
[pytest.param("A text body", id="str"), pytest.param(True, id="bool")],
159+
[
160+
pytest.param("A text body", id="str"),
161+
pytest.param(True, id="bool"),
162+
pytest.param(None, id="None"),
163+
pytest.param(
164+
{"my_dict": [{"key": b"bytes"}]}, id="list_of_dicts_with_bytes"
165+
),
166+
pytest.param(
167+
{"my_dict": [True, False, False, True]}, id="list_of_bools"
168+
),
169+
pytest.param(
170+
{"my_dict": [True, "str", 1, 0.234]}, id="list_of_mixed_sequence"
171+
),
172+
],
160173
)
161174
def test_convert_various_types_of_bodies(
162175
cloudloggingfake: CloudLoggingFake,
163176
snapshot_writelogentrycalls: List[WriteLogEntriesCall],
164-
body: Union[str, bool],
177+
body: Union[str, bool, None, Mapping],
165178
) -> None:
166179
log_data = [
167180
LogData(

opentelemetry-resourcedetector-gcp/CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22

33
## Unreleased
44

5-
Update opentelemetry-api/sdk dependencies to 1.3.
5+
- Update opentelemetry-api/sdk dependencies to 1.3.
6+
7+
- This is a breaking change which moves our official recource detector from `opentelemetry.resourcedetector.gcp_resource_detector._detector`
8+
into `opentelemetry.resourcedetector.gcp_resource_detector` and deletes the outdated duplicate resource detector
9+
which used to be there. Use `from opentelemetry.resourcedetector.gcp_resource_detector import GoogleCloudResourceDetector`
10+
to import it. See ([#389](https://github.com/GoogleCloudPlatform/opentelemetry-operations-python/pull/389)) for details.
611

712
## Version 1.9.0a0
813

0 commit comments

Comments
 (0)