Skip to content

Commit 56c3379

Browse files
committed
Make sure the apache license and current year is
on every file. Give log name a default value. Fix some types / formatting that running the tox commands surfaced.
1 parent a0577fc commit 56c3379

File tree

10 files changed

+160
-106
lines changed

10 files changed

+160
-106
lines changed
Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
OpenTelemetry Google Cloud Monitoring Exporter
1+
OpenTelemetry Google Cloud Logging Exporter
22
==============================================
33

4-
.. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-monitoring.svg
5-
:target: https://badge.fury.io/py/opentelemetry-exporter-gcp-monitoring
4+
.. image:: https://badge.fury.io/py/opentelemetry-exporter-gcp-logging.svg
5+
:target: https://badge.fury.io/py/opentelemetry-exporter-gcp-logging
66

77
.. image:: https://readthedocs.org/projects/google-cloud-opentelemetry/badge/?version=latest
88
:target: https://google-cloud-opentelemetry.readthedocs.io/en/latest/?badge=latest
99
:alt: Documentation Status
1010

11-
This library provides support for exporting metrics to Google Cloud
12-
Monitoring.
11+
This library provides support for exporting logs to Google Cloud
12+
Logging.
1313

1414
To get started with instrumentation in Google Cloud, see `Generate traces and metrics with
1515
Python <https://cloud.google.com/stackdriver/docs/instrumentation/setup/python>`_.
@@ -29,57 +29,54 @@ Installation
2929

3030
.. code:: bash
3131
32-
pip install opentelemetry-exporter-gcp-monitoring
32+
pip install opentelemetry-exporter-gcp-logging
3333
3434
Usage
3535
-----
3636

