From 455f8c05293393c3f9743810951d118a5aacb714 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 11:55:14 -0700 Subject: [PATCH 01/19] remove appengine and containerengine handlers --- google/cloud/logging/handlers/__init__.py | 4 - google/cloud/logging_v2/client.py | 8 +- google/cloud/logging_v2/handlers/__init__.py | 4 - .../cloud/logging_v2/handlers/app_engine.py | 131 ------------------ .../logging_v2/handlers/container_engine.py | 54 -------- 5 files changed, 2 insertions(+), 199 deletions(-) delete mode 100644 google/cloud/logging_v2/handlers/app_engine.py delete mode 100644 google/cloud/logging_v2/handlers/container_engine.py diff --git a/google/cloud/logging/handlers/__init__.py b/google/cloud/logging/handlers/__init__.py index e27f8e673..ae3db9cc6 100644 --- a/google/cloud/logging/handlers/__init__.py +++ b/google/cloud/logging/handlers/__init__.py @@ -14,18 +14,14 @@ """Python :mod:`logging` handlers for Google Cloud Logging.""" -from google.cloud.logging_v2.handlers.app_engine import AppEngineHandler -from google.cloud.logging_v2.handlers.container_engine import ContainerEngineHandler from google.cloud.logging_v2.handlers.structured_log import StructuredLogHandler from google.cloud.logging_v2.handlers.handlers import CloudLoggingFilter from google.cloud.logging_v2.handlers.handlers import CloudLoggingHandler from google.cloud.logging_v2.handlers.handlers import setup_logging __all__ = [ - "AppEngineHandler", "CloudLoggingFilter", "CloudLoggingHandler", - "ContainerEngineHandler", "StructuredLogHandler", "setup_logging", ] diff --git a/google/cloud/logging_v2/client.py b/google/cloud/logging_v2/client.py index 51d93355c..5163d680f 100644 --- a/google/cloud/logging_v2/client.py +++ b/google/cloud/logging_v2/client.py @@ -35,8 +35,6 @@ from google.cloud.logging_v2._http import _MetricsAPI as JSONMetricsAPI from google.cloud.logging_v2._http import _SinksAPI as JSONSinksAPI from google.cloud.logging_v2.handlers import CloudLoggingHandler -from google.cloud.logging_v2.handlers import AppEngineHandler -from google.cloud.logging_v2.handlers import ContainerEngineHandler from google.cloud.logging_v2.handlers import StructuredLogHandler from google.cloud.logging_v2.handlers import setup_logging from google.cloud.logging_v2.handlers.handlers import EXCLUDED_LOGGER_DEFAULTS @@ -351,10 +349,8 @@ def get_default_handler(self, **kw): monitored_resource = kw.pop("resource", detect_resource(self.project)) if isinstance(monitored_resource, Resource): - if monitored_resource.type == _GAE_RESOURCE_TYPE: - return AppEngineHandler(self, **kw) - elif monitored_resource.type == _GKE_RESOURCE_TYPE: - return ContainerEngineHandler(**kw) + if monitored_resource.type == _GKE_RESOURCE_TYPE: + return StructuredLogHandler(**kw, project_id=self.project) elif ( monitored_resource.type == _GCF_RESOURCE_TYPE and sys.version_info[0] == 3 diff --git a/google/cloud/logging_v2/handlers/__init__.py b/google/cloud/logging_v2/handlers/__init__.py index a1ed08b5e..7e59247dc 100644 --- a/google/cloud/logging_v2/handlers/__init__.py +++ b/google/cloud/logging_v2/handlers/__init__.py @@ -14,18 +14,14 @@ """Python :mod:`logging` handlers for Google Cloud Logging.""" -from google.cloud.logging_v2.handlers.app_engine import AppEngineHandler -from google.cloud.logging_v2.handlers.container_engine import ContainerEngineHandler from google.cloud.logging_v2.handlers.structured_log import StructuredLogHandler from google.cloud.logging_v2.handlers.handlers import CloudLoggingHandler from google.cloud.logging_v2.handlers.handlers import CloudLoggingFilter from google.cloud.logging_v2.handlers.handlers import setup_logging __all__ = [ - "AppEngineHandler", "CloudLoggingFilter", "CloudLoggingHandler", - "ContainerEngineHandler", "StructuredLogHandler", "setup_logging", ] diff --git a/google/cloud/logging_v2/handlers/app_engine.py b/google/cloud/logging_v2/handlers/app_engine.py deleted file mode 100644 index 874a9d608..000000000 --- a/google/cloud/logging_v2/handlers/app_engine.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright 2016 Google LLC All Rights Reserved. -# -# 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. - -"""Logging handler for App Engine Flexible - -Sends logs to the Cloud Logging API with the appropriate resource -and labels for App Engine logs. -""" - -import logging -import os - -from google.cloud.logging_v2.handlers._helpers import get_request_data -from google.cloud.logging_v2.handlers._monitored_resources import ( - _create_app_engine_resource, -) -from google.cloud.logging_v2.handlers.transports import BackgroundThreadTransport - -_DEFAULT_GAE_LOGGER_NAME = "app" - -_GAE_PROJECT_ENV_FLEX = "GCLOUD_PROJECT" -_GAE_PROJECT_ENV_STANDARD = "GOOGLE_CLOUD_PROJECT" -_GAE_SERVICE_ENV = "GAE_SERVICE" -_GAE_VERSION_ENV = "GAE_VERSION" - -_TRACE_ID_LABEL = "appengine.googleapis.com/trace_id" - - -class AppEngineHandler(logging.StreamHandler): - """A logging handler that sends App Engine-formatted logs to Stackdriver.""" - - def __init__( - self, - client, - *, - name=_DEFAULT_GAE_LOGGER_NAME, - transport=BackgroundThreadTransport, - stream=None, - ): - """ - Args: - client (~logging_v2.client.Client): The authenticated - Google Cloud Logging client for this handler to use. - name (Optional[str]): Name for the logger. - transport (Optional[~logging_v2.transports.Transport]): - The transport class. It should be a subclass - of :class:`.Transport`. If unspecified, - :class:`.BackgroundThreadTransport` will be used. - stream (Optional[IO]): Stream to be used by the handler. - - """ - super(AppEngineHandler, self).__init__(stream) - self.name = name - self.client = client - self.transport = transport(client, name) - self.project_id = os.environ.get( - _GAE_PROJECT_ENV_FLEX, os.environ.get(_GAE_PROJECT_ENV_STANDARD, "") - ) - self.module_id = os.environ.get(_GAE_SERVICE_ENV, "") - self.version_id = os.environ.get(_GAE_VERSION_ENV, "") - self.resource = self.get_gae_resource() - - def get_gae_resource(self): - """Return the GAE resource using the environment variables. - - Returns: - google.cloud.logging_v2.resource.Resource: Monitored resource for GAE. - """ - return _create_app_engine_resource() - - def get_gae_labels(self): - """Return the labels for GAE app. - - If the trace ID can be detected, it will be included as a label. - Currently, no other labels are included. - - Returns: - dict: Labels for GAE app. - """ - gae_labels = {} - - _, trace_id, _ = get_request_data() - if trace_id is not None: - gae_labels[_TRACE_ID_LABEL] = trace_id - - return gae_labels - - def emit(self, record): - """Actually log the specified logging record. - - Overrides the default emit behavior of ``StreamHandler``. - - See https://docs.python.org/2/library/logging.html#handler-objects - - Args: - record (logging.LogRecord): The record to be logged. - """ - message = super(AppEngineHandler, self).format(record) - inferred_http, inferred_trace, _ = get_request_data() - if inferred_trace is not None: - inferred_trace = f"projects/{self.project_id}/traces/{inferred_trace}" - # allow user overrides - trace = getattr(record, "trace", inferred_trace) - span_id = getattr(record, "span_id", None) - http_request = getattr(record, "http_request", inferred_http) - resource = getattr(record, "resource", self.resource) - user_labels = getattr(record, "labels", {}) - # merge labels - gae_labels = self.get_gae_labels() - gae_labels.update(user_labels) - # send off request - self.transport.send( - record, - message, - resource=resource, - labels=gae_labels, - trace=trace, - span_id=span_id, - http_request=http_request, - ) diff --git a/google/cloud/logging_v2/handlers/container_engine.py b/google/cloud/logging_v2/handlers/container_engine.py deleted file mode 100644 index a4bd0f848..000000000 --- a/google/cloud/logging_v2/handlers/container_engine.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2016 Google LLC All Rights Reserved. -# -# 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. - -"""Logging handler for Google Container Engine (GKE). - -Formats log messages in a JSON format, so that Kubernetes clusters with the -fluentd Google Cloud plugin installed can format their log messages so that -metadata such as log level is properly captured. -""" - -import logging.handlers - -from google.cloud.logging_v2.handlers._helpers import format_stackdriver_json - - -class ContainerEngineHandler(logging.StreamHandler): - """Handler to format log messages the format expected by GKE fluent. - - This handler is written to format messages for the Google Container Engine - (GKE) fluentd plugin, so that metadata such as log level are properly set. - """ - - def __init__(self, *, name=None, stream=None): - """ - Args: - name (Optional[str]): The name of the custom log in Cloud Logging. - stream (Optional[IO]): Stream to be used by the handler. - - """ - super(ContainerEngineHandler, self).__init__(stream=stream) - self.name = name - - def format(self, record): - """Format the message into JSON expected by fluentd. - - Args: - record (logging.LogRecord): The log record. - - Returns: - str: A JSON string formatted for GKE fluentd. - """ - message = super(ContainerEngineHandler, self).format(record) - return format_stackdriver_json(record, message) From f6f70afd82b85dfe1e1dc6adee13996776a960e5 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 12:31:27 -0700 Subject: [PATCH 02/19] removed stackdriver formatter --- google/cloud/logging_v2/handlers/_helpers.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/google/cloud/logging_v2/handlers/_helpers.py b/google/cloud/logging_v2/handlers/_helpers.py index 931b7a2f5..c08735559 100644 --- a/google/cloud/logging_v2/handlers/_helpers.py +++ b/google/cloud/logging_v2/handlers/_helpers.py @@ -34,24 +34,6 @@ _PROTOCOL_HEADER = "SERVER_PROTOCOL" -def format_stackdriver_json(record, message): - """Helper to format a LogRecord in in Stackdriver fluentd format. - - Returns: - str: JSON str to be written to the log file. - """ - subsecond, second = math.modf(record.created) - - payload = { - "message": message, - "timestamp": {"seconds": int(second), "nanos": int(subsecond * 1e9)}, - "thread": record.thread, - "severity": record.levelname, - } - - return json.dumps(payload, ensure_ascii=False) - - def get_request_data_from_flask(): """Get http_request and trace data from flask request headers. From 761a4c00028dd646b1897358212390b2973ce9e8 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 13:31:11 -0700 Subject: [PATCH 03/19] unit tests pass --- tests/unit/handlers/test_app_engine.py | 223 ------------------- tests/unit/handlers/test_container_engine.py | 56 ----- tests/unit/test_client.py | 8 +- 3 files changed, 4 insertions(+), 283 deletions(-) delete mode 100644 tests/unit/handlers/test_app_engine.py delete mode 100644 tests/unit/handlers/test_container_engine.py diff --git a/tests/unit/handlers/test_app_engine.py b/tests/unit/handlers/test_app_engine.py deleted file mode 100644 index c726c8496..000000000 --- a/tests/unit/handlers/test_app_engine.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright 2016 Google LLC All Rights Reserved. -# -# 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 logging -import unittest - -import mock - - -class TestAppEngineHandler(unittest.TestCase): - PROJECT = "PROJECT" - - def _get_target_class(self): - from google.cloud.logging.handlers import AppEngineHandler - - return AppEngineHandler - - def _make_one(self, *args, **kw): - return self._get_target_class()(*args, **kw) - - def test_constructor_w_gae_standard_env(self): - import sys - from google.cloud.logging_v2.handlers import app_engine - - client = mock.Mock(project=self.PROJECT, spec=["project"]) - - # Verify that project/service/version are picked up from the - # environment. - with mock.patch( - "os.environ", - new={ - app_engine._GAE_SERVICE_ENV: "test_service", - app_engine._GAE_VERSION_ENV: "test_version", - }, - ), mock.patch( - "google.cloud.logging_v2.handlers._monitored_resources.retrieve_metadata_server", - return_value=self.PROJECT, - ): - handler = self._make_one(client, transport=_Transport) - - self.assertIs(handler.client, client) - self.assertEqual(handler.name, app_engine._DEFAULT_GAE_LOGGER_NAME) - self.assertEqual(handler.resource.type, "gae_app") - self.assertEqual(handler.resource.labels["project_id"], self.PROJECT) - self.assertEqual(handler.resource.labels["module_id"], "test_service") - self.assertEqual(handler.resource.labels["version_id"], "test_version") - self.assertIs(handler.stream, sys.stderr) - - def test_constructor_w_gae_flex_env(self): - import io - from google.cloud.logging_v2.handlers import app_engine - - client = mock.Mock(project=self.PROJECT, spec=["project"]) - name = "test-logger" - stream = io.BytesIO() - - # Verify that _GAE_PROJECT_ENV_FLEX environment variable takes - # precedence over _GAE_PROJECT_ENV_STANDARD. - with mock.patch( - "os.environ", - new={ - app_engine._GAE_PROJECT_ENV_FLEX: "test_project_2", - app_engine._GAE_PROJECT_ENV_STANDARD: "test_project_should_be_overridden", - app_engine._GAE_SERVICE_ENV: "test_service_2", - app_engine._GAE_VERSION_ENV: "test_version_2", - }, - ), mock.patch( - "google.cloud.logging_v2.handlers._monitored_resources.retrieve_metadata_server", - return_value=self.PROJECT, - ): - handler = self._make_one( - client, name=name, transport=_Transport, stream=stream - ) - - self.assertIs(handler.client, client) - self.assertEqual(handler.name, name) - self.assertEqual(handler.resource.type, "gae_app") - self.assertEqual(handler.resource.labels["project_id"], self.PROJECT) - self.assertEqual(handler.resource.labels["module_id"], "test_service_2") - self.assertEqual(handler.resource.labels["version_id"], "test_version_2") - self.assertIs(handler.stream, stream) - - def test_emit(self): - expected_http_request = {"request_url": "test"} - trace_id = "trace-test" - expected_trace_id = f"projects/{self.PROJECT}/traces/{trace_id}" - get_request_patch = mock.patch( - "google.cloud.logging_v2.handlers.app_engine.get_request_data", - return_value=(expected_http_request, trace_id, None), - ) - with get_request_patch: - # library integrations mocked to return test data - client = mock.Mock(project=self.PROJECT, spec=["project"]) - handler = self._make_one(client, transport=_Transport) - gae_resource = handler.get_gae_resource() - gae_labels = handler.get_gae_labels() - logname = "app" - message = "hello world" - record = logging.LogRecord( - logname, logging, None, None, message, None, None - ) - handler.project_id = self.PROJECT - handler.emit(record) - - self.assertIs(handler.transport.client, client) - self.assertEqual(handler.transport.name, logname) - self.assertEqual( - handler.transport.send_called_with, - ( - record, - message, - gae_resource, - gae_labels, - expected_trace_id, - None, - expected_http_request, - ), - ) - - def test_emit_manual_field_override(self): - from google.cloud.logging_v2.resource import Resource - - inferred_http_request = {"request_url": "test"} - inferred_trace_id = "trace-test" - get_request_patch = mock.patch( - "google.cloud.logging_v2.handlers.app_engine.get_request_data", - return_value=(inferred_http_request, inferred_trace_id, None), - ) - with get_request_patch: - # library integrations mocked to return test data - client = mock.Mock(project=self.PROJECT, spec=["project"]) - handler = self._make_one(client, transport=_Transport) - gae_labels = handler.get_gae_labels() - logname = "app" - message = "hello world" - record = logging.LogRecord( - logname, logging, None, None, message, None, None - ) - handler.project_id = self.PROJECT - # set attributes manually - expected_trace = "123" - setattr(record, "trace", expected_trace) - expected_span = "456" - setattr(record, "span_id", expected_span) - expected_http = {"reuqest_url": "manual"} - setattr(record, "http_request", expected_http) - expected_resource = Resource(type="test", labels={}) - setattr(record, "resource", expected_resource) - additional_labels = {"test-label": "manual"} - expected_labels = dict(gae_labels) - expected_labels.update(additional_labels) - setattr(record, "labels", additional_labels) - handler.emit(record) - self.assertIs(handler.transport.client, client) - self.assertEqual(handler.transport.name, logname) - self.assertEqual( - handler.transport.send_called_with, - ( - record, - message, - expected_resource, - expected_labels, - expected_trace, - expected_span, - expected_http, - ), - ) - - def _get_gae_labels_helper(self, trace_id): - get_request_patch = mock.patch( - "google.cloud.logging_v2.handlers.app_engine.get_request_data", - return_value=(None, trace_id, None), - ) - - client = mock.Mock(project=self.PROJECT, spec=["project"]) - # The handler actually calls ``get_gae_labels()``. - with get_request_patch as mock_get_request: - handler = self._make_one(client, transport=_Transport) - - gae_labels = handler.get_gae_labels() - self.assertEqual(mock_get_request.mock_calls, [mock.call()]) - - return gae_labels - - def test_get_gae_labels_with_label(self): - from google.cloud.logging_v2.handlers import app_engine - - trace_id = "test-gae-trace-id" - gae_labels = self._get_gae_labels_helper(trace_id) - expected_labels = {app_engine._TRACE_ID_LABEL: trace_id} - self.assertEqual(gae_labels, expected_labels) - - def test_get_gae_labels_without_label(self): - gae_labels = self._get_gae_labels_helper(None) - self.assertEqual(gae_labels, {}) - - -class _Transport(object): - def __init__(self, client, name): - self.client = client - self.name = name - - def send(self, record, message, resource, labels, trace, span_id, http_request): - self.send_called_with = ( - record, - message, - resource, - labels, - trace, - span_id, - http_request, - ) diff --git a/tests/unit/handlers/test_container_engine.py b/tests/unit/handlers/test_container_engine.py deleted file mode 100644 index 280ab9cf0..000000000 --- a/tests/unit/handlers/test_container_engine.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2016 Google LLC All Rights Reserved. -# -# 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 unittest - - -class TestContainerEngineHandler(unittest.TestCase): - PROJECT = "PROJECT" - - def _get_target_class(self): - from google.cloud.logging.handlers import ContainerEngineHandler - - return ContainerEngineHandler - - def _make_one(self, *args, **kw): - return self._get_target_class()(*args, **kw) - - def test_ctor_defaults(self): - handler = self._make_one() - self.assertIsNone(handler.name) - - def test_ctor_w_name(self): - handler = self._make_one(name="foo") - self.assertEqual(handler.name, "foo") - - def test_format(self): - import logging - import json - - handler = self._make_one() - logname = "loggername" - message = "hello world,嗨 世界" - record = logging.LogRecord( - logname, logging.INFO, None, None, message, None, None - ) - record.created = 5.03 - expected_payload = { - "message": message, - "timestamp": {"seconds": 5, "nanos": int(0.03 * 1e9)}, - "thread": record.thread, - "severity": record.levelname, - } - payload = handler.format(record) - - self.assertEqual(payload, json.dumps(expected_payload, ensure_ascii=False)) diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index 9dbfa87fd..11ccd7e37 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.py @@ -719,7 +719,7 @@ def test_get_default_handler_app_engine(self): import os from google.cloud._testing import _Monkey from google.cloud.logging_v2.handlers._monitored_resources import _GAE_ENV_VARS - from google.cloud.logging.handlers import AppEngineHandler + from google.cloud.logging.handlers import CloudLoggingHandler credentials = _make_credentials() client = self._make_one( @@ -733,10 +733,10 @@ def test_get_default_handler_app_engine(self): handler.transport.worker.stop() - self.assertIsInstance(handler, AppEngineHandler) + self.assertIsInstance(handler, CloudLoggingHandler) def test_get_default_handler_container_engine(self): - from google.cloud.logging.handlers import ContainerEngineHandler + from google.cloud.logging.handlers import StructuredLogHandler credentials = _make_credentials() client = self._make_one( @@ -751,7 +751,7 @@ def test_get_default_handler_container_engine(self): with patch: handler = client.get_default_handler() - self.assertIsInstance(handler, ContainerEngineHandler) + self.assertIsInstance(handler, StructuredLogHandler) def test_get_default_handler_general(self): import io From cf789ed7158066b2fcffac1f15757e787e0877a9 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 13:37:41 -0700 Subject: [PATCH 04/19] fixed system tests --- tests/system/test_system.py | 62 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/tests/system/test_system.py b/tests/system/test_system.py index cc6d03804..161ad4f04 100644 --- a/tests/system/test_system.py +++ b/tests/system/test_system.py @@ -30,7 +30,6 @@ from google.api_core.exceptions import ServiceUnavailable import google.cloud.logging from google.cloud._helpers import UTC -from google.cloud.logging_v2.handlers import AppEngineHandler from google.cloud.logging_v2.handlers import CloudLoggingHandler from google.cloud.logging_v2.handlers.transports import SyncTransport from google.cloud.logging_v2 import client @@ -320,37 +319,36 @@ def test_log_handler_sync(self): def test_handlers_w_extras(self): LOG_MESSAGE = "Testing with injected extras." - for cls in [CloudLoggingHandler, AppEngineHandler]: - LOGGER_NAME = f"{cls.__name__}-handler_extras" - handler_name = self._logger_name(LOGGER_NAME) - - handler = cls(Config.CLIENT, name=handler_name, transport=SyncTransport) - - # only create the logger to delete, hidden otherwise - logger = Config.CLIENT.logger(handler.name) - self.to_delete.append(logger) - - cloud_logger = logging.getLogger(LOGGER_NAME) - cloud_logger.addHandler(handler) - expected_request = {"requestUrl": "localhost"} - expected_source = {"file": "test.py"} - extra = { - "trace": "123", - "span_id": "456", - "http_request": expected_request, - "source_location": expected_source, - "resource": Resource(type="cloudiot_device", labels={}), - "labels": {"test-label": "manual"}, - } - cloud_logger.warn(LOG_MESSAGE, extra=extra) - - entries = _list_entries(logger) - self.assertEqual(len(entries), 1) - self.assertEqual(entries[0].trace, extra["trace"]) - self.assertEqual(entries[0].span_id, extra["span_id"]) - self.assertEqual(entries[0].http_request, expected_request) - self.assertEqual(entries[0].labels, extra["labels"]) - self.assertEqual(entries[0].resource.type, extra["resource"].type) + LOGGER_NAME = f"handler_extras" + handler_name = self._logger_name(LOGGER_NAME) + + handler = CloudLoggingHandler(Config.CLIENT, name=handler_name, transport=SyncTransport) + + # only create the logger to delete, hidden otherwise + logger = Config.CLIENT.logger(handler.name) + self.to_delete.append(logger) + + cloud_logger = logging.getLogger(LOGGER_NAME) + cloud_logger.addHandler(handler) + expected_request = {"requestUrl": "localhost"} + expected_source = {"file": "test.py"} + extra = { + "trace": "123", + "span_id": "456", + "http_request": expected_request, + "source_location": expected_source, + "resource": Resource(type="cloudiot_device", labels={}), + "labels": {"test-label": "manual"}, + } + cloud_logger.warn(LOG_MESSAGE, extra=extra) + + entries = _list_entries(logger) + self.assertEqual(len(entries), 1) + self.assertEqual(entries[0].trace, extra["trace"]) + self.assertEqual(entries[0].span_id, extra["span_id"]) + self.assertEqual(entries[0].http_request, expected_request) + self.assertEqual(entries[0].labels, extra["labels"]) + self.assertEqual(entries[0].resource.type, extra["resource"].type) def test_log_root_handler(self): LOG_MESSAGE = "It was the best of times." From f6cb335704842e209d7354902546f5b50805dd7e Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 13:46:25 -0700 Subject: [PATCH 05/19] added CloudLoggingHandler support for GAE trace label --- google/cloud/logging_v2/client.py | 4 +++- google/cloud/logging_v2/handlers/handlers.py | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/google/cloud/logging_v2/client.py b/google/cloud/logging_v2/client.py index 5163d680f..ef75845ef 100644 --- a/google/cloud/logging_v2/client.py +++ b/google/cloud/logging_v2/client.py @@ -349,7 +349,9 @@ def get_default_handler(self, **kw): monitored_resource = kw.pop("resource", detect_resource(self.project)) if isinstance(monitored_resource, Resource): - if monitored_resource.type == _GKE_RESOURCE_TYPE: + if monitored_resource.type == _GAE_RESOURCE_TYPE: + CloudLoggingHandler(self, resource=monitored_resource, include_gae_labels=True, **kw) + elif monitored_resource.type == _GKE_RESOURCE_TYPE: return StructuredLogHandler(**kw, project_id=self.project) elif ( monitored_resource.type == _GCF_RESOURCE_TYPE diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index b3b787fe2..5914d6ce8 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -35,6 +35,7 @@ _CLEAR_HANDLER_RESOURCE_TYPES = ("gae_app", "cloud_function") +_GAE_TRACE_ID_LABEL = "appengine.googleapis.com/trace_id" class CloudLoggingFilter(logging.Filter): """Python standard ``logging`` Filter class to add Cloud Logging @@ -146,6 +147,7 @@ def __init__( resource=_GLOBAL_RESOURCE, labels=None, stream=None, + include_gae_labels=False, ): """ Args: @@ -165,6 +167,7 @@ def __init__( Resource for this Handler. Defaults to ``global``. labels (Optional[dict]): Additional labels to attach to logs. stream (Optional[IO]): Stream to be used by the handler. + include_gae_labels (Optional[bool]): If true, logs will include the "appengine.googleapis.com/trace_id" label """ super(CloudLoggingHandler, self).__init__(stream) self.name = name @@ -188,12 +191,15 @@ def emit(self, record): record (logging.LogRecord): The record to be logged. """ message = super(CloudLoggingHandler, self).format(record) + labels = record._labels or {} + if self.include_gae_labels and record._trace is not None: + labels[_GAE_TRACE_ID_LABEL] = record._trace # send off request self.transport.send( record, message, resource=(record._resource or self.resource), - labels=record._labels, + labels=labels, trace=record._trace, span_id=record._span_id, http_request=record._http_request, From c6b2b05fe601992600be630ba8ad192744e0b378 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:03:23 -0700 Subject: [PATCH 06/19] fixed missing reference --- google/cloud/logging_v2/handlers/handlers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index 5914d6ce8..7e99acc36 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -176,6 +176,7 @@ def __init__( self.project_id = client.project self.resource = resource self.labels = labels + self.include_gae_labels = include_gae_labels # add extra keys to log record log_filter = CloudLoggingFilter(project=self.project_id, default_labels=labels) self.addFilter(log_filter) @@ -191,8 +192,8 @@ def emit(self, record): record (logging.LogRecord): The record to be logged. """ message = super(CloudLoggingHandler, self).format(record) - labels = record._labels or {} - if self.include_gae_labels and record._trace is not None: + labels = record._labels + if self.include_gae_labels and record._trace and labels: labels[_GAE_TRACE_ID_LABEL] = record._trace # send off request self.transport.send( From a7bec22cb1dd3eb617bbd5e939e7dda525c19134 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:03:44 -0700 Subject: [PATCH 07/19] removed unsupported http_request fields --- google/cloud/logging_v2/handlers/_helpers.py | 13 ------------- google/cloud/logging_v2/handlers/handlers.py | 11 ----------- 2 files changed, 24 deletions(-) diff --git a/google/cloud/logging_v2/handlers/_helpers.py b/google/cloud/logging_v2/handlers/_helpers.py index c08735559..17be05527 100644 --- a/google/cloud/logging_v2/handlers/_helpers.py +++ b/google/cloud/logging_v2/handlers/_helpers.py @@ -50,10 +50,7 @@ def get_request_data_from_flask(): http_request = { "requestMethod": flask.request.method, "requestUrl": flask.request.url, - "requestSize": flask.request.content_length, "userAgent": flask.request.user_agent.string, - "remoteIp": flask.request.remote_addr, - "referer": flask.request.referrer, "protocol": flask.request.environ.get(_PROTOCOL_HEADER), } @@ -78,21 +75,11 @@ def get_request_data_from_django(): if request is None: return None, None, None - # convert content_length to int if it exists - content_length = None - try: - content_length = int(request.META.get(_DJANGO_CONTENT_LENGTH)) - except (ValueError, TypeError): - content_length = None - # build http_request http_request = { "requestMethod": request.method, "requestUrl": request.build_absolute_uri(), - "requestSize": content_length, "userAgent": request.META.get(_DJANGO_USERAGENT_HEADER), - "remoteIp": request.META.get(_DJANGO_REMOTE_ADDR_HEADER), - "referer": request.META.get(_DJANGO_REFERER_HEADER), "protocol": request.META.get(_PROTOCOL_HEADER), } diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index 7e99acc36..08191026f 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -46,10 +46,6 @@ class CloudLoggingFilter(logging.Filter): overwritten using the `extras` argument when writing logs. """ - # The subset of http_request fields have been tested to work consistently across GCP environments - # https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#httprequest - _supported_http_fields = ("requestMethod", "requestUrl", "userAgent", "protocol") - def __init__(self, project=None, default_labels=None): self.project = project self.default_labels = default_labels if default_labels else {} @@ -81,13 +77,6 @@ def filter(self, record): user_labels = getattr(record, "labels", {}) # infer request data from the environment inferred_http, inferred_trace, inferred_span = get_request_data() - if inferred_http is not None: - # filter inferred_http to include only well-supported fields - inferred_http = { - k: v - for (k, v) in inferred_http.items() - if k in self._supported_http_fields and v is not None - } if inferred_trace is not None and self.project is not None: # add full path for detected trace inferred_trace = f"projects/{self.project}/traces/{inferred_trace}" From d62c421156185f4aa57009f9abf8ca0f26b91fef Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:04:07 -0700 Subject: [PATCH 08/19] updated environment tests --- tests/environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/environment b/tests/environment index 30d6a8083..38c739e71 160000 --- a/tests/environment +++ b/tests/environment @@ -1 +1 @@ -Subproject commit 30d6a80838a1cae6fb3945f41f3e1d90e815c0c9 +Subproject commit 38c739e716e48397cae30035bd127785d75949e9 From 0b8ecde7d8717c76354a10974cb6976a35673a28 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:09:01 -0700 Subject: [PATCH 09/19] lint fixes --- google/cloud/logging_v2/client.py | 4 +++- google/cloud/logging_v2/handlers/_helpers.py | 2 -- google/cloud/logging_v2/handlers/handlers.py | 1 + tests/system/test_system.py | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/google/cloud/logging_v2/client.py b/google/cloud/logging_v2/client.py index ef75845ef..e1750687f 100644 --- a/google/cloud/logging_v2/client.py +++ b/google/cloud/logging_v2/client.py @@ -350,7 +350,9 @@ def get_default_handler(self, **kw): if isinstance(monitored_resource, Resource): if monitored_resource.type == _GAE_RESOURCE_TYPE: - CloudLoggingHandler(self, resource=monitored_resource, include_gae_labels=True, **kw) + CloudLoggingHandler( + self, resource=monitored_resource, include_gae_labels=True, **kw + ) elif monitored_resource.type == _GKE_RESOURCE_TYPE: return StructuredLogHandler(**kw, project_id=self.project) elif ( diff --git a/google/cloud/logging_v2/handlers/_helpers.py b/google/cloud/logging_v2/handlers/_helpers.py index 17be05527..ce7da3bd9 100644 --- a/google/cloud/logging_v2/handlers/_helpers.py +++ b/google/cloud/logging_v2/handlers/_helpers.py @@ -14,8 +14,6 @@ """Helper functions for logging handlers.""" -import math -import json import re try: diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index 08191026f..e351481af 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -37,6 +37,7 @@ _GAE_TRACE_ID_LABEL = "appengine.googleapis.com/trace_id" + class CloudLoggingFilter(logging.Filter): """Python standard ``logging`` Filter class to add Cloud Logging information to each LogRecord. diff --git a/tests/system/test_system.py b/tests/system/test_system.py index 161ad4f04..fb9fd6692 100644 --- a/tests/system/test_system.py +++ b/tests/system/test_system.py @@ -319,10 +319,12 @@ def test_log_handler_sync(self): def test_handlers_w_extras(self): LOG_MESSAGE = "Testing with injected extras." - LOGGER_NAME = f"handler_extras" + LOGGER_NAME = "handler_extras" handler_name = self._logger_name(LOGGER_NAME) - handler = CloudLoggingHandler(Config.CLIENT, name=handler_name, transport=SyncTransport) + handler = CloudLoggingHandler( + Config.CLIENT, name=handler_name, transport=SyncTransport + ) # only create the logger to delete, hidden otherwise logger = Config.CLIENT.logger(handler.name) From 6ce4b9ebf1a3fc8b9f38d40ad20082b60a8070f5 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Thu, 13 May 2021 21:13:12 +0000 Subject: [PATCH 10/19] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- google/cloud/logging_v2/client.py | 4 +++- google/cloud/logging_v2/handlers/handlers.py | 1 + tests/system/test_system.py | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/google/cloud/logging_v2/client.py b/google/cloud/logging_v2/client.py index ef75845ef..e1750687f 100644 --- a/google/cloud/logging_v2/client.py +++ b/google/cloud/logging_v2/client.py @@ -350,7 +350,9 @@ def get_default_handler(self, **kw): if isinstance(monitored_resource, Resource): if monitored_resource.type == _GAE_RESOURCE_TYPE: - CloudLoggingHandler(self, resource=monitored_resource, include_gae_labels=True, **kw) + CloudLoggingHandler( + self, resource=monitored_resource, include_gae_labels=True, **kw + ) elif monitored_resource.type == _GKE_RESOURCE_TYPE: return StructuredLogHandler(**kw, project_id=self.project) elif ( diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index 08191026f..e351481af 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -37,6 +37,7 @@ _GAE_TRACE_ID_LABEL = "appengine.googleapis.com/trace_id" + class CloudLoggingFilter(logging.Filter): """Python standard ``logging`` Filter class to add Cloud Logging information to each LogRecord. diff --git a/tests/system/test_system.py b/tests/system/test_system.py index 161ad4f04..cc06f0b91 100644 --- a/tests/system/test_system.py +++ b/tests/system/test_system.py @@ -322,7 +322,9 @@ def test_handlers_w_extras(self): LOGGER_NAME = f"handler_extras" handler_name = self._logger_name(LOGGER_NAME) - handler = CloudLoggingHandler(Config.CLIENT, name=handler_name, transport=SyncTransport) + handler = CloudLoggingHandler( + Config.CLIENT, name=handler_name, transport=SyncTransport + ) # only create the logger to delete, hidden otherwise logger = Config.CLIENT.logger(handler.name) From 6aea173db3d7319385ca7b7647752addae03e975 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:35:03 -0700 Subject: [PATCH 11/19] fixed docs --- docs/handlers-app-engine.rst | 6 ------ docs/handlers-container-engine.rst | 6 ------ docs/handlers-structured-log.rst | 6 ++++++ docs/usage.rst | 15 +++++---------- 4 files changed, 11 insertions(+), 22 deletions(-) delete mode 100644 docs/handlers-app-engine.rst delete mode 100644 docs/handlers-container-engine.rst create mode 100644 docs/handlers-structured-log.rst diff --git a/docs/handlers-app-engine.rst b/docs/handlers-app-engine.rst deleted file mode 100644 index f25223a20..000000000 --- a/docs/handlers-app-engine.rst +++ /dev/null @@ -1,6 +0,0 @@ -Google App Engine flexible Log Handler -====================================== - -.. automodule:: google.cloud.logging_v2.handlers.app_engine - :members: - :show-inheritance: diff --git a/docs/handlers-container-engine.rst b/docs/handlers-container-engine.rst deleted file mode 100644 index 981b41dcb..000000000 --- a/docs/handlers-container-engine.rst +++ /dev/null @@ -1,6 +0,0 @@ -Google Kubernetes Engine Log Handler -==================================== - -.. automodule:: google.cloud.logging_v2.handlers.container_engine - :members: - :show-inheritance: diff --git a/docs/handlers-structured-log.rst b/docs/handlers-structured-log.rst new file mode 100644 index 000000000..77e9c0c84 --- /dev/null +++ b/docs/handlers-structured-log.rst @@ -0,0 +1,6 @@ +Structured Log Handler +==================================== + +.. automodule:: google.cloud.logging_v2.handlers.structured_log + :members: + :show-inheritance: diff --git a/docs/usage.rst b/docs/usage.rst index 1ea9440fc..037a41b55 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -327,19 +327,14 @@ logging handler can use different transports. The default is fluentd logging handlers ~~~~~~~~~~~~~~~~~~~~~~~~ -Besides :class:`~google.cloud.logging.handlers.handlers.CloudLoggingHandler`, -which writes directly to the API, two other handlers are provided. -:class:`~google.cloud.logging.handlers.app_engine.AppEngineHandler`, which is -recommended when running on the Google App Engine Flexible vanilla runtimes -(i.e. your app.yaml contains ``runtime: python``), and -:class:`~google.cloud.logging.handlers.container_engine.ContainerEngineHandler` -, which is recommended when running on `Google Kubernetes Engine`_ with the -Cloud Logging plugin enabled. +Two handler classes are provided: :class:`~google.cloud.logging.handlers.handlers.CloudLoggingHandler`, +which writes directly to the API, and :class:`~google.cloud.logging.handlers.structured_log.StructuredLogHandler`, +which writes logs as structured JSON to standard output (to be later parsed by the environment). :meth:`~google.cloud.logging.client.Client.get_default_handler` and :meth:`~google.cloud.logging.client.Client.setup_logging` will attempt to use -the environment to automatically detect whether the code is running in -these platforms and use the appropriate handler. +the environment to automatically detect where the code is running and use the +appropriate handler. In both cases, the fluentd agent is configured to automatically parse log files in an expected format and forward them to Cloud Logging. The handlers From 7b77ef033181de22948b562e556c1a606e827bf3 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:38:12 -0700 Subject: [PATCH 12/19] updated environment tests --- tests/environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/environment b/tests/environment index 38c739e71..add5a2e2c 160000 --- a/tests/environment +++ b/tests/environment @@ -1 +1 @@ -Subproject commit 38c739e716e48397cae30035bd127785d75949e9 +Subproject commit add5a2e2cd6680cea7fc91fdb31419901fd551e0 From 5576128a6ad82002eaeebf0cbbc119efab848495 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 13 May 2021 14:52:33 -0700 Subject: [PATCH 13/19] fixed docs issue --- docs/v2.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/v2.rst b/docs/v2.rst index 823097bd7..78fa01097 100644 --- a/docs/v2.rst +++ b/docs/v2.rst @@ -12,8 +12,7 @@ v2 sink stdlib-usage handlers - handlers-app-engine - handlers-container-engine + handlers-structured-log transports-sync transports-thread transports-base From db7c131d7afe7a156eb52cffdef5b0fbe79154e8 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Mon, 17 May 2021 13:50:20 -0700 Subject: [PATCH 14/19] updated environment test --- tests/environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/environment b/tests/environment index add5a2e2c..708767bdb 160000 --- a/tests/environment +++ b/tests/environment @@ -1 +1 @@ -Subproject commit add5a2e2cd6680cea7fc91fdb31419901fd551e0 +Subproject commit 708767bdb8ba978f6c1300780eaa2cc3da8e1e89 From cc476faef6cfcbf7584c91ac2913b22959b3fba6 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Mon, 17 May 2021 14:07:07 -0700 Subject: [PATCH 15/19] fixed broken appengine tests --- tests/environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/environment b/tests/environment index 708767bdb..3342c1fd6 160000 --- a/tests/environment +++ b/tests/environment @@ -1 +1 @@ -Subproject commit 708767bdb8ba978f6c1300780eaa2cc3da8e1e89 +Subproject commit 3342c1fd600a0f0490bfdbc63c62e8b056f868a9 From 516ab177d70881c21ad972ec19cfc77948d863d8 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Mon, 17 May 2021 14:36:00 -0700 Subject: [PATCH 16/19] fix app engine label addition --- google/cloud/logging_v2/handlers/handlers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index e351481af..cf290fb01 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -183,8 +183,9 @@ def emit(self, record): """ message = super(CloudLoggingHandler, self).format(record) labels = record._labels - if self.include_gae_labels and record._trace and labels: - labels[_GAE_TRACE_ID_LABEL] = record._trace + if self.include_gae_labels and record._trace: + # add GAE-specific label + labels = {_GAE_TRACE_ID_LABEL: record._trace, **(labels or {})} # send off request self.transport.send( record, From bba5737ad1b829bb44993aef3ab1e1d1e9304f82 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Mon, 17 May 2021 17:14:47 -0700 Subject: [PATCH 17/19] changed how app engine label is added --- google/cloud/logging_v2/client.py | 4 +--- google/cloud/logging_v2/handlers/handlers.py | 11 +++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/google/cloud/logging_v2/client.py b/google/cloud/logging_v2/client.py index e1750687f..c169d112d 100644 --- a/google/cloud/logging_v2/client.py +++ b/google/cloud/logging_v2/client.py @@ -350,9 +350,7 @@ def get_default_handler(self, **kw): if isinstance(monitored_resource, Resource): if monitored_resource.type == _GAE_RESOURCE_TYPE: - CloudLoggingHandler( - self, resource=monitored_resource, include_gae_labels=True, **kw - ) + CloudLoggingHandler(self, resource=monitored_resource, **kw) elif monitored_resource.type == _GKE_RESOURCE_TYPE: return StructuredLogHandler(**kw, project_id=self.project) elif ( diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index cf290fb01..92d90e3cb 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -33,10 +33,14 @@ "werkzeug", ) +"""These environments require us to remove extra handlers on setup""" _CLEAR_HANDLER_RESOURCE_TYPES = ("gae_app", "cloud_function") +"""Extra trace label to be added on App Engine environments""" _GAE_TRACE_ID_LABEL = "appengine.googleapis.com/trace_id" +"""Resource name for App Engine environments""" +_GAE_RESOURCE_TYPE = "gae_app" class CloudLoggingFilter(logging.Filter): """Python standard ``logging`` Filter class to add Cloud Logging @@ -157,7 +161,6 @@ def __init__( Resource for this Handler. Defaults to ``global``. labels (Optional[dict]): Additional labels to attach to logs. stream (Optional[IO]): Stream to be used by the handler. - include_gae_labels (Optional[bool]): If true, logs will include the "appengine.googleapis.com/trace_id" label """ super(CloudLoggingHandler, self).__init__(stream) self.name = name @@ -166,7 +169,6 @@ def __init__( self.project_id = client.project self.resource = resource self.labels = labels - self.include_gae_labels = include_gae_labels # add extra keys to log record log_filter = CloudLoggingFilter(project=self.project_id, default_labels=labels) self.addFilter(log_filter) @@ -183,14 +185,15 @@ def emit(self, record): """ message = super(CloudLoggingHandler, self).format(record) labels = record._labels - if self.include_gae_labels and record._trace: + resource = (record._resource or self.resource) + if resource.type == _GAE_RESOURCE_TYPE and record._trace is not None: # add GAE-specific label labels = {_GAE_TRACE_ID_LABEL: record._trace, **(labels or {})} # send off request self.transport.send( record, message, - resource=(record._resource or self.resource), + resource=resource, labels=labels, trace=record._trace, span_id=record._span_id, From 41892af451ecb4c9cfd124ab2a66c0e9aaaaabd0 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Tue, 18 May 2021 00:15:52 +0000 Subject: [PATCH 18/19] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- google/cloud/logging_v2/handlers/handlers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/google/cloud/logging_v2/handlers/handlers.py b/google/cloud/logging_v2/handlers/handlers.py index 92d90e3cb..ad8a345a9 100644 --- a/google/cloud/logging_v2/handlers/handlers.py +++ b/google/cloud/logging_v2/handlers/handlers.py @@ -42,6 +42,7 @@ """Resource name for App Engine environments""" _GAE_RESOURCE_TYPE = "gae_app" + class CloudLoggingFilter(logging.Filter): """Python standard ``logging`` Filter class to add Cloud Logging information to each LogRecord. @@ -185,7 +186,7 @@ def emit(self, record): """ message = super(CloudLoggingHandler, self).format(record) labels = record._labels - resource = (record._resource or self.resource) + resource = record._resource or self.resource if resource.type == _GAE_RESOURCE_TYPE and record._trace is not None: # add GAE-specific label labels = {_GAE_TRACE_ID_LABEL: record._trace, **(labels or {})} From a88f43c67a06a345d94d6910132ef0ea05ee5a73 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Mon, 17 May 2021 17:46:20 -0700 Subject: [PATCH 19/19] updated environment tests --- tests/environment | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/environment b/tests/environment index 3342c1fd6..834e5f4eb 160000 --- a/tests/environment +++ b/tests/environment @@ -1 +1 @@ -Subproject commit 3342c1fd600a0f0490bfdbc63c62e8b056f868a9 +Subproject commit 834e5f4ebd76e2dbabb9237a54f9184964dcda1a