From 38b769a1e82f003a522167f932cfec9a384c6543 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Fri, 28 Oct 2022 13:06:35 -0700 Subject: [PATCH] Add django example (#1170) --- .../examples/traces/django/logfile | 8 + .../examples/traces/django/mysite/db.sqlite3 | 0 .../examples/traces/django/mysite/manage.py | 36 ++++ .../traces/django/mysite/mysite/__init__.py | 13 ++ .../traces/django/mysite/mysite/asgi.py | 29 +++ .../traces/django/mysite/mysite/settings.py | 184 ++++++++++++++++++ .../traces/django/mysite/mysite/urls.py | 35 ++++ .../traces/django/mysite/mysite/wsgi.py | 29 +++ .../traces/django/mysite/polls/__init__.py | 13 ++ .../traces/django/mysite/polls/admin.py | 13 ++ .../traces/django/mysite/polls/apps.py | 19 ++ .../mysite/polls/migrations/__init__.py | 13 ++ .../traces/django/mysite/polls/models.py | 13 ++ .../traces/django/mysite/polls/tests.py | 13 ++ .../traces/django/mysite/polls/urls.py | 20 ++ .../traces/django/mysite/polls/views.py | 29 +++ .../ext/azure/log_exporter/__init__.py | 9 +- .../tests/test_azure_statsbeat_metrics.py | 4 +- 18 files changed, 474 insertions(+), 6 deletions(-) create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/logfile create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/db.sqlite3 create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/manage.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/__init__.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/asgi.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/settings.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/urls.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/wsgi.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/__init__.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/admin.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/apps.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/migrations/__init__.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/models.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/tests.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/urls.py create mode 100644 contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/views.py diff --git a/contrib/opencensus-ext-azure/examples/traces/django/logfile b/contrib/opencensus-ext-azure/examples/traces/django/logfile new file mode 100644 index 000000000..c58b7d762 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/logfile @@ -0,0 +1,8 @@ +2022-10-26 15:48:57,700 INFO This is an INFO level log entry. +2022-10-26 15:48:57,700 WARNING This is a WARNING level log entry. +2022-10-26 15:48:57,701 ERROR This is an ERROR level log entry. +2022-10-26 15:48:57,702 CRITICAL This is a CRITICAL level log entry. +2022-10-26 16:10:22,849 INFO This is an INFO level log entry. +2022-10-26 16:10:22,850 WARNING This is a WARNING level log entry. +2022-10-26 16:10:22,850 ERROR This is an ERROR level log entry. +2022-10-26 16:10:22,850 CRITICAL This is a CRITICAL level log entry. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/db.sqlite3 b/contrib/opencensus-ext-azure/examples/traces/django/mysite/db.sqlite3 new file mode 100644 index 000000000..e69de29bb diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/manage.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/manage.py new file mode 100644 index 000000000..538658793 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/manage.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python + +# Copyright 2019, OpenCensus Authors +# +# 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. +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/__init__.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/__init__.py new file mode 100644 index 000000000..296af4941 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/asgi.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/asgi.py new file mode 100644 index 000000000..4d82b9f8c --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/asgi.py @@ -0,0 +1,29 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. +""" +ASGI config for mysite project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + +application = get_asgi_application() diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/settings.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/settings.py new file mode 100644 index 000000000..da26367f2 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/settings.py @@ -0,0 +1,184 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. +""" +Django settings for mysite project. + +Generated by 'django-admin startproject' using Django 3.2.14. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.2/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'secret_key_for_test' + +ALLOWED_HOSTS = ['*'] + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'opencensus.ext.django.middleware.OpencensusMiddleware', +] + +MY_CONNECTION_STRING = "''" + +OPENCENSUS = { + 'TRACE': { + 'SAMPLER': 'opencensus.trace.samplers.ProbabilitySampler(rate=1.0)', + 'EXPORTER': 'opencensus.ext.azure.trace_exporter.AzureExporter(connection_string=' + MY_CONNECTION_STRING + ')', # noqa: E501 + } +} + +ROOT_URLCONF = 'mysite.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'mysite.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', # noqa: E501 + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', # noqa: E501 + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', # noqa: E501 + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', # noqa: E501 + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.2/howto/static-files/ + +STATIC_URL = '/static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False +ALLOWED_HOSTS = ["*"] + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'timestamp': { + 'format': '{asctime} {levelname} {message}', + 'style': '{', + }, + }, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'timestamp', + }, + 'logfile': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'formatter': 'timestamp', + 'filename': str(BASE_DIR) + "/../logfile", + }, + 'azure': { + 'level': "DEBUG", + 'class': "opencensus.ext.azure.log_exporter.AzureLogHandler", + 'connection_string': MY_CONNECTION_STRING, + 'formatter': 'timestamp', + }, + }, + 'loggers': { + 'custom': { + 'level': 'INFO', + 'handlers': ['console', 'logfile', 'azure'] + } + } +} diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/urls.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/urls.py new file mode 100644 index 000000000..407f10f8b --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/urls.py @@ -0,0 +1,35 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. +"""mysite URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import include, path + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('polls.urls')), +] diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/wsgi.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/wsgi.py new file mode 100644 index 000000000..247a03089 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/mysite/wsgi.py @@ -0,0 +1,29 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. +""" +WSGI config for mysite project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + +application = get_wsgi_application() diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/__init__.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/__init__.py new file mode 100644 index 000000000..296af4941 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/admin.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/admin.py new file mode 100644 index 000000000..296af4941 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/admin.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/apps.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/apps.py new file mode 100644 index 000000000..41e62e385 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/apps.py @@ -0,0 +1,19 @@ +# Copyright 2019, OpenCensus Authors +# +# 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 django.apps import AppConfig + + +class PollsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'polls' diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/migrations/__init__.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/migrations/__init__.py new file mode 100644 index 000000000..296af4941 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/migrations/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/models.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/models.py new file mode 100644 index 000000000..296af4941 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/models.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/tests.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/tests.py new file mode 100644 index 000000000..296af4941 --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/tests.py @@ -0,0 +1,13 @@ +# Copyright 2019, OpenCensus Authors +# +# 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. diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/urls.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/urls.py new file mode 100644 index 000000000..580d73bef --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/urls.py @@ -0,0 +1,20 @@ +# Copyright 2019, OpenCensus Authors +# +# 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 django.urls import path + +from . import views + +urlpatterns = [ + path('', views.index, name='index'), +] diff --git a/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/views.py b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/views.py new file mode 100644 index 000000000..833f77d5e --- /dev/null +++ b/contrib/opencensus-ext-azure/examples/traces/django/mysite/polls/views.py @@ -0,0 +1,29 @@ +# Copyright 2019, OpenCensus Authors +# +# 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 + +from django.http import HttpResponse + +# Logging configured through settings.LOGGING in settings.py +logger = logging.getLogger('custom') + + +# Distributed tracing configured through settings.OPENCENSUS in settings.py +def index(request): + logger.debug('This is a DEBUG level log entry.') + logger.info('This is an INFO level log entry.') + logger.warning('This is a WARNING level log entry.') + logger.error('This is an ERROR level log entry.') + logger.critical('This is a CRITICAL level log entry.') + return HttpResponse("Hello, world. You're at the polls index.") diff --git a/contrib/opencensus-ext-azure/opencensus/ext/azure/log_exporter/__init__.py b/contrib/opencensus-ext-azure/opencensus/ext/azure/log_exporter/__init__.py index 8ccd9a9f3..f837779e3 100644 --- a/contrib/opencensus-ext-azure/opencensus/ext/azure/log_exporter/__init__.py +++ b/contrib/opencensus-ext-azure/opencensus/ext/azure/log_exporter/__init__.py @@ -94,11 +94,11 @@ def _export(self, batch, event=None): # pragma: NO COVER # Close is automatically called as part of logging shutdown def close(self, timeout=None): - if not timeout: + if not timeout and hasattr(self, "options"): timeout = self.options.grace_period - if self.storage: + if hasattr(self, "storage") and self.storage: self.storage.close() - if self._worker: + if hasattr(self, "_worker") and self._worker: self._worker.stop(timeout) super(BaseLogHandler, self).close() @@ -111,8 +111,9 @@ def emit(self, record): def log_record_to_envelope(self, record): raise NotImplementedError # pragma: NO COVER + # Flush is automatically called as part of logging shutdown def flush(self, timeout=None): - if self._queue.is_empty(): + if not hasattr(self, "_queue") or self._queue.is_empty(): return # We must check the worker thread is alive, because otherwise flush diff --git a/contrib/opencensus-ext-azure/tests/test_azure_statsbeat_metrics.py b/contrib/opencensus-ext-azure/tests/test_azure_statsbeat_metrics.py index 5af29168f..9ae366a95 100644 --- a/contrib/opencensus-ext-azure/tests/test_azure_statsbeat_metrics.py +++ b/contrib/opencensus-ext-azure/tests/test_azure_statsbeat_metrics.py @@ -690,7 +690,7 @@ def test_get_attach_metric_vm(self): _vm_data["subscriptionId"] = "sub123" _vm_data["osType"] = "linux" stats._vm_data = _vm_data - self._vm_retry = True + stats._vm_retry = True metadata_mock = mock.Mock() metadata_mock.return_value = True stats._get_azure_compute_metadata = metadata_mock @@ -714,7 +714,7 @@ def test_get_attach_metric_vm_no_os(self): _vm_data["subscriptionId"] = "sub123" _vm_data["osType"] = None stats._vm_data = _vm_data - self._vm_retry = True + stats._vm_retry = True metadata_mock = mock.Mock() metadata_mock.return_value = True stats._get_azure_compute_metadata = metadata_mock