Merge branch 'main' into exec-publish
This commit is contained in:
Коммит
1a2beedcbf
1
.flake8
1
.flake8
|
@ -21,6 +21,7 @@ exclude =
|
|||
CVS
|
||||
.venv*/
|
||||
venv*/
|
||||
*/samples/*
|
||||
target
|
||||
__pycache__
|
||||
*/build/lib/*
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
([#217](https://github.com/microsoft/ApplicationInsights-Python/pull/217))
|
||||
- Add Logging configuration to Distro API
|
||||
([#218](https://github.com/microsoft/ApplicationInsights-Python/pull/218))
|
||||
- Add instrumentation selection config
|
||||
([#228](https://github.com/microsoft/ApplicationInsights-Python/pull/228))
|
||||
|
||||
## [1.0.0b8](https://github.com/microsoft/ApplicationInsights-Python/releases/tag/v1.0.0b8) - 2022-09-26
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ pip install azure-monitor-opentelemetry-distro --pre
|
|||
You can use `configure_azure_monitor` to set up instrumentation for your app to Azure Monitor. `configure_azure_monitor` supports the following optional arguments:
|
||||
|
||||
* connection_string - The [connection string][connection_string_doc] for your Application Insights resource. The connection string will be automatically populated from the `APPLICATIONINSIGHTS_CONNECTION_STRING` environment variable if not explicitly passed in.
|
||||
* service_name = Specifies the [service][service_semantic_convention_doc] name.
|
||||
* instrumentations = Specifies the libraries with [instrumentations][ot_instrumentations] that you would like to use. Accepts a comma separated list. e.g. `["requests", "flask"]`
|
||||
* service_name = Specifies the [service][service_semantic_convention_doc] name.
|
||||
* service_namespace = Specifies the [service][service_semantic_convention_doc] namespace.
|
||||
* service_instance_id = Specifies the [service][service_semantic_convention_doc] instance id.
|
||||
* disable_logging = If set to `True`, disables collection and export of logging telemetry.
|
||||
|
@ -66,6 +67,7 @@ To use this package, you must have:
|
|||
[connection_string_doc]: https://learn.microsoft.com/en-us/azure/azure-monitor/app/sdk-connection-string
|
||||
[exporter_configuration_docs]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/monitor/azure-monitor-opentelemetry-exporter#configuration
|
||||
[logging_level]: https://docs.python.org/3/library/logging.html#levels
|
||||
[ot_instrumentations]: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation
|
||||
[ot_python_docs]: https://opentelemetry.io/docs/instrumentation/python/
|
||||
[ot_sdk_python]: https://github.com/open-telemetry/opentelemetry-python
|
||||
[opentelemetry_instrumentation_requests]: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-requests
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
import importlib
|
||||
from logging import NOTSET, getLogger
|
||||
from typing import Any, Dict
|
||||
|
||||
from azure.monitor.opentelemetry.distro.util import get_configurations
|
||||
from azure.monitor.opentelemetry.exporter import (
|
||||
|
@ -24,6 +26,16 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|||
from opentelemetry.semconv.resource import ResourceAttributes
|
||||
from opentelemetry.trace import get_tracer_provider, set_tracer_provider
|
||||
|
||||
_logger = getLogger(__name__)
|
||||
|
||||
|
||||
_SUPPORTED_INSTRUMENTED_LIBRARIES = {
|
||||
"django",
|
||||
"flask",
|
||||
"psycopg2",
|
||||
"requests",
|
||||
}
|
||||
|
||||
|
||||
def configure_azure_monitor(**kwargs):
|
||||
"""
|
||||
|
@ -33,51 +45,110 @@ def configure_azure_monitor(**kwargs):
|
|||
"""
|
||||
|
||||
configurations = get_configurations(**kwargs)
|
||||
|
||||
disable_tracing = configurations.get("disable_tracing", False)
|
||||
disable_logging = configurations.get("disable_logging", False)
|
||||
|
||||
resource = None
|
||||
if not disable_logging or not disable_tracing:
|
||||
resource = _get_resource(configurations)
|
||||
|
||||
# Setup tracing pipeline
|
||||
if not disable_tracing:
|
||||
_setup_tracing(resource, configurations)
|
||||
|
||||
# Setup logging pipeline
|
||||
if not disable_logging:
|
||||
_setup_logging(resource, configurations)
|
||||
|
||||
# Setup instrumentations
|
||||
# Instrumentations need to be setup last so to use the global providers
|
||||
# instanstiated in the other setup steps
|
||||
_setup_instrumentations(configurations)
|
||||
|
||||
|
||||
def _get_resource(configurations: Dict[str, Any]) -> Resource:
|
||||
service_name = configurations.get("service_name", "")
|
||||
service_namespace = configurations.get("service_namespace", "")
|
||||
service_instance_id = configurations.get("service_instance_id", "")
|
||||
disable_logging = configurations.get("disable_logging", False)
|
||||
logging_level = configurations.get("logging_level", NOTSET)
|
||||
logging_export_interval_millis = configurations.get(
|
||||
"logging_export_interval_millis", 30000
|
||||
return Resource.create(
|
||||
{
|
||||
ResourceAttributes.SERVICE_NAME: service_name,
|
||||
ResourceAttributes.SERVICE_NAMESPACE: service_namespace,
|
||||
ResourceAttributes.SERVICE_INSTANCE_ID: service_instance_id,
|
||||
}
|
||||
)
|
||||
disable_tracing = configurations.get("disable_tracing", False)
|
||||
|
||||
|
||||
def _setup_tracing(resource: Resource, configurations: Dict[str, Any]):
|
||||
sampling_ratio = configurations.get("sampling_ratio", 1.0)
|
||||
tracing_export_interval_millis = configurations.get(
|
||||
"tracing_export_interval_millis", 30000
|
||||
)
|
||||
tracer_provider = TracerProvider(
|
||||
sampler=ApplicationInsightsSampler(sampling_ratio=sampling_ratio),
|
||||
resource=resource,
|
||||
)
|
||||
set_tracer_provider(tracer_provider)
|
||||
trace_exporter = AzureMonitorTraceExporter(**configurations)
|
||||
span_processor = BatchSpanProcessor(
|
||||
trace_exporter,
|
||||
export_timeout_millis=tracing_export_interval_millis,
|
||||
)
|
||||
get_tracer_provider().add_span_processor(span_processor)
|
||||
|
||||
resource = None
|
||||
if not disable_logging or not disable_tracing:
|
||||
resource = Resource.create(
|
||||
{
|
||||
ResourceAttributes.SERVICE_NAME: service_name,
|
||||
ResourceAttributes.SERVICE_NAMESPACE: service_namespace,
|
||||
ResourceAttributes.SERVICE_INSTANCE_ID: service_instance_id,
|
||||
}
|
||||
)
|
||||
if not disable_logging:
|
||||
logger_provider = LoggerProvider(resource=resource)
|
||||
set_logger_provider(logger_provider)
|
||||
log_exporter = AzureMonitorLogExporter(**kwargs)
|
||||
log_record_processor = BatchLogRecordProcessor(
|
||||
log_exporter,
|
||||
export_timeout_millis=logging_export_interval_millis,
|
||||
)
|
||||
get_logger_provider().add_log_record_processor(log_record_processor)
|
||||
handler = LoggingHandler(
|
||||
level=logging_level, logger_provider=get_logger_provider()
|
||||
)
|
||||
getLogger().addHandler(handler)
|
||||
if not disable_tracing:
|
||||
tracer_provider = TracerProvider(
|
||||
sampler=ApplicationInsightsSampler(sampling_ratio=sampling_ratio),
|
||||
resource=resource,
|
||||
)
|
||||
set_tracer_provider(tracer_provider)
|
||||
trace_exporter = AzureMonitorTraceExporter(**kwargs)
|
||||
span_processor = BatchSpanProcessor(
|
||||
trace_exporter,
|
||||
export_timeout_millis=tracing_export_interval_millis,
|
||||
)
|
||||
get_tracer_provider().add_span_processor(span_processor)
|
||||
|
||||
def _setup_logging(resource: Resource, configurations: Dict[str, Any]):
|
||||
logging_level = configurations.get("logging_level", NOTSET)
|
||||
logging_export_interval_millis = configurations.get(
|
||||
"logging_export_interval_millis", 30000
|
||||
)
|
||||
logger_provider = LoggerProvider(resource=resource)
|
||||
set_logger_provider(logger_provider)
|
||||
log_exporter = AzureMonitorLogExporter(**configurations)
|
||||
log_record_processor = BatchLogRecordProcessor(
|
||||
log_exporter,
|
||||
export_timeout_millis=logging_export_interval_millis,
|
||||
)
|
||||
get_logger_provider().add_log_record_processor(log_record_processor)
|
||||
handler = LoggingHandler(
|
||||
level=logging_level, logger_provider=get_logger_provider()
|
||||
)
|
||||
getLogger().addHandler(handler)
|
||||
|
||||
|
||||
def _setup_instrumentations(configurations: Dict[str, Any]):
|
||||
instrumentations = configurations.get("instrumentations", [])
|
||||
for lib_name in instrumentations:
|
||||
if lib_name in _SUPPORTED_INSTRUMENTED_LIBRARIES:
|
||||
try:
|
||||
importlib.import_module(lib_name)
|
||||
except ImportError:
|
||||
_logger.warning(
|
||||
"Unable to import %s. Please make sure it is installed.",
|
||||
lib_name,
|
||||
)
|
||||
continue
|
||||
instr_lib_name = "opentelemetry.instrumentation." + lib_name
|
||||
try:
|
||||
module = importlib.import_module(instr_lib_name)
|
||||
instrumentor_name = "{}Instrumentor".format(
|
||||
lib_name.capitalize()
|
||||
)
|
||||
class_ = getattr(module, instrumentor_name)
|
||||
class_().instrument()
|
||||
except ImportError:
|
||||
_logger.warning(
|
||||
"Unable to import %s. Please make sure it is installed.",
|
||||
instr_lib_name,
|
||||
)
|
||||
except Exception as ex:
|
||||
_logger.warning(
|
||||
"Exception occured when instrumenting: %s.",
|
||||
lib_name,
|
||||
exc_info=ex,
|
||||
)
|
||||
else:
|
||||
_logger.warning(
|
||||
"Instrumentation not supported for library: %s.", lib_name
|
||||
)
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
# -------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
import platform
|
||||
from os import environ
|
||||
|
@ -7,11 +13,7 @@ from azure.monitor.opentelemetry.exporter._connection_string_parser import (
|
|||
ConnectionStringParser,
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
# --------------------Diagnostic/status logging------------------------------
|
||||
|
||||
_LOG_PATH_LINUX = "/var/log/applicationinsights"
|
||||
_LOG_PATH_WINDOWS = "\\LogFiles\\ApplicationInsights"
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# -------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from azure.monitor.opentelemetry.distro import configure_azure_monitor
|
||||
from opentelemetry import trace
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Configure Azure monitor collection telemetry pipeline
|
||||
configure_azure_monitor(
|
||||
connection_string="<your-connection-string>",
|
||||
service_name="client_service_name",
|
||||
disable_logging=True,
|
||||
instrumentations=["requests"],
|
||||
tracing_export_interval_millis=15000,
|
||||
)
|
||||
|
||||
tracer = trace.get_tracer(__name__)
|
||||
with tracer.start_as_current_span("Request parent span") as span:
|
||||
try:
|
||||
# Requests made using the requests library will be automatically captured
|
||||
response = requests.get("https://azure.microsoft.com/", timeout=5)
|
||||
logger.warning("Request sent")
|
||||
except Exception as ex:
|
||||
# If an exception occurs, this can be manually recorded on the parent span
|
||||
span.set_attribute("status", "exception")
|
||||
span.record_exception(ex)
|
||||
|
||||
input()
|
|
@ -0,0 +1,22 @@
|
|||
# -------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
import psycopg2
|
||||
from azure.monitor.opentelemetry.distro import configure_azure_monitor
|
||||
|
||||
# Configure Azure monitor collection telemetry pipeline
|
||||
configure_azure_monitor(
|
||||
connection_string="<your-connection-string>",
|
||||
service_name="psycopg2_service_name",
|
||||
disable_logging=True,
|
||||
instrumentations=["psycopg2"],
|
||||
tracing_export_interval_millis=15000,
|
||||
)
|
||||
|
||||
cnx = psycopg2.connect(database="test", user="<user>", password="<password>")
|
||||
cursor = cnx.cursor()
|
||||
cursor.execute("INSERT INTO test_tables (test_field) VALUES (123)")
|
||||
cursor.close()
|
||||
cnx.close()
|
|
@ -0,0 +1,2 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ExampleConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "example"
|
|
@ -0,0 +1,2 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.index, name="index"),
|
||||
path("exception", views.exception, name="exception"),
|
||||
]
|
|
@ -0,0 +1,26 @@
|
|||
# -------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
from azure.monitor.opentelemetry.distro import configure_azure_monitor
|
||||
from django.http import HttpResponse
|
||||
|
||||
# Configure Azure monitor collection telemetry pipeline
|
||||
configure_azure_monitor(
|
||||
# connection_string="<your-connection-string>",
|
||||
service_name="django_service_name",
|
||||
instrumentations=["django"],
|
||||
disable_logging=True,
|
||||
tracing_export_interval_millis=15000,
|
||||
)
|
||||
|
||||
# Requests sent to the django application will be automatically captured
|
||||
def index(request):
|
||||
return HttpResponse("Hello, world.")
|
||||
|
||||
|
||||
# Exceptions that are raised within the request are automatically captured
|
||||
def exception(request):
|
||||
raise Exception("Exception was raised.")
|
|
@ -0,0 +1,25 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sample.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()
|
|
@ -0,0 +1,2 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
# cSpell:disable
|
||||
"""
|
||||
ASGI config for sample 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", "sample.settings")
|
||||
|
||||
application = get_asgi_application()
|
||||
|
||||
# cSpell:enable
|
|
@ -0,0 +1,133 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
"""
|
||||
Django settings for sample project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 3.2.7.
|
||||
|
||||
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/
|
||||
"""
|
||||
|
||||
# cSpell:disable
|
||||
|
||||
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 = (
|
||||
"django-insecure--9p!az#-flphjtvtl#c_ep6x#1lo+0@nzci#-(!-3c$!o0lyjk"
|
||||
)
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
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",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "sample.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 = "sample.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",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# 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"
|
||||
|
||||
# cSpell:enable
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
"""sample 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.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path("", include("example.urls")),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
"""
|
||||
WSGI config for sample 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", "sample.settings")
|
||||
|
||||
application = get_wsgi_application()
|
|
@ -0,0 +1,33 @@
|
|||
# -------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License in the project root for
|
||||
# license information.
|
||||
# --------------------------------------------------------------------------
|
||||
import flask
|
||||
from azure.monitor.opentelemetry.distro import configure_azure_monitor
|
||||
|
||||
# Configure Azure monitor collection telemetry pipeline
|
||||
configure_azure_monitor(
|
||||
connection_string="<your-connection-string>",
|
||||
service_name="flask_service_name",
|
||||
disable_logging=True,
|
||||
instrumentations=["flask"],
|
||||
tracing_export_interval_millis=15000,
|
||||
)
|
||||
|
||||
app = flask.Flask(__name__)
|
||||
|
||||
# Requests sent to the flask application will be automatically captured
|
||||
@app.route("/")
|
||||
def test():
|
||||
return "Test flask request"
|
||||
|
||||
|
||||
# Exceptions that are raised within the request are automatically captured
|
||||
@app.route("/exception")
|
||||
def exception():
|
||||
raise Exception("Hit an exception")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="localhost", port=8080)
|
|
@ -13,321 +13,147 @@
|
|||
# limitations under the License.
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import Mock, call, patch
|
||||
|
||||
from azure.monitor.opentelemetry.distro import configure_azure_monitor
|
||||
from azure.monitor.opentelemetry.distro import (
|
||||
_SUPPORTED_INSTRUMENTED_LIBRARIES,
|
||||
_get_resource,
|
||||
_setup_instrumentations,
|
||||
_setup_logging,
|
||||
_setup_tracing,
|
||||
configure_azure_monitor,
|
||||
)
|
||||
from opentelemetry.semconv.resource import ResourceAttributes
|
||||
|
||||
|
||||
class TestConfigure(unittest.TestCase):
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchSpanProcessor",
|
||||
"azure.monitor.opentelemetry.distro._setup_instrumentations",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.AzureMonitorTraceExporter",
|
||||
"azure.monitor.opentelemetry.distro._setup_logging",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.get_tracer_provider",
|
||||
"azure.monitor.opentelemetry.distro._setup_tracing",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.set_tracer_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.TracerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.ApplicationInsightsSampler",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.getLogger",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.LoggingHandler",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchLogRecordProcessor",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.AzureMonitorLogExporter",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.get_logger_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.set_logger_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.LoggerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.Resource",
|
||||
"azure.monitor.opentelemetry.distro._get_resource",
|
||||
)
|
||||
def test_configure_azure_monitor(
|
||||
self,
|
||||
resource_mock,
|
||||
lp_mock,
|
||||
set_logger_provider_mock,
|
||||
get_logger_provider_mock,
|
||||
log_exporter_mock,
|
||||
blrp_mock,
|
||||
logging_handler_mock,
|
||||
get_logger_mock,
|
||||
sampler_mock,
|
||||
tp_mock,
|
||||
set_tracer_provider_mock,
|
||||
get_tracer_provider_mock,
|
||||
trace_exporter_mock,
|
||||
bsp_mock,
|
||||
tracing_mock,
|
||||
logging_mock,
|
||||
instrumentation_mock,
|
||||
):
|
||||
kwargs = {
|
||||
"connection_string": "test_cs",
|
||||
"disable_logging": False,
|
||||
"disable_tracing": False,
|
||||
"logging_export_interval_millis": 10000,
|
||||
"logging_level": "test_logging_level",
|
||||
"service_name": "test_service_name",
|
||||
"service_namespace": "test_namespace",
|
||||
"service_instance_id": "test_id",
|
||||
"sampling_ratio": 0.5,
|
||||
"tracing_export_interval_millis": 15000,
|
||||
}
|
||||
resource_init_mock = Mock()
|
||||
resource_mock.create.return_value = resource_init_mock
|
||||
|
||||
lp_init_mock = Mock()
|
||||
lp_mock.return_value = lp_init_mock
|
||||
get_logger_provider_mock.return_value = lp_init_mock
|
||||
log_exp_init_mock = Mock()
|
||||
log_exporter_mock.return_value = log_exp_init_mock
|
||||
blrp_init_mock = Mock()
|
||||
blrp_mock.return_value = blrp_init_mock
|
||||
logging_handler_init_mock = Mock()
|
||||
logging_handler_mock.return_value = logging_handler_init_mock
|
||||
logger_mock = Mock()
|
||||
get_logger_mock.return_value = logger_mock
|
||||
|
||||
sampler_init_mock = Mock()
|
||||
sampler_mock.return_value = sampler_init_mock
|
||||
tp_init_mock = Mock()
|
||||
tp_mock.return_value = tp_init_mock
|
||||
get_tracer_provider_mock.return_value = tp_init_mock
|
||||
trace_exp_init_mock = Mock()
|
||||
trace_exporter_mock.return_value = trace_exp_init_mock
|
||||
bsp_init_mock = Mock()
|
||||
bsp_mock.return_value = bsp_init_mock
|
||||
|
||||
configure_azure_monitor(
|
||||
connection_string="test_cs",
|
||||
console_exporting=False,
|
||||
disable_logging=False,
|
||||
disable_tracing=False,
|
||||
logging_export_interval_millis=10000,
|
||||
logging_level="test_logging_level",
|
||||
service_name="test_service_name",
|
||||
service_namespace="test_namespace",
|
||||
service_instance_id="test_id",
|
||||
sampling_ratio=0.5,
|
||||
tracing_export_interval_millis=15000,
|
||||
)
|
||||
resource_mock.create.assert_called_once_with(
|
||||
{
|
||||
ResourceAttributes.SERVICE_NAME: "test_service_name",
|
||||
ResourceAttributes.SERVICE_NAMESPACE: "test_namespace",
|
||||
ResourceAttributes.SERVICE_INSTANCE_ID: "test_id",
|
||||
}
|
||||
)
|
||||
|
||||
lp_mock.assert_called_once_with(resource=resource_init_mock)
|
||||
set_logger_provider_mock.assert_called_once_with(lp_init_mock)
|
||||
get_logger_provider_mock.assert_called()
|
||||
log_exporter_mock.assert_called_once()
|
||||
blrp_mock.assert_called_once_with(
|
||||
log_exp_init_mock, export_timeout_millis=10000
|
||||
)
|
||||
lp_init_mock.add_log_record_processor.assert_called_once_with(
|
||||
blrp_init_mock
|
||||
)
|
||||
logging_handler_mock.assert_called_once_with(
|
||||
level="test_logging_level", logger_provider=lp_init_mock
|
||||
)
|
||||
get_logger_mock.assert_called_once_with()
|
||||
logger_mock.addHandler.assert_called_once_with(
|
||||
logging_handler_init_mock
|
||||
)
|
||||
|
||||
sampler_mock.assert_called_once_with(sampling_ratio=0.5)
|
||||
tp_mock.assert_called_once_with(
|
||||
resource=resource_init_mock,
|
||||
sampler=sampler_init_mock,
|
||||
)
|
||||
set_tracer_provider_mock.assert_called_once_with(tp_init_mock)
|
||||
get_tracer_provider_mock.assert_called()
|
||||
trace_exporter_mock.assert_called_once()
|
||||
bsp_mock.assert_called_once_with(
|
||||
trace_exp_init_mock, export_timeout_millis=15000
|
||||
)
|
||||
tp_init_mock.add_span_processor(bsp_init_mock)
|
||||
resource_mock.return_value = resource_init_mock
|
||||
configure_azure_monitor(**kwargs)
|
||||
resource_mock.assert_called_once_with(kwargs)
|
||||
tracing_mock.assert_called_once_with(resource_init_mock, kwargs)
|
||||
logging_mock.assert_called_once_with(resource_init_mock, kwargs)
|
||||
instrumentation_mock.assert_called_once_with(kwargs)
|
||||
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchSpanProcessor",
|
||||
"azure.monitor.opentelemetry.distro._setup_instrumentations",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.AzureMonitorTraceExporter",
|
||||
"azure.monitor.opentelemetry.distro._setup_logging",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.get_tracer_provider",
|
||||
"azure.monitor.opentelemetry.distro._setup_tracing",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.set_tracer_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.TracerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.ApplicationInsightsSampler",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.getLogger",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.LoggingHandler",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchLogRecordProcessor",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.AzureMonitorLogExporter",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.get_logger_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.set_logger_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.LoggerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.Resource",
|
||||
)
|
||||
def test_configure_azure_monitor_disable_tracing_and_logging(
|
||||
self,
|
||||
resource_mock,
|
||||
lp_mock,
|
||||
set_logger_provider_mock,
|
||||
get_logger_provider_mock,
|
||||
log_exporter_mock,
|
||||
blrp_mock,
|
||||
logging_handler_mock,
|
||||
get_logger_mock,
|
||||
sampler_mock,
|
||||
tp_mock,
|
||||
set_tracer_provider_mock,
|
||||
get_tracer_provider_mock,
|
||||
trace_exporter_mock,
|
||||
bsp_mock,
|
||||
):
|
||||
configure_azure_monitor(
|
||||
connection_string="test_cs",
|
||||
disable_logging=True,
|
||||
disable_tracing=True,
|
||||
)
|
||||
resource_mock.assert_not_called()
|
||||
|
||||
lp_mock.assert_not_called()
|
||||
set_logger_provider_mock.assert_not_called()
|
||||
get_logger_provider_mock.assert_not_called()
|
||||
log_exporter_mock.assert_not_called()
|
||||
blrp_mock.assert_not_called()
|
||||
logging_handler_mock.assert_not_called()
|
||||
get_logger_mock.assert_not_called()
|
||||
|
||||
sampler_mock.assert_not_called()
|
||||
tp_mock.assert_not_called()
|
||||
set_tracer_provider_mock.assert_not_called()
|
||||
get_tracer_provider_mock.assert_not_called()
|
||||
trace_exporter_mock.assert_not_called()
|
||||
bsp_mock.assert_not_called()
|
||||
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchSpanProcessor",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.AzureMonitorTraceExporter",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.get_tracer_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.set_tracer_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.TracerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.ApplicationInsightsSampler",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.getLogger",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.LoggingHandler",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchLogRecordProcessor",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.AzureMonitorLogExporter",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.get_logger_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.set_logger_provider",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.LoggerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.Resource",
|
||||
"azure.monitor.opentelemetry.distro._get_resource",
|
||||
)
|
||||
def test_configure_azure_monitor_disable_tracing(
|
||||
self,
|
||||
resource_mock,
|
||||
lp_mock,
|
||||
set_logger_provider_mock,
|
||||
get_logger_provider_mock,
|
||||
log_exporter_mock,
|
||||
blrp_mock,
|
||||
logging_handler_mock,
|
||||
get_logger_mock,
|
||||
sampler_mock,
|
||||
tp_mock,
|
||||
set_tracer_provider_mock,
|
||||
get_tracer_provider_mock,
|
||||
trace_exporter_mock,
|
||||
bsp_mock,
|
||||
tracing_mock,
|
||||
logging_mock,
|
||||
instrumentation_mock,
|
||||
):
|
||||
kwargs = {
|
||||
"connection_string": "test_cs",
|
||||
"disable_logging": False,
|
||||
"disable_tracing": True,
|
||||
"logging_export_interval_millis": 10000,
|
||||
"logging_level": "test_logging_level",
|
||||
"service_name": "test_service_name",
|
||||
"service_namespace": "test_namespace",
|
||||
"service_instance_id": "test_id",
|
||||
"sampling_ratio": 0.5,
|
||||
"tracing_export_interval_millis": 15000,
|
||||
}
|
||||
resource_init_mock = Mock()
|
||||
resource_mock.create.return_value = resource_init_mock
|
||||
resource_mock.return_value = resource_init_mock
|
||||
configure_azure_monitor(**kwargs)
|
||||
resource_mock.assert_called_once_with(kwargs)
|
||||
tracing_mock.assert_not_called()
|
||||
logging_mock.assert_called_once_with(resource_init_mock, kwargs)
|
||||
instrumentation_mock.assert_called_once_with(kwargs)
|
||||
|
||||
lp_init_mock = Mock()
|
||||
lp_mock.return_value = lp_init_mock
|
||||
get_logger_provider_mock.return_value = lp_init_mock
|
||||
log_exp_init_mock = Mock()
|
||||
log_exporter_mock.return_value = log_exp_init_mock
|
||||
blrp_init_mock = Mock()
|
||||
blrp_mock.return_value = blrp_init_mock
|
||||
logging_handler_init_mock = Mock()
|
||||
logging_handler_mock.return_value = logging_handler_init_mock
|
||||
logger_mock = Mock()
|
||||
get_logger_mock.return_value = logger_mock
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro._setup_instrumentations",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro._setup_logging",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro._setup_tracing",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro._get_resource",
|
||||
)
|
||||
def test_configure_azure_monitor_disable_logging(
|
||||
self,
|
||||
resource_mock,
|
||||
tracing_mock,
|
||||
logging_mock,
|
||||
instrumentation_mock,
|
||||
):
|
||||
kwargs = {
|
||||
"connection_string": "test_cs",
|
||||
"disable_logging": True,
|
||||
"disable_tracing": False,
|
||||
"logging_export_interval_millis": 10000,
|
||||
"logging_level": "test_logging_level",
|
||||
"service_name": "test_service_name",
|
||||
"service_namespace": "test_namespace",
|
||||
"service_instance_id": "test_id",
|
||||
"sampling_ratio": 0.5,
|
||||
"tracing_export_interval_millis": 15000,
|
||||
}
|
||||
resource_init_mock = Mock()
|
||||
resource_mock.return_value = resource_init_mock
|
||||
configure_azure_monitor(**kwargs)
|
||||
resource_mock.assert_called_once_with(kwargs)
|
||||
tracing_mock.assert_called_once_with(resource_init_mock, kwargs)
|
||||
logging_mock.assert_not_called()
|
||||
instrumentation_mock.assert_called_once_with(kwargs)
|
||||
|
||||
configure_azure_monitor(
|
||||
connection_string="test_cs",
|
||||
console_exporting=False,
|
||||
disable_logging=False,
|
||||
disable_tracing=True,
|
||||
logging_export_interval_millis=10000,
|
||||
logging_level="test_logging_level",
|
||||
service_name="test_service_name",
|
||||
service_namespace="test_namespace",
|
||||
service_instance_id="test_id",
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.Resource",
|
||||
)
|
||||
def test_get_resource(self, resource_mock):
|
||||
configuration = {
|
||||
"service_name": "test_service_name",
|
||||
"service_namespace": "test_namespace",
|
||||
"service_instance_id": "test_id",
|
||||
}
|
||||
_get_resource(configuration)
|
||||
resource_mock.create.assert_called_once_with(
|
||||
{
|
||||
ResourceAttributes.SERVICE_NAME: "test_service_name",
|
||||
|
@ -336,31 +162,6 @@ class TestConfigure(unittest.TestCase):
|
|||
}
|
||||
)
|
||||
|
||||
lp_mock.assert_called_once_with(resource=resource_init_mock)
|
||||
set_logger_provider_mock.assert_called_once_with(lp_init_mock)
|
||||
get_logger_provider_mock.assert_called()
|
||||
log_exporter_mock.assert_called_once()
|
||||
blrp_mock.assert_called_once_with(
|
||||
log_exp_init_mock, export_timeout_millis=10000
|
||||
)
|
||||
lp_init_mock.add_log_record_processor.assert_called_once_with(
|
||||
blrp_init_mock
|
||||
)
|
||||
logging_handler_mock.assert_called_once_with(
|
||||
level="test_logging_level", logger_provider=lp_init_mock
|
||||
)
|
||||
get_logger_mock.assert_called_once_with()
|
||||
logger_mock.addHandler.assert_called_once_with(
|
||||
logging_handler_init_mock
|
||||
)
|
||||
|
||||
sampler_mock.assert_not_called()
|
||||
tp_mock.assert_not_called()
|
||||
set_tracer_provider_mock.assert_not_called()
|
||||
get_tracer_provider_mock.assert_not_called()
|
||||
trace_exporter_mock.assert_not_called()
|
||||
bsp_mock.assert_not_called()
|
||||
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.BatchSpanProcessor",
|
||||
)
|
||||
|
@ -380,6 +181,46 @@ class TestConfigure(unittest.TestCase):
|
|||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.ApplicationInsightsSampler",
|
||||
)
|
||||
def test_setup_tracing(
|
||||
self,
|
||||
sampler_mock,
|
||||
tp_mock,
|
||||
set_tracer_provider_mock,
|
||||
get_tracer_provider_mock,
|
||||
trace_exporter_mock,
|
||||
bsp_mock,
|
||||
):
|
||||
resource_mock = Mock()
|
||||
sampler_init_mock = Mock()
|
||||
sampler_mock.return_value = sampler_init_mock
|
||||
tp_init_mock = Mock()
|
||||
tp_mock.return_value = tp_init_mock
|
||||
get_tracer_provider_mock.return_value = tp_init_mock
|
||||
trace_exp_init_mock = Mock()
|
||||
trace_exporter_mock.return_value = trace_exp_init_mock
|
||||
bsp_init_mock = Mock()
|
||||
bsp_mock.return_value = bsp_init_mock
|
||||
|
||||
configurations = {
|
||||
"connection_string": "test_cs",
|
||||
"disable_tracing": False,
|
||||
"sampling_ratio": 0.5,
|
||||
"tracing_export_interval_millis": 15000,
|
||||
}
|
||||
_setup_tracing(resource_mock, configurations)
|
||||
sampler_mock.assert_called_once_with(sampling_ratio=0.5)
|
||||
tp_mock.assert_called_once_with(
|
||||
resource=resource_mock,
|
||||
sampler=sampler_init_mock,
|
||||
)
|
||||
set_tracer_provider_mock.assert_called_once_with(tp_init_mock)
|
||||
get_tracer_provider_mock.assert_called()
|
||||
trace_exporter_mock.assert_called_once()
|
||||
bsp_mock.assert_called_once_with(
|
||||
trace_exp_init_mock, export_timeout_millis=15000
|
||||
)
|
||||
tp_init_mock.add_span_processor(bsp_init_mock)
|
||||
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.getLogger",
|
||||
)
|
||||
|
@ -402,12 +243,8 @@ class TestConfigure(unittest.TestCase):
|
|||
"azure.monitor.opentelemetry.distro.LoggerProvider",
|
||||
autospec=True,
|
||||
)
|
||||
@patch(
|
||||
"azure.monitor.opentelemetry.distro.Resource",
|
||||
)
|
||||
def test_configure_azure_monitor_disable_logging(
|
||||
def test_setup_logging(
|
||||
self,
|
||||
resource_mock,
|
||||
lp_mock,
|
||||
set_logger_provider_mock,
|
||||
get_logger_provider_mock,
|
||||
|
@ -415,63 +252,141 @@ class TestConfigure(unittest.TestCase):
|
|||
blrp_mock,
|
||||
logging_handler_mock,
|
||||
get_logger_mock,
|
||||
sampler_mock,
|
||||
tp_mock,
|
||||
set_tracer_provider_mock,
|
||||
get_tracer_provider_mock,
|
||||
trace_exporter_mock,
|
||||
bsp_mock,
|
||||
):
|
||||
resource_init_mock = Mock()
|
||||
resource_mock.create.return_value = resource_init_mock
|
||||
resource_mock = Mock()
|
||||
|
||||
sampler_init_mock = Mock()
|
||||
sampler_mock.return_value = sampler_init_mock
|
||||
tp_init_mock = Mock()
|
||||
tp_mock.return_value = tp_init_mock
|
||||
get_tracer_provider_mock.return_value = tp_init_mock
|
||||
trace_exp_init_mock = Mock()
|
||||
trace_exporter_mock.return_value = trace_exp_init_mock
|
||||
bsp_init_mock = Mock()
|
||||
bsp_mock.return_value = bsp_init_mock
|
||||
lp_init_mock = Mock()
|
||||
lp_mock.return_value = lp_init_mock
|
||||
get_logger_provider_mock.return_value = lp_init_mock
|
||||
log_exp_init_mock = Mock()
|
||||
log_exporter_mock.return_value = log_exp_init_mock
|
||||
blrp_init_mock = Mock()
|
||||
blrp_mock.return_value = blrp_init_mock
|
||||
logging_handler_init_mock = Mock()
|
||||
logging_handler_mock.return_value = logging_handler_init_mock
|
||||
logger_mock = Mock()
|
||||
get_logger_mock.return_value = logger_mock
|
||||
|
||||
configure_azure_monitor(
|
||||
connection_string="test_cs",
|
||||
console_exporting=False,
|
||||
disable_logging=True,
|
||||
disable_tracing=False,
|
||||
logging_level="test_logging_level",
|
||||
service_name="test_service_name",
|
||||
service_namespace="test_namespace",
|
||||
service_instance_id="test_id",
|
||||
sampling_ratio=0.5,
|
||||
tracing_export_interval_millis=15000,
|
||||
configurations = {
|
||||
"connection_string": "test_cs",
|
||||
"disable_logging": False,
|
||||
"logging_export_interval_millis": 10000,
|
||||
"logging_level": "test_logging_level",
|
||||
}
|
||||
_setup_logging(resource_mock, configurations)
|
||||
|
||||
lp_mock.assert_called_once_with(resource=resource_mock)
|
||||
set_logger_provider_mock.assert_called_once_with(lp_init_mock)
|
||||
get_logger_provider_mock.assert_called()
|
||||
log_exporter_mock.assert_called_once()
|
||||
blrp_mock.assert_called_once_with(
|
||||
log_exp_init_mock, export_timeout_millis=10000
|
||||
)
|
||||
resource_mock.create.assert_called_once_with(
|
||||
{
|
||||
ResourceAttributes.SERVICE_NAME: "test_service_name",
|
||||
ResourceAttributes.SERVICE_NAMESPACE: "test_namespace",
|
||||
ResourceAttributes.SERVICE_INSTANCE_ID: "test_id",
|
||||
}
|
||||
lp_init_mock.add_log_record_processor.assert_called_once_with(
|
||||
blrp_init_mock
|
||||
)
|
||||
logging_handler_mock.assert_called_once_with(
|
||||
level="test_logging_level", logger_provider=lp_init_mock
|
||||
)
|
||||
get_logger_mock.assert_called_once_with()
|
||||
logger_mock.addHandler.assert_called_once_with(
|
||||
logging_handler_init_mock
|
||||
)
|
||||
|
||||
lp_mock.assert_not_called()
|
||||
set_logger_provider_mock.assert_not_called()
|
||||
get_logger_provider_mock.assert_not_called()
|
||||
log_exporter_mock.assert_not_called()
|
||||
blrp_mock.assert_not_called()
|
||||
logging_handler_mock.assert_not_called()
|
||||
get_logger_mock.assert_not_called()
|
||||
@patch("azure.monitor.opentelemetry.distro.getattr")
|
||||
def test_setup_instrumentations(
|
||||
self,
|
||||
getattr_mock,
|
||||
):
|
||||
for lib_name in _SUPPORTED_INSTRUMENTED_LIBRARIES:
|
||||
with patch("importlib.import_module") as import_module_mock:
|
||||
configurations = {"instrumentations": [lib_name]}
|
||||
instrument_mock = Mock()
|
||||
instrumentor_mock = Mock()
|
||||
instrumentor_mock.return_value = instrument_mock
|
||||
getattr_mock.return_value = instrumentor_mock
|
||||
_setup_instrumentations(configurations)
|
||||
self.assertEqual(import_module_mock.call_count, 2)
|
||||
instr_lib_name = "opentelemetry.instrumentation." + lib_name
|
||||
import_module_mock.assert_has_calls(
|
||||
[call(lib_name), call(instr_lib_name)]
|
||||
)
|
||||
instrumentor_mock.assert_called_once()
|
||||
instrument_mock.instrument.assert_called_once()
|
||||
|
||||
sampler_mock.assert_called_once_with(sampling_ratio=0.5)
|
||||
tp_mock.assert_called_once_with(
|
||||
resource=resource_init_mock,
|
||||
sampler=sampler_init_mock,
|
||||
)
|
||||
set_tracer_provider_mock.assert_called_once_with(tp_init_mock)
|
||||
get_tracer_provider_mock.assert_called()
|
||||
trace_exporter_mock.assert_called_once()
|
||||
bsp_mock.assert_called_once_with(
|
||||
trace_exp_init_mock, export_timeout_millis=15000
|
||||
)
|
||||
tp_init_mock.add_span_processor(bsp_init_mock)
|
||||
@patch("azure.monitor.opentelemetry.distro.getattr")
|
||||
def test_setup_instrumentations_lib_not_found(
|
||||
self,
|
||||
getattr_mock,
|
||||
):
|
||||
with patch("importlib.import_module") as import_module_mock:
|
||||
configurations = {"instrumentations": ["non_supported_lib"]}
|
||||
instrument_mock = Mock()
|
||||
instrumentor_mock = Mock()
|
||||
instrumentor_mock.return_value = instrument_mock
|
||||
getattr_mock.return_value = instrumentor_mock
|
||||
_setup_instrumentations(configurations)
|
||||
import_module_mock.assert_not_called()
|
||||
instrumentor_mock.assert_not_called()
|
||||
instrument_mock.instrument.assert_not_called()
|
||||
|
||||
@patch("azure.monitor.opentelemetry.distro.getattr")
|
||||
def test_setup_instrumentations_import_lib_failed(
|
||||
self,
|
||||
getattr_mock,
|
||||
):
|
||||
for lib_name in _SUPPORTED_INSTRUMENTED_LIBRARIES:
|
||||
with patch(
|
||||
"importlib.import_module", side_effect=ImportError()
|
||||
) as import_module_mock:
|
||||
configurations = {"instrumentations": [lib_name]}
|
||||
instrument_mock = Mock()
|
||||
instrumentor_mock = Mock()
|
||||
instrumentor_mock.return_value = instrument_mock
|
||||
getattr_mock.return_value = instrumentor_mock
|
||||
_setup_instrumentations(configurations)
|
||||
import_module_mock.assert_called_once()
|
||||
instrumentor_mock.assert_not_called()
|
||||
instrument_mock.instrument.assert_not_called()
|
||||
|
||||
@patch("azure.monitor.opentelemetry.distro.getattr")
|
||||
def test_setup_instrumentations_import_instr_failed(
|
||||
self,
|
||||
getattr_mock,
|
||||
):
|
||||
for lib_name in _SUPPORTED_INSTRUMENTED_LIBRARIES:
|
||||
with patch("importlib.import_module") as import_module_mock:
|
||||
configurations = {"instrumentations": [lib_name]}
|
||||
instrument_mock = Mock()
|
||||
instrumentor_mock = Mock()
|
||||
instrumentor_mock.return_value = instrument_mock
|
||||
getattr_mock.return_value = instrumentor_mock
|
||||
import_module_mock.side_effect = [None, ImportError()]
|
||||
_setup_instrumentations(configurations)
|
||||
instr_lib_name = "opentelemetry.instrumentation." + lib_name
|
||||
import_module_mock.assert_has_calls(
|
||||
[call(lib_name), call(instr_lib_name)]
|
||||
)
|
||||
instrumentor_mock.assert_not_called()
|
||||
instrument_mock.instrument.assert_not_called()
|
||||
|
||||
@patch("azure.monitor.opentelemetry.distro.getattr")
|
||||
def test_setup_instrumentations_failed_general(
|
||||
self,
|
||||
getattr_mock,
|
||||
):
|
||||
for lib_name in _SUPPORTED_INSTRUMENTED_LIBRARIES:
|
||||
with patch("importlib.import_module") as import_module_mock:
|
||||
configurations = {"instrumentations": [lib_name]}
|
||||
instrument_mock = Mock()
|
||||
instrumentor_mock = Mock()
|
||||
instrumentor_mock.return_value = instrument_mock
|
||||
getattr_mock.side_effect = Exception()
|
||||
_setup_instrumentations(configurations)
|
||||
self.assertEqual(import_module_mock.call_count, 2)
|
||||
instr_lib_name = "opentelemetry.instrumentation." + lib_name
|
||||
import_module_mock.assert_has_calls(
|
||||
[call(lib_name), call(instr_lib_name)]
|
||||
)
|
||||
instrumentor_mock.assert_not_called()
|
||||
instrument_mock.instrument.assert_not_called()
|
||||
|
|
Загрузка…
Ссылка в новой задаче