3737
.. code:: python
3838
39-
import time
40-
41-
from opentelemetry import metrics
42-
from opentelemetry.exporter.cloud_monitoring import (
43-
CloudMonitoringMetricsExporter,
39+
from opentelemetry.exporter.cloud_logging import (
40+
CloudLoggingExporter,
4441
)
45-
from opentelemetry.sdk.metrics import MeterProvider
46-
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
42+
from opentelemetry.sdk._logs._internal import LogRecord
43+
from opentelemetry._logs.severity import SeverityNumber
4744
from opentelemetry.sdk.resources import Resource
48-
49-
metrics.set_meter_provider(
50-
MeterProvider(
51-
metric_readers=[
52-
PeriodicExportingMetricReader(
53-
CloudMonitoringMetricsExporter(), export_interval_millis=5000
54-
)
55-
],
56-
resource=Resource.create(
57-
{
58-
"service.name": "basic_metrics",
59-
"service.namespace": "examples",
60-
"service.instance.id": "instance123",
61-
}
62-
),
63-
)
64-
)
65-
meter = metrics.get_meter(__name__)
66-
67-
# Creates metric workload.googleapis.com/request_counter with monitored resource generic_task
68-
requests_counter = meter.create_counter(
69-
name="request_counter",
70-
description="number of requests",
71-
unit="1",
45+
from opentelemetry.sdk._logs import LogData
46+
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
47+
48+
49+
exporter = CloudLoggingExporter(default_log_name='my_log')
50+
exporter.export(
51+
[
52+
LogData(
53+
log_record=LogRecord(
54+
resource=Resource({}),
55+
timestamp=1736976310997977393,
56+
severity_number=SeverityNumber(20),
57+
attributes={
58+
"gen_ai.system": "openai",
59+
"event.name": "gen_ai.system.message",
60+
},
61+
body={
62+
"kvlistValue": {
63+
"values": [
64+
{
65+
"key": "content",
66+
"value": {"stringValue": "You're a helpful assistant."},
67+
}
68+
]
69+
}
70+
},
71+
),
72+
instrumentation_scope=InstrumentationScope("test"),
73+
)
74+
]
7275
)
7376
74-
staging_labels = {"environment": "staging"}
75-
76-
for i in range(20):
77-
requests_counter.add(25, staging_labels)
78-
time.sleep(5)
79-
8077
8178
References
8279
----------
8380

84-
* `Cloud Monitoring <https://cloud.google.com/monitoring>`_
81+
* `Cloud Logging <https://cloud.google.com/logging>`_
8582
* `OpenTelemetry Project <https://opentelemetry.io/>`_

opentelemetry-exporter-gcp-logging/setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ where = src
3838
test =
3939

4040
[options.entry_points]
41-
opentelemetry_metrics_exporter =
41+
opentelemetry_logging_exporter =
4242
gcp_logging = opentelemetry.exporter.cloud_logging:CloudLoggingExporter
4343
opentelemetry_environment_variables =
4444
gcp_logging = opentelemetry.exporter.cloud_logging.environment_variables

opentelemetry-exporter-gcp-logging/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2021 The OpenTelemetry Authors
1+
# Copyright 2025 The OpenTelemetry Authors
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

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

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,41 @@
1-
from opentelemetry.sdk._logs.export import LogExporter
2-
from opentelemetry.sdk._logs import LogData
3-
import google.auth
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
414
import datetime
5-
from typing import Optional, Sequence
615
import logging
7-
from google.logging.type.log_severity_pb2 import LogSeverity # type: ignore
8-
from google.cloud.logging_v2.services.logging_service_v2 import LoggingServiceV2Client
16+
import urllib.parse
17+
from typing import Optional, Sequence
18+
19+
import google.auth
20+
from google.api.monitored_resource_pb2 import MonitoredResource # type: ignore
21+
from google.cloud.logging_v2.services.logging_service_v2 import (
22+
LoggingServiceV2Client,
23+
)
924
from google.cloud.logging_v2.services.logging_service_v2.transports.grpc import (
1025
LoggingServiceV2GrpcTransport,
1126
)
1227
from google.cloud.logging_v2.types.log_entry import LogEntry
28+
from google.logging.type.log_severity_pb2 import LogSeverity # type: ignore
29+
from google.protobuf.struct_pb2 import Struct
30+
from google.protobuf.timestamp_pb2 import Timestamp
31+
from opentelemetry.exporter.cloud_logging.version import __version__
1332
from opentelemetry.resourcedetector.gcp_resource_detector._mapping import (
1433
get_monitored_resource,
1534
)
16-
from google.api.monitored_resource_pb2 import (
17-
MonitoredResource, # type: ignore
18-
)
19-
from google.protobuf.timestamp_pb2 import Timestamp
20-
import urllib.parse
21-
from google.protobuf.struct_pb2 import Struct
22-
from opentelemetry.exporter.cloud_logging.version import __version__
2335
from opentelemetry.sdk import version as opentelemetry_sdk_version
24-
36+
from opentelemetry.sdk._logs import LogData
37+
from opentelemetry.sdk._logs.export import LogExporter
38+
from opentelemetry.sdk.resources import Resource
2539

2640
DEFAULT_MAX_ENTRY_SIZE = 256000 # 256 KB
2741
DEFAULT_MAX_REQUEST_SIZE = 10000000 # 10 MB
@@ -45,7 +59,7 @@
4559

4660
# severityMapping maps the integer severity level values from OTel [0-24]
4761
# to matching Cloud Logging severity levels.
48-
SEVERITY_MAPPING = {
62+
SEVERITY_MAPPING: dict[int, int] = {
4963
0: LogSeverity.DEFAULT, # Default, 0
5064
1: LogSeverity.DEBUG, #
5165
2: LogSeverity.DEBUG, #
@@ -87,7 +101,10 @@ def __init__(
87101
self.project_id = str(default_project_id)
88102
else:
89103
self.project_id = project_id
90-
self.default_log_name = default_log_name
104+
if default_log_name:
105+
self.default_log_name = default_log_name
106+
else:
107+
self.default_log_name = "otel_python_inprocess_log_name_temp"
91108
self.client = client or LoggingServiceV2Client(
92109
transport=LoggingServiceV2GrpcTransport(
93110
channel=LoggingServiceV2GrpcTransport.create_channel(
@@ -108,14 +125,11 @@ def export(self, batch: Sequence[LogData]):
108125
log_name = self.default_log_name
109126
if attributes.get(LOG_NAME_ATTRIBUTE_KEY):
110127
log_name = str(attributes.get(LOG_NAME_ATTRIBUTE_KEY))
111-
if not log_name:
112-
logging.warning(
113-
"No log name provided, cannot write log to Cloud Logging. Set the 'default_log_name' option, or add the 'gcp.log_name' attribute to set a log name."
114-
)
115-
continue
116-
monitored_resource_data = get_monitored_resource(log_record.resource)
128+
monitored_resource_data = get_monitored_resource(
129+
log_record.resource or Resource({})
130+
)
117131
# convert it to proto
118-
monitored_resource = (
132+
monitored_resource: Optional[MonitoredResource] = (
119133
MonitoredResource(
120134
type=monitored_resource_data.type,
121135
labels=monitored_resource_data.labels,
@@ -138,22 +152,31 @@ def export(self, batch: Sequence[LogData]):
138152
log_entry = LogEntry()
139153
log_entry.timestamp = ts
140154
log_entry.log_name = log_name
141-
log_entry.resource = monitored_resource
155+
if monitored_resource:
156+
log_entry.resource = monitored_resource
142157
attrs_map = {k: v for k, v in attributes.items()}
143158
log_entry.trace_sampled = (
144-
log_record.trace_flags is not None and log_record.trace_flags.sampled
159+
log_record.trace_flags is not None
160+
and log_record.trace_flags.sampled
145161
)
146162
if TRACE_SAMPLED_ATTRIBUTE_KEY in attrs_map:
147-
log_entry.trace_sampled |= bool(attrs_map[TRACE_SAMPLED_ATTRIBUTE_KEY])
163+
log_entry.trace_sampled |= bool(
164+
attrs_map[TRACE_SAMPLED_ATTRIBUTE_KEY]
165+
)
148166
del attrs_map[TRACE_SAMPLED_ATTRIBUTE_KEY]
149167
if log_record.trace_id:
150168
log_entry.trace = "projects/{}/traces/{}".format(
151169
project_id, log_record.trace_id
152170
)
153171
if log_record.span_id:
154172
log_entry.span_id = str(hex(log_record.span_id))[2:]
155-
if log_record.severity_number in SEVERITY_MAPPING:
156-
log_entry.severity = SEVERITY_MAPPING[log_record.severity_number]
173+
if (
174+
log_record.severity_number
175+
and log_record.severity_number in SEVERITY_MAPPING
176+
):
177+
log_entry.severity = SEVERITY_MAPPING[
178+
log_record.severity_number
179+
]
157180
log_entry.labels = {k: str(v) for k, v in attrs_map.items()}
158181
if type(log_record.body) is dict:
159182
s = Struct()
@@ -164,7 +187,7 @@ def export(self, batch: Sequence[LogData]):
164187
self._write_log_entries(log_entries)
165188

166189
def _write_log_entries(self, log_entries: list[LogEntry]):
167-
batch = []
190+
batch: list[LogEntry] = []
168191
batch_byte_size = 0
169192
for entry in log_entries:
170193
msg_size = LogEntry.pb(entry).ByteSize()

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2023 Google LLC
1+
# Copyright 2025 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -12,9 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID = (
16-
"OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID"
17-
)
15+
OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID = "OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID"
1816
"""
1917
.. envvar:: OTEL_EXPORTER_GCP_LOGGING_PROJECT_ID
2018

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2021 The OpenTelemetry Authors
1+
# Copyright 2025 The OpenTelemetry Authors
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2022 Google LLC
1+
# Copyright 2025 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

opentelemetry-exporter-gcp-logging/tests/fixtures/cloud_logging_fake.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
114
from concurrent.futures import ThreadPoolExecutor
215
from dataclasses import dataclass
316
from functools import partial
417
from typing import Callable, Iterable, List, cast
518
from unittest.mock import patch
19+
20+
import grpc
21+
import pytest
622
from google.cloud.logging_v2.services.logging_service_v2.transports.grpc import (
723
LoggingServiceV2GrpcTransport,
824
)
9-
1025
from google.cloud.logging_v2.types.logging import WriteLogEntriesRequest
11-
import grpc
12-
import pytest
1326

1427
# pylint: disable=no-name-in-module
1528
from google.protobuf.empty_pb2 import Empty
@@ -20,9 +33,7 @@
2033
method_handlers_generic_handler,
2134
unary_unary_rpc_method_handler,
2235
)
23-
from opentelemetry.exporter.cloud_logging import (
24-
CloudLoggingExporter,
25-
)
36+
from opentelemetry.exporter.cloud_logging import CloudLoggingExporter
2637

2738

2839
@dataclass

opentelemetry-exporter-gcp-logging/tests/fixtures/snapshot_logging_calls.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2022 Google LLC
1+
# Copyright 2025 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import Optional, cast, List
15+
from typing import List, Optional, cast
1616

1717
import pytest
1818
from fixtures.cloud_logging_fake import WriteLogEntriesCall
@@ -39,7 +39,9 @@ def serialize(
3939
) -> SerializedData:
4040
json = [
4141
json_format.MessageToDict(
42-
type(call.write_log_entries_request).pb(call.write_log_entries_request)
42+
type(call.write_log_entries_request).pb(
43+
call.write_log_entries_request
44+
)
4345
)
4446
for call in cast(List[WriteLogEntriesCall], data)
4547
]

0 commit comments

Comments
 (0)